@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,105 @@
|
|
|
1
|
+
# swap
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
swap(target: Element, content: SwapContent, options?: SwapOptions): Promise<void>
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Replaces the **content** of an element and resolves once the framework has caught up.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
type SwapContent = string | Element | DocumentFragment;
|
|
11
|
+
|
|
12
|
+
interface SwapOptions {
|
|
13
|
+
mode?: 'replace' | 'prepend' | 'append' | 'morph';
|
|
14
|
+
wrap?: (mutate: () => void) => void | Promise<unknown>;
|
|
15
|
+
self?: boolean;
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { swap } from '@studiometa/js-toolkit';
|
|
23
|
+
|
|
24
|
+
async function load(target: Element) {
|
|
25
|
+
const response = await fetch('/fragment');
|
|
26
|
+
await swap(target, await response.text());
|
|
27
|
+
// The mutation is applied, the new components are mounted, the old ones unmounted.
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The returned promise resolves after [`whenDOMSettled()`](whenDOMSettled.md).
|
|
32
|
+
|
|
33
|
+
## What survives
|
|
34
|
+
|
|
35
|
+
**By default the element itself is never replaced**, so the caller's reference, its `id` and any instance on it survive. Only its children change.
|
|
36
|
+
|
|
37
|
+
`content` as a **string** is parsed in the parsing context of the target, so `<tr>`, `<li>` and `<option>` survive. As an `Element` or a `DocumentFragment` it is read as the incoming counterpart of the target, and its **children** become the new content.
|
|
38
|
+
|
|
39
|
+
## The modes
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
import { SWAP_MODES } from '@studiometa/js-toolkit';
|
|
43
|
+
|
|
44
|
+
SWAP_MODES.REPLACE; // 'replace' — the default
|
|
45
|
+
SWAP_MODES.PREPEND; // 'prepend'
|
|
46
|
+
SWAP_MODES.APPEND; // 'append'
|
|
47
|
+
SWAP_MODES.MORPH; // 'morph'
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`SwapMode` is derived from the frozen object — the pattern for every closed set of strings in the framework.
|
|
51
|
+
|
|
52
|
+
`prepend` and `append` stay in core because they need the same before-and-after script diff as the other two.
|
|
53
|
+
|
|
54
|
+
### `morph`
|
|
55
|
+
|
|
56
|
+
Identity survives — nodes, focus, expandos, instances — **but markup that is not sent does not.** Two consequences are morphdom's policy, not `swap()`'s:
|
|
57
|
+
|
|
58
|
+
- an element the incoming markup does not contain is discarded even from a preserved parent;
|
|
59
|
+
- morphdom syncs the `value` of an input from the incoming markup.
|
|
60
|
+
|
|
61
|
+
**Attributes are not synced on the target.** Core passes `childrenOnly: true` without `self`, because `data-component` and `data-mount` are lifecycle declarations of the target, not content.
|
|
62
|
+
|
|
63
|
+
## `self`
|
|
64
|
+
|
|
65
|
+
Replaces the target element **itself**, attributes included, instead of its children:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
await swap(el, html, { mode: 'replace', self: true });
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
It is the axis a caller that matches an element of a response to an element of the page needs: an id-matched section otherwise keeps the classes of the element it replaces.
|
|
72
|
+
|
|
73
|
+
- With `self`, an `Element` content **is** the replacement rather than a container — the only way its own attributes reach the page. A string or a `DocumentFragment` contributes its **first top-level element**.
|
|
74
|
+
- `replace` puts the replacement in the place of the target, so the target **leaves** the document.
|
|
75
|
+
- `morph` morphs the target from the replacement without `childrenOnly`, so the element and its identity survive while its attributes are updated.
|
|
76
|
+
- `append` and `prepend` add to the children by definition, so `self` with either is a `swap.self-ignored` warning — as is content holding no element.
|
|
77
|
+
|
|
78
|
+
## Scripts
|
|
79
|
+
|
|
80
|
+
A `<script>` produced by the fragment parser is flagged as **already started** by the HTML specification and stays inert wherever it is moved. It runs only if it is **recreated** — and a script that was already in the page runs **twice** if it is recreated.
|
|
81
|
+
|
|
82
|
+
`swap()` owns that rule, once. Script adoption follows whatever ends up in the document, so a replacement carrying a script still runs it exactly once.
|
|
83
|
+
|
|
84
|
+
## `wrap`
|
|
85
|
+
|
|
86
|
+
The whole seam. It receives the single mutation of the swap and decides when it runs:
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { swap, viewTransition } from '@studiometa/js-toolkit';
|
|
90
|
+
|
|
91
|
+
async function load(el: Element, html: string) {
|
|
92
|
+
await swap(el, html, { wrap: (mutate) => viewTransition(mutate) });
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
[`domUpdate()`](domUpdate.md) produces that wrapper and nothing else, so an ancestor can claim the lane. **Resilience policy stays with `domUpdate()`** — `swap()` itself throws rather than swallowing.
|
|
97
|
+
|
|
98
|
+
## What is deliberately not in core
|
|
99
|
+
|
|
100
|
+
- **Attribute syncing in a default `morph`** — see above.
|
|
101
|
+
- **Transitions, view transitions, history, `id` matching and response parsing.** All caller policy.
|
|
102
|
+
|
|
103
|
+
## It is a free function
|
|
104
|
+
|
|
105
|
+
Not a `Base` method. `morphdom` is a real, statically imported dependency, and the subpath layout contains the cost: it is reachable through `swap()` only, so a page that never swaps never downloads it.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# watchAttributeNamespace
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
watchAttributeNamespace(
|
|
5
|
+
el: Element,
|
|
6
|
+
namespace: string,
|
|
7
|
+
bind: AttributeNamespaceBinder,
|
|
8
|
+
options?: { qualifiers?: readonly string[]; component?: string },
|
|
9
|
+
): () => void
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The mechanism for a namespace whose names **cannot be enumerated**. Declare the prefix, hand over a binder, and get the per-element observation, the keyed bindings and the teardown.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
interface AttributeNamespaceDeclaration {
|
|
16
|
+
qualifier: string;
|
|
17
|
+
value: string;
|
|
18
|
+
attribute: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type AttributeNamespaceBinder = (declaration: AttributeNamespaceDeclaration) => (() => void) | void;
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import { watchAttributeNamespace } from '@studiometa/js-toolkit';
|
|
28
|
+
|
|
29
|
+
mounted() {
|
|
30
|
+
return watchAttributeNamespace(this.$el, 'data-on', ({ qualifier, value }) =>
|
|
31
|
+
new ActionEvent(this, qualifier, value).attach(),
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`Base` has no wrapper and owns no cleanup. A component calls it from `mounted()` and returns its cleanup.
|
|
37
|
+
|
|
38
|
+
## One binding per attribute, keyed by the name that produced it
|
|
39
|
+
|
|
40
|
+
That is what lets **one** code path cover all three shapes a change takes:
|
|
41
|
+
|
|
42
|
+
| Change | Effect |
|
|
43
|
+
| ------- | ------------------------------- |
|
|
44
|
+
| added | attach, with nothing to release |
|
|
45
|
+
| changed | release, then attach |
|
|
46
|
+
| removed | release, with nothing to attach |
|
|
47
|
+
|
|
48
|
+
A memoised parse cannot express the middle one — and rewriting an attribute in place is not hypothetical: `swap({ mode: 'morph' })` does it, and so does any templating around the element.
|
|
49
|
+
|
|
50
|
+
**The binder returns that binding's release**, or nothing when the declaration produced no binding. Returning nothing leaves nothing held, so a malformed value costs no bookkeeping.
|
|
51
|
+
|
|
52
|
+
## Declaration order survives a rewrite
|
|
53
|
+
|
|
54
|
+
The bindings are a `Map` keyed by attribute, and `set` on a key already there keeps its position — so a consumer applying its bindings in order is not reordered by an edit.
|
|
55
|
+
|
|
56
|
+
## Validating the qualifier's head
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
watchAttributeNamespace(el, 'data-bind', bind, {
|
|
60
|
+
qualifiers: ['class', 'prop', 'attr', 'style', 'text', 'html'],
|
|
61
|
+
component: 'Bind',
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Given a finite vocabulary, an unknown head warns **once per element and per name** with `attribute.unknown-qualifier` and binds nothing — so `data-bind:prpo.value` stops being an attribute that silently does nothing.
|
|
66
|
+
|
|
67
|
+
Omitted, the vocabulary is **open** and anything binds, which is the only honest answer for `data-on`, whose qualifiers are any DOM event.
|
|
68
|
+
|
|
69
|
+
## The qualifier and its parts
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
data-<namespace>:<qualifier>[.<part>…]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**A dot splits the qualifier, and core reads none of it.** Whether the first part names what a binding writes to (`data-bind:prop.value`) or modifies how it fires (`data-on:click.prevent`) is the business of whoever declared the namespace.
|
|
76
|
+
|
|
77
|
+
Core reads the qualifier's **head** only, to check it against the vocabulary you handed over, and never past it.
|
|
78
|
+
|
|
79
|
+
> Core owns when a declaration is re-parsed and how the attribute is observed. The namespace's owner owns what the string means.
|
|
80
|
+
|
|
81
|
+
## It is built on `watchAttributes()`
|
|
82
|
+
|
|
83
|
+
So its records join the one mutation engine's queue and are reported from the same batch: [`whenDOMSettled()`](whenDOMSettled.md), and therefore [`swap()`](swap.md), covers a namespaced declaration the way it covers a mount.
|
|
84
|
+
|
|
85
|
+
## When a namespace does not need this
|
|
86
|
+
|
|
87
|
+
If the whole set of names can be listed in advance, it belongs in the one page-wide `attributeFilter` instead:
|
|
88
|
+
|
|
89
|
+
| Namespace | Names | Mechanism |
|
|
90
|
+
| ----------------------- | ------------------------------------------- | ------------------------- |
|
|
91
|
+
| `data-option-columns` | `attribute × breakpoint` — enumerable | the one `attributeFilter` |
|
|
92
|
+
| `data-component` | fixed plus one per breakpoint — enumerable | the one `attributeFilter` |
|
|
93
|
+
| `data-on`, `data-track` | any DOM event — open | **this** |
|
|
94
|
+
| `data-bind` | finite head, open name — **not** enumerable | **this** |
|
|
95
|
+
|
|
96
|
+
`data-bind` is the case that shows why "finite or open" is the wrong axis on its own: its binding types are finite, but the class, property or attribute name after the dot is not. See [The attribute grammar](../../guide/concepts/attribute-grammar.md).
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# watchAttributes
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
watchAttributes(el: Element, callback: (change: AttributeChange) => void): () => void
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
Observes **every** attribute of one element, through a second, unfiltered observer.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
interface AttributeChange {
|
|
11
|
+
name: string;
|
|
12
|
+
value: string | null;
|
|
13
|
+
previousValue: string | null;
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Why it exists
|
|
18
|
+
|
|
19
|
+
`attributeFilter` takes exact names and the DOM has no wildcard, so the engine cannot see an attribute the framework cannot name. This is the opt-in, and **the page pays for the elements that ask**.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
import { Base, watchAttributes } from '@studiometa/js-toolkit';
|
|
25
|
+
|
|
26
|
+
class Bindings extends Base {
|
|
27
|
+
static config = { name: 'Bindings' };
|
|
28
|
+
|
|
29
|
+
mounted() {
|
|
30
|
+
return watchAttributes(this.$el, ({ name, value, previousValue }) => {
|
|
31
|
+
if (!name.startsWith('data-my-')) return;
|
|
32
|
+
// …
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**The caller owns it.** The helper returns one idempotent cleanup and knows nothing about `Base`: a component calls it from `mounted()` and returns the cleanup.
|
|
39
|
+
|
|
40
|
+
## The contract
|
|
41
|
+
|
|
42
|
+
- **The records join the shared queue.** They are drained wherever the engine drains its own, [`whenDOMSettled()`](whenDOMSettled.md) included, and they are reported from the same background task — as the last step of the batch.
|
|
43
|
+
- **A callback runs after the framework work of the batch.** So a component that stops its watcher during the same batch in which its own declaration is withdrawn hears nothing about the attribute change.
|
|
44
|
+
- **Changes are coalesced**, with the rule of [`option<Name>Changed()`](../methods-hooks-options.md): several writes in one batch give one change, from the value before the first write to the value at the end, and a write that ends where it started is not a change.
|
|
45
|
+
- **The payload covers the element's whole attribute set**, framework names included, with raw strings and `null` for an absent attribute. **A caller narrows by prefix.**
|
|
46
|
+
- A failing callback is reported as `callback.attribute-watcher-failed`, so one watcher cannot stop another.
|
|
47
|
+
|
|
48
|
+
## What to reach for instead
|
|
49
|
+
|
|
50
|
+
| Want | Use |
|
|
51
|
+
| -------------------------------------------- | ------------------------------------------------------------- |
|
|
52
|
+
| a declared option | [`option<Name>Changed()`](../methods-hooks-options.md) |
|
|
53
|
+
| a whole namespace, with keyed bindings | [`watchAttributeNamespace()`](watchAttributeNamespace.md) |
|
|
54
|
+
| a subtree, character data, or a foreign node | [`useMutation()`](../services/useMutation.md) |
|
|
55
|
+
|
|
56
|
+
A declared option is already in the one page-wide filter, and costs no second observer.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# whenDOMSettled
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
whenDOMSettled(): Promise<void>
|
|
5
|
+
```
|
|
6
|
+
|
|
7
|
+
The completion boundary for morphing, fetch updates and breakpoint crossings.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { whenDOMSettled } from '@studiometa/js-toolkit';
|
|
13
|
+
|
|
14
|
+
async function replace(el: Element, html: string) {
|
|
15
|
+
el.innerHTML = html;
|
|
16
|
+
await whenDOMSettled();
|
|
17
|
+
// Every eager component in the new markup has mounted.
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
[`swap()`](swap.md) awaits it for you.
|
|
22
|
+
|
|
23
|
+
## What it waits for
|
|
24
|
+
|
|
25
|
+
- it **drains the pending mutation records**;
|
|
26
|
+
- it **follows the mutation chains of eager lifecycle work**, so markup a `mounted()` inserts is covered too;
|
|
27
|
+
- it resolves after the eager mounts **and the teardown**.
|
|
28
|
+
|
|
29
|
+
An **eager lazy** component is covered: the import promise joins the lifecycle-work set for the eager trigger only, so an awaited `swap()` waits for download, registration and mount.
|
|
30
|
+
|
|
31
|
+
Breakpoint work runs through the background lane, so a crossing's teardown, import and mount work is covered as well.
|
|
32
|
+
|
|
33
|
+
## What it does not wait for
|
|
34
|
+
|
|
35
|
+
- **visibility, interaction, idle or media conditions.** A component with `data-mount="visible"` has not mounted when this resolves, and that is the point: waiting on a viewport would mean never resolving on a page that is not scrolled.
|
|
36
|
+
- **the promises returned by `mounted()`.** An async `mounted()` is the component's own business.
|
|
37
|
+
|
|
38
|
+
## Where else it appears
|
|
39
|
+
|
|
40
|
+
- `watchAttributes()` records join the same queue, so a namespaced declaration is covered the way a mount is.
|
|
41
|
+
- A [`useMutation()`](../services/useMutation.md) subscriber that needs the framework's order rather than the platform's awaits this in its callback.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# `data-component`
|
|
2
|
+
|
|
3
|
+
Declares which components run on an element. **The instance exists because this attribute is here and the name is registered.**
|
|
4
|
+
|
|
5
|
+
## One component
|
|
6
|
+
|
|
7
|
+
```html
|
|
8
|
+
<div data-component="Slider"></div>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The token is the component's `config.name`.
|
|
12
|
+
|
|
13
|
+
## Several components
|
|
14
|
+
|
|
15
|
+
The value is a whitespace-separated token list, and each token gets its own instance:
|
|
16
|
+
|
|
17
|
+
```html
|
|
18
|
+
<a href="/next" data-component="Action Analytics Prefetch">Next</a>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The instances are independent. They share the element and nothing else.
|
|
22
|
+
|
|
23
|
+
## On native elements
|
|
24
|
+
|
|
25
|
+
`data-component` improves a native element rather than replacing it:
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<form data-component="Fetch">…</form>
|
|
29
|
+
<details data-component="Disclosure">…</details>
|
|
30
|
+
<a href="/page" data-component="Prefetch">…</a>
|
|
31
|
+
<tr data-component="Row">…</tr>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Nesting
|
|
35
|
+
|
|
36
|
+
A nested declaration is discovered by the same registry, on its own. Nesting is DOM ancestry, never ownership:
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<div data-component="Accordion">
|
|
40
|
+
<div data-component="AccordionItem">…</div>
|
|
41
|
+
<div data-component="AccordionItem">…</div>
|
|
42
|
+
</div>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Unmounting the parent does not unmount the children.
|
|
46
|
+
|
|
47
|
+
## Responsive declarations
|
|
48
|
+
|
|
49
|
+
One breakpoint-scoped companion attribute exists, with the spelling of responsive options:
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<div
|
|
53
|
+
data-component="Action Analytics"
|
|
54
|
+
data-component:xxs="MobileMenu MobileSearch"
|
|
55
|
+
data-component:m="DesktopMenu DesktopSearch"></div>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- The plain token set is **always active**.
|
|
59
|
+
- At the active breakpoint the registry walks from the widest active suffix **down** and takes the first attribute present.
|
|
60
|
+
- That value is the **complete** responsive set. A wider value **replaces** every lower value; it does not merge with it.
|
|
61
|
+
- An empty value is a **stop**, so a name can be removed above a breakpoint.
|
|
62
|
+
- The effective declaration is the **union** of the unconditional set and the selected responsive set, without duplicates.
|
|
63
|
+
|
|
64
|
+
`TabletFeature` below runs at `s` and `m`, and is removed at `l`:
|
|
65
|
+
|
|
66
|
+
```html
|
|
67
|
+
<div data-component="Base" data-component:s="TabletFeature" data-component:l=""></div>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### What a crossing does
|
|
71
|
+
|
|
72
|
+
A crossing compares the effective set against the element's current state:
|
|
73
|
+
|
|
74
|
+
| Case | Effect |
|
|
75
|
+
| ------------------------- | --------------------------------------------------------------------- |
|
|
76
|
+
| a name is in both | it keeps its controller and its instance — nothing happens |
|
|
77
|
+
| a name is no longer there | `$unmount()`, then the instance is dropped from the element |
|
|
78
|
+
| a name is new | the normal pipeline: mount strategy, `data-mount`, lazy entry, events |
|
|
79
|
+
|
|
80
|
+
A crossing back gives a **new** identity, because the DOM stopped declaring that one. An inactive lazy declaration imports nothing.
|
|
81
|
+
|
|
82
|
+
Connected elements with a scoped declaration share **one** reference-counted `useBreakpoint()` subscription. A page with plain declarations opens none. Breakpoint work runs through the background lane, so `whenDOMSettled()` covers the teardown, import and mount work of a crossing.
|
|
83
|
+
|
|
84
|
+
**A suffix must name a configured breakpoint**
|
|
85
|
+
|
|
86
|
+
An unknown suffix is ignored with one `responsive.unknown-breakpoint` warning. That includes the v3 list syntax `data-component:xxs:xs:s`.
|
|
87
|
+
|
|
88
|
+
See [`setBreakpoints()`](../dom/breakpoints.md).
|
|
89
|
+
|
|
90
|
+
## Changing it from code
|
|
91
|
+
|
|
92
|
+
The attribute is live. Adding a token mounts a new instance; removing one unmounts and drops it:
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
el.dataset.component = 'Slider Analytics';
|
|
96
|
+
await whenDOMSettled();
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Where the instances go
|
|
100
|
+
|
|
101
|
+
Each instance is published on the element under `Symbol.for('@studiometa/js-toolkit/instances')`. That map is not public API — [`getInstance()`](../registry/getInstance.md) and its three siblings are. In a console:
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
$0[Symbol.for('@studiometa/js-toolkit/instances')];
|
|
105
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# `data-mount`
|
|
2
|
+
|
|
3
|
+
Overrides, for one element, **when** its components mount.
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<div data-component="Map" data-mount="visible"></div>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## The values
|
|
10
|
+
|
|
11
|
+
| Value | Mounts when | Reversible |
|
|
12
|
+
| ------------------------ | -------------------------------------- | ---------- |
|
|
13
|
+
| `eager` | the element enters the document | no |
|
|
14
|
+
| `visible[:<rootMargin>]` | it first intersects the viewport | no |
|
|
15
|
+
| `in-view[:<rootMargin>]` | it intersects the viewport | **yes** |
|
|
16
|
+
| `idle` | the main thread becomes idle | no |
|
|
17
|
+
| `interaction` | the user first aims at **it** | no |
|
|
18
|
+
| `interaction:page` | the user first interacts with the page | no |
|
|
19
|
+
| `media:<query>` | the query is not empty and it matches | **yes** |
|
|
20
|
+
|
|
21
|
+
```html
|
|
22
|
+
<div data-component="Hero" data-mount="eager"></div>
|
|
23
|
+
<div data-component="Gallery" data-mount="visible:200px"></div>
|
|
24
|
+
<div data-component="Video" data-mount="in-view:-10% 0px"></div>
|
|
25
|
+
<div data-component="Analytics" data-mount="idle"></div>
|
|
26
|
+
<div data-component="Tooltip" data-mount="interaction"></div>
|
|
27
|
+
<div data-component="Chat" data-mount="interaction:page"></div>
|
|
28
|
+
<div data-component="Parallax" data-mount="media:(min-width: 64rem)"></div>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## The grammar
|
|
32
|
+
|
|
33
|
+
The accepted values are exactly `eager`, `visible`, `visible:`, `visible:<rootMargin>`, `in-view`, `in-view:`, `in-view:<rootMargin>`, `idle`, `interaction`, `interaction:`, `interaction:page` and `media:<non-empty query>`.
|
|
34
|
+
|
|
35
|
+
- A viewport suffix is passed straight through as `IntersectionObserverInit.rootMargin`.
|
|
36
|
+
- The empty suffix behaves as the bare strategy.
|
|
37
|
+
- `page` is the only scope the interaction strategy takes.
|
|
38
|
+
- There is **no** threshold, no root element, no JSON options and no second attribute.
|
|
39
|
+
|
|
40
|
+
## Precedence
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
data-mount > manifest entry mountStrategy > config.mountStrategy > 'eager'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Several components on one element share that element's `data-mount`.** A component that needs its own policy declares `config.mountStrategy` instead.
|
|
47
|
+
|
|
48
|
+
## Invalid values
|
|
49
|
+
|
|
50
|
+
An unknown value, an empty media query, or a `rootMargin` the browser refuses leaves the component **unmounted** and dispatches one cancelable `js-toolkit:diagnostic` with the code `component.invalid-mount-strategy`, the severity `error`, the component name and the original error.
|
|
51
|
+
|
|
52
|
+
The inert controller stays current while the declaration does not change, so it is not reported again; a corrected attribute replaces it. A failed strategy cannot stop the rest of a reconciliation.
|
|
53
|
+
|
|
54
|
+
## It is live
|
|
55
|
+
|
|
56
|
+
A change to `data-mount` disposes the old strategy and applies the final one. Controller identity guards a queued callback of a disposed strategy.
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
el.dataset.mount = 'eager';
|
|
60
|
+
await whenDOMSettled();
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## A waiting component has no instance
|
|
64
|
+
|
|
65
|
+
It is invisible to `$query()`, `$closest()`, `$watchChildren()` and `getInstances()`, and it announces nothing. There is nothing to guard against.
|
|
66
|
+
|
|
67
|
+
Once it has mounted and been stood down again — which only `in-view` and `media:` do — the instance exists and is unmounted, which is what [`getUnmountedInstances()`](../registry/getUnmountedInstances.md) answers.
|
|
68
|
+
|
|
69
|
+
See [Mount strategies](../../guide/going-further/mount-strategies.md) for the full behaviour of each value.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# `data-option-<name>`
|
|
2
|
+
|
|
3
|
+
Sets the value of one declared option.
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<div data-component="Slider" data-option-speed="2"></div>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The name is the option name in **kebab case**: `dragThreshold` is `data-option-drag-threshold`.
|
|
10
|
+
|
|
11
|
+
## An option's name is inside its namespace
|
|
12
|
+
|
|
13
|
+
Every declared option owns the attribute built for it, so `data-option-` is a namespace _family_ rather than a namespace. It is `data-option-columns:s`, never `data-option:columns:s`.
|
|
14
|
+
|
|
15
|
+
That is what keeps the page-wide `attributeFilter` precise: the set of names is enumerable _because_ it comes from a declaration, so no option costs a second observer.
|
|
16
|
+
|
|
17
|
+
## The five types
|
|
18
|
+
|
|
19
|
+
| Declared | `data-option-x="…"` | Reads as |
|
|
20
|
+
| --------- | ------------------- | ---------- |
|
|
21
|
+
| `String` | `"hello"` | `'hello'` |
|
|
22
|
+
| `Number` | `"2"` | `2` |
|
|
23
|
+
| `Boolean` | presence only | `true` |
|
|
24
|
+
| `Array` | `"[1, 2]"` | `[1, 2]` |
|
|
25
|
+
| `Object` | `'{"a": 1}'` | `{ a: 1 }` |
|
|
26
|
+
|
|
27
|
+
A union is declared in order — `[Number, Array]` reads `"10"` as a number and `"[10, 20]"` as an array. Each parser must give a value of its declared type before the next runs.
|
|
28
|
+
|
|
29
|
+
An absent attribute gives the declared default, or the empty value of the first declared type.
|
|
30
|
+
|
|
31
|
+
## A boolean reads presence
|
|
32
|
+
|
|
33
|
+
The string the attribute carries is **never read**, the way `disabled` and `checked` work on the platform:
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<div data-component="Panel" data-option-open></div>
|
|
37
|
+
<!-- true -->
|
|
38
|
+
<div data-component="Panel" data-option-open="false"></div>
|
|
39
|
+
<!-- true — the value says nothing -->
|
|
40
|
+
<div data-component="Panel"></div>
|
|
41
|
+
<!-- the declared default -->
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
A template must write the attribute conditionally rather than interpolate a boolean:
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
{# Correct #}
|
|
48
|
+
<div data-component="Panel" {% if isOpen %}data-option-open{% endif %}></div>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### `data-option-no-<name>` turns one off
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<div data-component="Dialog" data-option-no-trap-focus></div>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- It is how an option declared `default: true` is turned off, since removing an attribute that is not there says nothing.
|
|
58
|
+
- **Only an option that can hold `false` has one** — a declared `Boolean`, or a union containing it. A `String` option has nothing to turn off, so `data-option-no-label` is not an attribute and the observer never watches for it.
|
|
59
|
+
- **Presence is the whole statement.** `data-option-no-x="false"` is not a double negative; it is the same flag.
|
|
60
|
+
- **An option whose own name starts with `no` negates independently.** `noSort` owns `data-option-no-sort`, and its off spelling doubles the prefix, `data-option-no-no-sort`, so no attribute an author writes means two things.
|
|
61
|
+
|
|
62
|
+
The cost is paid by boolean options only: each adds its negated name, plus one scoped spelling per breakpoint, to the observer's filter.
|
|
63
|
+
|
|
64
|
+
## Every option is responsive
|
|
65
|
+
|
|
66
|
+
There is nothing to declare for it. **The suffix names one breakpoint and it cascades upwards:**
|
|
67
|
+
|
|
68
|
+
```html
|
|
69
|
+
<div
|
|
70
|
+
data-component="Grid"
|
|
71
|
+
data-option-columns="1"
|
|
72
|
+
data-option-columns:s="2"
|
|
73
|
+
data-option-columns:l="4"></div>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`$options.columns` walks from the active breakpoint down to the base value and gives the first attribute present. v3 spelled a set (`:xs:s`); v4 does not.
|
|
77
|
+
|
|
78
|
+
**The separator is a colon**, because an option name in kebab case can contain a dash.
|
|
79
|
+
|
|
80
|
+
### The negated spelling is responsive too
|
|
81
|
+
|
|
82
|
+
One cascade, from the active breakpoint down. At each level the value-carrying spelling is read first, then the negation, and the first hit wins — so a narrower breakpoint turns an option back **on**, and at one breakpoint an explicit value outranks a flag:
|
|
83
|
+
|
|
84
|
+
```html
|
|
85
|
+
<div data-component="Panel" data-option-no-x data-option-x:l="true"></div>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**A suffix must name a configured breakpoint**
|
|
89
|
+
|
|
90
|
+
An unknown suffix gives one `responsive.unknown-breakpoint` warning per mount.
|
|
91
|
+
|
|
92
|
+
## Writing one from code
|
|
93
|
+
|
|
94
|
+
`$options` is read-only, so the way to change a value is to write the attribute — the same statement the markup makes:
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
this.$el.setAttribute('data-option-speed', '4');
|
|
98
|
+
this.$el.removeAttribute('data-option-disabled');
|
|
99
|
+
flag ? el.setAttribute('data-option-open', '') : el.removeAttribute('data-option-open');
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The next read gives the new value, and [`option<Name>Changed()`](../methods-hooks-options.md) announces it.
|
|
103
|
+
|
|
104
|
+
Several writes in one batch give **one** change, from the value before the first write to the value at the end. A write that ends where it started is not a change.
|
|
105
|
+
|
|
106
|
+
See [Options](../../guide/introduction/managing-options.md).
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# `data-ref`
|
|
2
|
+
|
|
3
|
+
Marks an element as a named part of a component.
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<div data-component="Dialog">
|
|
7
|
+
<button data-ref="close">Close</button>
|
|
8
|
+
</div>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The name must also be declared in [`config.refs`](../configuration.md#config-refs).
|
|
12
|
+
|
|
13
|
+
## A single ref
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<button data-ref="close"></button>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`config.refs: ['close']` gives `$refs.close`, the **first** match.
|
|
20
|
+
|
|
21
|
+
## A list
|
|
22
|
+
|
|
23
|
+
**The `[]` is part of the attribute:**
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<button data-ref="tabs[]"></button>
|
|
27
|
+
<button data-ref="tabs[]"></button>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`config.refs: ['tabs[]']` gives `$refs.tabs` as an array.
|
|
31
|
+
|
|
32
|
+
A list declaration matches the suffixed attribute **and nothing else**. The opposite mistake — the suffix missing from the attribute — gives one `ref.mismatch` warning per instance and per ref, naming the component and both spellings.
|
|
33
|
+
|
|
34
|
+
## Naming the owner
|
|
35
|
+
|
|
36
|
+
By default a ref belongs to the **nearest enclosing component**. The prefixed form crosses every boundary except another component of that name:
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<div data-component="Slider">
|
|
40
|
+
<div data-component="SliderItem">
|
|
41
|
+
<button data-ref="Slider.next">Slider's, from inside a child</button>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The nearest `Slider` wins, and a nested `Slider` shadows its parent.
|
|
47
|
+
|
|
48
|
+
**The namespace is written in the markup only, never in `config.refs`**, and the name elsewhere never carries it. The namespace goes **before** the suffix:
|
|
49
|
+
|
|
50
|
+
| Markup | `config.refs` | Property | Handler | Decorator |
|
|
51
|
+
| -------------------------- | ------------- | ------------ | ------------- | ------------------ |
|
|
52
|
+
| `data-ref="next"` | `'next'` | `$refs.next` | `onNextClick` | `@on('next', …)` |
|
|
53
|
+
| `data-ref="Slider.next"` | `'next'` | `$refs.next` | `onNextClick` | `@on('next', …)` |
|
|
54
|
+
| `data-ref="dots[]"` | `'dots[]'` | `$refs.dots` | `onDotsClick` | `@on('dots[]', …)` |
|
|
55
|
+
| `data-ref="Slider.dots[]"` | `'dots[]'` | `$refs.dots` | `onDotsClick` | `@on('dots[]', …)` |
|
|
56
|
+
|
|
57
|
+
## It is live
|
|
58
|
+
|
|
59
|
+
`$refs` reads the DOM on access, so a `data-ref` element added later is found with no refresh, and a detached one never stays in a list. There is no `$update()`.
|
|
60
|
+
|
|
61
|
+
`on<Ref><Event>` handlers are delegated from the component's root element, so a ref that appears later needs no new binding. Events that do not bubble — `focus`, `blur`, `scroll`, `mouseenter`, `mouseleave` — are delegated from the capture phase.
|
|
62
|
+
|
|
63
|
+
See [Refs](../../guide/introduction/managing-refs.md).
|