@cocreate/scroll 1.13.4 → 1.15.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.
@@ -1,8 +1,10 @@
1
1
  name: Automated Workflow
2
+
2
3
  on:
3
4
  push:
4
5
  branches:
5
6
  - master
7
+
6
8
  jobs:
7
9
  about:
8
10
  runs-on: ubuntu-latest
@@ -18,27 +20,37 @@ jobs:
18
20
  with:
19
21
  direction: overwrite-github
20
22
  githubToken: "${{ secrets.GITHUB }}"
23
+
21
24
  release:
22
25
  runs-on: ubuntu-latest
23
26
  steps:
24
27
  - name: Checkout
25
- uses: actions/checkout@v3
26
- - name: Setup Node.js
27
- uses: actions/setup-node@v3
28
+ uses: actions/checkout@v4
28
29
  with:
29
- node-version: 14
30
- - name: Semantic Release
31
- uses: cycjimmy/semantic-release-action@v3
32
- id: semantic
30
+ fetch-depth: 0 # Required so semantic-release can trace git tags/history
31
+
32
+ - name: Setup Node.js
33
+ uses: actions/setup-node@v4
33
34
  with:
34
- extra_plugins: |
35
- @semantic-release/changelog
35
+ node-version: 22
36
+
37
+ - name: Install Semantic Release & Plugins
38
+ # Installs semantic-release and its plugins on the runner
39
+ run: |
40
+ npm install -g semantic-release \
41
+ @semantic-release/changelog \
42
+ @semantic-release/npm \
43
+ @semantic-release/github \
36
44
  @semantic-release/git
37
- @semantic-release/github
45
+
46
+ - name: Run Semantic Release (Native)
47
+ id: semantic
48
+ # This will automatically pick up your export default config file in the repository root
49
+ run: npx semantic-release
38
50
  env:
39
- GITHUB_TOKEN: "${{ secrets.GITHUB }}"
51
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
40
52
  NPM_TOKEN: "${{ secrets.NPM_TOKEN }}"
53
+
41
54
  outputs:
42
55
  new_release_published: "${{ steps.semantic.outputs.new_release_published }}"
43
- new_release_version: "${{ steps.semantic.outputs.new_release_version }}"
44
-
56
+ new_release_version: "${{ steps.semantic.outputs.new_release_version }}"
@@ -14,8 +14,7 @@ jobs:
14
14
  env:
15
15
  DRY_RUN: ${{ github.event.inputs.dry_run }}
16
16
  GITHUB_TOKEN: "${{ secrets.GITHUB }}"
17
- NPM_TOKEN: "${{ secrets.NPM_TOKEN }}"
18
-
17
+
19
18
  steps:
20
19
  - name: Checkout
21
20
  uses: actions/checkout@v3
package/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ # [1.15.0](https://github.com/CoCreate-app/CoCreate-scroll/compare/v1.14.1...v1.15.0) (2026-07-17)
2
+
3
+
4
+ ### Features
5
+
6
+ * update automated workflow and release configuration for improved semantic release handling ([ff16e37](https://github.com/CoCreate-app/CoCreate-scroll/commit/ff16e376a501b1b0f5dec6333d6d95dc9ade27f0))
7
+
8
+ ## [1.14.1](https://github.com/CoCreate-app/CoCreate-scroll/compare/v1.14.0...v1.14.1) (2026-07-11)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * bump package versions ([f4a4064](https://github.com/CoCreate-app/CoCreate-scroll/commit/f4a4064a6e6ebb72d92c9a425bba441cd1512252))
14
+ * removed post install and add add packages to apprved list ([d5ae12b](https://github.com/CoCreate-app/CoCreate-scroll/commit/d5ae12b24791656b8be230a90d7eb62f63d5fccd))
15
+ * semantic version handling ([87ae4c2](https://github.com/CoCreate-app/CoCreate-scroll/commit/87ae4c2fcb547ad8b459dbd4d8c85e809f2e2bce))
16
+
17
+ # [1.14.0](https://github.com/CoCreate-app/CoCreate-scroll/compare/v1.13.4...v1.14.0) (2026-01-15)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * update worklow ([ac9e74a](https://github.com/CoCreate-app/CoCreate-scroll/commit/ac9e74a15fd8c7d27dc5809130ea0ee99c46777f))
23
+
24
+
25
+ ### Features
26
+
27
+ * comprehensive initalization of ([cecbfce](https://github.com/CoCreate-app/CoCreate-scroll/commit/cecbfcec1d9d7f34b9d4a339d5e5ed3e8f38c363))
28
+
1
29
  ## [1.13.4](https://github.com/CoCreate-app/CoCreate-scroll/compare/v1.13.3...v1.13.4) (2025-09-07)
2
30
 
3
31
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/scroll",
3
- "version": "1.13.4",
3
+ "version": "1.15.0",
4
4
  "description": "A simple scroll component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "scroll",
@@ -18,8 +18,7 @@
18
18
  "scripts": {
19
19
  "start": "npx webpack --config webpack.config.js",
20
20
  "build": "npx webpack --mode=production --config webpack.config.js",
21
- "dev": "npx webpack --config webpack.config.js --watch",
22
- "postinstall": "node -e \"const { execSync } = require('child_process'); try { execSync('coc --version', { stdio: 'ignore' }); } catch (error) { try { execSync('npm install -g @cocreate/cli', { stdio: 'inherit' }); console.log('Installed \"@cocreate/cli\" globally.'); } catch (error) { console.error('Failed to install \"@cocreate/cli\" globally:', error); } }\""
21
+ "dev": "npx webpack --config webpack.config.js --watch"
23
22
  },
24
23
  "repository": {
25
24
  "type": "git",
@@ -36,17 +35,18 @@
36
35
  "url": "https://github.com/sponsors/CoCreate-app"
37
36
  },
38
37
  "main": "./src/index.js",
38
+ "dependencies": {
39
+ "@cocreate/actions": "^1.21.4",
40
+ "@cocreate/observer": "^1.19.0"
41
+ },
39
42
  "devDependencies": {
40
- "css-loader": "^5.1.3",
41
- "esbuild": "^0.25.2",
42
- "esbuild-loader": "^4.3.0",
43
- "mini-css-extract-plugin": "^1.5.0",
44
- "webpack": "^5.24.4",
45
- "webpack-cli": "^4.5.0",
46
- "webpack-log": "^3.0.1"
43
+ "@cocreate/webpack": "^1.4.3"
47
44
  },
48
- "dependencies": {
49
- "@cocreate/observer": "^1.18.1",
50
- "@cocreate/actions": "^1.21.1"
45
+ "allowScripts": {
46
+ "@cocreate/actions@1.21.4": true,
47
+ "@cocreate/observer@1.19.0": true,
48
+ "@cocreate/utils@1.42.2": true,
49
+ "@cocreate/uuid@1.12.4": true,
50
+ "@cocreate/webpack@1.4.3": true
51
51
  }
52
52
  }
package/release.config.js CHANGED
@@ -10,12 +10,20 @@ module.exports = {
10
10
  changelogFile: "CHANGELOG.md",
11
11
  },
12
12
  ],
13
- "@semantic-release/npm",
14
- "@semantic-release/github",
13
+ "@semantic-release/npm",
15
14
  [
16
- "@semantic-release/git",
15
+ "@semantic-release/github",
17
16
  {
17
+ successComment: false,
18
+ failTitle: false,
19
+ },
20
+ ],
21
+ [
22
+ "@semantic-release/git",
23
+ {
24
+ // Only stage and commit the changelog and package.json
18
25
  assets: ["CHANGELOG.md", "package.json"],
26
+ message: "chore(release): ${nextRelease.version} [skip ci]",
19
27
  },
20
28
  ],
21
29
  ],
package/src/index.js CHANGED
@@ -1,348 +1,374 @@
1
1
  import Observer from "@cocreate/observer";
2
2
  import Actions from "@cocreate/actions";
3
3
 
4
+ const selector =
5
+ "[scroll], [scroll-to], [scrollable-x], [scrollable-y], [scroll-up], [scroll-down], [scroll-top], [scroll-bottom], [scroll-limbo], [scroll-intersect], [scrolling]";
6
+
4
7
  const CoCreateScroll = {
5
- delta: 3,
6
- observer: null,
7
- timer: null,
8
- firedEvents: new Map(),
9
-
10
- init: function () {
11
- let elements = document.querySelectorAll(
12
- `[scroll], [scroll-to], [scrollable-x], [scrollable-y]`
13
- );
14
- this.__initIntersectionObserver();
15
- this.initElements(elements);
16
- },
17
-
18
- initElements: function (elements) {
19
- for (let el of elements) this.initElement(el);
20
- },
21
-
22
- initElement: function (element) {
23
- const self = this;
24
- const upSize = this.__getSize(element.getAttribute("scroll-up"));
25
- const downSize = this.__getSize(element.getAttribute("scroll-down"));
26
- const attrName = element.getAttribute("scroll-attribute") || "class";
27
- const targetSelector = element.getAttribute("scroll-query");
28
- const scrollSelector = element.getAttribute("scroll-element");
29
- const intersectValue = element.getAttribute("scroll-intersect");
30
- const scrollTo = element.getAttribute("scroll-to");
31
-
32
- updateScrollableAttributes(element);
33
-
34
- let values =
35
- element.getAttribute("scroll") ||
36
- element.getAttribute("scroll-value");
37
- if (values || values === "")
38
- values = values.split(",").map((x) => x.trim());
39
-
40
- let scrollInfo = {
41
- attrName: attrName,
42
- values: values,
43
- upSize: upSize,
44
- downSize: downSize,
45
- scrollTop: element.getAttribute("scroll-top"),
46
- scrollLimbo: element.getAttribute("scroll-limbo"),
47
- scrollBottom: element.getAttribute("scroll-bottom"),
48
- scrolling: element.getAttribute("scrolling"),
49
- scrollTo
50
- };
51
-
52
- let elements = [element];
53
- if (targetSelector) {
54
- elements = document.querySelectorAll(targetSelector);
55
- }
56
-
57
- elements.forEach((el) => {
58
- el.scrollStatus = { currentPos: 0 };
59
- });
60
-
61
- // this.__runScrollEvent(element, scrollInfo);
62
-
63
- let scrollableElements;
64
- if (scrollSelector)
65
- scrollableElements = document.querySelectorAll(scrollSelector);
66
- else if (element.hasAttribute("scroll-element"))
67
- scrollableElements = [element];
68
-
69
- if (scrollableElements) {
70
- for (let scrollableEl of scrollableElements) {
71
- scrollableEl.addEventListener("scroll", function (event) {
72
- self._scrollEvent(
73
- elements,
74
- element,
75
- scrollInfo,
76
- scrollableEl
77
- );
78
- });
79
- }
80
- } else {
81
- // this.WindowInit = true;
82
- window.addEventListener("scroll", function (event) {
83
- self._scrollEvent(elements, element, scrollInfo);
84
- });
85
- }
86
-
87
- if (intersectValue && window.IntersectionObserver && this.observer) {
88
- this.observer.observe(element);
89
- }
90
-
91
- if (scrollTo) {
92
- this.setScrollPosition(element, scrollTo);
93
- }
94
- },
95
-
96
- _scrollEvent: function (elements, element, scrollInfo, scrollableEl) {
97
- const self = this;
98
- if (!element.scrollStatus) return;
99
- let scrollEl = scrollableEl || window;
100
- if (
101
- Math.abs(
102
- scrollEl.scrollTop ||
103
- scrollEl.scrollY - element.scrollStatus.currentPos
104
- ) <= self.delta
105
- ) {
106
- return;
107
- }
108
-
109
- let timer = null;
110
- if (timer != null) {
111
- clearTimeout(timer);
112
- }
113
-
114
- elements.forEach((el) => {
115
- self.__setScrolling(el, scrollInfo, false);
116
- self.__runScrollEvent(el, scrollInfo, scrollableEl);
117
- });
118
-
119
- timer = setTimeout(function () {
120
- elements.forEach((el) => {
121
- self.__setScrolling(el, scrollInfo, true);
122
- });
123
- }, 500);
124
- },
125
-
126
- setScrollPosition: function (element, scrollTo) {
127
- if (!scrollTo) return;
128
- if (scrollTo.includes("top")) {
129
- element.scrollTop = 0;
130
- } else if (scrollTo.includes("bottom")) {
131
- element.scrollTop = element.scrollHeight;
132
- }
133
-
134
- if (scrollTo.includes("left")) {
135
- element.scrollLeft = 0;
136
- } else if (scrollTo.includes("right")) {
137
- element.scrollLeft = element.scrollWidth;
138
- }
139
- },
140
-
141
- __initIntersectionObserver: function () {
142
- const self = this;
143
- this.observer = new IntersectionObserver((entries) => {
144
- entries.forEach((entry) => {
145
- let element = entry.target;
146
- const attrName =
147
- element.getAttribute("scroll-attribute") || "class";
148
- const targetSelector = element.getAttribute("scroll-query");
149
- const intersectValue = element.getAttribute("scroll-intersect");
150
-
151
- let targetElements = [element];
152
- if (targetSelector) {
153
- targetElements = document.querySelectorAll(targetSelector);
154
- }
155
- if (entry.isIntersecting > 0) {
156
- targetElements.forEach((el) =>
157
- self.__addAttributeValue(el, attrName, intersectValue)
158
- );
159
- } else {
160
- targetElements.forEach((el) =>
161
- self.__removeAttrbuteValue(el, attrName, intersectValue)
162
- );
163
- }
164
- });
165
- });
166
- },
167
-
168
- __setScrolling: function (element, info, stopped = false) {
169
- const { scrolling, attrName } = info;
170
- if (stopped) {
171
- this.__removeAttrbuteValue(element, attrName, scrolling);
172
- } else {
173
- this.__addAttributeValue(element, attrName, scrolling);
174
- }
175
- },
176
-
177
- __runScrollEvent: function (element, info, scrollableEl) {
178
- if (!element.scrollStatus) return;
179
- const currentPos = element.scrollStatus.currentPos;
180
- let scrollY, scrollHeight, innerHeight;
181
- if (scrollableEl) {
182
- scrollY = scrollableEl.scrollTop;
183
- scrollHeight = scrollableEl.scrollHeight;
184
- innerHeight = scrollableEl.clientHeight;
185
- } else {
186
- scrollY = window.scrollY;
187
- scrollHeight = document.body.scrollHeight;
188
- innerHeight = window.innerHeight;
189
- }
190
- const {
191
- upSize,
192
- downSize,
193
- attrName,
194
- values,
195
- scrollTop,
196
- scrollBottom,
197
- scrollLimbo
198
- } = info;
199
-
200
- let newTime = new Date().getTime();
201
- if ((values && !info.datetime) || newTime - info.datetime > 200) {
202
- info["datetime"] = newTime;
203
-
204
- if (upSize <= currentPos - scrollY) {
205
- this.__addAttributeValue(element, attrName, values[0]);
206
- this.__removeAttrbuteValue(element, attrName, values[1]);
207
- } else if (downSize <= scrollY - currentPos) {
208
- this.__removeAttrbuteValue(element, attrName, values[0]);
209
- this.__addAttributeValue(element, attrName, values[1]);
210
- }
211
- }
212
-
213
- //. scroll top case
214
- if (scrollY <= this.delta) {
215
- if (values) {
216
- this.__removeAttrbuteValue(element, attrName, values[0]);
217
- this.__removeAttrbuteValue(element, attrName, values[1]);
218
- }
219
- this.__addAttributeValue(element, attrName, scrollTop);
220
- } else {
221
- this.__removeAttrbuteValue(element, attrName, scrollTop);
222
- }
223
-
224
- //. scroll bottom case
225
- // if ((window.innerHeight + scrollY) >= document.body.scrollHeight) {
226
- if (innerHeight + scrollY >= scrollHeight) {
227
- // this.__removeAttrbuteValue(element, attrName, values[0]);
228
- // this.__removeAttrbuteValue(element, attrName, values[1]);
229
-
230
- this.__addAttributeValue(element, attrName, scrollBottom);
231
- } else {
232
- this.__removeAttrbuteValue(element, attrName, scrollBottom);
233
- }
234
-
235
- // if (scrollY != 0 && (scrollY + window.innerHeight) != document.body.scrollHeight){
236
- if (scrollY != 0 && scrollY + innerHeight != scrollHeight) {
237
- this.__addAttributeValue(element, attrName, scrollLimbo);
238
- } else {
239
- this.__removeAttrbuteValue(element, attrName, scrollLimbo);
240
- }
241
-
242
- element.scrollStatus.currentPos = scrollY;
243
- },
244
-
245
- __addAttributeValue: function (element, attrName, value) {
246
- if (!value) return;
247
- let check = new RegExp("(\\s|^)" + value + "(\\s|$)");
248
- let attrValue = element.getAttribute(attrName) || "";
249
-
250
- if (!check.test(attrValue)) {
251
- if (attrName === "class") attrValue += " " + value;
252
- else attrValue = value;
253
- element.setAttribute(attrName, attrValue);
254
- }
255
- },
256
-
257
- __removeAttrbuteValue: function (element, attrName, value) {
258
- if (!value) return;
259
- let check = new RegExp("(\\s|^)" + value + "(\\s|$)");
260
- let attrValue = element.getAttribute(attrName) || "";
261
-
262
- if (check.test(attrValue)) {
263
- attrValue = attrValue.replace(check, " ").trim();
264
- element.setAttribute(attrName, attrValue);
265
- }
266
- },
267
-
268
- __getSize: function (attrValue, isWidth) {
269
- let size = 0;
270
- if (!attrValue) {
271
- return 0;
272
- }
273
-
274
- if (attrValue.includes("%")) {
275
- size = attrValue.replace("%", "").trim();
276
- size = Number(size) || 0;
277
-
278
- size = isWidth
279
- ? window.innerWidth / size
280
- : window.innerHeight / size;
281
- } else {
282
- size = attrValue.replace("px", "").trim();
283
- size = Number(size) || 0;
284
- }
285
-
286
- return size;
287
- }
8
+ delta: 3,
9
+ observer: null,
10
+ // timer: null, // Removed: Timer needs to be instance-specific, not global
11
+ firedEvents: new Map(),
12
+
13
+ init: function () {
14
+ let elements = document.querySelectorAll(selector);
15
+ this.__initIntersectionObserver();
16
+ this.initElements(elements);
17
+ },
18
+
19
+ initElements: function (elements) {
20
+ for (let el of elements) this.initElement(el);
21
+ },
22
+
23
+ initElement: function (element) {
24
+ const self = this;
25
+ const upSize = this.__getSize(element.getAttribute("scroll-up"));
26
+ const downSize = this.__getSize(element.getAttribute("scroll-down"));
27
+ const attrName = element.getAttribute("scroll-attribute") || "class";
28
+ const targetSelector = element.getAttribute("scroll-query");
29
+ const scrollSelector = element.getAttribute("scroll-element");
30
+ const intersectValue = element.getAttribute("scroll-intersect");
31
+ const scrollTo = element.getAttribute("scroll-to");
32
+
33
+ updateScrollableAttributes(element);
34
+
35
+ let values =
36
+ element.getAttribute("scroll") ||
37
+ element.getAttribute("scroll-value");
38
+ if (values || values === "")
39
+ values = values.split(",").map((x) => x.trim());
40
+
41
+ let scrollInfo = {
42
+ attrName: attrName,
43
+ values: values,
44
+ upSize: upSize,
45
+ downSize: downSize,
46
+ scrollTop: element.getAttribute("scroll-top"),
47
+ scrollLimbo: element.getAttribute("scroll-limbo"),
48
+ scrollBottom: element.getAttribute("scroll-bottom"),
49
+ scrolling: element.getAttribute("scrolling"),
50
+ scrollTo,
51
+ timer: null // Added: Store timer here to persist across events
52
+ };
53
+
54
+ let elements = [element];
55
+ if (targetSelector) {
56
+ elements = document.querySelectorAll(targetSelector);
57
+ }
58
+
59
+ elements.forEach((el) => {
60
+ el.scrollStatus = { currentPos: 0 };
61
+ });
62
+
63
+ // this.__runScrollEvent(element, scrollInfo);
64
+
65
+ let scrollableElements;
66
+ if (scrollSelector)
67
+ scrollableElements = document.querySelectorAll(scrollSelector);
68
+ else if (element.hasAttribute("scroll-element"))
69
+ scrollableElements = [element];
70
+
71
+ if (scrollableElements) {
72
+ for (let scrollableEl of scrollableElements) {
73
+ scrollableEl.addEventListener("scroll", function (event) {
74
+ self._scrollEvent(
75
+ elements,
76
+ element,
77
+ scrollInfo,
78
+ scrollableEl
79
+ );
80
+ });
81
+ }
82
+ } else {
83
+ // this.WindowInit = true;
84
+ window.addEventListener("scroll", function (event) {
85
+ self._scrollEvent(elements, element, scrollInfo);
86
+ });
87
+ }
88
+
89
+ if (intersectValue && window.IntersectionObserver && this.observer) {
90
+ this.observer.observe(element);
91
+ }
92
+
93
+ if (scrollTo) {
94
+ this.setScrollPosition(element, scrollTo);
95
+ }
96
+ },
97
+
98
+ _scrollEvent: function (elements, element, scrollInfo, scrollableEl) {
99
+ const self = this;
100
+ if (!element.scrollStatus) return;
101
+ let scrollEl = scrollableEl || window;
102
+ if (
103
+ Math.abs(
104
+ scrollEl.scrollTop ||
105
+ scrollEl.scrollY - element.scrollStatus.currentPos
106
+ ) <= self.delta
107
+ ) {
108
+ return;
109
+ }
110
+
111
+ // Fix: Use the timer stored in scrollInfo so it persists
112
+ if (scrollInfo.timer != null) {
113
+ clearTimeout(scrollInfo.timer);
114
+ }
115
+
116
+ elements.forEach((el) => {
117
+ self.__setScrolling(el, scrollInfo, false);
118
+ self.__runScrollEvent(el, scrollInfo, scrollableEl);
119
+ });
120
+
121
+ scrollInfo.timer = setTimeout(function () {
122
+ elements.forEach((el) => {
123
+ self.__setScrolling(el, scrollInfo, true);
124
+ });
125
+ }, 500);
126
+ },
127
+
128
+ setScrollPosition: function (element, scrollTo) {
129
+ if (!scrollTo) return;
130
+ if (scrollTo.includes("top")) {
131
+ element.scrollTop = 0;
132
+ } else if (scrollTo.includes("bottom")) {
133
+ element.scrollTop = element.scrollHeight;
134
+ }
135
+
136
+ if (scrollTo.includes("left")) {
137
+ element.scrollLeft = 0;
138
+ } else if (scrollTo.includes("right")) {
139
+ element.scrollLeft = element.scrollWidth;
140
+ }
141
+ },
142
+
143
+ __initIntersectionObserver: function () {
144
+ const self = this;
145
+ this.observer = new IntersectionObserver((entries) => {
146
+ // Deduplicate: Keep only the latest entry for each target element
147
+ const uniqueEntries = new Map();
148
+ entries.forEach((entry) => {
149
+ uniqueEntries.set(entry.target, entry);
150
+ });
151
+
152
+ // Process only the unique, latest entries
153
+ uniqueEntries.forEach((entry) => {
154
+ let element = entry.target;
155
+ const attrName =
156
+ element.getAttribute("scroll-attribute") || "class";
157
+ const targetSelector = element.getAttribute("scroll-query");
158
+ const intersectValue = element.getAttribute("scroll-intersect");
159
+
160
+ let targetElements = [element];
161
+ if (targetSelector) {
162
+ targetElements = document.querySelectorAll(targetSelector);
163
+ }
164
+
165
+ if (entry.isIntersecting) {
166
+ targetElements.forEach((el) =>
167
+ self.__addAttributeValue(el, attrName, intersectValue)
168
+ );
169
+ } else {
170
+ targetElements.forEach((el) =>
171
+ self.__removeAttributeValue(el, attrName, intersectValue)
172
+ );
173
+ }
174
+ });
175
+ });
176
+ },
177
+
178
+ __setScrolling: function (element, info, stopped = false) {
179
+ const { scrolling, attrName } = info;
180
+ if (stopped) {
181
+ this.__removeAttributeValue(element, attrName, scrolling);
182
+ } else {
183
+ this.__addAttributeValue(element, attrName, scrolling);
184
+ }
185
+ },
186
+
187
+ __runScrollEvent: function (element, info, scrollableEl) {
188
+ if (!element.scrollStatus) return;
189
+ const currentPos = element.scrollStatus.currentPos;
190
+ let scrollY, scrollHeight, innerHeight;
191
+ if (scrollableEl) {
192
+ scrollY = scrollableEl.scrollTop;
193
+ scrollHeight = scrollableEl.scrollHeight;
194
+ innerHeight = scrollableEl.clientHeight;
195
+ } else {
196
+ scrollY = window.scrollY;
197
+ scrollHeight = document.body.scrollHeight;
198
+ innerHeight = window.innerHeight;
199
+ }
200
+ const {
201
+ upSize,
202
+ downSize,
203
+ attrName,
204
+ values,
205
+ scrollTop,
206
+ scrollBottom,
207
+ scrollLimbo
208
+ } = info;
209
+
210
+ let newTime = new Date().getTime();
211
+ if ((values && !info.datetime) || newTime - info.datetime > 200) {
212
+ info["datetime"] = newTime;
213
+
214
+ if (upSize <= currentPos - scrollY) {
215
+ this.__addAttributeValue(element, attrName, values[0]);
216
+ this.__removeAttributeValue(element, attrName, values[1]);
217
+ } else if (downSize <= scrollY - currentPos) {
218
+ this.__removeAttributeValue(element, attrName, values[0]);
219
+ this.__addAttributeValue(element, attrName, values[1]);
220
+ }
221
+ }
222
+
223
+ //. scroll top case
224
+ if (scrollY <= this.delta) {
225
+ if (values) {
226
+ this.__removeAttributeValue(element, attrName, values[0]);
227
+ this.__removeAttributeValue(element, attrName, values[1]);
228
+ }
229
+ this.__addAttributeValue(element, attrName, scrollTop);
230
+ } else {
231
+ this.__removeAttributeValue(element, attrName, scrollTop);
232
+ }
233
+
234
+ //. scroll bottom case
235
+ // if ((window.innerHeight + scrollY) >= document.body.scrollHeight) {
236
+ if (innerHeight + scrollY >= scrollHeight) {
237
+ // this.__removeAttributeValue(element, attrName, values[0]);
238
+ // this.__removeAttributeValue(element, attrName, values[1]);
239
+
240
+ this.__addAttributeValue(element, attrName, scrollBottom);
241
+ } else {
242
+ this.__removeAttributeValue(element, attrName, scrollBottom);
243
+ }
244
+
245
+ // if (scrollY != 0 && (scrollY + window.innerHeight) != document.body.scrollHeight){
246
+ if (scrollY != 0 && scrollY + innerHeight != scrollHeight) {
247
+ this.__addAttributeValue(element, attrName, scrollLimbo);
248
+ } else {
249
+ this.__removeAttributeValue(element, attrName, scrollLimbo);
250
+ }
251
+
252
+ element.scrollStatus.currentPos = scrollY;
253
+ },
254
+
255
+ __addAttributeValue: function (element, attrName, value) {
256
+ if (!value) return;
257
+ // Optimization: Use classList if the attribute is 'class'
258
+ if (attrName === "class") {
259
+ element.classList.add(value);
260
+ return;
261
+ }
262
+
263
+ let check = new RegExp("(\\s|^)" + value + "(\\s|$)");
264
+ let attrValue = element.getAttribute(attrName) || "";
265
+
266
+ if (!check.test(attrValue)) {
267
+ // Logic note: For non-class attributes, we append with a space
268
+ // This mimics class-like behavior for custom attributes
269
+ if (attrValue.length > 0) attrValue += " " + value;
270
+ else attrValue = value;
271
+ element.setAttribute(attrName, attrValue);
272
+ }
273
+ },
274
+
275
+ __removeAttributeValue: function (element, attrName, value) {
276
+ if (!value) return;
277
+ // Optimization: Use classList if the attribute is 'class'
278
+ if (attrName === "class") {
279
+ element.classList.remove(value);
280
+ return;
281
+ }
282
+
283
+ let check = new RegExp("(\\s|^)" + value + "(\\s|$)");
284
+ let attrValue = element.getAttribute(attrName) || "";
285
+
286
+ if (check.test(attrValue)) {
287
+ attrValue = attrValue.replace(check, " ").trim();
288
+ element.setAttribute(attrName, attrValue);
289
+ }
290
+ },
291
+
292
+ __getSize: function (attrValue, isWidth) {
293
+ let size = 0;
294
+ if (!attrValue) {
295
+ return 0;
296
+ }
297
+
298
+ if (attrValue.includes("%")) {
299
+ size = attrValue.replace("%", "").trim();
300
+ size = Number(size) || 0;
301
+
302
+ // Fix: Logic was inverted (dividing screen by size).
303
+ // Changed to standard percentage calculation: size% of screen.
304
+ size = isWidth
305
+ ? window.innerWidth * (size / 100)
306
+ : window.innerHeight * (size / 100);
307
+ } else {
308
+ size = attrValue.replace("px", "").trim();
309
+ size = Number(size) || 0;
310
+ }
311
+
312
+ return size;
313
+ }
288
314
  };
289
315
 
290
316
  function updateScrollableAttributes(element) {
291
- if (element.hasAttribute("scrollable-y")) {
292
- if (element.scrollWidth > element.clientWidth)
293
- element.setAttribute("scrollable-y", "true");
294
- else element.setAttribute("scrollable-y", "false");
295
- }
296
-
297
- if (element.hasAttribute("scrollable-x")) {
298
- if (element.scrollHeight > element.clientHeight)
299
- element.setAttribute("scrollable-x", "true");
300
- else element.setAttribute("scrollable-x", "false");
301
- }
317
+ if (element.hasAttribute("scrollable-y")) {
318
+ if (element.scrollWidth > element.clientWidth)
319
+ element.setAttribute("scrollable-y", "true");
320
+ else element.setAttribute("scrollable-y", "false");
321
+ }
322
+
323
+ if (element.hasAttribute("scrollable-x")) {
324
+ if (element.scrollHeight > element.clientHeight)
325
+ element.setAttribute("scrollable-x", "true");
326
+ else element.setAttribute("scrollable-x", "false");
327
+ }
302
328
  }
303
329
 
304
330
  Observer.init({
305
- name: "CoCreateScrollCreate",
306
- types: ["addedNodes"],
307
- selector: "[scroll], [scroll-to], [scrollable-x], [scrollable-y]",
308
- callback: function (mutation) {
309
- CoCreateScroll.initElement(mutation.target);
310
- }
331
+ name: "CoCreateScrollCreate",
332
+ types: ["addedNodes"],
333
+ selector: selector,
334
+ callback: function (mutation) {
335
+ CoCreateScroll.initElement(mutation.target);
336
+ }
311
337
  });
312
338
 
313
339
  Observer.init({
314
- name: "CoCreateScrollAttributes",
315
- types: ["attributes"],
316
- attributeFilter: ["scroll-to"],
317
- // target: selector, // blocks mutations when applied
318
- callback: function (mutation) {
319
- CoCreateScroll.setScrollPosition(
320
- mutation.target,
321
- mutation.target.getAttribute("scroll-to")
322
- );
323
- }
340
+ name: "CoCreateScrollAttributes",
341
+ types: ["attributes"],
342
+ attributeFilter: ["scroll-to"],
343
+ // target: selector, // blocks mutations when applied
344
+ callback: function (mutation) {
345
+ CoCreateScroll.setScrollPosition(
346
+ mutation.target,
347
+ mutation.target.getAttribute("scroll-to")
348
+ );
349
+ }
324
350
  });
325
351
  Observer.init({
326
- name: "CoCreateScrollAttributes",
327
- types: ["attributes"],
328
- attributeFilter: ["scrollable-x", "scrollable-y"],
329
- // target: selector, // blocks mutations when applied
330
- callback: function (mutation) {
331
- if (
332
- mutation.oldValue !==
333
- mutation.target.getAttribute(mutation.attributeName)
334
- )
335
- updateScrollableAttributes(mutation.target);
336
- }
352
+ name: "CoCreateScrollAttributes",
353
+ types: ["attributes"],
354
+ attributeFilter: ["scrollable-x", "scrollable-y"],
355
+ // target: selector, // blocks mutations when applied
356
+ callback: function (mutation) {
357
+ if (
358
+ mutation.oldValue !==
359
+ mutation.target.getAttribute(mutation.attributeName)
360
+ )
361
+ updateScrollableAttributes(mutation.target);
362
+ }
337
363
  });
338
364
 
339
365
  Actions.init({
340
- name: "scroll-to",
341
- callback: (action) => {
342
- // CoCreateScroll.setScrollPosition(mutation.target)
343
- }
366
+ name: "scroll-to",
367
+ callback: (action) => {
368
+ // CoCreateScroll.setScrollPosition(mutation.target)
369
+ }
344
370
  });
345
371
 
346
372
  CoCreateScroll.init();
347
373
 
348
- export default CoCreateScroll;
374
+ export default CoCreateScroll;