@studiometa/js-toolkit 3.0.0-alpha.1 → 3.0.0-alpha.10
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/Base.d.ts +7 -7
- package/Base/Base.js +67 -33
- package/Base/Base.js.map +2 -2
- package/Base/features.d.ts +6 -1
- package/Base/features.js +9 -1
- package/Base/features.js.map +2 -2
- package/Base/index.d.ts +1 -0
- package/Base/index.js +4 -0
- package/Base/index.js.map +2 -2
- package/Base/managers/AbstractManager.d.ts +3 -3
- package/Base/managers/ChildrenManager.d.ts +6 -6
- package/Base/managers/ChildrenManager.js +34 -20
- package/Base/managers/ChildrenManager.js.map +2 -2
- package/Base/managers/EventsManager.d.ts +6 -28
- package/Base/managers/EventsManager.js +54 -64
- package/Base/managers/EventsManager.js.map +2 -2
- package/Base/managers/OptionsManager.d.ts +6 -6
- package/Base/managers/OptionsManager.js +29 -23
- package/Base/managers/OptionsManager.js.map +3 -3
- package/Base/managers/RefsManager.d.ts +1 -1
- package/Base/managers/RefsManager.js +23 -34
- package/Base/managers/RefsManager.js.map +3 -3
- package/Base/managers/ResponsiveOptionsManager.js +7 -4
- package/Base/managers/ResponsiveOptionsManager.js.map +2 -2
- package/Base/utils.d.ts +10 -5
- package/Base/utils.js +36 -22
- package/Base/utils.js.map +2 -2
- package/README.md +107 -6
- package/decorators/index.d.ts +1 -0
- package/decorators/index.js +1 -0
- package/decorators/index.js.map +2 -2
- package/decorators/withBreakpointManager.js +6 -4
- package/decorators/withBreakpointManager.js.map +2 -2
- package/decorators/withBreakpointObserver.d.ts +0 -1
- package/decorators/withBreakpointObserver.js +4 -2
- package/decorators/withBreakpointObserver.js.map +2 -2
- package/decorators/withIntersectionObserver.js +2 -4
- package/decorators/withIntersectionObserver.js.map +2 -2
- package/decorators/withMountOnMediaQuery.js +2 -2
- package/decorators/withMountOnMediaQuery.js.map +2 -2
- package/decorators/withMountWhenInView.js +2 -2
- package/decorators/withMountWhenInView.js.map +2 -2
- package/decorators/withName.d.ts +6 -0
- package/decorators/withName.js +12 -0
- package/decorators/withName.js.map +7 -0
- package/helpers/createApp.d.ts +3 -5
- package/helpers/createApp.js +21 -11
- package/helpers/createApp.js.map +2 -2
- package/helpers/getDirectChildren.js +10 -5
- package/helpers/getDirectChildren.js.map +2 -2
- package/helpers/importWhenVisible.js +1 -2
- package/helpers/importWhenVisible.js.map +1 -1
- package/index.d.ts +2 -3
- package/index.js +2 -4
- package/index.js.map +2 -2
- package/package.json +2 -2
- package/services/resize.js +2 -3
- package/services/resize.js.map +2 -2
- package/services/scroll.d.ts +14 -0
- package/services/scroll.js +31 -13
- package/services/scroll.js.map +2 -2
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/index.js.map +2 -2
- package/utils/math/createRange.d.ts +4 -0
- package/utils/math/createRange.js +13 -0
- package/utils/math/createRange.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/memo.d.ts +5 -0
- package/utils/memo.js +14 -0
- package/utils/memo.js.map +7 -0
- package/utils/random.js +1 -1
- package/utils/random.js.map +1 -1
- package/utils/string/changeCase.d.ts +24 -0
- package/utils/string/changeCase.js +47 -0
- package/utils/string/changeCase.js.map +7 -0
- package/utils/string/index.d.ts +1 -0
- package/utils/string/index.js +1 -0
- package/utils/string/index.js.map +2 -2
- package/Base/managers/ActionManager.d.ts +0 -4
- package/Base/managers/ActionManager.js +0 -10
- package/Base/managers/ActionManager.js.map +0 -7
|
@@ -2,18 +2,16 @@ import { AbstractManager } from "./AbstractManager.js";
|
|
|
2
2
|
import {
|
|
3
3
|
isDev,
|
|
4
4
|
isArray,
|
|
5
|
-
isDefined,
|
|
6
5
|
getAncestorWhereUntil,
|
|
7
6
|
endsWith,
|
|
8
|
-
startsWith
|
|
7
|
+
startsWith,
|
|
8
|
+
memo,
|
|
9
|
+
camelCase
|
|
9
10
|
} from "../../utils/index.js";
|
|
11
|
+
import { features } from "../features.js";
|
|
10
12
|
const NORMALIZE_REF_NAME_REGEX = /\[\]$/;
|
|
11
13
|
const NAMESPACED_REF_REGEX = /^(.*\.)/;
|
|
12
|
-
const
|
|
13
|
-
function normalizeRefName(name) {
|
|
14
|
-
if (normalizedRefNamesCache.has(name)) {
|
|
15
|
-
return normalizedRefNamesCache.get(name);
|
|
16
|
-
}
|
|
14
|
+
const normalizeRefName = memo(function normalizeRefName2(name) {
|
|
17
15
|
let normalizedName = name;
|
|
18
16
|
if (endsWith(name, "[]")) {
|
|
19
17
|
normalizedName = normalizedName.replace(NORMALIZE_REF_NAME_REGEX, "");
|
|
@@ -21,14 +19,14 @@ function normalizeRefName(name) {
|
|
|
21
19
|
if (normalizedName.includes(".")) {
|
|
22
20
|
return normalizedName.replace(NAMESPACED_REF_REGEX, "");
|
|
23
21
|
}
|
|
24
|
-
normalizedRefNamesCache.set(name, normalizedName);
|
|
25
22
|
return normalizedName;
|
|
26
|
-
}
|
|
23
|
+
});
|
|
27
24
|
function refBelongToInstance(ref, rootElement, name) {
|
|
28
|
-
const
|
|
25
|
+
const attributes = features.get("attributes");
|
|
26
|
+
const isPrefixed = startsWith(ref.getAttribute(attributes.ref), name);
|
|
29
27
|
const firstComponentAncestor = getAncestorWhereUntil(
|
|
30
28
|
ref,
|
|
31
|
-
(el) => el && (isPrefixed ? el.
|
|
29
|
+
(el) => el && (isPrefixed ? el.getAttribute(attributes.component) === name && el : el.getAttribute(attributes.component)) && el !== rootElement,
|
|
32
30
|
(el) => el === rootElement
|
|
33
31
|
);
|
|
34
32
|
return firstComponentAncestor === rootElement;
|
|
@@ -37,32 +35,25 @@ function __register(that, refName) {
|
|
|
37
35
|
const isMultiple = endsWith(refName, "[]");
|
|
38
36
|
const propName = normalizeRefName(refName);
|
|
39
37
|
const { name } = that.__base.$options;
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
const attributes = features.get("attributes");
|
|
39
|
+
const refs = [];
|
|
40
|
+
const selector = `[${attributes.ref}="${refName}"],[${attributes.ref}="${name}.${refName}"]`;
|
|
41
|
+
for (const ref of that.__element.querySelectorAll(selector)) {
|
|
42
|
+
if (refBelongToInstance(ref, that.__element, name)) {
|
|
43
|
+
refs.push(ref);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
45
46
|
if (isDev && !isMultiple && refs.length > 1) {
|
|
46
47
|
console.warn(
|
|
47
|
-
|
|
48
|
-
`[${that.__base.$options.name}]`,
|
|
48
|
+
`[${that.__base.$id}]`,
|
|
49
49
|
`The "${refName}" ref has been found multiple times.`,
|
|
50
50
|
"Did you forgot to add the `[]` suffix to its name?"
|
|
51
51
|
);
|
|
52
52
|
}
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
console.warn(
|
|
56
|
-
// @ts-ignore
|
|
57
|
-
`[${that.__base.$options.name}]`,
|
|
58
|
-
`The "${refName}" ref is missing.`,
|
|
59
|
-
`Is there an \`[data-ref="${refName}"]\` element in the component's scope?`
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
return;
|
|
53
|
+
if (refs.length) {
|
|
54
|
+
that.__eventsManager.bindRef(refName, refs);
|
|
63
55
|
}
|
|
64
|
-
|
|
65
|
-
Object.defineProperty(that, propName, {
|
|
56
|
+
Object.defineProperty(that, camelCase(propName), {
|
|
66
57
|
// @todo remove usage of non-multiple refs as array
|
|
67
58
|
value: isMultiple || refs.length > 1 ? refs : refs[0],
|
|
68
59
|
enumerable: true,
|
|
@@ -85,15 +76,13 @@ class RefsManager extends AbstractManager {
|
|
|
85
76
|
* Register all refs.
|
|
86
77
|
*/
|
|
87
78
|
registerAll() {
|
|
88
|
-
for (const refName of this.__refs)
|
|
89
|
-
__register(this, refName);
|
|
79
|
+
for (const refName of this.__refs) __register(this, refName);
|
|
90
80
|
}
|
|
91
81
|
/**
|
|
92
82
|
* Unregister all refs.
|
|
93
83
|
*/
|
|
94
84
|
unregisterAll() {
|
|
95
|
-
for (const refName of this.__refs)
|
|
96
|
-
__unregister(this, refName);
|
|
85
|
+
for (const refName of this.__refs) __unregister(this, refName);
|
|
97
86
|
}
|
|
98
87
|
}
|
|
99
88
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../packages/js-toolkit/Base/managers/RefsManager.ts"],
|
|
4
|
-
"sourcesContent": ["import { AbstractManager } from './AbstractManager.js';\nimport {\n isDev,\n isArray,\n isDefined,\n getAncestorWhereUntil,\n endsWith,\n startsWith,\n} from '../../utils/index.js';\n\nconst NORMALIZE_REF_NAME_REGEX = /\\[\\]$/;\nconst NAMESPACED_REF_REGEX = /^(.*\\.)/;\
|
|
5
|
-
"mappings": "AAAA,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["import { AbstractManager } from './AbstractManager.js';\nimport {\n isDev,\n isArray,\n isDefined,\n getAncestorWhereUntil,\n endsWith,\n startsWith,\n memo,\n camelCase,\n} from '../../utils/index.js';\nimport { features } from '../features.js';\n\nconst NORMALIZE_REF_NAME_REGEX = /\\[\\]$/;\nconst NAMESPACED_REF_REGEX = /^(.*\\.)/;\n\n/**\n * Normalize the name of ref.\n */\nexport const normalizeRefName = memo(function normalizeRefName(name: string) {\n let normalizedName = name;\n\n if (endsWith(name, '[]')) {\n normalizedName = normalizedName.replace(NORMALIZE_REF_NAME_REGEX, '');\n }\n\n if (normalizedName.includes('.')) {\n return normalizedName.replace(NAMESPACED_REF_REGEX, '');\n }\n\n return normalizedName;\n});\n\n/**\n * Filter refs belonging to the related Base instance.\n */\nfunction refBelongToInstance(ref: HTMLElement, rootElement: HTMLElement, name: string) {\n const attributes = features.get('attributes');\n const isPrefixed = startsWith(ref.getAttribute(attributes.ref), name);\n const firstComponentAncestor = getAncestorWhereUntil(\n ref,\n (el) =>\n el &&\n (isPrefixed\n ? el.getAttribute(attributes.component) === name && el\n : el.getAttribute(attributes.component)) &&\n el !== rootElement,\n (el) => el === rootElement,\n );\n\n return firstComponentAncestor === rootElement;\n}\n\n/**\n * Register one ref.\n *\n * @param {RefsManager} that\n * @param {string} refName The ref name.\n * @private\n */\nfunction __register(that: RefsManager, refName: string) {\n const isMultiple = endsWith(refName, '[]');\n const propName = normalizeRefName(refName);\n const { name } = that.__base.$options;\n const attributes = features.get('attributes');\n const refs = [] as HTMLElement[];\n const selector = `[${attributes.ref}=\"${refName}\"],[${attributes.ref}=\"${name}.${refName}\"]`;\n\n for (const ref of that.__element.querySelectorAll<HTMLElement>(selector)) {\n if (refBelongToInstance(ref, that.__element, name)) {\n refs.push(ref);\n }\n }\n\n /* v8 ignore next 7 */\n if (isDev && !isMultiple && refs.length > 1) {\n console.warn(\n `[${that.__base.$id}]`,\n `The \"${refName}\" ref has been found multiple times.`,\n 'Did you forgot to add the `[]` suffix to its name?',\n );\n }\n\n if (refs.length) {\n that.__eventsManager.bindRef(refName, refs);\n }\n\n Object.defineProperty(that, camelCase(propName), {\n // @todo remove usage of non-multiple refs as array\n value: isMultiple || refs.length > 1 ? refs : refs[0],\n enumerable: true,\n configurable: true,\n });\n}\n\n/**\n * Unregister one ref.\n */\nfunction __unregister(that: RefsManager, refName: string) {\n const propName = normalizeRefName(refName);\n const refs = isArray(that[propName]) ? that[propName] : [that[propName]];\n that.__eventsManager.unbindRef(refName, refs);\n}\n\n/**\n * Refs Manager\n *\n * @todo Use `MutationObserver` to automatically update refs?\n */\nexport class RefsManager extends AbstractManager {\n /**\n * Get refs configuration.\n */\n get __refs() {\n return this.__config.refs ?? [];\n }\n\n /**\n * Register all refs.\n */\n registerAll() {\n for (const refName of this.__refs) __register(this, refName);\n }\n\n /**\n * Unregister all refs.\n */\n unregisterAll() {\n for (const refName of this.__refs) __unregister(this, refName);\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,gBAAgB;AAEzB,MAAM,2BAA2B;AACjC,MAAM,uBAAuB;AAKtB,MAAM,mBAAmB,KAAK,SAASA,kBAAiB,MAAc;AAC3E,MAAI,iBAAiB;AAErB,MAAI,SAAS,MAAM,IAAI,GAAG;AACxB,qBAAiB,eAAe,QAAQ,0BAA0B,EAAE;AAAA,EACtE;AAEA,MAAI,eAAe,SAAS,GAAG,GAAG;AAChC,WAAO,eAAe,QAAQ,sBAAsB,EAAE;AAAA,EACxD;AAEA,SAAO;AACT,CAAC;AAKD,SAAS,oBAAoB,KAAkB,aAA0B,MAAc;AACrF,QAAM,aAAa,SAAS,IAAI,YAAY;AAC5C,QAAM,aAAa,WAAW,IAAI,aAAa,WAAW,GAAG,GAAG,IAAI;AACpE,QAAM,yBAAyB;AAAA,IAC7B;AAAA,IACA,CAAC,OACC,OACC,aACG,GAAG,aAAa,WAAW,SAAS,MAAM,QAAQ,KAClD,GAAG,aAAa,WAAW,SAAS,MACxC,OAAO;AAAA,IACT,CAAC,OAAO,OAAO;AAAA,EACjB;AAEA,SAAO,2BAA2B;AACpC;AASA,SAAS,WAAW,MAAmB,SAAiB;AACtD,QAAM,aAAa,SAAS,SAAS,IAAI;AACzC,QAAM,WAAW,iBAAiB,OAAO;AACzC,QAAM,EAAE,KAAK,IAAI,KAAK,OAAO;AAC7B,QAAM,aAAa,SAAS,IAAI,YAAY;AAC5C,QAAM,OAAO,CAAC;AACd,QAAM,WAAW,IAAI,WAAW,GAAG,KAAK,OAAO,OAAO,WAAW,GAAG,KAAK,IAAI,IAAI,OAAO;AAExF,aAAW,OAAO,KAAK,UAAU,iBAA8B,QAAQ,GAAG;AACxE,QAAI,oBAAoB,KAAK,KAAK,WAAW,IAAI,GAAG;AAClD,WAAK,KAAK,GAAG;AAAA,IACf;AAAA,EACF;AAGA,MAAI,SAAS,CAAC,cAAc,KAAK,SAAS,GAAG;AAC3C,YAAQ;AAAA,MACN,IAAI,KAAK,OAAO,GAAG;AAAA,MACnB,QAAQ,OAAO;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,MAAI,KAAK,QAAQ;AACf,SAAK,gBAAgB,QAAQ,SAAS,IAAI;AAAA,EAC5C;AAEA,SAAO,eAAe,MAAM,UAAU,QAAQ,GAAG;AAAA;AAAA,IAE/C,OAAO,cAAc,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC;AAAA,IACpD,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB,CAAC;AACH;AAKA,SAAS,aAAa,MAAmB,SAAiB;AACxD,QAAM,WAAW,iBAAiB,OAAO;AACzC,QAAM,OAAO,QAAQ,KAAK,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,QAAQ,CAAC;AACvE,OAAK,gBAAgB,UAAU,SAAS,IAAI;AAC9C;AAOO,MAAM,oBAAoB,gBAAgB;AAAA;AAAA;AAAA;AAAA,EAI/C,IAAI,SAAS;AACX,WAAO,KAAK,SAAS,QAAQ,CAAC;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc;AACZ,eAAW,WAAW,KAAK,OAAQ,YAAW,MAAM,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB;AACd,eAAW,WAAW,KAAK,OAAQ,cAAa,MAAM,OAAO;AAAA,EAC/D;AACF;",
|
|
6
|
+
"names": ["normalizeRefName"]
|
|
7
7
|
}
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import { OptionsManager, __getPropertyName } from "./OptionsManager.js";
|
|
2
2
|
import { useResize } from "../../services/index.js";
|
|
3
3
|
import { isDev } from "../../utils/index.js";
|
|
4
|
+
import { features } from "../features.js";
|
|
4
5
|
function __getResponsiveName(that, name) {
|
|
5
6
|
const { breakpoint } = useResize().props();
|
|
6
7
|
if (!breakpoint) {
|
|
7
8
|
return name;
|
|
8
9
|
}
|
|
9
10
|
let responsiveName = name;
|
|
10
|
-
const propertyName = __getPropertyName(name);
|
|
11
|
-
const regex = new RegExp(`${propertyName}:(.+)
|
|
12
|
-
|
|
11
|
+
const propertyName = __getPropertyName(name).toLowerCase();
|
|
12
|
+
const regex = new RegExp(`${propertyName}:(.+)$`, "i");
|
|
13
|
+
const attributes = features.get("attributes");
|
|
14
|
+
const dataOptionRegExp = new RegExp(`^${attributes.option}-`);
|
|
15
|
+
for (const optionName of that.__element.getAttributeNames()) {
|
|
13
16
|
if (regex.test(optionName)) {
|
|
14
17
|
const [, breakpoints] = optionName.match(regex);
|
|
15
18
|
const isInBreakpoint = breakpoints.split(":").includes(breakpoint);
|
|
16
19
|
if (isInBreakpoint) {
|
|
17
|
-
responsiveName = optionName.replace(
|
|
20
|
+
responsiveName = optionName.replace(dataOptionRegExp, "");
|
|
18
21
|
}
|
|
19
22
|
}
|
|
20
23
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../packages/js-toolkit/Base/managers/ResponsiveOptionsManager.ts"],
|
|
4
|
-
"sourcesContent": ["import { OptionsManager, __getPropertyName } from './OptionsManager.js';\nimport type { OptionObject } from './OptionsManager.js';\nimport { useResize } from '../../services/index.js';\nimport { isDev } from '../../utils/index.js';\n\nexport type ResponsiveOptionObject = OptionObject & { responsive?: boolean };\n\n/**\n * Get the currently active responsive name of an option.\n *\n * @param {ResponsiveOptionsManager} that\n * @param {string} name The default name of the option.\n * @returns {string} The responsive name if one matches the current breakpoint, the default name otherwise.\n */\nfunction __getResponsiveName(that: ResponsiveOptionsManager, name: string) {\n const { breakpoint } = useResize().props();\n\n if (!breakpoint) {\n return name;\n }\n\n let responsiveName = name;\n const propertyName = __getPropertyName(name);\n const regex = new RegExp(`${propertyName}:(.+)
|
|
5
|
-
"mappings": "AAAA,SAAS,gBAAgB,yBAAyB;AAElD,SAAS,iBAAiB;AAC1B,SAAS,aAAa;
|
|
4
|
+
"sourcesContent": ["import { OptionsManager, __getPropertyName } from './OptionsManager.js';\nimport type { OptionObject } from './OptionsManager.js';\nimport { useResize } from '../../services/index.js';\nimport { isDev } from '../../utils/index.js';\nimport { features } from '../features.js';\n\nexport type ResponsiveOptionObject = OptionObject & { responsive?: boolean };\n\n/**\n * Get the currently active responsive name of an option.\n *\n * @param {ResponsiveOptionsManager} that\n * @param {string} name The default name of the option.\n * @returns {string} The responsive name if one matches the current breakpoint, the default name otherwise.\n */\nfunction __getResponsiveName(that: ResponsiveOptionsManager, name: string) {\n const { breakpoint } = useResize().props();\n\n if (!breakpoint) {\n return name;\n }\n\n let responsiveName = name;\n const propertyName = __getPropertyName(name).toLowerCase();\n const regex = new RegExp(`${propertyName}:(.+)$`, 'i');\n const attributes = features.get('attributes');\n const dataOptionRegExp = new RegExp(`^${attributes.option}-`);\n\n for (const optionName of that.__element.getAttributeNames()) {\n if (regex.test(optionName)) {\n const [, breakpoints] = optionName.match(regex);\n const isInBreakpoint = breakpoints.split(':').includes(breakpoint);\n if (isInBreakpoint) {\n responsiveName = optionName.replace(dataOptionRegExp, '');\n }\n }\n }\n\n return responsiveName;\n}\n\n/**\n * Class options to manage options as data attributes on an HTML element.\n */\nexport class ResponsiveOptionsManager extends OptionsManager {\n /**\n * Get an option value.\n *\n * @param {string} name The option name.\n * @param {ResponsiveOptionObject} config The option configuration.\n * @returns {any}\n */\n get(name: string, config: ResponsiveOptionObject) {\n if (!config.responsive) {\n return super.get(name, config);\n }\n\n return super.get(__getResponsiveName(this, name), config);\n }\n\n /**\n * Set an option value.\n *\n * @param {string} name The option name.\n * @param {any} value The new value.\n * @param {ResponsiveOptionObject} config The option configuration.\n */\n set(name: string, value: unknown, config: ResponsiveOptionObject) {\n if (!config.responsive) {\n super.set(name, value, config);\n return;\n }\n\n if (isDev) {\n console.warn(`[${this.__config.name}]`, 'Responsive options are read-only.');\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,gBAAgB,yBAAyB;AAElD,SAAS,iBAAiB;AAC1B,SAAS,aAAa;AACtB,SAAS,gBAAgB;AAWzB,SAAS,oBAAoB,MAAgC,MAAc;AACzE,QAAM,EAAE,WAAW,IAAI,UAAU,EAAE,MAAM;AAEzC,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AAEA,MAAI,iBAAiB;AACrB,QAAM,eAAe,kBAAkB,IAAI,EAAE,YAAY;AACzD,QAAM,QAAQ,IAAI,OAAO,GAAG,YAAY,UAAU,GAAG;AACrD,QAAM,aAAa,SAAS,IAAI,YAAY;AAC5C,QAAM,mBAAmB,IAAI,OAAO,IAAI,WAAW,MAAM,GAAG;AAE5D,aAAW,cAAc,KAAK,UAAU,kBAAkB,GAAG;AAC3D,QAAI,MAAM,KAAK,UAAU,GAAG;AAC1B,YAAM,CAAC,EAAE,WAAW,IAAI,WAAW,MAAM,KAAK;AAC9C,YAAM,iBAAiB,YAAY,MAAM,GAAG,EAAE,SAAS,UAAU;AACjE,UAAI,gBAAgB;AAClB,yBAAiB,WAAW,QAAQ,kBAAkB,EAAE;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,MAAM,iCAAiC,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ3D,IAAI,MAAc,QAAgC;AAChD,QAAI,CAAC,OAAO,YAAY;AACtB,aAAO,MAAM,IAAI,MAAM,MAAM;AAAA,IAC/B;AAEA,WAAO,MAAM,IAAI,oBAAoB,MAAM,IAAI,GAAG,MAAM;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,MAAc,OAAgB,QAAgC;AAChE,QAAI,CAAC,OAAO,YAAY;AACtB,YAAM,IAAI,MAAM,OAAO,MAAM;AAC7B;AAAA,IACF;AAEA,QAAI,OAAO;AACT,cAAQ,KAAK,IAAI,KAAK,SAAS,IAAI,KAAK,mCAAmC;AAAA,IAC7E;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/Base/utils.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Base, BaseConfig } from './index.js';
|
|
1
|
+
import type { Base, BaseConfig, BaseConstructor } from './index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Add a task to the main queue.
|
|
4
4
|
*/
|
|
5
|
-
export declare function addToQueue(fn: () => unknown):
|
|
5
|
+
export declare function addToQueue(fn: () => unknown): Promise<unknown>;
|
|
6
6
|
/**
|
|
7
7
|
* Get a list of elements based on the name of a component.
|
|
8
8
|
*
|
|
@@ -24,7 +24,12 @@ export declare function eventIsDefinedInConfig(event: string, config: BaseConfig
|
|
|
24
24
|
export declare function eventIsNative(event: string, element: HTMLElement): boolean;
|
|
25
25
|
/**
|
|
26
26
|
* Get the target of a given event.
|
|
27
|
-
*
|
|
28
|
-
* @todo Return false in v3 if event is not defined or not native to prevent adding a listener.
|
|
29
27
|
*/
|
|
30
|
-
export declare function getEventTarget(instance: Base, event: string, config: BaseConfig): Base
|
|
28
|
+
export declare function getEventTarget(instance: Base, event: string, config: BaseConfig): Base['$el'];
|
|
29
|
+
/**
|
|
30
|
+
* Get all mounted instances or the ones from a given component.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getInstances(): Set<Base>;
|
|
33
|
+
export declare function getInstances<T extends BaseConstructor = BaseConstructor>(ctor: T): Set<InstanceType<T>>;
|
|
34
|
+
export declare function addInstance(instance: Base): void;
|
|
35
|
+
export declare function deleteInstance(instance: Base): void;
|
package/Base/utils.js
CHANGED
|
@@ -1,33 +1,35 @@
|
|
|
1
|
-
import { isArray, isDefined,
|
|
1
|
+
import { isArray, isDefined, SmartQueue } from "../utils/index.js";
|
|
2
2
|
import { features } from "./features.js";
|
|
3
3
|
let queue;
|
|
4
4
|
function addToQueue(fn) {
|
|
5
|
-
if (
|
|
5
|
+
if (features.get("blocking")) {
|
|
6
6
|
fn();
|
|
7
7
|
return;
|
|
8
8
|
}
|
|
9
9
|
if (!queue) {
|
|
10
10
|
queue = new SmartQueue();
|
|
11
11
|
}
|
|
12
|
-
queue.add(fn);
|
|
12
|
+
return queue.add(fn);
|
|
13
13
|
}
|
|
14
14
|
const selectors = /* @__PURE__ */ new Map();
|
|
15
15
|
const separator = " ";
|
|
16
16
|
function getSelector(nameOrSelector) {
|
|
17
|
-
|
|
17
|
+
const { component } = features.get("attributes");
|
|
18
|
+
const key = component + nameOrSelector;
|
|
19
|
+
if (!selectors.has(key)) {
|
|
18
20
|
const parts = [
|
|
19
21
|
// Single selector
|
|
20
|
-
`[
|
|
22
|
+
`[${component}="${nameOrSelector}"]`,
|
|
21
23
|
// Selector in the middle of a list of selectors
|
|
22
|
-
`[
|
|
24
|
+
`[${component}*="${separator}${nameOrSelector}${separator}"]`,
|
|
23
25
|
// Selector at the end of a list of selectors
|
|
24
|
-
`[
|
|
26
|
+
`[${component}$="${separator}${nameOrSelector}"]`,
|
|
25
27
|
// Selector at the beginning of a list of selectors
|
|
26
|
-
`[
|
|
28
|
+
`[${component}^="${nameOrSelector}${separator}"]`
|
|
27
29
|
];
|
|
28
|
-
selectors.set(
|
|
30
|
+
selectors.set(key, parts.join(","));
|
|
29
31
|
}
|
|
30
|
-
return selectors.get(
|
|
32
|
+
return selectors.get(key);
|
|
31
33
|
}
|
|
32
34
|
function getComponentElements(nameOrSelector, element = document) {
|
|
33
35
|
const selector = getSelector(nameOrSelector);
|
|
@@ -48,26 +50,38 @@ function eventIsNative(event, element) {
|
|
|
48
50
|
return isDefined(element[`on${event}`]);
|
|
49
51
|
}
|
|
50
52
|
function getEventTarget(instance, event, config) {
|
|
51
|
-
if (eventIsDefinedInConfig(event, config)) {
|
|
52
|
-
return instance;
|
|
53
|
-
}
|
|
54
|
-
if (eventIsNative(event, instance.$el)) {
|
|
53
|
+
if (eventIsDefinedInConfig(event, config) || eventIsNative(event, instance.$el)) {
|
|
55
54
|
return instance.$el;
|
|
56
55
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
)
|
|
56
|
+
}
|
|
57
|
+
const instances = /* @__PURE__ */ new Set();
|
|
58
|
+
function getInstances(ctor) {
|
|
59
|
+
if (isDefined(ctor)) {
|
|
60
|
+
const filteredInstances = /* @__PURE__ */ new Set();
|
|
61
|
+
for (const instance of instances) {
|
|
62
|
+
if (instance instanceof ctor) {
|
|
63
|
+
filteredInstances.add(instance);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return filteredInstances;
|
|
67
|
+
} else {
|
|
68
|
+
return new Set(instances);
|
|
63
69
|
}
|
|
64
|
-
|
|
70
|
+
}
|
|
71
|
+
function addInstance(instance) {
|
|
72
|
+
instances.add(instance);
|
|
73
|
+
}
|
|
74
|
+
function deleteInstance(instance) {
|
|
75
|
+
instances.delete(instance);
|
|
65
76
|
}
|
|
66
77
|
export {
|
|
78
|
+
addInstance,
|
|
67
79
|
addToQueue,
|
|
80
|
+
deleteInstance,
|
|
68
81
|
eventIsDefinedInConfig,
|
|
69
82
|
eventIsNative,
|
|
70
83
|
getComponentElements,
|
|
71
|
-
getEventTarget
|
|
84
|
+
getEventTarget,
|
|
85
|
+
getInstances
|
|
72
86
|
};
|
|
73
87
|
//# sourceMappingURL=utils.js.map
|
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, isDev, SmartQueue } from '../utils/index.js';\nimport type { Base, BaseConfig } from './index.js';\nimport { features } from './features.js';\n\nlet queue: SmartQueue;\n\n/**\n * Add a task to the main queue.\n */\nexport function addToQueue(fn: () => unknown)
|
|
5
|
-
"mappings": "AAAA,SAAS,SAAS,
|
|
4
|
+
"sourcesContent": ["import { isArray, isDefined, isDev, SmartQueue } from '../utils/index.js';\nimport type { Base, BaseConfig, BaseConstructor } from './index.js';\nimport { features } from './features.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 */\nfunction getSelector(nameOrSelector: string): string {\n const { component } = features.get('attributes');\n const key = component + nameOrSelector;\n\n if (!selectors.has(key)) {\n const parts = [\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 * @returns {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(\n instance: Base,\n event: string,\n config: BaseConfig,\n): Base['$el'] {\n if (eventIsDefinedInConfig(event, config) || eventIsNative(event, instance.$el)) {\n return instance.$el;\n }\n}\n\nconst instances = new Set<Base>();\n\n/**\n * Get all mounted instances or the ones from a given component.\n */\nexport function getInstances(): Set<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): Set<InstanceType<T>> | Set<Base> {\n if (isDefined(ctor)) {\n const filteredInstances = new Set<InstanceType<T>>();\n for (const instance of instances) {\n if (instance instanceof ctor) {\n filteredInstances.add(instance as InstanceType<T>);\n }\n }\n return filteredInstances;\n } else {\n return new Set(instances);\n }\n}\n\nexport function addInstance(instance: Base) {\n instances.add(instance);\n}\n\nexport function deleteInstance(instance: Base) {\n instances.delete(instance);\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS,WAAkB,kBAAkB;AAEtD,SAAS,gBAAgB;AAEzB,IAAI;AAKG,SAAS,WAAW,IAAmB;AAC5C,MAAI,SAAS,IAAI,UAAU,GAAG;AAC5B,OAAG;AACH;AAAA,EACF;AAEA,MAAI,CAAC,OAAO;AACV,YAAQ,IAAI,WAAW;AAAA,EACzB;AAEA,SAAO,MAAM,IAAI,EAAE;AACrB;AAEA,MAAM,YAAY,oBAAI,IAAI;AAG1B,MAAM,YAAY;AAKlB,SAAS,YAAY,gBAAgC;AACnD,QAAM,EAAE,UAAU,IAAI,SAAS,IAAI,YAAY;AAC/C,QAAM,MAAM,YAAY;AAExB,MAAI,CAAC,UAAU,IAAI,GAAG,GAAG;AACvB,UAAM,QAAQ;AAAA;AAAA,MAEZ,IAAI,SAAS,KAAK,cAAc;AAAA;AAAA,MAEhC,IAAI,SAAS,MAAM,SAAS,GAAG,cAAc,GAAG,SAAS;AAAA;AAAA,MAEzD,IAAI,SAAS,MAAM,SAAS,GAAG,cAAc;AAAA;AAAA,MAE7C,IAAI,SAAS,MAAM,cAAc,GAAG,SAAS;AAAA,IAC/C;AACA,cAAU,IAAI,KAAK,MAAM,KAAK,GAAG,CAAC;AAAA,EACpC;AAEA,SAAO,UAAU,IAAI,GAAG;AAC1B;AAYO,SAAS,qBACd,gBACA,UAAkC,UACnB;AACf,QAAM,WAAW,YAAY,cAAc;AAC3C,MAAI,WAAW,CAAC;AAEhB,MAAI;AACF,eAAW,MAAM,KAAK,QAAQ,iBAAiB,QAAQ,CAAC;AAAA,EAE1D,QAAQ;AAAA,EAAC;AAIT,MAAI,SAAS,WAAW,KAAK,eAAe,CAAC,MAAM,eAAe,CAAC,EAAE,YAAY,GAAG;AAClF,eAAW,MAAM,KAAK,QAAQ,iBAAiB,cAAc,CAAC;AAAA,EAChE;AAEA,SAAO;AACT;AAKO,SAAS,uBAAuB,OAAe,QAA6B;AACjF,SAAO,QAAQ,OAAO,KAAK,KAAK,OAAO,MAAM,SAAS,KAAK;AAC7D;AAKO,SAAS,cAAc,OAAe,SAA+B;AAC1E,SAAO,UAAU,QAAQ,KAAK,KAAK,EAAE,CAAC;AACxC;AAKO,SAAS,eACd,UACA,OACA,QACa;AACb,MAAI,uBAAuB,OAAO,MAAM,KAAK,cAAc,OAAO,SAAS,GAAG,GAAG;AAC/E,WAAO,SAAS;AAAA,EAClB;AACF;AAEA,MAAM,YAAY,oBAAI,IAAU;AASzB,SAAS,aACd,MACkC;AAClC,MAAI,UAAU,IAAI,GAAG;AACnB,UAAM,oBAAoB,oBAAI,IAAqB;AACnD,eAAW,YAAY,WAAW;AAChC,UAAI,oBAAoB,MAAM;AAC5B,0BAAkB,IAAI,QAA2B;AAAA,MACnD;AAAA,IACF;AACA,WAAO;AAAA,EACT,OAAO;AACL,WAAO,IAAI,IAAI,SAAS;AAAA,EAC1B;AACF;AAEO,SAAS,YAAY,UAAgB;AAC1C,YAAU,IAAI,QAAQ;AACxB;AAEO,SAAS,eAAe,UAAgB;AAC7C,YAAU,OAAO,QAAQ;AAC3B;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @studiometa/js-toolkit
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@studiometa/js-toolkit/)
|
|
4
|
+
[](https://www.npmjs.com/package/@studiometa/js-toolkit/v/next)
|
|
5
|
+
[](https://www.npmjs.com/package/@studiometa/js-toolkit/)
|
|
6
|
+
[](https://bundlephobia.com/package/@studiometa/js-toolkit)
|
|
7
|
+
[](https://david-dm.org/studiometa/js-toolkit)
|
|
8
|
+

|
|
7
9
|
|
|
8
10
|
> A JavaScript data-attributes driven micro-framework shipped with plenty of useful utility functions to boost your project.
|
|
9
11
|
|
|
@@ -26,7 +28,106 @@ This project is a JavaScript micro-framework (along with its utility functions)
|
|
|
26
28
|
- Initializing components in the right place at the right time
|
|
27
29
|
- Defining dependencies between components
|
|
28
30
|
|
|
29
|
-
Visit [js-toolkit.studiometa.dev](https://js-toolkit.studiometa.dev) to learn more.
|
|
31
|
+
Visit [js-toolkit.studiometa.dev](https://js-toolkit.studiometa.dev) to learn more, or jump directly to [ui.studiometa.dev](https://ui.studiometa.dev) to discover existing components.
|
|
32
|
+
|
|
33
|
+
## Quick overview
|
|
34
|
+
|
|
35
|
+
This framework lets you define components as classes, and bind them to the DOM with `data-…` attributes. For example, here is how a `Counter` component would be defined in JavaScript:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
import { Base } from '@studiometa/js-toolkit';
|
|
39
|
+
|
|
40
|
+
export default class Counter extends Base {
|
|
41
|
+
static config = {
|
|
42
|
+
name: 'Counter',
|
|
43
|
+
refs: ['add', 'remove', 'count'],
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
get counter() {
|
|
47
|
+
return this.$refs.count.valueAsNumber;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
set counter(value) {
|
|
51
|
+
this.$refs.count.value = value;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
onAddClick() {
|
|
55
|
+
this.counter += 1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
onRemoveClick() {
|
|
59
|
+
this.counter -= 1;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
And its accompanying HTML would be sprinkled with `data-…` attributes to bind elements from the DOM to the JavaScript class.
|
|
65
|
+
|
|
66
|
+
```html
|
|
67
|
+
<div data-component="Counter">
|
|
68
|
+
<button data-ref="add">Add</button>
|
|
69
|
+
<button data-ref="remove">Remove</button>
|
|
70
|
+
<input data-ref="count" type="number" value="0" />
|
|
71
|
+
</div>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
You can define options that can be specified with `data-option-...` attributes as well. First in JavaScript:
|
|
75
|
+
|
|
76
|
+
```diff
|
|
77
|
+
class Counter extends Base {
|
|
78
|
+
static config = {
|
|
79
|
+
name: 'Counter',
|
|
80
|
+
refs: ['add', 'remove', 'count'],
|
|
81
|
+
+ options: {
|
|
82
|
+
+ step: {
|
|
83
|
+
+ type: Number,
|
|
84
|
+
+ default: 1,
|
|
85
|
+
+ },
|
|
86
|
+
+ },
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
onAddClick() {
|
|
90
|
+
- this.counter += 1;
|
|
91
|
+
+ this.counter += this.$options.step;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
onRemoveClick() {
|
|
95
|
+
- this.counter -= 1;
|
|
96
|
+
+ this.counter -= this.$options.step;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
And then adjust it as you wish in your HTML:
|
|
102
|
+
|
|
103
|
+
```diff
|
|
104
|
+
- <div data-component="Counter">
|
|
105
|
+
+ <div data-component="Counter" data-option-step="2">
|
|
106
|
+
<button data-ref="add">Add</button>
|
|
107
|
+
<button data-ref="remove">Remove</button>
|
|
108
|
+
<input data-ref="count" type="number" value="0">
|
|
109
|
+
</div>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The framework also offers a way to instantiate a root component as an application, with child components as dependencies:
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
import { Base, createApp } from '@studiometa/js-toolkit';
|
|
116
|
+
import Counter from './components/Counter.js';
|
|
117
|
+
|
|
118
|
+
class App extends Base {
|
|
119
|
+
static config = {
|
|
120
|
+
name: 'App',
|
|
121
|
+
components: {
|
|
122
|
+
Counter,
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export default createApp(App);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Visit our ["Getting Started" guide](https://js-toolkit.studiometa.dev/guide/) to learn more and try the above component by visiting [the playground](https://ui.studiometa.dev/-/play/#script=eNqVkjFPwzAQhff%2BijcguRVtEGurSpTuDKyIwdiXYprYkX2pQFX%2BO7bjlg6A1EiJndO97873bNrOecYRjzLQHMqTZNp0HQbU3rUQD4F7bVxLLO8%2BwoKda%2FaGxWoyUY0MAVvXWyYP%2BmSyOmQOjhMgsGSjoJytzQ7rHAOsbGkJUVRinoOe6rDEi5BaizmEp9YdKO1UShOvY5br2DgbE0dSqkDdzx%2FAX11kP%2FXtG%2FlRkh5NtewbXuL%2BFBvGzRC%2FQzwHsCOOfeaOprMC9MS9t%2BB3E6qb1GCVM6qDbHrahLHKKiESIVwQcsYJ87s%2BjiOvZ72zG623jVH7cwNZWZi4XRdSGUKVzn6hfs4j%2Bwew%2BBsQEaOVyfbrbIyKYqFy8SJZsnzhTzG5TDstcdyp2umSTeM7W30DtazCdQ%3D%3D&html=eNqFkEsKwzAMRPc9hdDe5EOXcaD0Br2BEyvBkMjGkUN7%2Byb1ogkUupJAmjfMNNatYI0Y1fs5eCYWjXefWChiPvggzrNahILGGqGfzLJoDOoKw0RPGM22YnsBaLok4jnLIg0ajbUHQQ3dqLopkarKEuLmYslie7O2KbL0NyXS7Ff6D3p8%2Fk4sxyHJAdXv0RDkFUgjp7nbY65mQ2ksTw7R8aiqPBwvJF%2BfS1NstbVv4jxoZA%3D%3D&style=eNpLyk%2BpVKjmUlAoSExJycxLt1IwLErNteaqBQBpsgf8). Discover our existing library of components by checking out the [@studiometa/ui](https://github.com/studiometa/ui) package.
|
|
30
131
|
|
|
31
132
|
## Contributing
|
|
32
133
|
|
package/decorators/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './withIntersectionObserver.js';
|
|
|
7
7
|
export * from './withMountOnMediaQuery.js';
|
|
8
8
|
export * from './withMountWhenInView.js';
|
|
9
9
|
export * from './withMountWhenPrefersMotion.js';
|
|
10
|
+
export * from './withName.js';
|
|
10
11
|
export * from './withRelativePointer.js';
|
|
11
12
|
export * from './withResponsiveOptions.js';
|
|
12
13
|
export * from './withScrolledInView/index.js';
|
package/decorators/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./withIntersectionObserver.js";
|
|
|
7
7
|
export * from "./withMountOnMediaQuery.js";
|
|
8
8
|
export * from "./withMountWhenInView.js";
|
|
9
9
|
export * from "./withMountWhenPrefersMotion.js";
|
|
10
|
+
export * from "./withName.js";
|
|
10
11
|
export * from "./withRelativePointer.js";
|
|
11
12
|
export * from "./withResponsiveOptions.js";
|
|
12
13
|
export * from "./withScrolledInView/index.js";
|
package/decorators/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../packages/js-toolkit/decorators/index.ts"],
|
|
4
|
-
"sourcesContent": ["export * from './withBreakpointManager.js';\nexport * from './withBreakpointObserver.js';\nexport * from './withDrag.js';\nexport * from './withExtraConfig.js';\nexport * from './withFreezedOptions.js';\nexport * from './withIntersectionObserver.js';\nexport * from './withMountOnMediaQuery.js';\nexport * from './withMountWhenInView.js';\nexport * from './withMountWhenPrefersMotion.js';\nexport * from './withRelativePointer.js';\nexport * from './withResponsiveOptions.js';\nexport * from './withScrolledInView/index.js';\n"],
|
|
5
|
-
"mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
4
|
+
"sourcesContent": ["export * from './withBreakpointManager.js';\nexport * from './withBreakpointObserver.js';\nexport * from './withDrag.js';\nexport * from './withExtraConfig.js';\nexport * from './withFreezedOptions.js';\nexport * from './withIntersectionObserver.js';\nexport * from './withMountOnMediaQuery.js';\nexport * from './withMountWhenInView.js';\nexport * from './withMountWhenPrefersMotion.js';\nexport * from './withName.js';\nexport * from './withRelativePointer.js';\nexport * from './withResponsiveOptions.js';\nexport * from './withScrolledInView/index.js';\n"],
|
|
5
|
+
"mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -55,20 +55,22 @@ function withBreakpointManager(BaseClass, breakpoints) {
|
|
|
55
55
|
* Override the default $mount method to prevent component's from being
|
|
56
56
|
* mounted when they should not.
|
|
57
57
|
*/
|
|
58
|
-
$mount() {
|
|
59
|
-
super.$mount();
|
|
58
|
+
async $mount() {
|
|
59
|
+
await super.$mount();
|
|
60
60
|
testBreakpoints(instances.get(this));
|
|
61
61
|
return this;
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
64
|
* Destroy all instances when the main one is destroyed.
|
|
65
65
|
*/
|
|
66
|
-
$destroy() {
|
|
66
|
+
async $destroy() {
|
|
67
|
+
const promises = [];
|
|
67
68
|
if (isArray(instances.get(this))) {
|
|
68
69
|
for (const [, instance] of instances.get(this)) {
|
|
69
|
-
instance.$destroy();
|
|
70
|
+
promises.push(instance.$destroy());
|
|
70
71
|
}
|
|
71
72
|
}
|
|
73
|
+
await Promise.all(promises);
|
|
72
74
|
return super.$destroy();
|
|
73
75
|
}
|
|
74
76
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../packages/js-toolkit/decorators/withBreakpointManager.ts"],
|
|
4
|
-
"sourcesContent": ["import type { BaseDecorator, BaseInterface } from '../Base/types.js';\nimport type { Base, BaseConstructor, BaseProps } from '../Base/index.js';\nimport { useResize } from '../services/index.js';\nimport { isDev, isArray } from '../utils/index.js';\n\n/**\n * Test the breakpoins of the given Base instance and return the hook to call.\n */\nfunction testBreakpoints(breakpoints: Array<[string[], Base]>) {\n const { breakpoint } = useResize().props();\n for (const [breakpointKeys, instance] of breakpoints) {\n if (breakpointKeys.includes(breakpoint) && !instance.$isMounted) {\n setTimeout(() => instance.$mount(), 0);\n } else if (!breakpointKeys.includes(breakpoint) && instance.$isMounted) {\n instance.$destroy();\n }\n }\n}\n\n/**\n * Prepare the components.\n */\nfunction mountComponents(\n instance: Base,\n breakpoints: Array<[string, BaseConstructor]>,\n): Array<[string[], Base]> {\n return breakpoints.map(([bk, ComponentClass]) => {\n const child = new ComponentClass(instance.$el);\n Object.defineProperty(child, '$parent', { get: () => instance.$parent });\n return [bk.split(' '), child];\n });\n}\n\n/**\n * A cache object to hold each Base sub-instances.\n */\nconst instances: WeakMap<Base, Array<[string[], Base]>> = new WeakMap();\n\n/**\n * BreakpointManager class.\n */\nexport function withBreakpointManager<S extends Base>(\n BaseClass: typeof Base,\n breakpoints: Array<[string, BaseConstructor<Base>]>,\n): BaseDecorator<BaseInterface, S> {\n if (!isArray(breakpoints)) {\n if (isDev) {\n throw new Error('[withBreakpointManager] The `breakpoints` parameter must be an array.');\n }\n\n // @ts-ignore\n return BaseClass;\n }\n\n if (breakpoints.length < 2) {\n if (isDev) {\n throw new Error('[withBreakpointManager] You must define at least 2 breakpoints.');\n }\n\n // @ts-ignore\n return BaseClass;\n }\n\n const { add, props } = useResize();\n\n // Do nothing if no breakpoint has been defined.\n // @see https://js-toolkit.meta.fr/services/resize.html#breakpoint\n if (!props().breakpoint) {\n if (isDev) {\n throw new Error('The `BreakpointManager` class requires breakpoints to be defined.');\n }\n\n // @ts-ignore\n return BaseClass;\n }\n\n /**\n * Class.\n */\n class WithBreakpointManager<T extends BaseProps = BaseProps> extends BaseClass<T> {\n /**\n * Watch for the document resize to test the breakpoints.\n */\n constructor(element: HTMLElement) {\n super(element);\n\n if (!instances.has(this)) {\n instances.set(this, mountComponents(this, breakpoints));\n }\n\n add(`BreakpointManager-${this.$id}`, () => {\n testBreakpoints(instances.get(this));\n });\n }\n\n /**\n * Override the default $mount method to prevent component's from being\n * mounted when they should not.\n */\n $mount()
|
|
5
|
-
"mappings": "AAEA,SAAS,iBAAiB;AAC1B,SAAS,OAAO,eAAe;AAK/B,SAAS,gBAAgB,aAAsC;AAC7D,QAAM,EAAE,WAAW,IAAI,UAAU,EAAE,MAAM;AACzC,aAAW,CAAC,gBAAgB,QAAQ,KAAK,aAAa;AACpD,QAAI,eAAe,SAAS,UAAU,KAAK,CAAC,SAAS,YAAY;AAC/D,iBAAW,MAAM,SAAS,OAAO,GAAG,CAAC;AAAA,IACvC,WAAW,CAAC,eAAe,SAAS,UAAU,KAAK,SAAS,YAAY;AACtE,eAAS,SAAS;AAAA,IACpB;AAAA,EACF;AACF;AAKA,SAAS,gBACP,UACA,aACyB;AACzB,SAAO,YAAY,IAAI,CAAC,CAAC,IAAI,cAAc,MAAM;AAC/C,UAAM,QAAQ,IAAI,eAAe,SAAS,GAAG;AAC7C,WAAO,eAAe,OAAO,WAAW,EAAE,KAAK,MAAM,SAAS,QAAQ,CAAC;AACvE,WAAO,CAAC,GAAG,MAAM,GAAG,GAAG,KAAK;AAAA,EAC9B,CAAC;AACH;AAKA,MAAM,YAAoD,oBAAI,QAAQ;AAK/D,SAAS,sBACd,WACA,aACiC;AACjC,MAAI,CAAC,QAAQ,WAAW,GAAG;AACzB,QAAI,OAAO;AACT,YAAM,IAAI,MAAM,uEAAuE;AAAA,IACzF;AAGA,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,SAAS,GAAG;AAC1B,QAAI,OAAO;AACT,YAAM,IAAI,MAAM,iEAAiE;AAAA,IACnF;AAGA,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,KAAK,MAAM,IAAI,UAAU;AAIjC,MAAI,CAAC,MAAM,EAAE,YAAY;AACvB,QAAI,OAAO;AACT,YAAM,IAAI,MAAM,mEAAmE;AAAA,IACrF;AAGA,WAAO;AAAA,EACT;AAAA,EAKA,MAAM,8BAA+D,UAAa;AAAA;AAAA;AAAA;AAAA,IAIhF,YAAY,SAAsB;AAChC,YAAM,OAAO;AAEb,UAAI,CAAC,UAAU,IAAI,IAAI,GAAG;AACxB,kBAAU,IAAI,MAAM,gBAAgB,MAAM,WAAW,CAAC;AAAA,MACxD;AAEA,UAAI,qBAAqB,KAAK,GAAG,IAAI,MAAM;AACzC,wBAAgB,UAAU,IAAI,IAAI,CAAC;AAAA,MACrC,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,
|
|
4
|
+
"sourcesContent": ["import type { BaseDecorator, BaseInterface } from '../Base/types.js';\nimport type { Base, BaseConstructor, BaseProps } from '../Base/index.js';\nimport { useResize } from '../services/index.js';\nimport { isDev, isArray } from '../utils/index.js';\n\n/**\n * Test the breakpoins of the given Base instance and return the hook to call.\n */\nfunction testBreakpoints(breakpoints: Array<[string[], Base]>) {\n const { breakpoint } = useResize().props();\n for (const [breakpointKeys, instance] of breakpoints) {\n if (breakpointKeys.includes(breakpoint) && !instance.$isMounted) {\n setTimeout(() => instance.$mount(), 0);\n } else if (!breakpointKeys.includes(breakpoint) && instance.$isMounted) {\n instance.$destroy();\n }\n }\n}\n\n/**\n * Prepare the components.\n */\nfunction mountComponents(\n instance: Base,\n breakpoints: Array<[string, BaseConstructor]>,\n): Array<[string[], Base]> {\n return breakpoints.map(([bk, ComponentClass]) => {\n const child = new ComponentClass(instance.$el);\n Object.defineProperty(child, '$parent', { get: () => instance.$parent });\n return [bk.split(' '), child];\n });\n}\n\n/**\n * A cache object to hold each Base sub-instances.\n */\nconst instances: WeakMap<Base, Array<[string[], Base]>> = new WeakMap();\n\n/**\n * BreakpointManager class.\n */\nexport function withBreakpointManager<S extends Base>(\n BaseClass: typeof Base,\n breakpoints: Array<[string, BaseConstructor<Base>]>,\n): BaseDecorator<BaseInterface, S> {\n if (!isArray(breakpoints)) {\n if (isDev) {\n throw new Error('[withBreakpointManager] The `breakpoints` parameter must be an array.');\n }\n\n // @ts-ignore\n return BaseClass;\n }\n\n if (breakpoints.length < 2) {\n if (isDev) {\n throw new Error('[withBreakpointManager] You must define at least 2 breakpoints.');\n }\n\n // @ts-ignore\n return BaseClass;\n }\n\n const { add, props } = useResize();\n\n // Do nothing if no breakpoint has been defined.\n // @see https://js-toolkit.meta.fr/services/resize.html#breakpoint\n if (!props().breakpoint) {\n if (isDev) {\n throw new Error('The `BreakpointManager` class requires breakpoints to be defined.');\n }\n\n // @ts-ignore\n return BaseClass;\n }\n\n /**\n * Class.\n */\n class WithBreakpointManager<T extends BaseProps = BaseProps> extends BaseClass<T> {\n /**\n * Watch for the document resize to test the breakpoints.\n */\n constructor(element: HTMLElement) {\n super(element);\n\n if (!instances.has(this)) {\n instances.set(this, mountComponents(this, breakpoints));\n }\n\n add(`BreakpointManager-${this.$id}`, () => {\n testBreakpoints(instances.get(this));\n });\n }\n\n /**\n * Override the default $mount method to prevent component's from being\n * mounted when they should not.\n */\n async $mount() {\n await super.$mount();\n\n testBreakpoints(instances.get(this));\n\n return this;\n }\n\n /**\n * Destroy all instances when the main one is destroyed.\n */\n async $destroy() {\n const promises = [];\n if (isArray(instances.get(this))) {\n for (const [, instance] of instances.get(this)) {\n promises.push(instance.$destroy());\n }\n }\n\n await Promise.all(promises);\n\n return super.$destroy();\n }\n }\n\n // @ts-ignore\n return WithBreakpointManager;\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,iBAAiB;AAC1B,SAAS,OAAO,eAAe;AAK/B,SAAS,gBAAgB,aAAsC;AAC7D,QAAM,EAAE,WAAW,IAAI,UAAU,EAAE,MAAM;AACzC,aAAW,CAAC,gBAAgB,QAAQ,KAAK,aAAa;AACpD,QAAI,eAAe,SAAS,UAAU,KAAK,CAAC,SAAS,YAAY;AAC/D,iBAAW,MAAM,SAAS,OAAO,GAAG,CAAC;AAAA,IACvC,WAAW,CAAC,eAAe,SAAS,UAAU,KAAK,SAAS,YAAY;AACtE,eAAS,SAAS;AAAA,IACpB;AAAA,EACF;AACF;AAKA,SAAS,gBACP,UACA,aACyB;AACzB,SAAO,YAAY,IAAI,CAAC,CAAC,IAAI,cAAc,MAAM;AAC/C,UAAM,QAAQ,IAAI,eAAe,SAAS,GAAG;AAC7C,WAAO,eAAe,OAAO,WAAW,EAAE,KAAK,MAAM,SAAS,QAAQ,CAAC;AACvE,WAAO,CAAC,GAAG,MAAM,GAAG,GAAG,KAAK;AAAA,EAC9B,CAAC;AACH;AAKA,MAAM,YAAoD,oBAAI,QAAQ;AAK/D,SAAS,sBACd,WACA,aACiC;AACjC,MAAI,CAAC,QAAQ,WAAW,GAAG;AACzB,QAAI,OAAO;AACT,YAAM,IAAI,MAAM,uEAAuE;AAAA,IACzF;AAGA,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,SAAS,GAAG;AAC1B,QAAI,OAAO;AACT,YAAM,IAAI,MAAM,iEAAiE;AAAA,IACnF;AAGA,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,KAAK,MAAM,IAAI,UAAU;AAIjC,MAAI,CAAC,MAAM,EAAE,YAAY;AACvB,QAAI,OAAO;AACT,YAAM,IAAI,MAAM,mEAAmE;AAAA,IACrF;AAGA,WAAO;AAAA,EACT;AAAA,EAKA,MAAM,8BAA+D,UAAa;AAAA;AAAA;AAAA;AAAA,IAIhF,YAAY,SAAsB;AAChC,YAAM,OAAO;AAEb,UAAI,CAAC,UAAU,IAAI,IAAI,GAAG;AACxB,kBAAU,IAAI,MAAM,gBAAgB,MAAM,WAAW,CAAC;AAAA,MACxD;AAEA,UAAI,qBAAqB,KAAK,GAAG,IAAI,MAAM;AACzC,wBAAgB,UAAU,IAAI,IAAI,CAAC;AAAA,MACrC,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,MAAM,SAAS;AACb,YAAM,MAAM,OAAO;AAEnB,sBAAgB,UAAU,IAAI,IAAI,CAAC;AAEnC,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA,IAKA,MAAM,WAAW;AACf,YAAM,WAAW,CAAC;AAClB,UAAI,QAAQ,UAAU,IAAI,IAAI,CAAC,GAAG;AAChC,mBAAW,CAAC,EAAE,QAAQ,KAAK,UAAU,IAAI,IAAI,GAAG;AAC9C,mBAAS,KAAK,SAAS,SAAS,CAAC;AAAA,QACnC;AAAA,MACF;AAEA,YAAM,QAAQ,IAAI,QAAQ;AAE1B,aAAO,MAAM,SAAS;AAAA,IACxB;AAAA,EACF;AAGA,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useResize } from "../services/index.js";
|
|
2
2
|
import { isDev, startsWith } from "../utils/index.js";
|
|
3
|
+
import { features } from "../Base/features.js";
|
|
3
4
|
function testBreakpoints(instance, breakpoint = useResize().props().breakpoint) {
|
|
4
5
|
const { activeBreakpoints, inactiveBreakpoints } = instance.$options;
|
|
5
6
|
const isInActiveBreakpoint = activeBreakpoints && activeBreakpoints.split(" ").includes(breakpoint);
|
|
@@ -67,8 +68,9 @@ function withBreakpointObserver(BaseClass) {
|
|
|
67
68
|
return;
|
|
68
69
|
}
|
|
69
70
|
const key = `BreakpointObserver-${this.$id}`;
|
|
71
|
+
const attributes = features.get("attributes");
|
|
70
72
|
const mutationObserver = new MutationObserver(([mutation]) => {
|
|
71
|
-
if (mutation.type === "attributes" &&
|
|
73
|
+
if (mutation.type === "attributes" && startsWith(mutation.attributeName, `${attributes.option}-`)) {
|
|
72
74
|
if (!hasBreakpointConfiguration(this)) {
|
|
73
75
|
this.$mount();
|
|
74
76
|
remove(key);
|
|
@@ -87,7 +89,7 @@ function withBreakpointObserver(BaseClass) {
|
|
|
87
89
|
* Override the default $mount method to prevent component's from being
|
|
88
90
|
* mounted when they should not.
|
|
89
91
|
*/
|
|
90
|
-
$mount() {
|
|
92
|
+
async $mount() {
|
|
91
93
|
if (!hasBreakpointConfiguration(this)) {
|
|
92
94
|
return super.$mount();
|
|
93
95
|
}
|