@webalternatif/js-core 1.6.0 → 1.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +3 -3
  2. package/dist/cjs/Mouse.js +6 -1
  3. package/dist/cjs/Translator.js +7 -1
  4. package/dist/cjs/array.js +7 -25
  5. package/dist/cjs/dom.js +819 -210
  6. package/dist/cjs/eventDispatcher.js +6 -1
  7. package/dist/cjs/index.js +6 -13
  8. package/dist/cjs/is.js +49 -6
  9. package/dist/cjs/math.js +56 -31
  10. package/dist/cjs/onOff.js +2 -2
  11. package/dist/cjs/random.js +6 -6
  12. package/dist/cjs/string.js +19 -17
  13. package/dist/cjs/traversal.js +1 -2
  14. package/dist/cjs/utils.js +155 -38
  15. package/dist/esm/Mouse.js +8 -2
  16. package/dist/esm/Translator.js +9 -3
  17. package/dist/esm/array.js +10 -29
  18. package/dist/esm/dom.js +821 -211
  19. package/dist/esm/eventDispatcher.js +9 -3
  20. package/dist/esm/index.js +7 -8
  21. package/dist/esm/is.js +49 -6
  22. package/dist/esm/math.js +60 -34
  23. package/dist/esm/onOff.js +6 -6
  24. package/dist/esm/random.js +6 -6
  25. package/dist/esm/string.js +23 -21
  26. package/dist/esm/stringPrototype.js +2 -2
  27. package/dist/esm/traversal.js +2 -3
  28. package/dist/esm/utils.js +158 -41
  29. package/dist/umd/Translator.umd.js +1 -0
  30. package/dist/umd/dom.umd.js +1 -0
  31. package/dist/umd/eventDispatcher.umd.js +1 -0
  32. package/dist/umd/mouse.umd.js +1 -0
  33. package/dist/umd/webf.umd.js +1 -0
  34. package/docs/array.md +90 -0
  35. package/docs/dom.md +1477 -0
  36. package/docs/eventDispatcher.md +15 -0
  37. package/docs/is.md +259 -0
  38. package/docs/math.md +127 -0
  39. package/docs/mouse.md +58 -0
  40. package/docs/random.md +15 -0
  41. package/docs/string.md +145 -0
  42. package/docs/translator.md +95 -0
  43. package/docs/traversal.md +159 -0
  44. package/docs/utils.md +228 -0
  45. package/package.json +37 -5
  46. package/src/Mouse.js +73 -0
  47. package/src/Translator.js +148 -0
  48. package/src/array.js +136 -0
  49. package/src/dom.js +1553 -0
  50. package/src/eventDispatcher.js +118 -0
  51. package/src/index.js +106 -0
  52. package/src/is.js +201 -0
  53. package/src/math.js +113 -0
  54. package/src/onOff.js +313 -0
  55. package/src/random.js +38 -0
  56. package/src/string.js +662 -0
  57. package/src/stringPrototype.js +16 -0
  58. package/src/traversal.js +236 -0
  59. package/src/utils.js +242 -0
  60. package/types/Translator.d.ts +6 -5
  61. package/types/array.d.ts +1 -2
  62. package/types/dom.d.ts +763 -204
  63. package/types/index.d.ts +23 -22
  64. package/types/is.d.ts +3 -0
  65. package/types/math.d.ts +6 -5
  66. package/types/utils.d.ts +4 -4
  67. package/types/i18n.d.ts +0 -4
package/src/onOff.js ADDED
@@ -0,0 +1,313 @@
1
+ import { isFunction, isTouchDevice } from './is.js'
2
+ import { foreach, map } from './traversal.js'
3
+ import { inArray } from './array.js'
4
+ import Mouse from './Mouse.js'
5
+
6
+ const LISTENERS = new Map()
7
+ const CUSTOM_EVENTS = ['longtap', 'dbltap']
8
+ const ENABLED_EVENTS = new Set()
9
+
10
+ let teardownLongTap = null
11
+ let teardownDblTap = null
12
+
13
+ const supplyEvent = function (event) {
14
+ if (ENABLED_EVENTS?.has(event)) return
15
+
16
+ if (event === 'longtap') enableLongTap()
17
+ if (event === 'dbltap') enableDblTap()
18
+
19
+ ENABLED_EVENTS.add(event)
20
+ }
21
+
22
+ const enableLongTap = function () {
23
+ const LONGPRESS_DELAY = 800
24
+ const MOVE_TOLERANCE = 40
25
+
26
+ let timer = null
27
+ let startX = 0
28
+ let startY = 0
29
+ let target = null
30
+
31
+ const start = (ev) => {
32
+ target = ev.target
33
+
34
+ const pos = Mouse.getViewportPosition(ev)
35
+ startX = pos.x
36
+ startY = pos.y
37
+
38
+ timer = setTimeout(() => {
39
+ target.dispatchEvent(
40
+ new CustomEvent('longtap', {
41
+ bubbles: true,
42
+ cancelable: true,
43
+ detail: { originalEvent: ev },
44
+ }),
45
+ )
46
+
47
+ timer = null
48
+ }, LONGPRESS_DELAY)
49
+ }
50
+
51
+ const move = (ev) => {
52
+ // if (!timer) return;
53
+
54
+ const pos = Mouse.getViewportPosition(ev)
55
+
56
+ if (Math.hypot(pos.x - startX, pos.y - startY) > MOVE_TOLERANCE) {
57
+ clearTimeout(timer)
58
+ timer = null
59
+ }
60
+ }
61
+
62
+ const end = () => {
63
+ clearTimeout(timer)
64
+ timer = null
65
+ }
66
+
67
+ document.addEventListener('touchstart', start, { passive: true })
68
+ document.addEventListener('touchmove', move, { passive: true })
69
+ document.addEventListener('touchend', end)
70
+ document.addEventListener('touchcancel', end)
71
+
72
+ teardownLongTap = () => {
73
+ document.removeEventListener('touchstart', start, { passive: true })
74
+ document.removeEventListener('touchmove', move, { passive: true })
75
+ document.removeEventListener('touchend', end)
76
+ document.removeEventListener('touchcancel', end)
77
+ teardownLongTap = null
78
+ }
79
+ }
80
+
81
+ const enableDblTap = function () {
82
+ const DBLTAP_DELAY = 300
83
+ const MOVE_TOLERANCE = 40
84
+ let lastTapTime = 0
85
+ let lastPos = null
86
+
87
+ if (isTouchDevice()) {
88
+ document.addEventListener(
89
+ 'dblclick',
90
+ (ev) => {
91
+ ev.preventDefault()
92
+ ev.stopPropagation()
93
+ ev.stopImmediatePropagation()
94
+ },
95
+ { capture: true },
96
+ )
97
+ }
98
+
99
+ const start = (ev) => {
100
+ const target = ev.target
101
+
102
+ if (Date.now() - lastTapTime > DBLTAP_DELAY) {
103
+ lastTapTime = Date.now()
104
+ lastPos = Mouse.getViewportPosition(ev)
105
+ } else {
106
+ const pos = Mouse.getViewportPosition(ev)
107
+
108
+ if (Math.hypot(pos.x - lastPos.x, pos.y - lastPos.y) <= MOVE_TOLERANCE) {
109
+ target.dispatchEvent(
110
+ new CustomEvent('dbltap', {
111
+ bubbles: true,
112
+ cancelable: true,
113
+ detail: { originalEvent: ev },
114
+ }),
115
+ )
116
+ }
117
+
118
+ lastTapTime = Date.now()
119
+ lastPos = pos
120
+ }
121
+ }
122
+
123
+ document.addEventListener('touchstart', start, { passive: true })
124
+
125
+ teardownDblTap = () => {
126
+ document.removeEventListener('touchstart', start, { passive: true })
127
+ teardownDblTap = null
128
+ }
129
+ }
130
+
131
+ /**
132
+ * @param {Element} target
133
+ * @param {Element} el
134
+ * @returns {Element[]}
135
+ */
136
+ function buildTree(target, el) {
137
+ const path = []
138
+ let node = target.nodeType === 3 ? target.parentNode : target
139
+
140
+ while (node) {
141
+ path.push(node)
142
+ if (node === el) break
143
+ node = node.parentNode
144
+ }
145
+
146
+ return path
147
+ }
148
+
149
+ function createWrappedEvent(ev, currentTarget) {
150
+ const wrappedEv = {
151
+ _immediateStopped: false,
152
+ _propagationStopped: false,
153
+ originalEvent: ev,
154
+ currentTarget,
155
+
156
+ stopPropagation: (...args) => {
157
+ wrappedEv._propagationStopped = true
158
+ ev.stopPropagation(...args)
159
+ },
160
+
161
+ stopImmediatePropagation: (...args) => {
162
+ wrappedEv._immediateStopped = true
163
+ wrappedEv._propagationStopped = true
164
+ ev.stopImmediatePropagation(...args)
165
+ },
166
+ }
167
+
168
+ return new Proxy(wrappedEv, {
169
+ get(target, prop, receiver) {
170
+ if (prop in target) {
171
+ return Reflect.get(target, prop, receiver)
172
+ }
173
+
174
+ const value = ev[prop]
175
+ return isFunction(value) ? value.bind(ev) : value
176
+ },
177
+ })
178
+ }
179
+
180
+ /**
181
+ * @param {Element|Document|Window} el
182
+ * @param {string} events
183
+ * @param {string|Element|function} selector
184
+ * @param {function|AddEventListenerOptions|boolean} [handler]
185
+ * @param {AddEventListenerOptions|boolean} [options]
186
+ * @returns {Element}
187
+ */
188
+ export function on(el, events, selector, handler, options) {
189
+ if (isFunction(selector)) {
190
+ options = handler
191
+ handler = selector
192
+ selector = null
193
+ }
194
+
195
+ foreach(events.split(' '), (rawEvent) => {
196
+ const [event, namespace] = rawEvent.split('.')
197
+
198
+ const listener = (ev) => {
199
+ if (ev.cancelBubble) return
200
+
201
+ const tree = buildTree(ev.target, el)
202
+
203
+ const binds = [...LISTENERS.get(el)]
204
+
205
+ for (const node of tree) {
206
+ let propagationStoppedOnThisNode = false
207
+
208
+ for (const bind of binds) {
209
+ if (bind.event !== ev.type) continue
210
+
211
+ if (bind.selector) {
212
+ if (!node.matches(bind.selector)) continue
213
+ } else {
214
+ if (node !== el) continue
215
+ }
216
+
217
+ const wrappedEv = createWrappedEvent(ev, node)
218
+ bind.handler.call(node, wrappedEv)
219
+
220
+ if (wrappedEv._immediateStopped) return
221
+
222
+ if (wrappedEv._propagationStopped) {
223
+ propagationStoppedOnThisNode = true
224
+ }
225
+ }
226
+
227
+ if (propagationStoppedOnThisNode) return
228
+ }
229
+ }
230
+
231
+ let store = LISTENERS.get(el)
232
+ if (!store) {
233
+ store = []
234
+ LISTENERS.set(el, store)
235
+ }
236
+
237
+ if (inArray(event, CUSTOM_EVENTS)) {
238
+ supplyEvent(event)
239
+ }
240
+
241
+ const events = map(store, (_, entry) => entry.event)
242
+
243
+ if (!inArray(event, events)) {
244
+ el.addEventListener(event, listener, options)
245
+ }
246
+
247
+ store.push({ event, handler, selector, listener, namespace, options })
248
+ })
249
+
250
+ return el
251
+ }
252
+
253
+ /**
254
+ * @param {Element|Document|Window} el
255
+ * @param {string} [events]
256
+ * @param {string|Element|function} [selector]
257
+ * @param {function|AddEventListenerOptions|boolean} [handler]
258
+ * @param {AddEventListenerOptions|boolean} [options]
259
+ * @returns {Element}
260
+ */
261
+ export function off(el, events, selector, handler, options) {
262
+ if (isFunction(selector)) {
263
+ options = handler
264
+ handler = selector
265
+ selector = null
266
+ }
267
+
268
+ const store = LISTENERS.get(el)
269
+ if (!store) return el
270
+
271
+ const evts = events ? events.split(' ') : [undefined]
272
+
273
+ foreach(evts, (rawEvent) => {
274
+ let [event, namespace] =
275
+ undefined === rawEvent ? [undefined, undefined] : rawEvent.split('.')
276
+
277
+ event = !event ? undefined : event
278
+
279
+ const hasEvent = undefined !== event
280
+ const hasNs = undefined !== namespace
281
+
282
+ foreach([...store].reverse(), (l) => {
283
+ const match =
284
+ (!hasEvent && !hasNs) ||
285
+ (hasEvent && !hasNs && l.event === event) ||
286
+ (!hasEvent && hasNs && l.namespace === namespace) ||
287
+ (hasEvent && hasNs && l.event === event && l.namespace === namespace)
288
+
289
+ if (
290
+ match &&
291
+ (undefined === event || l.event === event) &&
292
+ (undefined === handler || l.handler === handler) &&
293
+ (undefined === selector || l.selector === selector) &&
294
+ (undefined === namespace || l.namespace === namespace) &&
295
+ (undefined === options || l.options === options)
296
+ ) {
297
+ const index = store.indexOf(l)
298
+ index !== -1 && store.splice(index, 1)
299
+
300
+ if (!map(store, (_, entry) => (entry.event === event ? entry : null))[0])
301
+ el.removeEventListener(l.event, l.listener, l.options)
302
+ }
303
+ })
304
+ })
305
+
306
+ return el
307
+ }
308
+
309
+ export function __resetCustomEventsForTests() {
310
+ ENABLED_EVENTS.clear()
311
+ teardownLongTap?.()
312
+ teardownDblTap?.()
313
+ }
package/src/random.js ADDED
@@ -0,0 +1,38 @@
1
+ export const randAlpha = function (n) {
2
+ return rand('abcdefghijklmnopqrstuvwxyz'.split(''), n)
3
+ }
4
+
5
+ export const randAlphaCs = function (n) {
6
+ return rand('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), n)
7
+ }
8
+
9
+ export const randAlphaNum = function (n) {
10
+ return rand('0123456789abcdefghijklmnopqrstuvwxyz'.split(''), n)
11
+ }
12
+
13
+ export const randAlphaNumCs = function (n) {
14
+ return rand('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), n)
15
+ }
16
+
17
+ export const randNum = function (n) {
18
+ return rand('0123456789'.split(''), n)
19
+ }
20
+
21
+ export const rand = function (range, n) {
22
+ let rand = ''
23
+
24
+ for (let i = 0; i < n; i++) {
25
+ rand += range[Math.floor(Math.random() * 1000) % range.length]
26
+ }
27
+
28
+ return rand
29
+ }
30
+
31
+ export const uniqid = (function () {
32
+ let uid = 0
33
+
34
+ return function (prefix = '') {
35
+ uid++
36
+ return `${prefix}${Date.now().toString(36)}_${uid.toString(36)}_${randAlphaNum(5)}`
37
+ }
38
+ })()