@studiometa/js-toolkit 3.0.0-beta.2 → 3.0.0-beta.4

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.
Files changed (195) hide show
  1. package/Base/managers/EventsManager.js +1 -1
  2. package/Base/managers/EventsManager.js.map +2 -2
  3. package/decorators/index.d.ts +1 -0
  4. package/decorators/index.js +1 -0
  5. package/decorators/index.js.map +2 -2
  6. package/decorators/withBreakpointObserver.js +0 -2
  7. package/decorators/withBreakpointObserver.js.map +2 -2
  8. package/decorators/withDrag.js +1 -1
  9. package/decorators/withDrag.js.map +2 -2
  10. package/decorators/withIntersectionObserver.js +0 -2
  11. package/decorators/withIntersectionObserver.js.map +2 -2
  12. package/decorators/withMountOnMediaQuery.js +0 -2
  13. package/decorators/withMountOnMediaQuery.js.map +2 -2
  14. package/decorators/withMountWhenInView.js +0 -2
  15. package/decorators/withMountWhenInView.js.map +2 -2
  16. package/decorators/withMutation.d.ts +13 -0
  17. package/decorators/withMutation.js +34 -0
  18. package/decorators/withMutation.js.map +7 -0
  19. package/decorators/withRelativePointer.js +1 -1
  20. package/decorators/withRelativePointer.js.map +2 -2
  21. package/decorators/withScrolledInView/withScrolledInView.js +1 -1
  22. package/decorators/withScrolledInView/withScrolledInView.js.map +2 -2
  23. package/helpers/createApp.d.ts +1 -1
  24. package/helpers/createApp.js +20 -1
  25. package/helpers/createApp.js.map +2 -2
  26. package/helpers/getClosestParent.d.ts +1 -1
  27. package/helpers/getClosestParent.js +2 -2
  28. package/helpers/getClosestParent.js.map +2 -2
  29. package/helpers/getInstanceFromElement.d.ts +1 -1
  30. package/helpers/getInstanceFromElement.js +1 -1
  31. package/helpers/getInstanceFromElement.js.map +2 -2
  32. package/helpers/importOnInteraction.d.ts +1 -1
  33. package/helpers/importOnInteraction.js +1 -1
  34. package/helpers/importOnInteraction.js.map +2 -2
  35. package/helpers/importOnMediaQuery.d.ts +1 -1
  36. package/helpers/importOnMediaQuery.js +1 -1
  37. package/helpers/importOnMediaQuery.js.map +2 -2
  38. package/helpers/importWhenIdle.d.ts +1 -1
  39. package/helpers/importWhenIdle.js +1 -1
  40. package/helpers/importWhenIdle.js.map +2 -2
  41. package/helpers/importWhenPrefersMotion.d.ts +1 -1
  42. package/helpers/importWhenPrefersMotion.js +2 -2
  43. package/helpers/importWhenPrefersMotion.js.map +2 -2
  44. package/helpers/importWhenVisible.d.ts +1 -1
  45. package/helpers/importWhenVisible.js +1 -1
  46. package/helpers/importWhenVisible.js.map +2 -2
  47. package/helpers/index.d.ts +8 -8
  48. package/helpers/index.js +8 -18
  49. package/helpers/index.js.map +3 -3
  50. package/package.json +1 -1
  51. package/services/AbstractService.d.ts +9 -9
  52. package/services/AbstractService.js +10 -10
  53. package/services/AbstractService.js.map +3 -3
  54. package/services/DragService.js +7 -2
  55. package/services/DragService.js.map +2 -2
  56. package/services/KeyService.js +1 -1
  57. package/services/KeyService.js.map +2 -2
  58. package/services/MutationService.d.ts +20 -0
  59. package/services/MutationService.js +34 -0
  60. package/services/MutationService.js.map +7 -0
  61. package/services/PointerService.js +1 -1
  62. package/services/PointerService.js.map +2 -2
  63. package/services/ResizeService.js +2 -2
  64. package/services/ResizeService.js.map +2 -2
  65. package/services/ScrollService.js +1 -1
  66. package/services/ScrollService.js.map +2 -2
  67. package/services/index.d.ts +1 -0
  68. package/services/index.js +1 -0
  69. package/services/index.js.map +2 -2
  70. package/tsconfig.build.tsbuildinfo +1 -1
  71. package/utils/cache.d.ts +4 -0
  72. package/utils/cache.js +18 -0
  73. package/utils/cache.js.map +7 -0
  74. package/utils/collide/boundingRectToCircle.d.ts +1 -1
  75. package/utils/collide/boundingRectToCircle.js +1 -1
  76. package/utils/collide/boundingRectToCircle.js.map +2 -2
  77. package/utils/collide/collideCircleCircle.d.ts +1 -1
  78. package/utils/collide/collideCircleCircle.js +1 -1
  79. package/utils/collide/collideCircleCircle.js.map +2 -2
  80. package/utils/collide/collideCircleRect.d.ts +1 -1
  81. package/utils/collide/collideCircleRect.js +1 -1
  82. package/utils/collide/collideCircleRect.js.map +2 -2
  83. package/utils/collide/collidePointCircle.d.ts +1 -1
  84. package/utils/collide/collidePointCircle.js +1 -1
  85. package/utils/collide/collidePointCircle.js.map +2 -2
  86. package/utils/collide/collidePointRect.d.ts +1 -1
  87. package/utils/collide/collidePointRect.js +1 -1
  88. package/utils/collide/collidePointRect.js.map +2 -2
  89. package/utils/collide/collideRectRect.d.ts +1 -1
  90. package/utils/collide/collideRectRect.js +1 -1
  91. package/utils/collide/collideRectRect.js.map +2 -2
  92. package/utils/collide/index.d.ts +6 -6
  93. package/utils/collide/index.js +12 -12
  94. package/utils/collide/index.js.map +3 -3
  95. package/utils/css/animate.js.map +2 -2
  96. package/utils/css/getOffsetSizes.d.ts +1 -1
  97. package/utils/css/getOffsetSizes.js +1 -1
  98. package/utils/css/getOffsetSizes.js.map +2 -2
  99. package/utils/css/index.d.ts +3 -3
  100. package/utils/css/index.js +6 -6
  101. package/utils/css/index.js.map +3 -3
  102. package/utils/css/matrix.d.ts +1 -1
  103. package/utils/css/matrix.js +1 -1
  104. package/utils/css/matrix.js.map +2 -2
  105. package/utils/css/transition.d.ts +1 -1
  106. package/utils/css/transition.js +2 -2
  107. package/utils/css/transition.js.map +2 -2
  108. package/utils/debounce.d.ts +1 -1
  109. package/utils/debounce.js +1 -1
  110. package/utils/debounce.js.map +2 -2
  111. package/utils/dom/createElement.d.ts +10 -0
  112. package/utils/dom/createElement.js +21 -0
  113. package/utils/dom/createElement.js.map +7 -0
  114. package/utils/dom/index.d.ts +1 -0
  115. package/utils/dom/index.js +1 -0
  116. package/utils/dom/index.js.map +2 -2
  117. package/utils/getComponentResolver.d.ts +1 -1
  118. package/utils/getComponentResolver.js +1 -1
  119. package/utils/getComponentResolver.js.map +2 -2
  120. package/utils/index.d.ts +6 -5
  121. package/utils/index.js +11 -10
  122. package/utils/index.js.map +3 -3
  123. package/utils/keyCodes.d.ts +1 -2
  124. package/utils/keyCodes.js +2 -2
  125. package/utils/keyCodes.js.map +2 -2
  126. package/utils/math/clamp.d.ts +1 -1
  127. package/utils/math/clamp.js +1 -1
  128. package/utils/math/clamp.js.map +2 -2
  129. package/utils/math/clamp01.d.ts +1 -1
  130. package/utils/math/clamp01.js +2 -2
  131. package/utils/math/clamp01.js.map +2 -2
  132. package/utils/math/damp.d.ts +1 -1
  133. package/utils/math/damp.js +1 -1
  134. package/utils/math/damp.js.map +2 -2
  135. package/utils/math/index.d.ts +7 -7
  136. package/utils/math/index.js +14 -14
  137. package/utils/math/index.js.map +3 -3
  138. package/utils/math/inertiaFinalValue.d.ts +1 -1
  139. package/utils/math/inertiaFinalValue.js +2 -2
  140. package/utils/math/inertiaFinalValue.js.map +2 -2
  141. package/utils/math/lerp.d.ts +1 -1
  142. package/utils/math/lerp.js +1 -1
  143. package/utils/math/lerp.js.map +2 -2
  144. package/utils/math/map.d.ts +1 -1
  145. package/utils/math/map.js +1 -1
  146. package/utils/math/map.js.map +2 -2
  147. package/utils/math/round.d.ts +1 -1
  148. package/utils/math/round.js +1 -1
  149. package/utils/math/round.js.map +2 -2
  150. package/utils/memoize.d.ts +1 -1
  151. package/utils/memoize.js +1 -1
  152. package/utils/memoize.js.map +2 -2
  153. package/utils/object/getAllProperties.d.ts +1 -1
  154. package/utils/object/getAllProperties.js +1 -1
  155. package/utils/object/getAllProperties.js.map +2 -2
  156. package/utils/string/index.d.ts +10 -10
  157. package/utils/string/index.js +10 -22
  158. package/utils/string/index.js.map +3 -3
  159. package/utils/string/withLeadingCharacters.d.ts +1 -1
  160. package/utils/string/withLeadingCharacters.js +2 -2
  161. package/utils/string/withLeadingCharacters.js.map +2 -2
  162. package/utils/string/withLeadingSlash.d.ts +1 -1
  163. package/utils/string/withLeadingSlash.js +2 -2
  164. package/utils/string/withLeadingSlash.js.map +2 -2
  165. package/utils/string/withTrailingCharacters.d.ts +1 -1
  166. package/utils/string/withTrailingCharacters.js +2 -2
  167. package/utils/string/withTrailingCharacters.js.map +2 -2
  168. package/utils/string/withTrailingSlash.d.ts +1 -1
  169. package/utils/string/withTrailingSlash.js +2 -2
  170. package/utils/string/withTrailingSlash.js.map +2 -2
  171. package/utils/string/withoutLeadingCharacters.d.ts +1 -1
  172. package/utils/string/withoutLeadingCharacters.js +1 -1
  173. package/utils/string/withoutLeadingCharacters.js.map +2 -2
  174. package/utils/string/withoutLeadingCharactersRecursive.d.ts +1 -1
  175. package/utils/string/withoutLeadingCharactersRecursive.js +2 -2
  176. package/utils/string/withoutLeadingCharactersRecursive.js.map +2 -2
  177. package/utils/string/withoutLeadingSlash.d.ts +1 -1
  178. package/utils/string/withoutLeadingSlash.js +2 -2
  179. package/utils/string/withoutLeadingSlash.js.map +2 -2
  180. package/utils/string/withoutTrailingCharacters.d.ts +1 -1
  181. package/utils/string/withoutTrailingCharacters.js +1 -1
  182. package/utils/string/withoutTrailingCharacters.js.map +2 -2
  183. package/utils/string/withoutTrailingCharactersRecursive.d.ts +1 -1
  184. package/utils/string/withoutTrailingCharactersRecursive.js +2 -2
  185. package/utils/string/withoutTrailingCharactersRecursive.js.map +2 -2
  186. package/utils/string/withoutTrailingSlash.d.ts +1 -1
  187. package/utils/string/withoutTrailingSlash.js +2 -2
  188. package/utils/string/withoutTrailingSlash.js.map +2 -2
  189. package/utils/throttle.d.ts +1 -1
  190. package/utils/throttle.js +1 -1
  191. package/utils/throttle.js.map +2 -2
  192. package/utils/trapFocus.js +1 -1
  193. package/utils/trapFocus.js.map +2 -2
  194. package/utils/tween.js +1 -1
  195. package/utils/tween.js.map +1 -1
@@ -2,4 +2,4 @@ import type { BaseConstructor, BaseEl } from '../Base/index.js';
2
2
  /**
3
3
  * Get a component instance from a DOM element.
4
4
  */
5
- export default function getInstanceFromElement<T extends BaseConstructor>(element: BaseEl, Constructor: T): InstanceType<T> | null;
5
+ export declare function getInstanceFromElement<T extends BaseConstructor>(element: BaseEl, Constructor: T): InstanceType<T> | null;
@@ -5,6 +5,6 @@ function getInstanceFromElement(element, Constructor) {
5
5
  return element.__base__.get(Constructor);
6
6
  }
7
7
  export {
8
- getInstanceFromElement as default
8
+ getInstanceFromElement
9
9
  };
10
10
  //# sourceMappingURL=getInstanceFromElement.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/js-toolkit/helpers/getInstanceFromElement.ts"],
4
- "sourcesContent": ["import type { BaseConstructor, BaseEl } from '../Base/index.js';\n\n/**\n * Get a component instance from a DOM element.\n */\nexport default function getInstanceFromElement<T extends BaseConstructor>(\n element: BaseEl,\n Constructor: T,\n): InstanceType<T> | null {\n if (!element || !element.__base__ || !element.__base__.has(Constructor)) {\n return null;\n }\n\n return element.__base__.get(Constructor) as InstanceType<T>;\n}\n"],
5
- "mappings": "AAKe,SAAR,uBACL,SACA,aACwB;AACxB,MAAI,CAAC,WAAW,CAAC,QAAQ,YAAY,CAAC,QAAQ,SAAS,IAAI,WAAW,GAAG;AACvE,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,SAAS,IAAI,WAAW;AACzC;",
4
+ "sourcesContent": ["import type { BaseConstructor, BaseEl } from '../Base/index.js';\n\n/**\n * Get a component instance from a DOM element.\n */\nexport function getInstanceFromElement<T extends BaseConstructor>(\n element: BaseEl,\n Constructor: T,\n): InstanceType<T> | null {\n if (!element || !element.__base__ || !element.__base__.has(Constructor)) {\n return null;\n }\n\n return element.__base__.get(Constructor) as InstanceType<T>;\n}\n"],
5
+ "mappings": "AAKO,SAAS,uBACd,SACA,aACwB;AACxB,MAAI,CAAC,WAAW,CAAC,QAAQ,YAAY,CAAC,QAAQ,SAAS,IAAI,WAAW,GAAG;AACvE,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,SAAS,IAAI,WAAW;AACzC;",
6
6
  "names": []
7
7
  }
@@ -13,6 +13,6 @@ import type { Base, BaseConstructor } from '../Base/index.js';
13
13
  * The parent component.
14
14
  * @returns {Promise<InstanceType<T>>}
15
15
  */
16
- export default function importOnInteraction<T extends BaseConstructor = BaseConstructor>(fn: () => Promise<T | {
16
+ export declare function importOnInteraction<T extends BaseConstructor = BaseConstructor>(fn: () => Promise<T | {
17
17
  default: T;
18
18
  }>, nameOrSelectorOrElement: string | HTMLElement | HTMLElement[], events: string | string[], parent?: Base): Promise<T>;
@@ -21,6 +21,6 @@ function importOnInteraction(fn, nameOrSelectorOrElement, events, parent) {
21
21
  });
22
22
  }
23
23
  export {
24
- importOnInteraction as default
24
+ importOnInteraction
25
25
  };
26
26
  //# sourceMappingURL=importOnInteraction.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/js-toolkit/helpers/importOnInteraction.ts"],
4
- "sourcesContent": ["import type { Base, BaseConstructor } from '../Base/index.js';\nimport { getTargetElements } from './utils.js';\nimport { isString, getComponentResolver } from '../utils/index.js';\n\n/**\n * Import a component on an interaction.\n *\n * @template {BaseConstructor} [T=BaseConstructor]\n * @param {() => Promise<T|{default:T}>} fn\n * The import function.\n * @param {string|HTMLElement|HTMLElement[]} nameOrSelectorOrElement\n * The name or selector for the component.\n * @param {string|string[]} events\n * The events to listen to to trigger the import.\n * @param {Base} [parent]\n * The parent component.\n * @returns {Promise<InstanceType<T>>}\n */\nexport default function importOnInteraction<T extends BaseConstructor = BaseConstructor>(\n fn: () => Promise<T | { default: T }>,\n nameOrSelectorOrElement: string | HTMLElement | HTMLElement[],\n events: string | string[],\n parent?: Base,\n): Promise<T> {\n const normalizedEvents = isString(events) ? [events] : events;\n\n const resolver = getComponentResolver(fn);\n\n return new Promise((resolve) => {\n const elements = getTargetElements(nameOrSelectorOrElement, parent?.$el);\n const eventListenerOptions = {\n capture: true,\n passive: true,\n once: true,\n };\n const handler = () => {\n resolver(resolve);\n };\n\n for (const element of elements) {\n for (const event of normalizedEvents) {\n element.addEventListener(event, handler, eventListenerOptions);\n }\n }\n });\n}\n"],
5
- "mappings": "AACA,SAAS,yBAAyB;AAClC,SAAS,UAAU,4BAA4B;AAgBhC,SAAR,oBACL,IACA,yBACA,QACA,QACY;AACZ,QAAM,mBAAmB,SAAS,MAAM,IAAI,CAAC,MAAM,IAAI;AAEvD,QAAM,WAAW,qBAAqB,EAAE;AAExC,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,WAAW,kBAAkB,yBAAyB,QAAQ,GAAG;AACvE,UAAM,uBAAuB;AAAA,MAC3B,SAAS;AAAA,MACT,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AACA,UAAM,UAAU,MAAM;AACpB,eAAS,OAAO;AAAA,IAClB;AAEA,eAAW,WAAW,UAAU;AAC9B,iBAAW,SAAS,kBAAkB;AACpC,gBAAQ,iBAAiB,OAAO,SAAS,oBAAoB;AAAA,MAC/D;AAAA,IACF;AAAA,EACF,CAAC;AACH;",
4
+ "sourcesContent": ["import type { Base, BaseConstructor } from '../Base/index.js';\nimport { getTargetElements } from './utils.js';\nimport { isString, getComponentResolver } from '../utils/index.js';\n\n/**\n * Import a component on an interaction.\n *\n * @template {BaseConstructor} [T=BaseConstructor]\n * @param {() => Promise<T|{default:T}>} fn\n * The import function.\n * @param {string|HTMLElement|HTMLElement[]} nameOrSelectorOrElement\n * The name or selector for the component.\n * @param {string|string[]} events\n * The events to listen to to trigger the import.\n * @param {Base} [parent]\n * The parent component.\n * @returns {Promise<InstanceType<T>>}\n */\nexport function importOnInteraction<T extends BaseConstructor = BaseConstructor>(\n fn: () => Promise<T | { default: T }>,\n nameOrSelectorOrElement: string | HTMLElement | HTMLElement[],\n events: string | string[],\n parent?: Base,\n): Promise<T> {\n const normalizedEvents = isString(events) ? [events] : events;\n\n const resolver = getComponentResolver(fn);\n\n return new Promise((resolve) => {\n const elements = getTargetElements(nameOrSelectorOrElement, parent?.$el);\n const eventListenerOptions = {\n capture: true,\n passive: true,\n once: true,\n };\n const handler = () => {\n resolver(resolve);\n };\n\n for (const element of elements) {\n for (const event of normalizedEvents) {\n element.addEventListener(event, handler, eventListenerOptions);\n }\n }\n });\n}\n"],
5
+ "mappings": "AACA,SAAS,yBAAyB;AAClC,SAAS,UAAU,4BAA4B;AAgBxC,SAAS,oBACd,IACA,yBACA,QACA,QACY;AACZ,QAAM,mBAAmB,SAAS,MAAM,IAAI,CAAC,MAAM,IAAI;AAEvD,QAAM,WAAW,qBAAqB,EAAE;AAExC,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,WAAW,kBAAkB,yBAAyB,QAAQ,GAAG;AACvE,UAAM,uBAAuB;AAAA,MAC3B,SAAS;AAAA,MACT,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AACA,UAAM,UAAU,MAAM;AACpB,eAAS,OAAO;AAAA,IAClB;AAEA,eAAW,WAAW,UAAU;AAC9B,iBAAW,SAAS,kBAAkB;AACpC,gBAAQ,iBAAiB,OAAO,SAAS,oBAAoB;AAAA,MAC/D;AAAA,IACF;AAAA,EACF,CAAC;AACH;",
6
6
  "names": []
7
7
  }
@@ -9,6 +9,6 @@ import type { BaseConstructor } from '../Base/index.js';
9
9
  * The media query name and value (see https://developer.mozilla.org/en-US/docs/Web/CSS/@media#media_features)
10
10
  * @returns {Promise<T>}
11
11
  */
12
- export default function importOnMediaQuery<T extends BaseConstructor = BaseConstructor>(fn: () => Promise<T | {
12
+ export declare function importOnMediaQuery<T extends BaseConstructor = BaseConstructor>(fn: () => Promise<T | {
13
13
  default: T;
14
14
  }>, media: string): Promise<T>;
@@ -17,6 +17,6 @@ function importOnMediaQuery(fn, media) {
17
17
  });
18
18
  }
19
19
  export {
20
- importOnMediaQuery as default
20
+ importOnMediaQuery
21
21
  };
22
22
  //# sourceMappingURL=importOnMediaQuery.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/js-toolkit/helpers/importOnMediaQuery.ts"],
4
- "sourcesContent": ["import type { BaseConstructor } from '../Base/index.js';\nimport { getComponentResolver } from '../utils/index.js';\n\n/**\n * Import a component when given media query is true.\n *\n * @template {BaseConstructor} T\n * @param {() => Promise<T|{default:T}>} fn\n * The import function.\n * @param {string} media\n * The media query name and value (see https://developer.mozilla.org/en-US/docs/Web/CSS/@media#media_features)\n * @returns {Promise<T>}\n */\nexport default function importOnMediaQuery<T extends BaseConstructor = BaseConstructor>(\n fn: () => Promise<T | { default: T }>,\n media: string,\n): Promise<T> {\n const resolver = getComponentResolver(fn);\n\n return new Promise((resolve) => {\n const mediaQueryList = window.matchMedia(media);\n\n if (mediaQueryList.matches) {\n resolver(resolve);\n }\n\n const changeHandler = (event: MediaQueryListEvent) => {\n if (event.matches) {\n setTimeout(() => {\n // Remove listener and mount the component\n resolver(resolve, () => mediaQueryList.removeEventListener('change', changeHandler));\n }, 0);\n }\n };\n\n // Start listening for changes\n mediaQueryList.addEventListener('change', changeHandler);\n });\n}\n"],
5
- "mappings": "AACA,SAAS,4BAA4B;AAYtB,SAAR,mBACL,IACA,OACY;AACZ,QAAM,WAAW,qBAAqB,EAAE;AAExC,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,iBAAiB,OAAO,WAAW,KAAK;AAE9C,QAAI,eAAe,SAAS;AAC1B,eAAS,OAAO;AAAA,IAClB;AAEA,UAAM,gBAAgB,CAAC,UAA+B;AACpD,UAAI,MAAM,SAAS;AACjB,mBAAW,MAAM;AAEf,mBAAS,SAAS,MAAM,eAAe,oBAAoB,UAAU,aAAa,CAAC;AAAA,QACrF,GAAG,CAAC;AAAA,MACN;AAAA,IACF;AAGA,mBAAe,iBAAiB,UAAU,aAAa;AAAA,EACzD,CAAC;AACH;",
4
+ "sourcesContent": ["import type { BaseConstructor } from '../Base/index.js';\nimport { getComponentResolver } from '../utils/index.js';\n\n/**\n * Import a component when given media query is true.\n *\n * @template {BaseConstructor} T\n * @param {() => Promise<T|{default:T}>} fn\n * The import function.\n * @param {string} media\n * The media query name and value (see https://developer.mozilla.org/en-US/docs/Web/CSS/@media#media_features)\n * @returns {Promise<T>}\n */\nexport function importOnMediaQuery<T extends BaseConstructor = BaseConstructor>(\n fn: () => Promise<T | { default: T }>,\n media: string,\n): Promise<T> {\n const resolver = getComponentResolver(fn);\n\n return new Promise((resolve) => {\n const mediaQueryList = window.matchMedia(media);\n\n if (mediaQueryList.matches) {\n resolver(resolve);\n }\n\n const changeHandler = (event: MediaQueryListEvent) => {\n if (event.matches) {\n setTimeout(() => {\n // Remove listener and mount the component\n resolver(resolve, () => mediaQueryList.removeEventListener('change', changeHandler));\n }, 0);\n }\n };\n\n // Start listening for changes\n mediaQueryList.addEventListener('change', changeHandler);\n });\n}\n"],
5
+ "mappings": "AACA,SAAS,4BAA4B;AAY9B,SAAS,mBACd,IACA,OACY;AACZ,QAAM,WAAW,qBAAqB,EAAE;AAExC,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,iBAAiB,OAAO,WAAW,KAAK;AAE9C,QAAI,eAAe,SAAS;AAC1B,eAAS,OAAO;AAAA,IAClB;AAEA,UAAM,gBAAgB,CAAC,UAA+B;AACpD,UAAI,MAAM,SAAS;AACjB,mBAAW,MAAM;AAEf,mBAAS,SAAS,MAAM,eAAe,oBAAoB,UAAU,aAAa,CAAC;AAAA,QACrF,GAAG,CAAC;AAAA,MACN;AAAA,IACF;AAGA,mBAAe,iBAAiB,UAAU,aAAa;AAAA,EACzD,CAAC;AACH;",
6
6
  "names": []
7
7
  }
@@ -12,7 +12,7 @@ type ImportWhenIdleOptions = {
12
12
  * The time to wait before triggering the callback if never idle.
13
13
  * @returns {Promise<T>}
14
14
  */
15
- export default function importWhenIdle<T extends BaseConstructor = BaseConstructor>(fn: () => Promise<T | {
15
+ export declare function importWhenIdle<T extends BaseConstructor = BaseConstructor>(fn: () => Promise<T | {
16
16
  default: T;
17
17
  }>, { timeout }?: ImportWhenIdleOptions): Promise<T>;
18
18
  export {};
@@ -19,6 +19,6 @@ function importWhenIdle(fn, { timeout = 1 } = {}) {
19
19
  });
20
20
  }
21
21
  export {
22
- importWhenIdle as default
22
+ importWhenIdle
23
23
  };
24
24
  //# sourceMappingURL=importWhenIdle.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/js-toolkit/helpers/importWhenIdle.ts"],
4
- "sourcesContent": ["import type { BaseConstructor } from '../Base/index.js';\nimport { getComponentResolver } from '../utils/index.js';\n\ntype ImportWhenIdleOptions = {\n timeout?: number;\n};\n\n/**\n * Import a component when user is idle.\n *\n * @template {BaseConstructor} T\n * @param {() => Promise<T|{default:T}>} fn\n * The import function.\n * @param {ImportWhenIdleOptions} [options]\n * The time to wait before triggering the callback if never idle.\n * @returns {Promise<T>}\n */\nexport default function importWhenIdle<T extends BaseConstructor = BaseConstructor>(\n fn: () => Promise<T | { default: T }>,\n { timeout = 1 }: ImportWhenIdleOptions = {},\n): Promise<T> {\n const resolver = getComponentResolver(fn);\n\n return new Promise((resolve) => {\n if (!('requestIdleCallback' in window)) {\n setTimeout(() => {\n resolver(resolve);\n }, timeout);\n } else {\n window.requestIdleCallback(\n () => {\n setTimeout(() => {\n resolver(resolve);\n }, 0);\n },\n { timeout },\n );\n }\n });\n}\n"],
5
- "mappings": "AACA,SAAS,4BAA4B;AAgBtB,SAAR,eACL,IACA,EAAE,UAAU,EAAE,IAA2B,CAAC,GAC9B;AACZ,QAAM,WAAW,qBAAqB,EAAE;AAExC,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI,EAAE,yBAAyB,SAAS;AACtC,iBAAW,MAAM;AACf,iBAAS,OAAO;AAAA,MAClB,GAAG,OAAO;AAAA,IACZ,OAAO;AACL,aAAO;AAAA,QACL,MAAM;AACJ,qBAAW,MAAM;AACf,qBAAS,OAAO;AAAA,UAClB,GAAG,CAAC;AAAA,QACN;AAAA,QACA,EAAE,QAAQ;AAAA,MACZ;AAAA,IACF;AAAA,EACF,CAAC;AACH;",
4
+ "sourcesContent": ["import type { BaseConstructor } from '../Base/index.js';\nimport { getComponentResolver } from '../utils/index.js';\n\ntype ImportWhenIdleOptions = {\n timeout?: number;\n};\n\n/**\n * Import a component when user is idle.\n *\n * @template {BaseConstructor} T\n * @param {() => Promise<T|{default:T}>} fn\n * The import function.\n * @param {ImportWhenIdleOptions} [options]\n * The time to wait before triggering the callback if never idle.\n * @returns {Promise<T>}\n */\nexport function importWhenIdle<T extends BaseConstructor = BaseConstructor>(\n fn: () => Promise<T | { default: T }>,\n { timeout = 1 }: ImportWhenIdleOptions = {},\n): Promise<T> {\n const resolver = getComponentResolver(fn);\n\n return new Promise((resolve) => {\n if (!('requestIdleCallback' in window)) {\n setTimeout(() => {\n resolver(resolve);\n }, timeout);\n } else {\n window.requestIdleCallback(\n () => {\n setTimeout(() => {\n resolver(resolve);\n }, 0);\n },\n { timeout },\n );\n }\n });\n}\n"],
5
+ "mappings": "AACA,SAAS,4BAA4B;AAgB9B,SAAS,eACd,IACA,EAAE,UAAU,EAAE,IAA2B,CAAC,GAC9B;AACZ,QAAM,WAAW,qBAAqB,EAAE;AAExC,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI,EAAE,yBAAyB,SAAS;AACtC,iBAAW,MAAM;AACf,iBAAS,OAAO;AAAA,MAClB,GAAG,OAAO;AAAA,IACZ,OAAO;AACL,aAAO;AAAA,QACL,MAAM;AACJ,qBAAW,MAAM;AACf,qBAAS,OAAO;AAAA,UAClB,GAAG,CAAC;AAAA,QACN;AAAA,QACA,EAAE,QAAQ;AAAA,MACZ;AAAA,IACF;AAAA,EACF,CAAC;AACH;",
6
6
  "names": []
7
7
  }
@@ -6,6 +6,6 @@ import type { BaseConstructor } from '../Base/index.js';
6
6
  * @param {() => Promise<T|{default:T}>} fn
7
7
  * @returns {Promise<T>}
8
8
  */
9
- export default function importWhenPrefersMotion<T extends BaseConstructor = BaseConstructor>(fn: () => Promise<T | {
9
+ export declare function importWhenPrefersMotion<T extends BaseConstructor = BaseConstructor>(fn: () => Promise<T | {
10
10
  default: T;
11
11
  }>): Promise<T>;
@@ -1,8 +1,8 @@
1
- import importOnMediaQuery from "./importOnMediaQuery.js";
1
+ import { importOnMediaQuery } from "./importOnMediaQuery.js";
2
2
  function importWhenPrefersMotion(fn) {
3
3
  return importOnMediaQuery(fn, "not (prefers-reduced-motion)");
4
4
  }
5
5
  export {
6
- importWhenPrefersMotion as default
6
+ importWhenPrefersMotion
7
7
  };
8
8
  //# sourceMappingURL=importWhenPrefersMotion.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/js-toolkit/helpers/importWhenPrefersMotion.ts"],
4
- "sourcesContent": ["import type { BaseConstructor } from '../Base/index.js';\nimport importOnMediaQuery from './importOnMediaQuery.js';\n\n/**\n * Import a component if user does not reduce motion.\n *\n * @template {BaseConstructor} T\n * @param {() => Promise<T|{default:T}>} fn\n * @returns {Promise<T>}\n */\nexport default function importWhenPrefersMotion<T extends BaseConstructor = BaseConstructor>(\n fn: () => Promise<T | { default: T }>,\n): Promise<T> {\n return importOnMediaQuery(fn, 'not (prefers-reduced-motion)');\n}\n"],
5
- "mappings": "AACA,OAAO,wBAAwB;AAShB,SAAR,wBACL,IACY;AACZ,SAAO,mBAAmB,IAAI,8BAA8B;AAC9D;",
4
+ "sourcesContent": ["import type { BaseConstructor } from '../Base/index.js';\nimport { importOnMediaQuery } from './importOnMediaQuery.js';\n\n/**\n * Import a component if user does not reduce motion.\n *\n * @template {BaseConstructor} T\n * @param {() => Promise<T|{default:T}>} fn\n * @returns {Promise<T>}\n */\nexport function importWhenPrefersMotion<T extends BaseConstructor = BaseConstructor>(\n fn: () => Promise<T | { default: T }>,\n): Promise<T> {\n return importOnMediaQuery(fn, 'not (prefers-reduced-motion)');\n}\n"],
5
+ "mappings": "AACA,SAAS,0BAA0B;AAS5B,SAAS,wBACd,IACY;AACZ,SAAO,mBAAmB,IAAI,8BAA8B;AAC9D;",
6
6
  "names": []
7
7
  }
@@ -13,6 +13,6 @@ import type { Base, BaseConstructor } from '../Base/index.js';
13
13
  * Options for the `IntersectionObserver` instance.
14
14
  * @returns {Promise<T>}
15
15
  */
16
- export default function importWhenVisible<T extends BaseConstructor = BaseConstructor>(fn: () => Promise<T | {
16
+ export declare function importWhenVisible<T extends BaseConstructor = BaseConstructor>(fn: () => Promise<T | {
17
17
  default: T;
18
18
  }>, nameOrSelectorOrElement: string | HTMLElement | HTMLElement[], parent?: Base, observerOptions?: IntersectionObserverInit): Promise<T>;
@@ -16,6 +16,6 @@ function importWhenVisible(fn, nameOrSelectorOrElement, parent, observerOptions
16
16
  });
17
17
  }
18
18
  export {
19
- importWhenVisible as default
19
+ importWhenVisible
20
20
  };
21
21
  //# sourceMappingURL=importWhenVisible.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/js-toolkit/helpers/importWhenVisible.ts"],
4
- "sourcesContent": ["import type { Base, BaseConstructor } from '../Base/index.js';\nimport { getTargetElements } from './utils.js';\nimport { getComponentResolver } from '../utils/index.js';\n\n/**\n * Import a component when it is visible.\n *\n * @template {BaseConstructor} T\n * @param {() => Promise<T|{default:T}>} fn\n * The import function.\n * @param {string|HTMLElement|HTMLElement[]} nameOrSelectorOrElement\n * The name or selector for the component.\n * @param {Base} [parent]\n * The parent component.\n * @param {IntersectionObserverInit} [observerOptions]\n * Options for the `IntersectionObserver` instance.\n * @returns {Promise<T>}\n */\nexport default function importWhenVisible<T extends BaseConstructor = BaseConstructor>(\n fn: () => Promise<T | { default: T }>,\n nameOrSelectorOrElement: string | HTMLElement | HTMLElement[],\n parent?: Base,\n observerOptions: IntersectionObserverInit = {},\n): Promise<T> {\n const resolver = getComponentResolver(fn);\n\n return new Promise((resolve) => {\n const observer = new IntersectionObserver((entries) => {\n const someEntriesAreVisible = entries.some((entry) => entry.isIntersecting);\n if (someEntriesAreVisible) {\n setTimeout(() => {\n resolver(resolve, () => observer.disconnect());\n }, 0);\n }\n }, observerOptions);\n\n const elements = getTargetElements(nameOrSelectorOrElement, parent?.$el);\n for (const element of elements) observer.observe(element);\n });\n}\n"],
5
- "mappings": "AACA,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AAgBtB,SAAR,kBACL,IACA,yBACA,QACA,kBAA4C,CAAC,GACjC;AACZ,QAAM,WAAW,qBAAqB,EAAE;AAExC,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,WAAW,IAAI,qBAAqB,CAAC,YAAY;AACrD,YAAM,wBAAwB,QAAQ,KAAK,CAAC,UAAU,MAAM,cAAc;AAC1E,UAAI,uBAAuB;AACzB,mBAAW,MAAM;AACf,mBAAS,SAAS,MAAM,SAAS,WAAW,CAAC;AAAA,QAC/C,GAAG,CAAC;AAAA,MACN;AAAA,IACF,GAAG,eAAe;AAElB,UAAM,WAAW,kBAAkB,yBAAyB,QAAQ,GAAG;AACvE,eAAW,WAAW,SAAU,UAAS,QAAQ,OAAO;AAAA,EAC1D,CAAC;AACH;",
4
+ "sourcesContent": ["import type { Base, BaseConstructor } from '../Base/index.js';\nimport { getTargetElements } from './utils.js';\nimport { getComponentResolver } from '../utils/index.js';\n\n/**\n * Import a component when it is visible.\n *\n * @template {BaseConstructor} T\n * @param {() => Promise<T|{default:T}>} fn\n * The import function.\n * @param {string|HTMLElement|HTMLElement[]} nameOrSelectorOrElement\n * The name or selector for the component.\n * @param {Base} [parent]\n * The parent component.\n * @param {IntersectionObserverInit} [observerOptions]\n * Options for the `IntersectionObserver` instance.\n * @returns {Promise<T>}\n */\nexport function importWhenVisible<T extends BaseConstructor = BaseConstructor>(\n fn: () => Promise<T | { default: T }>,\n nameOrSelectorOrElement: string | HTMLElement | HTMLElement[],\n parent?: Base,\n observerOptions: IntersectionObserverInit = {},\n): Promise<T> {\n const resolver = getComponentResolver(fn);\n\n return new Promise((resolve) => {\n const observer = new IntersectionObserver((entries) => {\n const someEntriesAreVisible = entries.some((entry) => entry.isIntersecting);\n if (someEntriesAreVisible) {\n setTimeout(() => {\n resolver(resolve, () => observer.disconnect());\n }, 0);\n }\n }, observerOptions);\n\n const elements = getTargetElements(nameOrSelectorOrElement, parent?.$el);\n for (const element of elements) observer.observe(element);\n });\n}\n"],
5
+ "mappings": "AACA,SAAS,yBAAyB;AAClC,SAAS,4BAA4B;AAgB9B,SAAS,kBACd,IACA,yBACA,QACA,kBAA4C,CAAC,GACjC;AACZ,QAAM,WAAW,qBAAqB,EAAE;AAExC,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,WAAW,IAAI,qBAAqB,CAAC,YAAY;AACrD,YAAM,wBAAwB,QAAQ,KAAK,CAAC,UAAU,MAAM,cAAc;AAC1E,UAAI,uBAAuB;AACzB,mBAAW,MAAM;AACf,mBAAS,SAAS,MAAM,SAAS,WAAW,CAAC;AAAA,QAC/C,GAAG,CAAC;AAAA,MACN;AAAA,IACF,GAAG,eAAe;AAElB,UAAM,WAAW,kBAAkB,yBAAyB,QAAQ,GAAG;AACvE,eAAW,WAAW,SAAU,UAAS,QAAQ,OAAO;AAAA,EAC1D,CAAC;AACH;",
6
6
  "names": []
7
7
  }
@@ -1,9 +1,9 @@
1
+ export * from './createApp.js';
2
+ export * from './getClosestParent.js';
1
3
  export * from './getDirectChildren.js';
2
- export { default as createApp } from './createApp.js';
3
- export { default as getClosestParent } from './getClosestParent.js';
4
- export { default as getInstanceFromElement } from './getInstanceFromElement.js';
5
- export { default as importOnInteraction } from './importOnInteraction.js';
6
- export { default as importWhenIdle } from './importWhenIdle.js';
7
- export { default as importWhenVisible } from './importWhenVisible.js';
8
- export { default as importOnMediaQuery } from './importOnMediaQuery.js';
9
- export { default as importWhenPrefersMotion } from './importWhenPrefersMotion.js';
4
+ export * from './getInstanceFromElement.js';
5
+ export * from './importOnInteraction.js';
6
+ export * from './importOnMediaQuery.js';
7
+ export * from './importWhenIdle.js';
8
+ export * from './importWhenPrefersMotion.js';
9
+ export * from './importWhenVisible.js';
package/helpers/index.js CHANGED
@@ -1,20 +1,10 @@
1
+ export * from "./createApp.js";
2
+ export * from "./getClosestParent.js";
1
3
  export * from "./getDirectChildren.js";
2
- import { default as default2 } from "./createApp.js";
3
- import { default as default3 } from "./getClosestParent.js";
4
- import { default as default4 } from "./getInstanceFromElement.js";
5
- import { default as default5 } from "./importOnInteraction.js";
6
- import { default as default6 } from "./importWhenIdle.js";
7
- import { default as default7 } from "./importWhenVisible.js";
8
- import { default as default8 } from "./importOnMediaQuery.js";
9
- import { default as default9 } from "./importWhenPrefersMotion.js";
10
- export {
11
- default2 as createApp,
12
- default3 as getClosestParent,
13
- default4 as getInstanceFromElement,
14
- default5 as importOnInteraction,
15
- default8 as importOnMediaQuery,
16
- default6 as importWhenIdle,
17
- default9 as importWhenPrefersMotion,
18
- default7 as importWhenVisible
19
- };
4
+ export * from "./getInstanceFromElement.js";
5
+ export * from "./importOnInteraction.js";
6
+ export * from "./importOnMediaQuery.js";
7
+ export * from "./importWhenIdle.js";
8
+ export * from "./importWhenPrefersMotion.js";
9
+ export * from "./importWhenVisible.js";
20
10
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/js-toolkit/helpers/index.ts"],
4
- "sourcesContent": ["export * from './getDirectChildren.js';\nexport { default as createApp } from './createApp.js';\nexport { default as getClosestParent } from './getClosestParent.js';\nexport { default as getInstanceFromElement } from './getInstanceFromElement.js';\nexport { default as importOnInteraction } from './importOnInteraction.js';\nexport { default as importWhenIdle } from './importWhenIdle.js';\nexport { default as importWhenVisible } from './importWhenVisible.js';\nexport { default as importOnMediaQuery } from './importOnMediaQuery.js';\nexport { default as importWhenPrefersMotion } from './importWhenPrefersMotion.js';\n"],
5
- "mappings": "AAAA,cAAc;AACd,SAAoB,WAAXA,gBAA4B;AACrC,SAAoB,WAAXA,gBAAmC;AAC5C,SAAoB,WAAXA,gBAAyC;AAClD,SAAoB,WAAXA,gBAAsC;AAC/C,SAAoB,WAAXA,gBAAiC;AAC1C,SAAoB,WAAXA,gBAAoC;AAC7C,SAAoB,WAAXA,gBAAqC;AAC9C,SAAoB,WAAXA,gBAA0C;",
6
- "names": ["default"]
4
+ "sourcesContent": ["export * from './createApp.js';\nexport * from './getClosestParent.js';\nexport * from './getDirectChildren.js';\nexport * from './getInstanceFromElement.js';\nexport * from './importOnInteraction.js';\nexport * from './importOnMediaQuery.js';\nexport * from './importWhenIdle.js';\nexport * from './importWhenPrefersMotion.js';\nexport * from './importWhenVisible.js';\n"],
5
+ "mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
6
+ "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studiometa/js-toolkit",
3
- "version": "3.0.0-beta.2",
3
+ "version": "3.0.0-beta.4",
4
4
  "description": "A set of useful little bits of JavaScript to boost your project! 🚀",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -2,15 +2,15 @@ export interface ServiceInterface<T> {
2
2
  /**
3
3
  * Remove a function from the resize service by its key.
4
4
  */
5
- remove(key: string): void;
5
+ remove(key: string | symbol): void;
6
6
  /**
7
7
  * Add a callback to the service. The callback will receive the current service props as parameter.
8
8
  */
9
- add(key: string, callback: (props: T) => void): void;
9
+ add(key: string | symbol, callback: (props: T) => void): void;
10
10
  /**
11
11
  * Test if the service has alreaydy a callback for the given key.
12
12
  */
13
- has(key: string): boolean;
13
+ has(key: string | symbol): boolean;
14
14
  /**
15
15
  * Get the service's props.
16
16
  */
@@ -46,7 +46,7 @@ export declare class AbstractService<PropsType = any> {
46
46
  /**
47
47
  * Get a service instance as a singleton based on the given key.
48
48
  */
49
- static getInstance<T extends ServiceInterface<any>>(key?: any, ...args: any[]): any;
49
+ static getInstance<T extends ServiceInterface<any>>(keys?: any, ...args: any[]): T;
50
50
  /**
51
51
  * Is the service active or not?
52
52
  */
@@ -58,23 +58,23 @@ export declare class AbstractService<PropsType = any> {
58
58
  /**
59
59
  * Holds all the callbacks that will be triggered.
60
60
  */
61
- callbacks: Map<string, (props: PropsType) => unknown>;
61
+ callbacks: Map<string | symbol, (props: PropsType) => unknown>;
62
62
  /**
63
63
  * Does the service has the given key?
64
64
  */
65
- has(key: string): boolean;
65
+ has(key: string | symbol): boolean;
66
66
  /**
67
67
  * Get a service callback by its key.
68
68
  */
69
- get(key: string): (props: PropsType) => unknown;
69
+ get(key: string | symbol): (props: PropsType) => unknown;
70
70
  /**
71
71
  * Add a callback to the service.
72
72
  */
73
- add(key: string, callback: (props: PropsType) => unknown): void;
73
+ add(key: string | symbol, callback: (props: PropsType) => unknown): void;
74
74
  /**
75
75
  * Remove a callback from the service by its key.
76
76
  */
77
- remove(key: string): void;
77
+ remove(key: string | symbol): void;
78
78
  /**
79
79
  * Trigger all service callbacks with service props.
80
80
  */
@@ -1,3 +1,4 @@
1
+ import { cache } from "../utils/cache.js";
1
2
  class AbstractService {
2
3
  /**
3
4
  * Service configuration.
@@ -10,17 +11,16 @@ class AbstractService {
10
11
  /**
11
12
  * Get a service instance as a singleton based on the given key.
12
13
  */
13
- static getInstance(key = this, ...args) {
14
- if (!this.__instances.has(key)) {
14
+ static getInstance(keys = [this], ...args) {
15
+ return cache(keys, () => {
15
16
  const instance = new this(...args);
16
- this.__instances.set(key, {
17
- add: (key2, callback) => instance.add(key2, callback),
18
- remove: (key2) => instance.remove(key2),
19
- has: (key2) => instance.has(key2),
17
+ return {
18
+ add: (key, callback) => instance.add(key, callback),
19
+ remove: (key) => instance.remove(key),
20
+ has: (key) => instance.has(key),
20
21
  props: () => instance.props
21
- });
22
- }
23
- return this.__instances.get(key);
22
+ };
23
+ });
24
24
  }
25
25
  /**
26
26
  * Is the service active or not?
@@ -51,7 +51,7 @@ class AbstractService {
51
51
  */
52
52
  add(key, callback) {
53
53
  if (this.has(key)) {
54
- console.warn(`The key \`${key}\` has already been added.`);
54
+ console.warn(`The key \`${String(key)}\` has already been added.`);
55
55
  return;
56
56
  }
57
57
  if (this.callbacks.size === 0 && !this.__isInit) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/js-toolkit/services/AbstractService.ts"],
4
- "sourcesContent": ["export interface ServiceInterface<T> {\n /**\n * Remove a function from the resize service by its key.\n */\n remove(key: string): void;\n /**\n * Add a callback to the service. The callback will receive the current service props as parameter.\n */\n add(key: string, callback: (props: T) => void): void;\n /**\n * Test if the service has alreaydy a callback for the given key.\n */\n has(key: string): boolean;\n /**\n * Get the service's props.\n */\n props(): T;\n}\n\n/**\n * Service configuration of events to be attached to targets.\n */\nexport type ServiceConfig = [\n (instance: AbstractService) => EventTarget,\n [string, AddEventListenerOptions?][],\n][];\n\n/**\n * AbstractService class.\n */\nexport class AbstractService<PropsType = any> {\n /**\n * Used to type `this.constructor` correctly\n * @see https://github.com/microsoft/TypeScript/issues/3841#issuecomment-2381594311\n */\n declare ['constructor']: typeof AbstractService;\n\n /**\n * Service configuration.\n */\n static config: ServiceConfig = [];\n\n /**\n * Cache for the created instances.\n */\n static __instances = new Map();\n\n /**\n * Get a service instance as a singleton based on the given key.\n */\n static getInstance<T extends ServiceInterface<any>>(key: any = this, ...args: any[]) {\n if (!this.__instances.has(key)) {\n // @ts-ignore\n const instance = new this(...args);\n this.__instances.set(key, {\n add: (key, callback) => instance.add(key, callback),\n remove: (key) => instance.remove(key),\n has: (key) => instance.has(key),\n props: () => instance.props,\n } as T);\n }\n\n return this.__instances.get(key);\n }\n\n /**\n * Is the service active or not?\n */\n __isInit = false;\n\n /**\n * Props for the service.\n */\n props = {};\n\n /**\n * Holds all the callbacks that will be triggered.\n */\n callbacks: Map<string, (props: PropsType) => unknown> = new Map();\n\n /**\n * Does the service has the given key?\n */\n has(key: string): boolean {\n return this.callbacks.has(key);\n }\n\n /**\n * Get a service callback by its key.\n */\n get(key: string): (props: PropsType) => unknown {\n return this.callbacks.get(key);\n }\n\n /**\n * Add a callback to the service.\n */\n add(key: string, callback: (props: PropsType) => unknown) {\n if (this.has(key)) {\n console.warn(`The key \\`${key}\\` has already been added.`);\n return;\n }\n\n // Initialize the service when we add the first callback\n if (this.callbacks.size === 0 && !this.__isInit) {\n this.init();\n this.__isInit = true;\n }\n\n this.callbacks.set(key, callback);\n }\n\n /**\n * Remove a callback from the service by its key.\n */\n remove(key: string) {\n this.callbacks.delete(key);\n\n // Kill the service when we remove the last callback\n if (this.callbacks.size === 0 && this.__isInit) {\n this.kill();\n this.__isInit = false;\n }\n }\n\n /**\n * Trigger all service callbacks with service props.\n */\n trigger(props: PropsType) {\n for (const callback of this.callbacks.values()) {\n callback(props);\n }\n }\n\n /* v8 ignore next 6 */\n /**\n * Implements the EventListenerObject interface.\n */\n handleEvent(event: Event) {\n // Should be implemented.\n }\n\n /**\n * Add or remove event listeners based on the static `config` property.\n */\n __manageEvents(mode: 'add' | 'remove') {\n for (const [target, events] of this.constructor.config) {\n const resolvedTarget = target(this);\n for (const [type, options] of events) {\n resolvedTarget[`${mode}EventListener`](type, this, options);\n }\n }\n }\n\n /**\n * Triggered when the service is initialized.\n */\n init() {\n this.__manageEvents('add');\n }\n\n /**\n * Triggered when the service is killed.\n */\n kill() {\n this.__manageEvents('remove');\n }\n}\n"],
5
- "mappings": "AA8BO,MAAM,gBAAiC;AAAA;AAAA;AAAA;AAAA,EAU5C,OAAO,SAAwB,CAAC;AAAA;AAAA;AAAA;AAAA,EAKhC,OAAO,cAAc,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA,EAK7B,OAAO,YAA6C,MAAW,SAAS,MAAa;AACnF,QAAI,CAAC,KAAK,YAAY,IAAI,GAAG,GAAG;AAE9B,YAAM,WAAW,IAAI,KAAK,GAAG,IAAI;AACjC,WAAK,YAAY,IAAI,KAAK;AAAA,QACxB,KAAK,CAACA,MAAK,aAAa,SAAS,IAAIA,MAAK,QAAQ;AAAA,QAClD,QAAQ,CAACA,SAAQ,SAAS,OAAOA,IAAG;AAAA,QACpC,KAAK,CAACA,SAAQ,SAAS,IAAIA,IAAG;AAAA,QAC9B,OAAO,MAAM,SAAS;AAAA,MACxB,CAAM;AAAA,IACR;AAEA,WAAO,KAAK,YAAY,IAAI,GAAG;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW;AAAA;AAAA;AAAA;AAAA,EAKX,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA,EAKT,YAAwD,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA,EAKhE,IAAI,KAAsB;AACxB,WAAO,KAAK,UAAU,IAAI,GAAG;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAA4C;AAC9C,WAAO,KAAK,UAAU,IAAI,GAAG;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAa,UAAyC;AACxD,QAAI,KAAK,IAAI,GAAG,GAAG;AACjB,cAAQ,KAAK,aAAa,GAAG,4BAA4B;AACzD;AAAA,IACF;AAGA,QAAI,KAAK,UAAU,SAAS,KAAK,CAAC,KAAK,UAAU;AAC/C,WAAK,KAAK;AACV,WAAK,WAAW;AAAA,IAClB;AAEA,SAAK,UAAU,IAAI,KAAK,QAAQ;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,KAAa;AAClB,SAAK,UAAU,OAAO,GAAG;AAGzB,QAAI,KAAK,UAAU,SAAS,KAAK,KAAK,UAAU;AAC9C,WAAK,KAAK;AACV,WAAK,WAAW;AAAA,IAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,OAAkB;AACxB,eAAW,YAAY,KAAK,UAAU,OAAO,GAAG;AAC9C,eAAS,KAAK;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,OAAc;AAAA,EAE1B;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,MAAwB;AACrC,eAAW,CAAC,QAAQ,MAAM,KAAK,KAAK,YAAY,QAAQ;AACtD,YAAM,iBAAiB,OAAO,IAAI;AAClC,iBAAW,CAAC,MAAM,OAAO,KAAK,QAAQ;AACpC,uBAAe,GAAG,IAAI,eAAe,EAAE,MAAM,MAAM,OAAO;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AACL,SAAK,eAAe,KAAK;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AACL,SAAK,eAAe,QAAQ;AAAA,EAC9B;AACF;",
6
- "names": ["key"]
4
+ "sourcesContent": ["import { cache } from '../utils/cache.js';\n\nexport interface ServiceInterface<T> {\n /**\n * Remove a function from the resize service by its key.\n */\n remove(key: string | symbol): void;\n /**\n * Add a callback to the service. The callback will receive the current service props as parameter.\n */\n add(key: string | symbol, callback: (props: T) => void): void;\n /**\n * Test if the service has alreaydy a callback for the given key.\n */\n has(key: string | symbol): boolean;\n /**\n * Get the service's props.\n */\n props(): T;\n}\n\n/**\n * Service configuration of events to be attached to targets.\n */\nexport type ServiceConfig = [\n (instance: AbstractService) => EventTarget,\n [string, AddEventListenerOptions?][],\n][];\n\n/**\n * AbstractService class.\n */\nexport class AbstractService<PropsType = any> {\n /**\n * Used to type `this.constructor` correctly\n * @see https://github.com/microsoft/TypeScript/issues/3841#issuecomment-2381594311\n */\n declare ['constructor']: typeof AbstractService;\n\n /**\n * Service configuration.\n */\n static config: ServiceConfig = [];\n\n /**\n * Cache for the created instances.\n */\n static __instances = new Map();\n\n /**\n * Get a service instance as a singleton based on the given key.\n */\n static getInstance<T extends ServiceInterface<any>>(keys: any = [this], ...args: any[]) {\n return cache(keys, () => {\n // @ts-ignore\n const instance = new this(...args);\n return {\n add: (key, callback) => instance.add(key, callback),\n remove: (key) => instance.remove(key),\n has: (key) => instance.has(key),\n props: () => instance.props,\n } as T;\n });\n }\n\n /**\n * Is the service active or not?\n */\n __isInit = false;\n\n /**\n * Props for the service.\n */\n props = {};\n\n /**\n * Holds all the callbacks that will be triggered.\n */\n callbacks: Map<string | symbol, (props: PropsType) => unknown> = new Map();\n\n /**\n * Does the service has the given key?\n */\n has(key: string | symbol): boolean {\n return this.callbacks.has(key);\n }\n\n /**\n * Get a service callback by its key.\n */\n get(key: string | symbol): (props: PropsType) => unknown {\n return this.callbacks.get(key);\n }\n\n /**\n * Add a callback to the service.\n */\n add(key: string | symbol, callback: (props: PropsType) => unknown) {\n if (this.has(key)) {\n console.warn(`The key \\`${String(key)}\\` has already been added.`);\n return;\n }\n\n // Initialize the service when we add the first callback\n if (this.callbacks.size === 0 && !this.__isInit) {\n this.init();\n this.__isInit = true;\n }\n\n this.callbacks.set(key, callback);\n }\n\n /**\n * Remove a callback from the service by its key.\n */\n remove(key: string | symbol) {\n this.callbacks.delete(key);\n\n // Kill the service when we remove the last callback\n if (this.callbacks.size === 0 && this.__isInit) {\n this.kill();\n this.__isInit = false;\n }\n }\n\n /**\n * Trigger all service callbacks with service props.\n */\n trigger(props: PropsType) {\n for (const callback of this.callbacks.values()) {\n callback(props);\n }\n }\n\n /* v8 ignore next 6 */\n /**\n * Implements the EventListenerObject interface.\n */\n handleEvent(event: Event) {\n // Should be implemented.\n }\n\n /**\n * Add or remove event listeners based on the static `config` property.\n */\n __manageEvents(mode: 'add' | 'remove') {\n for (const [target, events] of this.constructor.config) {\n const resolvedTarget = target(this);\n for (const [type, options] of events) {\n resolvedTarget[`${mode}EventListener`](type, this, options);\n }\n }\n }\n\n /**\n * Triggered when the service is initialized.\n */\n init() {\n this.__manageEvents('add');\n }\n\n /**\n * Triggered when the service is killed.\n */\n kill() {\n this.__manageEvents('remove');\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,aAAa;AAgCf,MAAM,gBAAiC;AAAA;AAAA;AAAA;AAAA,EAU5C,OAAO,SAAwB,CAAC;AAAA;AAAA;AAAA;AAAA,EAKhC,OAAO,cAAc,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA,EAK7B,OAAO,YAA6C,OAAY,CAAC,IAAI,MAAM,MAAa;AACtF,WAAO,MAAM,MAAM,MAAM;AAEvB,YAAM,WAAW,IAAI,KAAK,GAAG,IAAI;AACjC,aAAO;AAAA,QACL,KAAK,CAAC,KAAK,aAAa,SAAS,IAAI,KAAK,QAAQ;AAAA,QAClD,QAAQ,CAAC,QAAQ,SAAS,OAAO,GAAG;AAAA,QACpC,KAAK,CAAC,QAAQ,SAAS,IAAI,GAAG;AAAA,QAC9B,OAAO,MAAM,SAAS;AAAA,MACxB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW;AAAA;AAAA;AAAA;AAAA,EAKX,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA,EAKT,YAAiE,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA,EAKzE,IAAI,KAA+B;AACjC,WAAO,KAAK,UAAU,IAAI,GAAG;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAqD;AACvD,WAAO,KAAK,UAAU,IAAI,GAAG;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAsB,UAAyC;AACjE,QAAI,KAAK,IAAI,GAAG,GAAG;AACjB,cAAQ,KAAK,aAAa,OAAO,GAAG,CAAC,4BAA4B;AACjE;AAAA,IACF;AAGA,QAAI,KAAK,UAAU,SAAS,KAAK,CAAC,KAAK,UAAU;AAC/C,WAAK,KAAK;AACV,WAAK,WAAW;AAAA,IAClB;AAEA,SAAK,UAAU,IAAI,KAAK,QAAQ;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,KAAsB;AAC3B,SAAK,UAAU,OAAO,GAAG;AAGzB,QAAI,KAAK,UAAU,SAAS,KAAK,KAAK,UAAU;AAC9C,WAAK,KAAK;AACV,WAAK,WAAW;AAAA,IAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,OAAkB;AACxB,eAAW,YAAY,KAAK,UAAU,OAAO,GAAG;AAC9C,eAAS,KAAK;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,OAAc;AAAA,EAE1B;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,MAAwB;AACrC,eAAW,CAAC,QAAQ,MAAM,KAAK,KAAK,YAAY,QAAQ;AACtD,YAAM,iBAAiB,OAAO,IAAI;AAClC,iBAAW,CAAC,MAAM,OAAO,KAAK,QAAQ;AACpC,uBAAe,GAAG,IAAI,eAAe,EAAE,MAAM,MAAM,OAAO;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AACL,SAAK,eAAe,KAAK;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AACL,SAAK,eAAe,QAAQ;AAAA,EAC9B;AACF;",
6
+ "names": []
7
7
  }
@@ -1,6 +1,7 @@
1
1
  import { AbstractService } from "./AbstractService.js";
2
2
  import { useRaf } from "./RafService.js";
3
- import { isDefined, inertiaFinalValue } from "../utils/index.js";
3
+ import { isDefined } from "../utils/is.js";
4
+ import { inertiaFinalValue } from "../utils/math/index.js";
4
5
  import { PASSIVE_EVENT_OPTIONS, CAPTURE_EVENT_OPTIONS } from "./utils.js";
5
6
  let count = 0;
6
7
  class DragService extends AbstractService {
@@ -208,7 +209,11 @@ class DragService extends AbstractService {
208
209
  }
209
210
  }
210
211
  function useDrag(target, options) {
211
- return DragService.getInstance(target, target, options);
212
+ return DragService.getInstance(
213
+ [target, JSON.stringify(options)],
214
+ target,
215
+ options
216
+ );
212
217
  }
213
218
  export {
214
219
  DragService,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/js-toolkit/services/DragService.ts"],
4
- "sourcesContent": ["import type { ServiceConfig, ServiceInterface } from './AbstractService.js';\nimport { AbstractService } from './AbstractService.js';\nimport { useRaf } from './RafService.js';\nimport { isDefined, inertiaFinalValue } from '../utils/index.js';\nimport { PASSIVE_EVENT_OPTIONS, CAPTURE_EVENT_OPTIONS } from './utils.js';\n\ntype DragLifecycle = 'start' | 'drag' | 'drop' | 'inertia' | 'stop';\n\nexport interface DragServiceProps {\n /**\n * The current mode of the dragging logic.\n */\n mode: DragLifecycle;\n /**\n * The target element of the drag.\n */\n target: HTMLElement;\n /**\n * Whether the user is currently grabbing the targeted element or not.\n */\n isGrabbing: boolean;\n /**\n * Whether the drag currently has inertia or not.\n */\n hasInertia: boolean;\n /**\n * The current horizontal position in the viewport.\n */\n x: number;\n /**\n * The current vertical position in the viewport.\n */\n y: number;\n /**\n * The delta between the current position and the last.\n */\n delta: { x: number; y: number };\n /**\n * The initial position where the dragging started.\n */\n origin: { x: number; y: number };\n /**\n * The distance from the current position to the origin.\n */\n distance: { x: number; y: number };\n /**\n * The final position that will be reached at the end of the inertia.\n */\n final: { x: number; y: number };\n}\n\nexport type DragServiceInterface = ServiceInterface<DragServiceProps>;\n\nexport interface DragServiceOptions {\n dampFactor?: number;\n dragTreshold?: number;\n}\n\nlet count = 0;\n\nexport class DragService extends AbstractService<DragServiceProps> {\n static MODES: Record<Uppercase<DragLifecycle>, DragLifecycle> = {\n START: 'start',\n DRAG: 'drag',\n DROP: 'drop',\n INERTIA: 'inertia',\n STOP: 'stop',\n };\n\n static config: ServiceConfig = [\n [\n (instance) => (instance as DragService).props.target,\n [\n ['dragstart', CAPTURE_EVENT_OPTIONS],\n ['click', CAPTURE_EVENT_OPTIONS],\n ['pointerdown', PASSIVE_EVENT_OPTIONS],\n ],\n ],\n [\n () => window,\n [\n ['pointerup', PASSIVE_EVENT_OPTIONS],\n ['touchend', PASSIVE_EVENT_OPTIONS],\n ],\n ],\n ];\n\n id: string;\n\n dampFactor = 0.85;\n\n dragTreshold = 10;\n\n previousEvent: TouchEvent | MouseEvent = null;\n\n props = {\n target: null,\n mode: undefined,\n isGrabbing: false,\n hasInertia: false,\n x: 0,\n y: 0,\n delta: {\n x: 0,\n y: 0,\n },\n origin: {\n x: 0,\n y: 0,\n },\n distance: {\n x: 0,\n y: 0,\n },\n final: {\n x: 0,\n y: 0,\n },\n } as DragServiceProps;\n\n /**\n * Test if we should allow click on links and buttons.\n */\n get shouldPreventClick(): boolean {\n return (\n Math.abs(this.props.distance.x) > this.dragTreshold ||\n Math.abs(this.props.distance.y) > this.dragTreshold\n );\n }\n\n constructor(\n target: HTMLElement,\n { dampFactor = 0.85, dragTreshold = 10 }: DragServiceOptions = {},\n ) {\n super();\n count += 1;\n this.id = `drag-${count}`;\n this.dampFactor = dampFactor;\n this.dragTreshold = dragTreshold;\n this.props.target = target;\n }\n\n /**\n * Get the client value for the given axis.\n */\n getEventPosition(event: MouseEvent | TouchEvent): { x: number; y: number } {\n // @ts-ignore\n const eventOrTouch = isDefined(event.touches) ? event.touches[0] : event;\n return {\n x: eventOrTouch.clientX,\n y: eventOrTouch.clientY,\n };\n }\n\n /**\n * Start the drag.\n *\n * @param {number} x The initial horizontal position.\n * @param {number} y The initial vertical position.\n */\n start(x: number, y: number) {\n const { props } = this;\n if (props.isGrabbing) {\n return;\n }\n\n // Reset state\n props.x = props.origin.x = props.final.x = x;\n props.y = props.origin.y = props.final.y = y;\n props.delta.x = props.distance.x = 0;\n props.delta.y = props.distance.y = 0;\n props.mode = DragService.MODES.START;\n props.isGrabbing = true;\n\n this.trigger(props);\n\n document.addEventListener('touchmove', this, PASSIVE_EVENT_OPTIONS);\n document.addEventListener('mousemove', this, PASSIVE_EVENT_OPTIONS);\n }\n\n /**\n * Stop the drag, or drop.\n */\n drop() {\n const { props, dampFactor, id } = this;\n\n if (!props.isGrabbing) {\n return;\n }\n\n document.removeEventListener('touchmove', this);\n document.removeEventListener('mousemove', this);\n\n props.isGrabbing = false;\n props.mode = DragService.MODES.DROP;\n props.hasInertia = true;\n props.final.x = inertiaFinalValue(props.x, props.delta.x, dampFactor);\n props.final.y = inertiaFinalValue(props.y, props.delta.y, dampFactor);\n this.previousEvent = null;\n\n this.trigger(props);\n\n setTimeout(() => {\n const raf = useRaf();\n raf.remove(id);\n raf.add(id, () => this.rafHandler());\n });\n }\n\n /**\n * Stop the drag.\n */\n stop() {\n const { props, id } = this;\n\n useRaf().remove(id);\n props.isGrabbing = false;\n props.hasInertia = false;\n props.mode = DragService.MODES.STOP;\n\n this.trigger(props);\n }\n\n /**\n * Raf service handler.\n */\n rafHandler() {\n const { props, dampFactor } = this;\n\n if (!props.isGrabbing) {\n props.x += props.delta.x;\n props.y += props.delta.y;\n props.distance.x = props.x - props.origin.x;\n props.distance.y = props.y - props.origin.y;\n props.delta.x *= dampFactor;\n props.delta.y *= dampFactor;\n props.mode = DragService.MODES.INERTIA;\n\n this.trigger(props);\n\n if (Math.abs(props.delta.x) < 0.1 && Math.abs(props.delta.y) < 0.1) {\n this.stop();\n }\n }\n }\n\n /**\n * Pointer service handler.\n */\n drag(event: TouchEvent | MouseEvent) {\n const { props } = this;\n\n if (props.isGrabbing) {\n const position = this.getEventPosition(event);\n props.x = position.x;\n props.y = position.y;\n\n if (this.previousEvent) {\n const previousPosition = this.getEventPosition(this.previousEvent);\n props.delta.x = position.x - previousPosition.x;\n props.delta.y = position.y - previousPosition.y;\n }\n\n props.final.x = position.x;\n props.final.y = position.y;\n props.distance.x = props.x - props.origin.x;\n props.distance.y = props.y - props.origin.y;\n props.mode = DragService.MODES.DRAG;\n\n this.trigger(props);\n this.previousEvent = event;\n }\n }\n\n /**\n * Handle any event.\n */\n handleEvent(event: MouseEvent | PointerEvent | DragEvent) {\n switch (event.type) {\n case 'dragstart':\n event.preventDefault();\n break;\n case 'click':\n if (this.shouldPreventClick) {\n event.stopImmediatePropagation();\n event.stopPropagation();\n event.preventDefault();\n }\n break;\n case 'pointerup':\n case 'touchend':\n this.drop();\n break;\n case 'touchmove':\n case 'mousemove':\n this.drag(event);\n break;\n default:\n if (event.button === 0) {\n this.start(event.x, event.y);\n }\n }\n }\n}\n\n/**\n * Use the drag service.\n *\n * ```js\n * import { useDrag } from '@studiometa/js-toolkit/services';\n * const element = document.querySelector('.draggable');\n * const { add, remove, props } = useDrag(element, { dampFactor: 0.5 });\n * add('key', (props) => console.log(props));\n * remove('key');\n * props();\n * ```\n */\nexport function useDrag(target: HTMLElement, options: DragServiceOptions): DragServiceInterface {\n return DragService.getInstance<DragServiceInterface>(target, target, options);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { ServiceConfig, ServiceInterface } from './AbstractService.js';\nimport { AbstractService } from './AbstractService.js';\nimport { useRaf } from './RafService.js';\nimport { isDefined } from '../utils/is.js';\nimport { inertiaFinalValue } from '../utils/math/index.js';\nimport { PASSIVE_EVENT_OPTIONS, CAPTURE_EVENT_OPTIONS } from './utils.js';\n\ntype DragLifecycle = 'start' | 'drag' | 'drop' | 'inertia' | 'stop';\n\nexport interface DragServiceProps {\n /**\n * The current mode of the dragging logic.\n */\n mode: DragLifecycle;\n /**\n * The target element of the drag.\n */\n target: HTMLElement;\n /**\n * Whether the user is currently grabbing the targeted element or not.\n */\n isGrabbing: boolean;\n /**\n * Whether the drag currently has inertia or not.\n */\n hasInertia: boolean;\n /**\n * The current horizontal position in the viewport.\n */\n x: number;\n /**\n * The current vertical position in the viewport.\n */\n y: number;\n /**\n * The delta between the current position and the last.\n */\n delta: { x: number; y: number };\n /**\n * The initial position where the dragging started.\n */\n origin: { x: number; y: number };\n /**\n * The distance from the current position to the origin.\n */\n distance: { x: number; y: number };\n /**\n * The final position that will be reached at the end of the inertia.\n */\n final: { x: number; y: number };\n}\n\nexport type DragServiceInterface = ServiceInterface<DragServiceProps>;\n\nexport interface DragServiceOptions {\n dampFactor?: number;\n dragTreshold?: number;\n}\n\nlet count = 0;\n\nexport class DragService extends AbstractService<DragServiceProps> {\n static MODES: Record<Uppercase<DragLifecycle>, DragLifecycle> = {\n START: 'start',\n DRAG: 'drag',\n DROP: 'drop',\n INERTIA: 'inertia',\n STOP: 'stop',\n };\n\n static config: ServiceConfig = [\n [\n (instance) => (instance as DragService).props.target,\n [\n ['dragstart', CAPTURE_EVENT_OPTIONS],\n ['click', CAPTURE_EVENT_OPTIONS],\n ['pointerdown', PASSIVE_EVENT_OPTIONS],\n ],\n ],\n [\n () => window,\n [\n ['pointerup', PASSIVE_EVENT_OPTIONS],\n ['touchend', PASSIVE_EVENT_OPTIONS],\n ],\n ],\n ];\n\n id: string;\n\n dampFactor = 0.85;\n\n dragTreshold = 10;\n\n previousEvent: TouchEvent | MouseEvent = null;\n\n props = {\n target: null,\n mode: undefined,\n isGrabbing: false,\n hasInertia: false,\n x: 0,\n y: 0,\n delta: {\n x: 0,\n y: 0,\n },\n origin: {\n x: 0,\n y: 0,\n },\n distance: {\n x: 0,\n y: 0,\n },\n final: {\n x: 0,\n y: 0,\n },\n } as DragServiceProps;\n\n /**\n * Test if we should allow click on links and buttons.\n */\n get shouldPreventClick(): boolean {\n return (\n Math.abs(this.props.distance.x) > this.dragTreshold ||\n Math.abs(this.props.distance.y) > this.dragTreshold\n );\n }\n\n constructor(\n target: HTMLElement,\n { dampFactor = 0.85, dragTreshold = 10 }: DragServiceOptions = {},\n ) {\n super();\n count += 1;\n this.id = `drag-${count}`;\n this.dampFactor = dampFactor;\n this.dragTreshold = dragTreshold;\n this.props.target = target;\n }\n\n /**\n * Get the client value for the given axis.\n */\n getEventPosition(event: MouseEvent | TouchEvent): { x: number; y: number } {\n // @ts-ignore\n const eventOrTouch = isDefined(event.touches) ? event.touches[0] : event;\n return {\n x: eventOrTouch.clientX,\n y: eventOrTouch.clientY,\n };\n }\n\n /**\n * Start the drag.\n *\n * @param {number} x The initial horizontal position.\n * @param {number} y The initial vertical position.\n */\n start(x: number, y: number) {\n const { props } = this;\n if (props.isGrabbing) {\n return;\n }\n\n // Reset state\n props.x = props.origin.x = props.final.x = x;\n props.y = props.origin.y = props.final.y = y;\n props.delta.x = props.distance.x = 0;\n props.delta.y = props.distance.y = 0;\n props.mode = DragService.MODES.START;\n props.isGrabbing = true;\n\n this.trigger(props);\n\n document.addEventListener('touchmove', this, PASSIVE_EVENT_OPTIONS);\n document.addEventListener('mousemove', this, PASSIVE_EVENT_OPTIONS);\n }\n\n /**\n * Stop the drag, or drop.\n */\n drop() {\n const { props, dampFactor, id } = this;\n\n if (!props.isGrabbing) {\n return;\n }\n\n document.removeEventListener('touchmove', this);\n document.removeEventListener('mousemove', this);\n\n props.isGrabbing = false;\n props.mode = DragService.MODES.DROP;\n props.hasInertia = true;\n props.final.x = inertiaFinalValue(props.x, props.delta.x, dampFactor);\n props.final.y = inertiaFinalValue(props.y, props.delta.y, dampFactor);\n this.previousEvent = null;\n\n this.trigger(props);\n\n setTimeout(() => {\n const raf = useRaf();\n raf.remove(id);\n raf.add(id, () => this.rafHandler());\n });\n }\n\n /**\n * Stop the drag.\n */\n stop() {\n const { props, id } = this;\n\n useRaf().remove(id);\n props.isGrabbing = false;\n props.hasInertia = false;\n props.mode = DragService.MODES.STOP;\n\n this.trigger(props);\n }\n\n /**\n * Raf service handler.\n */\n rafHandler() {\n const { props, dampFactor } = this;\n\n if (!props.isGrabbing) {\n props.x += props.delta.x;\n props.y += props.delta.y;\n props.distance.x = props.x - props.origin.x;\n props.distance.y = props.y - props.origin.y;\n props.delta.x *= dampFactor;\n props.delta.y *= dampFactor;\n props.mode = DragService.MODES.INERTIA;\n\n this.trigger(props);\n\n if (Math.abs(props.delta.x) < 0.1 && Math.abs(props.delta.y) < 0.1) {\n this.stop();\n }\n }\n }\n\n /**\n * Pointer service handler.\n */\n drag(event: TouchEvent | MouseEvent) {\n const { props } = this;\n\n if (props.isGrabbing) {\n const position = this.getEventPosition(event);\n props.x = position.x;\n props.y = position.y;\n\n if (this.previousEvent) {\n const previousPosition = this.getEventPosition(this.previousEvent);\n props.delta.x = position.x - previousPosition.x;\n props.delta.y = position.y - previousPosition.y;\n }\n\n props.final.x = position.x;\n props.final.y = position.y;\n props.distance.x = props.x - props.origin.x;\n props.distance.y = props.y - props.origin.y;\n props.mode = DragService.MODES.DRAG;\n\n this.trigger(props);\n this.previousEvent = event;\n }\n }\n\n /**\n * Handle any event.\n */\n handleEvent(event: MouseEvent | PointerEvent | DragEvent) {\n switch (event.type) {\n case 'dragstart':\n event.preventDefault();\n break;\n case 'click':\n if (this.shouldPreventClick) {\n event.stopImmediatePropagation();\n event.stopPropagation();\n event.preventDefault();\n }\n break;\n case 'pointerup':\n case 'touchend':\n this.drop();\n break;\n case 'touchmove':\n case 'mousemove':\n this.drag(event);\n break;\n default:\n if (event.button === 0) {\n this.start(event.x, event.y);\n }\n }\n }\n}\n\n/**\n * Use the drag service.\n *\n * ```js\n * import { useDrag } from '@studiometa/js-toolkit/services';\n * const element = document.querySelector('.draggable');\n * const { add, remove, props } = useDrag(element, { dampFactor: 0.5 });\n * add('key', (props) => console.log(props));\n * remove('key');\n * props();\n * ```\n */\nexport function useDrag(target: HTMLElement, options: DragServiceOptions): DragServiceInterface {\n return DragService.getInstance<DragServiceInterface>(\n [target, JSON.stringify(options)],\n target,\n options,\n );\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,5 @@
1
1
  import { AbstractService } from "./AbstractService.js";
2
- import keyCodes from "../utils/keyCodes.js";
2
+ import { keyCodes } from "../utils/keyCodes.js";
3
3
  function getInitialKeyCodes() {
4
4
  return Object.fromEntries(Object.keys(keyCodes).map((key) => [key, false]));
5
5
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/js-toolkit/services/KeyService.ts"],
4
- "sourcesContent": ["import type { ServiceConfig, ServiceInterface } from './AbstractService.js';\nimport { AbstractService } from './AbstractService.js';\nimport keyCodes from '../utils/keyCodes.js';\n\nfunction getInitialKeyCodes(): Record<keyof typeof keyCodes, false> {\n return Object.fromEntries(Object.keys(keyCodes).map((key) => [key, false])) as Record<\n keyof typeof keyCodes,\n false\n >;\n}\n\nexport interface KeyServiceProps {\n event: KeyboardEvent;\n triggered: number;\n direction: 'up' | 'down' | 'none';\n isUp: boolean;\n isDown: boolean;\n ENTER: boolean;\n SPACE: boolean;\n TAB: boolean;\n ESC: boolean;\n LEFT: boolean;\n UP: boolean;\n RIGHT: boolean;\n DOWN: boolean;\n}\n\nexport type KeyServiceInterface = ServiceInterface<KeyServiceProps>;\n\nexport class KeyService extends AbstractService<KeyServiceProps> {\n static config: ServiceConfig = [[() => document, [['keydown'], ['keyup']]]];\n\n previousEvent: Event | null = null;\n\n props: KeyServiceProps = {\n event: null,\n triggered: 0,\n isUp: false,\n isDown: false,\n direction: 'none',\n ...getInitialKeyCodes(),\n };\n\n updateProps(event: KeyboardEvent): KeyServiceProps {\n const { props } = this;\n\n props.event = event;\n\n for (const [name, code] of Object.entries(keyCodes)) {\n props[name] = code === event.keyCode;\n }\n\n if (!this.previousEvent) {\n props.triggered = 0;\n }\n\n if (props.event.type === 'keydown' && this.previousEvent?.type === 'keydown') {\n props.triggered += 1;\n } else {\n props.triggered = 1;\n }\n\n this.previousEvent = props.event;\n\n props.direction = props.event.type === 'keydown' ? 'down' : 'up';\n props.isUp = props.event.type === 'keyup';\n props.isDown = props.event.type === 'keydown';\n\n return props;\n }\n\n handleEvent(event: KeyboardEvent) {\n this.trigger(this.updateProps(event));\n }\n}\n\n/**\n * Use the keyboard service.\n */\nexport function useKey(): KeyServiceInterface {\n return KeyService.getInstance();\n}\n"],
5
- "mappings": "AACA,SAAS,uBAAuB;AAChC,OAAO,cAAc;AAErB,SAAS,qBAA2D;AAClE,SAAO,OAAO,YAAY,OAAO,KAAK,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,CAAC,CAAC;AAI5E;AAoBO,MAAM,mBAAmB,gBAAiC;AAAA,EAC/D,OAAO,SAAwB,CAAC,CAAC,MAAM,UAAU,CAAC,CAAC,SAAS,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAAA,EAE1E,gBAA8B;AAAA,EAE9B,QAAyB;AAAA,IACvB,OAAO;AAAA,IACP,WAAW;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,GAAG,mBAAmB;AAAA,EACxB;AAAA,EAEA,YAAY,OAAuC;AACjD,UAAM,EAAE,MAAM,IAAI;AAElB,UAAM,QAAQ;AAEd,eAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACnD,YAAM,IAAI,IAAI,SAAS,MAAM;AAAA,IAC/B;AAEA,QAAI,CAAC,KAAK,eAAe;AACvB,YAAM,YAAY;AAAA,IACpB;AAEA,QAAI,MAAM,MAAM,SAAS,aAAa,KAAK,eAAe,SAAS,WAAW;AAC5E,YAAM,aAAa;AAAA,IACrB,OAAO;AACL,YAAM,YAAY;AAAA,IACpB;AAEA,SAAK,gBAAgB,MAAM;AAE3B,UAAM,YAAY,MAAM,MAAM,SAAS,YAAY,SAAS;AAC5D,UAAM,OAAO,MAAM,MAAM,SAAS;AAClC,UAAM,SAAS,MAAM,MAAM,SAAS;AAEpC,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,OAAsB;AAChC,SAAK,QAAQ,KAAK,YAAY,KAAK,CAAC;AAAA,EACtC;AACF;AAKO,SAAS,SAA8B;AAC5C,SAAO,WAAW,YAAY;AAChC;",
4
+ "sourcesContent": ["import type { ServiceConfig, ServiceInterface } from './AbstractService.js';\nimport { AbstractService } from './AbstractService.js';\nimport { keyCodes } from '../utils/keyCodes.js';\n\nfunction getInitialKeyCodes(): Record<keyof typeof keyCodes, false> {\n return Object.fromEntries(Object.keys(keyCodes).map((key) => [key, false])) as Record<\n keyof typeof keyCodes,\n false\n >;\n}\n\nexport interface KeyServiceProps {\n event: KeyboardEvent;\n triggered: number;\n direction: 'up' | 'down' | 'none';\n isUp: boolean;\n isDown: boolean;\n ENTER: boolean;\n SPACE: boolean;\n TAB: boolean;\n ESC: boolean;\n LEFT: boolean;\n UP: boolean;\n RIGHT: boolean;\n DOWN: boolean;\n}\n\nexport type KeyServiceInterface = ServiceInterface<KeyServiceProps>;\n\nexport class KeyService extends AbstractService<KeyServiceProps> {\n static config: ServiceConfig = [[() => document, [['keydown'], ['keyup']]]];\n\n previousEvent: Event | null = null;\n\n props: KeyServiceProps = {\n event: null,\n triggered: 0,\n isUp: false,\n isDown: false,\n direction: 'none',\n ...getInitialKeyCodes(),\n };\n\n updateProps(event: KeyboardEvent): KeyServiceProps {\n const { props } = this;\n\n props.event = event;\n\n for (const [name, code] of Object.entries(keyCodes)) {\n props[name] = code === event.keyCode;\n }\n\n if (!this.previousEvent) {\n props.triggered = 0;\n }\n\n if (props.event.type === 'keydown' && this.previousEvent?.type === 'keydown') {\n props.triggered += 1;\n } else {\n props.triggered = 1;\n }\n\n this.previousEvent = props.event;\n\n props.direction = props.event.type === 'keydown' ? 'down' : 'up';\n props.isUp = props.event.type === 'keyup';\n props.isDown = props.event.type === 'keydown';\n\n return props;\n }\n\n handleEvent(event: KeyboardEvent) {\n this.trigger(this.updateProps(event));\n }\n}\n\n/**\n * Use the keyboard service.\n */\nexport function useKey(): KeyServiceInterface {\n return KeyService.getInstance();\n}\n"],
5
+ "mappings": "AACA,SAAS,uBAAuB;AAChC,SAAS,gBAAgB;AAEzB,SAAS,qBAA2D;AAClE,SAAO,OAAO,YAAY,OAAO,KAAK,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,CAAC,CAAC;AAI5E;AAoBO,MAAM,mBAAmB,gBAAiC;AAAA,EAC/D,OAAO,SAAwB,CAAC,CAAC,MAAM,UAAU,CAAC,CAAC,SAAS,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAAA,EAE1E,gBAA8B;AAAA,EAE9B,QAAyB;AAAA,IACvB,OAAO;AAAA,IACP,WAAW;AAAA,IACX,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,GAAG,mBAAmB;AAAA,EACxB;AAAA,EAEA,YAAY,OAAuC;AACjD,UAAM,EAAE,MAAM,IAAI;AAElB,UAAM,QAAQ;AAEd,eAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACnD,YAAM,IAAI,IAAI,SAAS,MAAM;AAAA,IAC/B;AAEA,QAAI,CAAC,KAAK,eAAe;AACvB,YAAM,YAAY;AAAA,IACpB;AAEA,QAAI,MAAM,MAAM,SAAS,aAAa,KAAK,eAAe,SAAS,WAAW;AAC5E,YAAM,aAAa;AAAA,IACrB,OAAO;AACL,YAAM,YAAY;AAAA,IACpB;AAEA,SAAK,gBAAgB,MAAM;AAE3B,UAAM,YAAY,MAAM,MAAM,SAAS,YAAY,SAAS;AAC5D,UAAM,OAAO,MAAM,MAAM,SAAS;AAClC,UAAM,SAAS,MAAM,MAAM,SAAS;AAEpC,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,OAAsB;AAChC,SAAK,QAAQ,KAAK,YAAY,KAAK,CAAC;AAAA,EACtC;AACF;AAKO,SAAS,SAA8B;AAC5C,SAAO,WAAW,YAAY;AAChC;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,20 @@
1
+ import type { ServiceInterface } from './AbstractService.js';
2
+ import { AbstractService } from './AbstractService.js';
3
+ export interface MutationServiceProps {
4
+ mutations: MutationRecord[];
5
+ }
6
+ export type MutationServiceInterface = ServiceInterface<MutationServiceProps>;
7
+ export type MutationServiceOptions = MutationObserverInit;
8
+ export declare class MutationService extends AbstractService<MutationServiceProps> {
9
+ props: MutationServiceProps;
10
+ target: Node;
11
+ options: MutationObserverInit;
12
+ observer: MutationObserver;
13
+ constructor(target?: Node, options?: MutationObserverInit);
14
+ init(): void;
15
+ kill(): void;
16
+ }
17
+ /**
18
+ * Use the mutation service.
19
+ */
20
+ export declare function useMutation(target?: Node, options?: MutationObserverInit): MutationServiceInterface;
@@ -0,0 +1,34 @@
1
+ import { AbstractService } from "./AbstractService.js";
2
+ import { isEmpty } from "../utils/is.js";
3
+ class MutationService extends AbstractService {
4
+ props = {
5
+ mutations: []
6
+ };
7
+ target;
8
+ options;
9
+ observer;
10
+ constructor(target, options) {
11
+ super();
12
+ this.target = target ?? document.documentElement;
13
+ this.options = options;
14
+ }
15
+ init() {
16
+ this.observer = new MutationObserver((mutations) => {
17
+ this.props.mutations = mutations;
18
+ this.trigger(this.props);
19
+ });
20
+ this.observer.observe(this.target, isEmpty(this.options) ? { attributes: true } : this.options);
21
+ }
22
+ kill() {
23
+ this.observer.disconnect();
24
+ this.observer = null;
25
+ }
26
+ }
27
+ function useMutation(target, options) {
28
+ return MutationService.getInstance([target, JSON.stringify(options)], target, options);
29
+ }
30
+ export {
31
+ MutationService,
32
+ useMutation
33
+ };
34
+ //# sourceMappingURL=MutationService.js.map