@cloudparker/moldex.js 0.0.51 → 0.0.52
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/dist/services/dialog/dialog-service.d.ts +27 -0
- package/dist/services/dialog/dialog-service.js +110 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.js +5 -0
- package/dist/services/utils/color-service.d.ts +46 -0
- package/dist/services/utils/color-service.js +73 -0
- package/dist/services/utils/download-service.d.ts +91 -0
- package/dist/services/utils/download-service.js +159 -0
- package/dist/services/utils/file-service.d.ts +138 -0
- package/dist/services/utils/file-service.js +258 -0
- package/dist/services/utils/http-service.d.ts +77 -0
- package/dist/services/utils/http-service.js +158 -0
- package/dist/services/utils/image-service.d.ts +81 -0
- package/dist/services/utils/image-service.js +194 -0
- package/dist/services/utils/utils-service.d.ts +257 -55
- package/dist/services/utils/utils-service.js +347 -327
- package/dist/tailwind.css +1 -1
- package/dist/views/core/input/components/color-field/color-field.svelte +2 -2
- package/dist/views/core/input/components/color-field/color-field.svelte.d.ts +2 -11
- package/dist/views/core/input/components/combobox-field/combobox-field.svelte +2 -2
- package/dist/views/core/input/components/date-field/date-field.svelte +1 -1
- package/dist/views/core/input/components/date-field/date-field.svelte.d.ts +1 -10
- package/dist/views/core/input/components/datetime-field/datetime-field.svelte +1 -1
- package/dist/views/core/input/components/datetime-field/datetime-field.svelte.d.ts +1 -10
- package/dist/views/core/input/components/email-field/email-field.svelte +1 -1
- package/dist/views/core/input/components/email-field/email-field.svelte.d.ts +1 -10
- package/dist/views/core/input/components/file-field/file-field.svelte +15 -8
- package/dist/views/core/input/components/file-field/file-field.svelte.d.ts +2 -11
- package/dist/views/core/input/components/number-field/number-field.svelte +1 -1
- package/dist/views/core/input/components/number-field/number-field.svelte.d.ts +1 -10
- package/dist/views/core/input/components/password-field/password-field.svelte +1 -1
- package/dist/views/core/input/components/password-field/password-field.svelte.d.ts +1 -10
- package/dist/views/core/input/components/phone-field/phone-field.svelte +1 -1
- package/dist/views/core/input/components/phone-field/phone-field.svelte.d.ts +1 -10
- package/dist/views/core/input/components/search-field/search-field.svelte +1 -1
- package/dist/views/core/input/components/search-field/search-field.svelte.d.ts +1 -10
- package/dist/views/core/input/components/text-field/text-field.svelte +1 -1
- package/dist/views/core/input/components/text-field/text-field.svelte.d.ts +2 -11
- package/dist/views/core/input/components/textarea-field/textarea-field.svelte +1 -1
- package/dist/views/core/input/components/textarea-field/textarea-field.svelte.d.ts +2 -11
- package/dist/views/core/input/components/time-field/time-field.svelte +1 -1
- package/dist/views/core/input/components/time-field/time-field.svelte.d.ts +2 -11
- package/dist/views/core/text/components/text-copy/text-copy.svelte +3 -3
- package/package.json +2 -2
|
@@ -1,158 +1,52 @@
|
|
|
1
|
-
import { BROWSER } from 'esm-env';
|
|
2
1
|
import { toDate } from '../date/date-service';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Generates a random number between the specified minimum and maximum values (inclusive of the minimum and exclusive of the maximum).
|
|
4
|
+
*
|
|
5
|
+
* @param min - The minimum value (inclusive) of the random number range.
|
|
6
|
+
* @param max - The maximum value (exclusive) of the random number range.
|
|
7
|
+
* @returns A random number between `min` (inclusive) and `max` (exclusive).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // Generate a random number between 1 (inclusive) and 5 (exclusive)
|
|
11
|
+
* const randomNumber = random(1, 5); // Possible values: 1.0, 2.4, 3.6, etc.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* // Generate a random number between 10 (inclusive) and 20 (exclusive)
|
|
15
|
+
* const randomNumber = random(10, 20); // Possible values: 10.0, 15.3, 19.8, etc.
|
|
16
|
+
*/
|
|
12
17
|
export function random(min, max) {
|
|
18
|
+
if (min >= max) {
|
|
19
|
+
throw new Error('The "max" value must be greater than the "min" value.');
|
|
20
|
+
}
|
|
13
21
|
return min + Math.random() * (max - min);
|
|
14
22
|
}
|
|
15
|
-
export function openFilePicker(opt) {
|
|
16
|
-
return new Promise(resolve => {
|
|
17
|
-
let input = document.createElement('input');
|
|
18
|
-
input.type = 'file';
|
|
19
|
-
input.multiple = opt.multiple || false;
|
|
20
|
-
input.accept = opt.accept || ACCEPT_IMAGE_FILES;
|
|
21
|
-
input.onchange = _ => {
|
|
22
|
-
let files = Array.from(input.files);
|
|
23
|
-
if (opt.multiple) {
|
|
24
|
-
resolve(files);
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
resolve(files[0]);
|
|
28
|
-
}
|
|
29
|
-
document.body.removeChild(input);
|
|
30
|
-
};
|
|
31
|
-
input.style.display = 'none';
|
|
32
|
-
document.body.appendChild(input);
|
|
33
|
-
input.click();
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
23
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
24
|
+
* Strips the Base64 content from a Data URL string.
|
|
25
|
+
*
|
|
26
|
+
* This function removes the `data:[<mediatype>][;base64],` prefix from a Data URL string,
|
|
27
|
+
* leaving only the Base64 content. If the input is not a valid Data URL, the original input is returned.
|
|
28
|
+
*
|
|
29
|
+
* @param dataUrl - The Data URL string to be stripped.
|
|
30
|
+
* @returns The stripped Base64 content, or the original string if it is not a valid Data URL.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Remove the prefix from a Data URL string
|
|
34
|
+
* const dataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...';
|
|
35
|
+
* const base64Content = stripDataUrl(dataUrl);
|
|
36
|
+
* console.log(base64Content); // Output: "iVBORw0KGgoAAAANSUhEUgAA..."
|
|
40
37
|
*/
|
|
41
|
-
export function
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
reader.readAsDataURL(opt.file);
|
|
45
|
-
reader.onload = (event) => {
|
|
46
|
-
const img = new Image();
|
|
47
|
-
img.src = event.target.result;
|
|
48
|
-
img.onload = () => {
|
|
49
|
-
const elem = document.createElement('canvas');
|
|
50
|
-
let width = opt.width;
|
|
51
|
-
let height = opt.height || opt.width;
|
|
52
|
-
elem.width = width;
|
|
53
|
-
elem.height = height;
|
|
54
|
-
const ctx = elem.getContext('2d');
|
|
55
|
-
if (ctx) {
|
|
56
|
-
ctx.drawImage(img, 0, 0, width, height);
|
|
57
|
-
ctx.canvas.toBlob((blob) => {
|
|
58
|
-
const f = new File([blob], opt.fileName || opt.file
|
|
59
|
-
.name, {
|
|
60
|
-
type: opt.type || 'image/webp',
|
|
61
|
-
lastModified: Date.now()
|
|
62
|
-
});
|
|
63
|
-
resolve(f);
|
|
64
|
-
}, opt.type || 'image/webp', opt.quality ? (opt.quality / 100) : 0.8);
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
reader.onerror = error => console.log(error);
|
|
68
|
-
};
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
export async function downloadURI(uri, name) {
|
|
72
|
-
const res = await fetch(uri);
|
|
73
|
-
const link = document.createElement("a");
|
|
74
|
-
link.download = name;
|
|
75
|
-
link.href = URL.createObjectURL(await res.blob());
|
|
76
|
-
document.body.appendChild(link);
|
|
77
|
-
link.click();
|
|
78
|
-
document.body.removeChild(link);
|
|
79
|
-
}
|
|
80
|
-
export async function downloadFile(file) {
|
|
81
|
-
const link = document.createElement("a");
|
|
82
|
-
link.download = file.name;
|
|
83
|
-
link.href = URL.createObjectURL(file);
|
|
84
|
-
document.body.appendChild(link);
|
|
85
|
-
link.click();
|
|
86
|
-
document.body.removeChild(link);
|
|
87
|
-
}
|
|
88
|
-
export function downloadBlob(blob, name) {
|
|
89
|
-
return downloadFile(new File([blob], name));
|
|
90
|
-
}
|
|
91
|
-
export async function fileToDataURL(file) {
|
|
92
|
-
return new Promise((resolve, reject) => {
|
|
93
|
-
const reader = new FileReader();
|
|
94
|
-
reader.onloadend = function () {
|
|
95
|
-
const base64data = reader.result;
|
|
96
|
-
//console.log(base64data);
|
|
97
|
-
resolve(base64data);
|
|
98
|
-
};
|
|
99
|
-
reader.readAsDataURL(file);
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
export async function fileToText(file) {
|
|
103
|
-
return new Promise((resolve, reject) => {
|
|
104
|
-
const reader = new FileReader();
|
|
105
|
-
reader.onloadend = function () {
|
|
106
|
-
const text = reader.result;
|
|
107
|
-
//console.log(base64data);
|
|
108
|
-
resolve(text);
|
|
109
|
-
};
|
|
110
|
-
reader.readAsText(file);
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
export async function fileToBuffer(file) {
|
|
114
|
-
return new Promise((resolve, reject) => {
|
|
115
|
-
const reader = new FileReader();
|
|
116
|
-
reader.onloadend = function () {
|
|
117
|
-
resolve(reader.result);
|
|
118
|
-
};
|
|
119
|
-
reader.readAsArrayBuffer(file);
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
export async function fileToImage(file) {
|
|
123
|
-
return new Promise((resolve, reject) => {
|
|
124
|
-
const reader = new FileReader();
|
|
125
|
-
reader.onloadend = () => {
|
|
126
|
-
var imgObj = new Image();
|
|
127
|
-
imgObj.src = reader.result;
|
|
128
|
-
imgObj.onload = () => {
|
|
129
|
-
resolve(imgObj);
|
|
130
|
-
};
|
|
131
|
-
};
|
|
132
|
-
reader.readAsDataURL(file);
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
export async function dataUrlToImage(base64) {
|
|
136
|
-
return new Promise((resolve, reject) => {
|
|
137
|
-
var imgObj = new Image();
|
|
138
|
-
imgObj.src = base64;
|
|
139
|
-
imgObj.onload = () => {
|
|
140
|
-
resolve(imgObj);
|
|
141
|
-
};
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
export function stripBase64(data) {
|
|
145
|
-
if (data) {
|
|
146
|
-
return data.split(',')[1];
|
|
38
|
+
export function stripDataUrl(dataUrl) {
|
|
39
|
+
if (typeof dataUrl === 'string' && dataUrl.startsWith('data:')) {
|
|
40
|
+
return dataUrl.split(',')[1] || '';
|
|
147
41
|
}
|
|
148
|
-
return
|
|
42
|
+
return dataUrl;
|
|
149
43
|
}
|
|
150
44
|
/**
|
|
151
45
|
* Function to download content from a given URL and convert it to a Base64-encoded string.
|
|
152
46
|
* @param url - The URL to download the content from.
|
|
153
47
|
* @returns A promise that resolves to the Base64-encoded string of the downloaded content.
|
|
154
48
|
*/
|
|
155
|
-
export async function
|
|
49
|
+
export async function readUrlAsBase64(url) {
|
|
156
50
|
try {
|
|
157
51
|
const response = await fetch(url);
|
|
158
52
|
if (!response.ok) {
|
|
@@ -168,232 +62,358 @@ export async function urlToBase64(url) {
|
|
|
168
62
|
throw error;
|
|
169
63
|
}
|
|
170
64
|
}
|
|
171
|
-
|
|
172
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Validates if a given string is a valid email address.
|
|
67
|
+
*
|
|
68
|
+
* This function uses a regular expression to validate email addresses based on common patterns.
|
|
69
|
+
*
|
|
70
|
+
* @param email - The email address string to validate.
|
|
71
|
+
* @returns A boolean indicating whether the email is valid.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* const isValid = isValidEmailAddress('test@example.com');
|
|
75
|
+
* console.log(isValid); // Output: true
|
|
76
|
+
*/
|
|
77
|
+
export function isValidEmailAddress(email) {
|
|
78
|
+
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
79
|
+
return emailPattern.test(email.toLowerCase());
|
|
173
80
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Validates if a given string is a valid URL.
|
|
83
|
+
*
|
|
84
|
+
* This function uses a regular expression to validate URLs based on common URL patterns.
|
|
85
|
+
*
|
|
86
|
+
* @param url - The URL string to validate.
|
|
87
|
+
* @returns A boolean indicating whether the URL is valid.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* const isValid = isValidUrl('https://www.example.com');
|
|
91
|
+
* console.log(isValid); // Output: true
|
|
92
|
+
*/
|
|
93
|
+
export function isValidUrl(url) {
|
|
94
|
+
const urlPattern = new RegExp('^(https?:\\/\\/)?' + // Protocol
|
|
95
|
+
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // Domain name
|
|
96
|
+
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR IP (v4) address
|
|
97
|
+
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // Port and path
|
|
98
|
+
'(\\?[;&a-z\\d%_.~+=-]*)?' + // Query string
|
|
99
|
+
'(\\#[-a-z\\d_]*)?$', 'i'); // Fragment locator
|
|
100
|
+
return urlPattern.test(url);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Creates a mailto URI and opens it in the user's default email client.
|
|
104
|
+
*
|
|
105
|
+
* This function constructs a mailto URI based on the provided email details and opens it using `window.open`.
|
|
106
|
+
* It supports specifying the recipient, subject, and body of the email.
|
|
107
|
+
*
|
|
108
|
+
* @param param - An object containing the email details:
|
|
109
|
+
* - `to`: The recipient email address.
|
|
110
|
+
* - `body`: Optional. The body content of the email.
|
|
111
|
+
* - `subject`: Optional. The subject of the email.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* // Create a mailto link with recipient, subject, and body
|
|
115
|
+
* createMailtoLink({
|
|
116
|
+
* to: 'recipient@example.com',
|
|
117
|
+
* subject: 'Hello',
|
|
118
|
+
* body: 'This is a sample email message.'
|
|
119
|
+
* });
|
|
120
|
+
*/
|
|
121
|
+
export function createMailtoLink({ to, body = '', subject = '' }) {
|
|
122
|
+
const mailtoUri = `mailto:${encodeURIComponent(to)}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
|
123
|
+
window.open(mailtoUri, '_self');
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Copies the provided text or HTML content to the clipboard.
|
|
127
|
+
*
|
|
128
|
+
* This function handles copying both plain text and rich text (HTML) content.
|
|
129
|
+
* It uses the Clipboard API where available and falls back to older methods for unsupported browsers.
|
|
130
|
+
*
|
|
131
|
+
* @param content - The content to be copied to the clipboard. It can be either a string (plain text) or an HTMLElement (rich text).
|
|
132
|
+
* @returns A promise that resolves to `true` if the copy operation is successful, or `false` otherwise.
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* // Copy plain text to clipboard
|
|
136
|
+
* copyToClipboard('Hello, World!').then((success) => {
|
|
137
|
+
* console.log(success ? 'Copied successfully!' : 'Failed to copy.');
|
|
138
|
+
* });
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* // Copy rich text (HTML element) to clipboard
|
|
142
|
+
* const element = document.getElementById('myElement');
|
|
143
|
+
* if (element) {
|
|
144
|
+
* copyToClipboard(element).then((success) => {
|
|
145
|
+
* console.log(success ? 'Copied successfully!' : 'Failed to copy.');
|
|
146
|
+
* });
|
|
147
|
+
* }
|
|
148
|
+
*/
|
|
149
|
+
export async function copyToClipboard(content) {
|
|
150
|
+
try {
|
|
151
|
+
// If content is a string, attempt to copy it using the Clipboard API
|
|
152
|
+
if (typeof content === 'string') {
|
|
153
|
+
if (navigator.clipboard) {
|
|
154
|
+
await navigator.clipboard.writeText(content);
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
// Fallback for older browsers
|
|
159
|
+
const textarea = document.createElement('textarea');
|
|
160
|
+
textarea.value = content;
|
|
161
|
+
textarea.setAttribute('readonly', '');
|
|
162
|
+
textarea.style.position = 'absolute';
|
|
163
|
+
textarea.style.left = '-9999px';
|
|
164
|
+
document.body.appendChild(textarea);
|
|
165
|
+
textarea.select();
|
|
166
|
+
textarea.setSelectionRange(0, 99999); // For mobile devices
|
|
167
|
+
const successful = document.execCommand('copy');
|
|
168
|
+
document.body.removeChild(textarea);
|
|
169
|
+
return successful;
|
|
185
170
|
}
|
|
186
171
|
}
|
|
187
|
-
//
|
|
188
|
-
if (
|
|
189
|
-
const
|
|
190
|
-
|
|
172
|
+
// If content is an HTML element, copy its contents as rich text
|
|
173
|
+
if (content instanceof HTMLElement) {
|
|
174
|
+
const range = document.createRange();
|
|
175
|
+
range.selectNodeContents(content);
|
|
176
|
+
const selection = window.getSelection();
|
|
177
|
+
if (!selection)
|
|
178
|
+
return false;
|
|
179
|
+
selection.removeAllRanges();
|
|
180
|
+
selection.addRange(range);
|
|
181
|
+
// Execute the copy command
|
|
182
|
+
const successful = document.execCommand('copy');
|
|
183
|
+
selection.removeAllRanges();
|
|
184
|
+
return successful;
|
|
191
185
|
}
|
|
192
|
-
|
|
193
|
-
const mimeType = res.headers.get('Content-Type') || '';
|
|
194
|
-
const buffer = await res.arrayBuffer();
|
|
195
|
-
return { buffer, fileName, mimeType };
|
|
196
|
-
})
|
|
197
|
-
.then(({ buffer, fileName, mimeType }) => {
|
|
198
|
-
return new File([buffer], givenFileName || fileName, {
|
|
199
|
-
type: givenMimeType || mimeType
|
|
200
|
-
});
|
|
201
|
-
}));
|
|
202
|
-
}
|
|
203
|
-
export async function bufferToFile(buffer, filename, mimeType) {
|
|
204
|
-
return new File([buffer], filename, {
|
|
205
|
-
type: mimeType
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
export async function postData(url = '', data = {}) {
|
|
209
|
-
// Default options are marked with *
|
|
210
|
-
const response = await fetch(url, {
|
|
211
|
-
method: 'POST', // *GET, POST, PUT, DELETE, etc.
|
|
212
|
-
mode: 'cors', // no-cors, *cors, same-origin
|
|
213
|
-
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
|
|
214
|
-
credentials: 'same-origin', // include, *same-origin, omit
|
|
215
|
-
headers: {
|
|
216
|
-
'Content-Type': 'application/json'
|
|
217
|
-
// 'Content-Type': 'application/x-www-form-urlencoded',
|
|
218
|
-
},
|
|
219
|
-
redirect: 'follow', // manual, *follow, error
|
|
220
|
-
referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
|
|
221
|
-
body: JSON.stringify(data) // body data type must match "Content-Type" header
|
|
222
|
-
});
|
|
223
|
-
return response.json(); // parses JSON response into native JavaScript objects
|
|
224
|
-
}
|
|
225
|
-
export function fileNameAndExt(filename) {
|
|
226
|
-
let arr = (filename || '').split('.');
|
|
227
|
-
let ext = arr.pop();
|
|
228
|
-
let name = arr.join('.');
|
|
229
|
-
return { name, ext };
|
|
230
|
-
}
|
|
231
|
-
export function isValidateEmail(email) {
|
|
232
|
-
const reg = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
233
|
-
return reg.test(String(email).toLowerCase());
|
|
234
|
-
}
|
|
235
|
-
export function isValidURL(str) {
|
|
236
|
-
var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
|
|
237
|
-
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
|
|
238
|
-
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
|
|
239
|
-
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
|
|
240
|
-
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
|
|
241
|
-
'(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
|
|
242
|
-
return !!pattern.test(str);
|
|
243
|
-
}
|
|
244
|
-
export function mailto({ to, body = '', subject = '' }) {
|
|
245
|
-
var uri = `mailto:${to || ''}?subject=${encodeURIComponent(subject || '')}&body=${encodeURIComponent(body || '')}`;
|
|
246
|
-
window.open(uri);
|
|
247
|
-
}
|
|
248
|
-
export function copyText(str) {
|
|
249
|
-
const el = document.createElement('textarea');
|
|
250
|
-
el.value = str;
|
|
251
|
-
el.setAttribute('readonly', '');
|
|
252
|
-
el.style.position = 'absolute';
|
|
253
|
-
el.style.left = '-9999px';
|
|
254
|
-
document.body.appendChild(el);
|
|
255
|
-
el.select();
|
|
256
|
-
el.setSelectionRange(0, 99999); /* For mobile devices */
|
|
257
|
-
if (navigator.clipboard) {
|
|
258
|
-
navigator.clipboard.writeText(str);
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
document.execCommand('copy', false);
|
|
186
|
+
return false; // Unsupported content type
|
|
262
187
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
;
|
|
266
|
-
export function copyRichText(node) {
|
|
267
|
-
if (BROWSER) {
|
|
268
|
-
let r = document.createRange();
|
|
269
|
-
r.selectNode(node);
|
|
270
|
-
window.getSelection().removeAllRanges();
|
|
271
|
-
window.getSelection().addRange(r);
|
|
272
|
-
document.execCommand("copy");
|
|
273
|
-
window.getSelection().removeAllRanges();
|
|
188
|
+
catch (error) {
|
|
189
|
+
console.error('Failed to copy content to clipboard:', error);
|
|
190
|
+
return false;
|
|
274
191
|
}
|
|
275
192
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
193
|
+
/**
|
|
194
|
+
* Formats a string by replacing placeholders `{index}` with corresponding arguments.
|
|
195
|
+
*
|
|
196
|
+
* This function replaces placeholders in the format `{0}`, `{1}`, etc., in the provided string
|
|
197
|
+
* with the corresponding values from the `args` array.
|
|
198
|
+
*
|
|
199
|
+
* @param str - The string containing placeholders.
|
|
200
|
+
* @param args - The values to replace the placeholders with.
|
|
201
|
+
* @returns A formatted string with the placeholders replaced by the corresponding arguments.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* const formatted = formatString('Hello, {0}!', 'World');
|
|
205
|
+
* console.log(formatted); // Output: "Hello, World!"
|
|
206
|
+
*/
|
|
285
207
|
export function formatString(str, ...args) {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
return formatted;
|
|
208
|
+
return args.reduce((formatted, arg, index) => {
|
|
209
|
+
const regexp = new RegExp(`\\{${index}\\}`, 'g');
|
|
210
|
+
return formatted.replace(regexp, arg);
|
|
211
|
+
}, str);
|
|
292
212
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
213
|
+
/**
|
|
214
|
+
* Delays the execution of code for a specified number of milliseconds.
|
|
215
|
+
*
|
|
216
|
+
* This function returns a promise that resolves after the specified delay.
|
|
217
|
+
*
|
|
218
|
+
* @param milliseconds - The number of milliseconds to wait before resolving the promise. Default is 0.
|
|
219
|
+
* @returns A promise that resolves after the specified delay.
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* delay(1000).then(() => console.log('1 second later'));
|
|
223
|
+
*/
|
|
224
|
+
export function delay(milliseconds = 0) {
|
|
225
|
+
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
303
226
|
}
|
|
304
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Sorts an array of objects or values based on a specified field or value.
|
|
229
|
+
*
|
|
230
|
+
* This function sorts an array of objects based on a specified field or directly sorts an array of values.
|
|
231
|
+
* It supports both ascending and descending orders and can handle date values.
|
|
232
|
+
*
|
|
233
|
+
* @typeParam T - The type of elements in the array.
|
|
234
|
+
* @param param - An object containing the array to sort, the field to sort by (optional),
|
|
235
|
+
* whether to sort in descending order, and whether to sort as date values.
|
|
236
|
+
* @param param.array - The array of objects or values to sort.
|
|
237
|
+
* @param param.field - Optional. The field of the objects to sort by.
|
|
238
|
+
* @param param.desc - Optional. If true, sorts in descending order. Default is false (ascending).
|
|
239
|
+
* @param param.isDate - Optional. If true, sorts the values as dates.
|
|
240
|
+
* @returns The sorted array.
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* const arr = [{ name: 'Alice' }, { name: 'Bob' }];
|
|
244
|
+
* const sortedArr = sort({ array: arr, field: 'name', desc: true });
|
|
245
|
+
* console.log(sortedArr); // Output: [{ name: 'Bob' }, { name: 'Alice' }]
|
|
246
|
+
*/
|
|
247
|
+
export function sort({ array, field, desc = false, isDate = false }) {
|
|
305
248
|
return array.sort((a, b) => {
|
|
306
|
-
let valA =
|
|
307
|
-
let valB =
|
|
249
|
+
let valA = field ? a[field] : a;
|
|
250
|
+
let valB = field ? b[field] : b;
|
|
251
|
+
// Convert to Date objects if sorting by date
|
|
308
252
|
if (isDate) {
|
|
309
253
|
valA = toDate(valA);
|
|
310
254
|
valB = toDate(valB);
|
|
311
255
|
}
|
|
312
256
|
else {
|
|
313
|
-
//
|
|
257
|
+
// Convert to lowercase for case-insensitive string comparison
|
|
314
258
|
if (typeof valA === 'string')
|
|
315
259
|
valA = valA.toLowerCase();
|
|
316
260
|
if (typeof valB === 'string')
|
|
317
261
|
valB = valB.toLowerCase();
|
|
318
262
|
}
|
|
319
|
-
|
|
263
|
+
// Perform comparison and adjust for descending order if specified
|
|
264
|
+
if (valA < valB)
|
|
320
265
|
return desc ? 1 : -1;
|
|
321
|
-
|
|
322
|
-
else if (valA > valB) {
|
|
266
|
+
if (valA > valB)
|
|
323
267
|
return desc ? -1 : 1;
|
|
324
|
-
}
|
|
325
268
|
return 0;
|
|
326
269
|
});
|
|
327
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Triggers a vibration effect on supported devices.
|
|
273
|
+
*
|
|
274
|
+
* This function uses the Vibration API to trigger a vibration effect. If the Vibration API is not
|
|
275
|
+
* supported or if permissions are not granted, the function will have no effect.
|
|
276
|
+
*
|
|
277
|
+
* @param value - A single number representing the duration of the vibration in milliseconds, or
|
|
278
|
+
* an array of numbers representing vibration patterns.
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* // Single vibration for 200 milliseconds
|
|
282
|
+
* vibrate(200);
|
|
283
|
+
*
|
|
284
|
+
* @example
|
|
285
|
+
* // Vibration pattern: 200ms on, 100ms off, 200ms on
|
|
286
|
+
* vibrate([200, 100, 200]);
|
|
287
|
+
*/
|
|
328
288
|
export function vibrate(value = 20) {
|
|
329
|
-
if (
|
|
330
|
-
|
|
289
|
+
if (navigator?.vibrate) {
|
|
290
|
+
navigator.vibrate(value);
|
|
331
291
|
}
|
|
332
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Plays a simple click effect using the vibration API (if supported).
|
|
295
|
+
*
|
|
296
|
+
* This function triggers a short vibration effect to simulate a click or feedback action on devices
|
|
297
|
+
* that support the Vibration API.
|
|
298
|
+
*
|
|
299
|
+
* @example
|
|
300
|
+
* playClickEffect(); // Triggers a short vibration effect.
|
|
301
|
+
*/
|
|
333
302
|
export function playClickEffect() {
|
|
334
|
-
vibrate();
|
|
303
|
+
vibrate(20);
|
|
335
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* Converts an object into an array of its values, attaching a specified key to each value.
|
|
307
|
+
*
|
|
308
|
+
* This function takes an object and converts it into an array of its values, where each value is
|
|
309
|
+
* augmented with a new property specified by the `key` parameter. The property is set to the key
|
|
310
|
+
* of the original object.
|
|
311
|
+
*
|
|
312
|
+
* @param key - The property name to attach to each value.
|
|
313
|
+
* @param obj - The object to be converted to an array.
|
|
314
|
+
* @returns An array of values with the specified key attached.
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* const obj = { a: { name: 'Alice' }, b: { name: 'Bob' } };
|
|
318
|
+
* const array = toArrayByKey('id', obj);
|
|
319
|
+
* console.log(array); // Output: [{ name: 'Alice', id: 'a' }, { name: 'Bob', id: 'b' }]
|
|
320
|
+
*/
|
|
336
321
|
export function toArrayByKey(key, obj = {}) {
|
|
337
|
-
return Object.keys(obj)
|
|
338
|
-
|
|
322
|
+
return Object.keys(obj)
|
|
323
|
+
.map((k) => {
|
|
324
|
+
const data = obj[k];
|
|
339
325
|
if (data) {
|
|
340
326
|
data[key] = k;
|
|
341
327
|
}
|
|
342
328
|
return data;
|
|
343
|
-
})
|
|
344
|
-
|
|
345
|
-
export function convertNumToAlphabates(num) {
|
|
346
|
-
let alphabates = 'abcdefghij'.split('');
|
|
347
|
-
let numArray = num.toString().split('').map((o) => parseInt(o));
|
|
348
|
-
return numArray.map((i) => alphabates[i]).join('');
|
|
329
|
+
})
|
|
330
|
+
.filter((item) => item !== undefined);
|
|
349
331
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
332
|
+
/**
|
|
333
|
+
* Converts a numeric string into its corresponding alphabets (0-9 => a-j).
|
|
334
|
+
*
|
|
335
|
+
* This function maps each digit in the provided number to its corresponding alphabet:
|
|
336
|
+
* - 0 => a, 1 => b, 2 => c, ... , 9 => j.
|
|
337
|
+
*
|
|
338
|
+
* @param num - The number to be converted to a string of alphabets.
|
|
339
|
+
* @returns A string representing the number converted to alphabets.
|
|
340
|
+
*
|
|
341
|
+
* @example
|
|
342
|
+
* const result = convertNumToAlphabets(123); // "bcd"
|
|
343
|
+
* console.log(result); // Output: "bcd"
|
|
344
|
+
*/
|
|
345
|
+
export function convertNumToAlphabets(num) {
|
|
346
|
+
const alphabets = 'abcdefghij';
|
|
347
|
+
return num
|
|
348
|
+
.toString()
|
|
349
|
+
.split('')
|
|
350
|
+
.map((digit) => alphabets[parseInt(digit, 10)] || '')
|
|
351
|
+
.join('');
|
|
355
352
|
}
|
|
353
|
+
/**
|
|
354
|
+
* Converts a number to a currency-formatted string.
|
|
355
|
+
*
|
|
356
|
+
* This function formats a given number as a currency string, using a specified currency symbol
|
|
357
|
+
* (default is '$'). It handles negative values by adding a '-' sign in front of the formatted value.
|
|
358
|
+
*
|
|
359
|
+
* @param value - The numeric value to format as currency.
|
|
360
|
+
* @param symbol - The currency symbol to use. Default is '$'.
|
|
361
|
+
* @returns A formatted string representing the currency value.
|
|
362
|
+
*
|
|
363
|
+
* @example
|
|
364
|
+
* const formattedValue = toCurrency(1234.56, '$');
|
|
365
|
+
* console.log(formattedValue); // Output: "$ 1234.56"
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
368
|
+
* const formattedNegative = toCurrency(-1234.56, '€');
|
|
369
|
+
* console.log(formattedNegative); // Output: "- € 1234.56"
|
|
370
|
+
*/
|
|
356
371
|
export function toCurrency(value = 0, symbol = '$') {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
result += '- ';
|
|
361
|
-
}
|
|
362
|
-
if (symbol) {
|
|
363
|
-
result += `${symbol} `;
|
|
364
|
-
}
|
|
365
|
-
result += currency.toFixed(2);
|
|
366
|
-
return result;
|
|
372
|
+
const isNegative = value < 0;
|
|
373
|
+
const currencyValue = Math.abs(value).toFixed(2);
|
|
374
|
+
return `${isNegative ? '- ' : ''}${symbol} ${currencyValue}`;
|
|
367
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Converts a length in inches to pixels based on a DPI of 96.
|
|
378
|
+
*
|
|
379
|
+
* This function converts inches to pixels assuming a screen DPI (Dots Per Inch) of 96.
|
|
380
|
+
* It is useful for calculating dimensions in pixels when working with different units of measurement.
|
|
381
|
+
*
|
|
382
|
+
* @param inches - The length in inches to be converted to pixels.
|
|
383
|
+
* @returns The length in pixels corresponding to the provided inches.
|
|
384
|
+
*
|
|
385
|
+
* @throws An error if the input is not a valid number or is negative.
|
|
386
|
+
*
|
|
387
|
+
* @example
|
|
388
|
+
* const pixels = inchToPixel(1); // 1 inch to pixels
|
|
389
|
+
* console.log(pixels); // Output: 96
|
|
390
|
+
*/
|
|
368
391
|
export function inchToPixel(inches) {
|
|
369
|
-
|
|
392
|
+
if (typeof inches !== 'number' || isNaN(inches) || inches < 0) {
|
|
393
|
+
throw new Error('Invalid input: Inches must be a non-negative number.');
|
|
394
|
+
}
|
|
395
|
+
const DPI = 96; // Default DPI for screen resolution
|
|
396
|
+
return inches * DPI;
|
|
370
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* Converts a length in pixels to inches based on a DPI of 96.
|
|
400
|
+
*
|
|
401
|
+
* This function converts pixels to inches assuming a screen DPI (Dots Per Inch) of 96.
|
|
402
|
+
* It is useful for converting pixel measurements to physical dimensions.
|
|
403
|
+
*
|
|
404
|
+
* @param pixels - The length in pixels to be converted to inches.
|
|
405
|
+
* @returns The length in inches corresponding to the provided pixels.
|
|
406
|
+
*
|
|
407
|
+
* @throws An error if the input is not a valid number or is negative.
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* const inches = pixelToInch(96); // 96 pixels to inches
|
|
411
|
+
* console.log(inches); // Output: 1
|
|
412
|
+
*/
|
|
371
413
|
export function pixelToInch(pixels) {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
return res;
|
|
378
|
-
}
|
|
379
|
-
export function colorToHex(color) {
|
|
380
|
-
// Create a temporary div element to use its computed style
|
|
381
|
-
const tempDiv = document.createElement("div");
|
|
382
|
-
tempDiv.style.color = color;
|
|
383
|
-
document.body.appendChild(tempDiv);
|
|
384
|
-
// Get the computed color from the div element
|
|
385
|
-
const computedColor = window.getComputedStyle(tempDiv).color;
|
|
386
|
-
document.body.removeChild(tempDiv);
|
|
387
|
-
// Convert the computed color to RGB values
|
|
388
|
-
const rgb = computedColor.match(/\d+/g).map(Number);
|
|
389
|
-
// Convert RGB values to a 6-character hex color
|
|
390
|
-
const hexColor = rgbToHex(rgb[0], rgb[1], rgb[2]);
|
|
391
|
-
return hexColor;
|
|
392
|
-
}
|
|
393
|
-
export function rgbToHex(r, g, b) {
|
|
394
|
-
return ("#" +
|
|
395
|
-
[r, g, b]
|
|
396
|
-
.map((x) => x.toString(16).padStart(2, "0")) // Convert to hex and ensure two characters
|
|
397
|
-
.join("")
|
|
398
|
-
.toUpperCase());
|
|
414
|
+
if (typeof pixels !== 'number' || isNaN(pixels) || pixels < 0) {
|
|
415
|
+
throw new Error('Invalid input: Pixels must be a non-negative number.');
|
|
416
|
+
}
|
|
417
|
+
const DPI = 96; // Default DPI for screen resolution
|
|
418
|
+
return pixels / DPI;
|
|
399
419
|
}
|