@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,81 @@
1
+ section-menu {
2
+ grid-column: breakout;
3
+
4
+ & ol {
5
+ display: grid;
6
+ list-style: none;
7
+ gap: var(--space-s);
8
+ margin-block: var(--space-l);
9
+ grid-template-columns: 1fr;
10
+ padding: 0;
11
+ }
12
+
13
+ & li {
14
+ padding: 0;
15
+ margin: 0;
16
+ }
17
+
18
+ & a {
19
+ display: grid;
20
+ grid-template-areas: "icon title" "icon description";
21
+ grid-template-columns: auto 1fr;
22
+ grid-template-rows: auto 1fr;
23
+ gap: var(--space-xs) var(--space-s);
24
+ padding: var(--space-m);
25
+ border-radius: var(--space-xs);
26
+ height: calc(100% - 2 * var(--space-m));
27
+ color: var(--color-text);
28
+ text-decoration: none;
29
+
30
+ &:hover,
31
+ &:focus {
32
+ background-color: var(--color-secondary-hover);
33
+ }
34
+
35
+ &.active {
36
+ background-color: var(--color-background-alt);
37
+ }
38
+
39
+ .icon {
40
+ grid-area: icon;
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ font-size: var(--font-size-l);
45
+ width: var(--space-xl);
46
+ height: var(--space-xl);
47
+ border-radius: 50%;
48
+ background-color: var(--color-background);
49
+ border: 1px solid var(--color-border);
50
+ }
51
+
52
+ & strong {
53
+ grid-area: title;
54
+ font-size: var(--font-size-m);
55
+ line-height: var(--line-height-s);
56
+ margin: 0;
57
+ }
58
+
59
+ & small {
60
+ grid-area: description;
61
+ font-size: var(--font-size-s);
62
+ line-height: var(--line-height-m);
63
+ margin: 0;
64
+ color: var(--color-text-soft);
65
+ }
66
+ }
67
+ }
68
+
69
+ @media screen and (min-width: 32em) and (max-width: 48em) {
70
+ section-menu ol {
71
+ grid-template-columns: 1fr 1fr;
72
+ gap: var(--space-m);
73
+ }
74
+ }
75
+
76
+ @media screen and (min-width: 48em) {
77
+ section-menu ol {
78
+ grid-template-columns: 1fr 1fr 1fr;
79
+ gap: var(--space-l);
80
+ }
81
+ }
@@ -0,0 +1,95 @@
1
+ import { serve } from 'bun'
2
+ import { readdir, readFile } from 'fs/promises'
3
+ import { join } from 'path'
4
+
5
+ // Directory containing example fragments
6
+ const EXAMPLES_DIR = './examples'
7
+ const LAYOUT_PATH = join(EXAMPLES_DIR, 'layout.html')
8
+
9
+ // Helper to get all component fragments (*.html in examples/*/)
10
+ async function getComponentFragments() {
11
+ const dirs = await readdir(EXAMPLES_DIR, { withFileTypes: true })
12
+ const fragments: Record<string, string> = {}
13
+ for (const dir of dirs) {
14
+ if (!dir.isDirectory() || dir.name === 'assets' || dir.name === '_common')
15
+ continue
16
+ const files = await readdir(join(EXAMPLES_DIR, dir.name))
17
+ for (const file of files) {
18
+ if (file.endsWith('.html')) {
19
+ const component = file.replace(/\.html$/, '')
20
+ fragments[component] = join(EXAMPLES_DIR, dir.name, file)
21
+ }
22
+ }
23
+ }
24
+ return fragments
25
+ }
26
+
27
+ // Serve /test/{component}.html with injected fragment
28
+ async function serveTestPage(component: string): Promise<Response> {
29
+ try {
30
+ const fragments = await getComponentFragments()
31
+ const fragmentPath = fragments[component]
32
+ if (!fragmentPath) {
33
+ return new Response('Component not found', { status: 404 })
34
+ }
35
+ const [layout, fragment] = await Promise.all([
36
+ readFile(LAYOUT_PATH, 'utf8'),
37
+ readFile(fragmentPath, 'utf8'),
38
+ ])
39
+ // Replace marker in layout with fragment
40
+ const html = layout.replace(/<!-- \{\{content}} -->/, fragment)
41
+ return new Response(html, {
42
+ headers: { 'Content-Type': 'text/html; charset=utf-8' },
43
+ })
44
+ } catch (_err) {
45
+ return new Response('Error rendering test page', { status: 500 })
46
+ }
47
+ }
48
+
49
+ // Serve static assets (main.js, main.css, etc.)
50
+ async function serveStaticAsset(url: string): Promise<Response> {
51
+ try {
52
+ const assetPath = join('.', url)
53
+ const asset = await readFile(assetPath)
54
+ let contentType = 'application/octet-stream'
55
+ if (url.endsWith('.js')) contentType = 'application/javascript'
56
+ if (url.endsWith('.css')) contentType = 'text/css'
57
+ if (url.endsWith('.html')) contentType = 'text/html'
58
+ if (url.endsWith('.json')) contentType = 'application/json'
59
+ return new Response(asset, { headers: { 'Content-Type': contentType } })
60
+ } catch (_err) {
61
+ return new Response('Asset not found', { status: 404 })
62
+ }
63
+ }
64
+
65
+ // Main server
66
+ serve({
67
+ port: 3000,
68
+ async fetch(req) {
69
+ const url = new URL(req.url)
70
+ // Serve /test/{component}.html
71
+ const testMatch = url.pathname.match(/^\/test\/([a-zA-Z0-9_-]+)\.html$/)
72
+ if (testMatch) {
73
+ const component = testMatch[1]
74
+ return await serveTestPage(component)
75
+ }
76
+ // Serve static assets from /examples/assets/
77
+ if (url.pathname.startsWith('/assets/')) {
78
+ return await serveStaticAsset('examples' + url.pathname)
79
+ }
80
+ // Serve static fragments and other files for manual inspection
81
+ const fragmentMatch = url.pathname.match(
82
+ /^\/([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+)\.(html|json)$/,
83
+ )
84
+ if (fragmentMatch) {
85
+ return await serveStaticAsset('examples' + url.pathname)
86
+ }
87
+ // Serve layout.html for root
88
+ if (url.pathname === '/' || url.pathname === '/layout.html') {
89
+ return await serveStaticAsset('examples/layout.html')
90
+ }
91
+ return new Response('Not found', { status: 404 })
92
+ },
93
+ })
94
+
95
+ console.log('Bun example server running at http://localhost:3000/')
@@ -0,0 +1,314 @@
1
+ # Le Truc Testing Guide
2
+
3
+ ## Test Infrastructure Overview
4
+
5
+ Le Truc uses a sophisticated test setup that combines Bun's build system with Playwright for end-to-end testing. Here's how the pieces work together:
6
+
7
+ ### **Test Server Architecture**
8
+
9
+ 1. **Bun Development Server** (`examples/server.ts`)
10
+ - Serves on `http://localhost:3000`
11
+ - Dynamically injects component HTML fragments into a layout template
12
+ - Routes `/test/{component}.html` to render component examples for testing
13
+ - Serves compiled assets from `/assets/` directory
14
+
15
+ 2. **Layout Template** (`examples/layout.html`)
16
+ - Base HTML structure with compiled JS/CSS imports
17
+ - Component HTML fragments are injected via comment placeholder
18
+ - Provides consistent testing environment across all components
19
+
20
+ 3. **Asset Compilation**
21
+ - `bun run build:examples` compiles all components and examples
22
+ - Creates `examples/assets/main.js` and `examples/assets/main.css`
23
+ - Includes all component definitions and shared styles
24
+
25
+ ### **Test Structure**
26
+
27
+ ```typescript
28
+ // Standard test pattern
29
+ test.describe('component-name component', () => {
30
+ test.beforeEach(async ({ page }) => {
31
+ await page.goto('http://localhost:3000/test/component-name.html')
32
+ await page.waitForSelector('component-name')
33
+ })
34
+
35
+ test('test description', async ({ page }) => {
36
+ // Test implementation
37
+ })
38
+ })
39
+ ```
40
+
41
+ ### **Fixture System**
42
+
43
+ - **HTML Fixtures**: Each component's `.html` file in `examples/` serves as test fixture
44
+ - **Dynamic Injection**: Server reads HTML files and injects them into layout
45
+ - **Multiple Instances**: HTML fixtures can contain multiple component instances with different configurations
46
+ - **Real DOM**: Tests run against actual component implementations, not mocks
47
+
48
+ ## Le Truc Component Architecture
49
+
50
+ ### **1. Reactive Properties**
51
+
52
+ All custom component properties in Le Truc are reactive - they track access and notify on changes. The component's `Props` type interface defines which properties can be controlled externally:
53
+
54
+ ```typescript
55
+ type FormCheckboxProps = {
56
+ readonly checked: boolean // Read-only sensor property
57
+ label: string // Writable reactive property
58
+ }
59
+ ```
60
+
61
+ **Key Points**:
62
+ - Properties marked `readonly` cannot be set externally
63
+ - Writable properties can be controlled by outside components or arbitrary JavaScript
64
+ - All properties are reactive and will trigger updates when changed
65
+
66
+ ### **2. Uncontrolled Form Components**
67
+
68
+ **Key Insight**: Le Truc form components are fundamentally different from React-style controlled components.
69
+
70
+ ```typescript
71
+ // 🚫 Wrong assumption - trying to control read-only sensor property
72
+ await page.evaluate(() => {
73
+ const element = document.querySelector('form-checkbox')
74
+ element.checked = true // This won't work - readonly property
75
+ })
76
+
77
+ // ✅ Correct approach - interact with actual DOM elements
78
+ const checkbox = page.locator('form-checkbox input[type="checkbox"]')
79
+ await checkbox.click() // User interaction drives state
80
+
81
+ // ✅ Also correct - setting writable properties
82
+ await page.evaluate(() => {
83
+ const element = document.querySelector('form-checkbox')
84
+ element.label = 'New Label' // This works - writable property
85
+ })
86
+ ```
87
+
88
+ **Why**: Le Truc protects user-entered data from external JavaScript modification while allowing controlled updates to non-sensitive properties.
89
+
90
+ ### **3. Sensor-Based State Management**
91
+
92
+ Many Le Truc form components use sensors that read from DOM elements:
93
+
94
+ ```typescript
95
+ // Component definition
96
+ checked: createSensor(
97
+ read(ui => ui.checkbox.checked, false),
98
+ 'checkbox',
99
+ { change: ({ target }) => target.checked },
100
+ )
101
+ ```
102
+
103
+ **Testing Implications**:
104
+ - Sensor properties are read-only and reflect DOM state
105
+ - State updates only through user interactions or DOM events
106
+ - Test by simulating real user behavior for sensor properties
107
+ - Other properties can be set programmatically if not marked readonly
108
+
109
+ ### **4. Security-First Design**
110
+
111
+ Le Truc assumes potential malicious JavaScript on the page:
112
+
113
+ - **User interactions** (clicks, typing, form submissions) are trusted
114
+ - **Sensor properties** are protected from external manipulation
115
+ - **Writable properties** can be controlled but are still reactive
116
+ - **Server-rendered HTML** provides initial trusted state
117
+
118
+ ## Testing Best Practices
119
+
120
+ ### **1. Understanding Property Types**
121
+
122
+ Before testing, check the component's Props interface:
123
+
124
+ ```typescript
125
+ // Check component definition
126
+ type MyComponentProps = {
127
+ readonly sensorValue: number // Test via user interaction
128
+ writableValue: string // Can test both ways
129
+ label: string // Writable reactive property
130
+ }
131
+ ```
132
+
133
+ ### **2. Test Real User Interactions for Sensors**
134
+
135
+ ```typescript
136
+ // For readonly/sensor properties
137
+ await button.click()
138
+ await input.fill('text')
139
+ await select.selectOption('value')
140
+ ```
141
+
142
+ ### **3. Test Programmatic Updates for Writable Properties**
143
+
144
+ ```typescript
145
+ // For writable reactive properties
146
+ await page.evaluate(() => {
147
+ const element = document.querySelector('my-component')
148
+ element.label = 'New Label' // This works
149
+ element.writableValue = 'test' // This works
150
+ })
151
+ ```
152
+
153
+ ### **4. Verify Property Reactivity**
154
+
155
+ ```typescript
156
+ // Test that property changes trigger updates
157
+ await page.evaluate(() => {
158
+ const element = document.querySelector('my-component')
159
+ element.label = 'Updated Label'
160
+ })
161
+
162
+ const labelElement = page.locator('my-component .label')
163
+ await expect(labelElement).toHaveText('Updated Label')
164
+ ```
165
+
166
+ ### **5. Test Read-only Property Reflection**
167
+
168
+ ```typescript
169
+ // Check that readonly properties reflect internal state
170
+ const sensorValue = await page.evaluate(() => {
171
+ const element = document.querySelector('form-checkbox')
172
+ return element.checked // Read-only reflection of DOM state
173
+ })
174
+ expect(sensorValue).toBe(true)
175
+ ```
176
+
177
+ ### **6. Test Multiple Component Instances**
178
+
179
+ ```typescript
180
+ const firstComponent = page.locator('form-checkbox').first()
181
+ const secondComponent = page.locator('form-checkbox.todo')
182
+ // Test independence between instances
183
+ ```
184
+
185
+ ### **7. Validate Attribute Synchronization**
186
+
187
+ ```typescript
188
+ // Components sync internal state to host attributes
189
+ await expect(component).toHaveAttribute('checked')
190
+ await expect(component).not.toHaveAttribute('checked')
191
+ ```
192
+
193
+ ### **8. Test Form Integration**
194
+
195
+ ```typescript
196
+ // Verify components work with standard form APIs
197
+ const formData = await page.evaluate(() => {
198
+ const form = document.querySelector('form')
199
+ return Object.fromEntries(new FormData(form).entries())
200
+ })
201
+ ```
202
+
203
+ ## Event-Driven Updates
204
+
205
+ Components respond to real DOM events for sensor properties:
206
+
207
+ ```typescript
208
+ // ✅ Correct - triggers sensor update
209
+ await checkbox.click()
210
+
211
+ // ✅ Also correct - dispatches real event
212
+ await page.evaluate(() => {
213
+ const input = document.querySelector('input[type="checkbox"]')
214
+ input.checked = true
215
+ input.dispatchEvent(new Event('change', { bubbles: true }))
216
+ })
217
+
218
+ // 🚫 Wrong - doesn't trigger sensor updates
219
+ await page.evaluate(() => {
220
+ const input = document.querySelector('input[type="checkbox"]')
221
+ input.checked = true // Missing event dispatch
222
+ })
223
+ ```
224
+
225
+ ## Common Testing Pitfalls
226
+
227
+ ### **🚫 Don't**: Try to control readonly sensor properties
228
+ ```typescript
229
+ element.checked = true // Ignored if readonly
230
+ element.value = 'new value' // Won't work for sensors
231
+ ```
232
+
233
+ ### **🚫 Don't**: Assume all properties are readonly
234
+ ```typescript
235
+ // Check the Props interface first
236
+ element.label = 'new label' // This might work!
237
+ ```
238
+
239
+ ### **🚫 Don't**: Assume React-like behavior
240
+ ```typescript
241
+ // This pattern doesn't work in Le Truc
242
+ component.props.onChange({ target: { checked: true }})
243
+ ```
244
+
245
+ ### **🚫 Don't**: Mock component behavior
246
+ ```typescript
247
+ // Test real components, not mocked implementations
248
+ ```
249
+
250
+ ### **✅ Do**: Check component Props interface first
251
+ ```typescript
252
+ // Understand what's readonly vs writable before testing
253
+ type ComponentProps = {
254
+ readonly sensor: boolean
255
+ writable: string
256
+ }
257
+ ```
258
+
259
+ ### **✅ Do**: Simulate real user interactions for sensors
260
+ ```typescript
261
+ await checkbox.click()
262
+ await input.type('text')
263
+ await page.keyboard.press('Space')
264
+ ```
265
+
266
+ ### **✅ Do**: Test programmatic updates for writable properties
267
+ ```typescript
268
+ await page.evaluate(() => {
269
+ element.writableProperty = 'new value'
270
+ })
271
+ ```
272
+
273
+ ### **✅ Do**: Verify property reactivity
274
+ ```typescript
275
+ // All properties are reactive and trigger updates
276
+ const propertyValue = await page.evaluate(() => element.property)
277
+ expect(propertyValue).toBe('expected')
278
+ ```
279
+
280
+ ### **✅ Do**: Verify DOM synchronization
281
+ ```typescript
282
+ await expect(checkbox).toBeChecked()
283
+ await expect(component).toHaveAttribute('checked')
284
+ ```
285
+
286
+ ## Key Commands
287
+
288
+ ```bash
289
+ # Start test server
290
+ bun run serve:examples
291
+
292
+ # Run all tests
293
+ bunx playwright test
294
+
295
+ # Run specific component tests
296
+ bunx playwright test tests/components/form-checkbox.spec.ts
297
+
298
+ # Run tests on specific browser
299
+ bunx playwright test --project=Chromium
300
+
301
+ # Build examples for testing
302
+ bun run build:examples
303
+ ```
304
+
305
+ ## Summary
306
+
307
+ Le Truc's testing approach ensures components work correctly in real-world scenarios where:
308
+ - User interactions drive sensor property changes
309
+ - Writable properties can be controlled by external JavaScript
310
+ - All properties are reactive and trigger appropriate updates
311
+ - Components maintain their security boundaries for sensitive data
312
+ - The distinction between readonly sensors and writable properties is clearly defined
313
+
314
+ Always check the component's Props interface to understand which properties are readonly sensors (controlled by user interaction) versus writable reactive properties (controllable by external JavaScript).