@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,449 @@
1
+ ---
2
+ title: 'Data Flow'
3
+ emoji: '🔄'
4
+ description: 'Passing state, events, context'
5
+ ---
6
+
7
+ {% hero %}
8
+ # 🔄 Data Flow
9
+
10
+ **Learn how Le Truc components can work together seamlessly.** Start with simple parent-child relationships, then explore advanced patterns like custom events and shared state. Build modular, loosely coupled components that communicate efficiently.
11
+ {% /hero %}
12
+
13
+ {% section %}
14
+ ## Component Coordination
15
+
16
+ Let's consider a **product catalog** where users can add items to a shopping cart. We have **three independent components** that work together:
17
+
18
+ - `ModuleCatalog` **(Parent)**:
19
+ - **Tracks all `SpinButton` components** in its subtree and calculates the total count of items in the shopping cart.
20
+ - **Passes that total** to a `BasicButton`.
21
+ - `BasicButton` **(Child)**:
22
+ - Displays a **badge** in the top-right corner when the `badge` property is set.
23
+ - **Does not track any state** – it simply renders whatever value is passed to it.
24
+ - `FormSpinbutton` **(Child)**:
25
+ - Displays an **Add to Cart** button initially.
26
+ - When an item is added, it transforms into a **stepper** (increment/decrement buttons).
27
+
28
+ Although `BasicButton` and `FormSpinbutton` are completely independent, they need to work together. So `ModuleCatalog` **coordinates the data flow between them**.
29
+
30
+ ### Parent Component: ModuleCatalog
31
+
32
+ The **parent component (`ModuleCatalog`) knows about its children**, meaning it can **read state from and pass state to** them.
33
+
34
+ First, we need to observe the quantities of all `FormSpinbutton` components. For this, we create a `Collection` of all children matching the `form-spinbutton` selector using the `all` function:
35
+
36
+ ```js#module-catalog.js
37
+ defineComponent(
38
+ 'module-catalog',
39
+ {},
40
+ ({ all, first }) => ({
41
+ button: first('basic-button', 'Add a button to go go the Shopping Cart'),
42
+ spinbuttons: all(
43
+ 'form-spinbutton',
44
+ 'Add spinbutton components to calculate sum from.',
45
+ ),
46
+ }),
47
+ ui => {
48
+ // Component setup
49
+ },
50
+ )
51
+ ```
52
+
53
+ In contrast to a static `querySelectorAll()` call, the `Collection` signal returned by `all()` is reactive and updates whenever new elements are added or removed from the DOM.
54
+
55
+ Then, we need to convert the total of all product quantities to a string and pass it on to the `BasicButton` component. In Le Truc we use the `pass()` function to share state with descendant components:
56
+
57
+ ```js#module-catalog.js
58
+ defineComponent(
59
+ 'module-catalog',
60
+ {},
61
+ ({ all, first }) => ({
62
+ button: first('basic-button', 'Add a button to go go the Shopping Cart'),
63
+ spinbuttons: all(
64
+ 'form-spinbutton',
65
+ 'Add spinbutton components to calculate sum from.',
66
+ ),
67
+ }),
68
+ ({ spinbuttons }) => {
69
+ const total = createComputed(() =>
70
+ spinbuttons.get().reduce((sum, item) => sum + item.value, 0),
71
+ )
72
+ return {
73
+ button: pass({
74
+ disabled: () => !total.get(),
75
+ badge: () => (total.get() > 0 ? String(total.get()) : ''),
76
+ }),
77
+ }
78
+ },
79
+ )
80
+ ```
81
+
82
+ Allright, that's it!
83
+
84
+ - Whenever one of the `value` signals of a `<form-spinbutton>` updates, the total in the badge of `<basic-button>` automatically updates.
85
+ - No need for event listeners or manual updates!
86
+
87
+ ### Child Component: BasicButton
88
+
89
+ The `BasicButton` component **displays a badge when needed** – it does not know about any other component nor track state itself. It just exposes a reactive properties `badge` of type `string` and `disabled` of type `boolean` and has effects to react to state changes that updates the DOM subtree.
90
+
91
+ ```js#basic-button.js
92
+ defineComponent(
93
+ 'basic-button',
94
+ {
95
+ disabled: asBoolean(),
96
+ badge: asString(ui => ui.badge?.textContent ?? ''),
97
+ },
98
+ ({ first }) => ({
99
+ button: first('button', 'Add a native button as descendant.'),
100
+ badge: first('span.badge'),
101
+ }),
102
+ () => ({
103
+ button: setProperty('disabled'),
104
+ badge: setText('badge'),
105
+ }),
106
+ )
107
+ ```
108
+
109
+ - Whenever the `disabled` property is updated by a parent component, the button is disabled or enabled.
110
+ - Whenever the `badge` property is updated by a parent component, the badge text updates.
111
+ - If `badge` is an empty string, the badge indicator is hidden (via CSS).
112
+
113
+ ### Child Component: FormSpinbutton
114
+
115
+ The `FormSpinbutton` component reacts to user interactions and exposes a reactive property `value` of type `number`. It updates its own internal DOM subtree, but doesn't know about any other component nor where the value is used.
116
+
117
+ ```js#form-spinbutton.js
118
+ defineComponent(
119
+ 'form-spinbutton',
120
+ {
121
+ value: createSensor(
122
+ read(ui => ui.input.value, asInteger()),
123
+ 'controls',
124
+ {
125
+ change: ({ ui, target, prev }) => {
126
+ if (!(target instanceof HTMLInputElement)) return prev
127
+
128
+ const resetTo = (next: number) => {
129
+ target.value = String(next)
130
+ target.checkValidity()
131
+ return next
132
+ }
133
+
134
+ const next = Number(target.value)
135
+ if (!Number.isInteger(next)) return resetTo(prev)
136
+ const clamped = Math.min(ui.host.max, Math.max(0, next))
137
+ if (next !== clamped) return resetTo(clamped)
138
+ return clamped
139
+ },
140
+ click: ({ target, prev }) =>
141
+ prev +
142
+ (target.classList.contains('decrement')
143
+ ? -1
144
+ : target.classList.contains('increment')
145
+ ? 1
146
+ : 0),
147
+ keydown: ({ ui, event, prev }) => {
148
+ const { key } = event
149
+ if (['ArrowUp', 'ArrowDown', '-', '+'].includes(key)) {
150
+ event.stopPropagation()
151
+ event.preventDefault()
152
+ const next = prev + (key === 'ArrowDown' || key === '-' ? -1 : 1)
153
+ return Math.min(ui.host.max, Math.max(0, next))
154
+ }
155
+ },
156
+ },
157
+ ),
158
+ max: read(ui => ui.input.max, asInteger(10)),
159
+ },
160
+ ({ all, first }) => ({
161
+ controls: all(
162
+ 'button, input:not([disabled])',
163
+ ),
164
+ increment: first(
165
+ 'button.increment',
166
+ 'Add a native button to increment the value',
167
+ ),
168
+ decrement: first(
169
+ 'button.decrement',
170
+ 'Add a native button to decrement the value',
171
+ ),
172
+ input: first('input.value', 'Add a native input to display the value'),
173
+ zero: first('.zero'),
174
+ other: first('.other'),
175
+ }),
176
+ ({ host, increment, zero }) => {
177
+ const nonZero = createComputed(() => host.value !== 0)
178
+ const incrementLabel = increment.ariaLabel || 'Increment'
179
+ const ariaLabel = createComputed(() =>
180
+ nonZero.get() || !zero ? incrementLabel : zero.textContent,
181
+ )
182
+
183
+ return {
184
+ input: [
185
+ show(nonZero),
186
+ setProperty('value'),
187
+ setProperty('max', () => String(host.max)),
188
+ ],
189
+ decrement: show(nonZero),
190
+ increment: [
191
+ setProperty('disabled', () => host.value >= host.max),
192
+ setProperty('ariaLabel', ariaLabel),
193
+ ],
194
+ zero: show(() => !nonZero.get()),
195
+ other: show(nonZero),
196
+ }
197
+ },
198
+ )
199
+ ```
200
+
201
+ - Whenever the user clicks a button or presses a handled key, the value property is updated.
202
+ - The component sets hidden and disabled states of buttons and updates the text of the `input` element.
203
+
204
+ ### Full Example
205
+
206
+ Here's how everything comes together:
207
+
208
+ - Each `FormSpinbutton` tracks its own value.
209
+ - The `ModuleCatalog` sums all quantities and passes the total to `BasicButton`.
210
+ - The `BasicButton` displays the total if it's greater than zero.
211
+
212
+ **No custom events are needed – state flows naturally!**
213
+
214
+ {% demo %}
215
+ <module-catalog>
216
+ <header>
217
+ <p>Shop</p>
218
+ <basic-button disabled>
219
+ <button type="button" disabled>
220
+ <span class="label">🛒 Shopping Cart</span>
221
+ <span class="badge"></span>
222
+ </button>
223
+ </basic-button>
224
+ </header>
225
+ <ul>
226
+ <li>
227
+ <p>Product 1</p>
228
+ <form-spinbutton>
229
+ <button type="button" class="decrement" aria-label="Decrement" hidden>
230
+
231
+ </button>
232
+ <input
233
+ type="number"
234
+ class="value"
235
+ name="amount-product1"
236
+ value="0"
237
+ min="0"
238
+ max="10"
239
+ readonly
240
+ disabled
241
+ hidden
242
+ />
243
+ <button type="button" class="increment" aria-label="Increment">
244
+ <span class="zero">Add to Cart</span>
245
+ <span class="other" hidden>+</span>
246
+ </button>
247
+ </form-spinbutton>
248
+ </li>
249
+ <li>
250
+ <p>Product 2</p>
251
+ <form-spinbutton>
252
+ <button type="button" class="decrement" aria-label="Decrement" hidden>
253
+
254
+ </button>
255
+ <input
256
+ type="number"
257
+ class="value"
258
+ name="amount-product2"
259
+ value="0"
260
+ min="0"
261
+ max="5"
262
+ readonly
263
+ disabled
264
+ hidden
265
+ />
266
+ <button type="button" class="increment" aria-label="Increment">
267
+ <span class="zero">Add to Cart</span>
268
+ <span class="other" hidden>+</span>
269
+ </button>
270
+ </form-spinbutton>
271
+ </li>
272
+ <li>
273
+ <p>Product 3</p>
274
+ <form-spinbutton>
275
+ <button type="button" class="decrement" aria-label="Decrement" hidden>
276
+
277
+ </button>
278
+ <input
279
+ type="number"
280
+ class="value"
281
+ name="amount-product3"
282
+ value="0"
283
+ min="0"
284
+ max="20"
285
+ readonly
286
+ disabled
287
+ hidden
288
+ />
289
+ <button type="button" class="increment" aria-label="Increment">
290
+ <span class="zero">Add to Cart</span>
291
+ <span class="other" hidden>+</span>
292
+ </button>
293
+ </form-spinbutton>
294
+ </li>
295
+ </ul>
296
+ </module-catalog>
297
+ ---
298
+ {% source title="ModuleCatalog source code" src="./examples/module-catalog.html" /%}
299
+ {% source title="BasicButton source code" src="./examples/basic-button.html" /%}
300
+ {% source title="FormSpinbutton source code" src="./examples/form-spinbutton.html" /%}
301
+ {% /demo %}
302
+
303
+ {% /section %}
304
+
305
+ {% section %}
306
+
307
+ ## Providing Context
308
+
309
+ Context allows **parent components to share state** with any descendant components in the DOM tree, **without prop drilling**. This is perfect for application-wide settings like user preferences, theme data, or authentication state.
310
+
311
+ ### Creating Context Keys
312
+
313
+ First, define typed context keys for the values you want to share:
314
+
315
+ ```ts#context-media.ts
316
+ // Define context keys with types
317
+ export const MEDIA_MOTION = 'media-motion' as Context<
318
+ 'media-motion',
319
+ () => 'no-preference' | 'reduce'
320
+ >
321
+ export const MEDIA_THEME = 'media-theme' as Context<
322
+ 'media-theme',
323
+ () => 'light' | 'dark'
324
+ >
325
+ ```
326
+
327
+ ### Provider Component
328
+
329
+ The **provider component** creates the shared state and makes it available to descendants:
330
+
331
+ ```ts#context-media.ts
332
+ export type ContextMediaProps = {
333
+ readonly 'media-motion': 'no-preference' | 'reduce'
334
+ readonly 'media-theme': 'light' | 'dark'
335
+ }
336
+
337
+ declare global {
338
+ interface HTMLElementTagNameMap {
339
+ 'context-media': Component<ContextMediaProps>
340
+ }
341
+ }
342
+
343
+ export default defineComponent<ContextMediaProps>(
344
+ 'context-media',
345
+ {
346
+ [MEDIA_MOTION]: () => {
347
+ const mql = matchMedia('(prefers-reduced-motion: reduce)')
348
+ const motion = createState(mql.matches ? 'reduce' : 'no-preference')
349
+ mql.addEventListener('change', e => {
350
+ motion.set(e.matches ? 'reduce' : 'no-preference')
351
+ })
352
+ return motion
353
+ },
354
+ [MEDIA_THEME]: () => {
355
+ const mql = matchMedia('(prefers-color-scheme: dark)')
356
+ const theme = createState(mql.matches ? 'dark' : 'light')
357
+ mql.addEventListener('change', e => {
358
+ theme.set(e.matches ? 'dark' : 'light')
359
+ })
360
+ return theme
361
+ },
362
+ },
363
+ undefined, // Component has no own descendant elements
364
+ () => ({
365
+ host: provideContexts([MEDIA_MOTION, MEDIA_THEME]),
366
+ }),
367
+ )
368
+ ```
369
+
370
+ ### Usage in HTML
371
+
372
+ The provider component wraps your entire application or a section that needs shared state:
373
+
374
+ ```html#index.html
375
+ <context-media>
376
+ <!-- Arbitrarily nested HTML with one or many context consumers -->
377
+ <main>
378
+ <card-mediaqueries>
379
+ <dl>
380
+ <dt>Motion Preference:</dt>
381
+ <dd class="motion"></dd>
382
+ <dt>Theme Preference:</dt>
383
+ <dd class="theme"></dd>
384
+ </dl>
385
+ </card-mediaqueries>
386
+ </main>
387
+ </context-media>
388
+ ```
389
+
390
+ **Key Benefits:**
391
+
392
+ - **Centralized State**: All global state is managed in one place
393
+ - **Type Safety**: Full TypeScript support with autocomplete
394
+ - **Reactive Updates**: All consumers automatically update when context changes
395
+ - **No Prop Drilling**: Deep components access context directly
396
+
397
+ {% /section %}
398
+
399
+ {% section %}
400
+
401
+ ## Consuming Context
402
+
403
+ **Consumer components** use `requestContext()` to access shared state from ancestor providers. The context is automatically reactive - when the provider updates the context, all consumers update immediately.
404
+
405
+ ### Consumer Component
406
+
407
+ Here's a simple card that displays the current motion and theme preferences:
408
+
409
+ ```js#card-mediaqueries.js
410
+ export default defineComponent(
411
+ 'card-mediaqueries',
412
+ {
413
+ motion: requestContext(MEDIA_MOTION, 'unknown'),
414
+ theme: requestContext(MEDIA_THEME, 'unknown'),
415
+ },
416
+ ({ first }) => ({
417
+ motion: first('.motion'),
418
+ theme: first('.theme'),
419
+ }),
420
+ () => ({
421
+ motion: setText('motion'),
422
+ theme: setText('theme'),
423
+ }),
424
+ )
425
+ ```
426
+
427
+ ### Full Example
428
+
429
+ {% demo %}
430
+ <context-media>
431
+ <card-mediaqueries>
432
+ <dl>
433
+ <dt>Motion Preference:</dt>
434
+ <dd class="motion"></dd>
435
+ <dt>Theme Preference:</dt>
436
+ <dd class="theme"></dd>
437
+ <dt>Device Viewport:</dt>
438
+ <dd class="viewport"></dd>
439
+ <dt>Device Orientation:</dt>
440
+ <dd class="orientation"></dd>
441
+ </dl>
442
+ </card-mediaqueries>
443
+ </context-media>
444
+ ---
445
+ {% source title="ContextMedia source code" src="./examples/context-media.html" /%}
446
+ {% source title="CardMediaqueries source code" src="./examples/card-mediaqueries.html" /%}
447
+ {% /demo %}
448
+
449
+ {% /section %}
@@ -0,0 +1,170 @@
1
+ ---
2
+ title: 'Getting Started'
3
+ emoji: '🚀'
4
+ description: 'Installation, setup, and first steps'
5
+ ---
6
+
7
+ {% hero %}
8
+ # 🚀 Getting Started
9
+
10
+ **Set up Le Truc in minutes – no build tools required**. Or use any package manager and bundler to take advantage of TypeScript support and optimize frontend assets.
11
+ {% /hero %}
12
+
13
+ {% section %}
14
+ ## How to Install Le Truc
15
+
16
+ Le Truc works **without build tools** but also supports **package managers and bundlers** for larger projects. Choose the option that best fits your needs.
17
+
18
+ ### Using a CDN
19
+
20
+ For the easiest setup, include Le Truc via a CDN. This is ideal for **testing or quick projects** where you want lightweight interactivity without additional tooling.
21
+
22
+ ```html#page.html
23
+ <script src="https://cdn.jsdelivr.net/npm/@zeix/le-truc@latest/index.js"></script>
24
+ ```
25
+
26
+ ### Self-Hosting Le Truc
27
+
28
+ For production use, you may want to **self-host Le Truc** to avoid relying on a CDN. You can download the latest version from:
29
+
30
+ [index.js in Github Repository](https://github.com/zeixcom/le-truc/blob/main/index.js)
31
+
32
+ Simply host the file on your server and include it like this:
33
+
34
+ ```html#page.html
35
+ <script src="/path/to/your/hosted/le-truc.js"></script>
36
+ ```
37
+
38
+ **Why self-host?**
39
+
40
+ - You **control updates** and avoid breaking changes from external CDNs.
41
+ - Works for **projects with stricter Content Security Policy rules**.
42
+
43
+ Remember to keep the hosted file updated to use the latest features and bug fixes.
44
+
45
+ ### Installing via Package Managers
46
+
47
+ If you're using a **bundler** like **Vite, Webpack, or Rollup**, install Le Truc via NPM or Bun:
48
+
49
+ {% tabgroup %}
50
+ #### NPM
51
+
52
+ ```sh
53
+ npm install @zeix/le-truc
54
+ ```
55
+
56
+ ---
57
+
58
+ #### Bun
59
+
60
+ ```sh
61
+ bun add @zeix/le-truc
62
+ ```
63
+ {% /tabgroup %}
64
+
65
+ Then import the needed functions in your JavaScript:
66
+
67
+ ```js#main.js
68
+ import { asString, component, on, setText } from '@zeix/le-truc'
69
+ ```
70
+
71
+ {% /section %}
72
+
73
+ {% section %}
74
+
75
+ ## Creating Your First Component
76
+
77
+ Now, let's create an interactive Web Component to verify your setup.
78
+
79
+ **What This Component Does**
80
+
81
+ - Displays `Hello, World!` by default.
82
+ - Updates dynamically when you type into the input field.
83
+
84
+ ### Markup
85
+
86
+ Include the following in your server-rendered HTML:
87
+
88
+ ```html#page.html
89
+ <basic-hello>
90
+ <label>
91
+ Your name<br />
92
+ <input name="name" type="text" autocomplete="given-name" />
93
+ </label>
94
+ <p>Hello, <output>World</output>!</p>
95
+ </basic-hello>
96
+ ```
97
+
98
+ ### Component Definition
99
+
100
+ Save the following inside a `<script type="module">` tag or an external JavaScript file.
101
+
102
+ ```html#page.html
103
+ <script type="module">
104
+ import {
105
+ asString,
106
+ defineComponent,
107
+ on,
108
+ setText,
109
+ } from 'https://cdn.jsdelivr.net/npm/@zeix/le-truc@latest/index.js'
110
+
111
+ defineComponent(
112
+ 'basic-hello',
113
+ {
114
+ name: asString(ui => ui.output.textContent),
115
+ },
116
+ ({ first }) => ({
117
+ input: first('input', 'Needed to enter the name.'),
118
+ output: first('output', 'Needed to display the name.'),
119
+ }),
120
+ ({ host, input }) => {
121
+ const fallback = host.name
122
+ return {
123
+ input: on('input', () => {
124
+ host.name = input.value || fallback
125
+ }),
126
+ output: setText('name'),
127
+ }
128
+ },
129
+ )
130
+ </script>
131
+ ```
132
+
133
+ ### Understanding Your First Component
134
+
135
+ This component demonstrates Le Truc's core concepts:
136
+
137
+ - **Reactive Properties**: `name: asString(...)` creates a reactive property that syncs with the `name` attribute and falls back to the `<output>` content
138
+ - **Effects**: The setup function returns effects that handle user input and update the display text
139
+ - **Element Selection**: `first()` selects descendant element to apply effects to
140
+
141
+ Learn more about these concepts in the [Components](components.html) guide.
142
+
143
+ {% /section %}
144
+
145
+ {% section %}
146
+
147
+ ## Verifying Your Installation
148
+
149
+ If everything is set up correctly, you should see:
150
+
151
+ - A text input field
152
+ - A greeting (`Hello, World!`)
153
+ - The greeting updates as you type
154
+
155
+ {% demo %}
156
+ <basic-hello>
157
+ <label>Your name<br>
158
+ <input name="name" type="text" autocomplete="given-name">
159
+ </label>
160
+ <p>Hello, <output>World</output>!</p>
161
+ </basic-hello>
162
+ {% /demo %}
163
+
164
+ If it's not working:
165
+
166
+ - Check the browser console for errors (missing imports, typos).
167
+ - Ensure your `<script>` tag is set to `type="module"` when using ES modules.
168
+ - If using NPM, confirm Le Truc is installed inside `node_modules/@zeix/le-truc`.
169
+
170
+ {% /section %}