@operato/utils 8.0.0-alpha.37 → 8.0.0-beta.1
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 +17 -0
- package/dist/src/mixins/gesture-mixin.d.ts +4 -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/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/gesture-helper.ts +0 -147
- 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/gesture-mixin.ts +0 -157
- package/src/mixins/index.ts +0 -2
- 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/longpressable.ts
DELETED
@@ -1,101 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* @license Copyright © HatioLab Inc. All rights reserved.
|
3
|
-
*/
|
4
|
-
|
5
|
-
/* Inspired by https://github.com/john-doherty/long-press-event */
|
6
|
-
|
7
|
-
var timer = null as any
|
8
|
-
|
9
|
-
// check if we're using a touch screen
|
10
|
-
//@ts-ignore
|
11
|
-
const isTouch = 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0
|
12
|
-
|
13
|
-
// switch to touch events if using a touch screen
|
14
|
-
const mouseDown = isTouch ? 'touchstart' : 'mousedown'
|
15
|
-
const mouseOut = isTouch ? 'touchcancel' : 'mouseout'
|
16
|
-
const mouseUp = isTouch ? 'touchend' : 'mouseup'
|
17
|
-
const mouseMove = isTouch ? 'touchmove' : 'mousemove'
|
18
|
-
|
19
|
-
/*
|
20
|
-
* Fires the 'long-press' event on element
|
21
|
-
* @returns {void}
|
22
|
-
*/
|
23
|
-
function fireLongPressEvent(this: HTMLElement) {
|
24
|
-
clearLongPressTimer()
|
25
|
-
|
26
|
-
// fire the long-press event
|
27
|
-
var suppressClickEvent = this.dispatchEvent(new CustomEvent('long-press', { bubbles: true, cancelable: true }))
|
28
|
-
|
29
|
-
if (suppressClickEvent) {
|
30
|
-
// temporarily intercept and clear the next click
|
31
|
-
this.addEventListener(
|
32
|
-
mouseUp,
|
33
|
-
function clearMouseUp(e) {
|
34
|
-
this.removeEventListener(mouseUp, clearMouseUp, true)
|
35
|
-
cancelEvent(e)
|
36
|
-
},
|
37
|
-
true
|
38
|
-
)
|
39
|
-
}
|
40
|
-
}
|
41
|
-
|
42
|
-
/*
|
43
|
-
* method responsible for starting the long press timer
|
44
|
-
* @param {event} e - event object
|
45
|
-
* @returns {void}
|
46
|
-
*/
|
47
|
-
function startLongPressTimer(e: Event) {
|
48
|
-
clearLongPressTimer(e)
|
49
|
-
|
50
|
-
var el = e.target as HTMLElement
|
51
|
-
|
52
|
-
// get delay from html attribute if it exists, otherwise default to 1500
|
53
|
-
var longPressDelayInMs = parseInt(el.getAttribute('data-long-press-delay') || '600', 10)
|
54
|
-
|
55
|
-
// start the timer
|
56
|
-
timer = setTimeout(fireLongPressEvent.bind(el), longPressDelayInMs)
|
57
|
-
}
|
58
|
-
|
59
|
-
/*
|
60
|
-
* method responsible for clearing a pending long press timer
|
61
|
-
* @param {event} e - event object
|
62
|
-
* @returns {void}
|
63
|
-
*/
|
64
|
-
function clearLongPressTimer(e?: Event) {
|
65
|
-
clearTimeout(timer)
|
66
|
-
timer = null
|
67
|
-
}
|
68
|
-
|
69
|
-
/*
|
70
|
-
* Cancels the current event
|
71
|
-
* @param {object} e - browser event object
|
72
|
-
* @returns {void}
|
73
|
-
*/
|
74
|
-
function cancelEvent(e: Event) {
|
75
|
-
e.stopImmediatePropagation()
|
76
|
-
e.preventDefault()
|
77
|
-
e.stopPropagation()
|
78
|
-
}
|
79
|
-
|
80
|
-
/**
|
81
|
-
* method set target element to be able to respond longpress event
|
82
|
-
* @param {HTMLElement} element target element
|
83
|
-
*/
|
84
|
-
export const longpressable = (element: HTMLElement) => {
|
85
|
-
// hook events that clear a pending long press event
|
86
|
-
element.addEventListener(mouseOut, clearLongPressTimer, true)
|
87
|
-
element.addEventListener(mouseUp, clearLongPressTimer, true)
|
88
|
-
element.addEventListener(mouseMove, clearLongPressTimer, true)
|
89
|
-
element.addEventListener('wheel', clearLongPressTimer, true)
|
90
|
-
element.addEventListener('scroll', clearLongPressTimer, true)
|
91
|
-
|
92
|
-
// hook events that can trigger a long press event
|
93
|
-
element.addEventListener(mouseDown, startLongPressTimer, true) // <- start
|
94
|
-
|
95
|
-
// cancel context for touch display
|
96
|
-
if (mouseDown.indexOf('touch') === 0) {
|
97
|
-
element.addEventListener('contextmenu', cancelEvent, true)
|
98
|
-
} else {
|
99
|
-
element.addEventListener('contextmenu', clearLongPressTimer, true)
|
100
|
-
}
|
101
|
-
}
|
@@ -1,157 +0,0 @@
|
|
1
|
-
interface CustomElement extends HTMLElement {
|
2
|
-
connectedCallback?(): void
|
3
|
-
disconnectedCallback?(): void
|
4
|
-
}
|
5
|
-
|
6
|
-
type Constructor<T = CustomElement> = new (...args: any[]) => T
|
7
|
-
|
8
|
-
export type GestureEventPinch = CustomEvent<{ scale: number; centerX: number; centerY: number }>
|
9
|
-
export type GestureEventDrag = CustomEvent<{
|
10
|
-
deltaX: number
|
11
|
-
deltaY: number
|
12
|
-
clientX: number
|
13
|
-
clientY: number
|
14
|
-
end: boolean
|
15
|
-
}>
|
16
|
-
export type GestureEventDoubleTap = CustomEvent<{ x: number; y: number }>
|
17
|
-
|
18
|
-
export function gesture<TBase extends Constructor>(Base: TBase) {
|
19
|
-
return class extends Base {
|
20
|
-
__pointers = new Map<number, { x: number; y: number }>()
|
21
|
-
__lastTapTime = 0
|
22
|
-
__lastPinchDistance = 0
|
23
|
-
__dragStart: { x: number; y: number } | null = null
|
24
|
-
|
25
|
-
connectedCallback(): void {
|
26
|
-
if (super.connectedCallback) {
|
27
|
-
super.connectedCallback()
|
28
|
-
}
|
29
|
-
this.addEventListener('pointerdown', this.handlePointerDown as EventListener)
|
30
|
-
}
|
31
|
-
|
32
|
-
disconnectedCallback(): void {
|
33
|
-
if (super.disconnectedCallback) {
|
34
|
-
super.disconnectedCallback()
|
35
|
-
}
|
36
|
-
this.removeEventListener('pointerdown', this.handlePointerDown as EventListener)
|
37
|
-
this.removeGlobalListeners()
|
38
|
-
}
|
39
|
-
|
40
|
-
handlePointerDown = (e: PointerEvent) => {
|
41
|
-
e.preventDefault()
|
42
|
-
const point = { x: e.clientX, y: e.clientY }
|
43
|
-
this.__pointers.set(e.pointerId, point)
|
44
|
-
|
45
|
-
this.addGlobalListeners()
|
46
|
-
}
|
47
|
-
|
48
|
-
handlePointerMove = (e: PointerEvent) => {
|
49
|
-
e.preventDefault()
|
50
|
-
const point = { x: e.clientX, y: e.clientY }
|
51
|
-
this.__pointers.set(e.pointerId, point)
|
52
|
-
|
53
|
-
if (this.__pointers.size === 2) {
|
54
|
-
this.handlePinch()
|
55
|
-
} else if (this.__pointers.size === 1) {
|
56
|
-
this.handleDrag(point, false)
|
57
|
-
}
|
58
|
-
}
|
59
|
-
|
60
|
-
handlePointerUp = (e: PointerEvent) => {
|
61
|
-
const point = { x: e.clientX, y: e.clientY }
|
62
|
-
this.__pointers.delete(e.pointerId)
|
63
|
-
|
64
|
-
if (this.__dragStart) {
|
65
|
-
this.handleDrag(point, true)
|
66
|
-
}
|
67
|
-
|
68
|
-
if (this.__pointers.size === 0) {
|
69
|
-
this.removeGlobalListeners()
|
70
|
-
this.__dragStart = null
|
71
|
-
this.__lastPinchDistance = 0
|
72
|
-
this.handleTap(point)
|
73
|
-
}
|
74
|
-
}
|
75
|
-
|
76
|
-
handlePinch() {
|
77
|
-
const pointers = Array.from(this.__pointers.values()) as { x: number; y: number }[]
|
78
|
-
const currentDistance = this.getDistance(pointers[0], pointers[1])
|
79
|
-
|
80
|
-
if (this.__lastPinchDistance) {
|
81
|
-
const scale = currentDistance / this.__lastPinchDistance
|
82
|
-
const center = {
|
83
|
-
x: (pointers[0].x + pointers[1].x) / 2,
|
84
|
-
y: (pointers[0].y + pointers[1].y) / 2
|
85
|
-
}
|
86
|
-
|
87
|
-
this.dispatchEvent(
|
88
|
-
new CustomEvent('pinch', {
|
89
|
-
detail: { scale, centerX: center.x, centerY: center.y }
|
90
|
-
})
|
91
|
-
)
|
92
|
-
}
|
93
|
-
|
94
|
-
this.__lastPinchDistance = currentDistance
|
95
|
-
}
|
96
|
-
|
97
|
-
handleDrag(point: { x: number; y: number }, end: boolean) {
|
98
|
-
if (this.__dragStart) {
|
99
|
-
const deltaX = point.x - this.__dragStart.x
|
100
|
-
const deltaY = point.y - this.__dragStart.y
|
101
|
-
|
102
|
-
this.dispatchEvent(
|
103
|
-
new CustomEvent('drag', {
|
104
|
-
detail: { deltaX, deltaY, clientX: point.x, clientY: point.y, end }
|
105
|
-
})
|
106
|
-
)
|
107
|
-
|
108
|
-
if (end) {
|
109
|
-
this.__dragStart = null
|
110
|
-
} else {
|
111
|
-
this.__dragStart = point
|
112
|
-
}
|
113
|
-
} else if (!end && this.__pointers.size === 1) {
|
114
|
-
/* dragging을 시작하려면, pointer 개수가 1개인 것을 (지연)확인해야한다. */
|
115
|
-
setTimeout(() => {
|
116
|
-
if (this.__pointers.size === 1 && !this.__dragStart) {
|
117
|
-
this.__dragStart = point
|
118
|
-
}
|
119
|
-
}, 30)
|
120
|
-
}
|
121
|
-
}
|
122
|
-
|
123
|
-
handleTap(point: { x: number; y: number }) {
|
124
|
-
const currentTime = performance.now()
|
125
|
-
const timeSinceLastTap = currentTime - this.__lastTapTime
|
126
|
-
|
127
|
-
if (timeSinceLastTap < 300) {
|
128
|
-
// 300ms is a common double-tap threshold
|
129
|
-
this.dispatchEvent(
|
130
|
-
new CustomEvent('doubletap', {
|
131
|
-
detail: { x: point.x, y: point.y }
|
132
|
-
})
|
133
|
-
)
|
134
|
-
}
|
135
|
-
|
136
|
-
this.__lastTapTime = currentTime
|
137
|
-
}
|
138
|
-
|
139
|
-
getDistance(p1: { x: number; y: number }, p2: { x: number; y: number }): number {
|
140
|
-
const dx = p1.x - p2.x
|
141
|
-
const dy = p1.y - p2.y
|
142
|
-
return Math.sqrt(dx * dx + dy * dy)
|
143
|
-
}
|
144
|
-
|
145
|
-
addGlobalListeners() {
|
146
|
-
document.addEventListener('pointermove', this.handlePointerMove as EventListener)
|
147
|
-
document.addEventListener('pointerup', this.handlePointerUp as EventListener)
|
148
|
-
document.addEventListener('pointercancel', this.handlePointerUp as EventListener)
|
149
|
-
}
|
150
|
-
|
151
|
-
removeGlobalListeners() {
|
152
|
-
document.removeEventListener('pointermove', this.handlePointerMove as EventListener)
|
153
|
-
document.removeEventListener('pointerup', this.handlePointerUp as EventListener)
|
154
|
-
document.removeEventListener('pointercancel', this.handlePointerUp as EventListener)
|
155
|
-
}
|
156
|
-
}
|
157
|
-
}
|
package/src/mixins/index.ts
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
import debounce from 'lodash-es/debounce'
|
2
|
-
|
3
|
-
type Constructor = new (...args: any[]) => {}
|
4
|
-
|
5
|
-
/**
|
6
|
-
* A higher-order function that enhances a base class with infinite scrolling functionality.
|
7
|
-
*
|
8
|
-
* @template TBase - The base class constructor type.
|
9
|
-
* @param {TBase} Base - The base class to enhance with infinite scrolling.
|
10
|
-
* @returns {TBase & InfiniteScrollable} - The extended class with infinite scrolling capabilities.
|
11
|
-
*/
|
12
|
-
export default function InfiniteScrollable<TBase extends Constructor>(Base: TBase) {
|
13
|
-
return class Scrolling extends Base {
|
14
|
-
/**
|
15
|
-
* Default options for infinite scrolling.
|
16
|
-
*
|
17
|
-
* @type {object}
|
18
|
-
* @property {number} threshold - The threshold value to trigger loading more items.
|
19
|
-
* @property {number} limit - The limit of items to load per page.
|
20
|
-
* @property {string} totalProp - The property name for the total number of items.
|
21
|
-
* @property {string} pageProp - The property name for the current page number.
|
22
|
-
*/
|
23
|
-
_infiniteScrollOptions = {
|
24
|
-
threshold: 20,
|
25
|
-
limit: 30,
|
26
|
-
totalProp: '_total',
|
27
|
-
pageProp: '_page'
|
28
|
-
}
|
29
|
-
|
30
|
-
/**
|
31
|
-
* Event handler for the scroll event with debouncing.
|
32
|
-
*
|
33
|
-
* @param {Event} e - The scroll event object.
|
34
|
-
*/
|
35
|
-
onScroll = debounce(e => {
|
36
|
-
//@ts-ignore inheritted class should have scrollTargetEl property
|
37
|
-
var el = this.scrollTargetEl
|
38
|
-
if (!el) {
|
39
|
-
console.warn('scroll target element is not defined.')
|
40
|
-
return
|
41
|
-
}
|
42
|
-
|
43
|
-
var { threshold = 0, limit, totalProp, pageProp } = this._infiniteScrollOptions
|
44
|
-
|
45
|
-
if (
|
46
|
-
(this as any)[pageProp] < (this as any)[totalProp] / limit &&
|
47
|
-
el.scrollHeight - el.clientHeight <= el.scrollTop + threshold
|
48
|
-
) {
|
49
|
-
this.scrollAction()
|
50
|
-
}
|
51
|
-
}, 300)
|
52
|
-
|
53
|
-
// commented due to TS2611 error
|
54
|
-
// get scrollTargetEl(): HTMLElement | null {
|
55
|
-
// console.warn('scroll target element is not defined.')
|
56
|
-
|
57
|
-
// return null
|
58
|
-
// }
|
59
|
-
|
60
|
-
/**
|
61
|
-
* An async function to handle scroll action when the threshold is reached.
|
62
|
-
*/
|
63
|
-
async scrollAction() {
|
64
|
-
console.warn('scroll action not implemented.')
|
65
|
-
}
|
66
|
-
}
|
67
|
-
}
|
package/src/number-parser.ts
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
// 숫자라면 숫자값을, 아니면 null을 반환
|
2
|
-
// 0 = true
|
3
|
-
// '0' = true
|
4
|
-
// 123 = true
|
5
|
-
// "123" = true
|
6
|
-
// -123 = true
|
7
|
-
// "-123" = true
|
8
|
-
// true = false
|
9
|
-
// false = false
|
10
|
-
// "" = false
|
11
|
-
// null = false
|
12
|
-
// undefined = false
|
13
|
-
// {} = false
|
14
|
-
// [] = false
|
15
|
-
export function parseToNumberOrNull(value: any): number | null {
|
16
|
-
let result: number | null = null
|
17
|
-
|
18
|
-
// 숫자나 스트링이면서 NaN이 아니면 숫자로 변환
|
19
|
-
if ((typeof value === 'string' || typeof value === 'number') && value !== '' && !isNaN(value as number)) {
|
20
|
-
result = Number(value)
|
21
|
-
}
|
22
|
-
|
23
|
-
return result
|
24
|
-
}
|
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
|
-
}
|