@studiometa/js-toolkit 4.0.0-alpha.1 → 4.0.0-alpha.3
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/README.md +10 -0
- package/dist/Base.d.ts +0 -2
- package/dist/Base.js +1 -2
- package/dist/Base.js.map +1 -1
- package/dist/attribute-namespaces.d.ts +0 -2
- package/dist/attribute-namespaces.js +1 -2
- package/dist/attributes.d.ts +0 -2
- package/dist/attributes.js +1 -2
- package/dist/children-watchers.d.ts +0 -2
- package/dist/children-watchers.js +1 -2
- package/dist/component-brand.d.ts +0 -2
- package/dist/component-brand.js +1 -2
- package/dist/component-declarations.d.ts +0 -2
- package/dist/component-declarations.js +1 -2
- package/dist/context-subscription.d.ts +0 -2
- package/dist/context-subscription.js +1 -2
- package/dist/context.d.ts +0 -2
- package/dist/context.js +1 -2
- package/dist/decorators.d.ts +0 -2
- package/dist/decorators.js +1 -2
- package/dist/diagnostic-contract.d.ts +0 -2
- package/dist/diagnostic-contract.js +1 -2
- package/dist/diagnostics.d.ts +0 -2
- package/dist/diagnostics.js +1 -2
- package/dist/document-order.d.ts +0 -2
- package/dist/document-order.js +1 -2
- package/dist/dom-mutations.d.ts +0 -2
- package/dist/dom-mutations.js +1 -2
- package/dist/events.d.ts +0 -2
- package/dist/events.js +1 -2
- package/dist/group.d.ts +0 -2
- package/dist/group.js +1 -2
- package/dist/instances.d.ts +0 -2
- package/dist/instances.js +1 -2
- package/dist/manifest.d.ts +0 -2
- package/dist/manifest.js +1 -2
- package/dist/mount-strategies.d.ts +0 -2
- package/dist/mount-strategies.js +1 -2
- package/dist/negotiated-events.d.ts +0 -2
- package/dist/negotiated-events.js +1 -2
- package/dist/protocol-symbols.d.ts +0 -2
- package/dist/protocol-symbols.js +1 -2
- package/dist/registry.d.ts +0 -2
- package/dist/registry.js +1 -2
- package/dist/responsive-options.d.ts +0 -2
- package/dist/responsive-options.js +1 -2
- package/dist/scheduler.d.ts +0 -2
- package/dist/scheduler.js +1 -2
- package/dist/scheduler.js.map +1 -1
- package/dist/services/breakpoint.d.ts +0 -2
- package/dist/services/breakpoint.js +1 -2
- package/dist/services/drag.d.ts +0 -2
- package/dist/services/drag.js +1 -2
- package/dist/services/in-view.d.ts +0 -2
- package/dist/services/in-view.js +1 -2
- package/dist/services/key.d.ts +0 -2
- package/dist/services/key.js +1 -2
- package/dist/services/media.d.ts +0 -2
- package/dist/services/media.js +1 -2
- package/dist/services/mixin.d.ts +0 -2
- package/dist/services/mixin.js +1 -2
- package/dist/services/mutation.d.ts +0 -2
- package/dist/services/mutation.js +1 -2
- package/dist/services/pointer.d.ts +0 -2
- package/dist/services/pointer.js +1 -2
- package/dist/services/raf.d.ts +0 -2
- package/dist/services/raf.js +1 -2
- package/dist/services/resize.d.ts +0 -2
- package/dist/services/resize.js +1 -2
- package/dist/services/scroll-progress-offset.d.ts +0 -2
- package/dist/services/scroll-progress-offset.js +1 -2
- package/dist/services/scroll-progress.d.ts +0 -2
- package/dist/services/scroll-progress.js +1 -2
- package/dist/services/scroll.d.ts +0 -2
- package/dist/services/scroll.js +1 -2
- package/dist/services/service.d.ts +0 -2
- package/dist/services/service.js +1 -2
- package/dist/services/toggle.d.ts +0 -2
- package/dist/services/toggle.js +1 -2
- package/dist/services/until.d.ts +0 -2
- package/dist/services/until.js +1 -2
- package/dist/shared-runtime.d.ts +0 -2
- package/dist/shared-runtime.js +1 -2
- package/dist/storage/createStorage.d.ts +0 -2
- package/dist/storage/createStorage.js +1 -2
- package/dist/storage/index.d.ts +0 -2
- package/dist/storage/index.js +1 -2
- package/dist/storage/providers.d.ts +0 -2
- package/dist/storage/providers.js +1 -2
- package/dist/storage/serializers.d.ts +0 -2
- package/dist/storage/serializers.js +1 -2
- package/dist/storage/sync.d.ts +0 -2
- package/dist/storage/sync.js +1 -2
- package/dist/storage/types.d.ts +0 -2
- package/dist/subpaths/BREAKPOINTS.js +1 -2
- package/dist/subpaths/Base.js +1 -2
- package/dist/subpaths/DIAGNOSTICS.js +1 -2
- package/dist/subpaths/DRAG_MODES.js +1 -2
- package/dist/subpaths/EVENTS.js +1 -2
- package/dist/subpaths/MOUNT_ATTRIBUTE.js +1 -2
- package/dist/subpaths/SWAP_MODES.js +1 -2
- package/dist/subpaths/children.js +1 -2
- package/dist/subpaths/component.js +1 -2
- package/dist/subpaths/createContext.js +1 -2
- package/dist/subpaths/createFallbackProvider.js +1 -2
- package/dist/subpaths/createGroup.js +1 -2
- package/dist/subpaths/createLocalStorage.js +1 -2
- package/dist/subpaths/createMemoryStorageProvider.js +1 -2
- package/dist/subpaths/createService.js +1 -2
- package/dist/subpaths/createServiceMixin.js +1 -2
- package/dist/subpaths/createSessionStorage.js +1 -2
- package/dist/subpaths/createStorage.js +1 -2
- package/dist/subpaths/createUrlSearchParamsInHashProvider.js +1 -2
- package/dist/subpaths/createUrlSearchParamsInHashStorage.js +1 -2
- package/dist/subpaths/createUrlSearchParamsProvider.js +1 -2
- package/dist/subpaths/createUrlSearchParamsStorage.js +1 -2
- package/dist/subpaths/defaultScheduler.js +1 -2
- package/dist/subpaths/defineManifest.js +1 -2
- package/dist/subpaths/domUpdate.js +1 -2
- package/dist/subpaths/emitExtendable.js +1 -2
- package/dist/subpaths/fromMetaGlob.js +1 -2
- package/dist/subpaths/fromWebpackContext.js +1 -2
- package/dist/subpaths/getBreakpoints.js +1 -2
- package/dist/subpaths/getInstance.js +1 -2
- package/dist/subpaths/getInstances.js +1 -2
- package/dist/subpaths/getMountedInstances.js +1 -2
- package/dist/subpaths/getUnmountedInstances.js +1 -2
- package/dist/subpaths/inject.js +1 -2
- package/dist/subpaths/injectContext.js +1 -2
- package/dist/subpaths/injectContextSync.js +1 -2
- package/dist/subpaths/jsonSerializer.js +1 -2
- package/dist/subpaths/localStorageProvider.js +1 -2
- package/dist/subpaths/memoryStorageProvider.js +1 -2
- package/dist/subpaths/namespaceQualifier.js +1 -2
- package/dist/subpaths/nextFrame.js +1 -2
- package/dist/subpaths/on.js +1 -2
- package/dist/subpaths/perTarget.js +1 -2
- package/dist/subpaths/provide.js +1 -2
- package/dist/subpaths/provideContext.js +1 -2
- package/dist/subpaths/provideRootContext.js +1 -2
- package/dist/subpaths/read.js +1 -2
- package/dist/subpaths/registerComponent.js +1 -2
- package/dist/subpaths/registerComponents.js +1 -2
- package/dist/subpaths/registerManifest.js +1 -2
- package/dist/subpaths/reportDiagnostic.js +1 -2
- package/dist/subpaths/sessionStorageProvider.js +1 -2
- package/dist/subpaths/setBreakpoints.js +1 -2
- package/dist/subpaths/signal.js +1 -2
- package/dist/subpaths/subscribeContext.js +1 -2
- package/dist/subpaths/swap.js +1 -2
- package/dist/subpaths/toggle.js +1 -2
- package/dist/subpaths/until.js +1 -2
- package/dist/subpaths/urlSearchParamsInHashProvider.js +1 -2
- package/dist/subpaths/urlSearchParamsProvider.js +1 -2
- package/dist/subpaths/useBreakpoint.js +1 -2
- package/dist/subpaths/useDrag.js +1 -2
- package/dist/subpaths/useInView.js +1 -2
- package/dist/subpaths/useKey.js +1 -2
- package/dist/subpaths/useMediaQuery.js +1 -2
- package/dist/subpaths/useMutation.js +1 -2
- package/dist/subpaths/usePointer.js +1 -2
- package/dist/subpaths/usePrefersReducedMotion.js +1 -2
- package/dist/subpaths/useRaf.js +1 -2
- package/dist/subpaths/useResize.js +1 -2
- package/dist/subpaths/useScroll.js +1 -2
- package/dist/subpaths/useScrollProgress.js +1 -2
- package/dist/subpaths/useWindowScroll.js +1 -2
- package/dist/subpaths/useWindowSize.js +1 -2
- package/dist/subpaths/utils/DEFAULT_DAMP_FACTOR.js +1 -2
- package/dist/subpaths/utils/INERTIA_FRAME.js +1 -2
- package/dist/subpaths/utils/MAX_SPRING_RATIO.js +1 -2
- package/dist/subpaths/utils/SCROLL_ALIGNMENTS.js +1 -2
- package/dist/subpaths/utils/SCROLL_AXES.js +1 -2
- package/dist/subpaths/utils/TRANSFORM_PROPS.js +1 -2
- package/dist/subpaths/utils/TRANSITION_OPTIONS.js +1 -2
- package/dist/subpaths/utils/camelCase.js +1 -2
- package/dist/subpaths/utils/capitalize.js +1 -2
- package/dist/subpaths/utils/clamp.js +1 -2
- package/dist/subpaths/utils/clamp01.js +1 -2
- package/dist/subpaths/utils/clampDampFactor.js +1 -2
- package/dist/subpaths/utils/createEaseInOut.js +1 -2
- package/dist/subpaths/utils/createEaseOut.js +1 -2
- package/dist/subpaths/utils/createElement.js +1 -2
- package/dist/subpaths/utils/createRange.js +1 -2
- package/dist/subpaths/utils/damp.js +1 -2
- package/dist/subpaths/utils/debounce.js +1 -2
- package/dist/subpaths/utils/decayOver.js +1 -2
- package/dist/subpaths/utils/deepmerge.js +1 -2
- package/dist/subpaths/utils/easeInCirc.js +1 -2
- package/dist/subpaths/utils/easeInCubic.js +1 -2
- package/dist/subpaths/utils/easeInExpo.js +1 -2
- package/dist/subpaths/utils/easeInOutCirc.js +1 -2
- package/dist/subpaths/utils/easeInOutCubic.js +1 -2
- package/dist/subpaths/utils/easeInOutExpo.js +1 -2
- package/dist/subpaths/utils/easeInOutQuad.js +1 -2
- package/dist/subpaths/utils/easeInOutQuart.js +1 -2
- package/dist/subpaths/utils/easeInOutQuint.js +1 -2
- package/dist/subpaths/utils/easeInOutSine.js +1 -2
- package/dist/subpaths/utils/easeInQuad.js +1 -2
- package/dist/subpaths/utils/easeInQuart.js +1 -2
- package/dist/subpaths/utils/easeInQuint.js +1 -2
- package/dist/subpaths/utils/easeInSine.js +1 -2
- package/dist/subpaths/utils/easeLinear.js +1 -2
- package/dist/subpaths/utils/easeOutCirc.js +1 -2
- package/dist/subpaths/utils/easeOutCubic.js +1 -2
- package/dist/subpaths/utils/easeOutExpo.js +1 -2
- package/dist/subpaths/utils/easeOutQuad.js +1 -2
- package/dist/subpaths/utils/easeOutQuart.js +1 -2
- package/dist/subpaths/utils/easeOutQuint.js +1 -2
- package/dist/subpaths/utils/easeOutSine.js +1 -2
- package/dist/subpaths/utils/enterTransition.js +1 -2
- package/dist/subpaths/utils/fold.js +1 -2
- package/dist/subpaths/utils/getOffsetSizes.js +1 -2
- package/dist/subpaths/utils/historyPush.js +1 -2
- package/dist/subpaths/utils/historyReplace.js +1 -2
- package/dist/subpaths/utils/inertiaDecay.js +1 -2
- package/dist/subpaths/utils/inertiaFinalValue.js +1 -2
- package/dist/subpaths/utils/inertiaStep.js +1 -2
- package/dist/subpaths/utils/inertiaTimeConstant.js +1 -2
- package/dist/subpaths/utils/isBoolean.js +1 -2
- package/dist/subpaths/utils/isDefined.js +1 -2
- package/dist/subpaths/utils/isFunction.js +1 -2
- package/dist/subpaths/utils/isNull.js +1 -2
- package/dist/subpaths/utils/isNumber.js +1 -2
- package/dist/subpaths/utils/isObject.js +1 -2
- package/dist/subpaths/utils/isString.js +1 -2
- package/dist/subpaths/utils/kebabCase.js +1 -2
- package/dist/subpaths/utils/leaveTransition.js +1 -2
- package/dist/subpaths/utils/lerp.js +1 -2
- package/dist/subpaths/utils/loadImage.js +1 -2
- package/dist/subpaths/utils/loadLink.js +1 -2
- package/dist/subpaths/utils/loadScript.js +1 -2
- package/dist/subpaths/utils/lockScroll.js +1 -2
- package/dist/subpaths/utils/lowerCase.js +1 -2
- package/dist/subpaths/utils/map.js +1 -2
- package/dist/subpaths/utils/matrix.js +1 -2
- package/dist/subpaths/utils/mean.js +1 -2
- package/dist/subpaths/utils/memo.js +1 -2
- package/dist/subpaths/utils/noop.js +1 -2
- package/dist/subpaths/utils/noopValue.js +1 -2
- package/dist/subpaths/utils/objectToURLSearchParams.js +1 -2
- package/dist/subpaths/utils/pascalCase.js +1 -2
- package/dist/subpaths/utils/random.js +1 -2
- package/dist/subpaths/utils/randomInt.js +1 -2
- package/dist/subpaths/utils/randomItem.js +1 -2
- package/dist/subpaths/utils/round.js +1 -2
- package/dist/subpaths/utils/saveActiveElement.js +1 -2
- package/dist/subpaths/utils/scrollPosition.js +1 -2
- package/dist/subpaths/utils/scrollTo.js +1 -2
- package/dist/subpaths/utils/selectorFor.js +1 -2
- package/dist/subpaths/utils/setClassesOrStyles.js +1 -2
- package/dist/subpaths/utils/smoothTo.js +1 -2
- package/dist/subpaths/utils/snakeCase.js +1 -2
- package/dist/subpaths/utils/spring.js +1 -2
- package/dist/subpaths/utils/throttle.js +1 -2
- package/dist/subpaths/utils/transform.js +1 -2
- package/dist/subpaths/utils/transition.js +1 -2
- package/dist/subpaths/utils/trapFocus.js +1 -2
- package/dist/subpaths/utils/untrapFocus.js +1 -2
- package/dist/subpaths/utils/upperCase.js +1 -2
- package/dist/subpaths/utils/wait.js +1 -2
- package/dist/subpaths/utils/withLeadingCharacters.js +1 -2
- package/dist/subpaths/utils/withLeadingSlash.js +1 -2
- package/dist/subpaths/utils/withTrailingCharacters.js +1 -2
- package/dist/subpaths/utils/withTrailingSlash.js +1 -2
- package/dist/subpaths/utils/withoutLeadingCharacters.js +1 -2
- package/dist/subpaths/utils/withoutLeadingCharactersRecursive.js +1 -2
- package/dist/subpaths/utils/withoutLeadingSlash.js +1 -2
- package/dist/subpaths/utils/withoutTrailingCharacters.js +1 -2
- package/dist/subpaths/utils/withoutTrailingCharactersRecursive.js +1 -2
- package/dist/subpaths/utils/withoutTrailingSlash.js +1 -2
- package/dist/subpaths/utils/wrap.js +1 -2
- package/dist/subpaths/viewTransition.js +1 -2
- package/dist/subpaths/warn.js +1 -2
- package/dist/subpaths/watchAttributeNamespace.js +1 -2
- package/dist/subpaths/watchAttributes.js +1 -2
- package/dist/subpaths/whenDOMSettled.js +1 -2
- package/dist/subpaths/withDrag.js +1 -2
- package/dist/subpaths/withInView.js +1 -2
- package/dist/subpaths/withKey.js +1 -2
- package/dist/subpaths/withMutation.js +1 -2
- package/dist/subpaths/withPointer.js +1 -2
- package/dist/subpaths/withRaf.js +1 -2
- package/dist/subpaths/withResize.js +1 -2
- package/dist/subpaths/withScroll.js +1 -2
- package/dist/subpaths/withScrollProgress.js +1 -2
- package/dist/subpaths/write.js +1 -2
- package/dist/swap.d.ts +0 -2
- package/dist/swap.js +1 -2
- package/dist/test/index.d.ts +0 -2
- package/dist/test/index.js +1 -2
- package/dist/utils/deepmerge.d.ts +0 -2
- package/dist/utils/deepmerge.js +1 -2
- package/dist/utils/dom.d.ts +0 -2
- package/dist/utils/dom.js +1 -2
- package/dist/utils/easings.d.ts +0 -2
- package/dist/utils/easings.js +1 -2
- package/dist/utils/focus.d.ts +0 -2
- package/dist/utils/focus.js +1 -2
- package/dist/utils/history.d.ts +0 -2
- package/dist/utils/history.js +1 -2
- package/dist/utils/is.d.ts +0 -2
- package/dist/utils/is.js +1 -2
- package/dist/utils/load.d.ts +0 -2
- package/dist/utils/load.js +1 -2
- package/dist/utils/maths.d.ts +0 -2
- package/dist/utils/maths.js +1 -2
- package/dist/utils/memo.d.ts +0 -2
- package/dist/utils/memo.js +1 -2
- package/dist/utils/noop.d.ts +0 -2
- package/dist/utils/noop.js +1 -2
- package/dist/utils/random.d.ts +0 -2
- package/dist/utils/random.js +1 -2
- package/dist/utils/scroll-lock.d.ts +0 -2
- package/dist/utils/scroll-lock.js +1 -2
- package/dist/utils/scrollTo.d.ts +0 -2
- package/dist/utils/scrollTo.js +1 -2
- package/dist/utils/selectors.d.ts +0 -2
- package/dist/utils/selectors.js +1 -2
- package/dist/utils/smoothTo.d.ts +0 -2
- package/dist/utils/smoothTo.js +1 -2
- package/dist/utils/strings.d.ts +0 -2
- package/dist/utils/strings.js +1 -2
- package/dist/utils/timing.d.ts +0 -2
- package/dist/utils/timing.js +1 -2
- package/dist/utils/transform.d.ts +0 -2
- package/dist/utils/transform.js +1 -2
- package/dist/utils/transition.d.ts +0 -2
- package/dist/utils/transition.js +1 -2
- package/dist/viewTransition.d.ts +0 -2
- package/dist/viewTransition.js +1 -2
- package/package.json +6 -3
- package/skills/studiometa-js-toolkit/SKILL.md +87 -0
- package/skills/studiometa-js-toolkit/references/api/configuration.md +169 -0
- package/skills/studiometa-js-toolkit/references/api/context/createContext.md +46 -0
- package/skills/studiometa-js-toolkit/references/api/context/createGroup.md +67 -0
- package/skills/studiometa-js-toolkit/references/api/context/index.md +69 -0
- package/skills/studiometa-js-toolkit/references/api/context/injectContext.md +58 -0
- package/skills/studiometa-js-toolkit/references/api/context/injectContextSync.md +44 -0
- package/skills/studiometa-js-toolkit/references/api/context/provideContext.md +61 -0
- package/skills/studiometa-js-toolkit/references/api/context/provideRootContext.md +42 -0
- package/skills/studiometa-js-toolkit/references/api/context/signal.md +85 -0
- package/skills/studiometa-js-toolkit/references/api/context/subscribeContext.md +71 -0
- package/skills/studiometa-js-toolkit/references/api/decorators/children.md +92 -0
- package/skills/studiometa-js-toolkit/references/api/decorators/component.md +75 -0
- package/skills/studiometa-js-toolkit/references/api/decorators/index.md +41 -0
- package/skills/studiometa-js-toolkit/references/api/decorators/inject.md +73 -0
- package/skills/studiometa-js-toolkit/references/api/decorators/on.md +149 -0
- package/skills/studiometa-js-toolkit/references/api/decorators/provide.md +77 -0
- package/skills/studiometa-js-toolkit/references/api/decorators/read-write.md +93 -0
- package/skills/studiometa-js-toolkit/references/api/diagnostics/DIAGNOSTICS.md +137 -0
- package/skills/studiometa-js-toolkit/references/api/diagnostics/EVENTS.md +45 -0
- package/skills/studiometa-js-toolkit/references/api/diagnostics/index.md +58 -0
- package/skills/studiometa-js-toolkit/references/api/diagnostics/reportDiagnostic.md +67 -0
- package/skills/studiometa-js-toolkit/references/api/diagnostics/warn.md +54 -0
- package/skills/studiometa-js-toolkit/references/api/dom/breakpoints.md +81 -0
- package/skills/studiometa-js-toolkit/references/api/dom/domUpdate.md +70 -0
- package/skills/studiometa-js-toolkit/references/api/dom/emitExtendable.md +68 -0
- package/skills/studiometa-js-toolkit/references/api/dom/index.md +26 -0
- package/skills/studiometa-js-toolkit/references/api/dom/swap.md +105 -0
- package/skills/studiometa-js-toolkit/references/api/dom/watchAttributeNamespace.md +96 -0
- package/skills/studiometa-js-toolkit/references/api/dom/watchAttributes.md +56 -0
- package/skills/studiometa-js-toolkit/references/api/dom/whenDOMSettled.md +41 -0
- package/skills/studiometa-js-toolkit/references/api/html/data-component.md +105 -0
- package/skills/studiometa-js-toolkit/references/api/html/data-mount.md +69 -0
- package/skills/studiometa-js-toolkit/references/api/html/data-option.md +106 -0
- package/skills/studiometa-js-toolkit/references/api/html/data-ref.md +63 -0
- package/skills/studiometa-js-toolkit/references/api/html/index.md +32 -0
- package/skills/studiometa-js-toolkit/references/api/index.md +73 -0
- package/skills/studiometa-js-toolkit/references/api/instance-events.md +75 -0
- package/skills/studiometa-js-toolkit/references/api/instance-methods.md +267 -0
- package/skills/studiometa-js-toolkit/references/api/instance-properties.md +90 -0
- package/skills/studiometa-js-toolkit/references/api/methods-hooks-events.md +149 -0
- package/skills/studiometa-js-toolkit/references/api/methods-hooks-lifecycle.md +90 -0
- package/skills/studiometa-js-toolkit/references/api/methods-hooks-options.md +96 -0
- package/skills/studiometa-js-toolkit/references/api/methods-hooks-services.md +164 -0
- package/skills/studiometa-js-toolkit/references/api/registry/defineManifest.md +57 -0
- package/skills/studiometa-js-toolkit/references/api/registry/fromMetaGlob.md +33 -0
- package/skills/studiometa-js-toolkit/references/api/registry/fromWebpackContext.md +37 -0
- package/skills/studiometa-js-toolkit/references/api/registry/getInstance.md +52 -0
- package/skills/studiometa-js-toolkit/references/api/registry/getInstances.md +48 -0
- package/skills/studiometa-js-toolkit/references/api/registry/getMountedInstances.md +39 -0
- package/skills/studiometa-js-toolkit/references/api/registry/getUnmountedInstances.md +46 -0
- package/skills/studiometa-js-toolkit/references/api/registry/index.md +49 -0
- package/skills/studiometa-js-toolkit/references/api/registry/registerComponent.md +93 -0
- package/skills/studiometa-js-toolkit/references/api/registry/registerComponents.md +37 -0
- package/skills/studiometa-js-toolkit/references/api/registry/registerManifest.md +72 -0
- package/skills/studiometa-js-toolkit/references/api/scheduler/defaultScheduler.md +104 -0
- package/skills/studiometa-js-toolkit/references/api/scheduler/index.md +27 -0
- package/skills/studiometa-js-toolkit/references/api/scheduler/nextFrame.md +31 -0
- package/skills/studiometa-js-toolkit/references/api/scheduler/viewTransition.md +53 -0
- package/skills/studiometa-js-toolkit/references/api/services/createService.md +95 -0
- package/skills/studiometa-js-toolkit/references/api/services/createServiceMixin.md +81 -0
- package/skills/studiometa-js-toolkit/references/api/services/index.md +94 -0
- package/skills/studiometa-js-toolkit/references/api/services/mixins.md +148 -0
- package/skills/studiometa-js-toolkit/references/api/services/perTarget.md +65 -0
- package/skills/studiometa-js-toolkit/references/api/services/toggle.md +80 -0
- package/skills/studiometa-js-toolkit/references/api/services/until.md +44 -0
- package/skills/studiometa-js-toolkit/references/api/services/useBreakpoint.md +42 -0
- package/skills/studiometa-js-toolkit/references/api/services/useDrag.md +119 -0
- package/skills/studiometa-js-toolkit/references/api/services/useInView.md +64 -0
- package/skills/studiometa-js-toolkit/references/api/services/useKey.md +105 -0
- package/skills/studiometa-js-toolkit/references/api/services/useMediaQuery.md +45 -0
- package/skills/studiometa-js-toolkit/references/api/services/useMutation.md +69 -0
- package/skills/studiometa-js-toolkit/references/api/services/usePointer.md +91 -0
- package/skills/studiometa-js-toolkit/references/api/services/usePrefersReducedMotion.md +42 -0
- package/skills/studiometa-js-toolkit/references/api/services/useRaf.md +91 -0
- package/skills/studiometa-js-toolkit/references/api/services/useResize.md +60 -0
- package/skills/studiometa-js-toolkit/references/api/services/useScroll.md +88 -0
- package/skills/studiometa-js-toolkit/references/api/services/useScrollProgress.md +88 -0
- package/skills/studiometa-js-toolkit/references/api/services/useWindowScroll.md +25 -0
- package/skills/studiometa-js-toolkit/references/api/services/useWindowSize.md +25 -0
- package/skills/studiometa-js-toolkit/references/api/storage/createStorage.md +126 -0
- package/skills/studiometa-js-toolkit/references/api/storage/index.md +33 -0
- package/skills/studiometa-js-toolkit/references/api/storage/presets.md +58 -0
- package/skills/studiometa-js-toolkit/references/api/storage/providers.md +109 -0
- package/skills/studiometa-js-toolkit/references/api/test/index.md +214 -0
- package/skills/studiometa-js-toolkit/references/guide/concepts/attribute-grammar.md +93 -0
- package/skills/studiometa-js-toolkit/references/guide/concepts/mutation-engine.md +71 -0
- package/skills/studiometa-js-toolkit/references/guide/concepts/philosophy.md +78 -0
- package/skills/studiometa-js-toolkit/references/guide/concepts/the-registry.md +110 -0
- package/skills/studiometa-js-toolkit/references/guide/going-further/autoloading.md +104 -0
- package/skills/studiometa-js-toolkit/references/guide/going-further/handling-diagnostics.md +104 -0
- package/skills/studiometa-js-toolkit/references/guide/going-further/mount-strategies.md +95 -0
- package/skills/studiometa-js-toolkit/references/guide/going-further/scheduling-work.md +124 -0
- package/skills/studiometa-js-toolkit/references/guide/going-further/sharing-state.md +218 -0
- package/skills/studiometa-js-toolkit/references/guide/going-further/swapping-content.md +92 -0
- package/skills/studiometa-js-toolkit/references/guide/going-further/testing-components.md +137 -0
- package/skills/studiometa-js-toolkit/references/guide/going-further/typing-components.md +190 -0
- package/skills/studiometa-js-toolkit/references/guide/going-further/using-decorators.md +168 -0
- package/skills/studiometa-js-toolkit/references/guide/going-further/using-storage.md +125 -0
- package/skills/studiometa-js-toolkit/references/guide/index.md +163 -0
- package/skills/studiometa-js-toolkit/references/guide/introduction/installation.md +144 -0
- package/skills/studiometa-js-toolkit/references/guide/introduction/lifecycle-hooks.md +174 -0
- package/skills/studiometa-js-toolkit/references/guide/introduction/managing-components.md +229 -0
- package/skills/studiometa-js-toolkit/references/guide/introduction/managing-options.md +235 -0
- package/skills/studiometa-js-toolkit/references/guide/introduction/managing-refs.md +174 -0
- package/skills/studiometa-js-toolkit/references/guide/introduction/using-services.md +218 -0
- package/skills/studiometa-js-toolkit/references/guide/introduction/working-with-events.md +251 -0
- package/skills/studiometa-js-toolkit/references/guide/migration/v3-to-v4.md +373 -0
- package/skills/studiometa-js-toolkit/references/utils/css.md +98 -0
- package/skills/studiometa-js-toolkit/references/utils/dom.md +54 -0
- package/skills/studiometa-js-toolkit/references/utils/easings.md +217 -0
- package/skills/studiometa-js-toolkit/references/utils/focus.md +84 -0
- package/skills/studiometa-js-toolkit/references/utils/history.md +69 -0
- package/skills/studiometa-js-toolkit/references/utils/index.md +53 -0
- package/skills/studiometa-js-toolkit/references/utils/is.md +84 -0
- package/skills/studiometa-js-toolkit/references/utils/load.md +59 -0
- package/skills/studiometa-js-toolkit/references/utils/math.md +129 -0
- package/skills/studiometa-js-toolkit/references/utils/motion.md +218 -0
- package/skills/studiometa-js-toolkit/references/utils/objects.md +68 -0
- package/skills/studiometa-js-toolkit/references/utils/scroll.md +128 -0
- package/skills/studiometa-js-toolkit/references/utils/strings.md +176 -0
- package/skills/studiometa-js-toolkit/references/utils/timing.md +111 -0
- package/skills/studiometa-js-toolkit/references/utils/transitions.md +122 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# subscribeContext
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
subscribeContext<T>(el: Element, key: ContextKey<T>, onProvide: ContextCallback<T>): () => void
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
The subscription behaviour of the WICG context protocol: **every** answer, as providers come and go.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { Base, createContext, subscribeContext } from '@studiometa/js-toolkit';
|
|
13
|
+
|
|
14
|
+
interface GroupApi {
|
|
15
|
+
join(peer: Base): () => void;
|
|
16
|
+
}
|
|
17
|
+
const DisclosureGroupContext = createContext<GroupApi>('disclosure-group');
|
|
18
|
+
class Disclosure extends Base {
|
|
19
|
+
static config = { name: 'Disclosure' };
|
|
20
|
+
|
|
21
|
+
group?: GroupApi;
|
|
22
|
+
|
|
23
|
+
mounted() {
|
|
24
|
+
return subscribeContext(this.$el, DisclosureGroupContext, (group) => {
|
|
25
|
+
this.group = group;
|
|
26
|
+
const leave = group.join(this);
|
|
27
|
+
|
|
28
|
+
// The teardown for *this* value.
|
|
29
|
+
return () => {
|
|
30
|
+
leave();
|
|
31
|
+
this.group = undefined;
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Parameters**
|
|
39
|
+
|
|
40
|
+
- `onProvide` — **required**. It runs synchronously for each answer and receives the value and the same unsubscribe function the helper returns.
|
|
41
|
+
|
|
42
|
+
**Return value**
|
|
43
|
+
|
|
44
|
+
- the unsubscribe function. Call it from `mounted()`'s return value to get an unmount-scoped lifetime.
|
|
45
|
+
|
|
46
|
+
## A new answer replaces; it never accumulates
|
|
47
|
+
|
|
48
|
+
The callback can return a teardown for the value it received. That teardown runs:
|
|
49
|
+
|
|
50
|
+
- before the next **different** value;
|
|
51
|
+
- on unsubscribe.
|
|
52
|
+
|
|
53
|
+
**An identical value is not an answer**, so nothing runs and nothing is torn down.
|
|
54
|
+
|
|
55
|
+
That is what lets a member move between groups correctly: `join()` returns its own `leave`, the teardown calls it, and a member that moves to a nearer group leaves the old one first.
|
|
56
|
+
|
|
57
|
+
## When it fires
|
|
58
|
+
|
|
59
|
+
**The trigger is the mount announcement**, not a broadcast from the provider, and it runs after `mounted()`.
|
|
60
|
+
|
|
61
|
+
The optional `context-subscription` module keeps **one** listener on the document, attached on the first subscription and never at import time.
|
|
62
|
+
|
|
63
|
+
Two `contains()` calls bound the cost per mount: the new provider must contain the consumer, and it must sit inside the provider that answers it now. **A mount that changes nothing checks nothing.**
|
|
64
|
+
|
|
65
|
+
## What it holds
|
|
66
|
+
|
|
67
|
+
**The registry holds nothing.** A subscription is anchored on its consumer element through a `WeakMap`, and the iterable index holds `WeakRef`s that the sweep prunes.
|
|
68
|
+
|
|
69
|
+
Callback and teardown failures are isolated — `callback.context-subscription-failed` and `callback.context-teardown-failed` — so one consumer cannot stop the shared sweep.
|
|
70
|
+
|
|
71
|
+
`context.ts` and the `Base` graph import **none** of this optional state, so a page that never subscribes pays for none of it.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# @children
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
children<T extends Base>(name: string, callbacks?: WatchChildrenCallbacks<T>): ValueDecorator<ChildrenCollection<T>>
|
|
5
|
+
children<T extends BaseConstructor>(ComponentClass: T, callbacks?: WatchChildrenCallbacks<InstanceType<T>>): ValueDecorator<ChildrenCollection<InstanceType<T>>>
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
Field sugar over [`$watchChildren()`](../instance-methods.md#watchchildren).
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { Base, children, component, type ChildrenCollection } from '@studiometa/js-toolkit';
|
|
14
|
+
|
|
15
|
+
class SliderItem extends Base {
|
|
16
|
+
static config = { name: 'SliderItem' };
|
|
17
|
+
}
|
|
18
|
+
@component({ name: 'Slider', components: { SliderItem } })
|
|
19
|
+
class Slider extends Base {
|
|
20
|
+
// Exact `config.name`.
|
|
21
|
+
@children('SliderItem')
|
|
22
|
+
items!: ChildrenCollection<Base>;
|
|
23
|
+
|
|
24
|
+
// Also every named subclass, through `instanceof`.
|
|
25
|
+
@children(SliderItem)
|
|
26
|
+
allItems!: ChildrenCollection<SliderItem>;
|
|
27
|
+
|
|
28
|
+
reset() {
|
|
29
|
+
for (const item of this.items) {
|
|
30
|
+
item.$el.removeAttribute('data-option-active');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The collection is **live**, in document order whatever the mount order is.
|
|
37
|
+
|
|
38
|
+
## Callbacks
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
import { Base, children, component, type ChildrenCollection } from '@studiometa/js-toolkit';
|
|
42
|
+
|
|
43
|
+
class SliderItem extends Base {
|
|
44
|
+
static config = { name: 'SliderItem' };
|
|
45
|
+
}
|
|
46
|
+
@component({ name: 'Slider', components: { SliderItem } })
|
|
47
|
+
class Slider extends Base {
|
|
48
|
+
@children(SliderItem, {
|
|
49
|
+
added(item) {
|
|
50
|
+
// `this` is the Slider instance.
|
|
51
|
+
this.reindex();
|
|
52
|
+
},
|
|
53
|
+
removed(item) {
|
|
54
|
+
this.reindex();
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
items!: ChildrenCollection<SliderItem>;
|
|
58
|
+
|
|
59
|
+
reindex() {}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**The callbacks are bound to the instance**, which is the one thing this form gives over the function form.
|
|
64
|
+
|
|
65
|
+
## It is instance-scoped
|
|
66
|
+
|
|
67
|
+
The subscription stays active through unmount and mount cycles, for the whole life of the watching instance. It is never released and dies with the element.
|
|
68
|
+
|
|
69
|
+
The initial sweep is deferred to a microtask, because a field initializer runs before the element is in place; the announcement listeners attach at once, so nothing is missed.
|
|
70
|
+
|
|
71
|
+
## The function form
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
import { Base } from '@studiometa/js-toolkit';
|
|
75
|
+
|
|
76
|
+
class SliderItem extends Base {
|
|
77
|
+
static config = { name: 'SliderItem' };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
class Slider extends Base {
|
|
81
|
+
static config = { name: 'Slider', components: { SliderItem } };
|
|
82
|
+
|
|
83
|
+
items = this.$watchChildren(SliderItem, {
|
|
84
|
+
added: (item) => this.reindex(),
|
|
85
|
+
removed: (item) => this.reindex(),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
reindex() {}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Identical behaviour, no build step. Note the arrow functions: the function form does not bind the callbacks for you.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# @component
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
component(config: BaseConfig): (value, context) => void
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Writes `static config` and calls [`registerComponent()`](../registry/registerComponent.md), in one step.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { Base, component } from '@studiometa/js-toolkit';
|
|
13
|
+
|
|
14
|
+
@component({
|
|
15
|
+
name: 'Slider',
|
|
16
|
+
refs: ['next', 'items[]'],
|
|
17
|
+
options: { speed: { type: Number, default: 1 } },
|
|
18
|
+
})
|
|
19
|
+
class Slider extends Base {
|
|
20
|
+
onNextClick() {}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The class is registered **as soon as it is defined**, so there is no separate registration line to forget.
|
|
25
|
+
|
|
26
|
+
## It merges with `static config`
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { Base, component } from '@studiometa/js-toolkit';
|
|
30
|
+
|
|
31
|
+
@component({ name: 'Slider', refs: ['next'] })
|
|
32
|
+
class Slider extends Base {
|
|
33
|
+
static config = { name: 'Slider', options: { speed: Number } };
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
They merge in a **class initializer**, which runs after the fields and inside the class definition, so `registerComponent()` on the next line reads the finished config.
|
|
38
|
+
|
|
39
|
+
The rules are the rules of `$config`:
|
|
40
|
+
|
|
41
|
+
| Key | Merge rule |
|
|
42
|
+
| ----------------------- | -------------- |
|
|
43
|
+
| `refs` | union |
|
|
44
|
+
| `options`, `components` | entry by entry |
|
|
45
|
+
| a declared scalar | overrides |
|
|
46
|
+
|
|
47
|
+
A key both sides declare **differently** is reported as `component.config-conflict`.
|
|
48
|
+
|
|
49
|
+
## It is applied last
|
|
50
|
+
|
|
51
|
+
Among stacked class decorators, `@component` is applied last, so it registers a finished class. That is what lets a service mixin decorator sit under it:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { Base, component, withScroll } from '@studiometa/js-toolkit';
|
|
55
|
+
|
|
56
|
+
@component({ name: 'Header' })
|
|
57
|
+
@withScroll()
|
|
58
|
+
class Header extends Base {
|
|
59
|
+
scrolled() {}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## The function form
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
import { Base, registerComponent } from '@studiometa/js-toolkit';
|
|
67
|
+
|
|
68
|
+
class Slider extends Base {
|
|
69
|
+
static config = { name: 'Slider', refs: ['next'] };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
registerComponent(Slider);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Identical behaviour, no build step.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Decorators
|
|
2
|
+
|
|
3
|
+
**Sugar, never a requirement.** No engine ships stage-3 decorators, so every decorator here is a thin wrapper over a function API that works without it.
|
|
4
|
+
|
|
5
|
+
| Decorator | Wraps |
|
|
6
|
+
| ------------------------------------------------ | --------------------------------------- |
|
|
7
|
+
| [`@component(config)`](component.md) | `static config` + `registerComponent()` |
|
|
8
|
+
| [`@on(target, type)`](on.md) | the `on<Child><Event>` names |
|
|
9
|
+
| [`@provide(key)`](provide.md) | `$provide()` |
|
|
10
|
+
| [`@inject(key)`](inject.md) | `$inject()` |
|
|
11
|
+
| [`@children(nameOrClass, cb?)`](children.md) | `$watchChildren()` |
|
|
12
|
+
| [`@read` / `@write`](read-write.md) | `$read()` / `$write()` |
|
|
13
|
+
|
|
14
|
+
The service mixins have a decorator form too — see [Mixins](../services/mixins.md).
|
|
15
|
+
|
|
16
|
+
## A page with no build step keeps everything
|
|
17
|
+
|
|
18
|
+
`registerComponent`, `$provide`, `$watchChildren`, `$read`, `$write` and the `on<Child><Event>` method names are all there is. A page loaded from an ESM CDN uses the same framework with none of this file's contents.
|
|
19
|
+
|
|
20
|
+
## Each value decorator works on a plain field or an `accessor`
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { Base, component, inject, createContext } from '@studiometa/js-toolkit';
|
|
24
|
+
|
|
25
|
+
const Key = createContext<number>('key');
|
|
26
|
+
@component({ name: 'Demo' })
|
|
27
|
+
class Demo extends Base {
|
|
28
|
+
@inject(Key) a?: number;
|
|
29
|
+
@inject(Key) accessor b: number | undefined;
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Build setup
|
|
34
|
+
|
|
35
|
+
Vite 8 transforms TypeScript with Oxc, which passes decorators through untouched, so a transform has to compile them. TypeScript 5 needs `experimentalDecorators: false`. See [Installation](../../guide/introduction/installation.md#with-a-build-step).
|
|
36
|
+
|
|
37
|
+
The package itself compiles them with `@rollup/plugin-swc` and `decoratorVersion: '2023-11'`, filtered to the files that contain a decorator.
|
|
38
|
+
|
|
39
|
+
## Read next
|
|
40
|
+
|
|
41
|
+
[Decorators](../../guide/going-further/using-decorators.md) walks the whole set, including how they stack and why the phase decorators are leaf-method sugar.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# @inject
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
inject<T>(key: ContextKey<T>): ValueObserver<T | undefined>
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Field sugar over [`$inject()`](../instance-methods.md#inject). **It asks once, at construction.**
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { Base, component, createContext, inject, type Signal } from '@studiometa/js-toolkit';
|
|
13
|
+
|
|
14
|
+
const CountContext = createContext<Signal<number>>('count');
|
|
15
|
+
@component({ name: 'Output' })
|
|
16
|
+
class Output extends Base {
|
|
17
|
+
@inject(CountContext)
|
|
18
|
+
count?: Signal<number>;
|
|
19
|
+
|
|
20
|
+
mounted() {
|
|
21
|
+
// The request may not have been answered yet.
|
|
22
|
+
return this.count?.subscribe((value) => {
|
|
23
|
+
this.$el.textContent = String(value);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The field type includes `undefined`, because the request is asynchronous and the value lands when a provider answers.
|
|
30
|
+
|
|
31
|
+
## When to use it, and when not
|
|
32
|
+
|
|
33
|
+
| Situation | Reach for |
|
|
34
|
+
| -------------------------------------------------------------- | ---------------------------------------------------------- |
|
|
35
|
+
| the value is there for the whole life of the instance | `@inject` |
|
|
36
|
+
| the consumer must be able to wait through several mount cycles | `$inject()` from `mounted()` |
|
|
37
|
+
| the answer is optional and there is a fallback | `$injectSync()` |
|
|
38
|
+
| the provider comes and goes | [`subscribeContext()`](../context/subscribeContext.md) |
|
|
39
|
+
|
|
40
|
+
**`@inject` asks once, at construction.** `$inject()` from `mounted()` is unmount-scoped: `$unmount()` cancels the pending request, and a new mount asks again. That difference is the whole reason both exist.
|
|
41
|
+
|
|
42
|
+
## A plain field or an `accessor`
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { Base, component, createContext, inject, type Signal } from '@studiometa/js-toolkit';
|
|
46
|
+
|
|
47
|
+
const CountContext = createContext<Signal<number>>('count');
|
|
48
|
+
@component({ name: 'Output' })
|
|
49
|
+
class Output extends Base {
|
|
50
|
+
@inject(CountContext) a?: Signal<number>;
|
|
51
|
+
@inject(CountContext) accessor b: Signal<number> | undefined;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## The function form
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { Base, createContext, type Signal } from '@studiometa/js-toolkit';
|
|
59
|
+
|
|
60
|
+
const CountContext = createContext<Signal<number>>('count');
|
|
61
|
+
class Output extends Base {
|
|
62
|
+
static config = { name: 'Output' };
|
|
63
|
+
|
|
64
|
+
async mounted() {
|
|
65
|
+
const count = await this.$inject(CountContext);
|
|
66
|
+
return count.subscribe((value) => {
|
|
67
|
+
this.$el.textContent = String(value);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The `await` form has no `undefined` to handle, which is usually the better trade.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# @on
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
on(type: string)
|
|
5
|
+
on(target: typeof window | typeof document, type: string)
|
|
6
|
+
on(child: BaseConstructor | string, type: string)
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Binds a method to an event source, in place of the `on<X><Event>` naming convention.
|
|
10
|
+
|
|
11
|
+
## Every form
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import {
|
|
15
|
+
Base,
|
|
16
|
+
component,
|
|
17
|
+
on,
|
|
18
|
+
type DelegatedEvent,
|
|
19
|
+
type GlobalEvent,
|
|
20
|
+
type RefEvent,
|
|
21
|
+
} from '@studiometa/js-toolkit';
|
|
22
|
+
|
|
23
|
+
class AccordionItem extends Base<{ $emits: { open: { height: number } } }> {
|
|
24
|
+
static config = { name: 'AccordionItem' };
|
|
25
|
+
}
|
|
26
|
+
@component({ name: 'Demo', components: { AccordionItem }, refs: ['dots[]'] })
|
|
27
|
+
class Demo extends Base {
|
|
28
|
+
// The component's own element, typed from HTMLElementEventMap.
|
|
29
|
+
@on('click') a(event: MouseEvent) {}
|
|
30
|
+
@on('submit') b(event: SubmitEvent) {}
|
|
31
|
+
|
|
32
|
+
// A ref, named as it is declared.
|
|
33
|
+
@on('dots[]', 'click') c({ index }: RefEvent) {}
|
|
34
|
+
|
|
35
|
+
// A child, by name — imports nothing, and the payload stays `unknown`.
|
|
36
|
+
@on('AccordionItem', 'open') d({ payload }: DelegatedEvent<AccordionItem>) {}
|
|
37
|
+
|
|
38
|
+
// A child, by class — the class is the type, so the payload is typed.
|
|
39
|
+
@on(AccordionItem, 'open') e({ payload }: DelegatedEvent<AccordionItem, 'open'>) {}
|
|
40
|
+
|
|
41
|
+
// A global.
|
|
42
|
+
@on(window, 'resize') f({ event }: GlobalEvent<UIEvent>) {}
|
|
43
|
+
@on(document, 'click') g({ event }: GlobalEvent<MouseEvent>) {}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## The one-argument form
|
|
48
|
+
|
|
49
|
+
It types its event from `HTMLElementEventMap`, so `@on('click')` hands over a `MouseEvent` and `@on('submit')` a `SubmitEvent`.
|
|
50
|
+
|
|
51
|
+
A name **outside** that map is a component event, whose detail only its emitter knows, so the handler declares the type it expects:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { Base, component, on } from '@studiometa/js-toolkit';
|
|
55
|
+
@component({ name: 'Slot' })
|
|
56
|
+
class Slot extends Base {
|
|
57
|
+
@on('content')
|
|
58
|
+
inject(event: CustomEvent<{ content: string }>) {
|
|
59
|
+
this.$el.innerHTML = event.detail.content;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## A name is a child or a ref
|
|
65
|
+
|
|
66
|
+
Resolved **children-first**, so the handler is typed as `DelegatedEvent` or `RefEvent`.
|
|
67
|
+
|
|
68
|
+
A **ref is named as it is declared**: `@on('dots[]', 'click')` for `config.refs: ['dots[]']`. The rule is one rule — the declaration spelling refers to the entry, and the property spelling is used where a name is derived from it.
|
|
69
|
+
|
|
70
|
+
A mismatched `@on('dots', 'click')` gives a warning at bind time when the other spelling is declared. A name that matches nothing stays **silent**.
|
|
71
|
+
|
|
72
|
+
## A class resolves to its merged `config.name`
|
|
73
|
+
|
|
74
|
+
It lands on the same delegated entry as the string form, so the two behave identically **at runtime**. They differ in what they can type:
|
|
75
|
+
|
|
76
|
+
| Form | `target` | `payload` |
|
|
77
|
+
| ------------------------------ | --------------- | ----------------------- |
|
|
78
|
+
| `@on(AccordionItem, 'open')` | `AccordionItem` | typed from its `$emits` |
|
|
79
|
+
| `@on('AccordionItem', 'open')` | the annotation | `unknown` |
|
|
80
|
+
|
|
81
|
+
**Only the class form carries the payload type**, because only it has the class to read `$emits` from. The string form's event name is a plain `string` as far as the type system is concerned, so annotate it as `DelegatedEvent<AccordionItem>` and narrow the payload yourself:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { Base, component, on, type DelegatedEvent } from '@studiometa/js-toolkit';
|
|
85
|
+
|
|
86
|
+
class AccordionItem extends Base<{ $emits: { open: { height: number } } }> {
|
|
87
|
+
static config = { name: 'AccordionItem' };
|
|
88
|
+
}
|
|
89
|
+
@component({ name: 'Accordion', components: { AccordionItem } })
|
|
90
|
+
class Accordion extends Base {
|
|
91
|
+
@on('AccordionItem', 'open')
|
|
92
|
+
byName({ payload }: DelegatedEvent<AccordionItem>) {
|
|
93
|
+
(payload as { height: number }).height;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@on(AccordionItem, 'open')
|
|
97
|
+
byClass({ payload }: DelegatedEvent<AccordionItem, 'open'>) {
|
|
98
|
+
payload.height; // number, with no cast
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**A lazy child needs the string form**
|
|
104
|
+
|
|
105
|
+
`@on('Child', 'open')` imports nothing. **A thunk is not a target**, and both the overloads and the runtime refuse it — so a lazy child is exactly the case that trades the typed payload for the deferred import.
|
|
106
|
+
|
|
107
|
+
## Globals
|
|
108
|
+
|
|
109
|
+
`@on(window, 'click')` types the event from `WindowEventMap` and falls back to `Event`. It goes through the same binding `onWindow<Event>` uses: **bubble phase, one listener per mount cycle, removed by `$unmount()`**.
|
|
110
|
+
|
|
111
|
+
**Nothing is reserved in its string space.** `@on('Window', 'resize')` means the child named `Window`; `@on(window, 'resize')` means the global. That is the escape from the reserved `onWindow` prefix.
|
|
112
|
+
|
|
113
|
+
## Any other `EventTarget` is refused
|
|
114
|
+
|
|
115
|
+
By the overloads, and by a `TypeError` at runtime. A decorator is evaluated once, at class definition, so an arbitrary target could only ever be a module-scope value — and binding a component's lifetime to one would be a leak with no way to see it.
|
|
116
|
+
|
|
117
|
+
## It checks the annotation; it does not replace it
|
|
118
|
+
|
|
119
|
+
A decorator cannot infer a method's own parameters: the method signature is checked **against** what the decorator expects. So annotate the payload either way — with `@on`, the annotation is verified against a real target instead of being taken on trust.
|
|
120
|
+
|
|
121
|
+
## Stacking
|
|
122
|
+
|
|
123
|
+
The skip is keyed by the **method name**, so `@on` stacks with itself and with `@read`/`@write` in either order:
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
import { Base, component, on, write } from '@studiometa/js-toolkit';
|
|
127
|
+
|
|
128
|
+
class Child extends Base {
|
|
129
|
+
static config = { name: 'Child' };
|
|
130
|
+
}
|
|
131
|
+
@component({ name: 'Demo', components: { Child } })
|
|
132
|
+
class Demo extends Base {
|
|
133
|
+
// One method, two events.
|
|
134
|
+
@on('Child', 'open')
|
|
135
|
+
@on('Child', 'close')
|
|
136
|
+
track() {}
|
|
137
|
+
|
|
138
|
+
// A phase decorator nearest the method schedules the handler's body.
|
|
139
|
+
@on('click')
|
|
140
|
+
@write
|
|
141
|
+
paint() {}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
See [`@read` / `@write`](read-write.md).
|
|
146
|
+
|
|
147
|
+
## The function form
|
|
148
|
+
|
|
149
|
+
The `on<X><Event>` method names. Identical behaviour, no build step. See [Events hooks](../methods-hooks-events.md).
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# @provide
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
provide<T>(key: ContextKey<T>): ValueDecorator<T>
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Field sugar over [`$provide()`](../instance-methods.md#provide).
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import {
|
|
13
|
+
Base,
|
|
14
|
+
component,
|
|
15
|
+
createContext,
|
|
16
|
+
provide,
|
|
17
|
+
signal,
|
|
18
|
+
type Signal,
|
|
19
|
+
} from '@studiometa/js-toolkit';
|
|
20
|
+
|
|
21
|
+
const CountContext = createContext<Signal<number>>('count');
|
|
22
|
+
@component({ name: 'Counter' })
|
|
23
|
+
class Counter extends Base {
|
|
24
|
+
@provide(CountContext)
|
|
25
|
+
count = signal(0);
|
|
26
|
+
|
|
27
|
+
increment() {
|
|
28
|
+
this.count.value += 1;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The field's value is provided to the subtree, **as it is**. Nothing is wrapped, so the type of the key is the contract from end to end.
|
|
34
|
+
|
|
35
|
+
## It is instance-scoped
|
|
36
|
+
|
|
37
|
+
Like `$provide()`, it is never released and dies with the element. A component whose declaration is withdrawn keeps providing until its element goes.
|
|
38
|
+
|
|
39
|
+
## A plain field or an `accessor`
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import {
|
|
43
|
+
Base,
|
|
44
|
+
component,
|
|
45
|
+
createContext,
|
|
46
|
+
provide,
|
|
47
|
+
signal,
|
|
48
|
+
type Signal,
|
|
49
|
+
} from '@studiometa/js-toolkit';
|
|
50
|
+
|
|
51
|
+
const CountContext = createContext<Signal<number>>('count');
|
|
52
|
+
@component({ name: 'Counter' })
|
|
53
|
+
class Counter extends Base {
|
|
54
|
+
@provide(CountContext) a = signal(0);
|
|
55
|
+
@provide(CountContext) accessor b = signal(0);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## The function form
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { Base, createContext, signal, type Signal } from '@studiometa/js-toolkit';
|
|
63
|
+
|
|
64
|
+
const CountContext = createContext<Signal<number>>('count');
|
|
65
|
+
class Counter extends Base {
|
|
66
|
+
static config = { name: 'Counter' };
|
|
67
|
+
|
|
68
|
+
count = this.$provide(CountContext, signal(0));
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Identical behaviour, no build step — and `$provide()` returns the value, which is why the field initializer reads the same way.
|
|
73
|
+
|
|
74
|
+
## See also
|
|
75
|
+
|
|
76
|
+
- [`@inject`](inject.md) — the other half
|
|
77
|
+
- [Shared state](../../guide/going-further/sharing-state.md)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @read and @write
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
read: (value: VoidMethod, context: ClassMethodDecoratorContext) => VoidMethod;
|
|
5
|
+
write: (value: VoidMethod, context: ClassMethodDecoratorContext) => VoidMethod;
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
Runs the method body in the frame's `read` or `write` phase, cancelled on unmount. They are sugar over [`$read()`](../instance-methods.md#read-and-write) and `$write()`.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { Base, component, read, write } from '@studiometa/js-toolkit';
|
|
14
|
+
|
|
15
|
+
@component({ name: 'Measure' })
|
|
16
|
+
class Measure extends Base {
|
|
17
|
+
#height = 0;
|
|
18
|
+
|
|
19
|
+
@read
|
|
20
|
+
measure() {
|
|
21
|
+
this.#height = this.$el.scrollHeight;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@write
|
|
25
|
+
apply() {
|
|
26
|
+
this.$el.style.setProperty('--height', `${this.#height}px`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Every read runs before every write, once, before paint. A `read` scheduled from a `write` runs in the **next** frame; a `write` scheduled from a `read` runs in the **same** frame.
|
|
32
|
+
|
|
33
|
+
## They are leaf-method sugar: the phase belongs to the call site
|
|
34
|
+
|
|
35
|
+
**Decorate a method nobody overrides**
|
|
36
|
+
|
|
37
|
+
A phase decorator returns a wrapper around the method it decorates, and that wrapper is a property of **that class**. A subclass that overrides the method defines its own, undecorated, and `this.method()` resolves to it — so the base's scheduling disappears and the body runs in whatever phase the caller was in.
|
|
38
|
+
|
|
39
|
+
A **template method** — a base that schedules work its subclasses implement — schedules at the call site instead:
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
// in the base, where the call is
|
|
43
|
+
state.subscribe((value) => this.$write(() => this.update(value)));
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The alternative, dispatching a decorated method through something a subclass cannot replace, was refused: it would make a decorator's behaviour depend on inheritance depth, which nothing else in v4 does, to buy a convenience no consumer has asked for.
|
|
47
|
+
|
|
48
|
+
## Stacking with `@on`
|
|
49
|
+
|
|
50
|
+
The skip is keyed by the method name, so the two stack in either order — and **the order decides what the listener calls**:
|
|
51
|
+
|
|
52
|
+
| Written | Schedules |
|
|
53
|
+
| ------------------------- | ----------------------- |
|
|
54
|
+
| `@on(...)` above `@write` | the body of the handler |
|
|
55
|
+
| `@write` above `@on(...)` | direct calls only |
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { Base, component, on, write } from '@studiometa/js-toolkit';
|
|
59
|
+
@component({ name: 'Demo' })
|
|
60
|
+
class Demo extends Base {
|
|
61
|
+
@on('click')
|
|
62
|
+
@write
|
|
63
|
+
paint() {}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Write `@read` and `@write` closest to the method body.**
|
|
68
|
+
|
|
69
|
+
## The function form
|
|
70
|
+
|
|
71
|
+
```js
|
|
72
|
+
import { Base } from '@studiometa/js-toolkit';
|
|
73
|
+
|
|
74
|
+
class Measure extends Base {
|
|
75
|
+
static config = { name: 'Measure' };
|
|
76
|
+
|
|
77
|
+
#height = 0;
|
|
78
|
+
|
|
79
|
+
measure() {
|
|
80
|
+
return this.$read(() => {
|
|
81
|
+
this.#height = this.$el.scrollHeight;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
apply() {
|
|
86
|
+
return this.$write(() => {
|
|
87
|
+
this.$el.style.setProperty('--height', `${this.#height}px`);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The function form also gives you the [`ScheduledTask`](../scheduler/defaultScheduler.md) handle — its promise and its `cancel()` — which the decorator discards.
|