@studiometa/js-toolkit 3.6.1 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Base/utils.js +6 -1
- package/Base/utils.js.map +2 -2
- package/decorators/withGroup.d.ts +24 -1
- package/decorators/withGroup.js +47 -5
- package/decorators/withGroup.js.map +2 -2
- package/package.json +1 -1
- package/utils/math/fold.d.ts +5 -0
- package/utils/math/fold.js +14 -0
- package/utils/math/fold.js.map +7 -0
- package/utils/math/index.d.ts +1 -0
- package/utils/math/index.js +2 -0
- package/utils/math/index.js.map +2 -2
- package/utils/math/wrap.js +3 -0
- package/utils/math/wrap.js.map +2 -2
package/Base/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isArray, isDefined, SmartQueue, dashCase } from "../utils/index.js";
|
|
1
|
+
import { isArray, isDefined, SmartQueue, dashCase, isDev } from "../utils/index.js";
|
|
2
2
|
import { features } from "./features.js";
|
|
3
3
|
import { useMutation } from "../services/MutationService.js";
|
|
4
4
|
import { getInstanceFromElement } from "../helpers/getInstanceFromElement.js";
|
|
@@ -115,6 +115,11 @@ function mutationCallback() {
|
|
|
115
115
|
}
|
|
116
116
|
function addToRegistry(nameOrSelector, ctor) {
|
|
117
117
|
if (registry().has(nameOrSelector)) {
|
|
118
|
+
if (isDev && registry().get(nameOrSelector) !== ctor) {
|
|
119
|
+
console.warn(
|
|
120
|
+
`[${nameOrSelector}] A different component is already registered under this name. Registration is ignored \u2014 like \`customElements.define\`, a name maps to a single component. Give this component a unique \`config.name\` (or use \`withExtraConfig\`, which renames automatically).`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
118
123
|
return;
|
|
119
124
|
}
|
|
120
125
|
registry().set(nameOrSelector, ctor);
|
package/Base/utils.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../packages/js-toolkit/Base/utils.ts"],
|
|
4
|
-
"sourcesContent": ["import { isArray, isDefined, SmartQueue, dashCase } from '../utils/index.js';\nimport type { Base, BaseConfig, BaseConstructor } from './index.js';\nimport { features } from './features.js';\nimport { useMutation } from '../services/MutationService.js';\nimport { getInstanceFromElement } from '../helpers/getInstanceFromElement.js';\n\nlet queue: SmartQueue;\n\n/**\n * Add a task to the main queue.\n */\nexport function addToQueue(fn: () => unknown) {\n if (features.get('blocking')) {\n fn();\n return;\n }\n\n if (!queue) {\n queue = new SmartQueue();\n }\n\n return queue.add(fn);\n}\n\nconst selectors = new Map();\n\n// Separator used for multi-component declaration in `data-component` attributeS.\nconst separator = ' ';\n\n/**\n * Get the selector for a given component.\n */\nexport function getSelector(nameOrSelector: string): string {\n const { component } = features.get('attributes');\n const prefix = features.get('prefix');\n const key = prefix + component + nameOrSelector;\n\n if (!selectors.has(key)) {\n const parts = [\n // Tag select\n `${prefix}-${dashCase(nameOrSelector)}`,\n // Single selector\n `[${component}=\"${nameOrSelector}\"]`,\n // Selector in the middle of a list of selectors\n `[${component}*=\"${separator}${nameOrSelector}${separator}\"]`,\n // Selector at the end of a list of selectors\n `[${component}$=\"${separator}${nameOrSelector}\"]`,\n // Selector at the beginning of a list of selectors\n `[${component}^=\"${nameOrSelector}${separator}\"]`,\n ];\n selectors.set(key, parts.join(','));\n }\n\n return selectors.get(key);\n}\n\n/**\n * Get a list of elements based on the name of a component.\n *\n * @param {string} nameOrSelector\n * The name or selector to used for this component.\n * @param {HTMLElement|Document} element\n * The root element on which to query the selector, defaults to `document`.\n * @return {Array<HTMLElement>}\n * A list of elements on which the component should be mounted.\n */\nexport function getComponentElements(\n nameOrSelector: string,\n element: HTMLElement | Document = document,\n): HTMLElement[] {\n const selector = getSelector(nameOrSelector);\n let elements = [];\n\n try {\n elements = Array.from(element.querySelectorAll(selector));\n // eslint-disable-next-line no-empty\n } catch {}\n\n // If no child component found with the default selector, and if the selector does not\n // start with an uppercase letter, matching a component's name, try a classic DOM selector.\n if (elements.length === 0 && nameOrSelector[0] === nameOrSelector[0].toLowerCase()) {\n elements = Array.from(element.querySelectorAll(nameOrSelector));\n }\n\n return elements;\n}\n\n/**\n * Test if an event is defined in the given config.\n */\nexport function eventIsDefinedInConfig(event: string, config: BaseConfig): boolean {\n return isArray(config.emits) && config.emits.includes(event);\n}\n\n/**\n * Test if an event can be used on the given element.\n */\nexport function eventIsNative(event: string, element: HTMLElement): boolean {\n return isDefined(element[`on${event}`]);\n}\n\n/**\n * Get the target of a given event.\n */\nexport function getEventTarget(instance: Base, event: string, config: BaseConfig): Base['$el'] {\n if (eventIsDefinedInConfig(event, config) || eventIsNative(event, instance.$el)) {\n return instance.$el;\n }\n}\n\n/**\n * Get the global instance storage.\n * We attach it to `globalThis` so it can be shared between different\n * instances of the framework.\n */\nfunction getInstancesStorage(): Set<Base> {\n return (globalThis.__JS_TOOLKIT_INSTANCES__ ??= new Set<Base>());\n}\n\n/**\n * Get the global elements storage.\n * It will hold reference to all elements with at least one component attached to it.\n */\nfunction getElementsStorage(): Set<HTMLElement & { __base__: Map<string, Base> }> {\n return (globalThis.__JS_TOOLKIT_ELEMENTS__ ??= new Set<\n HTMLElement & { __base__: Map<string, Base> }\n >());\n}\n\n/**\n * Get all mounted instances or the ones from a given component.\n * @link https://js-toolkit.studiometa.dev/api/helpers/getInstances.html\n */\nexport function getInstances(): ReadonlySet<Base>;\nexport function getInstances<T extends BaseConstructor = BaseConstructor>(\n ctor: T,\n): Set<InstanceType<T>>;\nexport function getInstances<T extends BaseConstructor = BaseConstructor>(\n ctor?: T,\n): ReadonlySet<InstanceType<T>> | ReadonlySet<Base> {\n if (isDefined(ctor)) {\n const filteredInstances = new Set<InstanceType<T>>();\n for (const instance of getInstancesStorage()) {\n if (instance instanceof ctor) {\n filteredInstances.add(instance as InstanceType<T>);\n }\n }\n return filteredInstances;\n }\n\n return new Set(getInstancesStorage());\n}\n\nexport function getElements() {\n return new Set(getElementsStorage());\n}\n\nexport function addInstance(instance: Base) {\n getInstancesStorage().add(instance);\n getElementsStorage().add(instance.$el as HTMLElement & { __base__: Map<string, Base> });\n}\n\nexport function deleteInstance(instance: Base) {\n getInstancesStorage().delete(instance);\n getElementsStorage().delete(instance.$el as HTMLElement & { __base__: Map<string, Base> });\n}\n\n/**\n * Test whether an instance is currently registered in the global storage.\n * Membership is added on `before-mounted` and removed on `after-destroyed`,\n * so this is an O(1) check for \"is this instance live\" without copying the Set.\n */\nexport function hasInstance(instance: Base): boolean {\n return getInstancesStorage().has(instance);\n}\n\nconst registryKey = '__JS_TOOLKIT_REGISTRY__';\n\nfunction registry() {\n return (globalThis[registryKey] ??= new Map<string, BaseConstructor>());\n}\n\nfunction mutationCallback() {\n addToQueue(() => {\n for (const [nameOrSelector, ctor] of registry()) {\n for (const el of getComponentElements(nameOrSelector)) {\n if (!getInstanceFromElement(el, ctor)) {\n new ctor(el).$mount();\n }\n }\n }\n });\n\n addToQueue(() => {\n for (const instance of getInstances()) {\n if (!instance.$el.isConnected) {\n instance.$terminate();\n }\n }\n });\n}\n\nexport function addToRegistry(nameOrSelector: string, ctor: BaseConstructor) {\n if (registry().has(nameOrSelector)) {\n return;\n }\n\n registry().set(nameOrSelector, ctor);\n\n // Add children components to the registry\n if (ctor.config?.components) {\n for (const [selector, childConstructor] of Object.entries(ctor.config?.components)) {\n if ('$isBase' in childConstructor && childConstructor.$isBase) {\n addToRegistry(selector, childConstructor);\n }\n }\n }\n\n const mutation = useMutation(document, { childList: true, subtree: true });\n if (!mutation.has(registryKey)) {\n mutation.add(registryKey, mutationCallback);\n }\n}\n\n/**\n * Find the closest instance from the given element in the given set of Base instances.\n */\nexport function findClosestInstance<T extends Base = Base>(\n element: HTMLElement,\n instances: Set<T>,\n): T {\n let closest = null;\n let minDepth = Infinity;\n\n for (const instance of instances) {\n let depth = 0;\n let el = element;\n while (el && el !== instance.$el) {\n depth++;\n el = el.parentElement;\n }\n\n if (depth < minDepth) {\n minDepth = depth;\n closest = instance;\n }\n }\n\n return closest;\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,SAAS,WAAW,YAAY,
|
|
4
|
+
"sourcesContent": ["import { isArray, isDefined, SmartQueue, dashCase, isDev } from '../utils/index.js';\nimport type { Base, BaseConfig, BaseConstructor } from './index.js';\nimport { features } from './features.js';\nimport { useMutation } from '../services/MutationService.js';\nimport { getInstanceFromElement } from '../helpers/getInstanceFromElement.js';\n\nlet queue: SmartQueue;\n\n/**\n * Add a task to the main queue.\n */\nexport function addToQueue(fn: () => unknown) {\n if (features.get('blocking')) {\n fn();\n return;\n }\n\n if (!queue) {\n queue = new SmartQueue();\n }\n\n return queue.add(fn);\n}\n\nconst selectors = new Map();\n\n// Separator used for multi-component declaration in `data-component` attributeS.\nconst separator = ' ';\n\n/**\n * Get the selector for a given component.\n */\nexport function getSelector(nameOrSelector: string): string {\n const { component } = features.get('attributes');\n const prefix = features.get('prefix');\n const key = prefix + component + nameOrSelector;\n\n if (!selectors.has(key)) {\n const parts = [\n // Tag select\n `${prefix}-${dashCase(nameOrSelector)}`,\n // Single selector\n `[${component}=\"${nameOrSelector}\"]`,\n // Selector in the middle of a list of selectors\n `[${component}*=\"${separator}${nameOrSelector}${separator}\"]`,\n // Selector at the end of a list of selectors\n `[${component}$=\"${separator}${nameOrSelector}\"]`,\n // Selector at the beginning of a list of selectors\n `[${component}^=\"${nameOrSelector}${separator}\"]`,\n ];\n selectors.set(key, parts.join(','));\n }\n\n return selectors.get(key);\n}\n\n/**\n * Get a list of elements based on the name of a component.\n *\n * @param {string} nameOrSelector\n * The name or selector to used for this component.\n * @param {HTMLElement|Document} element\n * The root element on which to query the selector, defaults to `document`.\n * @return {Array<HTMLElement>}\n * A list of elements on which the component should be mounted.\n */\nexport function getComponentElements(\n nameOrSelector: string,\n element: HTMLElement | Document = document,\n): HTMLElement[] {\n const selector = getSelector(nameOrSelector);\n let elements = [];\n\n try {\n elements = Array.from(element.querySelectorAll(selector));\n // eslint-disable-next-line no-empty\n } catch {}\n\n // If no child component found with the default selector, and if the selector does not\n // start with an uppercase letter, matching a component's name, try a classic DOM selector.\n if (elements.length === 0 && nameOrSelector[0] === nameOrSelector[0].toLowerCase()) {\n elements = Array.from(element.querySelectorAll(nameOrSelector));\n }\n\n return elements;\n}\n\n/**\n * Test if an event is defined in the given config.\n */\nexport function eventIsDefinedInConfig(event: string, config: BaseConfig): boolean {\n return isArray(config.emits) && config.emits.includes(event);\n}\n\n/**\n * Test if an event can be used on the given element.\n */\nexport function eventIsNative(event: string, element: HTMLElement): boolean {\n return isDefined(element[`on${event}`]);\n}\n\n/**\n * Get the target of a given event.\n */\nexport function getEventTarget(instance: Base, event: string, config: BaseConfig): Base['$el'] {\n if (eventIsDefinedInConfig(event, config) || eventIsNative(event, instance.$el)) {\n return instance.$el;\n }\n}\n\n/**\n * Get the global instance storage.\n * We attach it to `globalThis` so it can be shared between different\n * instances of the framework.\n */\nfunction getInstancesStorage(): Set<Base> {\n return (globalThis.__JS_TOOLKIT_INSTANCES__ ??= new Set<Base>());\n}\n\n/**\n * Get the global elements storage.\n * It will hold reference to all elements with at least one component attached to it.\n */\nfunction getElementsStorage(): Set<HTMLElement & { __base__: Map<string, Base> }> {\n return (globalThis.__JS_TOOLKIT_ELEMENTS__ ??= new Set<\n HTMLElement & { __base__: Map<string, Base> }\n >());\n}\n\n/**\n * Get all mounted instances or the ones from a given component.\n * @link https://js-toolkit.studiometa.dev/api/helpers/getInstances.html\n */\nexport function getInstances(): ReadonlySet<Base>;\nexport function getInstances<T extends BaseConstructor = BaseConstructor>(\n ctor: T,\n): Set<InstanceType<T>>;\nexport function getInstances<T extends BaseConstructor = BaseConstructor>(\n ctor?: T,\n): ReadonlySet<InstanceType<T>> | ReadonlySet<Base> {\n if (isDefined(ctor)) {\n const filteredInstances = new Set<InstanceType<T>>();\n for (const instance of getInstancesStorage()) {\n if (instance instanceof ctor) {\n filteredInstances.add(instance as InstanceType<T>);\n }\n }\n return filteredInstances;\n }\n\n return new Set(getInstancesStorage());\n}\n\nexport function getElements() {\n return new Set(getElementsStorage());\n}\n\nexport function addInstance(instance: Base) {\n getInstancesStorage().add(instance);\n getElementsStorage().add(instance.$el as HTMLElement & { __base__: Map<string, Base> });\n}\n\nexport function deleteInstance(instance: Base) {\n getInstancesStorage().delete(instance);\n getElementsStorage().delete(instance.$el as HTMLElement & { __base__: Map<string, Base> });\n}\n\n/**\n * Test whether an instance is currently registered in the global storage.\n * Membership is added on `before-mounted` and removed on `after-destroyed`,\n * so this is an O(1) check for \"is this instance live\" without copying the Set.\n */\nexport function hasInstance(instance: Base): boolean {\n return getInstancesStorage().has(instance);\n}\n\nconst registryKey = '__JS_TOOLKIT_REGISTRY__';\n\nfunction registry() {\n return (globalThis[registryKey] ??= new Map<string, BaseConstructor>());\n}\n\nfunction mutationCallback() {\n addToQueue(() => {\n for (const [nameOrSelector, ctor] of registry()) {\n for (const el of getComponentElements(nameOrSelector)) {\n if (!getInstanceFromElement(el, ctor)) {\n new ctor(el).$mount();\n }\n }\n }\n });\n\n addToQueue(() => {\n for (const instance of getInstances()) {\n if (!instance.$el.isConnected) {\n instance.$terminate();\n }\n }\n });\n}\n\nexport function addToRegistry(nameOrSelector: string, ctor: BaseConstructor) {\n if (registry().has(nameOrSelector)) {\n if (isDev && registry().get(nameOrSelector) !== ctor) {\n console.warn(\n `[${nameOrSelector}] A different component is already registered under this name. ` +\n 'Registration is ignored \u2014 like `customElements.define`, a name maps to a single ' +\n 'component. Give this component a unique `config.name` (or use `withExtraConfig`, ' +\n 'which renames automatically).',\n );\n }\n return;\n }\n\n registry().set(nameOrSelector, ctor);\n\n // Add children components to the registry\n if (ctor.config?.components) {\n for (const [selector, childConstructor] of Object.entries(ctor.config?.components)) {\n if ('$isBase' in childConstructor && childConstructor.$isBase) {\n addToRegistry(selector, childConstructor);\n }\n }\n }\n\n const mutation = useMutation(document, { childList: true, subtree: true });\n if (!mutation.has(registryKey)) {\n mutation.add(registryKey, mutationCallback);\n }\n}\n\n/**\n * Find the closest instance from the given element in the given set of Base instances.\n */\nexport function findClosestInstance<T extends Base = Base>(\n element: HTMLElement,\n instances: Set<T>,\n): T {\n let closest = null;\n let minDepth = Infinity;\n\n for (const instance of instances) {\n let depth = 0;\n let el = element;\n while (el && el !== instance.$el) {\n depth++;\n el = el.parentElement;\n }\n\n if (depth < minDepth) {\n minDepth = depth;\n closest = instance;\n }\n }\n\n return closest;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -8,9 +8,32 @@ export interface WithGroupProps extends BaseProps {
|
|
|
8
8
|
export interface WithGroupInterface extends BaseInterface {
|
|
9
9
|
get $group(): Set<Base>;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Options for the `withGroup` decorator.
|
|
13
|
+
*/
|
|
14
|
+
export interface WithGroupOptions<T extends Base = Base, Scope extends object = object> {
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the scope an instance belongs to. Return `undefined` to fall back
|
|
17
|
+
* to the global (unscoped) registry.
|
|
18
|
+
*/
|
|
19
|
+
getScope?: (instance: T) => Scope | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the group name of an instance, optionally using its resolved scope.
|
|
22
|
+
* Defaults to `instance.$options.group`.
|
|
23
|
+
*/
|
|
24
|
+
getGroup?: (instance: T, scope: Scope | undefined) => string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Enumerate the scoped groups registered for a given scope.
|
|
28
|
+
*
|
|
29
|
+
* Returns the live `Map` of `${namespace}${group}` keys to their members set
|
|
30
|
+
* for the given scope, or an empty `Map` for unknown scopes. Unknown scopes are
|
|
31
|
+
* NOT registered as a side effect of reading.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getScopedGroups(scope: object): Map<string, Set<Base>>;
|
|
11
34
|
/**
|
|
12
35
|
* Add group features to easily bind multiple components together.
|
|
13
36
|
*
|
|
14
37
|
* @link https://js-toolkit.studiometa.dev/api/decorators/withGroup.html
|
|
15
38
|
*/
|
|
16
|
-
export declare function withGroup<S extends Base = Base>(BaseClass: typeof Base, namespace?: string): BaseDecorator<WithGroupInterface, S, WithGroupProps>;
|
|
39
|
+
export declare function withGroup<S extends Base = Base, Scope extends object = object>(BaseClass: typeof Base, namespace?: string, options?: WithGroupOptions<S, Scope>): BaseDecorator<WithGroupInterface, S, WithGroupProps>;
|
package/decorators/withGroup.js
CHANGED
|
@@ -1,7 +1,30 @@
|
|
|
1
1
|
function groups() {
|
|
2
2
|
return globalThis.__JS_TOOLKIT_GROUPS__ ??= /* @__PURE__ */ new Map();
|
|
3
3
|
}
|
|
4
|
-
|
|
4
|
+
const scopedGroups = /* @__PURE__ */ new WeakMap();
|
|
5
|
+
function getScopedGroups(scope) {
|
|
6
|
+
return scopedGroups.get(scope) ?? /* @__PURE__ */ new Map();
|
|
7
|
+
}
|
|
8
|
+
function resolveGroupSet(scope, key) {
|
|
9
|
+
if (scope) {
|
|
10
|
+
let map = scopedGroups.get(scope);
|
|
11
|
+
if (!map) {
|
|
12
|
+
map = /* @__PURE__ */ new Map();
|
|
13
|
+
scopedGroups.set(scope, map);
|
|
14
|
+
}
|
|
15
|
+
let set = map.get(key);
|
|
16
|
+
if (!set) {
|
|
17
|
+
set = /* @__PURE__ */ new Set();
|
|
18
|
+
map.set(key, set);
|
|
19
|
+
}
|
|
20
|
+
return set;
|
|
21
|
+
}
|
|
22
|
+
const registry = groups();
|
|
23
|
+
return registry.get(key) ?? registry.set(key, /* @__PURE__ */ new Set()).get(key);
|
|
24
|
+
}
|
|
25
|
+
function withGroup(BaseClass, namespace = "", options = {}) {
|
|
26
|
+
const getScope = options.getScope;
|
|
27
|
+
const getGroup = options.getGroup ?? ((instance) => instance.$options.group);
|
|
5
28
|
return class WithGroup extends BaseClass {
|
|
6
29
|
static config = {
|
|
7
30
|
...BaseClass.config,
|
|
@@ -9,12 +32,27 @@ function withGroup(BaseClass, namespace = "") {
|
|
|
9
32
|
group: String
|
|
10
33
|
}
|
|
11
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* The members set remembered at mount time, if any.
|
|
37
|
+
*
|
|
38
|
+
* @private
|
|
39
|
+
*/
|
|
40
|
+
__groupSnapshot = void 0;
|
|
41
|
+
/**
|
|
42
|
+
* Resolve the members set for the current scope and group.
|
|
43
|
+
*
|
|
44
|
+
* @private
|
|
45
|
+
*/
|
|
46
|
+
__resolveGroup() {
|
|
47
|
+
const scope = getScope?.(this);
|
|
48
|
+
const group = `${namespace}${getGroup(this, scope)}`;
|
|
49
|
+
return resolveGroupSet(scope, group);
|
|
50
|
+
}
|
|
12
51
|
/**
|
|
13
52
|
* Get the group set.
|
|
14
53
|
*/
|
|
15
54
|
get $group() {
|
|
16
|
-
const
|
|
17
|
-
const instances = groups().get(group) ?? groups().set(group, /* @__PURE__ */ new Set()).get(group);
|
|
55
|
+
const instances = this.__groupSnapshot ?? this.__resolveGroup();
|
|
18
56
|
for (const instance of instances) {
|
|
19
57
|
if (!instance.$el.isConnected) {
|
|
20
58
|
instances.delete(instance);
|
|
@@ -25,15 +63,19 @@ function withGroup(BaseClass, namespace = "") {
|
|
|
25
63
|
constructor(element) {
|
|
26
64
|
super(element);
|
|
27
65
|
this.$on("mounted", () => {
|
|
28
|
-
this.$group
|
|
66
|
+
const instances = this.$group;
|
|
67
|
+
instances.add(this);
|
|
68
|
+
this.__groupSnapshot = instances;
|
|
29
69
|
});
|
|
30
70
|
this.$on("destroyed", () => {
|
|
31
|
-
this
|
|
71
|
+
this.__groupSnapshot?.delete(this);
|
|
72
|
+
this.__groupSnapshot = void 0;
|
|
32
73
|
});
|
|
33
74
|
}
|
|
34
75
|
};
|
|
35
76
|
}
|
|
36
77
|
export {
|
|
78
|
+
getScopedGroups,
|
|
37
79
|
withGroup
|
|
38
80
|
};
|
|
39
81
|
//# sourceMappingURL=withGroup.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../packages/js-toolkit/decorators/withGroup.ts"],
|
|
4
|
-
"sourcesContent": ["import type { BaseDecorator, BaseInterface } from '../Base/types.js';\nimport type { Base, BaseProps, BaseConfig } from '../Base/index.js';\n\nexport interface WithGroupProps extends BaseProps {\n $options: {\n group: string;\n };\n}\n\nexport interface WithGroupInterface extends BaseInterface {\n get $group(): Set<Base>;\n}\n\n/**\n * Get global groups map.\n */\nfunction groups<T extends Base = Base>(): Map<string, Set<T>> {\n return (globalThis.__JS_TOOLKIT_GROUPS__ ??= new Map<string, Set<T>>());\n}\n\n/**\n * Add group features to easily bind multiple components together.\n *\n * @link https://js-toolkit.studiometa.dev/api/decorators/withGroup.html\n */\nexport function withGroup<S extends Base = Base>(\n BaseClass: typeof Base,\n namespace = '',\n): BaseDecorator<WithGroupInterface, S, WithGroupProps> {\n // @ts-expect-error Decorators can not be typed.\n return class WithGroup<T extends BaseProps = BaseProps> extends BaseClass<T & WithGroupProps> {\n static config: BaseConfig = {\n ...BaseClass.config,\n options: {\n group: String,\n },\n };\n\n /**\n *
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type { BaseDecorator, BaseInterface } from '../Base/types.js';\nimport type { Base, BaseProps, BaseConfig } from '../Base/index.js';\n\nexport interface WithGroupProps extends BaseProps {\n $options: {\n group: string;\n };\n}\n\nexport interface WithGroupInterface extends BaseInterface {\n get $group(): Set<Base>;\n}\n\n/**\n * Options for the `withGroup` decorator.\n */\nexport interface WithGroupOptions<T extends Base = Base, Scope extends object = object> {\n /**\n * Resolve the scope an instance belongs to. Return `undefined` to fall back\n * to the global (unscoped) registry.\n */\n getScope?: (instance: T) => Scope | undefined;\n /**\n * Resolve the group name of an instance, optionally using its resolved scope.\n * Defaults to `instance.$options.group`.\n */\n getGroup?: (instance: T, scope: Scope | undefined) => string;\n}\n\n/**\n * Get global groups map.\n */\nfunction groups<T extends Base = Base>(): Map<string, Set<T>> {\n return (globalThis.__JS_TOOLKIT_GROUPS__ ??= new Map<string, Set<T>>());\n}\n\n/**\n * Scoped groups registry, keyed by scope identity. Scopes are stored in a\n * `WeakMap` so they can be garbage-collected once no longer referenced.\n */\nconst scopedGroups = new WeakMap<object, Map<string, Set<Base>>>();\n\n/**\n * Enumerate the scoped groups registered for a given scope.\n *\n * Returns the live `Map` of `${namespace}${group}` keys to their members set\n * for the given scope, or an empty `Map` for unknown scopes. Unknown scopes are\n * NOT registered as a side effect of reading.\n */\nexport function getScopedGroups(scope: object): Map<string, Set<Base>> {\n return scopedGroups.get(scope) ?? new Map<string, Set<Base>>();\n}\n\n/**\n * Get the members set for a given `(scope, key)` pair, creating it if needed.\n * When `scope` is `undefined`, the global (unscoped) registry is used.\n */\nfunction resolveGroupSet(scope: object | undefined, key: string): Set<Base> {\n if (scope) {\n let map = scopedGroups.get(scope);\n if (!map) {\n map = new Map<string, Set<Base>>();\n scopedGroups.set(scope, map);\n }\n let set = map.get(key);\n if (!set) {\n set = new Set<Base>();\n map.set(key, set);\n }\n return set;\n }\n\n const registry = groups();\n return registry.get(key) ?? registry.set(key, new Set()).get(key)!;\n}\n\n/**\n * Add group features to easily bind multiple components together.\n *\n * @link https://js-toolkit.studiometa.dev/api/decorators/withGroup.html\n */\nexport function withGroup<S extends Base = Base, Scope extends object = object>(\n BaseClass: typeof Base,\n namespace = '',\n options: WithGroupOptions<S, Scope> = {},\n): BaseDecorator<WithGroupInterface, S, WithGroupProps> {\n const getScope = options.getScope;\n const getGroup = options.getGroup ?? ((instance: S) => instance.$options.group);\n\n // @ts-expect-error Decorators can not be typed.\n return class WithGroup<T extends BaseProps = BaseProps> extends BaseClass<T & WithGroupProps> {\n static config: BaseConfig = {\n ...BaseClass.config,\n options: {\n group: String,\n },\n };\n\n /**\n * The members set remembered at mount time, if any.\n *\n * @private\n */\n __groupSnapshot: Set<Base> | undefined = undefined;\n\n /**\n * Resolve the members set for the current scope and group.\n *\n * @private\n */\n __resolveGroup() {\n const scope = getScope?.(this as unknown as S);\n const group = `${namespace}${getGroup(this as unknown as S, scope)}`;\n return resolveGroupSet(scope, group);\n }\n\n /**\n * Get the group set.\n */\n get $group() {\n const instances = this.__groupSnapshot ?? this.__resolveGroup();\n\n for (const instance of instances) {\n if (!instance.$el.isConnected) {\n instances.delete(instance);\n }\n }\n\n return instances;\n }\n\n constructor(element: HTMLElement) {\n super(element);\n\n this.$on('mounted', () => {\n // Resolve the members set through the public `$group` getter so that\n // subclasses overriding it keep receiving the membership writes. At this\n // point `__groupSnapshot` is still `undefined`, so the base getter\n // resolves fresh (identical behaviour for non-overriding classes).\n // Remember the exact set the instance was added to so that on destroy a\n // member is always removed from the set it joined, even if the scope or\n // group would now resolve differently.\n const instances = this.$group;\n instances.add(this);\n this.__groupSnapshot = instances;\n });\n this.$on('destroyed', () => {\n this.__groupSnapshot?.delete(this);\n this.__groupSnapshot = undefined;\n });\n }\n };\n}\n"],
|
|
5
|
+
"mappings": "AAgCA,SAAS,SAAqD;AAC5D,SAAQ,WAAW,0BAA0B,oBAAI,IAAoB;AACvE;AAMA,MAAM,eAAe,oBAAI,QAAwC;AAS1D,SAAS,gBAAgB,OAAuC;AACrE,SAAO,aAAa,IAAI,KAAK,KAAK,oBAAI,IAAuB;AAC/D;AAMA,SAAS,gBAAgB,OAA2B,KAAwB;AAC1E,MAAI,OAAO;AACT,QAAI,MAAM,aAAa,IAAI,KAAK;AAChC,QAAI,CAAC,KAAK;AACR,YAAM,oBAAI,IAAuB;AACjC,mBAAa,IAAI,OAAO,GAAG;AAAA,IAC7B;AACA,QAAI,MAAM,IAAI,IAAI,GAAG;AACrB,QAAI,CAAC,KAAK;AACR,YAAM,oBAAI,IAAU;AACpB,UAAI,IAAI,KAAK,GAAG;AAAA,IAClB;AACA,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,OAAO;AACxB,SAAO,SAAS,IAAI,GAAG,KAAK,SAAS,IAAI,KAAK,oBAAI,IAAI,CAAC,EAAE,IAAI,GAAG;AAClE;AAOO,SAAS,UACd,WACA,YAAY,IACZ,UAAsC,CAAC,GACe;AACtD,QAAM,WAAW,QAAQ;AACzB,QAAM,WAAW,QAAQ,aAAa,CAAC,aAAgB,SAAS,SAAS;AAGzE,SAAO,MAAM,kBAAmD,UAA8B;AAAA,IAC5F,OAAO,SAAqB;AAAA,MAC1B,GAAG,UAAU;AAAA,MACb,SAAS;AAAA,QACP,OAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,kBAAyC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOzC,iBAAiB;AACf,YAAM,QAAQ,WAAW,IAAoB;AAC7C,YAAM,QAAQ,GAAG,SAAS,GAAG,SAAS,MAAsB,KAAK,CAAC;AAClE,aAAO,gBAAgB,OAAO,KAAK;AAAA,IACrC;AAAA;AAAA;AAAA;AAAA,IAKA,IAAI,SAAS;AACX,YAAM,YAAY,KAAK,mBAAmB,KAAK,eAAe;AAE9D,iBAAW,YAAY,WAAW;AAChC,YAAI,CAAC,SAAS,IAAI,aAAa;AAC7B,oBAAU,OAAO,QAAQ;AAAA,QAC3B;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,YAAY,SAAsB;AAChC,YAAM,OAAO;AAEb,WAAK,IAAI,WAAW,MAAM;AAQxB,cAAM,YAAY,KAAK;AACvB,kBAAU,IAAI,IAAI;AAClB,aAAK,kBAAkB;AAAA,MACzB,CAAC;AACD,WAAK,IAAI,aAAa,MAAM;AAC1B,aAAK,iBAAiB,OAAO,IAAI;AACjC,aAAK,kBAAkB;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { wrap } from "./wrap.js";
|
|
2
|
+
function fold(value, min, max) {
|
|
3
|
+
const range = max - min;
|
|
4
|
+
if (!Number.isFinite(range) || range <= 0) {
|
|
5
|
+
return min;
|
|
6
|
+
}
|
|
7
|
+
const cycle = range * 2;
|
|
8
|
+
const wrapped = wrap(value, min, min + cycle);
|
|
9
|
+
return wrapped > max ? 2 * max - wrapped : wrapped;
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
fold
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=fold.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../packages/js-toolkit/utils/math/fold.ts"],
|
|
4
|
+
"sourcesContent": ["import { wrap } from './wrap.js';\n\n/**\n * Fold a value back and forth in the min and max range.\n * @link https://js-toolkit.studiometa.dev/utils/math/fold.html\n */\nexport function fold(value: number, min: number, max: number): number {\n const range = max - min;\n\n if (!Number.isFinite(range) || range <= 0) {\n return min;\n }\n\n const cycle = range * 2;\n const wrapped = wrap(value, min, min + cycle);\n\n return wrapped > max ? 2 * max - wrapped : wrapped;\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,YAAY;AAMd,SAAS,KAAK,OAAe,KAAa,KAAqB;AACpE,QAAM,QAAQ,MAAM;AAEpB,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,GAAG;AACzC,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,QAAQ;AACtB,QAAM,UAAU,KAAK,OAAO,KAAK,MAAM,KAAK;AAE5C,SAAO,UAAU,MAAM,IAAI,MAAM,UAAU;AAC7C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/utils/math/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { createRange } from './createRange.js';
|
|
|
5
5
|
export { clamp } from './clamp.js';
|
|
6
6
|
export { clamp01 } from './clamp01.js';
|
|
7
7
|
export { damp } from './damp.js';
|
|
8
|
+
export { fold } from './fold.js';
|
|
8
9
|
export { spring } from './spring.js';
|
|
9
10
|
export { inertiaFinalValue } from './inertiaFinalValue.js';
|
|
10
11
|
export { lerp } from './lerp.js';
|
package/utils/math/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { createRange } from "./createRange.js";
|
|
|
5
5
|
import { clamp } from "./clamp.js";
|
|
6
6
|
import { clamp01 } from "./clamp01.js";
|
|
7
7
|
import { damp } from "./damp.js";
|
|
8
|
+
import { fold } from "./fold.js";
|
|
8
9
|
import { spring } from "./spring.js";
|
|
9
10
|
import { inertiaFinalValue } from "./inertiaFinalValue.js";
|
|
10
11
|
import { lerp } from "./lerp.js";
|
|
@@ -19,6 +20,7 @@ export {
|
|
|
19
20
|
createRange,
|
|
20
21
|
damp,
|
|
21
22
|
ease,
|
|
23
|
+
fold,
|
|
22
24
|
inertiaFinalValue,
|
|
23
25
|
lerp,
|
|
24
26
|
map,
|
package/utils/math/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../packages/js-toolkit/utils/math/index.ts"],
|
|
4
|
-
"sourcesContent": ["export * as ease from './ease.js';\nexport * from './createEases.js';\nexport * from './ease.js';\nexport { createRange } from './createRange.js';\nexport { clamp } from './clamp.js';\nexport { clamp01 } from './clamp01.js';\nexport { damp } from './damp.js';\nexport { spring } from './spring.js';\nexport { inertiaFinalValue } from './inertiaFinalValue.js';\nexport { lerp } from './lerp.js';\nexport { map } from './map.js';\nexport { round } from './round.js';\nexport { mean } from './mean.js';\nexport { smoothTo } from './smoothTo.js';\nexport { wrap } from './wrap.js';\n"],
|
|
5
|
-
"mappings": "AAAA,YAAY,UAAU;AACtB,cAAc;AACd,cAAc;AACd,SAAS,mBAAmB;AAC5B,SAAS,aAAa;AACtB,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,cAAc;AACvB,SAAS,yBAAyB;AAClC,SAAS,YAAY;AACrB,SAAS,WAAW;AACpB,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,gBAAgB;AACzB,SAAS,YAAY;",
|
|
4
|
+
"sourcesContent": ["export * as ease from './ease.js';\nexport * from './createEases.js';\nexport * from './ease.js';\nexport { createRange } from './createRange.js';\nexport { clamp } from './clamp.js';\nexport { clamp01 } from './clamp01.js';\nexport { damp } from './damp.js';\nexport { fold } from './fold.js';\nexport { spring } from './spring.js';\nexport { inertiaFinalValue } from './inertiaFinalValue.js';\nexport { lerp } from './lerp.js';\nexport { map } from './map.js';\nexport { round } from './round.js';\nexport { mean } from './mean.js';\nexport { smoothTo } from './smoothTo.js';\nexport { wrap } from './wrap.js';\n"],
|
|
5
|
+
"mappings": "AAAA,YAAY,UAAU;AACtB,cAAc;AACd,cAAc;AACd,SAAS,mBAAmB;AAC5B,SAAS,aAAa;AACtB,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,YAAY;AACrB,SAAS,cAAc;AACvB,SAAS,yBAAyB;AAClC,SAAS,YAAY;AACrB,SAAS,WAAW;AACpB,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,gBAAgB;AACzB,SAAS,YAAY;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/utils/math/wrap.js
CHANGED
package/utils/math/wrap.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../packages/js-toolkit/utils/math/wrap.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Wrap a value in the min and max range.\n * @link https://js-toolkit.studiometa.dev/utils/math/wrap.html\n */\nexport function wrap(value: number, min: number, max: number): number {\n const range = max - min;\n return min === max ? min : ((range + ((value - min) % range)) % range) + min;\n}\n"],
|
|
5
|
-
"mappings": "AAIO,SAAS,KAAK,OAAe,KAAa,KAAqB;AACpE,QAAM,QAAQ,MAAM;
|
|
4
|
+
"sourcesContent": ["/**\n * Wrap a value in the min and max range.\n * @link https://js-toolkit.studiometa.dev/utils/math/wrap.html\n */\nexport function wrap(value: number, min: number, max: number): number {\n const range = max - min;\n\n if (!Number.isFinite(range)) {\n return value;\n }\n\n return min === max ? min : ((range + ((value - min) % range)) % range) + min;\n}\n"],
|
|
5
|
+
"mappings": "AAIO,SAAS,KAAK,OAAe,KAAa,KAAqB;AACpE,QAAM,QAAQ,MAAM;AAEpB,MAAI,CAAC,OAAO,SAAS,KAAK,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,MAAM,OAAQ,SAAU,QAAQ,OAAO,SAAU,QAAS;AAC3E;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|