@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,478 @@
1
+ **le-truc**
2
+
3
+ ***
4
+
5
+ # Le Truc
6
+
7
+ Version 0.15.0
8
+
9
+ **Le Truc - the thing for type-safe reactive web components**
10
+
11
+ Le Truc helps you create reusable, interactive web components that work with any backend or static site generator. Build once, use everywhere.
12
+
13
+ Le Truc is a set of functions to build reusable, loosely coupled Web Components with reactive properties. It provides structure through components and simplifies state management and DOM synchronization using signals and effects, leading to more organized and maintainable code without a steep learning curve.
14
+
15
+ Unlike SPA frameworks (React, Vue, Svelte, etc.) Le Truc takes a HTML-first approach, progressively enhancing server-rendered HTML rather than recreating (rendering) it using JavaScript. Le Truc achieves the same result as SPA frameworks with SSR, with a simpler, more efficient approach.
16
+
17
+ ## Quick Start
18
+
19
+ Add interactivity to your HTML in three steps:
20
+
21
+ 1. Start with HTML:
22
+
23
+ ```html
24
+ <basic-hello>
25
+ <label for="name">Your name</label>
26
+ <input id="name" name="name" type="text" autocomplete="given-name" />
27
+ <p>Hello, <output for="name">World</output>!</p>
28
+ </basic-hello>
29
+ ```
30
+
31
+ 2. Define the component:
32
+
33
+ ```js
34
+ import { asString, defineComponent, on, setText } from '@zeix/le-truc'
35
+
36
+ defineComponent(
37
+ 'basic-hello', // 1. Component name
38
+ { name: asString('World') }, // 2. Reactive property
39
+ q => ({ // 3. Find DOM elements
40
+ input: q.first('input'),
41
+ output: q.first('output'),
42
+ }),
43
+ ({ host, input }) => ({ // 4. Define behavior
44
+ input: on('input', () => { host.name = input.value }),
45
+ output: setText('name'),
46
+ }),
47
+ )
48
+ ```
49
+
50
+ 3. Import and watch it work!
51
+
52
+ ## Key Features
53
+
54
+ - 🧱 **HTML Web Components**: Build on standard HTML and enhance it with reusable Web Components. No Virtual DOM – Le Truc works directly with the real DOM.
55
+ - 🚦 **Reactive Properties**: Get and set values like with normal element properties, but they automatically track reads and notify on changes (signals).
56
+ - ⚡️ **Fine-grained Effects**: Pinpoint updates to the parts of the DOM that need updating, avoiding unnecessary re-renders.
57
+ - 🧩 **Function Composition**: Declare component behavior by composing small, reusable functions (parsers and effects).
58
+ - 🛠️ **Customizable**: Le Truc is designed to be easily customizable and extensible. Create your own custom parsers and effects to suit your specific needs.
59
+ - 🌐 **Context Support**: Share global states across components without prop drilling or tightly coupling logic.
60
+ - 🪶 **Tiny footprint**: Minimal core (~8kB gzipped) with tree-shaking support, minimizing JavaScript bundle size.
61
+ - 🛡️ **Type Safety**: Early warnings when types don't match improve code quality and reduce bugs.
62
+
63
+ Le Truc uses [Cause & Effect](https://github.com/zeixcom/cause-effect) internally for state management with signals and glitch-free DOM updates. If wanted, you could fork Le Truc and replace Cause & Effect with a different state management library without changes to the user-facing `createComponent()` API.
64
+
65
+ ## Installation
66
+
67
+ ```bash
68
+ # with npm
69
+ npm install @zeix/le-truc
70
+
71
+ # or with bun
72
+ bun add @zeix/le-truc
73
+ ```
74
+
75
+ ## Documentation
76
+
77
+ The full documentation is still work in progress. The following chapters are already reasonably complete:
78
+
79
+ - [Introduction](https://zeixcom.github.io/le-truc/index.html)
80
+ - [Getting Started](https://zeixcom.github.io/le-truc/getting-started.html)
81
+ - [Components](https://zeixcom.github.io/le-truc/components.html)
82
+ - [Styling](https://zeixcom.github.io/le-truc/styling.html)
83
+ - [Data Flow](https://zeixcom.github.io/le-truc/data-flow.html)
84
+ - [About](https://zeixcom.github.io/le-truc/about.html)
85
+
86
+ ## Basic Usage
87
+
88
+ 1. Start with HTML:
89
+
90
+ ```html
91
+ <basic-counter>
92
+ <button type="button">💐 <span>5</span></button>
93
+ </basic-counter>
94
+ ```
95
+
96
+ 2. Define the component:
97
+
98
+ ```js
99
+ import { asInteger, defineComponent, on, read, setText } from '@zeix/le-truc'
100
+
101
+ export default defineComponent(
102
+ // 1. Component name
103
+ 'basic-counter',
104
+
105
+ // 2. Reactive properties (signals)
106
+ {
107
+ // Count property is read from the DOM (ui.count) and converted to an integer
108
+ count: read(ui => ui.count.textContent, asInteger()),
109
+ },
110
+
111
+ // 3. Find DOM elements
112
+ ({ first }) => ({
113
+ // first() returns the first element matching the selector
114
+ increment: first(
115
+ 'button',
116
+ 'Add a native button element to increment the count.',
117
+ ),
118
+ count: first('span', 'Add a span to display the count.'),
119
+ }),
120
+
121
+ // 4. Define behavior (effects)
122
+ ({ host }) => ({ // host is the component element with reactive properties
123
+ // Add a click event listener to the increment button
124
+ increment: on('click', () => {
125
+ host.count++
126
+ }),
127
+ // Set the text of the count element to the count property whenever it changes
128
+ count: setText('count'),
129
+ }),
130
+ )
131
+ ```
132
+
133
+ Example styles:
134
+
135
+ ```css
136
+ basic-counter {
137
+ & button {
138
+ border: 1px solid var(--color-border);
139
+ border-radius: var(--space-xs);
140
+ background-color: var(--color-secondary);
141
+ padding: var(--space-xs) var(--space-s);
142
+ cursor: pointer;
143
+ color: var(--color-text);
144
+ font-size: var(--font-size-m);
145
+ line-height: var(--line-height-xs);
146
+ transition: background-color var(--transition-short) var(--easing-inout);
147
+
148
+ &:hover {
149
+ background-color: var(--color-secondary-hover);
150
+ }
151
+
152
+ &:active {
153
+ background-color: var(--color-secondary-active);
154
+ }
155
+ }
156
+ }
157
+ ```
158
+
159
+ 3. Import and watch it work!
160
+
161
+ ## Advanced Examples
162
+
163
+ ### Tab Group
164
+
165
+ An example demonstrating how to create a fully accessible tab navigation.
166
+
167
+ Server-rendered markup:
168
+
169
+ ```html
170
+ <module-tabgroup>
171
+ <div role="tablist">
172
+ <button
173
+ type="button"
174
+ role="tab"
175
+ id="trigger1"
176
+ aria-controls="panel1"
177
+ aria-selected="true"
178
+ tabindex="0"
179
+ >
180
+ Tab 1
181
+ </button>
182
+ <button
183
+ type="button"
184
+ role="tab"
185
+ id="trigger2"
186
+ aria-controls="panel2"
187
+ aria-selected="false"
188
+ tabindex="-1"
189
+ >
190
+ Tab 2
191
+ </button>
192
+ <button
193
+ type="button"
194
+ role="tab"
195
+ id="trigger3"
196
+ aria-controls="panel3"
197
+ aria-selected="false"
198
+ tabindex="-1"
199
+ >
200
+ Tab 3
201
+ </button>
202
+ </div>
203
+ <div role="tabpanel" id="panel1" aria-labelledby="trigger1">
204
+ Tab 1 content
205
+ </div>
206
+ <div role="tabpanel" id="panel2" aria-labelledby="trigger2" hidden>
207
+ Tab 2 content
208
+ </div>
209
+ <div role="tabpanel" id="panel3" aria-labelledby="trigger3" hidden>
210
+ Tab 3 content
211
+ </div>
212
+ </module-tabgroup>
213
+ ```
214
+
215
+ Le Truc component:
216
+
217
+ ```js
218
+ import { createSensor, defineComponent, read, setProperty, show } from '@zeix/le-truc'
219
+
220
+ const getAriaControls = element => element.getAttribute('aria-controls') ?? ''
221
+
222
+ const getSelected = (elements, isCurrent, offset = 0) => {
223
+ const tabs = elements.get()
224
+ const currentIndex = tabs.findIndex(isCurrent)
225
+ const newIndex = (currentIndex + offset + tabs.length) % tabs.length
226
+ return getAriaControls(tabs[newIndex])
227
+ }
228
+
229
+ export default defineComponent(
230
+ // 1. Component name
231
+ 'module-tabgroup',
232
+
233
+ // 2. Reactive properties (signals)
234
+ {
235
+ // Sensors are read-only signals that update on user interaction only (events)
236
+ selected: createSensor(
237
+ // Initial value from aria-selected attribute
238
+ read(ui => getSelected(ui.tabs, tab => tab.ariaSelected === 'true'), ''),
239
+ // Target element(s) key
240
+ 'tabs',
241
+ // Event handlers return a value to update the signal
242
+ {
243
+ click: ({ target }) => getAriaControls(target),
244
+ keyup: ({ event, ui, target }) => {
245
+ const key = event.key
246
+ if (
247
+ [
248
+ 'ArrowLeft',
249
+ 'ArrowRight',
250
+ 'ArrowUp',
251
+ 'ArrowDown',
252
+ 'Home',
253
+ 'End',
254
+ ].includes(key)
255
+ ) {
256
+ event.preventDefault()
257
+ event.stopPropagation()
258
+ const tabs = ui.tabs.get()
259
+ const next =
260
+ key === 'Home'
261
+ ? getAriaControls(tabs[0])
262
+ : key === 'End'
263
+ ? getAriaControls(tabs[tabs.length - 1])
264
+ : getSelected(
265
+ ui.tabs,
266
+ tab => tab === target,
267
+ key === 'ArrowLeft' || key === 'ArrowUp' ? -1 : 1,
268
+ )
269
+ tabs.filter(tab => getAriaControls(tab) === next)[0].focus()
270
+ return next
271
+ }
272
+ },
273
+ },
274
+ ),
275
+ },
276
+
277
+ // 3. Find DOM elements
278
+ ({ all }) => ({
279
+ // all() returns a Collection signal that holds all elements matching the selector,
280
+ // dynamically updating when the DOM changes
281
+ tabs: all(
282
+ 'button[role="tab"]',
283
+ 'At least 2 tabs as children of a <[role="tablist"]> element are needed. Each tab must reference a unique id of a <[role="tabpanel"]> element.',
284
+ ),
285
+ panels: all(
286
+ '[role="tabpanel"]',
287
+ 'At least 2 tabpanels are needed. Each tabpanel must have a unique id.',
288
+ ),
289
+ }),
290
+
291
+ // 4. Define behavior (effects)
292
+ ({ host }) => {
293
+ // Extracted function to check if a tab is the current selected tab
294
+ const isCurrentTab = tab => host.selected === getAriaControls(tab)
295
+
296
+ return {
297
+ // Set properties on tabs based on their selection status
298
+ tabs: [
299
+ setProperty('ariaSelected', target => String(isCurrentTab(target))),
300
+ setProperty('tabIndex', target => (isCurrentTab(target) ? 0 : -1)),
301
+ ],
302
+ // Toggle visibility of panels based on the selected tab
303
+ panels: show(target => host.selected === target.id),
304
+ }
305
+ },
306
+ )
307
+ ```
308
+
309
+ Example styles:
310
+
311
+ ```css
312
+ module-tabgroup {
313
+ display: block;
314
+ margin-bottom: var(--space-l);
315
+
316
+ > [role="tablist"] {
317
+ display: flex;
318
+ border-bottom: 1px solid var(--color-border);
319
+ padding: 0;
320
+ margin-bottom: 0;
321
+
322
+ > [role="tab"] {
323
+ border: 0;
324
+ border-top: 2px solid transparent;
325
+ border-bottom-width: 0;
326
+ border-radius: var(--space-xs) var(--space-xs) 0 0;
327
+ font-family: var(--font-family-sans);
328
+ font-size: var(--font-size-s);
329
+ font-weight: var(--font-weight-bold);
330
+ padding: var(--space-s) var(--space-m);
331
+ color: var(--color-text-soft);
332
+ background-color: var(--color-secondary);
333
+ cursor: pointer;
334
+ transition: all var(--transition-short) var(--easing-inout);
335
+
336
+ &:hover,
337
+ &:focus {
338
+ color: var(--color-text);
339
+ background-color: var(--color-secondary-hover);
340
+ }
341
+
342
+ &:focus {
343
+ z-index: 1;
344
+ }
345
+
346
+ &:active {
347
+ color: var(--color-text);
348
+ background-color: var(--color-secondary-active);
349
+ }
350
+
351
+ &[aria-selected="true"] {
352
+ color: var(--color-primary-active);
353
+ border-top: 3px solid var(--color-primary);
354
+ background-color: var(--color-background);
355
+ margin-bottom: -1px;
356
+ }
357
+ }
358
+ }
359
+
360
+ > [role="tabpanel"] {
361
+ font-family: sans-serif;
362
+ font-size: var(--font-size-m);
363
+ background: var(--color-background);
364
+ margin-block: var(--space-l);
365
+ }
366
+ }
367
+ ```
368
+
369
+ ### Lazy Load
370
+
371
+ An example demonstrating how to use a custom attribute parser (sanitize an URL) and a signal producer (async fetch) to implement lazy loading.
372
+
373
+ ```html
374
+ <module-lazyload src="/module-lazyload/snippet.html">
375
+ <card-callout>
376
+ <p class="loading" role="status">Loading...</p>
377
+ <p class="error" role="alert" aria-live="assertive" hidden></p>
378
+ </card-callout>
379
+ <div class="content" hidden></div>
380
+ </module-lazyload>
381
+ ```
382
+
383
+ Le Truc component:
384
+
385
+ ```js
386
+ import {
387
+ asString,
388
+ type Component,
389
+ createComputed,
390
+ dangerouslySetInnerHTML,
391
+ defineComponent,
392
+ setText,
393
+ show,
394
+ toggleClass,
395
+ } from '@zeix/le-truc'
396
+ import { isRecursiveURL, isValidURL } from '../_common/fetch'
397
+
398
+ export default defineComponent(
399
+ // 1. Component name
400
+ 'module-lazyload',
401
+
402
+ // 2. Reactive properties (signals)
403
+ {
404
+ src: asString(),
405
+ },
406
+
407
+ // 3. Find DOM elements
408
+ ({ first }) => ({
409
+ callout: first(
410
+ 'card-callout',
411
+ 'Needed to display loading state and error messages.',
412
+ ),
413
+ loading: first('.loading', 'Needed to display loading state.'),
414
+ error: first('.error', 'Needed to display error messages.'),
415
+ content: first('.content', 'Needed to display content.'),
416
+ }),
417
+
418
+ // 4. Define behavior (effects)
419
+ ui => {
420
+ const { host } = ui
421
+
422
+ // Private async computed signal to fetch content from the provided URL
423
+ const result = createComputed(
424
+ async (_prev, abort) => {
425
+ const url = host.src
426
+ const error = !url
427
+ ? 'No URL provided'
428
+ : !isValidURL(url)
429
+ ? 'Invalid URL'
430
+ : isRecursiveURL(url, host)
431
+ ? 'Recursive URL detected'
432
+ : ''
433
+ if (error) return { ok: false, value: '', error, pending: false }
434
+
435
+ try {
436
+ const response = await fetch(url, abort)
437
+ if (!response.ok) throw new Error(`HTTP error: ${response.statusText}`)
438
+ const content = await response.text()
439
+ return { ok: true, value: content, error: '', pending: false }
440
+ } catch (error) {
441
+ return {
442
+ ok: false,
443
+ value: '',
444
+ error: `Failed to fetch content for "${url}": ${String(error)}`,
445
+ pending: false,
446
+ }
447
+ }
448
+ },
449
+ // Initial value of the signal before the Promise is resolved
450
+ { ok: false, value: '', error: '', pending: true },
451
+ )
452
+
453
+ // Extracted function to check if an error occurred
454
+ const hasError = () => !!result.get().error
455
+
456
+ return {
457
+ callout: [show(() => !result.get().ok), toggleClass('danger', hasError)],
458
+ loading: show(() => !!result.get().pending),
459
+ error: [show(hasError), setText(() => result.get().error ?? '')],
460
+ content: [
461
+ show(() => result.get().ok),
462
+ // Set inner HTML to the fetched content (use only for trusted sources)
463
+ dangerouslySetInnerHTML(() => result.get().value ?? '', {
464
+ allowScripts: host.hasAttribute('allow-scripts'),
465
+ }),
466
+ ],
467
+ }
468
+ },
469
+ )
470
+ ```
471
+
472
+ ## Contributing & License
473
+
474
+ Feel free to contribute, report issues, or suggest improvements.
475
+
476
+ License: [MIT](_media/LICENSE)
477
+
478
+ (c) 2025 [Zeix AG](https://zeix.com)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 - 2025 Zeix AG
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.