@zeix/le-truc 0.15.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 (406) hide show
  1. package/.ai-context.md +234 -0
  2. package/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc +111 -0
  3. package/.editorconfig +12 -0
  4. package/.github/copilot-instructions.md +62 -0
  5. package/.github/workflows/codeql.yml +108 -0
  6. package/.github/workflows/static.yml +43 -0
  7. package/.prettierrc +17 -0
  8. package/CLAUDE.md +215 -0
  9. package/CODE_OF_CONDUCT.md +128 -0
  10. package/CONTRIBUTING.md +160 -0
  11. package/LICENSE +21 -0
  12. package/README.md +474 -0
  13. package/biome.json +295 -0
  14. package/bun.lock +239 -0
  15. package/docs/about.html +105 -0
  16. package/docs/assets/main.css +1 -0
  17. package/docs/assets/main.js +10 -0
  18. package/docs/assets/main.js.map +66 -0
  19. package/docs/components.html +293 -0
  20. package/docs/data-flow.html +308 -0
  21. package/docs/examples/basic-button.html +367 -0
  22. package/docs/examples/basic-counter.html +188 -0
  23. package/docs/examples/basic-hello.html +138 -0
  24. package/docs/examples/basic-number.html +271 -0
  25. package/docs/examples/basic-pluralize.html +214 -0
  26. package/docs/examples/card-callout.html +152 -0
  27. package/docs/examples/card-mediaqueries.html +138 -0
  28. package/docs/examples/context-media.html +198 -0
  29. package/docs/examples/empty.html +37 -0
  30. package/docs/examples/form-checkbox.html +233 -0
  31. package/docs/examples/form-combobox.html +420 -0
  32. package/docs/examples/form-listbox.html +434 -0
  33. package/docs/examples/form-radiogroup.html +296 -0
  34. package/docs/examples/form-spinbutton.html +402 -0
  35. package/docs/examples/form-textbox.html +361 -0
  36. package/docs/examples/layout.html +67 -0
  37. package/docs/examples/module-carousel.html +552 -0
  38. package/docs/examples/module-catalog.html +241 -0
  39. package/docs/examples/module-codeblock.html +270 -0
  40. package/docs/examples/module-dialog.html +343 -0
  41. package/docs/examples/module-lazyload.html +289 -0
  42. package/docs/examples/module-list.html +197 -0
  43. package/docs/examples/module-pagination.html +283 -0
  44. package/docs/examples/module-scrollarea.html +447 -0
  45. package/docs/examples/module-tabgroup.html +526 -0
  46. package/docs/examples/module-todo.html +367 -0
  47. package/docs/examples/module-with-type.html +63 -0
  48. package/docs/examples/nested-components.html +88 -0
  49. package/docs/examples/recursive.html +56 -0
  50. package/docs/examples/simple-text.html +39 -0
  51. package/docs/examples/snippet.html +93 -0
  52. package/docs/examples/with-styles.html +75 -0
  53. package/docs/getting-started.html +143 -0
  54. package/docs/index.html +112 -0
  55. package/docs/sitemap.xml +28 -0
  56. package/docs/styling.html +160 -0
  57. package/docs/sw.js +112 -0
  58. package/docs-src/api/README.md +478 -0
  59. package/docs-src/api/_media/LICENSE +21 -0
  60. package/docs-src/api/classes/CircularDependencyError.md +299 -0
  61. package/docs-src/api/classes/CircularMutationError.md +301 -0
  62. package/docs-src/api/classes/ContextRequestEvent.md +590 -0
  63. package/docs-src/api/classes/DependencyTimeoutError.md +301 -0
  64. package/docs-src/api/classes/InvalidCallbackError.md +303 -0
  65. package/docs-src/api/classes/InvalidComponentNameError.md +295 -0
  66. package/docs-src/api/classes/InvalidCustomElementError.md +301 -0
  67. package/docs-src/api/classes/InvalidEffectsError.md +301 -0
  68. package/docs-src/api/classes/InvalidPropertyNameError.md +307 -0
  69. package/docs-src/api/classes/InvalidReactivesError.md +307 -0
  70. package/docs-src/api/classes/InvalidSignalValueError.md +303 -0
  71. package/docs-src/api/classes/MissingElementError.md +307 -0
  72. package/docs-src/api/classes/NullishSignalValueError.md +299 -0
  73. package/docs-src/api/classes/StoreKeyExistsError.md +303 -0
  74. package/docs-src/api/classes/StoreKeyRangeError.md +299 -0
  75. package/docs-src/api/classes/StoreKeyReadonlyError.md +303 -0
  76. package/docs-src/api/functions/asBoolean.md +21 -0
  77. package/docs-src/api/functions/asEnum.md +31 -0
  78. package/docs-src/api/functions/asInteger.md +39 -0
  79. package/docs-src/api/functions/asJSON.md +49 -0
  80. package/docs-src/api/functions/asNumber.md +37 -0
  81. package/docs-src/api/functions/asString.md +37 -0
  82. package/docs-src/api/functions/createCollection.md +83 -0
  83. package/docs-src/api/functions/createSensor.md +71 -0
  84. package/docs-src/api/functions/dangerouslySetInnerHTML.md +48 -0
  85. package/docs-src/api/functions/defineComponent.md +65 -0
  86. package/docs-src/api/functions/isCollection.md +37 -0
  87. package/docs-src/api/functions/isParser.md +41 -0
  88. package/docs-src/api/functions/match.md +47 -0
  89. package/docs-src/api/functions/on.md +58 -0
  90. package/docs-src/api/functions/pass.md +53 -0
  91. package/docs-src/api/functions/provideContexts.md +47 -0
  92. package/docs-src/api/functions/read.md +47 -0
  93. package/docs-src/api/functions/requestContext.md +51 -0
  94. package/docs-src/api/functions/resolve.md +40 -0
  95. package/docs-src/api/functions/runEffects.md +51 -0
  96. package/docs-src/api/functions/runElementEffects.md +57 -0
  97. package/docs-src/api/functions/schedule.md +33 -0
  98. package/docs-src/api/functions/setAttribute.md +48 -0
  99. package/docs-src/api/functions/setProperty.md +52 -0
  100. package/docs-src/api/functions/setStyle.md +48 -0
  101. package/docs-src/api/functions/setText.md +42 -0
  102. package/docs-src/api/functions/show.md +42 -0
  103. package/docs-src/api/functions/toSignal.md +37 -0
  104. package/docs-src/api/functions/toggleAttribute.md +48 -0
  105. package/docs-src/api/functions/toggleClass.md +48 -0
  106. package/docs-src/api/functions/updateElement.md +53 -0
  107. package/docs-src/api/globals.md +131 -0
  108. package/docs-src/api/type-aliases/Cleanup.md +27 -0
  109. package/docs-src/api/type-aliases/Collection.md +91 -0
  110. package/docs-src/api/type-aliases/CollectionListener.md +27 -0
  111. package/docs-src/api/type-aliases/Component.md +17 -0
  112. package/docs-src/api/type-aliases/ComponentProp.md +11 -0
  113. package/docs-src/api/type-aliases/ComponentProps.md +11 -0
  114. package/docs-src/api/type-aliases/ComponentSetup.md +31 -0
  115. package/docs-src/api/type-aliases/ComponentUI.md +27 -0
  116. package/docs-src/api/type-aliases/Computed.md +49 -0
  117. package/docs-src/api/type-aliases/ComputedCallback.md +29 -0
  118. package/docs-src/api/type-aliases/Context.md +33 -0
  119. package/docs-src/api/type-aliases/ContextType.md +19 -0
  120. package/docs-src/api/type-aliases/DangerouslySetInnerHTMLOptions.md +27 -0
  121. package/docs-src/api/type-aliases/DiffResult.md +61 -0
  122. package/docs-src/api/type-aliases/Effect.md +35 -0
  123. package/docs-src/api/type-aliases/EffectCallback.md +23 -0
  124. package/docs-src/api/type-aliases/Effects.md +21 -0
  125. package/docs-src/api/type-aliases/ElementEffects.md +21 -0
  126. package/docs-src/api/type-aliases/ElementFromKey.md +21 -0
  127. package/docs-src/api/type-aliases/ElementQueries.md +27 -0
  128. package/docs-src/api/type-aliases/ElementUpdater.md +131 -0
  129. package/docs-src/api/type-aliases/EventHandler.md +31 -0
  130. package/docs-src/api/type-aliases/EventType.md +17 -0
  131. package/docs-src/api/type-aliases/Fallback.md +21 -0
  132. package/docs-src/api/type-aliases/Initializers.md +21 -0
  133. package/docs-src/api/type-aliases/LooseReader.md +31 -0
  134. package/docs-src/api/type-aliases/MatchHandlers.md +77 -0
  135. package/docs-src/api/type-aliases/MaybeCleanup.md +23 -0
  136. package/docs-src/api/type-aliases/MaybeSignal.md +17 -0
  137. package/docs-src/api/type-aliases/Parser.md +39 -0
  138. package/docs-src/api/type-aliases/ParserOrFallback.md +21 -0
  139. package/docs-src/api/type-aliases/PassedProp.md +25 -0
  140. package/docs-src/api/type-aliases/PassedProps.md +21 -0
  141. package/docs-src/api/type-aliases/Reactive.md +25 -0
  142. package/docs-src/api/type-aliases/Reader.md +31 -0
  143. package/docs-src/api/type-aliases/ReservedWords.md +11 -0
  144. package/docs-src/api/type-aliases/ResolveResult.md +29 -0
  145. package/docs-src/api/type-aliases/SensorEvents.md +25 -0
  146. package/docs-src/api/type-aliases/Signal.md +41 -0
  147. package/docs-src/api/type-aliases/State.md +85 -0
  148. package/docs-src/api/type-aliases/Store.md +29 -0
  149. package/docs-src/api/type-aliases/UI.md +11 -0
  150. package/docs-src/api/type-aliases/UnknownContext.md +13 -0
  151. package/docs-src/api/variables/CONTEXT_REQUEST.md +11 -0
  152. package/docs-src/api/variables/UNSET.md +23 -0
  153. package/docs-src/api/variables/batch.md +25 -0
  154. package/docs-src/api/variables/createComputed.md +41 -0
  155. package/docs-src/api/variables/createEffect.md +35 -0
  156. package/docs-src/api/variables/createState.md +37 -0
  157. package/docs-src/api/variables/createStore.md +42 -0
  158. package/docs-src/api/variables/diff.md +43 -0
  159. package/docs-src/api/variables/isAbortError.md +33 -0
  160. package/docs-src/api/variables/isAsyncFunction.md +39 -0
  161. package/docs-src/api/variables/isComputed.md +37 -0
  162. package/docs-src/api/variables/isEqual.md +49 -0
  163. package/docs-src/api/variables/isFunction.md +39 -0
  164. package/docs-src/api/variables/isMutableSignal.md +37 -0
  165. package/docs-src/api/variables/isNumber.md +33 -0
  166. package/docs-src/api/variables/isRecord.md +39 -0
  167. package/docs-src/api/variables/isRecordOrArray.md +39 -0
  168. package/docs-src/api/variables/isSignal.md +37 -0
  169. package/docs-src/api/variables/isState.md +37 -0
  170. package/docs-src/api/variables/isStore.md +37 -0
  171. package/docs-src/api/variables/isString.md +33 -0
  172. package/docs-src/api/variables/isSymbol.md +33 -0
  173. package/docs-src/api/variables/toError.md +33 -0
  174. package/docs-src/api/variables/valueString.md +33 -0
  175. package/docs-src/includes/menu.html +44 -0
  176. package/docs-src/pages/about.md +89 -0
  177. package/docs-src/pages/components.md +437 -0
  178. package/docs-src/pages/data-flow.md +449 -0
  179. package/docs-src/pages/getting-started.md +170 -0
  180. package/docs-src/pages/index.md +98 -0
  181. package/docs-src/pages/styling.md +165 -0
  182. package/eslint.config.js +64 -0
  183. package/examples/_common/clear.ts +49 -0
  184. package/examples/_common/fetch.ts +160 -0
  185. package/examples/_common/focus.ts +45 -0
  186. package/examples/_common/highlight.ts +5 -0
  187. package/examples/_global.css +463 -0
  188. package/examples/basic-button/basic-button.css +176 -0
  189. package/examples/basic-button/basic-button.html +46 -0
  190. package/examples/basic-button/basic-button.spec.ts +160 -0
  191. package/examples/basic-button/basic-button.ts +45 -0
  192. package/examples/basic-button/copyToClipboard.ts +37 -0
  193. package/examples/basic-counter/basic-counter.css +21 -0
  194. package/examples/basic-counter/basic-counter.html +24 -0
  195. package/examples/basic-counter/basic-counter.spec.ts +85 -0
  196. package/examples/basic-counter/basic-counter.ts +43 -0
  197. package/examples/basic-hello/basic-hello.html +34 -0
  198. package/examples/basic-hello/basic-hello.spec.ts +110 -0
  199. package/examples/basic-hello/basic-hello.ts +36 -0
  200. package/examples/basic-number/basic-number.html +79 -0
  201. package/examples/basic-number/basic-number.spec.ts +175 -0
  202. package/examples/basic-number/basic-number.ts +124 -0
  203. package/examples/basic-pluralize/basic-pluralize.html +64 -0
  204. package/examples/basic-pluralize/basic-pluralize.spec.ts +258 -0
  205. package/examples/basic-pluralize/basic-pluralize.ts +82 -0
  206. package/examples/card-callout/card-callout.css +79 -0
  207. package/examples/card-callout/card-callout.html +5 -0
  208. package/examples/card-mediaqueries/card-mediaqueries.html +29 -0
  209. package/examples/card-mediaqueries/card-mediaqueries.spec.ts +300 -0
  210. package/examples/card-mediaqueries/card-mediaqueries.ts +41 -0
  211. package/examples/context-media/context-media.html +3 -0
  212. package/examples/context-media/context-media.ts +127 -0
  213. package/examples/form-checkbox/form-checkbox.css +70 -0
  214. package/examples/form-checkbox/form-checkbox.html +13 -0
  215. package/examples/form-checkbox/form-checkbox.spec.ts +357 -0
  216. package/examples/form-checkbox/form-checkbox.ts +50 -0
  217. package/examples/form-checkbox/vanilla-checkbox.ts +101 -0
  218. package/examples/form-combobox/form-combobox.css +118 -0
  219. package/examples/form-combobox/form-combobox.html +74 -0
  220. package/examples/form-combobox/form-combobox.spec.ts +977 -0
  221. package/examples/form-combobox/form-combobox.ts +128 -0
  222. package/examples/form-listbox/form-listbox.css +71 -0
  223. package/examples/form-listbox/form-listbox.html +67 -0
  224. package/examples/form-listbox/form-listbox.spec.ts +1050 -0
  225. package/examples/form-listbox/form-listbox.ts +196 -0
  226. package/examples/form-listbox/mocks/timezones.json +495 -0
  227. package/examples/form-radiogroup/form-radiogroup.css +87 -0
  228. package/examples/form-radiogroup/form-radiogroup.html +51 -0
  229. package/examples/form-radiogroup/form-radiogroup.spec.ts +515 -0
  230. package/examples/form-radiogroup/form-radiogroup.ts +58 -0
  231. package/examples/form-spinbutton/form-spinbutton.css +95 -0
  232. package/examples/form-spinbutton/form-spinbutton.html +96 -0
  233. package/examples/form-spinbutton/form-spinbutton.spec.ts +688 -0
  234. package/examples/form-spinbutton/form-spinbutton.ts +111 -0
  235. package/examples/form-textbox/form-textbox.css +104 -0
  236. package/examples/form-textbox/form-textbox.html +53 -0
  237. package/examples/form-textbox/form-textbox.spec.ts +542 -0
  238. package/examples/form-textbox/form-textbox.ts +104 -0
  239. package/examples/main.css +22 -0
  240. package/examples/main.ts +23 -0
  241. package/examples/module-carousel/module-carousel.css +113 -0
  242. package/examples/module-carousel/module-carousel.html +208 -0
  243. package/examples/module-carousel/module-carousel.spec.ts +523 -0
  244. package/examples/module-carousel/module-carousel.ts +131 -0
  245. package/examples/module-catalog/module-catalog.css +22 -0
  246. package/examples/module-catalog/module-catalog.html +82 -0
  247. package/examples/module-catalog/module-catalog.spec.ts +396 -0
  248. package/examples/module-catalog/module-catalog.ts +37 -0
  249. package/examples/module-codeblock/module-codeblock.css +95 -0
  250. package/examples/module-codeblock/module-codeblock.html +28 -0
  251. package/examples/module-codeblock/module-codeblock.ts +47 -0
  252. package/examples/module-demo/module-demo.css +13 -0
  253. package/examples/module-dialog/module-dialog.css +96 -0
  254. package/examples/module-dialog/module-dialog.html +66 -0
  255. package/examples/module-dialog/module-dialog.spec.ts +557 -0
  256. package/examples/module-dialog/module-dialog.ts +81 -0
  257. package/examples/module-lazyload/mocks/empty.html +1 -0
  258. package/examples/module-lazyload/mocks/module-with-type.html +27 -0
  259. package/examples/module-lazyload/mocks/nested-components.html +52 -0
  260. package/examples/module-lazyload/mocks/recursive.html +20 -0
  261. package/examples/module-lazyload/mocks/simple-text.html +3 -0
  262. package/examples/module-lazyload/mocks/snippet.html +57 -0
  263. package/examples/module-lazyload/mocks/with-styles.html +39 -0
  264. package/examples/module-lazyload/module-lazyload.html +132 -0
  265. package/examples/module-lazyload/module-lazyload.spec.ts +734 -0
  266. package/examples/module-lazyload/module-lazyload.ts +89 -0
  267. package/examples/module-list/module-list.html +30 -0
  268. package/examples/module-list/module-list.spec.ts +592 -0
  269. package/examples/module-list/module-list.ts +99 -0
  270. package/examples/module-pagination/module-pagination.css +79 -0
  271. package/examples/module-pagination/module-pagination.html +16 -0
  272. package/examples/module-pagination/module-pagination.spec.ts +701 -0
  273. package/examples/module-pagination/module-pagination.ts +88 -0
  274. package/examples/module-scrollarea/module-scrollarea.css +77 -0
  275. package/examples/module-scrollarea/module-scrollarea.html +189 -0
  276. package/examples/module-scrollarea/module-scrollarea.spec.ts +445 -0
  277. package/examples/module-scrollarea/module-scrollarea.ts +81 -0
  278. package/examples/module-tabgroup/module-tabgroup.css +55 -0
  279. package/examples/module-tabgroup/module-tabgroup.html +269 -0
  280. package/examples/module-tabgroup/module-tabgroup.spec.ts +631 -0
  281. package/examples/module-tabgroup/module-tabgroup.ts +102 -0
  282. package/examples/module-toc/module-toc.css +34 -0
  283. package/examples/module-todo/module-todo.css +84 -0
  284. package/examples/module-todo/module-todo.html +92 -0
  285. package/examples/module-todo/module-todo.spec.ts +528 -0
  286. package/examples/module-todo/module-todo.ts +91 -0
  287. package/examples/section-hero/section-hero.css +37 -0
  288. package/examples/section-menu/section-menu.css +81 -0
  289. package/examples/server.ts +95 -0
  290. package/examples/test-setup.md +314 -0
  291. package/index.dev.js +1688 -0
  292. package/index.dev.ts +127 -0
  293. package/index.js +3 -0
  294. package/index.js.map +42 -0
  295. package/index.ts +127 -0
  296. package/package.json +64 -0
  297. package/playwright.config.ts +31 -0
  298. package/server/BUILD_SYSTEM.md +428 -0
  299. package/server/SERVER.md +286 -0
  300. package/server/build.ts +91 -0
  301. package/server/config.ts +130 -0
  302. package/server/effects/api.ts +28 -0
  303. package/server/effects/css.ts +31 -0
  304. package/server/effects/examples.ts +109 -0
  305. package/server/effects/js.ts +32 -0
  306. package/server/effects/menu.ts +34 -0
  307. package/server/effects/pages.ts +178 -0
  308. package/server/effects/service-worker.ts +57 -0
  309. package/server/effects/sitemap.ts +27 -0
  310. package/server/file-signals.ts +361 -0
  311. package/server/file-watcher.ts +77 -0
  312. package/server/io.ts +174 -0
  313. package/server/layout-engine.ts +470 -0
  314. package/server/layout-utils.ts +615 -0
  315. package/server/layouts/api.html +76 -0
  316. package/server/layouts/base.html +37 -0
  317. package/server/layouts/blog.html +115 -0
  318. package/server/layouts/example.html +104 -0
  319. package/server/layouts/overview.html +165 -0
  320. package/server/layouts/page.html +36 -0
  321. package/server/layouts/test.html +24 -0
  322. package/server/markdoc-helpers.ts +217 -0
  323. package/server/markdoc.config.ts +29 -0
  324. package/server/schema/callout.markdoc.ts +17 -0
  325. package/server/schema/carousel.markdoc.ts +118 -0
  326. package/server/schema/demo.markdoc.ts +74 -0
  327. package/server/schema/fence.markdoc.ts +84 -0
  328. package/server/schema/heading.markdoc.ts +23 -0
  329. package/server/schema/hero.markdoc.ts +59 -0
  330. package/server/schema/section.markdoc.ts +10 -0
  331. package/server/schema/slide.markdoc.ts +17 -0
  332. package/server/schema/source.markdoc.ts +53 -0
  333. package/server/schema/tabgroup.markdoc.ts +102 -0
  334. package/server/serve.ts +635 -0
  335. package/server/templates/README.md +352 -0
  336. package/server/templates/constants.ts +236 -0
  337. package/server/templates/fragments.ts +159 -0
  338. package/server/templates/hmr.ts +269 -0
  339. package/server/templates/menu.ts +33 -0
  340. package/server/templates/performance-hints.ts +94 -0
  341. package/server/templates/service-worker.ts +403 -0
  342. package/server/templates/sitemap.ts +57 -0
  343. package/server/templates/toc.ts +41 -0
  344. package/server/templates/utils.ts +378 -0
  345. package/src/component.ts +215 -0
  346. package/src/context.ts +156 -0
  347. package/src/effects/attribute.ts +82 -0
  348. package/src/effects/class.ts +28 -0
  349. package/src/effects/event.ts +67 -0
  350. package/src/effects/html.ts +60 -0
  351. package/src/effects/method.ts +57 -0
  352. package/src/effects/pass.ts +103 -0
  353. package/src/effects/property.ts +57 -0
  354. package/src/effects/style.ts +34 -0
  355. package/src/effects/text.ts +28 -0
  356. package/src/effects.ts +412 -0
  357. package/src/errors.ts +160 -0
  358. package/src/parsers/boolean.ts +14 -0
  359. package/src/parsers/json.ts +33 -0
  360. package/src/parsers/number.ts +55 -0
  361. package/src/parsers/string.ts +32 -0
  362. package/src/parsers.ts +90 -0
  363. package/src/scheduler.ts +47 -0
  364. package/src/signals/collection.ts +253 -0
  365. package/src/signals/sensor.ts +131 -0
  366. package/src/ui.ts +236 -0
  367. package/src/util.ts +187 -0
  368. package/tsconfig.json +34 -0
  369. package/types/examples/basic-button/basic-button.d.ts +16 -0
  370. package/types/examples/basic-hello/basic-hello.d.ts +18 -0
  371. package/types/index.d.ts +27 -0
  372. package/types/index.dev.d.ts +27 -0
  373. package/types/src/collection.d.ts +27 -0
  374. package/types/src/component.d.ts +32 -0
  375. package/types/src/context.d.ts +85 -0
  376. package/types/src/effects/attribute.d.ts +23 -0
  377. package/types/src/effects/callMethod.d.ts +23 -0
  378. package/types/src/effects/class.d.ts +13 -0
  379. package/types/src/effects/dangerouslySetInnerHTML.d.ts +18 -0
  380. package/types/src/effects/event.d.ts +18 -0
  381. package/types/src/effects/html.d.ts +17 -0
  382. package/types/src/effects/method.d.ts +22 -0
  383. package/types/src/effects/pass.d.ts +18 -0
  384. package/types/src/effects/property.d.ts +22 -0
  385. package/types/src/effects/setAttribute.d.ts +24 -0
  386. package/types/src/effects/setProperty.d.ts +23 -0
  387. package/types/src/effects/setStyle.d.ts +14 -0
  388. package/types/src/effects/setText.d.ts +13 -0
  389. package/types/src/effects/style.d.ts +13 -0
  390. package/types/src/effects/text.d.ts +12 -0
  391. package/types/src/effects/toggleClass.d.ts +14 -0
  392. package/types/src/effects.d.ts +153 -0
  393. package/types/src/errors.d.ts +99 -0
  394. package/types/src/events.d.ts +27 -0
  395. package/types/src/extractors.d.ts +23 -0
  396. package/types/src/parsers/boolean.d.ts +10 -0
  397. package/types/src/parsers/json.d.ts +13 -0
  398. package/types/src/parsers/number.d.ts +21 -0
  399. package/types/src/parsers/string.d.ts +19 -0
  400. package/types/src/parsers.d.ts +41 -0
  401. package/types/src/scheduler.d.ts +11 -0
  402. package/types/src/sensor.d.ts +27 -0
  403. package/types/src/signals/collection.d.ts +32 -0
  404. package/types/src/signals/sensor.d.ts +27 -0
  405. package/types/src/ui.d.ts +37 -0
  406. package/types/src/util.d.ts +65 -0
@@ -0,0 +1,615 @@
1
+ import {
2
+ CONTENT_MARKER,
3
+ LAYOUT_PATHS,
4
+ LAYOUTS_DIR,
5
+ type LayoutConfig,
6
+ ROUTE_LAYOUT_MAP,
7
+ } from './config'
8
+ import { fileExists, getFileContent, getFilePath, writeFileSafe } from './io'
9
+ import { DEFAULT_LAYOUTS, LayoutEngine } from './layout-engine'
10
+
11
+ /**
12
+ * Layout development utilities
13
+ */
14
+ export class LayoutUtils {
15
+ /**
16
+ * Validate all layout files exist and are readable
17
+ */
18
+ static async validateLayouts(): Promise<{
19
+ valid: boolean
20
+ errors: string[]
21
+ }> {
22
+ const errors: string[] = []
23
+
24
+ for (const [name, path] of Object.entries(LAYOUT_PATHS)) {
25
+ if (!fileExists(path)) {
26
+ errors.push(`Layout file not found: ${name} at ${path}`)
27
+ continue
28
+ }
29
+
30
+ try {
31
+ await getFileContent(path)
32
+ } catch (error) {
33
+ errors.push(`Cannot read layout file: ${name} at ${path} - ${error}`)
34
+ }
35
+ }
36
+
37
+ return {
38
+ valid: errors.length === 0,
39
+ errors,
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Generate a layout template with common structure
45
+ */
46
+ static generateLayoutTemplate(
47
+ name: string,
48
+ options: {
49
+ title?: string
50
+ hasHeader?: boolean
51
+ hasFooter?: boolean
52
+ hasNavigation?: boolean
53
+ customCSS?: string
54
+ customJS?: string
55
+ } = {},
56
+ ): string {
57
+ const {
58
+ title = `{{ title }} – Le Truc`,
59
+ hasHeader = true,
60
+ hasFooter = true,
61
+ hasNavigation = false,
62
+ customCSS = '',
63
+ customJS = '',
64
+ } = options
65
+
66
+ return `<!doctype html>
67
+ <html lang="en">
68
+ <head>
69
+ <meta charset="UTF-8" />
70
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
71
+ <title>${title}</title>
72
+ <meta name="description" content="{{ description }}" />
73
+ <link
74
+ rel="preload"
75
+ href="{{ base-path }}assets/main.css?v={{ css-hash }}"
76
+ as="style"
77
+ />
78
+ <link
79
+ rel="modulepreload"
80
+ href="{{ base-path }}assets/main.js?v={{ js-hash }}"
81
+ />
82
+ <link
83
+ rel="stylesheet"
84
+ href="{{ base-path }}assets/main.css?v={{ css-hash }}"
85
+ />
86
+ <script
87
+ type="module"
88
+ src="{{ base-path }}assets/main.js?v={{ js-hash }}"
89
+ ></script>${
90
+ customCSS
91
+ ? `
92
+ <style>
93
+ ${customCSS}
94
+ </style>`
95
+ : ''
96
+ }
97
+ </head>
98
+ <body class="{{ section }} ${name}-page">${
99
+ hasHeader
100
+ ? `
101
+ <context-router>
102
+ <header class="content-grid">
103
+ <a href="#main" class="skiplink visually-hidden">
104
+ Skip to main content
105
+ </a>
106
+ <h1 class="content">Le Truc <small>Version 0.15.0</small></h1>${
107
+ hasNavigation
108
+ ? `
109
+ {{ include 'menu.html' }}`
110
+ : ''
111
+ }
112
+ <card-callout class="content danger" hidden>
113
+ <p class="error" role="alert" aria-live="assertive"></p>
114
+ </card-callout>
115
+ </header>`
116
+ : ''
117
+ }
118
+ <main id="main" class="content-grid">
119
+ <div class="content">
120
+ {{ content }}
121
+ </div>
122
+ </main>${
123
+ hasFooter
124
+ ? `
125
+ <footer class="content-grid">
126
+ <div class="content">
127
+ <h2 class="visually-hidden">Footer</h2>
128
+ <p>© 2024 – 2025 Zeix AG</p>
129
+ </div>
130
+ </footer>`
131
+ : ''
132
+ }${
133
+ hasHeader
134
+ ? `
135
+ </context-router>`
136
+ : ''
137
+ }${
138
+ customJS
139
+ ? `
140
+ <script>
141
+ ${customJS}
142
+ </script>`
143
+ : ''
144
+ }
145
+ </body>
146
+ </html>`
147
+ }
148
+
149
+ /**
150
+ * Create a new layout file
151
+ */
152
+ static async createLayout(
153
+ name: string,
154
+ template?: string,
155
+ options?: Parameters<typeof LayoutUtils.generateLayoutTemplate>[1],
156
+ ): Promise<void> {
157
+ const layoutPath = getFilePath(LAYOUTS_DIR, `${name}.html`)
158
+
159
+ if (fileExists(layoutPath)) {
160
+ throw new Error(`Layout ${name} already exists at ${layoutPath}`)
161
+ }
162
+
163
+ const content = template || this.generateLayoutTemplate(name, options)
164
+ await writeFileSafe(layoutPath, content)
165
+
166
+ console.log(`✅ Created layout: ${name} at ${layoutPath}`)
167
+ }
168
+
169
+ /**
170
+ * Extract template variables from layout content
171
+ */
172
+ static extractTemplateVariables(content: string): string[] {
173
+ const variables = new Set<string>()
174
+ const regex = /{{\s*([\w\-]+)\s*}}/g
175
+ let match: RegExpExecArray | null
176
+
177
+ while ((match = regex.exec(content)) !== null) {
178
+ const variable = match[1].trim()
179
+ if (variable !== 'content') {
180
+ // Exclude the main content variable
181
+ variables.add(variable)
182
+ }
183
+ }
184
+
185
+ return Array.from(variables).sort()
186
+ }
187
+
188
+ /**
189
+ * Analyze layout usage across routes
190
+ */
191
+ static analyzeLayoutUsage(): Record<string, string[]> {
192
+ const usage: Record<string, string[]> = {}
193
+
194
+ for (const [route, layout] of Object.entries(ROUTE_LAYOUT_MAP)) {
195
+ if (!usage[layout]) {
196
+ usage[layout] = []
197
+ }
198
+ usage[layout].push(route)
199
+ }
200
+
201
+ return usage
202
+ }
203
+
204
+ /**
205
+ * Generate layout configuration for a new layout
206
+ */
207
+ static generateLayoutConfig(
208
+ name: string,
209
+ options: {
210
+ type?: 'simple' | 'template'
211
+ contentMarker?: string
212
+ defaultContext?: Record<string, string>
213
+ } = {},
214
+ ): LayoutConfig {
215
+ return {
216
+ name,
217
+ path: getFilePath(LAYOUTS_DIR, `${name}.html`),
218
+ type: options.type || 'template',
219
+ contentMarker: options.contentMarker || CONTENT_MARKER,
220
+ defaultContext: options.defaultContext,
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Preview layout with sample content
226
+ */
227
+ static async previewLayout(
228
+ name: string,
229
+ sampleContent: string = '<h1>Sample Content</h1><p>This is a preview of your layout.</p>',
230
+ context: Record<string, string> = {},
231
+ ): Promise<string> {
232
+ const engine = new LayoutEngine(DEFAULT_LAYOUTS)
233
+
234
+ const defaultContext = {
235
+ title: 'Layout Preview',
236
+ description: 'Preview of layout with sample content',
237
+ section: 'preview',
238
+ 'base-path': '',
239
+ 'css-hash': 'preview',
240
+ 'js-hash': 'preview',
241
+ ...context,
242
+ }
243
+
244
+ return engine.renderWithLayout(name, sampleContent, defaultContext)
245
+ }
246
+
247
+ /**
248
+ * Check for unused template variables in layouts
249
+ */
250
+ static async findUnusedVariables(): Promise<Record<string, string[]>> {
251
+ const unused: Record<string, string[]> = {}
252
+
253
+ for (const [name, path] of Object.entries(LAYOUT_PATHS)) {
254
+ if (!fileExists(path)) continue
255
+
256
+ try {
257
+ const content = await getFileContent(path)
258
+ const variables = this.extractTemplateVariables(content)
259
+
260
+ // Common variables that are always available
261
+ const commonVars = new Set([
262
+ 'title',
263
+ 'description',
264
+ 'section',
265
+ 'base-path',
266
+ 'css-hash',
267
+ 'js-hash',
268
+ 'content',
269
+ ])
270
+
271
+ const potentiallyUnused = variables.filter(v => !commonVars.has(v))
272
+ if (potentiallyUnused.length > 0) {
273
+ unused[name] = potentiallyUnused
274
+ }
275
+ } catch (error) {
276
+ console.warn(`Could not analyze ${name}: ${error}`)
277
+ }
278
+ }
279
+
280
+ return unused
281
+ }
282
+
283
+ /**
284
+ * Generate route test URLs for layout testing
285
+ */
286
+ static generateTestUrls(): Record<string, string[]> {
287
+ const testUrls: Record<string, string[]> = {}
288
+
289
+ for (const [route, layout] of Object.entries(ROUTE_LAYOUT_MAP)) {
290
+ if (!testUrls[layout]) {
291
+ testUrls[layout] = []
292
+ }
293
+
294
+ // Generate sample URLs based on route patterns
295
+ if (route.includes('{')) {
296
+ // Dynamic route - generate sample
297
+ const sampleUrl = route
298
+ .replace('{component}', 'sample-component')
299
+ .replace('{example}', 'basic-example')
300
+ .replace('{id}', 'sample-item')
301
+ .replace('{article}', 'sample-article')
302
+ testUrls[layout].push(sampleUrl + 'sample.html')
303
+ } else {
304
+ // Static route
305
+ testUrls[layout].push(route + (route.endsWith('/') ? 'index.html' : ''))
306
+ }
307
+ }
308
+
309
+ return testUrls
310
+ }
311
+
312
+ /**
313
+ * Lint layout files for common issues
314
+ */
315
+ static async lintLayouts(): Promise<
316
+ {
317
+ layout: string
318
+ issues: Array<{ type: 'error' | 'warning' | 'info'; message: string }>
319
+ }[]
320
+ > {
321
+ const results: {
322
+ layout: string
323
+ issues: Array<{ type: 'error' | 'warning' | 'info'; message: string }>
324
+ }[] = []
325
+
326
+ for (const [name, path] of Object.entries(LAYOUT_PATHS)) {
327
+ const issues: Array<{
328
+ type: 'error' | 'warning' | 'info'
329
+ message: string
330
+ }> = []
331
+
332
+ if (!fileExists(path)) {
333
+ issues.push({
334
+ type: 'error',
335
+ message: `Layout file not found: ${path}`,
336
+ })
337
+ results.push({ layout: name, issues })
338
+ continue
339
+ }
340
+
341
+ try {
342
+ const content = await getFileContent(path)
343
+
344
+ // Check for required elements
345
+ if (!content.includes('<!doctype html>')) {
346
+ issues.push({
347
+ type: 'warning',
348
+ message: 'Missing DOCTYPE declaration',
349
+ })
350
+ }
351
+
352
+ if (!content.includes('<title>')) {
353
+ issues.push({ type: 'warning', message: 'Missing title element' })
354
+ }
355
+
356
+ if (!content.includes('{{ content }}')) {
357
+ issues.push({
358
+ type: 'error',
359
+ message: 'Missing {{ content }} placeholder',
360
+ })
361
+ }
362
+
363
+ if (!content.includes('charset="UTF-8"')) {
364
+ issues.push({
365
+ type: 'warning',
366
+ message: 'Missing or incorrect charset declaration',
367
+ })
368
+ }
369
+
370
+ if (!content.includes('viewport')) {
371
+ issues.push({ type: 'warning', message: 'Missing viewport meta tag' })
372
+ }
373
+
374
+ // Check for accessibility
375
+ if (!content.includes('lang="')) {
376
+ issues.push({
377
+ type: 'warning',
378
+ message: 'Missing lang attribute on html element',
379
+ })
380
+ }
381
+
382
+ if (
383
+ content.includes('<a href="#main"')
384
+ && !content.includes('id="main"')
385
+ ) {
386
+ issues.push({
387
+ type: 'warning',
388
+ message: 'Skip link target not found',
389
+ })
390
+ }
391
+
392
+ // Check for potential issues
393
+ if (content.includes('{{') && content.includes('}}')) {
394
+ const variables = this.extractTemplateVariables(content)
395
+ if (variables.length === 0) {
396
+ issues.push({
397
+ type: 'info',
398
+ message: 'No template variables found',
399
+ })
400
+ }
401
+ }
402
+
403
+ results.push({ layout: name, issues })
404
+ } catch (error) {
405
+ issues.push({
406
+ type: 'error',
407
+ message: `Cannot read layout file: ${error}`,
408
+ })
409
+ results.push({ layout: name, issues })
410
+ }
411
+ }
412
+
413
+ return results
414
+ }
415
+
416
+ /**
417
+ * Generate development report for layouts
418
+ */
419
+ static async generateReport(): Promise<string> {
420
+ const validation = await this.validateLayouts()
421
+ const usage = this.analyzeLayoutUsage()
422
+ const testUrls = this.generateTestUrls()
423
+ const lintResults = await this.lintLayouts()
424
+ const unused = await this.findUnusedVariables()
425
+
426
+ let report = '# Layout System Report\n\n'
427
+
428
+ // Validation section
429
+ report += '## Layout Validation\n\n'
430
+ if (validation.valid) {
431
+ report += '✅ All layouts are valid and readable\n\n'
432
+ } else {
433
+ report += '❌ Layout validation issues found:\n\n'
434
+ for (const error of validation.errors) {
435
+ report += `- ${error}\n`
436
+ }
437
+ report += '\n'
438
+ }
439
+
440
+ // Usage analysis
441
+ report += '## Layout Usage\n\n'
442
+ for (const [layout, routes] of Object.entries(usage)) {
443
+ report += `### ${layout}\n`
444
+ report += `Routes: ${routes.length}\n`
445
+ for (const route of routes) {
446
+ report += `- \`${route}\`\n`
447
+ }
448
+ report += '\n'
449
+ }
450
+
451
+ // Test URLs
452
+ report += '## Test URLs\n\n'
453
+ for (const [layout, urls] of Object.entries(testUrls)) {
454
+ report += `### ${layout}\n`
455
+ for (const url of urls) {
456
+ report += `- http://localhost:5000${url}\n`
457
+ }
458
+ report += '\n'
459
+ }
460
+
461
+ // Lint results
462
+ report += '## Layout Linting\n\n'
463
+ for (const result of lintResults) {
464
+ if (result.issues.length === 0) {
465
+ report += `✅ **${result.layout}**: No issues\n\n`
466
+ } else {
467
+ report += `### ${result.layout}\n\n`
468
+ for (const issue of result.issues) {
469
+ const icon =
470
+ issue.type === 'error'
471
+ ? '❌'
472
+ : issue.type === 'warning'
473
+ ? '⚠️'
474
+ : 'ℹ️'
475
+ report += `${icon} ${issue.message}\n`
476
+ }
477
+ report += '\n'
478
+ }
479
+ }
480
+
481
+ // Unused variables
482
+ if (Object.keys(unused).length > 0) {
483
+ report += '## Potentially Unused Variables\n\n'
484
+ for (const [layout, variables] of Object.entries(unused)) {
485
+ report += `### ${layout}\n`
486
+ for (const variable of variables) {
487
+ report += `- \`{{ ${variable} }}\`\n`
488
+ }
489
+ report += '\n'
490
+ }
491
+ }
492
+
493
+ return report
494
+ }
495
+ }
496
+
497
+ /**
498
+ * CLI helper functions
499
+ */
500
+ export const LayoutCLI = {
501
+ /**
502
+ * Create a new layout interactively
503
+ */
504
+ async createInteractive(): Promise<void> {
505
+ console.log('🎨 Creating new layout...')
506
+
507
+ // This would typically use a CLI library like inquirer
508
+ // For now, just show the concept
509
+ const name = process.argv[3] || 'new-layout'
510
+ const hasHeader = true
511
+ const hasFooter = true
512
+ const hasNavigation = false
513
+
514
+ await LayoutUtils.createLayout(name, undefined, {
515
+ hasHeader,
516
+ hasFooter,
517
+ hasNavigation,
518
+ })
519
+
520
+ console.log(`
521
+ Next steps:
522
+ 1. Edit the layout file: server/layouts/${name}.html
523
+ 2. Add route mapping in server/config.ts
524
+ 3. Add to DEFAULT_LAYOUTS in server/layout-engine.ts
525
+ 4. Test with: bun server/serve.ts --mode unified
526
+ `)
527
+ },
528
+
529
+ /**
530
+ * Validate all layouts
531
+ */
532
+ async validate(): Promise<void> {
533
+ console.log('🔍 Validating layouts...')
534
+ const result = await LayoutUtils.validateLayouts()
535
+
536
+ if (result.valid) {
537
+ console.log('✅ All layouts are valid')
538
+ } else {
539
+ console.log('❌ Validation errors found:')
540
+ for (const error of result.errors) {
541
+ console.log(` ${error}`)
542
+ }
543
+ process.exit(1)
544
+ }
545
+ },
546
+
547
+ /**
548
+ * Generate and display report
549
+ */
550
+ async report(): Promise<void> {
551
+ console.log('📊 Generating layout report...')
552
+ const report = await LayoutUtils.generateReport()
553
+ console.log(report)
554
+ },
555
+
556
+ /**
557
+ * Preview a layout
558
+ */
559
+ async preview(): Promise<void> {
560
+ const layoutName = process.argv[3]
561
+ if (!layoutName) {
562
+ console.log('Usage: bun server/layout-utils.ts preview <layout-name>')
563
+ process.exit(1)
564
+ }
565
+
566
+ try {
567
+ const html = await LayoutUtils.previewLayout(layoutName)
568
+ console.log('📋 Layout preview:')
569
+ console.log(html)
570
+ } catch (error) {
571
+ console.error('❌ Preview failed:', error)
572
+ process.exit(1)
573
+ }
574
+ },
575
+ }
576
+
577
+ // CLI interface
578
+ if (import.meta.main) {
579
+ const command = process.argv[2]
580
+
581
+ switch (command) {
582
+ case 'create':
583
+ await LayoutCLI.createInteractive()
584
+ break
585
+ case 'validate':
586
+ await LayoutCLI.validate()
587
+ break
588
+ case 'report':
589
+ await LayoutCLI.report()
590
+ break
591
+ case 'preview':
592
+ await LayoutCLI.preview()
593
+ break
594
+ default:
595
+ console.log(`
596
+ Layout Utils CLI
597
+
598
+ Usage:
599
+ bun server/layout-utils.ts <command>
600
+
601
+ Commands:
602
+ create Create a new layout interactively
603
+ validate Validate all layout files
604
+ report Generate development report
605
+ preview Preview a layout with sample content
606
+
607
+ Examples:
608
+ bun server/layout-utils.ts create
609
+ bun server/layout-utils.ts validate
610
+ bun server/layout-utils.ts report
611
+ bun server/layout-utils.ts preview page
612
+ `)
613
+ break
614
+ }
615
+ }
@@ -0,0 +1,76 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>{{ title }} – Le Truc API</title>
7
+ <meta name="description" content="{{ description }}" />
8
+ <link
9
+ rel="preload"
10
+ href="{{ base-path }}assets/main.css?v={{ css-hash }}"
11
+ as="style"
12
+ />
13
+ <link
14
+ rel="modulepreload"
15
+ href="{{ base-path }}assets/main.js?v={{ js-hash }}"
16
+ />
17
+ <link
18
+ rel="stylesheet"
19
+ href="{{ base-path }}assets/main.css?v={{ css-hash }}"
20
+ />
21
+ <script
22
+ type="module"
23
+ src="{{ base-path }}assets/main.js?v={{ js-hash }}"
24
+ ></script>
25
+ </head>
26
+ <body class="api">
27
+ <context-router>
28
+ <header class="content-grid">
29
+ <a href="#main" class="skiplink visually-hidden">
30
+ Skip to main content
31
+ </a>
32
+ <h1 class="content">Le Truc Docs <small>Version 0.15.0</small></h1>
33
+ {{ include 'menu.html' }}
34
+ <card-callout class="content danger" hidden>
35
+ <p class="error" role="alert" aria-live="assertive"></p>
36
+ </card-callout>
37
+ </header>
38
+ <div class="api-header">
39
+ <div class="content-grid">
40
+ <div class="content">
41
+ <nav class="api-breadcrumb" aria-label="Breadcrumb">
42
+ <a href="/api/">API</a> ›
43
+ <a href="/api/{{ api-category }}/">{{ api-category }}</a> ›
44
+ {{ api-name }}
45
+ </nav>
46
+ <h1 class="api-title">
47
+ {{ api-name }}
48
+ <span class="api-kind {{ api-kind }}">{{ api-kind }}</span>
49
+ </h1>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ <main id="main" class="content-grid">
54
+ <div class="content api-content">
55
+ <div class="grid" style="grid-template-columns: 1fr 300px; gap: 2rem;">
56
+ <article></article>
57
+ {{ content }}
58
+ </article>
59
+ <aside class="api-sidebar">
60
+ <nav class="api-nav" aria-label="Page contents">
61
+ <h3>On this page</h3>
62
+ {{ toc }}
63
+ </nav>
64
+ </aside>
65
+ </div>
66
+ </div>
67
+ </main>
68
+ <footer class="content-grid">
69
+ <div class="content">
70
+ <h2 class="visually-hidden">Footer</h2>
71
+ <p>© 2024 – 2025 Zeix AG</p>
72
+ </div>
73
+ </footer>
74
+ </context-router>
75
+ </body>
76
+ </html>