@studiometa/ui 1.6.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/Accordion/Accordion.d.ts +1 -1
  2. package/Accordion/Accordion.js.map +1 -1
  3. package/Action/Action.d.ts +1 -1
  4. package/Action/Action.js.map +1 -1
  5. package/AnchorNav/AnchorNav.d.ts +1 -1
  6. package/AnchorNav/AnchorNav.js.map +1 -1
  7. package/AnchorScrollTo/AnchorScrollTo.d.ts +1 -1
  8. package/AnchorScrollTo/AnchorScrollTo.js.map +1 -1
  9. package/CircularMarquee/CircularMarquee.d.ts +1 -1
  10. package/CircularMarquee/CircularMarquee.js.map +1 -1
  11. package/Cursor/Cursor.d.ts +1 -1
  12. package/Cursor/Cursor.js.map +1 -1
  13. package/Data/DataBind.d.ts +2 -2
  14. package/Data/DataBind.js.map +1 -1
  15. package/Draggable/Draggable.d.ts +1 -1
  16. package/Draggable/Draggable.js.map +1 -1
  17. package/Fetch/Fetch.d.ts +18 -18
  18. package/Fetch/Fetch.js.map +2 -2
  19. package/Fetch/utils.js +1 -4
  20. package/Fetch/utils.js.map +2 -2
  21. package/Figure/Figure.d.ts +1 -1
  22. package/Figure/Figure.js.map +1 -1
  23. package/Figure/FigureShopify.d.ts +1 -1
  24. package/Figure/FigureShopify.js.map +1 -1
  25. package/Figure/FigureTwicpics.d.ts +1 -1
  26. package/Figure/FigureTwicpics.js.map +1 -1
  27. package/FigureVideo/FigureVideo.d.ts +1 -1
  28. package/FigureVideo/FigureVideo.js.map +1 -1
  29. package/FigureVideo/FigureVideoTwicpics.d.ts +1 -1
  30. package/FigureVideo/FigureVideoTwicpics.js.map +1 -1
  31. package/Frame/Frame.d.ts +5 -5
  32. package/Frame/Frame.js.map +1 -1
  33. package/Frame/FrameForm.d.ts +1 -1
  34. package/Frame/FrameTarget.d.ts +4 -4
  35. package/Frame/FrameTarget.js.map +2 -2
  36. package/Hoverable/Hoverable.d.ts +1 -1
  37. package/Hoverable/Hoverable.js.map +1 -1
  38. package/LargeText/LargeText.d.ts +1 -1
  39. package/LargeText/LargeText.js.map +1 -1
  40. package/LazyInclude/LazyInclude.d.ts +1 -1
  41. package/LazyInclude/LazyInclude.js.map +1 -1
  42. package/Menu/Menu.d.ts +1 -1
  43. package/Menu/Menu.js.map +1 -1
  44. package/Menu/MenuList.js +1 -0
  45. package/Menu/MenuList.js.map +2 -2
  46. package/Modal/Modal.d.ts +1 -1
  47. package/Modal/Modal.js.map +1 -1
  48. package/Panel/Panel.d.ts +1 -1
  49. package/Panel/Panel.js.map +1 -1
  50. package/Prefetch/AbstractPrefetch.d.ts +1 -1
  51. package/Prefetch/AbstractPrefetch.js.map +1 -1
  52. package/Prefetch/PrefetchWhenOver.d.ts +1 -1
  53. package/Prefetch/PrefetchWhenOver.js.map +1 -1
  54. package/Prefetch/PrefetchWhenVisible.d.ts +1 -1
  55. package/Prefetch/PrefetchWhenVisible.js.map +1 -1
  56. package/README.md +1 -1
  57. package/ScrollAnimation/AbstractScrollAnimation.d.ts +8 -0
  58. package/ScrollAnimation/AbstractScrollAnimation.js +20 -1
  59. package/ScrollAnimation/AbstractScrollAnimation.js.map +2 -2
  60. package/ScrollAnimation/ScrollAnimation.d.ts +7 -1
  61. package/ScrollAnimation/ScrollAnimation.js +12 -0
  62. package/ScrollAnimation/ScrollAnimation.js.map +2 -2
  63. package/ScrollAnimation/ScrollAnimationChild.d.ts +6 -0
  64. package/ScrollAnimation/ScrollAnimationChild.js +17 -4
  65. package/ScrollAnimation/ScrollAnimationChild.js.map +2 -2
  66. package/ScrollAnimation/ScrollAnimationChildWithEase.d.ts +7 -1
  67. package/ScrollAnimation/ScrollAnimationChildWithEase.js +12 -0
  68. package/ScrollAnimation/ScrollAnimationChildWithEase.js.map +2 -2
  69. package/ScrollAnimation/ScrollAnimationParent.d.ts +6 -0
  70. package/ScrollAnimation/ScrollAnimationParent.js +12 -0
  71. package/ScrollAnimation/ScrollAnimationParent.js.map +2 -2
  72. package/ScrollAnimation/ScrollAnimationTarget.d.ts +43 -0
  73. package/ScrollAnimation/ScrollAnimationTarget.js +68 -0
  74. package/ScrollAnimation/ScrollAnimationTarget.js.map +7 -0
  75. package/ScrollAnimation/ScrollAnimationTimeline.d.ts +35 -0
  76. package/ScrollAnimation/ScrollAnimationTimeline.js +28 -0
  77. package/ScrollAnimation/ScrollAnimationTimeline.js.map +7 -0
  78. package/ScrollAnimation/ScrollAnimationWithEase.d.ts +7 -1
  79. package/ScrollAnimation/ScrollAnimationWithEase.js +12 -0
  80. package/ScrollAnimation/ScrollAnimationWithEase.js.map +2 -2
  81. package/ScrollAnimation/animationScrollWithEase.d.ts +2 -0
  82. package/ScrollAnimation/animationScrollWithEase.js +12 -1
  83. package/ScrollAnimation/animationScrollWithEase.js.map +2 -2
  84. package/ScrollAnimation/index.d.ts +3 -0
  85. package/ScrollAnimation/index.js +3 -0
  86. package/ScrollAnimation/index.js.map +2 -2
  87. package/ScrollAnimation/withScrollAnimationDebug.d.ts +28 -0
  88. package/ScrollAnimation/withScrollAnimationDebug.js +309 -0
  89. package/ScrollAnimation/withScrollAnimationDebug.js.map +7 -0
  90. package/ScrollReveal/ScrollReveal.d.ts +1 -1
  91. package/ScrollReveal/ScrollReveal.js.map +1 -1
  92. package/Sentinel/Sentinel.d.ts +1 -1
  93. package/Sentinel/Sentinel.js.map +1 -1
  94. package/Slider/Slider.d.ts +1 -1
  95. package/Slider/Slider.js.map +1 -1
  96. package/Sticky/Sticky.d.ts +1 -1
  97. package/Sticky/Sticky.js.map +1 -1
  98. package/Tabs/Tabs.d.ts +1 -1
  99. package/Tabs/Tabs.js.map +1 -1
  100. package/Transition/Transition.d.ts +23 -1
  101. package/Transition/Transition.js.map +2 -2
  102. package/decorators/withTransition.d.ts +11 -0
  103. package/decorators/withTransition.js +49 -0
  104. package/decorators/withTransition.js.map +2 -2
  105. package/package.json +3 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/ui/ScrollAnimation/animationScrollWithEase.ts"],
4
- "sourcesContent": ["import type { BaseConfig, BaseProps, BaseDecorator, BaseInterface } from '@studiometa/js-toolkit';\nimport { ease } from '@studiometa/js-toolkit/utils';\nimport type { AbstractScrollAnimation } from './AbstractScrollAnimation.js';\n\nconst regex = /ease([A-Z])/;\nconst eases = Object.fromEntries(\n Object.entries(ease)\n .filter(([name]) => name.startsWith('ease'))\n .map(([name, value]) => [name.replace(regex, (match, $1) => $1.toLowerCase()), value]),\n);\n\nexport interface AnimationScrollWithEaseProps extends BaseProps {\n $options: {\n ease: string;\n };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface AnimationScrollWithEaseInterface extends BaseInterface {}\n\n/**\n * Extend a `ScrollAnimation` component to use easings.\n */\nexport function animationScrollWithEase<S extends AbstractScrollAnimation>(\n ScrollAnimation: typeof AbstractScrollAnimation,\n): BaseDecorator<AnimationScrollWithEaseInterface, S, AnimationScrollWithEaseProps> {\n class AnimationScrollWithEase extends ScrollAnimation<AnimationScrollWithEaseProps> {\n /**\n * Config.\n */\n static config: BaseConfig = {\n ...ScrollAnimation.config,\n name: `${ScrollAnimation.config.name}WithEase`,\n options: {\n ...ScrollAnimation.config.options,\n ease: {\n type: String,\n default: 'outExpo',\n },\n },\n };\n\n /**\n * Eases the progress value.\n */\n render(progress: number) {\n if (typeof eases[this.$options.ease] === 'function') {\n // eslint-disable-next-line no-param-reassign\n progress = eases[this.$options.ease](progress);\n }\n\n super.render(progress);\n }\n }\n\n // @ts-ignore\n return AnimationScrollWithEase;\n}\n"],
5
- "mappings": "AACA,SAAS,YAAY;AAGrB,MAAM,QAAQ;AACd,MAAM,QAAQ,OAAO;AAAA,EACnB,OAAO,QAAQ,IAAI,EAChB,OAAO,CAAC,CAAC,IAAI,MAAM,KAAK,WAAW,MAAM,CAAC,EAC1C,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,CAAC,OAAO,OAAO,GAAG,YAAY,CAAC,GAAG,KAAK,CAAC;AACzF;AAcO,SAAS,wBACd,iBACkF;AAAA,EAClF,MAAM,gCAAgC,gBAA8C;AAAA;AAAA;AAAA;AAAA,IAIlF,OAAO,SAAqB;AAAA,MAC1B,GAAG,gBAAgB;AAAA,MACnB,MAAM,GAAG,gBAAgB,OAAO,IAAI;AAAA,MACpC,SAAS;AAAA,QACP,GAAG,gBAAgB,OAAO;AAAA,QAC1B,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAKA,OAAO,UAAkB;AACvB,UAAI,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,YAAY;AAEnD,mBAAW,MAAM,KAAK,SAAS,IAAI,EAAE,QAAQ;AAAA,MAC/C;AAEA,YAAM,OAAO,QAAQ;AAAA,IACvB;AAAA,EACF;AAGA,SAAO;AACT;",
4
+ "sourcesContent": ["import type { BaseConfig, BaseProps, BaseDecorator, BaseInterface } from '@studiometa/js-toolkit';\nimport { ease, isDev } from '@studiometa/js-toolkit/utils';\nimport type { AbstractScrollAnimation } from './AbstractScrollAnimation.js';\n\nconst regex = /ease([A-Z])/;\nconst eases = Object.fromEntries(\n Object.entries(ease)\n .filter(([name]) => name.startsWith('ease'))\n .map(([name, value]) => [name.replace(regex, (match, $1) => $1.toLowerCase()), value]),\n);\n\nexport interface AnimationScrollWithEaseProps extends BaseProps {\n $options: {\n ease: string;\n };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface AnimationScrollWithEaseInterface extends BaseInterface {}\n\n/**\n * Extend a `ScrollAnimation` component to use easings.\n *\n * @deprecated This decorator is deprecated. Easing can be applied directly via CSS or animation options.\n */\nexport function animationScrollWithEase<S extends AbstractScrollAnimation>(\n ScrollAnimation: typeof AbstractScrollAnimation,\n): BaseDecorator<AnimationScrollWithEaseInterface, S, AnimationScrollWithEaseProps> {\n class AnimationScrollWithEase extends ScrollAnimation<AnimationScrollWithEaseProps> {\n /**\n * Config.\n */\n static config: BaseConfig = {\n ...ScrollAnimation.config,\n name: `${ScrollAnimation.config.name}WithEase`,\n options: {\n ...ScrollAnimation.config.options,\n ease: {\n type: String,\n default: 'outExpo',\n },\n },\n };\n\n /**\n * Display a deprecation warning.\n */\n mounted() {\n if (isDev) {\n console.warn(\n `The animationScrollWithEase decorator is deprecated.`,\n '\\nEasing can be applied directly via CSS or animation options.',\n );\n }\n }\n\n /**\n * Eases the progress value.\n */\n render(progress: number) {\n if (typeof eases[this.$options.ease] === 'function') {\n // eslint-disable-next-line no-param-reassign\n progress = eases[this.$options.ease](progress);\n }\n\n super.render(progress);\n }\n }\n\n // @ts-ignore\n return AnimationScrollWithEase;\n}\n"],
5
+ "mappings": "AACA,SAAS,MAAM,aAAa;AAG5B,MAAM,QAAQ;AACd,MAAM,QAAQ,OAAO;AAAA,EACnB,OAAO,QAAQ,IAAI,EAChB,OAAO,CAAC,CAAC,IAAI,MAAM,KAAK,WAAW,MAAM,CAAC,EAC1C,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,CAAC,OAAO,OAAO,GAAG,YAAY,CAAC,GAAG,KAAK,CAAC;AACzF;AAgBO,SAAS,wBACd,iBACkF;AAAA,EAClF,MAAM,gCAAgC,gBAA8C;AAAA;AAAA;AAAA;AAAA,IAIlF,OAAO,SAAqB;AAAA,MAC1B,GAAG,gBAAgB;AAAA,MACnB,MAAM,GAAG,gBAAgB,OAAO,IAAI;AAAA,MACpC,SAAS;AAAA,QACP,GAAG,gBAAgB,OAAO;AAAA,QAC1B,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAKA,UAAU;AACR,UAAI,OAAO;AACT,gBAAQ;AAAA,UACN;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAKA,OAAO,UAAkB;AACvB,UAAI,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,YAAY;AAEnD,mBAAW,MAAM,KAAK,SAAS,IAAI,EAAE,QAAQ;AAAA,MAC/C;AAEA,YAAM,OAAO,QAAQ;AAAA,IACvB;AAAA,EACF;AAGA,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,7 @@
1
1
  export * from './AbstractScrollAnimation.js';
2
+ export * from './ScrollAnimationTimeline.js';
3
+ export * from './ScrollAnimationTarget.js';
4
+ export * from './withScrollAnimationDebug.js';
2
5
  export * from './animationScrollWithEase.js';
3
6
  export * from './ScrollAnimation.js';
4
7
  export * from './ScrollAnimationWithEase.js';
@@ -1,4 +1,7 @@
1
1
  export * from "./AbstractScrollAnimation.js";
2
+ export * from "./ScrollAnimationTimeline.js";
3
+ export * from "./ScrollAnimationTarget.js";
4
+ export * from "./withScrollAnimationDebug.js";
2
5
  export * from "./animationScrollWithEase.js";
3
6
  export * from "./ScrollAnimation.js";
4
7
  export * from "./ScrollAnimationWithEase.js";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/ui/ScrollAnimation/index.ts"],
4
- "sourcesContent": ["export * from './AbstractScrollAnimation.js';\nexport * from './animationScrollWithEase.js';\nexport * from './ScrollAnimation.js';\nexport * from './ScrollAnimationWithEase.js';\nexport * from './ScrollAnimationChild.js';\nexport * from './ScrollAnimationChildWithEase.js';\nexport * from './ScrollAnimationParent.js';\n"],
5
- "mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
4
+ "sourcesContent": ["export * from './AbstractScrollAnimation.js';\nexport * from './ScrollAnimationTimeline.js';\nexport * from './ScrollAnimationTarget.js';\nexport * from './withScrollAnimationDebug.js';\n\n// Deprecated exports\nexport * from './animationScrollWithEase.js';\nexport * from './ScrollAnimation.js';\nexport * from './ScrollAnimationWithEase.js';\nexport * from './ScrollAnimationChild.js';\nexport * from './ScrollAnimationChildWithEase.js';\nexport * from './ScrollAnimationParent.js';\n"],
5
+ "mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,28 @@
1
+ import type { Base, BaseProps, BaseInterface, BaseDecorator } from '@studiometa/js-toolkit';
2
+ export interface WithScrollAnimationDebugProps extends BaseProps {
3
+ $options: {
4
+ debug: boolean;
5
+ offset: string;
6
+ };
7
+ }
8
+ export interface WithScrollAnimationDebugInterface extends BaseInterface {
9
+ }
10
+ /**
11
+ * Add debug capabilities to a ScrollAnimationTimeline component.
12
+ *
13
+ * @example
14
+ * ```js
15
+ * import { ScrollAnimationTimeline } from '@studiometa/ui';
16
+ * import { withScrollAnimationDebug } from '@studiometa/ui/ScrollAnimation/withScrollAnimationDebug';
17
+ *
18
+ * class App extends Base {
19
+ * static config = {
20
+ * name: 'App',
21
+ * components: {
22
+ * ScrollAnimationTimeline: withScrollAnimationDebug(ScrollAnimationTimeline),
23
+ * },
24
+ * };
25
+ * }
26
+ * ```
27
+ */
28
+ export declare function withScrollAnimationDebug<S extends Base>(BaseClass: typeof Base): BaseDecorator<WithScrollAnimationDebugInterface, S, WithScrollAnimationDebugProps>;
@@ -0,0 +1,309 @@
1
+ import { createElement } from "@studiometa/js-toolkit/utils";
2
+ const debugColors = [
3
+ "#8b5cf6",
4
+ // violet
5
+ "#3b82f6",
6
+ // blue
7
+ "#10b981",
8
+ // emerald
9
+ "#f59e0b",
10
+ // amber
11
+ "#ef4444",
12
+ // red
13
+ "#ec4899",
14
+ // pink
15
+ "#06b6d4",
16
+ // cyan
17
+ "#84cc16"
18
+ // lime
19
+ ];
20
+ function getDebugColor(index) {
21
+ return debugColors[(index - 1) % debugColors.length];
22
+ }
23
+ const debugStyles = `
24
+ .scroll-animation-debug {
25
+ --debug-color: #8b5cf6;
26
+ position: fixed;
27
+ right: 0;
28
+ top: 0;
29
+ bottom: 0;
30
+ width: 80px;
31
+ pointer-events: none;
32
+ z-index: 99999;
33
+ font-family: ui-monospace, monospace;
34
+ font-size: 10px;
35
+ }
36
+ .scroll-animation-debug__marker {
37
+ position: absolute;
38
+ right: 0;
39
+ display: flex;
40
+ align-items: center;
41
+ gap: 4px;
42
+ padding: 2px 6px;
43
+ color: white;
44
+ white-space: nowrap;
45
+ transform: translateY(-50%);
46
+ }
47
+ .scroll-animation-debug__marker::before {
48
+ content: '';
49
+ position: absolute;
50
+ top: 50%;
51
+ right: 100%;
52
+ width: 100vw;
53
+ height: 1px;
54
+ background: var(--debug-color);
55
+ }
56
+ .scroll-animation-debug__marker--start {
57
+ background: var(--debug-color);
58
+ }
59
+ .scroll-animation-debug__marker--end {
60
+ background: var(--debug-color);
61
+ opacity: 0.7;
62
+ }
63
+ .scroll-animation-debug__outline {
64
+ position: absolute;
65
+ inset: 0;
66
+ border: 2px dashed var(--debug-color);
67
+ pointer-events: none;
68
+ z-index: 99998;
69
+ }
70
+ .scroll-animation-debug-progress-container {
71
+ position: fixed;
72
+ right: 8px;
73
+ top: 50%;
74
+ transform: translateY(-50%);
75
+ display: flex;
76
+ flex-direction: row;
77
+ align-items: center;
78
+ gap: 8px;
79
+ pointer-events: none;
80
+ z-index: 99999;
81
+ font-family: ui-monospace, monospace;
82
+ font-size: 10px;
83
+ }
84
+ .scroll-animation-debug__progress {
85
+ --debug-color: #8b5cf6;
86
+ display: flex;
87
+ flex-direction: column;
88
+ align-items: center;
89
+ gap: 4px;
90
+ }
91
+ .scroll-animation-debug__progress-bar {
92
+ width: 4px;
93
+ height: 60px;
94
+ background: rgba(139, 92, 246, 0.2);
95
+ border-radius: 2px;
96
+ overflow: hidden;
97
+ }
98
+ .scroll-animation-debug__progress-fill {
99
+ width: 100%;
100
+ background: var(--debug-color);
101
+ border-radius: 2px;
102
+ transition: height 0.1s ease-out;
103
+ }
104
+ .scroll-animation-debug__progress-text {
105
+ color: var(--debug-color);
106
+ font-weight: bold;
107
+ width: 3ch;
108
+ text-align: center;
109
+ }
110
+ `;
111
+ let styleElement = null;
112
+ let progressContainer = null;
113
+ let debugInstanceCount = 0;
114
+ let debugIdCounter = 0;
115
+ function injectDebugStyles() {
116
+ if (!styleElement) {
117
+ styleElement = createElement("style", [debugStyles]);
118
+ document.head.appendChild(styleElement);
119
+ }
120
+ }
121
+ function removeDebugStyles() {
122
+ if (styleElement && debugInstanceCount === 0) {
123
+ styleElement.remove();
124
+ styleElement = null;
125
+ }
126
+ }
127
+ function getProgressContainer() {
128
+ if (!progressContainer) {
129
+ progressContainer = createElement("div", {
130
+ class: "scroll-animation-debug-progress-container"
131
+ });
132
+ document.body.appendChild(progressContainer);
133
+ }
134
+ return progressContainer;
135
+ }
136
+ function cleanupProgressContainer() {
137
+ if (progressContainer && progressContainer.children.length === 0) {
138
+ progressContainer.remove();
139
+ progressContainer = null;
140
+ }
141
+ }
142
+ const namedOffsets = {
143
+ start: 0,
144
+ center: 0.5,
145
+ end: 1
146
+ };
147
+ function parseOffsetValue(value) {
148
+ if (namedOffsets[value] !== void 0) {
149
+ return namedOffsets[value];
150
+ }
151
+ if (value.endsWith("%")) {
152
+ return Number.parseFloat(value) / 100;
153
+ }
154
+ return Number.parseFloat(value) || 0;
155
+ }
156
+ function parseOffset(offset) {
157
+ const parts = offset.split("/").map((part) => part.trim().split(" "));
158
+ const viewportStart = parseOffsetValue(parts[0]?.[1] || "end");
159
+ const viewportEnd = parseOffsetValue(parts[1]?.[1] || "start");
160
+ return { viewportStart, viewportEnd };
161
+ }
162
+ function createDebugElements(color) {
163
+ const startMarker = createElement(
164
+ "div",
165
+ { class: "scroll-animation-debug__marker scroll-animation-debug__marker--start" },
166
+ [createElement("span", ["start"])]
167
+ );
168
+ const endMarker = createElement(
169
+ "div",
170
+ { class: "scroll-animation-debug__marker scroll-animation-debug__marker--end" },
171
+ [createElement("span", ["end"])]
172
+ );
173
+ const wrapper = createElement("div", { class: "scroll-animation-debug" }, [
174
+ startMarker,
175
+ endMarker
176
+ ]);
177
+ wrapper.style.setProperty("--debug-color", color);
178
+ const progressBar = createElement("div", { class: "scroll-animation-debug__progress-fill" });
179
+ const progressText = createElement("span", { class: "scroll-animation-debug__progress-text" }, [
180
+ "0%"
181
+ ]);
182
+ const progress = createElement("div", { class: "scroll-animation-debug__progress" }, [
183
+ createElement("div", { class: "scroll-animation-debug__progress-bar" }, [progressBar]),
184
+ progressText
185
+ ]);
186
+ progress.style.setProperty("--debug-color", color);
187
+ return {
188
+ wrapper,
189
+ startMarker,
190
+ endMarker,
191
+ progress,
192
+ progressBar,
193
+ progressText
194
+ };
195
+ }
196
+ function createOutlineElement(color) {
197
+ const outline = createElement("div", {
198
+ class: "scroll-animation-debug__outline"
199
+ });
200
+ outline.style.setProperty("--debug-color", color);
201
+ return outline;
202
+ }
203
+ function withScrollAnimationDebug(BaseClass) {
204
+ class WithScrollAnimationDebug extends BaseClass {
205
+ static config = {
206
+ ...BaseClass.config,
207
+ name: BaseClass.config.name,
208
+ options: {
209
+ ...BaseClass.config.options,
210
+ debug: Boolean
211
+ }
212
+ };
213
+ /**
214
+ * Debug elements.
215
+ */
216
+ __debugElements = null;
217
+ /**
218
+ * Debug outline element.
219
+ */
220
+ __debugOutline = null;
221
+ /**
222
+ * Debug ID.
223
+ */
224
+ __debugId = "";
225
+ /**
226
+ * Mounted hook.
227
+ */
228
+ mounted() {
229
+ if (super.mounted) super.mounted();
230
+ if (this.$options.debug) {
231
+ this.__initDebug();
232
+ }
233
+ }
234
+ /**
235
+ * Destroyed hook.
236
+ */
237
+ destroyed() {
238
+ this.__destroyDebug();
239
+ if (super.destroyed) super.destroyed();
240
+ }
241
+ /**
242
+ * Initialize debug elements.
243
+ */
244
+ __initDebug() {
245
+ debugIdCounter += 1;
246
+ debugInstanceCount += 1;
247
+ this.__debugId = `timeline-${debugIdCounter}`;
248
+ const color = getDebugColor(debugIdCounter);
249
+ injectDebugStyles();
250
+ this.__debugElements = createDebugElements(color);
251
+ document.body.appendChild(this.__debugElements.wrapper);
252
+ const container = getProgressContainer();
253
+ container.appendChild(this.__debugElements.progress);
254
+ const { viewportStart, viewportEnd } = parseOffset(this.$options.offset);
255
+ const viewportHeight = window.innerHeight;
256
+ this.__debugElements.startMarker.style.top = `${viewportStart * viewportHeight}px`;
257
+ this.__debugElements.endMarker.style.top = `${viewportEnd * viewportHeight}px`;
258
+ this.__debugOutline = createOutlineElement(color);
259
+ const position = getComputedStyle(this.$el).position;
260
+ if (position === "static") {
261
+ this.$el.style.position = "relative";
262
+ }
263
+ this.$el.appendChild(this.__debugOutline);
264
+ }
265
+ /**
266
+ * Destroy debug elements.
267
+ */
268
+ __destroyDebug() {
269
+ if (this.__debugElements) {
270
+ this.__debugElements.wrapper.remove();
271
+ this.__debugElements.progress.remove();
272
+ this.__debugElements = null;
273
+ }
274
+ if (this.__debugOutline) {
275
+ this.__debugOutline.remove();
276
+ this.__debugOutline = null;
277
+ }
278
+ if (this.$options.debug) {
279
+ debugInstanceCount -= 1;
280
+ cleanupProgressContainer();
281
+ removeDebugStyles();
282
+ }
283
+ }
284
+ /**
285
+ * Update debug progress.
286
+ */
287
+ __updateDebug(props) {
288
+ if (!this.__debugElements) return;
289
+ const { progressBar, progressText } = this.__debugElements;
290
+ const progress = Math.round(props.dampedProgress.y * 100);
291
+ progressBar.style.height = `${progress}%`;
292
+ progressText.textContent = `${progress}%`;
293
+ }
294
+ /**
295
+ * Scrolled in view hook.
296
+ */
297
+ scrolledInView(props) {
298
+ if (this.$options.debug) {
299
+ this.__updateDebug(props);
300
+ }
301
+ super.scrolledInView(props);
302
+ }
303
+ }
304
+ return WithScrollAnimationDebug;
305
+ }
306
+ export {
307
+ withScrollAnimationDebug
308
+ };
309
+ //# sourceMappingURL=withScrollAnimationDebug.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../packages/ui/ScrollAnimation/withScrollAnimationDebug.ts"],
4
+ "sourcesContent": ["import type {\n Base,\n BaseProps,\n BaseConfig,\n BaseInterface,\n BaseDecorator,\n ScrollInViewProps,\n} from '@studiometa/js-toolkit';\nimport { createElement } from '@studiometa/js-toolkit/utils';\n\n/**\n * Debug marker element interface.\n */\ninterface DebugElements {\n wrapper: HTMLElement;\n startMarker: HTMLElement;\n endMarker: HTMLElement;\n progress: HTMLElement;\n progressBar: HTMLElement;\n progressText: HTMLElement;\n}\n\n/**\n * Debug colors for different timelines.\n */\nconst debugColors = [\n '#8b5cf6', // violet\n '#3b82f6', // blue\n '#10b981', // emerald\n '#f59e0b', // amber\n '#ef4444', // red\n '#ec4899', // pink\n '#06b6d4', // cyan\n '#84cc16', // lime\n];\n\n/**\n * Get debug color for a given index.\n */\nfunction getDebugColor(index: number): string {\n return debugColors[(index - 1) % debugColors.length];\n}\n\n/**\n * Debug styles.\n */\nconst debugStyles = `\n .scroll-animation-debug {\n --debug-color: #8b5cf6;\n position: fixed;\n right: 0;\n top: 0;\n bottom: 0;\n width: 80px;\n pointer-events: none;\n z-index: 99999;\n font-family: ui-monospace, monospace;\n font-size: 10px;\n }\n .scroll-animation-debug__marker {\n position: absolute;\n right: 0;\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n color: white;\n white-space: nowrap;\n transform: translateY(-50%);\n }\n .scroll-animation-debug__marker::before {\n content: '';\n position: absolute;\n top: 50%;\n right: 100%;\n width: 100vw;\n height: 1px;\n background: var(--debug-color);\n }\n .scroll-animation-debug__marker--start {\n background: var(--debug-color);\n }\n .scroll-animation-debug__marker--end {\n background: var(--debug-color);\n opacity: 0.7;\n }\n .scroll-animation-debug__outline {\n position: absolute;\n inset: 0;\n border: 2px dashed var(--debug-color);\n pointer-events: none;\n z-index: 99998;\n }\n .scroll-animation-debug-progress-container {\n position: fixed;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 8px;\n pointer-events: none;\n z-index: 99999;\n font-family: ui-monospace, monospace;\n font-size: 10px;\n }\n .scroll-animation-debug__progress {\n --debug-color: #8b5cf6;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n }\n .scroll-animation-debug__progress-bar {\n width: 4px;\n height: 60px;\n background: rgba(139, 92, 246, 0.2);\n border-radius: 2px;\n overflow: hidden;\n }\n .scroll-animation-debug__progress-fill {\n width: 100%;\n background: var(--debug-color);\n border-radius: 2px;\n transition: height 0.1s ease-out;\n }\n .scroll-animation-debug__progress-text {\n color: var(--debug-color);\n font-weight: bold;\n width: 3ch;\n text-align: center;\n }\n`;\n\n/**\n * Shared style element.\n */\nlet styleElement: HTMLStyleElement | null = null;\n\n/**\n * Shared progress container.\n */\nlet progressContainer: HTMLElement | null = null;\n\n/**\n * Debug instance counter.\n */\nlet debugInstanceCount = 0;\n\n/**\n * Debug ID counter.\n */\nlet debugIdCounter = 0;\n\n/**\n * Inject debug styles if not already injected.\n */\nfunction injectDebugStyles() {\n if (!styleElement) {\n styleElement = createElement('style', [debugStyles]) as HTMLStyleElement;\n document.head.appendChild(styleElement);\n }\n}\n\n/**\n * Remove debug styles if no more instances.\n */\nfunction removeDebugStyles() {\n if (styleElement && debugInstanceCount === 0) {\n styleElement.remove();\n styleElement = null;\n }\n}\n\n/**\n * Get or create the shared progress container.\n */\nfunction getProgressContainer(): HTMLElement {\n if (!progressContainer) {\n progressContainer = createElement('div', {\n class: 'scroll-animation-debug-progress-container',\n });\n document.body.appendChild(progressContainer);\n }\n return progressContainer;\n}\n\n/**\n * Remove progress container if empty.\n */\nfunction cleanupProgressContainer() {\n if (progressContainer && progressContainer.children.length === 0) {\n progressContainer.remove();\n progressContainer = null;\n }\n}\n\n/**\n * Named offset values mapping.\n */\nconst namedOffsets: Record<string, number> = {\n start: 0,\n center: 0.5,\n end: 1,\n};\n\n/**\n * Parse an offset value to a ratio (0-1).\n */\nfunction parseOffsetValue(value: string): number {\n if (namedOffsets[value] !== undefined) {\n return namedOffsets[value];\n }\n if (value.endsWith('%')) {\n return Number.parseFloat(value) / 100;\n }\n return Number.parseFloat(value) || 0;\n}\n\n/**\n * Parse the offset option to get viewport positions.\n * Format: \"<targetStart> <viewportStart> / <targetEnd> <viewportEnd>\"\n */\nfunction parseOffset(offset: string): { viewportStart: number; viewportEnd: number } {\n const parts = offset.split('/').map((part) => part.trim().split(' '));\n const viewportStart = parseOffsetValue(parts[0]?.[1] || 'end');\n const viewportEnd = parseOffsetValue(parts[1]?.[1] || 'start');\n return { viewportStart, viewportEnd };\n}\n\n/**\n * Create debug marker elements.\n */\nfunction createDebugElements(color: string): DebugElements {\n const startMarker = createElement(\n 'div',\n { class: 'scroll-animation-debug__marker scroll-animation-debug__marker--start' },\n [createElement('span', ['start'])],\n );\n\n const endMarker = createElement(\n 'div',\n { class: 'scroll-animation-debug__marker scroll-animation-debug__marker--end' },\n [createElement('span', ['end'])],\n );\n\n const wrapper = createElement('div', { class: 'scroll-animation-debug' }, [\n startMarker,\n endMarker,\n ]) as HTMLElement;\n wrapper.style.setProperty('--debug-color', color);\n\n const progressBar = createElement('div', { class: 'scroll-animation-debug__progress-fill' });\n const progressText = createElement('span', { class: 'scroll-animation-debug__progress-text' }, [\n '0%',\n ]);\n\n const progress = createElement('div', { class: 'scroll-animation-debug__progress' }, [\n createElement('div', { class: 'scroll-animation-debug__progress-bar' }, [progressBar]),\n progressText,\n ]) as HTMLElement;\n progress.style.setProperty('--debug-color', color);\n\n return {\n wrapper,\n startMarker,\n endMarker,\n progress,\n progressBar,\n progressText,\n };\n}\n\n/**\n * Create outline element for the timeline.\n */\nfunction createOutlineElement(color: string): HTMLElement {\n const outline = createElement('div', {\n class: 'scroll-animation-debug__outline',\n }) as HTMLElement;\n outline.style.setProperty('--debug-color', color);\n return outline;\n}\n\nexport interface WithScrollAnimationDebugProps extends BaseProps {\n $options: {\n debug: boolean;\n offset: string;\n };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface WithScrollAnimationDebugInterface extends BaseInterface {}\n\n/**\n * Add debug capabilities to a ScrollAnimationTimeline component.\n *\n * @example\n * ```js\n * import { ScrollAnimationTimeline } from '@studiometa/ui';\n * import { withScrollAnimationDebug } from '@studiometa/ui/ScrollAnimation/withScrollAnimationDebug';\n *\n * class App extends Base {\n * static config = {\n * name: 'App',\n * components: {\n * ScrollAnimationTimeline: withScrollAnimationDebug(ScrollAnimationTimeline),\n * },\n * };\n * }\n * ```\n */\nexport function withScrollAnimationDebug<S extends Base>(\n BaseClass: typeof Base,\n): BaseDecorator<WithScrollAnimationDebugInterface, S, WithScrollAnimationDebugProps> {\n /**\n * Class.\n */\n class WithScrollAnimationDebug<T extends BaseProps = BaseProps> extends BaseClass<\n T & WithScrollAnimationDebugProps\n > {\n static config: BaseConfig = {\n ...BaseClass.config,\n name: BaseClass.config.name,\n options: {\n ...BaseClass.config.options,\n debug: Boolean,\n },\n };\n\n /**\n * Debug elements.\n */\n private __debugElements: DebugElements | null = null;\n\n /**\n * Debug outline element.\n */\n private __debugOutline: HTMLElement | null = null;\n\n /**\n * Debug ID.\n */\n private __debugId: string = '';\n\n /**\n * Mounted hook.\n */\n mounted() {\n // @ts-expect-error - Calling parent method\n if (super.mounted) super.mounted();\n if (this.$options.debug) {\n this.__initDebug();\n }\n }\n\n /**\n * Destroyed hook.\n */\n destroyed() {\n this.__destroyDebug();\n // @ts-expect-error - Calling parent method\n if (super.destroyed) super.destroyed();\n }\n\n /**\n * Initialize debug elements.\n */\n __initDebug() {\n debugIdCounter += 1;\n debugInstanceCount += 1;\n this.__debugId = `timeline-${debugIdCounter}`;\n\n const color = getDebugColor(debugIdCounter);\n\n // Inject styles\n injectDebugStyles();\n\n // Create and append debug markers\n this.__debugElements = createDebugElements(color);\n document.body.appendChild(this.__debugElements.wrapper);\n\n // Append progress to shared container\n const container = getProgressContainer();\n container.appendChild(this.__debugElements.progress);\n\n // Position markers based on offset option\n const { viewportStart, viewportEnd } = parseOffset(this.$options.offset);\n const viewportHeight = window.innerHeight;\n\n this.__debugElements.startMarker.style.top = `${viewportStart * viewportHeight}px`;\n this.__debugElements.endMarker.style.top = `${viewportEnd * viewportHeight}px`;\n\n // Create and append outline\n this.__debugOutline = createOutlineElement(color);\n const position = getComputedStyle(this.$el).position;\n if (position === 'static') {\n (this.$el as HTMLElement).style.position = 'relative';\n }\n this.$el.appendChild(this.__debugOutline);\n }\n\n /**\n * Destroy debug elements.\n */\n __destroyDebug() {\n if (this.__debugElements) {\n this.__debugElements.wrapper.remove();\n this.__debugElements.progress.remove();\n this.__debugElements = null;\n }\n\n if (this.__debugOutline) {\n this.__debugOutline.remove();\n this.__debugOutline = null;\n }\n\n if (this.$options.debug) {\n debugInstanceCount -= 1;\n cleanupProgressContainer();\n removeDebugStyles();\n }\n }\n\n /**\n * Update debug progress.\n */\n __updateDebug(props: ScrollInViewProps) {\n if (!this.__debugElements) return;\n\n const { progressBar, progressText } = this.__debugElements;\n\n // Update progress\n const progress = Math.round(props.dampedProgress.y * 100);\n progressBar.style.height = `${progress}%`;\n progressText.textContent = `${progress}%`;\n }\n\n /**\n * Scrolled in view hook.\n */\n scrolledInView(props: ScrollInViewProps) {\n if (this.$options.debug) {\n this.__updateDebug(props);\n }\n\n // @ts-expect-error - Calling parent method\n super.scrolledInView(props);\n }\n }\n\n // @ts-ignore\n return WithScrollAnimationDebug;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -12,7 +12,7 @@ export interface ScrollRevealProps extends BaseProps {
12
12
  declare const ScrollReveal_base: import("@studiometa/js-toolkit").BaseDecorator<import("@studiometa/js-toolkit").WithMountWhenInViewInterface, Transition<BaseProps>, import("@studiometa/js-toolkit").WithMountWhenInViewProps>;
13
13
  /**
14
14
  * ScrollReveal class.
15
- * @link https://ui.studiometa.dev/-/components/ScrollReveal/
15
+ * @link https://ui.studiometa.dev/components/ScrollReveal/
16
16
  */
17
17
  export declare class ScrollReveal<T extends BaseProps = BaseProps> extends ScrollReveal_base<T & ScrollRevealProps> {
18
18
  /**
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/ui/ScrollReveal/ScrollReveal.ts"],
4
- "sourcesContent": ["import { withMountWhenInView, useScroll, ScrollServiceProps } from '@studiometa/js-toolkit';\nimport type { BaseProps, BaseConfig } from '@studiometa/js-toolkit';\nimport { Transition } from '../Transition/index.js';\n\nexport interface ScrollRevealProps extends BaseProps {\n $refs: {\n target?: HTMLElement;\n };\n $options: {\n repeat: boolean;\n };\n}\n\n/**\n * ScrollReveal class.\n * @link https://ui.studiometa.dev/-/components/ScrollReveal/\n */\nexport class ScrollReveal<T extends BaseProps = BaseProps> extends withMountWhenInView<Transition>(\n Transition,\n)<T & ScrollRevealProps> {\n /**\n * Config.\n */\n static config: BaseConfig = {\n ...Transition.config,\n name: 'ScrollReveal',\n refs: ['target'],\n options: {\n ...Transition.config.options,\n enterKeep: {\n type: Boolean,\n default: true,\n },\n repeat: Boolean,\n intersectionObserver: {\n type: Object,\n default: () => ({ threshold: [0, 1] }),\n },\n },\n };\n\n /**\n * Vertical scroll direction.\n */\n static scrollDirectionY: ScrollServiceProps['direction']['y'] = 'NONE';\n\n /**\n * Get the transition target.\n */\n get target(): HTMLElement {\n return this.$refs.target ?? this.$el;\n }\n\n /**\n * Trigger the `enter` transition on mount.\n */\n mounted() {\n if (!this.$options.repeat) {\n this.enter();\n this.$terminate();\n return;\n }\n\n const scroll = useScroll();\n\n if (!scroll.has('ScrollRevealRepeat')) {\n scroll.add('ScrollRevealRepeat', (props) => {\n ScrollReveal.scrollDirectionY = props.direction.y;\n });\n }\n\n if (ScrollReveal.scrollDirectionY !== 'UP') {\n this.enter();\n }\n }\n}\n"],
4
+ "sourcesContent": ["import { withMountWhenInView, useScroll, ScrollServiceProps } from '@studiometa/js-toolkit';\nimport type { BaseProps, BaseConfig } from '@studiometa/js-toolkit';\nimport { Transition } from '../Transition/index.js';\n\nexport interface ScrollRevealProps extends BaseProps {\n $refs: {\n target?: HTMLElement;\n };\n $options: {\n repeat: boolean;\n };\n}\n\n/**\n * ScrollReveal class.\n * @link https://ui.studiometa.dev/components/ScrollReveal/\n */\nexport class ScrollReveal<T extends BaseProps = BaseProps> extends withMountWhenInView<Transition>(\n Transition,\n)<T & ScrollRevealProps> {\n /**\n * Config.\n */\n static config: BaseConfig = {\n ...Transition.config,\n name: 'ScrollReveal',\n refs: ['target'],\n options: {\n ...Transition.config.options,\n enterKeep: {\n type: Boolean,\n default: true,\n },\n repeat: Boolean,\n intersectionObserver: {\n type: Object,\n default: () => ({ threshold: [0, 1] }),\n },\n },\n };\n\n /**\n * Vertical scroll direction.\n */\n static scrollDirectionY: ScrollServiceProps['direction']['y'] = 'NONE';\n\n /**\n * Get the transition target.\n */\n get target(): HTMLElement {\n return this.$refs.target ?? this.$el;\n }\n\n /**\n * Trigger the `enter` transition on mount.\n */\n mounted() {\n if (!this.$options.repeat) {\n this.enter();\n this.$terminate();\n return;\n }\n\n const scroll = useScroll();\n\n if (!scroll.has('ScrollRevealRepeat')) {\n scroll.add('ScrollRevealRepeat', (props) => {\n ScrollReveal.scrollDirectionY = props.direction.y;\n });\n }\n\n if (ScrollReveal.scrollDirectionY !== 'UP') {\n this.enter();\n }\n }\n}\n"],
5
5
  "mappings": "AAAA,SAAS,qBAAqB,iBAAqC;AAEnE,SAAS,kBAAkB;AAepB,MAAM,qBAAsD;AAAA,EACjE;AACF,EAAyB;AAAA;AAAA;AAAA;AAAA,EAIvB,OAAO,SAAqB;AAAA,IAC1B,GAAG,WAAW;AAAA,IACd,MAAM;AAAA,IACN,MAAM,CAAC,QAAQ;AAAA,IACf,SAAS;AAAA,MACP,GAAG,WAAW,OAAO;AAAA,MACrB,WAAW;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,MACA,QAAQ;AAAA,MACR,sBAAsB;AAAA,QACpB,MAAM;AAAA,QACN,SAAS,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,mBAAyD;AAAA;AAAA;AAAA;AAAA,EAKhE,IAAI,SAAsB;AACxB,WAAO,KAAK,MAAM,UAAU,KAAK;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AACR,QAAI,CAAC,KAAK,SAAS,QAAQ;AACzB,WAAK,MAAM;AACX,WAAK,WAAW;AAChB;AAAA,IACF;AAEA,UAAM,SAAS,UAAU;AAEzB,QAAI,CAAC,OAAO,IAAI,oBAAoB,GAAG;AACrC,aAAO,IAAI,sBAAsB,CAAC,UAAU;AAC1C,qBAAa,mBAAmB,MAAM,UAAU;AAAA,MAClD,CAAC;AAAA,IACH;AAEA,QAAI,aAAa,qBAAqB,MAAM;AAC1C,WAAK,MAAM;AAAA,IACb;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,7 @@ import type { BaseConfig } from '@studiometa/js-toolkit';
3
3
  declare const Sentinel_base: import("@studiometa/js-toolkit").BaseDecorator<import("@studiometa/js-toolkit").WithIntersectionObserverInterface, Base<import("@studiometa/js-toolkit").BaseProps>, import("@studiometa/js-toolkit").WithIntersectionObserverProps>;
4
4
  /**
5
5
  * Sentinel class.
6
- * @link https://ui.studiometa.dev/-/components/Sentinel/
6
+ * @link https://ui.studiometa.dev/components/Sentinel/
7
7
  */
8
8
  export declare class Sentinel extends Sentinel_base {
9
9
  /**
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/ui/Sentinel/Sentinel.ts"],
4
- "sourcesContent": ["import { Base, withIntersectionObserver } from '@studiometa/js-toolkit';\nimport type { BaseConfig } from '@studiometa/js-toolkit';\n\n/**\n * Sentinel class.\n * @link https://ui.studiometa.dev/-/components/Sentinel/\n */\nexport class Sentinel extends withIntersectionObserver(Base, { threshold: [0, 1] }) {\n /**\n * Config.\n */\n static config: BaseConfig = {\n name: 'Sentinel',\n };\n}\n"],
4
+ "sourcesContent": ["import { Base, withIntersectionObserver } from '@studiometa/js-toolkit';\nimport type { BaseConfig } from '@studiometa/js-toolkit';\n\n/**\n * Sentinel class.\n * @link https://ui.studiometa.dev/components/Sentinel/\n */\nexport class Sentinel extends withIntersectionObserver(Base, { threshold: [0, 1] }) {\n /**\n * Config.\n */\n static config: BaseConfig = {\n name: 'Sentinel',\n };\n}\n"],
5
5
  "mappings": "AAAA,SAAS,MAAM,gCAAgC;AAOxC,MAAM,iBAAiB,yBAAyB,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;AAAA;AAAA;AAAA;AAAA,EAIlF,OAAO,SAAqB;AAAA,IAC1B,MAAM;AAAA,EACR;AACF;",
6
6
  "names": []
7
7
  }
@@ -24,7 +24,7 @@ export interface SliderProps extends BaseProps {
24
24
  }
25
25
  /**
26
26
  * Slider class.
27
- * @link https://ui.studiometa.dev/-/components/Slider/
27
+ * @link https://ui.studiometa.dev/components/Slider/
28
28
  * @todo a11y
29
29
  */
30
30
  export declare class Slider<T extends BaseProps = BaseProps> extends Base<T & SliderProps> {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/ui/Slider/Slider.ts"],
4
- "sourcesContent": ["import { Base } from '@studiometa/js-toolkit';\nimport type {\n BaseProps,\n BaseConfig,\n DragServiceProps,\n KeyServiceProps,\n} from '@studiometa/js-toolkit';\nimport { clamp, inertiaFinalValue, nextFrame } from '@studiometa/js-toolkit/utils';\nimport { SliderDrag } from './SliderDrag.js';\nimport { SliderItem } from './SliderItem.js';\n\nexport type SliderModes = 'left' | 'center' | 'right';\n\ntype SliderState = { x: Record<SliderModes, number> };\n\nexport interface SliderProps extends BaseProps {\n $refs: {\n wrapper: HTMLElement;\n };\n $children: {\n SliderItem: SliderItem[];\n SliderDrag: SliderDrag[];\n };\n $options: {\n mode: SliderModes;\n fitBounds: boolean;\n contain: boolean;\n sensitivity: number;\n dropSensitivity: number;\n };\n}\n\n/**\n * Slider class.\n * @link https://ui.studiometa.dev/-/components/Slider/\n * @todo a11y\n */\nexport class Slider<T extends BaseProps = BaseProps> extends Base<T & SliderProps> {\n /**\n * Config.\n */\n static config: BaseConfig = {\n name: 'Slider',\n refs: ['wrapper'],\n emits: ['goto', 'index'],\n components: {\n SliderItem,\n SliderDrag,\n },\n options: {\n mode: { type: String, default: 'left' },\n fitBounds: Boolean,\n contain: Boolean,\n sensitivity: { type: Number, default: 1 },\n dropSensitivity: { type: Number, default: 2 },\n },\n };\n\n /**\n * Distance on the x axis.\n * @private\n */\n __distanceX = 0;\n\n /**\n * Initial x position.\n * @private\n */\n __initialX = 0;\n\n /**\n * Index of the current active slide.\n * @private\n */\n __currentIndex = 0;\n\n /**\n * Store all the states.\n */\n states: SliderState[] = [];\n\n /**\n * Origins for the different modes.\n */\n origins: Record<SliderModes, number> = {\n left: 0,\n center: 0,\n right: 0,\n };\n\n /**\n * Wether or not the wrapper is focused.\n */\n hasFocus = false;\n\n /**\n * Get the current index.\n */\n get currentIndex() {\n return this.__currentIndex;\n }\n\n /**\n * Set the current index and emit the `index` event.\n */\n set currentIndex(value: number) {\n this.currentSliderItem.disactivate();\n this.$emit('index', value);\n this.__currentIndex = value;\n this.currentSliderItem.activate();\n }\n\n /**\n * Get the current state.\n */\n get currentState() {\n return this.states[this.currentIndex];\n }\n\n /**\n * Get the first state.\n */\n get firstState() {\n return this.states[0];\n }\n\n /**\n * Get the last state.\n */\n get lastState() {\n return this.states.at(-1);\n }\n\n /**\n * Get the minimal contain state value.\n */\n get containMinState(): number {\n return this.getStateValueByMode(this.firstState.x, 'left');\n }\n\n /**\n * Get the maximal contain state value.\n */\n get containMaxState(): number {\n return this.getStateValueByMode(this.lastState.x, 'right');\n }\n\n /**\n * Get the last index.\n */\n get indexMax(): number {\n return this.$children.SliderItem.length - 1;\n }\n\n /**\n * Get the current SliderItem\n */\n get currentSliderItem() {\n return this.$children.SliderItem[this.currentIndex];\n }\n\n /**\n * Get the states for each SliderItem.\n */\n getStates(): SliderState[] {\n const { wrapper } = this.$refs;\n const originRect = wrapper.getBoundingClientRect();\n\n this.origins = {\n left: originRect.left,\n center: originRect.x + originRect.width / 2,\n right: originRect.x + originRect.width,\n };\n\n const states: SliderState[] = this.$children.SliderItem.map((item) => ({\n x: {\n left: (item.rect.x - this.origins.left) * -1,\n center: (item.rect.x + item.rect.width / 2 - this.origins.center) * -1,\n right: (item.rect.x + item.rect.width - this.origins.right) * -1,\n },\n }));\n\n if (this.$options.contain) {\n const { mode } = this.$options;\n // Find state where last child has passed the wrapper bound completely\n if (mode === 'left') {\n const lastChild = this.$children.SliderItem.at(-1);\n\n const maxState = states.find((state) => {\n const lastChildPosition =\n lastChild.rect.x - this.origins.left + lastChild.rect.width + state.x.left;\n const diffWithWrapperBound = originRect.width - lastChildPosition;\n if (diffWithWrapperBound > 0) {\n state.x.left = Math.min(state.x.left + diffWithWrapperBound, 0);\n return true;\n }\n\n return false;\n });\n\n if (maxState) {\n return states.map((state) => {\n state.x.left = Math.max(state.x.left, maxState.x.left);\n return state;\n });\n }\n }\n\n if (mode === 'right') {\n const maxStateIndex = states.findIndex((state) => state.x.right <= 0);\n const maxState = maxStateIndex < 0 ? states.at(-1) : states[maxStateIndex - 1];\n\n return states.map((state) => {\n state.x.right = maxStateIndex < 0 ? maxState.x.right : Math.min(state.x.right, 0);\n return state;\n });\n }\n\n if (mode === 'center') {\n this.$warn('The `center` mode is not yet compatible with the `contain` mode.');\n }\n }\n\n return states;\n }\n\n /**\n * Get an origin by mode.\n */\n getOriginByMode(mode?: SliderModes) {\n return this.origins[mode ?? this.$options.mode];\n }\n\n /**\n * Get a state value according to the given mode.\n */\n getStateValueByMode(state: SliderState['x'], mode?: SliderModes) {\n return state[mode ?? this.$options.mode];\n }\n\n /**\n * Mounted hook.\n */\n mounted() {\n this.states = this.getStates();\n this.setAccessibilityAttributes();\n this.goTo(this.currentIndex);\n }\n\n /**\n * Resized hook.\n */\n resized() {\n nextFrame(() => {\n this.states = this.getStates();\n nextFrame(() => {\n this.goTo(this.currentIndex);\n });\n });\n }\n\n /**\n * Set accessibility attributes for the component\n */\n setAccessibilityAttributes() {\n this.$el.setAttribute('role', 'group');\n this.$el.setAttribute('aria-roledescription', 'carousel');\n }\n\n /**\n * Go to the next slide.\n */\n goNext() {\n if (this.currentIndex + 1 > this.indexMax) {\n return;\n }\n\n this.goTo(this.currentIndex + 1);\n }\n\n /**\n * Go to the previous slide.\n */\n goPrev() {\n if (this.currentIndex - 1 < 0) {\n return;\n }\n\n this.goTo(this.currentIndex - 1);\n }\n\n /**\n * Go to the given index.\n */\n goTo(index: number) {\n if (index < 0 || index > this.indexMax) {\n throw new Error('Index out of bound.');\n }\n\n const state = this.getStateValueByMode(this.states[index].x);\n\n for (const item of this.$children.SliderItem) {\n item.move(state);\n }\n\n this.currentIndex = index;\n this.$emit('goto', index);\n }\n\n /**\n * Listen to the Draggable `start` event.\n */\n onSliderDragStart() {\n this.__initialX = this.currentSliderItem ? this.currentSliderItem.x : 0;\n this.__distanceX = this.__initialX;\n }\n\n /**\n * Listen to the Draggable `drag` event.\n */\n onSliderDragDrag({ args: [props] }: { args: [DragServiceProps] }) {\n this.__distanceX = this.__initialX + props.distance.x * this.$options.sensitivity;\n\n for (const item of this.$children.SliderItem) {\n item.moveInstantly(this.__distanceX);\n }\n }\n\n /**\n * Listen to the Draggable `drop` event and find the new active slide.\n */\n onSliderDragDrop({ args: [props] }: { args: [DragServiceProps] }) {\n let finalX = clamp(\n inertiaFinalValue(this.__distanceX, props.delta.x * this.$options.dropSensitivity),\n this.getStateValueByMode(this.firstState.x),\n this.getStateValueByMode(this.lastState.x),\n );\n\n const absoluteDifferencesBetweenDistanceAndState = this.states.map((state) =>\n Math.abs(finalX - this.getStateValueByMode(state.x)),\n );\n const minimumDifference = Math.min(...absoluteDifferencesBetweenDistanceAndState);\n const closestIndex = absoluteDifferencesBetweenDistanceAndState.indexOf(minimumDifference);\n\n if (this.$options.fitBounds) {\n this.goTo(closestIndex);\n } else {\n if (this.$options.contain) {\n finalX = Math.min(this.containMinState, finalX);\n finalX = Math.max(this.containMaxState, finalX);\n }\n for (const item of this.$children.SliderItem) {\n item.move(finalX);\n }\n this.currentIndex = closestIndex;\n }\n }\n\n /**\n * Enable focus.\n */\n onWrapperFocus() {\n this.hasFocus = true;\n }\n\n /**\n * Disable focus.\n */\n onWrapperBlur() {\n this.hasFocus = false;\n }\n\n /**\n * Go prev or next when focus is on the wrapper and pressing arrow keys.\n */\n keyed({ LEFT, RIGHT, isDown }: KeyServiceProps) {\n if (this.hasFocus && isDown) {\n if (LEFT) {\n this.goPrev();\n } else if (RIGHT) {\n this.goNext();\n }\n }\n }\n}\n"],
4
+ "sourcesContent": ["import { Base } from '@studiometa/js-toolkit';\nimport type {\n BaseProps,\n BaseConfig,\n DragServiceProps,\n KeyServiceProps,\n} from '@studiometa/js-toolkit';\nimport { clamp, inertiaFinalValue, nextFrame } from '@studiometa/js-toolkit/utils';\nimport { SliderDrag } from './SliderDrag.js';\nimport { SliderItem } from './SliderItem.js';\n\nexport type SliderModes = 'left' | 'center' | 'right';\n\ntype SliderState = { x: Record<SliderModes, number> };\n\nexport interface SliderProps extends BaseProps {\n $refs: {\n wrapper: HTMLElement;\n };\n $children: {\n SliderItem: SliderItem[];\n SliderDrag: SliderDrag[];\n };\n $options: {\n mode: SliderModes;\n fitBounds: boolean;\n contain: boolean;\n sensitivity: number;\n dropSensitivity: number;\n };\n}\n\n/**\n * Slider class.\n * @link https://ui.studiometa.dev/components/Slider/\n * @todo a11y\n */\nexport class Slider<T extends BaseProps = BaseProps> extends Base<T & SliderProps> {\n /**\n * Config.\n */\n static config: BaseConfig = {\n name: 'Slider',\n refs: ['wrapper'],\n emits: ['goto', 'index'],\n components: {\n SliderItem,\n SliderDrag,\n },\n options: {\n mode: { type: String, default: 'left' },\n fitBounds: Boolean,\n contain: Boolean,\n sensitivity: { type: Number, default: 1 },\n dropSensitivity: { type: Number, default: 2 },\n },\n };\n\n /**\n * Distance on the x axis.\n * @private\n */\n __distanceX = 0;\n\n /**\n * Initial x position.\n * @private\n */\n __initialX = 0;\n\n /**\n * Index of the current active slide.\n * @private\n */\n __currentIndex = 0;\n\n /**\n * Store all the states.\n */\n states: SliderState[] = [];\n\n /**\n * Origins for the different modes.\n */\n origins: Record<SliderModes, number> = {\n left: 0,\n center: 0,\n right: 0,\n };\n\n /**\n * Wether or not the wrapper is focused.\n */\n hasFocus = false;\n\n /**\n * Get the current index.\n */\n get currentIndex() {\n return this.__currentIndex;\n }\n\n /**\n * Set the current index and emit the `index` event.\n */\n set currentIndex(value: number) {\n this.currentSliderItem.disactivate();\n this.$emit('index', value);\n this.__currentIndex = value;\n this.currentSliderItem.activate();\n }\n\n /**\n * Get the current state.\n */\n get currentState() {\n return this.states[this.currentIndex];\n }\n\n /**\n * Get the first state.\n */\n get firstState() {\n return this.states[0];\n }\n\n /**\n * Get the last state.\n */\n get lastState() {\n return this.states.at(-1);\n }\n\n /**\n * Get the minimal contain state value.\n */\n get containMinState(): number {\n return this.getStateValueByMode(this.firstState.x, 'left');\n }\n\n /**\n * Get the maximal contain state value.\n */\n get containMaxState(): number {\n return this.getStateValueByMode(this.lastState.x, 'right');\n }\n\n /**\n * Get the last index.\n */\n get indexMax(): number {\n return this.$children.SliderItem.length - 1;\n }\n\n /**\n * Get the current SliderItem\n */\n get currentSliderItem() {\n return this.$children.SliderItem[this.currentIndex];\n }\n\n /**\n * Get the states for each SliderItem.\n */\n getStates(): SliderState[] {\n const { wrapper } = this.$refs;\n const originRect = wrapper.getBoundingClientRect();\n\n this.origins = {\n left: originRect.left,\n center: originRect.x + originRect.width / 2,\n right: originRect.x + originRect.width,\n };\n\n const states: SliderState[] = this.$children.SliderItem.map((item) => ({\n x: {\n left: (item.rect.x - this.origins.left) * -1,\n center: (item.rect.x + item.rect.width / 2 - this.origins.center) * -1,\n right: (item.rect.x + item.rect.width - this.origins.right) * -1,\n },\n }));\n\n if (this.$options.contain) {\n const { mode } = this.$options;\n // Find state where last child has passed the wrapper bound completely\n if (mode === 'left') {\n const lastChild = this.$children.SliderItem.at(-1);\n\n const maxState = states.find((state) => {\n const lastChildPosition =\n lastChild.rect.x - this.origins.left + lastChild.rect.width + state.x.left;\n const diffWithWrapperBound = originRect.width - lastChildPosition;\n if (diffWithWrapperBound > 0) {\n state.x.left = Math.min(state.x.left + diffWithWrapperBound, 0);\n return true;\n }\n\n return false;\n });\n\n if (maxState) {\n return states.map((state) => {\n state.x.left = Math.max(state.x.left, maxState.x.left);\n return state;\n });\n }\n }\n\n if (mode === 'right') {\n const maxStateIndex = states.findIndex((state) => state.x.right <= 0);\n const maxState = maxStateIndex < 0 ? states.at(-1) : states[maxStateIndex - 1];\n\n return states.map((state) => {\n state.x.right = maxStateIndex < 0 ? maxState.x.right : Math.min(state.x.right, 0);\n return state;\n });\n }\n\n if (mode === 'center') {\n this.$warn('The `center` mode is not yet compatible with the `contain` mode.');\n }\n }\n\n return states;\n }\n\n /**\n * Get an origin by mode.\n */\n getOriginByMode(mode?: SliderModes) {\n return this.origins[mode ?? this.$options.mode];\n }\n\n /**\n * Get a state value according to the given mode.\n */\n getStateValueByMode(state: SliderState['x'], mode?: SliderModes) {\n return state[mode ?? this.$options.mode];\n }\n\n /**\n * Mounted hook.\n */\n mounted() {\n this.states = this.getStates();\n this.setAccessibilityAttributes();\n this.goTo(this.currentIndex);\n }\n\n /**\n * Resized hook.\n */\n resized() {\n nextFrame(() => {\n this.states = this.getStates();\n nextFrame(() => {\n this.goTo(this.currentIndex);\n });\n });\n }\n\n /**\n * Set accessibility attributes for the component\n */\n setAccessibilityAttributes() {\n this.$el.setAttribute('role', 'group');\n this.$el.setAttribute('aria-roledescription', 'carousel');\n }\n\n /**\n * Go to the next slide.\n */\n goNext() {\n if (this.currentIndex + 1 > this.indexMax) {\n return;\n }\n\n this.goTo(this.currentIndex + 1);\n }\n\n /**\n * Go to the previous slide.\n */\n goPrev() {\n if (this.currentIndex - 1 < 0) {\n return;\n }\n\n this.goTo(this.currentIndex - 1);\n }\n\n /**\n * Go to the given index.\n */\n goTo(index: number) {\n if (index < 0 || index > this.indexMax) {\n throw new Error('Index out of bound.');\n }\n\n const state = this.getStateValueByMode(this.states[index].x);\n\n for (const item of this.$children.SliderItem) {\n item.move(state);\n }\n\n this.currentIndex = index;\n this.$emit('goto', index);\n }\n\n /**\n * Listen to the Draggable `start` event.\n */\n onSliderDragStart() {\n this.__initialX = this.currentSliderItem ? this.currentSliderItem.x : 0;\n this.__distanceX = this.__initialX;\n }\n\n /**\n * Listen to the Draggable `drag` event.\n */\n onSliderDragDrag({ args: [props] }: { args: [DragServiceProps] }) {\n this.__distanceX = this.__initialX + props.distance.x * this.$options.sensitivity;\n\n for (const item of this.$children.SliderItem) {\n item.moveInstantly(this.__distanceX);\n }\n }\n\n /**\n * Listen to the Draggable `drop` event and find the new active slide.\n */\n onSliderDragDrop({ args: [props] }: { args: [DragServiceProps] }) {\n let finalX = clamp(\n inertiaFinalValue(this.__distanceX, props.delta.x * this.$options.dropSensitivity),\n this.getStateValueByMode(this.firstState.x),\n this.getStateValueByMode(this.lastState.x),\n );\n\n const absoluteDifferencesBetweenDistanceAndState = this.states.map((state) =>\n Math.abs(finalX - this.getStateValueByMode(state.x)),\n );\n const minimumDifference = Math.min(...absoluteDifferencesBetweenDistanceAndState);\n const closestIndex = absoluteDifferencesBetweenDistanceAndState.indexOf(minimumDifference);\n\n if (this.$options.fitBounds) {\n this.goTo(closestIndex);\n } else {\n if (this.$options.contain) {\n finalX = Math.min(this.containMinState, finalX);\n finalX = Math.max(this.containMaxState, finalX);\n }\n for (const item of this.$children.SliderItem) {\n item.move(finalX);\n }\n this.currentIndex = closestIndex;\n }\n }\n\n /**\n * Enable focus.\n */\n onWrapperFocus() {\n this.hasFocus = true;\n }\n\n /**\n * Disable focus.\n */\n onWrapperBlur() {\n this.hasFocus = false;\n }\n\n /**\n * Go prev or next when focus is on the wrapper and pressing arrow keys.\n */\n keyed({ LEFT, RIGHT, isDown }: KeyServiceProps) {\n if (this.hasFocus && isDown) {\n if (LEFT) {\n this.goPrev();\n } else if (RIGHT) {\n this.goNext();\n }\n }\n }\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -16,7 +16,7 @@ export interface StickyProps extends BaseProps {
16
16
  }
17
17
  /**
18
18
  * Sticky class.
19
- * @link https://ui.studiometa.dev/-/components/Sticky/
19
+ * @link https://ui.studiometa.dev/components/Sticky/
20
20
  */
21
21
  export declare class Sticky<T extends BaseProps = BaseProps> extends Base<T & StickyProps> {
22
22
  /**
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/ui/Sticky/Sticky.ts"],
4
- "sourcesContent": ["import { Base } from '@studiometa/js-toolkit';\nimport type { BaseProps, BaseConfig } from '@studiometa/js-toolkit';\nimport { Sentinel } from '../Sentinel/index.js';\n\nexport interface StickyProps extends BaseProps {\n $refs: {\n inner: HTMLElement;\n };\n $options: {\n zIndex: number;\n hideWhenUp: boolean;\n hideWhenDown: boolean;\n };\n $children: {\n Sentinel: Sentinel[];\n };\n}\n\n/**\n * Sticky class.\n * @link https://ui.studiometa.dev/-/components/Sticky/\n */\nexport class Sticky<T extends BaseProps = BaseProps> extends Base<T & StickyProps> {\n /**\n * Config.\n */\n static config: BaseConfig = {\n name: 'Sticky',\n refs: ['inner'],\n components: {\n Sentinel,\n },\n options: {\n zIndex: {\n type: Number,\n default: 100,\n },\n hideWhenUp: Boolean,\n hideWhenDown: Boolean,\n },\n };\n\n /**\n * Holder for all instances.\n */\n // eslint-disable-next-line no-use-before-define\n static instances: Set<Sticky> = new Set();\n\n /**\n * Is the component sticky?\n */\n isSticky = false;\n\n /**\n * Is the component visible?\n */\n isVisible = true;\n\n /**\n * Set the Y value.\n */\n set y(value: number) {\n this.$refs.inner.style.transform = `translateY(${value}px) translateZ(0px)`;\n }\n\n /**\n * Get instances as array.\n */\n get instances(): Sticky[] {\n return Array.from(Sticky.instances);\n }\n\n /**\n * Get the sentinel instance.\n */\n get sentinel(): Sentinel {\n return this.$children.Sentinel[0];\n }\n\n /**\n * Mounted hook.\n */\n mounted() {\n Sticky.instances.add(this);\n this.setSentinelSize();\n }\n\n /**\n * Resized hook.\n */\n resized() {\n this.setSentinelSize();\n }\n\n /**\n * Destroyed hook.\n */\n destroyed() {\n Sticky.instances.delete(this);\n }\n\n /**\n * Scrolled hook.\n */\n scrolled(props) {\n if (!this.isSticky || props.y === props.last.y) {\n return;\n }\n\n if (\n (props.direction.y === 'DOWN' && this.$options.hideWhenDown) ||\n (props.direction.y === 'UP' && this.$options.hideWhenUp)\n ) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n /**\n * Listen to the sentinel's `intersected` event to set the `isSticky` value.\n * @param {IntersectionObserverEntry[]} entries\n * @returns {void}\n */\n onSentinelIntersected({ args: [[entry]] }: { args: [IntersectionObserverEntry[]] }) {\n this.isSticky = entry.isIntersecting && entry.boundingClientRect.y < 0;\n this.setPosition();\n }\n\n /**\n * Hide the sticky component when another one is sticky.\n */\n hide() {\n if (!this.isVisible) {\n return;\n }\n\n this.isVisible = false;\n this.$el.classList.add('pointer-events-none');\n\n this.instances.forEach((instance, index) => instance.setPosition(index));\n }\n\n /**\n * Show the sticky component when the other one is not sticky anymore.\n */\n show() {\n if (this.isVisible) {\n return;\n }\n\n this.isVisible = true;\n this.$el.classList.remove('pointer-events-none');\n this.instances.forEach((instance, index) => instance.setPosition(index));\n }\n\n /**\n * Set the sentinel height based on the previous instances.\n */\n setSentinelSize() {\n const { instances } = this;\n const index = instances.indexOf(this);\n const height = instances\n .slice(0, index)\n .filter(\n // Test each instance sticky context against the current element\n (instance) => this.closestRelativeElement(instance.$el).contains(this.$el),\n )\n .reduce((acc, instance) => acc + instance.$el.offsetHeight, 0);\n\n this.sentinel.$el.style.height = `${height + 1}px`;\n this.$el.style.top = `${height}px`;\n this.$el.style.zIndex = String(this.$options.zIndex - index);\n }\n\n /**\n * Set the component's position.\n * @param {number} [index] The instance index in all the pages' instances.\n * @returns {void}\n */\n setPosition(index?: number) {\n if (!this.isSticky) {\n this.y = 0;\n return;\n }\n\n const { instances } = this;\n\n // eslint-disable-next-line no-param-reassign\n index = index ?? instances.indexOf(this);\n\n this.y = instances\n .slice(0, index)\n .filter((instance) => instance.isSticky && !instance.isVisible)\n .reduce<number>(\n (y: number, instance) => y - instance.$refs.inner.offsetHeight,\n this.isVisible ? 0 : this.$refs.inner.offsetHeight * -1,\n ) as number;\n }\n\n /**\n * Find the first parent which has a relative position.\n */\n closestRelativeElement(element: HTMLElement) {\n let parent = element.parentElement;\n\n while (getComputedStyle(parent).position !== 'relative' && parent.parentElement) {\n parent = parent.parentElement;\n }\n\n return parent;\n }\n}\n"],
4
+ "sourcesContent": ["import { Base } from '@studiometa/js-toolkit';\nimport type { BaseProps, BaseConfig } from '@studiometa/js-toolkit';\nimport { Sentinel } from '../Sentinel/index.js';\n\nexport interface StickyProps extends BaseProps {\n $refs: {\n inner: HTMLElement;\n };\n $options: {\n zIndex: number;\n hideWhenUp: boolean;\n hideWhenDown: boolean;\n };\n $children: {\n Sentinel: Sentinel[];\n };\n}\n\n/**\n * Sticky class.\n * @link https://ui.studiometa.dev/components/Sticky/\n */\nexport class Sticky<T extends BaseProps = BaseProps> extends Base<T & StickyProps> {\n /**\n * Config.\n */\n static config: BaseConfig = {\n name: 'Sticky',\n refs: ['inner'],\n components: {\n Sentinel,\n },\n options: {\n zIndex: {\n type: Number,\n default: 100,\n },\n hideWhenUp: Boolean,\n hideWhenDown: Boolean,\n },\n };\n\n /**\n * Holder for all instances.\n */\n // eslint-disable-next-line no-use-before-define\n static instances: Set<Sticky> = new Set();\n\n /**\n * Is the component sticky?\n */\n isSticky = false;\n\n /**\n * Is the component visible?\n */\n isVisible = true;\n\n /**\n * Set the Y value.\n */\n set y(value: number) {\n this.$refs.inner.style.transform = `translateY(${value}px) translateZ(0px)`;\n }\n\n /**\n * Get instances as array.\n */\n get instances(): Sticky[] {\n return Array.from(Sticky.instances);\n }\n\n /**\n * Get the sentinel instance.\n */\n get sentinel(): Sentinel {\n return this.$children.Sentinel[0];\n }\n\n /**\n * Mounted hook.\n */\n mounted() {\n Sticky.instances.add(this);\n this.setSentinelSize();\n }\n\n /**\n * Resized hook.\n */\n resized() {\n this.setSentinelSize();\n }\n\n /**\n * Destroyed hook.\n */\n destroyed() {\n Sticky.instances.delete(this);\n }\n\n /**\n * Scrolled hook.\n */\n scrolled(props) {\n if (!this.isSticky || props.y === props.last.y) {\n return;\n }\n\n if (\n (props.direction.y === 'DOWN' && this.$options.hideWhenDown) ||\n (props.direction.y === 'UP' && this.$options.hideWhenUp)\n ) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n /**\n * Listen to the sentinel's `intersected` event to set the `isSticky` value.\n * @param {IntersectionObserverEntry[]} entries\n * @returns {void}\n */\n onSentinelIntersected({ args: [[entry]] }: { args: [IntersectionObserverEntry[]] }) {\n this.isSticky = entry.isIntersecting && entry.boundingClientRect.y < 0;\n this.setPosition();\n }\n\n /**\n * Hide the sticky component when another one is sticky.\n */\n hide() {\n if (!this.isVisible) {\n return;\n }\n\n this.isVisible = false;\n this.$el.classList.add('pointer-events-none');\n\n this.instances.forEach((instance, index) => instance.setPosition(index));\n }\n\n /**\n * Show the sticky component when the other one is not sticky anymore.\n */\n show() {\n if (this.isVisible) {\n return;\n }\n\n this.isVisible = true;\n this.$el.classList.remove('pointer-events-none');\n this.instances.forEach((instance, index) => instance.setPosition(index));\n }\n\n /**\n * Set the sentinel height based on the previous instances.\n */\n setSentinelSize() {\n const { instances } = this;\n const index = instances.indexOf(this);\n const height = instances\n .slice(0, index)\n .filter(\n // Test each instance sticky context against the current element\n (instance) => this.closestRelativeElement(instance.$el).contains(this.$el),\n )\n .reduce((acc, instance) => acc + instance.$el.offsetHeight, 0);\n\n this.sentinel.$el.style.height = `${height + 1}px`;\n this.$el.style.top = `${height}px`;\n this.$el.style.zIndex = String(this.$options.zIndex - index);\n }\n\n /**\n * Set the component's position.\n * @param {number} [index] The instance index in all the pages' instances.\n * @returns {void}\n */\n setPosition(index?: number) {\n if (!this.isSticky) {\n this.y = 0;\n return;\n }\n\n const { instances } = this;\n\n // eslint-disable-next-line no-param-reassign\n index = index ?? instances.indexOf(this);\n\n this.y = instances\n .slice(0, index)\n .filter((instance) => instance.isSticky && !instance.isVisible)\n .reduce<number>(\n (y: number, instance) => y - instance.$refs.inner.offsetHeight,\n this.isVisible ? 0 : this.$refs.inner.offsetHeight * -1,\n ) as number;\n }\n\n /**\n * Find the first parent which has a relative position.\n */\n closestRelativeElement(element: HTMLElement) {\n let parent = element.parentElement;\n\n while (getComputedStyle(parent).position !== 'relative' && parent.parentElement) {\n parent = parent.parentElement;\n }\n\n return parent;\n }\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
package/Tabs/Tabs.d.ts CHANGED
@@ -18,7 +18,7 @@ export interface TabsProps extends BaseProps {
18
18
  }
19
19
  /**
20
20
  * Tabs class.
21
- * @link https://ui.studiometa.dev/-/components/Tabs/
21
+ * @link https://ui.studiometa.dev/components/Tabs/
22
22
  */
23
23
  export declare class Tabs<T extends BaseProps = BaseProps> extends Base<T & TabsProps> {
24
24
  /**