@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.
- package/.ai-context.md +234 -0
- package/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc +111 -0
- package/.editorconfig +12 -0
- package/.github/copilot-instructions.md +62 -0
- package/.github/workflows/codeql.yml +108 -0
- package/.github/workflows/static.yml +43 -0
- package/.prettierrc +17 -0
- package/CLAUDE.md +215 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +160 -0
- package/LICENSE +21 -0
- package/README.md +474 -0
- package/biome.json +295 -0
- package/bun.lock +239 -0
- package/docs/about.html +105 -0
- package/docs/assets/main.css +1 -0
- package/docs/assets/main.js +10 -0
- package/docs/assets/main.js.map +66 -0
- package/docs/components.html +293 -0
- package/docs/data-flow.html +308 -0
- package/docs/examples/basic-button.html +367 -0
- package/docs/examples/basic-counter.html +188 -0
- package/docs/examples/basic-hello.html +138 -0
- package/docs/examples/basic-number.html +271 -0
- package/docs/examples/basic-pluralize.html +214 -0
- package/docs/examples/card-callout.html +152 -0
- package/docs/examples/card-mediaqueries.html +138 -0
- package/docs/examples/context-media.html +198 -0
- package/docs/examples/empty.html +37 -0
- package/docs/examples/form-checkbox.html +233 -0
- package/docs/examples/form-combobox.html +420 -0
- package/docs/examples/form-listbox.html +434 -0
- package/docs/examples/form-radiogroup.html +296 -0
- package/docs/examples/form-spinbutton.html +402 -0
- package/docs/examples/form-textbox.html +361 -0
- package/docs/examples/layout.html +67 -0
- package/docs/examples/module-carousel.html +552 -0
- package/docs/examples/module-catalog.html +241 -0
- package/docs/examples/module-codeblock.html +270 -0
- package/docs/examples/module-dialog.html +343 -0
- package/docs/examples/module-lazyload.html +289 -0
- package/docs/examples/module-list.html +197 -0
- package/docs/examples/module-pagination.html +283 -0
- package/docs/examples/module-scrollarea.html +447 -0
- package/docs/examples/module-tabgroup.html +526 -0
- package/docs/examples/module-todo.html +367 -0
- package/docs/examples/module-with-type.html +63 -0
- package/docs/examples/nested-components.html +88 -0
- package/docs/examples/recursive.html +56 -0
- package/docs/examples/simple-text.html +39 -0
- package/docs/examples/snippet.html +93 -0
- package/docs/examples/with-styles.html +75 -0
- package/docs/getting-started.html +143 -0
- package/docs/index.html +112 -0
- package/docs/sitemap.xml +28 -0
- package/docs/styling.html +160 -0
- package/docs/sw.js +112 -0
- package/docs-src/api/README.md +478 -0
- package/docs-src/api/_media/LICENSE +21 -0
- package/docs-src/api/classes/CircularDependencyError.md +299 -0
- package/docs-src/api/classes/CircularMutationError.md +301 -0
- package/docs-src/api/classes/ContextRequestEvent.md +590 -0
- package/docs-src/api/classes/DependencyTimeoutError.md +301 -0
- package/docs-src/api/classes/InvalidCallbackError.md +303 -0
- package/docs-src/api/classes/InvalidComponentNameError.md +295 -0
- package/docs-src/api/classes/InvalidCustomElementError.md +301 -0
- package/docs-src/api/classes/InvalidEffectsError.md +301 -0
- package/docs-src/api/classes/InvalidPropertyNameError.md +307 -0
- package/docs-src/api/classes/InvalidReactivesError.md +307 -0
- package/docs-src/api/classes/InvalidSignalValueError.md +303 -0
- package/docs-src/api/classes/MissingElementError.md +307 -0
- package/docs-src/api/classes/NullishSignalValueError.md +299 -0
- package/docs-src/api/classes/StoreKeyExistsError.md +303 -0
- package/docs-src/api/classes/StoreKeyRangeError.md +299 -0
- package/docs-src/api/classes/StoreKeyReadonlyError.md +303 -0
- package/docs-src/api/functions/asBoolean.md +21 -0
- package/docs-src/api/functions/asEnum.md +31 -0
- package/docs-src/api/functions/asInteger.md +39 -0
- package/docs-src/api/functions/asJSON.md +49 -0
- package/docs-src/api/functions/asNumber.md +37 -0
- package/docs-src/api/functions/asString.md +37 -0
- package/docs-src/api/functions/createCollection.md +83 -0
- package/docs-src/api/functions/createSensor.md +71 -0
- package/docs-src/api/functions/dangerouslySetInnerHTML.md +48 -0
- package/docs-src/api/functions/defineComponent.md +65 -0
- package/docs-src/api/functions/isCollection.md +37 -0
- package/docs-src/api/functions/isParser.md +41 -0
- package/docs-src/api/functions/match.md +47 -0
- package/docs-src/api/functions/on.md +58 -0
- package/docs-src/api/functions/pass.md +53 -0
- package/docs-src/api/functions/provideContexts.md +47 -0
- package/docs-src/api/functions/read.md +47 -0
- package/docs-src/api/functions/requestContext.md +51 -0
- package/docs-src/api/functions/resolve.md +40 -0
- package/docs-src/api/functions/runEffects.md +51 -0
- package/docs-src/api/functions/runElementEffects.md +57 -0
- package/docs-src/api/functions/schedule.md +33 -0
- package/docs-src/api/functions/setAttribute.md +48 -0
- package/docs-src/api/functions/setProperty.md +52 -0
- package/docs-src/api/functions/setStyle.md +48 -0
- package/docs-src/api/functions/setText.md +42 -0
- package/docs-src/api/functions/show.md +42 -0
- package/docs-src/api/functions/toSignal.md +37 -0
- package/docs-src/api/functions/toggleAttribute.md +48 -0
- package/docs-src/api/functions/toggleClass.md +48 -0
- package/docs-src/api/functions/updateElement.md +53 -0
- package/docs-src/api/globals.md +131 -0
- package/docs-src/api/type-aliases/Cleanup.md +27 -0
- package/docs-src/api/type-aliases/Collection.md +91 -0
- package/docs-src/api/type-aliases/CollectionListener.md +27 -0
- package/docs-src/api/type-aliases/Component.md +17 -0
- package/docs-src/api/type-aliases/ComponentProp.md +11 -0
- package/docs-src/api/type-aliases/ComponentProps.md +11 -0
- package/docs-src/api/type-aliases/ComponentSetup.md +31 -0
- package/docs-src/api/type-aliases/ComponentUI.md +27 -0
- package/docs-src/api/type-aliases/Computed.md +49 -0
- package/docs-src/api/type-aliases/ComputedCallback.md +29 -0
- package/docs-src/api/type-aliases/Context.md +33 -0
- package/docs-src/api/type-aliases/ContextType.md +19 -0
- package/docs-src/api/type-aliases/DangerouslySetInnerHTMLOptions.md +27 -0
- package/docs-src/api/type-aliases/DiffResult.md +61 -0
- package/docs-src/api/type-aliases/Effect.md +35 -0
- package/docs-src/api/type-aliases/EffectCallback.md +23 -0
- package/docs-src/api/type-aliases/Effects.md +21 -0
- package/docs-src/api/type-aliases/ElementEffects.md +21 -0
- package/docs-src/api/type-aliases/ElementFromKey.md +21 -0
- package/docs-src/api/type-aliases/ElementQueries.md +27 -0
- package/docs-src/api/type-aliases/ElementUpdater.md +131 -0
- package/docs-src/api/type-aliases/EventHandler.md +31 -0
- package/docs-src/api/type-aliases/EventType.md +17 -0
- package/docs-src/api/type-aliases/Fallback.md +21 -0
- package/docs-src/api/type-aliases/Initializers.md +21 -0
- package/docs-src/api/type-aliases/LooseReader.md +31 -0
- package/docs-src/api/type-aliases/MatchHandlers.md +77 -0
- package/docs-src/api/type-aliases/MaybeCleanup.md +23 -0
- package/docs-src/api/type-aliases/MaybeSignal.md +17 -0
- package/docs-src/api/type-aliases/Parser.md +39 -0
- package/docs-src/api/type-aliases/ParserOrFallback.md +21 -0
- package/docs-src/api/type-aliases/PassedProp.md +25 -0
- package/docs-src/api/type-aliases/PassedProps.md +21 -0
- package/docs-src/api/type-aliases/Reactive.md +25 -0
- package/docs-src/api/type-aliases/Reader.md +31 -0
- package/docs-src/api/type-aliases/ReservedWords.md +11 -0
- package/docs-src/api/type-aliases/ResolveResult.md +29 -0
- package/docs-src/api/type-aliases/SensorEvents.md +25 -0
- package/docs-src/api/type-aliases/Signal.md +41 -0
- package/docs-src/api/type-aliases/State.md +85 -0
- package/docs-src/api/type-aliases/Store.md +29 -0
- package/docs-src/api/type-aliases/UI.md +11 -0
- package/docs-src/api/type-aliases/UnknownContext.md +13 -0
- package/docs-src/api/variables/CONTEXT_REQUEST.md +11 -0
- package/docs-src/api/variables/UNSET.md +23 -0
- package/docs-src/api/variables/batch.md +25 -0
- package/docs-src/api/variables/createComputed.md +41 -0
- package/docs-src/api/variables/createEffect.md +35 -0
- package/docs-src/api/variables/createState.md +37 -0
- package/docs-src/api/variables/createStore.md +42 -0
- package/docs-src/api/variables/diff.md +43 -0
- package/docs-src/api/variables/isAbortError.md +33 -0
- package/docs-src/api/variables/isAsyncFunction.md +39 -0
- package/docs-src/api/variables/isComputed.md +37 -0
- package/docs-src/api/variables/isEqual.md +49 -0
- package/docs-src/api/variables/isFunction.md +39 -0
- package/docs-src/api/variables/isMutableSignal.md +37 -0
- package/docs-src/api/variables/isNumber.md +33 -0
- package/docs-src/api/variables/isRecord.md +39 -0
- package/docs-src/api/variables/isRecordOrArray.md +39 -0
- package/docs-src/api/variables/isSignal.md +37 -0
- package/docs-src/api/variables/isState.md +37 -0
- package/docs-src/api/variables/isStore.md +37 -0
- package/docs-src/api/variables/isString.md +33 -0
- package/docs-src/api/variables/isSymbol.md +33 -0
- package/docs-src/api/variables/toError.md +33 -0
- package/docs-src/api/variables/valueString.md +33 -0
- package/docs-src/includes/menu.html +44 -0
- package/docs-src/pages/about.md +89 -0
- package/docs-src/pages/components.md +437 -0
- package/docs-src/pages/data-flow.md +449 -0
- package/docs-src/pages/getting-started.md +170 -0
- package/docs-src/pages/index.md +98 -0
- package/docs-src/pages/styling.md +165 -0
- package/eslint.config.js +64 -0
- package/examples/_common/clear.ts +49 -0
- package/examples/_common/fetch.ts +160 -0
- package/examples/_common/focus.ts +45 -0
- package/examples/_common/highlight.ts +5 -0
- package/examples/_global.css +463 -0
- package/examples/basic-button/basic-button.css +176 -0
- package/examples/basic-button/basic-button.html +46 -0
- package/examples/basic-button/basic-button.spec.ts +160 -0
- package/examples/basic-button/basic-button.ts +45 -0
- package/examples/basic-button/copyToClipboard.ts +37 -0
- package/examples/basic-counter/basic-counter.css +21 -0
- package/examples/basic-counter/basic-counter.html +24 -0
- package/examples/basic-counter/basic-counter.spec.ts +85 -0
- package/examples/basic-counter/basic-counter.ts +43 -0
- package/examples/basic-hello/basic-hello.html +34 -0
- package/examples/basic-hello/basic-hello.spec.ts +110 -0
- package/examples/basic-hello/basic-hello.ts +36 -0
- package/examples/basic-number/basic-number.html +79 -0
- package/examples/basic-number/basic-number.spec.ts +175 -0
- package/examples/basic-number/basic-number.ts +124 -0
- package/examples/basic-pluralize/basic-pluralize.html +64 -0
- package/examples/basic-pluralize/basic-pluralize.spec.ts +258 -0
- package/examples/basic-pluralize/basic-pluralize.ts +82 -0
- package/examples/card-callout/card-callout.css +79 -0
- package/examples/card-callout/card-callout.html +5 -0
- package/examples/card-mediaqueries/card-mediaqueries.html +29 -0
- package/examples/card-mediaqueries/card-mediaqueries.spec.ts +300 -0
- package/examples/card-mediaqueries/card-mediaqueries.ts +41 -0
- package/examples/context-media/context-media.html +3 -0
- package/examples/context-media/context-media.ts +127 -0
- package/examples/form-checkbox/form-checkbox.css +70 -0
- package/examples/form-checkbox/form-checkbox.html +13 -0
- package/examples/form-checkbox/form-checkbox.spec.ts +357 -0
- package/examples/form-checkbox/form-checkbox.ts +50 -0
- package/examples/form-checkbox/vanilla-checkbox.ts +101 -0
- package/examples/form-combobox/form-combobox.css +118 -0
- package/examples/form-combobox/form-combobox.html +74 -0
- package/examples/form-combobox/form-combobox.spec.ts +977 -0
- package/examples/form-combobox/form-combobox.ts +128 -0
- package/examples/form-listbox/form-listbox.css +71 -0
- package/examples/form-listbox/form-listbox.html +67 -0
- package/examples/form-listbox/form-listbox.spec.ts +1050 -0
- package/examples/form-listbox/form-listbox.ts +196 -0
- package/examples/form-listbox/mocks/timezones.json +495 -0
- package/examples/form-radiogroup/form-radiogroup.css +87 -0
- package/examples/form-radiogroup/form-radiogroup.html +51 -0
- package/examples/form-radiogroup/form-radiogroup.spec.ts +515 -0
- package/examples/form-radiogroup/form-radiogroup.ts +58 -0
- package/examples/form-spinbutton/form-spinbutton.css +95 -0
- package/examples/form-spinbutton/form-spinbutton.html +96 -0
- package/examples/form-spinbutton/form-spinbutton.spec.ts +688 -0
- package/examples/form-spinbutton/form-spinbutton.ts +111 -0
- package/examples/form-textbox/form-textbox.css +104 -0
- package/examples/form-textbox/form-textbox.html +53 -0
- package/examples/form-textbox/form-textbox.spec.ts +542 -0
- package/examples/form-textbox/form-textbox.ts +104 -0
- package/examples/main.css +22 -0
- package/examples/main.ts +23 -0
- package/examples/module-carousel/module-carousel.css +113 -0
- package/examples/module-carousel/module-carousel.html +208 -0
- package/examples/module-carousel/module-carousel.spec.ts +523 -0
- package/examples/module-carousel/module-carousel.ts +131 -0
- package/examples/module-catalog/module-catalog.css +22 -0
- package/examples/module-catalog/module-catalog.html +82 -0
- package/examples/module-catalog/module-catalog.spec.ts +396 -0
- package/examples/module-catalog/module-catalog.ts +37 -0
- package/examples/module-codeblock/module-codeblock.css +95 -0
- package/examples/module-codeblock/module-codeblock.html +28 -0
- package/examples/module-codeblock/module-codeblock.ts +47 -0
- package/examples/module-demo/module-demo.css +13 -0
- package/examples/module-dialog/module-dialog.css +96 -0
- package/examples/module-dialog/module-dialog.html +66 -0
- package/examples/module-dialog/module-dialog.spec.ts +557 -0
- package/examples/module-dialog/module-dialog.ts +81 -0
- package/examples/module-lazyload/mocks/empty.html +1 -0
- package/examples/module-lazyload/mocks/module-with-type.html +27 -0
- package/examples/module-lazyload/mocks/nested-components.html +52 -0
- package/examples/module-lazyload/mocks/recursive.html +20 -0
- package/examples/module-lazyload/mocks/simple-text.html +3 -0
- package/examples/module-lazyload/mocks/snippet.html +57 -0
- package/examples/module-lazyload/mocks/with-styles.html +39 -0
- package/examples/module-lazyload/module-lazyload.html +132 -0
- package/examples/module-lazyload/module-lazyload.spec.ts +734 -0
- package/examples/module-lazyload/module-lazyload.ts +89 -0
- package/examples/module-list/module-list.html +30 -0
- package/examples/module-list/module-list.spec.ts +592 -0
- package/examples/module-list/module-list.ts +99 -0
- package/examples/module-pagination/module-pagination.css +79 -0
- package/examples/module-pagination/module-pagination.html +16 -0
- package/examples/module-pagination/module-pagination.spec.ts +701 -0
- package/examples/module-pagination/module-pagination.ts +88 -0
- package/examples/module-scrollarea/module-scrollarea.css +77 -0
- package/examples/module-scrollarea/module-scrollarea.html +189 -0
- package/examples/module-scrollarea/module-scrollarea.spec.ts +445 -0
- package/examples/module-scrollarea/module-scrollarea.ts +81 -0
- package/examples/module-tabgroup/module-tabgroup.css +55 -0
- package/examples/module-tabgroup/module-tabgroup.html +269 -0
- package/examples/module-tabgroup/module-tabgroup.spec.ts +631 -0
- package/examples/module-tabgroup/module-tabgroup.ts +102 -0
- package/examples/module-toc/module-toc.css +34 -0
- package/examples/module-todo/module-todo.css +84 -0
- package/examples/module-todo/module-todo.html +92 -0
- package/examples/module-todo/module-todo.spec.ts +528 -0
- package/examples/module-todo/module-todo.ts +91 -0
- package/examples/section-hero/section-hero.css +37 -0
- package/examples/section-menu/section-menu.css +81 -0
- package/examples/server.ts +95 -0
- package/examples/test-setup.md +314 -0
- package/index.dev.js +1688 -0
- package/index.dev.ts +127 -0
- package/index.js +3 -0
- package/index.js.map +42 -0
- package/index.ts +127 -0
- package/package.json +64 -0
- package/playwright.config.ts +31 -0
- package/server/BUILD_SYSTEM.md +428 -0
- package/server/SERVER.md +286 -0
- package/server/build.ts +91 -0
- package/server/config.ts +130 -0
- package/server/effects/api.ts +28 -0
- package/server/effects/css.ts +31 -0
- package/server/effects/examples.ts +109 -0
- package/server/effects/js.ts +32 -0
- package/server/effects/menu.ts +34 -0
- package/server/effects/pages.ts +178 -0
- package/server/effects/service-worker.ts +57 -0
- package/server/effects/sitemap.ts +27 -0
- package/server/file-signals.ts +361 -0
- package/server/file-watcher.ts +77 -0
- package/server/io.ts +174 -0
- package/server/layout-engine.ts +470 -0
- package/server/layout-utils.ts +615 -0
- package/server/layouts/api.html +76 -0
- package/server/layouts/base.html +37 -0
- package/server/layouts/blog.html +115 -0
- package/server/layouts/example.html +104 -0
- package/server/layouts/overview.html +165 -0
- package/server/layouts/page.html +36 -0
- package/server/layouts/test.html +24 -0
- package/server/markdoc-helpers.ts +217 -0
- package/server/markdoc.config.ts +29 -0
- package/server/schema/callout.markdoc.ts +17 -0
- package/server/schema/carousel.markdoc.ts +118 -0
- package/server/schema/demo.markdoc.ts +74 -0
- package/server/schema/fence.markdoc.ts +84 -0
- package/server/schema/heading.markdoc.ts +23 -0
- package/server/schema/hero.markdoc.ts +59 -0
- package/server/schema/section.markdoc.ts +10 -0
- package/server/schema/slide.markdoc.ts +17 -0
- package/server/schema/source.markdoc.ts +53 -0
- package/server/schema/tabgroup.markdoc.ts +102 -0
- package/server/serve.ts +635 -0
- package/server/templates/README.md +352 -0
- package/server/templates/constants.ts +236 -0
- package/server/templates/fragments.ts +159 -0
- package/server/templates/hmr.ts +269 -0
- package/server/templates/menu.ts +33 -0
- package/server/templates/performance-hints.ts +94 -0
- package/server/templates/service-worker.ts +403 -0
- package/server/templates/sitemap.ts +57 -0
- package/server/templates/toc.ts +41 -0
- package/server/templates/utils.ts +378 -0
- package/src/component.ts +215 -0
- package/src/context.ts +156 -0
- package/src/effects/attribute.ts +82 -0
- package/src/effects/class.ts +28 -0
- package/src/effects/event.ts +67 -0
- package/src/effects/html.ts +60 -0
- package/src/effects/method.ts +57 -0
- package/src/effects/pass.ts +103 -0
- package/src/effects/property.ts +57 -0
- package/src/effects/style.ts +34 -0
- package/src/effects/text.ts +28 -0
- package/src/effects.ts +412 -0
- package/src/errors.ts +160 -0
- package/src/parsers/boolean.ts +14 -0
- package/src/parsers/json.ts +33 -0
- package/src/parsers/number.ts +55 -0
- package/src/parsers/string.ts +32 -0
- package/src/parsers.ts +90 -0
- package/src/scheduler.ts +47 -0
- package/src/signals/collection.ts +253 -0
- package/src/signals/sensor.ts +131 -0
- package/src/ui.ts +236 -0
- package/src/util.ts +187 -0
- package/tsconfig.json +34 -0
- package/types/examples/basic-button/basic-button.d.ts +16 -0
- package/types/examples/basic-hello/basic-hello.d.ts +18 -0
- package/types/index.d.ts +27 -0
- package/types/index.dev.d.ts +27 -0
- package/types/src/collection.d.ts +27 -0
- package/types/src/component.d.ts +32 -0
- package/types/src/context.d.ts +85 -0
- package/types/src/effects/attribute.d.ts +23 -0
- package/types/src/effects/callMethod.d.ts +23 -0
- package/types/src/effects/class.d.ts +13 -0
- package/types/src/effects/dangerouslySetInnerHTML.d.ts +18 -0
- package/types/src/effects/event.d.ts +18 -0
- package/types/src/effects/html.d.ts +17 -0
- package/types/src/effects/method.d.ts +22 -0
- package/types/src/effects/pass.d.ts +18 -0
- package/types/src/effects/property.d.ts +22 -0
- package/types/src/effects/setAttribute.d.ts +24 -0
- package/types/src/effects/setProperty.d.ts +23 -0
- package/types/src/effects/setStyle.d.ts +14 -0
- package/types/src/effects/setText.d.ts +13 -0
- package/types/src/effects/style.d.ts +13 -0
- package/types/src/effects/text.d.ts +12 -0
- package/types/src/effects/toggleClass.d.ts +14 -0
- package/types/src/effects.d.ts +153 -0
- package/types/src/errors.d.ts +99 -0
- package/types/src/events.d.ts +27 -0
- package/types/src/extractors.d.ts +23 -0
- package/types/src/parsers/boolean.d.ts +10 -0
- package/types/src/parsers/json.d.ts +13 -0
- package/types/src/parsers/number.d.ts +21 -0
- package/types/src/parsers/string.d.ts +19 -0
- package/types/src/parsers.d.ts +41 -0
- package/types/src/scheduler.d.ts +11 -0
- package/types/src/sensor.d.ts +27 -0
- package/types/src/signals/collection.d.ts +32 -0
- package/types/src/signals/sensor.d.ts +27 -0
- package/types/src/ui.d.ts +37 -0
- package/types/src/util.d.ts +65 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[**le-truc**](../README.md)
|
|
2
|
+
|
|
3
|
+
***
|
|
4
|
+
|
|
5
|
+
[le-truc](../globals.md) / toError
|
|
6
|
+
|
|
7
|
+
# Variable: toError()
|
|
8
|
+
|
|
9
|
+
> `const` **toError**: (`reason`) => `Error`
|
|
10
|
+
|
|
11
|
+
Defined in: node\_modules/@zeix/cause-effect/types/src/util.d.ts:12
|
|
12
|
+
|
|
13
|
+
## Parameters
|
|
14
|
+
|
|
15
|
+
### reason
|
|
16
|
+
|
|
17
|
+
`unknown`
|
|
18
|
+
|
|
19
|
+
## Returns
|
|
20
|
+
|
|
21
|
+
`Error`
|
|
22
|
+
|
|
23
|
+
## Name
|
|
24
|
+
|
|
25
|
+
Le Truc
|
|
26
|
+
|
|
27
|
+
## Version
|
|
28
|
+
|
|
29
|
+
0.15.0
|
|
30
|
+
|
|
31
|
+
## Author
|
|
32
|
+
|
|
33
|
+
Esther Brunner
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[**le-truc**](../README.md)
|
|
2
|
+
|
|
3
|
+
***
|
|
4
|
+
|
|
5
|
+
[le-truc](../globals.md) / valueString
|
|
6
|
+
|
|
7
|
+
# Variable: valueString()
|
|
8
|
+
|
|
9
|
+
> `const` **valueString**: (`value`) => `string`
|
|
10
|
+
|
|
11
|
+
Defined in: node\_modules/@zeix/cause-effect/types/src/util.d.ts:15
|
|
12
|
+
|
|
13
|
+
## Parameters
|
|
14
|
+
|
|
15
|
+
### value
|
|
16
|
+
|
|
17
|
+
`unknown`
|
|
18
|
+
|
|
19
|
+
## Returns
|
|
20
|
+
|
|
21
|
+
`string`
|
|
22
|
+
|
|
23
|
+
## Name
|
|
24
|
+
|
|
25
|
+
Le Truc
|
|
26
|
+
|
|
27
|
+
## Version
|
|
28
|
+
|
|
29
|
+
0.15.0
|
|
30
|
+
|
|
31
|
+
## Author
|
|
32
|
+
|
|
33
|
+
Esther Brunner
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<section-menu>
|
|
2
|
+
<nav>
|
|
3
|
+
<h2 class="visually-hidden">Main Menu</h2>
|
|
4
|
+
<ol>
|
|
5
|
+
<li>
|
|
6
|
+
<a href="index.html">
|
|
7
|
+
<span class="icon">📖</span>
|
|
8
|
+
<strong>Introduction</strong>
|
|
9
|
+
<small>Overview and key benefits of Le Truc</small>
|
|
10
|
+
</a>
|
|
11
|
+
</li><li>
|
|
12
|
+
<a href="getting-started.html">
|
|
13
|
+
<span class="icon">🚀</span>
|
|
14
|
+
<strong>Getting Started</strong>
|
|
15
|
+
<small>Installation, setup, and first steps</small>
|
|
16
|
+
</a>
|
|
17
|
+
</li><li>
|
|
18
|
+
<a href="components.html">
|
|
19
|
+
<span class="icon">🏗️</span>
|
|
20
|
+
<strong>Components</strong>
|
|
21
|
+
<small>Anatomy, lifecycle, signals, effects</small>
|
|
22
|
+
</a>
|
|
23
|
+
</li><li>
|
|
24
|
+
<a href="styling.html">
|
|
25
|
+
<span class="icon">🎨</span>
|
|
26
|
+
<strong>Styling</strong>
|
|
27
|
+
<small>Scoped styles, CSS custom properties</small>
|
|
28
|
+
</a>
|
|
29
|
+
</li><li>
|
|
30
|
+
<a href="data-flow.html">
|
|
31
|
+
<span class="icon">🔄</span>
|
|
32
|
+
<strong>Data Flow</strong>
|
|
33
|
+
<small>Passing state, events, context</small>
|
|
34
|
+
</a>
|
|
35
|
+
</li><li>
|
|
36
|
+
<a href="about.html">
|
|
37
|
+
<span class="icon">🤝</span>
|
|
38
|
+
<strong>About</strong>
|
|
39
|
+
<small>License, versioning, getting involved</small>
|
|
40
|
+
</a>
|
|
41
|
+
</li>
|
|
42
|
+
</ol>
|
|
43
|
+
</nav>
|
|
44
|
+
</section-menu>
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'About'
|
|
3
|
+
emoji: '🤝'
|
|
4
|
+
description: 'License, versioning, getting involved'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
{% hero %}
|
|
8
|
+
# 🤝 About
|
|
9
|
+
|
|
10
|
+
**Join the Le Truc community!** This page covers the people behind Le Truc, how you can contribute, versioning details, and licensing. Whether you're a developer, designer, or sponsor, there are many ways to get involved.
|
|
11
|
+
{% /hero %}
|
|
12
|
+
|
|
13
|
+
{% section %}
|
|
14
|
+
## Who's Behind Le Truc?
|
|
15
|
+
|
|
16
|
+
Le Truc is an **open-source project**, actively developed by [Zeix AG](https://zeix.com), a Switzerland-based agency for User-Centered Design, committed to enhancing accessibility and usability in web technologies.
|
|
17
|
+
|
|
18
|
+
### Core Team & Contributors
|
|
19
|
+
|
|
20
|
+
- **Zeix AG**: [@zeixcom](https://github.com/zeixcom) – Maintainers and primary developers
|
|
21
|
+
- **Esther Brunner**: [@estherbrunner](https://github.com/estherbrunner) – Lead developer
|
|
22
|
+
- **Fabian Haefliger**: [@fabianhaef](https://github.com/fabianhaef) – Core team
|
|
23
|
+
|
|
24
|
+
### Sponsors
|
|
25
|
+
|
|
26
|
+
{% callout class="note" %}
|
|
27
|
+
**Become a Sponsor**
|
|
28
|
+
|
|
29
|
+
Le Truc is free and open-source. If your organization finds it valuable, consider [sponsoring its development](info@zeix.com) to help make web development **lightweight, accessible, and fun** again!
|
|
30
|
+
{% /callout %}
|
|
31
|
+
|
|
32
|
+
{% /section %}
|
|
33
|
+
|
|
34
|
+
{% section %}
|
|
35
|
+
## License
|
|
36
|
+
|
|
37
|
+
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT), which means you can **use, modify, and distribute** it freely – even in commercial projects.
|
|
38
|
+
|
|
39
|
+
A copy of the license can be found in the [LICENSE](https://github.com/zeixcom/le-truc/blob/main/LICENSE) file of the repository.
|
|
40
|
+
|
|
41
|
+
{% /section %}
|
|
42
|
+
|
|
43
|
+
{% section %}
|
|
44
|
+
|
|
45
|
+
## Version History
|
|
46
|
+
|
|
47
|
+
### Current Version: 0.15.0
|
|
48
|
+
|
|
49
|
+
{% callout class="caution" %}
|
|
50
|
+
|
|
51
|
+
**Release candidate**
|
|
52
|
+
|
|
53
|
+
This version is a **pre-release** of Le Truc, meaning **breaking changes** may still occur before the official release of version 1.0. Please check the [release notes](https://github.com/zeixcom/le-truc/releases) before updating.
|
|
54
|
+
|
|
55
|
+
{% /callout %}
|
|
56
|
+
|
|
57
|
+
### Versioning Scheme
|
|
58
|
+
|
|
59
|
+
Le Truc follows [Semantic Versioning](https://semver.org/) (SemVer), which is structured as `MAJOR.MINOR.PATCH`.
|
|
60
|
+
|
|
61
|
+
- **MAJOR**: Breaking changes that require migrations.
|
|
62
|
+
- **MINOR**: New features that are backwards compatible.
|
|
63
|
+
- **PATCH**: Bug fixes and performance improvements.
|
|
64
|
+
|
|
65
|
+
### Previous Pre-Releases
|
|
66
|
+
|
|
67
|
+
View all releases and associated notes on [Github Releases](https://github.com/zeixcom/le-truc/releases).
|
|
68
|
+
|
|
69
|
+
{% /section %}
|
|
70
|
+
|
|
71
|
+
{% section %}
|
|
72
|
+
## Getting Involved
|
|
73
|
+
|
|
74
|
+
Le Truc is **an open-source project**, and contributions are always welcome! Whether you’re **reporting bugs, improving documentation, or suggesting features**, here's how you can help:
|
|
75
|
+
|
|
76
|
+
- [Open an Issue](https://github.com/zeixcom/le-truc/issues) – Report bugs or suggest features.
|
|
77
|
+
- [Submit a Pull Request](https://github.com/zeixcom/le-truc/blob/main/CONTRIBUTING.md) – Help improve Le Truc by fixing issues or adding new features.
|
|
78
|
+
- Join the Discussion – Share ideas and get feedback from the community.
|
|
79
|
+
|
|
80
|
+
### Contributing Code
|
|
81
|
+
|
|
82
|
+
- Fork the repository, create a new branch, and submit a pull request.
|
|
83
|
+
- Read the [Contributing Guidelines](https://github.com/zeixcom/le-truc/blob/main/CONTRIBUTING.md) for setting up a development environment and best practices.
|
|
84
|
+
|
|
85
|
+
### Community Guidelines
|
|
86
|
+
|
|
87
|
+
We strive for a welcoming and inclusive environment. Please follow our [Code of Conduct](https://github.com/zeixcom/le-truc/blob/main/CODE_OF_CONDUCT.md) when contributing.
|
|
88
|
+
|
|
89
|
+
{% /section %}
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Components'
|
|
3
|
+
emoji: '🏗️'
|
|
4
|
+
description: 'Anatomy, lifecycle, signals, effects'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
{% hero %}
|
|
8
|
+
# 🏗️ Components
|
|
9
|
+
|
|
10
|
+
**Create lightweight, self-contained Web Components with built-in reactivity**. Le Truc lets you define custom elements that manage state efficiently, update the DOM automatically, and enhance server-rendered pages without an SPA framework.
|
|
11
|
+
{% /hero %}
|
|
12
|
+
|
|
13
|
+
{% section %}
|
|
14
|
+
## Defining a Component
|
|
15
|
+
|
|
16
|
+
Le Truc builds on **Web Components**, extending `HTMLElement` to provide **built-in state management and reactive updates**.
|
|
17
|
+
|
|
18
|
+
Le Truc creates components using the `defineComponent()` function:
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
defineComponent('my-component', {}, {}, () => [
|
|
22
|
+
// Component setup
|
|
23
|
+
])
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Every Le Truc component must be registered with a valid custom element tag name (two or more words joined with `-`) as the first parameter.
|
|
27
|
+
|
|
28
|
+
### Using the Custom Element in HTML
|
|
29
|
+
|
|
30
|
+
Once registered, the component can be used like any native HTML element:
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<my-component>Content goes here</my-component>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Anatomy of a Component
|
|
37
|
+
|
|
38
|
+
Let's examine a complete component example to understand how Le Truc works:
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
defineComponent(
|
|
42
|
+
'basic-hello',
|
|
43
|
+
{
|
|
44
|
+
name: asString(ui => ui.output.textContent),
|
|
45
|
+
},
|
|
46
|
+
({ first }) => ({
|
|
47
|
+
input: first('input', 'Needed to enter the name.'),
|
|
48
|
+
output: first('output', 'Needed to display the name.'),
|
|
49
|
+
}),
|
|
50
|
+
({ host, input }) => {
|
|
51
|
+
const fallback = host.name
|
|
52
|
+
return {
|
|
53
|
+
input: on('input', () => {
|
|
54
|
+
host.name = input.value || fallback
|
|
55
|
+
}),
|
|
56
|
+
output: setText('name'),
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
#### Reactive Properties
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
{
|
|
66
|
+
name: asString(ui => ui.output.textContent),
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
This creates a reactive property called `name`:
|
|
71
|
+
|
|
72
|
+
- `asString()` observes the attribute `name` and assigns its value as a string to the `name` property
|
|
73
|
+
- `ui => ...` is an instruction how to get the fallback value in the DOM if there is no name attribute
|
|
74
|
+
- Le Truc automatically reads "World" from the `<output>` element as the initial value
|
|
75
|
+
- When `name` changes, any effects that depend on it automatically update
|
|
76
|
+
|
|
77
|
+
#### Select Function
|
|
78
|
+
|
|
79
|
+
The select function is used to find descendant elements within the component's DOM:
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
({ first }) => ({
|
|
83
|
+
input: first('input', 'Needed to enter the name.'),
|
|
84
|
+
output: first('output', 'Needed to display the name.'),
|
|
85
|
+
}),
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The select function must return a record of the selected elements, commonly called `ui` to which initializer functions for reactive properties and the setup function for effects have access to. In the above example, the helper function `first()` is used to find the first descendant matching a selector. Also available is `all()` to find all descendants matching a selector, dynamically updating the list of elements when the DOM changes. Both helper functions take a selector string and an optional error message to display if no element is found.
|
|
89
|
+
|
|
90
|
+
#### Setup Function
|
|
91
|
+
|
|
92
|
+
The setup function must return a record with an array of effects for properties of the `ui` object that is passed in. The additional `host` key of the `ui` object holds the component element itself.
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
({ host, input }) => {
|
|
96
|
+
const fallback = host.name
|
|
97
|
+
return {
|
|
98
|
+
input: on('input', () => {
|
|
99
|
+
host.name = input.value || fallback
|
|
100
|
+
}),
|
|
101
|
+
output: setText('name'),
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Effects define **component behaviors**:
|
|
107
|
+
|
|
108
|
+
- `input: on('input', ...)` adds an event listener to the `<input>` element
|
|
109
|
+
- `output: setText('name')` keeps its text in sync with the `name` property
|
|
110
|
+
|
|
111
|
+
Characteristics of effects:
|
|
112
|
+
|
|
113
|
+
- Effects run when the component is added to the page
|
|
114
|
+
- Effects rerun when their dependencies change
|
|
115
|
+
- Effects may return a cleanup function to be executed when the target element or the component is removed from the page
|
|
116
|
+
|
|
117
|
+
The bundled effects `on()` and `setText()` in this case are partially applied functions that connect to component properties and the target element and return the appropriate cleanup function.
|
|
118
|
+
|
|
119
|
+
{% /section %}
|
|
120
|
+
|
|
121
|
+
{% section %}
|
|
122
|
+
## Component Lifecycle
|
|
123
|
+
|
|
124
|
+
Le Truc manages the **Web Component lifecycle** from creation to removal. Here's what happens.
|
|
125
|
+
|
|
126
|
+
### Connected to the DOM
|
|
127
|
+
|
|
128
|
+
In the `connectedCallback()` reactive properties are initialized. You pass a second argument to the `defineComponent()` function to define initial values for **component states**.
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
defineComponent(
|
|
132
|
+
'my-component',
|
|
133
|
+
{
|
|
134
|
+
count: 0, // Initial value of "count" signal
|
|
135
|
+
value: asInteger(5), // Parse "value" attribute as integer defaulting to 5
|
|
136
|
+
isEven: ui => () => !(ui.host.count % 2), // Computed signal based on "count" signal
|
|
137
|
+
name: fromContext('display-name', 'World'), // Consume "display-name" signal from closest context provider
|
|
138
|
+
},
|
|
139
|
+
() => ({
|
|
140
|
+
// Component UI
|
|
141
|
+
}),
|
|
142
|
+
ui => ({
|
|
143
|
+
// Component setup
|
|
144
|
+
})
|
|
145
|
+
)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
In this example you see all three ways to define a reactive property:
|
|
149
|
+
|
|
150
|
+
- A **static initial value** creates a `State` signal with the initial value
|
|
151
|
+
- An **attribute parser** creates a `State` signal may from the attribute or fallback value, updating the state whenever the attribute changes
|
|
152
|
+
- An **initializer** function that creates a `State` or a `Computed` signal depending on the return type of the function. If the function returns a value, it creates a `State` signal. If the function returns a function, it creates a `Computed` signal. Initializer functions have access to the component's `ui` object, allowing them to create signals based on the component's state or descendant elements.
|
|
153
|
+
|
|
154
|
+
### Disconnected from the DOM
|
|
155
|
+
|
|
156
|
+
In the `disconnectedCallback()` Le Truc runs all cleanup functions returned by effects during the setup phase in `connectedCallback()`. This will remove all event listeners and unsubscribe all signals the component is subscribed to, so you don't need to worry about memory leaks.
|
|
157
|
+
|
|
158
|
+
If you added **event listeners** outside the scope of your component or **subscribed manually to external APIs** in a custom effect, you need to return a cleanup function:
|
|
159
|
+
|
|
160
|
+
```js
|
|
161
|
+
defineComponent('my-component', {}, {}, ({ host }) => {
|
|
162
|
+
// Setup logic
|
|
163
|
+
host: () => {
|
|
164
|
+
const observer = new IntersectionObserver(([entry]) => {
|
|
165
|
+
// Do something
|
|
166
|
+
})
|
|
167
|
+
observer.observe(host)
|
|
168
|
+
|
|
169
|
+
// Cleanup logic
|
|
170
|
+
return () => observer.disconnect()
|
|
171
|
+
},
|
|
172
|
+
})
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Managing State with Signals
|
|
176
|
+
|
|
177
|
+
Le Truc manages state using **signals**, which are atomic reactive states that trigger updates when they change. We use regular properties for public component states:
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
console.log('count' in el) // Check if the signal exists
|
|
181
|
+
console.log(el.count) // Read the signal value
|
|
182
|
+
el.count = 42 // Update the signal value
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Characteristics and Special Values
|
|
186
|
+
|
|
187
|
+
Signals in Le Truc are of a **static type** and **non-nullable**. This allows to **simplify the logic** as you will never have to check the type or perform null-checks.
|
|
188
|
+
|
|
189
|
+
- If you use **TypeScript** (recommended), **you will be warned** that `null` or `undefined` cannot be assigned to a signal or if you try to assign a value of a wrong type.
|
|
190
|
+
- If you use vanilla **JavaScript** without a build step, setting a signal to `null` or `undefined` **will throw a `NullishSignalValueError`**. However, strict type checking is not enforced at runtime.
|
|
191
|
+
|
|
192
|
+
Because of the **non-nullable nature of signals** in Le Truc, we need two special values that can be assigned to any signal type:
|
|
193
|
+
|
|
194
|
+
- **`RESET`**: Will **reset to the server-rendered version** that was there before Le Truc took control. This is what you want to do most of the times when a signal lacks a specific value.
|
|
195
|
+
- **`UNSET`**: Will **delete the signal**, **unsubscribe its watchers** and also **delete related attributes or style properties** in effects. Use this with special care!
|
|
196
|
+
|
|
197
|
+
### Initializing State from Attributes
|
|
198
|
+
|
|
199
|
+
The standard way to set initial state in Le Truc is via **server-rendered attributes** on the component that needs it. No props drilling as in other frameworks. Le Trucs provides some bundled attribute parsers to convert attribute values to the desired type. And you can also define your own custom parsers.
|
|
200
|
+
|
|
201
|
+
```js
|
|
202
|
+
defineComponent(
|
|
203
|
+
'my-component',
|
|
204
|
+
{
|
|
205
|
+
count: asInteger(), // Bundled parser: Convert '42' -> 42
|
|
206
|
+
date: (_, v) => new Date(v), // Custom parser: '2025-12-12' -> Date object
|
|
207
|
+
},
|
|
208
|
+
() => ({
|
|
209
|
+
// Component UI
|
|
210
|
+
})
|
|
211
|
+
() => ({
|
|
212
|
+
// Component setup
|
|
213
|
+
}),
|
|
214
|
+
)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
{% callout class="caution" %}
|
|
218
|
+
**Careful**: Attributes **may not be present** on the element or **parsing to the desired type may fail**. To ensure **non-nullability** of signals, Le Truc falls back to neutral defaults if no fallback value is provided:
|
|
219
|
+
|
|
220
|
+
- `""` (empty string) for `string`
|
|
221
|
+
- `0` for `number`
|
|
222
|
+
- `{}` (empty object) for objects of any kind
|
|
223
|
+
{% /callout %}
|
|
224
|
+
|
|
225
|
+
### Bundled Attribute Parsers
|
|
226
|
+
|
|
227
|
+
Le Truc provides several built-in parsers for common attribute types. See the [Parsers section](api.html#parsers) in the API reference for detailed descriptions and usage examples.
|
|
228
|
+
|
|
229
|
+
{% /section %}
|
|
230
|
+
|
|
231
|
+
{% section %}
|
|
232
|
+
|
|
233
|
+
## Selecting Elements
|
|
234
|
+
|
|
235
|
+
Use the provided selector utilities to find descendant elements within your component:
|
|
236
|
+
|
|
237
|
+
### first()
|
|
238
|
+
|
|
239
|
+
Selects the first matching element:
|
|
240
|
+
|
|
241
|
+
```js
|
|
242
|
+
defineComponent(
|
|
243
|
+
'basic-counter',
|
|
244
|
+
{
|
|
245
|
+
// Initialize properties
|
|
246
|
+
},
|
|
247
|
+
({ first }) => ({
|
|
248
|
+
increment: first(
|
|
249
|
+
'button',
|
|
250
|
+
'Add a native button element to increment the count.',
|
|
251
|
+
),
|
|
252
|
+
count: first('span', 'Add a span to display the count.'),
|
|
253
|
+
}),
|
|
254
|
+
ui => ({
|
|
255
|
+
// Component setup
|
|
256
|
+
}),
|
|
257
|
+
)
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### all()
|
|
261
|
+
|
|
262
|
+
Selects all matching elements:
|
|
263
|
+
|
|
264
|
+
```js
|
|
265
|
+
defineComponent(
|
|
266
|
+
'module-tabgroup',
|
|
267
|
+
{
|
|
268
|
+
// Initialize properties
|
|
269
|
+
},
|
|
270
|
+
({ all }) => ({
|
|
271
|
+
tabs: all(
|
|
272
|
+
'button[role="tab"]',
|
|
273
|
+
'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.',
|
|
274
|
+
),
|
|
275
|
+
panels: all(
|
|
276
|
+
'[role="tabpanel"]',
|
|
277
|
+
'At least 2 tabpanels are needed. Each tabpanel must have a unique id.',
|
|
278
|
+
),
|
|
279
|
+
}),
|
|
280
|
+
ui => ({
|
|
281
|
+
// Component setup
|
|
282
|
+
}),
|
|
283
|
+
)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
The `first()` function expects the matched element to be present at connection time. If not, it will silently ignore the call.
|
|
287
|
+
|
|
288
|
+
On the other hand, the `all()` function creates a dynamic array of elements that will be updated whenever the matching elements are added or removed from the component's DOM branch. Le Truc will apply the given setup functions to added elements and run the cleanup functions on removed elements.
|
|
289
|
+
|
|
290
|
+
{% callout class="tip" %}
|
|
291
|
+
**Tip**: The `all()` function is more flexible but also more resource-intensive than `first()`. Prefer `first()` when targeting a single element known to be present at connection time.
|
|
292
|
+
{% /callout %}
|
|
293
|
+
|
|
294
|
+
{% /section %}
|
|
295
|
+
|
|
296
|
+
{% section %}
|
|
297
|
+
|
|
298
|
+
## Adding Event Listeners
|
|
299
|
+
|
|
300
|
+
Event listeners allow to respond to user interactions. They are the the main cause for changes in the component's state. Le Truc provides the `on()` function to add event listeners to elements and remove them when the component is disconnected.
|
|
301
|
+
|
|
302
|
+
```js
|
|
303
|
+
defineComponent(
|
|
304
|
+
'my-component',
|
|
305
|
+
{
|
|
306
|
+
active: 0,
|
|
307
|
+
value: ''
|
|
308
|
+
},
|
|
309
|
+
({ all, first }) => ({
|
|
310
|
+
buttons: all('button'),
|
|
311
|
+
input: first('input')
|
|
312
|
+
}),
|
|
313
|
+
({ host, input }) => ({
|
|
314
|
+
buttons: on('click', ({ target }) => {
|
|
315
|
+
// Set 'active' signal to value of data-index attribute of button
|
|
316
|
+
const index = parseInt(target.dataset.index, 10);
|
|
317
|
+
host.active = Number.isInteger(index) ? index : 0;
|
|
318
|
+
})
|
|
319
|
+
input: on('change', () => {
|
|
320
|
+
// Set 'value' signal to value of input element
|
|
321
|
+
host.value = target.value;
|
|
322
|
+
})
|
|
323
|
+
})
|
|
324
|
+
)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
{% /section %}
|
|
328
|
+
|
|
329
|
+
{% section %}
|
|
330
|
+
|
|
331
|
+
## Synchronizing State with Effects
|
|
332
|
+
|
|
333
|
+
Effects **automatically update the DOM** when signals change, avoiding manual DOM manipulation.
|
|
334
|
+
|
|
335
|
+
### Applying Effects
|
|
336
|
+
|
|
337
|
+
Apply one or multiple effects in the setup function (for component itself) or in element selector functions:
|
|
338
|
+
|
|
339
|
+
```js
|
|
340
|
+
return {
|
|
341
|
+
// On the component itself
|
|
342
|
+
host: setAttribute('open', 'open'), // Set 'open' attribute according to 'open' signal
|
|
343
|
+
// On element for the 'count' property of the UI object
|
|
344
|
+
count: [
|
|
345
|
+
setText('count'), // Update text content according to 'count' signal
|
|
346
|
+
toggleClass('even', 'isEven') // Toggle 'even' class according to 'isEven' signal
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
The order of effects is not important. Feel free to apply them in any order that suits your needs.
|
|
352
|
+
|
|
353
|
+
### Bundled Effects
|
|
354
|
+
|
|
355
|
+
Le Truc provides many built-in effects for common DOM operations. See the [Effects section](api.html#effects) in the API reference for detailed descriptions and usage examples.
|
|
356
|
+
|
|
357
|
+
### Simplifying Effect Notation
|
|
358
|
+
|
|
359
|
+
For effects that take two arguments, **the second argument can be omitted** if the signal key matches the targeted property name, attribute, class, or style property.
|
|
360
|
+
|
|
361
|
+
The following are equivalent:
|
|
362
|
+
|
|
363
|
+
```js
|
|
364
|
+
// setAttribute('open', 'open')
|
|
365
|
+
setAttribute('open')
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Here, `setAttribute('open')` automatically uses the `open` signal.
|
|
369
|
+
|
|
370
|
+
### Using Local Signals for Private State
|
|
371
|
+
|
|
372
|
+
Local signals are useful for storing state that should not be exposed to the outside world. They can be used to manage internal state within a component:
|
|
373
|
+
|
|
374
|
+
```js
|
|
375
|
+
defineComponent(
|
|
376
|
+
'my-component',
|
|
377
|
+
{},
|
|
378
|
+
({ first }) => ({
|
|
379
|
+
increment: first('button.increment'),
|
|
380
|
+
count: first('.count'),
|
|
381
|
+
double: first('.double')
|
|
382
|
+
}),
|
|
383
|
+
() => {
|
|
384
|
+
const count = createState(0)
|
|
385
|
+
const double = createComputed(() => count.get() * 2)
|
|
386
|
+
return {
|
|
387
|
+
increment: on('click', () => {
|
|
388
|
+
count.update(v => ++v)
|
|
389
|
+
}),
|
|
390
|
+
count: setText(count),
|
|
391
|
+
double: setText(double),
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
)
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Outside components cannot access the `count` or `double` signals.
|
|
398
|
+
|
|
399
|
+
### Using Functions for Ad-hoc Derived State
|
|
400
|
+
|
|
401
|
+
Instead of a signal key or a local signal, you can **pass a function** that derives a value dynamically:
|
|
402
|
+
|
|
403
|
+
```js
|
|
404
|
+
defineComponent(
|
|
405
|
+
'my-component',
|
|
406
|
+
{
|
|
407
|
+
count: 0,
|
|
408
|
+
},
|
|
409
|
+
({ first }) => ({
|
|
410
|
+
count: first('.count'),
|
|
411
|
+
double: first('.double')
|
|
412
|
+
}),
|
|
413
|
+
({ host }) => ({
|
|
414
|
+
count: toggleClass('even', () => !(host.count % 2)),
|
|
415
|
+
double: setText(() => String(host.count * 2))
|
|
416
|
+
})
|
|
417
|
+
)
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
{% callout class="tip" %}
|
|
421
|
+
**When to use**
|
|
422
|
+
|
|
423
|
+
- **Use a signal key or a local signal** when the state is part of the component's public interface or internally reused.
|
|
424
|
+
- **Use a function** to **derive a value on the fly** when it is needed only in this one place.
|
|
425
|
+
|
|
426
|
+
Ad-hoc derived state is more efficient than the overhead of a memoized computed signal for simple functions like converting to a string or boolean, formatting a value or performing a calculation.
|
|
427
|
+
{% /callout %}
|
|
428
|
+
|
|
429
|
+
### Efficient & Fine-Grained Updates
|
|
430
|
+
|
|
431
|
+
Unlike some frameworks that **re-render entire components**, Le Truc updates only what changes:
|
|
432
|
+
|
|
433
|
+
- **No virtual DOM** – Le Truc modifies the DOM directly.
|
|
434
|
+
- **Signals propagate automatically** – no need to track dependencies manually.
|
|
435
|
+
- **Optimized with a scheduler** – multiple updates are batched efficiently.
|
|
436
|
+
|
|
437
|
+
{% /section %}
|