@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,49 @@
|
|
|
1
|
+
# Registry
|
|
2
|
+
|
|
3
|
+
The registry is the only code that constructs an instance. It holds one entry per name and one controller per element/component pair.
|
|
4
|
+
|
|
5
|
+
## Registering
|
|
6
|
+
|
|
7
|
+
- [`registerComponent(Ctor)`](registerComponent.md) — one eager entry, and its declared family
|
|
8
|
+
- [`registerComponents(...ctors)`](registerComponents.md) — several at once
|
|
9
|
+
- [`registerManifest(entries)`](registerManifest.md) — lazy entries in the same map
|
|
10
|
+
|
|
11
|
+
## Building a manifest
|
|
12
|
+
|
|
13
|
+
- [`defineManifest(options)`](defineManifest.md) — derive tokens from module paths
|
|
14
|
+
- [`fromMetaGlob(glob)`](fromMetaGlob.md) — a Vite `import.meta.glob` result
|
|
15
|
+
- [`fromWebpackContext(context)`](fromWebpackContext.md) — a webpack context
|
|
16
|
+
|
|
17
|
+
## Looking instances up
|
|
18
|
+
|
|
19
|
+
Four functions answer from the DOM. They keep **no registry of instances**.
|
|
20
|
+
|
|
21
|
+
| Function | Population |
|
|
22
|
+
| --------------------------------------------------------- | ------------------------------------------ |
|
|
23
|
+
| [`getInstances()`](getInstances.md) | every instance that exists, mounted or not |
|
|
24
|
+
| [`getMountedInstances()`](getMountedInstances.md) | the live ones — safe to call a method on |
|
|
25
|
+
| [`getUnmountedInstances()`](getUnmountedInstances.md) | built, then stood down |
|
|
26
|
+
| [`getInstance(el, name)`](getInstance.md) | the one on this element |
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
getMountedInstances('Dialog').forEach((dialog) => dialog.close());
|
|
30
|
+
getInstances('Dialog', section);
|
|
31
|
+
getUnmountedInstances('Dialog');
|
|
32
|
+
getInstance(el, 'Dialog');
|
|
33
|
+
getInstances(el);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The three plural forms take the same two overloads: a **name** with an optional `ParentNode` root, or an **element**.
|
|
37
|
+
|
|
38
|
+
- **A matching element with no instance is skipped, and that is the whole narrowing.** `selectorFor(name)` over-matches on purpose — it lists the responsive spellings of `data-component` too — and the instance-map read removes an inactive declaration, because a breakpoint-withdrawn component is destroyed _and_ deleted from the map.
|
|
39
|
+
- `root` is a `ParentNode` and the call is `querySelectorAll`, so an element root searches its **descendants** and never matches itself.
|
|
40
|
+
- **The element overload is the only form that reaches a detached element**, since `querySelectorAll()` does not see one. Pass the detached root as `root` when a name lookup has to reach inside it.
|
|
41
|
+
- **There is no `getMountedInstance`.** The singular returns one object, so a caller reads `.$isMounted` on it.
|
|
42
|
+
|
|
43
|
+
## In tests
|
|
44
|
+
|
|
45
|
+
`resetRegistry()` is re-exported from [`/test`](../test/index.md) and drops every registration. It is not part of a page's vocabulary.
|
|
46
|
+
|
|
47
|
+
## Read next
|
|
48
|
+
|
|
49
|
+
[The registry](../../guide/concepts/the-registry.md) explains the entry, the controller and the one scheduling algorithm that covers eager, lazy and conditional mounting.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# registerComponent
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
registerComponent(ComponentClass: BaseConstructor): void
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Registers a component and its merged family, then scans the document for matching elements.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import { Base, registerComponent } from '@studiometa/js-toolkit';
|
|
13
|
+
|
|
14
|
+
class Slider extends Base {
|
|
15
|
+
static config = { name: 'Slider' };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
registerComponent(Slider);
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Parameters**
|
|
22
|
+
|
|
23
|
+
- `ComponentClass` — a class extending `Base`, with a `config.name`.
|
|
24
|
+
|
|
25
|
+
**Return value**
|
|
26
|
+
|
|
27
|
+
- `void`. It is a registration, not an instantiation: the elements that match get their instances through the ordinary pipeline, and there is no list of instances to hand back. Use [`getInstances()`](getInstances.md) if you need them.
|
|
28
|
+
|
|
29
|
+
## It registers the family too
|
|
30
|
+
|
|
31
|
+
`config.components` is walked in one loop, so one call covers a whole tree:
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
import { Base, registerComponent } from '@studiometa/js-toolkit';
|
|
35
|
+
|
|
36
|
+
class AccordionItem extends Base {
|
|
37
|
+
static config = { name: 'AccordionItem' };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
class Accordion extends Base {
|
|
41
|
+
static config = {
|
|
42
|
+
name: 'Accordion',
|
|
43
|
+
components: { AccordionItem },
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Registers both.
|
|
48
|
+
registerComponent(Accordion);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
A thunk in `config.components` is **deferred** rather than resolved, and becomes a lazy entry of the same registry under its key. See [Autoloading](../../guide/going-further/autoloading.md).
|
|
52
|
+
|
|
53
|
+
## The name comes from the merged config
|
|
54
|
+
|
|
55
|
+
Like the instance's `$id` and the instance-map key it publishes itself under. A subclass that extends a component with extra config and forgets to rename therefore **collides** with the name it inherited, rather than registering under `undefined`.
|
|
56
|
+
|
|
57
|
+
## One name, one entry
|
|
58
|
+
|
|
59
|
+
As with `customElements.define()`. A second registration under a name already taken gives a `registry.conflict` warning and is ignored.
|
|
60
|
+
|
|
61
|
+
The exception is a lazy child declared by several parents: that is the normal case, and it is **first wins, quietly**. A token two components genuinely claim is caught by the class-name check when the import lands.
|
|
62
|
+
|
|
63
|
+
## Registering a class you cannot edit
|
|
64
|
+
|
|
65
|
+
Do it in expression position:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
registerComponent(
|
|
69
|
+
class extends Vendor {
|
|
70
|
+
static config = { name: 'CompactVendor', options: { compact: Boolean } };
|
|
71
|
+
},
|
|
72
|
+
);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## What it does not do
|
|
76
|
+
|
|
77
|
+
- **It does not construct anything itself.** The registry does, when the DOM and the mount strategy agree.
|
|
78
|
+
- **It does not take a name or a selector.** `config.name` is the only name, and arbitrary selectors are removed.
|
|
79
|
+
- **It does not take a promise or a thunk.** Use [`registerManifest()`](registerManifest.md) for a lazy entry.
|
|
80
|
+
- **It has no inverse on a page.** `resetRegistry()` exists for tests only — see [`/test`](../test/index.md).
|
|
81
|
+
|
|
82
|
+
## `@component`
|
|
83
|
+
|
|
84
|
+
The decorator writes `static config` and calls this function in one step:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { Base, component } from '@studiometa/js-toolkit';
|
|
88
|
+
|
|
89
|
+
@component({ name: 'Slider', refs: ['next'] })
|
|
90
|
+
class Slider extends Base {}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
See [`@component`](../decorators/component.md).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# registerComponents
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
registerComponents(...classes: BaseConstructor[]): void
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
[`registerComponent()`](registerComponent.md) for several classes, in order.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import { Base, registerComponents } from '@studiometa/js-toolkit';
|
|
13
|
+
|
|
14
|
+
class Accordion extends Base {
|
|
15
|
+
static config = { name: 'Accordion' };
|
|
16
|
+
}
|
|
17
|
+
class Slider extends Base {
|
|
18
|
+
static config = { name: 'Slider' };
|
|
19
|
+
}
|
|
20
|
+
class TodoList extends Base {
|
|
21
|
+
static config = { name: 'TodoList' };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
registerComponents(Accordion, Slider, TodoList);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
This is the whole bootstrap of a page. There is no `createApp()` and no root component: each of these registers its own declared family, and every registered name auto-mounts through the single MutationObserver.
|
|
28
|
+
|
|
29
|
+
**Parameters**
|
|
30
|
+
|
|
31
|
+
- `...classes` — classes extending `Base`.
|
|
32
|
+
|
|
33
|
+
**Return value**
|
|
34
|
+
|
|
35
|
+
- `void`.
|
|
36
|
+
|
|
37
|
+
Order matters only for collisions: the first registration of a name wins and the second gives a `registry.conflict` warning.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# registerManifest
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
registerManifest(entries: ComponentManifest): void
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Registers lazy component entries in the same registry the eager classes use.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
import { registerManifest } from '@studiometa/js-toolkit';
|
|
13
|
+
|
|
14
|
+
registerManifest({
|
|
15
|
+
Accordion: () => import('./components/Accordion.js'),
|
|
16
|
+
Slider: () => import('./components/Slider.js'),
|
|
17
|
+
Map: { load: () => import('./components/Map.js'), mountStrategy: 'visible' },
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Types
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
type ComponentManifest = Record<string, ComponentImporter | ComponentManifestEntry>;
|
|
25
|
+
|
|
26
|
+
type ComponentImporter = () => Promise<unknown>;
|
|
27
|
+
|
|
28
|
+
interface ComponentManifestEntry {
|
|
29
|
+
load: ComponentImporter;
|
|
30
|
+
mountStrategy?: MountStrategy;
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
An entry is either the importer itself, or an object with `load` and an optional `mountStrategy`.
|
|
35
|
+
|
|
36
|
+
## The contract
|
|
37
|
+
|
|
38
|
+
- **One name, one entry**, across eager classes and manifests alike. A token an eager class or an earlier manifest owns gives a `manifest.duplicate-token` warning and is ignored.
|
|
39
|
+
- **No dependency and no bundler knowledge.** The value is a function that returns a promise. `import.meta.glob`, `import.meta.webpackContext` and a generated manifest all produce that shape, and core names none of them.
|
|
40
|
+
- **The class is resolved out of the imported module for you**, so a hand-written entry is `Slider: () => import('./Slider.js')` with nothing to unwrap.
|
|
41
|
+
- **The registry stays the only constructor.** The import ends in [`registerComponent()`](registerComponent.md); autoload never touches `new`, the instance map or a mount hook.
|
|
42
|
+
- **One import per name, one failure report per name.** A failure emits one `component.load-failed` diagnostic and is never retried.
|
|
43
|
+
- **A class whose `config.name` differs from its token** gives a `registry.lazy-name-mismatch` warning.
|
|
44
|
+
- **An unloaded declaration is invisible** to `$query()`, `$closest()`, `$watchChildren()` and `getInstances()`, because nothing is constructed at discovery.
|
|
45
|
+
|
|
46
|
+
## The mount strategy chain
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
data-mount > manifest entry mountStrategy > 'eager'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The entry's strategy stands in the middle slot for the `config.mountStrategy` of a class that cannot be read yet. Once the class registers, the chain reads `config.mountStrategy` and the entry is deleted from the map.
|
|
53
|
+
|
|
54
|
+
There is **no `data-load`**: deferring the import and deferring the mount are one decision. See [Autoloading](../../guide/going-further/autoloading.md).
|
|
55
|
+
|
|
56
|
+
## `whenDOMSettled()` covers an eager lazy component
|
|
57
|
+
|
|
58
|
+
The import promise joins the lifecycle-work set for the **eager** trigger only, so [`swap()`](../dom/swap.md) waits for download, registration and mount — and still never waits on a viewport, an idle callback, an interaction or a media query.
|
|
59
|
+
|
|
60
|
+
## From a glob
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
import { defineManifest, fromMetaGlob, registerManifest } from '@studiometa/js-toolkit';
|
|
64
|
+
|
|
65
|
+
registerManifest(
|
|
66
|
+
defineManifest({
|
|
67
|
+
modules: fromMetaGlob(import.meta.glob('./components/*/index.js')),
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
See [`defineManifest()`](defineManifest.md).
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# defaultScheduler
|
|
2
|
+
|
|
3
|
+
The one scheduler instance. Duplicate copies of the package reuse the canonical one through the shared runtime.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
class Scheduler {
|
|
7
|
+
get phase(): SchedulerPhase;
|
|
8
|
+
tick(callback: TickCallback): () => void;
|
|
9
|
+
read<T>(fn: () => T): ScheduledTask<T>;
|
|
10
|
+
write<T>(fn: () => T): ScheduledTask<T>;
|
|
11
|
+
whenIdle(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## `read()` and `write()`
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { defaultScheduler } from '@studiometa/js-toolkit';
|
|
19
|
+
|
|
20
|
+
const el = document.body;
|
|
21
|
+
async function resize() {
|
|
22
|
+
const box = await defaultScheduler.read(() => el.getBoundingClientRect()).promise;
|
|
23
|
+
await defaultScheduler.write(() => {
|
|
24
|
+
el.style.height = `${box?.height}px`;
|
|
25
|
+
}).promise;
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Both return a handle:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
interface ScheduledTask<T = unknown> {
|
|
33
|
+
promise: Promise<T | undefined>;
|
|
34
|
+
cancel(): void;
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- The promise resolves with the **return value of the task**, so a read hands its measurement back.
|
|
39
|
+
- `cancel()` is idempotent, and a cancelled task's promise never resolves with a value.
|
|
40
|
+
- **Queued execution only.** There is no synchronous escape.
|
|
41
|
+
|
|
42
|
+
### The thrash rule
|
|
43
|
+
|
|
44
|
+
| Scheduled from | Runs in |
|
|
45
|
+
| -------------- | -------------- |
|
|
46
|
+
| a `read` | the same frame |
|
|
47
|
+
| a `write` | the next frame |
|
|
48
|
+
|
|
49
|
+
Each queue array is **swapped for an empty one when its phase starts**, so a task scheduled into the running phase lands in the next frame's batch. The `write` batch is taken after the reads run.
|
|
50
|
+
|
|
51
|
+
## `tick()`
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
import { defaultScheduler } from '@studiometa/js-toolkit';
|
|
55
|
+
|
|
56
|
+
const unsubscribe = defaultScheduler.tick(({ time, delta }) => {
|
|
57
|
+
console.log(time, delta);
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
interface TickProps {
|
|
63
|
+
readonly time: DOMHighResTimeStamp;
|
|
64
|
+
readonly delta: number;
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- Tick callbacks run at the **start** of the flush, before `read`, so what they schedule belongs to the same frame.
|
|
69
|
+
- **The subscription is the only handle, and it keeps the loop alive.** The scheduler requests the next frame when a queue inside the frame is not empty, or when a tick subscriber stays. **There is no permanent rAF loop.**
|
|
70
|
+
- Tick subscribers are **not queued work**, so `whenIdle()` ignores them.
|
|
71
|
+
- A tick callback that throws is reported as `callback.scheduler-tick-failed` and skipped, never unsubscribed.
|
|
72
|
+
- **`delta` is clamped to `[1, 40]` ms**, and the first tick after the loop wakes reports `1000/60`. `time` stays the raw rAF timestamp.
|
|
73
|
+
|
|
74
|
+
For a subscription that comes and goes within a cycle, use [`toggle()`](../services/toggle.md) rather than subscribing and unsubscribing by hand.
|
|
75
|
+
|
|
76
|
+
## `whenIdle()`
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
await defaultScheduler.whenIdle();
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Resolves at the end of a flush **and** at the end of a background drain, because it counts background tasks too.
|
|
83
|
+
|
|
84
|
+
It is one half of the timing recipe the [`/test`](../test/index.md) helpers encode — the other half is the mutation observer's delivery latency, which is why `whenIdle()` alone is not enough to know a component has mounted.
|
|
85
|
+
|
|
86
|
+
## `phase`
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
type SchedulerPhase = 'idle' | 'tick' | 'read' | 'write' | 'background';
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Reading it is a diagnostic, not a control. Code that branches on the phase is usually code that should schedule instead.
|
|
93
|
+
|
|
94
|
+
## The background lane
|
|
95
|
+
|
|
96
|
+
It posts its own turns through `scheduler.postTask({ priority: 'background' })`, and falls back to a `MessageChannel` message. Each turn runs a **5 ms slice** measured from the start of the drain, then gives the thread back and posts the next turn.
|
|
97
|
+
|
|
98
|
+
**Background work alone never requests an animation frame.**
|
|
99
|
+
|
|
100
|
+
A failure to post is reported as `scheduler.background-post-failed`.
|
|
101
|
+
|
|
102
|
+
## Error isolation
|
|
103
|
+
|
|
104
|
+
One try/catch per task. A task that throws is reported as `callback.scheduled-task-failed`, **rejects its own promise with the same value**, and is dropped. The flush continues and the scheduler never deadlocks.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Scheduler
|
|
2
|
+
|
|
3
|
+
One frame-aligned scheduler is the clock of the framework. It replaces `domScheduler`, the `RafService` loop, `SmartQueue` and the view-transition scheduler of `@studiometa/ui`.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
frame start (rAF)
|
|
7
|
+
1. tick — fan out to the subscribers of the clock
|
|
8
|
+
2. read — measure: layout reads only
|
|
9
|
+
3. write — mutate: DOM writes only
|
|
10
|
+
style / layout / paint
|
|
11
|
+
|
|
12
|
+
between frames, on its own turns
|
|
13
|
+
background — time-sliced lane: mount and update lifecycle work,
|
|
14
|
+
mutation-record processing, manifest loading
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## The exports
|
|
18
|
+
|
|
19
|
+
- [`defaultScheduler`](defaultScheduler.md) — the instance, with `tick`, `read`, `write`, `whenIdle` and `phase`
|
|
20
|
+
- [`nextFrame()`](nextFrame.md) — await one frame
|
|
21
|
+
- [`viewTransition(update)`](viewTransition.md) — a batched native view transition
|
|
22
|
+
|
|
23
|
+
From a component, `$read()` and `$write()` tie tasks to the instance so unmount cancels them. See [Instance methods](../instance-methods.md#read-and-write).
|
|
24
|
+
|
|
25
|
+
## Read next
|
|
26
|
+
|
|
27
|
+
[The scheduler](../../guide/going-further/scheduling-work.md) explains the lanes, the thrash rule and why `afterWrite` is gone.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# nextFrame
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
nextFrame(): Promise<void>
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Resolves on the next animation frame.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { nextFrame } from '@studiometa/js-toolkit';
|
|
13
|
+
|
|
14
|
+
async function afterOneFrame(el: HTMLElement) {
|
|
15
|
+
el.classList.add('is-entering');
|
|
16
|
+
await nextFrame();
|
|
17
|
+
el.classList.add('is-active');
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## What it is for
|
|
22
|
+
|
|
23
|
+
Letting the browser see a style before the next one is applied — the two-step every CSS transition needs. `transition()`, `enterTransition()` and `leaveTransition()` are built on exactly this.
|
|
24
|
+
|
|
25
|
+
## What it is not
|
|
26
|
+
|
|
27
|
+
It does **not** mean "after paint". rAF callbacks run **before** style, layout and paint, so no phase inside a frame can read post-layout geometry. `afterWrite` is removed for that reason.
|
|
28
|
+
|
|
29
|
+
To measure after a layout has happened, measure in the `read` phase of the next frame — [`defaultScheduler.read()`](defaultScheduler.md) or `$read()` — or use a `ResizeObserver`.
|
|
30
|
+
|
|
31
|
+
For a test that needs several frames, [`frames(count?)`](../test/index.md) is the same idea with a count.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# viewTransition
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
viewTransition(update: () => void | Promise<void>): Promise<void>
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Runs a DOM update inside a native view transition, with a progressive-enhancement contract: where the platform has no `startViewTransition`, the update simply runs.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { viewTransition } from '@studiometa/js-toolkit';
|
|
13
|
+
|
|
14
|
+
async function replace(el: Element, html: string) {
|
|
15
|
+
await viewTransition(() => {
|
|
16
|
+
el.innerHTML = html;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Batching
|
|
22
|
+
|
|
23
|
+
**Updates queued in the same flush batch into one `startViewTransition()` call**, so a backdrop and a panel animate as one transition rather than two fighting each other.
|
|
24
|
+
|
|
25
|
+
Each later batch is appended to **one promise tail**, so several flushes during one running transition stay serialized instead of interleaving.
|
|
26
|
+
|
|
27
|
+
The scheduler flushes the pending `write` tasks **before the snapshot**, so a pending write is part of the "before" state rather than landing mid-transition. Writes scheduled _inside_ the update callback run within the transition.
|
|
28
|
+
|
|
29
|
+
## It is standalone
|
|
30
|
+
|
|
31
|
+
`Base` has no view-transition method and no import of one. The helper is a free function, and the whole view-transition graph stays out of the `Base` module graph — a page that never calls it never downloads it.
|
|
32
|
+
|
|
33
|
+
## Composing it
|
|
34
|
+
|
|
35
|
+
It is a `DomUpdateRunner`, so an ancestor can claim a [negotiated update](../dom/domUpdate.md) with it:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
this.$on(EVENTS.dom.update, ({ detail }) => detail.wrap(viewTransition));
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
and it is a `SwapWrap`, so a [`swap()`](../dom/swap.md) can play as one transition:
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
await swap(el, html, { wrap: (mutate) => viewTransition(mutate) });
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Neither is the default. **The ancestor chooses the lane, because it knows whether the region animates.**
|
|
48
|
+
|
|
49
|
+
## `exit`, `layout` and `layoutId`
|
|
50
|
+
|
|
51
|
+
They are not an animation engine's job. Native view transitions solve them, which is why this is in core while `tween` and `animate` are not shipped at all.
|
|
52
|
+
|
|
53
|
+
`@studiometa/ui` keeps a declarative `ViewTransition` component, rebuilt on this helper.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# createService
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
createService<T, R = void>(definition: ServiceDefinition<T>): Service<T, R>
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
The primitive every built-in service is built on.
|
|
8
|
+
|
|
9
|
+
## The definition
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
interface ServiceDefinition<T> {
|
|
13
|
+
props: () => T;
|
|
14
|
+
hasProps?: () => boolean;
|
|
15
|
+
start: (emit: (props: T) => void) => Unsubscribe;
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
| Field | Does |
|
|
20
|
+
| ---------- | ----------------------------------------------------------------------------------- |
|
|
21
|
+
| `props` | reads the current props |
|
|
22
|
+
| `hasProps` | says whether there **is** a current value, which is what `{ immediate: true }` asks |
|
|
23
|
+
| `start` | starts the source on the first subscriber, and returns its teardown |
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { createService } from '@studiometa/js-toolkit';
|
|
29
|
+
|
|
30
|
+
interface OnlineProps {
|
|
31
|
+
readonly isOnline: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const useOnline = createService<OnlineProps>({
|
|
35
|
+
props: () => ({ isOnline: navigator.onLine }),
|
|
36
|
+
start(emit) {
|
|
37
|
+
const publish = () => emit({ isOnline: navigator.onLine });
|
|
38
|
+
window.addEventListener('online', publish);
|
|
39
|
+
window.addEventListener('offline', publish);
|
|
40
|
+
return () => {
|
|
41
|
+
window.removeEventListener('online', publish);
|
|
42
|
+
window.removeEventListener('offline', publish);
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## What you get for free
|
|
49
|
+
|
|
50
|
+
- **Lazy and reference-counted.** `start` runs on the first subscriber and its teardown on the last. With no subscriber there is no listener, no observer and no frame.
|
|
51
|
+
- **Symmetric subscriptions.** `subscribe(callback)` returns the unsubscribe function. A subscription is a **record**, not a key in a set, so two holders of one function are two subscribers.
|
|
52
|
+
- **A safe fan-out.** The fan-out walks a snapshot and each record carries an `isActive` flag, so a subscriber that unsubscribes during a delivery is not called.
|
|
53
|
+
- **Error isolation.** A subscriber that throws is skipped and reported as `callback.service-failed`.
|
|
54
|
+
|
|
55
|
+
Publishing is **re-entrant**, so any code that changes state after a publication must check first that the service is still alive.
|
|
56
|
+
|
|
57
|
+
## `hasProps`
|
|
58
|
+
|
|
59
|
+
Omit it and the service is assumed to have a current value. Declare it when it does not:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { createService } from '@studiometa/js-toolkit';
|
|
63
|
+
|
|
64
|
+
interface BatchProps {
|
|
65
|
+
readonly records: readonly unknown[];
|
|
66
|
+
}
|
|
67
|
+
let current: readonly unknown[] = [];
|
|
68
|
+
createService<BatchProps>({
|
|
69
|
+
props: () => ({ records: current }),
|
|
70
|
+
hasProps: () => current.length > 0, // nothing to deliver between batches
|
|
71
|
+
start: (emit) => () => {},
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
This is what makes `{ immediate: true }` honest: the frame tick has no current value between two frames, the pointer has none before it is seen, a drag has none outside a gesture, and a mutation service has none between batches.
|
|
76
|
+
|
|
77
|
+
## What a callback may return
|
|
78
|
+
|
|
79
|
+
`R` is a type parameter, so a service can require its callbacks to return something. `useRaf()` uses it to enforce `RafRender`:
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
type RafService = Service<RafProps, void | RafRender>;
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Scoping it to a target
|
|
86
|
+
|
|
87
|
+
Wrap it in [`perTarget()`](perTarget.md) to get one instance per target and per options, keyed in a `WeakMap` — the caching every built-in service has.
|
|
88
|
+
|
|
89
|
+
## Making a mixin over it
|
|
90
|
+
|
|
91
|
+
See [`createServiceMixin()`](createServiceMixin.md).
|
|
92
|
+
|
|
93
|
+
**A consumer's service is owned by the consumer**
|
|
94
|
+
|
|
95
|
+
The shared runtime coordinates the **built-in** service caches across duplicate copies of the package. A `createService()` or `perTarget()` call of a consumer stays owned by that consumer.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# createServiceMixin
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
createServiceMixin<Instance, Target, Options extends object = object>(
|
|
5
|
+
definition: ServiceMixinDefinition<Target, Options>,
|
|
6
|
+
): ServiceMixin<Instance, Target, Options>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Builds the mixin-and-decorator pair over a service. Every built-in `with*` is one of these.
|
|
10
|
+
|
|
11
|
+
## The definition
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
interface ServiceMixinDefinition<Target, Options> {
|
|
15
|
+
hook: string;
|
|
16
|
+
target: (instance: Base) => Target;
|
|
17
|
+
defaultImmediate?: boolean;
|
|
18
|
+
use: (target: Target, options: Options) => Service<unknown, unknown>;
|
|
19
|
+
handleResult?: (instance: Base, result: unknown) => void;
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
| Field | Does |
|
|
24
|
+
| ------------------ | ------------------------------------------------------------------------- |
|
|
25
|
+
| `hook` | the one method name the service owns |
|
|
26
|
+
| `target` | the default target resolver |
|
|
27
|
+
| `defaultImmediate` | whether the first delivery is asked for unless the caller says otherwise |
|
|
28
|
+
| `use` | calls the service factory |
|
|
29
|
+
| `handleResult` | does something with what the hook returned — `withRaf` schedules a render |
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { createService, createServiceMixin, perTarget } from '@studiometa/js-toolkit';
|
|
35
|
+
|
|
36
|
+
interface FocusProps {
|
|
37
|
+
readonly hasFocus: boolean;
|
|
38
|
+
}
|
|
39
|
+
const useFocus = perTarget((target: Element) =>
|
|
40
|
+
createService<FocusProps>({
|
|
41
|
+
props: () => ({ hasFocus: target.contains(document.activeElement) }),
|
|
42
|
+
start: () => () => {},
|
|
43
|
+
}),
|
|
44
|
+
);
|
|
45
|
+
interface FocusHook {
|
|
46
|
+
focused?(props: FocusProps): void;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const withFocus = createServiceMixin<FocusHook, Element>({
|
|
50
|
+
hook: 'focused',
|
|
51
|
+
target: (instance) => instance.$el,
|
|
52
|
+
use: (target) => useFocus(target),
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
class Field extends withFocus(Base) {
|
|
58
|
+
focused({ hasFocus }) {}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## `use` receives the service's options only
|
|
63
|
+
|
|
64
|
+
`target`, `manual` and `immediate` are removed before `use` is called and they are absent from its `Options` type — which is why `use: (target, options) => useDrag(target, options)` is correct and needs no filtering.
|
|
65
|
+
|
|
66
|
+
## Override `$mount()`, not `mounted()`
|
|
67
|
+
|
|
68
|
+
`createServiceMixin()` overrides `$mount()` and `$unmount()`, which is what lets a component write its own `mounted()` without `super.mounted()` and still subscribe.
|
|
69
|
+
|
|
70
|
+
**The rule is about what a mixin overrides, not who wrote it.** A userland mixin that puts its work in `mounted()` needs its subclasses to call `super.mounted()`. The way not to need that is to override `$mount()` — or to use this function, which already does.
|
|
71
|
+
|
|
72
|
+
## What it gives the class
|
|
73
|
+
|
|
74
|
+
- the hook, bound for each mount cycle;
|
|
75
|
+
- `$services.<hook>` as a [`Toggle`](toggle.md), typed through `ServiceHandles<'<hook>'>`;
|
|
76
|
+
- the two call forms, mixin and class decorator;
|
|
77
|
+
- the `service.missing-target` check on a caller-supplied resolver.
|
|
78
|
+
|
|
79
|
+
## One hook per class
|
|
80
|
+
|
|
81
|
+
A mixin names one hook and binds one subscription per cycle. That is its limit, and a component with a dynamic set of subscriptions calls `subscribe()` itself. See [Mixins](mixins.md).
|