@operato/utils 7.1.1 → 7.1.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/.editorconfig +0 -29
- package/.storybook/main.js +0 -3
- package/.storybook/preview.js +0 -52
- package/.storybook/server.mjs +0 -8
- package/demo/index.html +0 -43
- package/src/adjust-list-param.ts +0 -79
- package/src/async-lock.ts +0 -27
- package/src/clipboard.ts +0 -41
- package/src/closest-element.ts +0 -24
- package/src/context-path.ts +0 -42
- package/src/cookie.ts +0 -44
- package/src/decode-html.ts +0 -5
- package/src/detect-overflow.ts +0 -18
- package/src/encode-form-params.ts +0 -24
- package/src/file-drop-helper.ts +0 -62
- package/src/format.ts +0 -123
- package/src/fullscreen.ts +0 -82
- package/src/has-overflow.ts +0 -22
- package/src/index.ts +0 -25
- package/src/is-unvalued.ts +0 -10
- package/src/logger.ts +0 -32
- package/src/longpressable.ts +0 -101
- package/src/mixins/index.ts +0 -1
- package/src/mixins/infinite-scrollable.ts +0 -67
- package/src/number-parser.ts +0 -24
- package/src/os.ts +0 -48
- package/src/parse-jwt.ts +0 -21
- package/src/password-pattern.ts +0 -63
- package/src/reactive-controllers/index.ts +0 -1
- package/src/reactive-controllers/tooltip-reactive-controller.ts +0 -88
- package/src/sleep.ts +0 -10
- package/src/stringify-bignum.ts +0 -35
- package/src/swipe-listener.ts +0 -290
- package/src/timecapsule/index.ts +0 -2
- package/src/timecapsule/snapshot-taker.ts +0 -105
- package/src/timecapsule/timecapsule.ts +0 -139
- package/tsconfig.json +0 -24
- package/web-dev-server.config.mjs +0 -27
- package/web-test-runner.config.mjs +0 -41
package/src/os.ts
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* method to tell if platform of running browser is kind of touch device
|
3
|
-
* @returns {boolean}
|
4
|
-
*/
|
5
|
-
export function isTouchDevice() {
|
6
|
-
return window.matchMedia('(pointer:none), (pointer:coarse)').matches
|
7
|
-
}
|
8
|
-
|
9
|
-
/**
|
10
|
-
* method to tell if platform of running browser is kind of mobile device
|
11
|
-
* @returns {boolean}
|
12
|
-
*/
|
13
|
-
export function isHandheldDevice() {
|
14
|
-
return window.matchMedia('(max-width: 460px)').matches
|
15
|
-
}
|
16
|
-
|
17
|
-
/**
|
18
|
-
* method to tell if platform of running browser is kind of mobile device
|
19
|
-
* @returns {boolean}
|
20
|
-
*/
|
21
|
-
export function isMobileDevice() {
|
22
|
-
return window.matchMedia('(max-width: 767px)').matches
|
23
|
-
}
|
24
|
-
|
25
|
-
/**
|
26
|
-
* method to tell if operating system of running browser is iOS
|
27
|
-
* @returns {boolean}
|
28
|
-
*/
|
29
|
-
export function isIOS() {
|
30
|
-
//@ts-ignore
|
31
|
-
return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream
|
32
|
-
}
|
33
|
-
|
34
|
-
/**
|
35
|
-
* method to tell if operating system of running browser is MacOS
|
36
|
-
* @returns {boolean}
|
37
|
-
*/
|
38
|
-
export function isMacOS() {
|
39
|
-
return navigator.userAgent.indexOf('Mac') !== -1
|
40
|
-
}
|
41
|
-
|
42
|
-
/**
|
43
|
-
* method to tell if platform of running browser is Safari
|
44
|
-
* @returns {boolean}
|
45
|
-
*/
|
46
|
-
export function isSafari() {
|
47
|
-
return !navigator.userAgent.match(/chrome|chromium|crios/i) && navigator.userAgent.match(/safari/i)
|
48
|
-
}
|
package/src/parse-jwt.ts
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
var atob: any =
|
2
|
-
typeof atob !== 'undefined'
|
3
|
-
? atob
|
4
|
-
: (base64: string) => {
|
5
|
-
return Buffer.from(base64, 'base64').toString()
|
6
|
-
}
|
7
|
-
|
8
|
-
export function parseJwt(token: string): any {
|
9
|
-
var base64Url = token.split('.')[1]
|
10
|
-
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')
|
11
|
-
var jsonPayload = decodeURIComponent(
|
12
|
-
atob(base64)
|
13
|
-
.split('')
|
14
|
-
.map(function (c: string) {
|
15
|
-
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
|
16
|
-
})
|
17
|
-
.join('')
|
18
|
-
)
|
19
|
-
|
20
|
-
return JSON.parse(jsonPayload)
|
21
|
-
}
|
package/src/password-pattern.ts
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Generates a regular expression pattern for validating passwords based on specified criteria.
|
3
|
-
*
|
4
|
-
* @param {object} options - An object containing options for generating the pattern.
|
5
|
-
* @param {boolean} options.lowerCase - Indicates whether the password should contain at least one lowercase character.
|
6
|
-
* @param {boolean} options.upperCase - Indicates whether the password should contain at least one uppercase character.
|
7
|
-
* @param {boolean} options.digit - Indicates whether the password should contain at least one digit.
|
8
|
-
* @param {boolean} options.specialCharacter - Indicates whether the password should contain at least one special character.
|
9
|
-
* @param {boolean} options.allowRepeat - Indicates whether repeated characters are allowed in the password.
|
10
|
-
* @param {boolean} options.useTightPattern - Indicates whether to use a tight pattern for password length.
|
11
|
-
* @param {boolean} options.useLoosePattern - Indicates whether to use a loose pattern for password length.
|
12
|
-
* @param {number} options.tightCharacterLength - The minimum length of the password for the tight pattern.
|
13
|
-
* @param {number} options.looseCharacterLength - The minimum length of the password for the loose pattern.
|
14
|
-
* @returns {RegExp} - A regular expression pattern for validating passwords based on the specified criteria.
|
15
|
-
*/
|
16
|
-
export function generatePasswordPatternRegExp({
|
17
|
-
lowerCase = true,
|
18
|
-
upperCase = true,
|
19
|
-
digit = true,
|
20
|
-
specialCharacter = true,
|
21
|
-
allowRepeat = false,
|
22
|
-
useTightPattern = true,
|
23
|
-
useLoosePattern = false,
|
24
|
-
tightCharacterLength = 8,
|
25
|
-
looseCharacterLength = 15
|
26
|
-
}: {
|
27
|
-
lowerCase?: boolean
|
28
|
-
upperCase?: boolean
|
29
|
-
digit?: boolean
|
30
|
-
specialCharacter?: boolean
|
31
|
-
allowRepeat?: boolean
|
32
|
-
useTightPattern?: boolean
|
33
|
-
useLoosePattern?: boolean
|
34
|
-
tightCharacterLength?: Number
|
35
|
-
looseCharacterLength?: Number
|
36
|
-
} = {}) {
|
37
|
-
var tightChecklist = useTightPattern
|
38
|
-
? [
|
39
|
-
lowerCase ? '(?=.*[a-z])' : '', // has at least one lower case character
|
40
|
-
upperCase ? '(?=.*[A-Z])' : '', // has at least one upper case character
|
41
|
-
digit ? '(?=.*\\d)' : '', // has at least one digit
|
42
|
-
specialCharacter ? '(?=.*[!@#$%^&*()])' : '', // has at least one special character
|
43
|
-
!allowRepeat ? '(?!.*(.)\\1(?=\\1{1,}))' : '', // has not an repeated character more than twice
|
44
|
-
`.{${tightCharacterLength},}` // has a length of 8 and more
|
45
|
-
]
|
46
|
-
: []
|
47
|
-
|
48
|
-
var looseChecklist = useLoosePattern
|
49
|
-
? [
|
50
|
-
`.{${looseCharacterLength},}` // has a length of 15 and more
|
51
|
-
]
|
52
|
-
: []
|
53
|
-
|
54
|
-
var checkList = [
|
55
|
-
'^', // from start
|
56
|
-
...tightChecklist,
|
57
|
-
tightChecklist.length && looseChecklist.length ? '|' : '',
|
58
|
-
...looseChecklist,
|
59
|
-
'$' //to the end"
|
60
|
-
]
|
61
|
-
|
62
|
-
return new RegExp(checkList.join(''))
|
63
|
-
}
|
@@ -1 +0,0 @@
|
|
1
|
-
export * from './tooltip-reactive-controller.js'
|
@@ -1,88 +0,0 @@
|
|
1
|
-
import { ReactiveController, ReactiveControllerHost } from 'lit'
|
2
|
-
import { hasOverflow } from '../has-overflow'
|
3
|
-
|
4
|
-
export class TooltipReactiveController implements ReactiveController {
|
5
|
-
private host: ReactiveControllerHost & HTMLElement
|
6
|
-
private attributeName: string
|
7
|
-
private content?: string | ((element: HTMLElement) => string)
|
8
|
-
private static tooltipContainer: HTMLElement | null = null
|
9
|
-
|
10
|
-
constructor(
|
11
|
-
host: ReactiveControllerHost & HTMLElement,
|
12
|
-
options?: {
|
13
|
-
content?: string | ((element: HTMLElement) => string)
|
14
|
-
attributeName?: string
|
15
|
-
}
|
16
|
-
) {
|
17
|
-
const { attributeName, content } = options || {}
|
18
|
-
|
19
|
-
this.host = host
|
20
|
-
this.attributeName = attributeName || 'data-reactive-tooltip'
|
21
|
-
this.content = content
|
22
|
-
|
23
|
-
host.addController(this)
|
24
|
-
|
25
|
-
// Create a tooltip container element if it doesn't exist
|
26
|
-
if (!TooltipReactiveController.tooltipContainer) {
|
27
|
-
TooltipReactiveController.tooltipContainer = document.createElement('div')
|
28
|
-
TooltipReactiveController.tooltipContainer.className = 'ox-tooltip-container'
|
29
|
-
TooltipReactiveController.tooltipContainer.style.position = 'fixed'
|
30
|
-
TooltipReactiveController.tooltipContainer.style.pointerEvents = 'none'
|
31
|
-
TooltipReactiveController.tooltipContainer.style.zIndex = '1000'
|
32
|
-
// Set default styles using CSS variables
|
33
|
-
TooltipReactiveController.tooltipContainer.style.fontSize = 'var(--tooltip-font-size, 1.0em)'
|
34
|
-
TooltipReactiveController.tooltipContainer.style.color = 'var(--tooltip-color, #fff)'
|
35
|
-
TooltipReactiveController.tooltipContainer.style.backgroundColor =
|
36
|
-
'var(--tooltip-background-color, rgba(0, 0, 0, 0.7))'
|
37
|
-
TooltipReactiveController.tooltipContainer.style.padding = 'var(--tooltip-padding, 5px)'
|
38
|
-
TooltipReactiveController.tooltipContainer.style.borderRadius = 'var(--tooltip-border-radius, 3px)'
|
39
|
-
TooltipReactiveController.tooltipContainer.style.boxShadow =
|
40
|
-
'var(--tooltip-box-shadow, 0 2px 10px rgba(0, 0, 0, 0.2))'
|
41
|
-
TooltipReactiveController.tooltipContainer.style.maxWidth = 'var(--tooltip-max-width, 300px)'
|
42
|
-
TooltipReactiveController.tooltipContainer.style.wordWrap = 'break-word'
|
43
|
-
TooltipReactiveController.tooltipContainer.style.whiteSpace = 'pre-wrap'
|
44
|
-
TooltipReactiveController.tooltipContainer.style.overflow = 'hidden'
|
45
|
-
document.body.appendChild(TooltipReactiveController.tooltipContainer)
|
46
|
-
}
|
47
|
-
}
|
48
|
-
|
49
|
-
hostConnected() {
|
50
|
-
const target = this.host.shadowRoot ?? this.host
|
51
|
-
target.addEventListener('mouseover', this.handleMouseOver)
|
52
|
-
target.addEventListener('mouseout', this.handleMouseOut)
|
53
|
-
}
|
54
|
-
|
55
|
-
hostDisconnected() {
|
56
|
-
const target = this.host.shadowRoot ?? this.host
|
57
|
-
target.removeEventListener('mouseover', this.handleMouseOver)
|
58
|
-
target.removeEventListener('mouseout', this.handleMouseOut)
|
59
|
-
}
|
60
|
-
|
61
|
-
private handleMouseOver = (e: Event) => {
|
62
|
-
const element = e.target as HTMLElement
|
63
|
-
if (element.hasAttribute(this.attributeName) && hasOverflow(element)) {
|
64
|
-
const tooltipContent =
|
65
|
-
typeof this.content === 'function'
|
66
|
-
? this.content.call(this, element)
|
67
|
-
: this.content || element.textContent?.trim() || ''
|
68
|
-
|
69
|
-
const rect = element.getBoundingClientRect()
|
70
|
-
|
71
|
-
// Calculate the fixed position
|
72
|
-
const fixedTop = rect.top + rect.height
|
73
|
-
const fixedLeft = rect.left
|
74
|
-
|
75
|
-
// Set tooltip container position and content
|
76
|
-
TooltipReactiveController.tooltipContainer!.style.top = `${fixedTop}px`
|
77
|
-
TooltipReactiveController.tooltipContainer!.style.left = `${fixedLeft}px`
|
78
|
-
TooltipReactiveController.tooltipContainer!.style.display = 'block'
|
79
|
-
TooltipReactiveController.tooltipContainer!.textContent = tooltipContent
|
80
|
-
}
|
81
|
-
}
|
82
|
-
|
83
|
-
private handleMouseOut = (e: Event) => {
|
84
|
-
if (TooltipReactiveController.tooltipContainer) {
|
85
|
-
TooltipReactiveController.tooltipContainer.style.display = 'none'
|
86
|
-
}
|
87
|
-
}
|
88
|
-
}
|
package/src/sleep.ts
DELETED
package/src/stringify-bignum.ts
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Converts a large number into a human-readable string representation with SI unit prefixes (K, M, B, T, P, E).
|
3
|
-
*
|
4
|
-
* This function takes a large number as input and converts it into a human-readable string representation using SI unit prefixes
|
5
|
-
* (K for thousand, M for million, B for billion, T for trillion, P for quadrillion, E for quintillion, etc.).
|
6
|
-
* It checks the magnitude of the input number and selects the appropriate SI unit,
|
7
|
-
* then formats the number with two decimal places and appends the corresponding SI unit symbol to create the readable string.
|
8
|
-
*
|
9
|
-
* @param {number} n - The number to be converted.
|
10
|
-
* @returns {string} - A human-readable string representation of the number with SI unit prefixes.
|
11
|
-
*/
|
12
|
-
|
13
|
-
export function stringifyBigNumber(n: number) {
|
14
|
-
if (n < 1000) {
|
15
|
-
return n
|
16
|
-
}
|
17
|
-
|
18
|
-
var si = [
|
19
|
-
{ v: 1e3, s: 'K' },
|
20
|
-
{ v: 1e6, s: 'M' },
|
21
|
-
{ v: 1e9, s: 'B' },
|
22
|
-
{ v: 1e12, s: 'T' },
|
23
|
-
{ v: 1e15, s: 'P' },
|
24
|
-
{ v: 1e18, s: 'E' }
|
25
|
-
]
|
26
|
-
|
27
|
-
var index
|
28
|
-
for (index = si.length - 1; index > 0; index--) {
|
29
|
-
if (n >= si[index].v) {
|
30
|
-
break
|
31
|
-
}
|
32
|
-
}
|
33
|
-
|
34
|
-
return (n / si[index].v).toFixed(2).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[index].s
|
35
|
-
}
|
package/src/swipe-listener.ts
DELETED
@@ -1,290 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* Starts monitoring swipes on the given element and
|
3
|
-
* emits `swipe` event when a swipe gesture is performed.
|
4
|
-
* @param {DOMElement} element Element on which to listen for swipe gestures.
|
5
|
-
* @param {Object} options Optional: Options.
|
6
|
-
* @return {Object}
|
7
|
-
*/
|
8
|
-
export function SwipeListener(element: HTMLElement, options?: any) {
|
9
|
-
if (!element) return
|
10
|
-
|
11
|
-
// CustomEvent polyfill
|
12
|
-
if (typeof window !== 'undefined') {
|
13
|
-
;(function () {
|
14
|
-
if (typeof window.CustomEvent === 'function') return false
|
15
|
-
function CustomEvent(event: string, params: any) {
|
16
|
-
params = params || { bubbles: false, cancelable: false, detail: undefined }
|
17
|
-
var evt = document.createEvent('CustomEvent')
|
18
|
-
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
|
19
|
-
return evt
|
20
|
-
}
|
21
|
-
CustomEvent.prototype = window.Event.prototype
|
22
|
-
;(window as any).CustomEvent = CustomEvent
|
23
|
-
})()
|
24
|
-
}
|
25
|
-
|
26
|
-
let defaultOpts = {
|
27
|
-
minHorizontal: 10, // Minimum number of pixels traveled to count as a horizontal swipe.
|
28
|
-
minVertical: 10, // Minimum number of pixels traveled to count as a vertical swipe.
|
29
|
-
deltaHorizontal: 3, // Delta for horizontal swipe
|
30
|
-
deltaVertical: 5, // Delta for vertical swipe
|
31
|
-
preventScroll: false, // Prevents scrolling when swiping.
|
32
|
-
lockAxis: true, // Select only one axis to be true instead of multiple.
|
33
|
-
touch: true, // Listen for touch events
|
34
|
-
mouse: true // Listen for mouse events
|
35
|
-
}
|
36
|
-
|
37
|
-
// Set options
|
38
|
-
if (!options) {
|
39
|
-
options = {}
|
40
|
-
}
|
41
|
-
options = {
|
42
|
-
...defaultOpts,
|
43
|
-
...options
|
44
|
-
}
|
45
|
-
|
46
|
-
// Store the touches
|
47
|
-
let touches: Array<{ x: number; y: number }> = []
|
48
|
-
|
49
|
-
// Not dragging by default.
|
50
|
-
let dragging = false
|
51
|
-
|
52
|
-
// When mouse-click is started, make dragging true.
|
53
|
-
const _mousedown = function (e: MouseEvent) {
|
54
|
-
dragging = true
|
55
|
-
}
|
56
|
-
|
57
|
-
// When mouse-click is released, make dragging false and signify end by imitating `touchend`.
|
58
|
-
const _mouseup = function (e: MouseEvent) {
|
59
|
-
dragging = false
|
60
|
-
_touchend(e as any)
|
61
|
-
}
|
62
|
-
|
63
|
-
// When mouse is moved while being clicked, imitate a `touchmove`.
|
64
|
-
const _mousemove = function (e: MouseEvent) {
|
65
|
-
if (dragging) {
|
66
|
-
;(e as any).changedTouches = [
|
67
|
-
{
|
68
|
-
clientX: e.clientX,
|
69
|
-
clientY: e.clientY
|
70
|
-
}
|
71
|
-
]
|
72
|
-
_touchmove(e as any)
|
73
|
-
}
|
74
|
-
}
|
75
|
-
|
76
|
-
if (options.mouse) {
|
77
|
-
element.addEventListener('mousedown', _mousedown)
|
78
|
-
element.addEventListener('mouseup', _mouseup)
|
79
|
-
element.addEventListener('mousemove', _mousemove)
|
80
|
-
}
|
81
|
-
|
82
|
-
// When the swipe is completed, calculate the direction.
|
83
|
-
const _touchend = function (e: TouchEvent) {
|
84
|
-
if (!touches.length) return
|
85
|
-
|
86
|
-
const touch = typeof TouchEvent === 'function' && e instanceof TouchEvent
|
87
|
-
|
88
|
-
let x = [],
|
89
|
-
y = []
|
90
|
-
|
91
|
-
let directions = {
|
92
|
-
top: false,
|
93
|
-
right: false,
|
94
|
-
bottom: false,
|
95
|
-
left: false
|
96
|
-
}
|
97
|
-
|
98
|
-
for (let i = 0; i < touches.length; i++) {
|
99
|
-
x.push(touches[i].x)
|
100
|
-
y.push(touches[i].y)
|
101
|
-
}
|
102
|
-
|
103
|
-
const xs = x[0],
|
104
|
-
xe = x[x.length - 1], // Start and end x-coords
|
105
|
-
ys = y[0],
|
106
|
-
ye = y[y.length - 1] // Start and end y-coords
|
107
|
-
|
108
|
-
const eventCoords = {
|
109
|
-
x: [xs, xe],
|
110
|
-
y: [ys, ye]
|
111
|
-
}
|
112
|
-
|
113
|
-
if (touches.length > 1) {
|
114
|
-
const swipeReleaseEventData = {
|
115
|
-
detail: {
|
116
|
-
touch,
|
117
|
-
target: e.target,
|
118
|
-
...eventCoords
|
119
|
-
}
|
120
|
-
}
|
121
|
-
|
122
|
-
let swipeReleaseEvent = new CustomEvent('swiperelease', swipeReleaseEventData)
|
123
|
-
element.dispatchEvent(swipeReleaseEvent)
|
124
|
-
}
|
125
|
-
|
126
|
-
// Determine left or right
|
127
|
-
let diff = x[0] - x[x.length - 1]
|
128
|
-
let swipe = 'none'
|
129
|
-
if (diff > 0) {
|
130
|
-
swipe = 'left'
|
131
|
-
} else {
|
132
|
-
swipe = 'right'
|
133
|
-
}
|
134
|
-
|
135
|
-
let min = Math.min(...x),
|
136
|
-
max = Math.max(...x),
|
137
|
-
_diff
|
138
|
-
|
139
|
-
// If minimum horizontal distance was travelled
|
140
|
-
if (Math.abs(diff) >= options.minHorizontal) {
|
141
|
-
switch (swipe) {
|
142
|
-
case 'left':
|
143
|
-
_diff = Math.abs(min - x[x.length - 1])
|
144
|
-
if (_diff <= options.deltaHorizontal) {
|
145
|
-
directions.left = true
|
146
|
-
}
|
147
|
-
break
|
148
|
-
case 'right':
|
149
|
-
_diff = Math.abs(max - x[x.length - 1])
|
150
|
-
if (_diff <= options.deltaHorizontal) {
|
151
|
-
directions.right = true
|
152
|
-
}
|
153
|
-
break
|
154
|
-
}
|
155
|
-
}
|
156
|
-
|
157
|
-
// Determine top or bottom
|
158
|
-
diff = y[0] - y[y.length - 1]
|
159
|
-
swipe = 'none'
|
160
|
-
if (diff > 0) {
|
161
|
-
swipe = 'top'
|
162
|
-
} else {
|
163
|
-
swipe = 'bottom'
|
164
|
-
}
|
165
|
-
|
166
|
-
min = Math.min(...y)
|
167
|
-
max = Math.max(...y)
|
168
|
-
|
169
|
-
// If minimum vertical distance was travelled
|
170
|
-
if (Math.abs(diff) >= options.minVertical) {
|
171
|
-
switch (swipe) {
|
172
|
-
case 'top':
|
173
|
-
_diff = Math.abs(min - y[y.length - 1])
|
174
|
-
if (_diff <= options.deltaVertical) {
|
175
|
-
directions.top = true
|
176
|
-
}
|
177
|
-
break
|
178
|
-
case 'bottom':
|
179
|
-
_diff = Math.abs(max - y[y.length - 1])
|
180
|
-
if (_diff <= options.deltaVertical) {
|
181
|
-
directions.bottom = true
|
182
|
-
}
|
183
|
-
break
|
184
|
-
}
|
185
|
-
}
|
186
|
-
|
187
|
-
// Clear touches array.
|
188
|
-
touches = []
|
189
|
-
|
190
|
-
// If there is a swipe direction, emit an event.
|
191
|
-
if (directions.top || directions.right || directions.bottom || directions.left) {
|
192
|
-
/**
|
193
|
-
* If lockAxis is true, determine which axis to select.
|
194
|
-
* The axis with the most travel is selected.
|
195
|
-
* TODO: Factor in for the orientation of the device
|
196
|
-
* and use it as a weight to determine the travel along an axis.
|
197
|
-
*/
|
198
|
-
if (options.lockAxis) {
|
199
|
-
if ((directions.left || directions.right) && Math.abs(xs - xe) > Math.abs(ys - ye)) {
|
200
|
-
directions.top = directions.bottom = false
|
201
|
-
} else if ((directions.top || directions.bottom) && Math.abs(xs - xe) < Math.abs(ys - ye)) {
|
202
|
-
directions.left = directions.right = false
|
203
|
-
}
|
204
|
-
}
|
205
|
-
|
206
|
-
const eventData = {
|
207
|
-
detail: {
|
208
|
-
directions,
|
209
|
-
touch,
|
210
|
-
target: e.target,
|
211
|
-
...eventCoords
|
212
|
-
}
|
213
|
-
}
|
214
|
-
|
215
|
-
let event = new CustomEvent('swipe', eventData)
|
216
|
-
element.dispatchEvent(event)
|
217
|
-
} else {
|
218
|
-
let cancelEvent = new CustomEvent('swipecancel', {
|
219
|
-
detail: {
|
220
|
-
touch,
|
221
|
-
target: e.target,
|
222
|
-
...eventCoords
|
223
|
-
}
|
224
|
-
})
|
225
|
-
element.dispatchEvent(cancelEvent)
|
226
|
-
}
|
227
|
-
}
|
228
|
-
|
229
|
-
// When a swipe is performed, store the coords.
|
230
|
-
const _touchmove = function (e: TouchEvent) {
|
231
|
-
let touch = e.changedTouches[0]
|
232
|
-
touches.push({
|
233
|
-
x: touch.clientX,
|
234
|
-
y: touch.clientY
|
235
|
-
})
|
236
|
-
|
237
|
-
// Emit a `swiping` event if there are more than one touch-points.
|
238
|
-
if (touches.length > 1) {
|
239
|
-
const xs = touches[0].x, // Start and end x-coords
|
240
|
-
xe = touches[touches.length - 1].x,
|
241
|
-
ys = touches[0].y, // Start and end y-coords
|
242
|
-
ye = touches[touches.length - 1].y,
|
243
|
-
eventData = {
|
244
|
-
detail: {
|
245
|
-
x: [xs, xe],
|
246
|
-
y: [ys, ye],
|
247
|
-
touch: typeof TouchEvent === 'function' && e instanceof TouchEvent,
|
248
|
-
target: e.target
|
249
|
-
}
|
250
|
-
}
|
251
|
-
let event = new CustomEvent('swiping', eventData)
|
252
|
-
|
253
|
-
const shouldPrevent =
|
254
|
-
options.preventScroll === true || (typeof options.preventScroll === 'function' && options.preventScroll(event))
|
255
|
-
|
256
|
-
if (shouldPrevent) {
|
257
|
-
e.preventDefault()
|
258
|
-
}
|
259
|
-
|
260
|
-
element.dispatchEvent(event)
|
261
|
-
}
|
262
|
-
}
|
263
|
-
|
264
|
-
// Test via a getter in the options object to see if the passive property is accessed
|
265
|
-
let passiveOptions: any = false
|
266
|
-
try {
|
267
|
-
const testOptions = Object.defineProperty({}, 'passive', {
|
268
|
-
get: function () {
|
269
|
-
passiveOptions = { passive: !options.preventScroll }
|
270
|
-
}
|
271
|
-
})
|
272
|
-
window.addEventListener('testPassive', null as any, testOptions)
|
273
|
-
window.removeEventListener('testPassive', null as any, testOptions)
|
274
|
-
} catch (e) {}
|
275
|
-
|
276
|
-
if (options.touch) {
|
277
|
-
element.addEventListener('touchmove', _touchmove, passiveOptions)
|
278
|
-
element.addEventListener('touchend', _touchend)
|
279
|
-
}
|
280
|
-
|
281
|
-
return {
|
282
|
-
off: function () {
|
283
|
-
element.removeEventListener('touchmove', _touchmove, passiveOptions)
|
284
|
-
element.removeEventListener('touchend', _touchend)
|
285
|
-
element.removeEventListener('mousedown', _mousedown)
|
286
|
-
element.removeEventListener('mouseup', _mouseup)
|
287
|
-
element.removeEventListener('mousemove', _mousemove)
|
288
|
-
}
|
289
|
-
}
|
290
|
-
}
|
package/src/timecapsule/index.ts
DELETED
@@ -1,105 +0,0 @@
|
|
1
|
-
import { TimeCapsule } from './timecapsule'
|
2
|
-
import debounce from 'lodash-es/debounce'
|
3
|
-
|
4
|
-
/**
|
5
|
-
* A function that takes a SnapshotTaker as an argument and initiates snapshot creation
|
6
|
-
* using a debouncer to delay the process.
|
7
|
-
* @param {SnapshotTaker} taker - The SnapshotTaker instance to trigger snapshots for.
|
8
|
-
*/
|
9
|
-
var debouncer = debounce(
|
10
|
-
taker => {
|
11
|
-
if (!taker.brake) {
|
12
|
-
taker.take()
|
13
|
-
}
|
14
|
-
},
|
15
|
-
1000,
|
16
|
-
{ leading: true, trailing: false }
|
17
|
-
)
|
18
|
-
|
19
|
-
/**
|
20
|
-
* Function to trigger snapshot creation for a SnapshotTaker instance.
|
21
|
-
* Checks if the taker is in a brake state or not dirty before triggering the snapshot.
|
22
|
-
* @param {SnapshotTaker} taker - The SnapshotTaker instance to create a snapshot for.
|
23
|
-
*/
|
24
|
-
function take_snapshot(taker: SnapshotTaker) {
|
25
|
-
if (taker.brake || !taker.dirty) return
|
26
|
-
debouncer(taker)
|
27
|
-
}
|
28
|
-
|
29
|
-
/**
|
30
|
-
* Type definition for holding state information.
|
31
|
-
* @typedef {Object} StateHolder
|
32
|
-
* @property {*} state - The state to be held.
|
33
|
-
*/
|
34
|
-
export type StateHolder = {
|
35
|
-
state: any
|
36
|
-
}
|
37
|
-
|
38
|
-
/**
|
39
|
-
* Class responsible for taking and managing snapshots of state.
|
40
|
-
*/
|
41
|
-
export class SnapshotTaker {
|
42
|
-
private _brake: boolean = false
|
43
|
-
|
44
|
-
dirty: boolean = false
|
45
|
-
|
46
|
-
state_holder?: StateHolder
|
47
|
-
timecapsule?: TimeCapsule
|
48
|
-
|
49
|
-
/**
|
50
|
-
* Creates an instance of SnapshotTaker.
|
51
|
-
* @param {*} state_holder - The object that holds the state to be snapshot.
|
52
|
-
* @param {TimeCapsule} timecapsule - The TimeCapsule instance associated with this SnapshotTaker.
|
53
|
-
*/
|
54
|
-
constructor(state_holder: any, timecapsule: TimeCapsule) {
|
55
|
-
this.state_holder = state_holder
|
56
|
-
this.timecapsule = timecapsule
|
57
|
-
this.timecapsule.snapshot_taker = this
|
58
|
-
}
|
59
|
-
|
60
|
-
/**
|
61
|
-
* Disposes of the SnapshotTaker and clears associated references.
|
62
|
-
*/
|
63
|
-
dispose() {
|
64
|
-
delete this.state_holder
|
65
|
-
delete this.timecapsule
|
66
|
-
}
|
67
|
-
|
68
|
-
/**
|
69
|
-
* Marks the SnapshotTaker as dirty and initiates snapshot creation.
|
70
|
-
*/
|
71
|
-
touch() {
|
72
|
-
this.dirty = true
|
73
|
-
take_snapshot(this)
|
74
|
-
}
|
75
|
-
|
76
|
-
/* 모든 조건에 관계없이 현재 상태를 snapshot으로 취한다. */
|
77
|
-
/**
|
78
|
-
* Takes a snapshot of the current state.
|
79
|
-
* @param {boolean} [force=false] - If true, the snapshot is taken even if not dirty.
|
80
|
-
*/
|
81
|
-
take(force: boolean = false) {
|
82
|
-
if (this.dirty || force) {
|
83
|
-
this.timecapsule?.snapshot(this.state_holder?.state)
|
84
|
-
this.dirty = false
|
85
|
-
}
|
86
|
-
}
|
87
|
-
|
88
|
-
/**
|
89
|
-
* Gets the brake state of the SnapshotTaker.
|
90
|
-
* @returns {boolean} - true if the brake is active, false otherwise.
|
91
|
-
*/
|
92
|
-
get brake() {
|
93
|
-
return this._brake
|
94
|
-
}
|
95
|
-
|
96
|
-
/* 마우스를 드래깅하는 동안, 보통 brake 를 ON 시킨다. */
|
97
|
-
/**
|
98
|
-
* Sets the brake state of the SnapshotTaker and initiates snapshot creation.
|
99
|
-
* @param {boolean} brake - The new brake state.
|
100
|
-
*/
|
101
|
-
set brake(brake) {
|
102
|
-
this._brake = !!brake
|
103
|
-
take_snapshot(this)
|
104
|
-
}
|
105
|
-
}
|