@cloudparker/moldex.js 0.0.83 → 0.0.85
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 +20 -4
- package/dist/services/dialog/dialog-service.js +44 -12
- package/dist/services/screen/screen-service.d.ts +2 -0
- package/dist/services/screen/screen-service.js +4 -0
- package/dist/services/utils/file-service.d.ts +3 -1
- package/dist/services/utils/file-service.js +50 -7
- package/dist/services/utils/image-service.d.ts +28 -2
- package/dist/services/utils/image-service.js +72 -6
- package/dist/services/utils/utils-service.d.ts +2 -0
- package/dist/services/utils/utils-service.js +8 -0
- package/dist/views/core/dialog/components/cropper-dialog/cropper-dialog.svelte +11 -3
- package/dist/views/core/dialog/components/cropper-dialog/cropper-dialog.svelte.d.ts +2 -1
- package/dist/views/core/dialog/components/dialog/dialog.svelte +2 -2
- package/dist/views/core/dialog/components/dialog/dialog.svelte.d.ts +2 -1
- package/package.json +1 -1
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
import { type DialogProps, type InputFieldProps } from '../../views';
|
|
1
|
+
import { type DialogProps, type DialogSize, type InputFieldProps } from '../../views';
|
|
2
2
|
import { type CropperDialogPropsType } from '../../views/core/dialog/components/cropper-dialog/cropper-dialog.svelte';
|
|
3
3
|
import type { PickerDialogProps } from '../../views/core/dialog/components/picker-dialog/picker-dialog.svelte';
|
|
4
|
+
import { type ImageCapttures, type OutputImageFormats } from '../utils/image-service';
|
|
5
|
+
export declare enum DialogSizeEnum {
|
|
6
|
+
XS = "xs",
|
|
7
|
+
SM = "sm",
|
|
8
|
+
MD = "md",
|
|
9
|
+
LG = "lg",
|
|
10
|
+
XL = "xl",
|
|
11
|
+
FULL = "full"
|
|
12
|
+
}
|
|
4
13
|
export type PickerDialogPropsType = {
|
|
5
14
|
items?: any[];
|
|
6
15
|
itemTitle?: string;
|
|
@@ -65,7 +74,7 @@ export declare function openLoadingDialog({ msg, loadingDialogContainerClassName
|
|
|
65
74
|
* @param props
|
|
66
75
|
* @returns
|
|
67
76
|
*/
|
|
68
|
-
export declare function openCropperDialog<T, R>({ outputWidth, outputFormat, outputQuality, outputType, inputImageFile, className, ...params }: DialogProps & CropperDialogPropsType): Promise<R | string | File>;
|
|
77
|
+
export declare function openCropperDialog<T, R>({ outputWidth, outputFormat, outputQuality, outputType, inputImageFile, className, outputAspectRatio, ...params }: DialogProps & CropperDialogPropsType): Promise<R | string | File>;
|
|
69
78
|
/**
|
|
70
79
|
* Opens a file picker dialog and returns the selected file or files.
|
|
71
80
|
* This function uses native browser APIs to ensure compatibility across different browsers.
|
|
@@ -85,10 +94,17 @@ export declare function openFilePickerDialog<T extends File | File[]>(accepts?:
|
|
|
85
94
|
*/
|
|
86
95
|
export declare function openImagePickerDialog<T extends File | File[]>(accepts?: string | string[], options?: {
|
|
87
96
|
multiple?: boolean;
|
|
88
|
-
capture?:
|
|
97
|
+
capture?: ImageCapttures;
|
|
89
98
|
maxWidth?: number;
|
|
90
99
|
maxHeight?: number;
|
|
91
100
|
maxSizeInBytes?: number;
|
|
92
|
-
outputFormat?:
|
|
101
|
+
outputFormat?: OutputImageFormats;
|
|
93
102
|
quality?: number;
|
|
94
103
|
}): Promise<T | null>;
|
|
104
|
+
export declare function openImagePickerDialogWithCropper({ outputFormat, outputWidth, outputQuality, outputAspectRatio, dialogSize, }?: {
|
|
105
|
+
outputFormat?: OutputImageFormats;
|
|
106
|
+
outputWidth?: number;
|
|
107
|
+
outputQuality?: number;
|
|
108
|
+
outputAspectRatio?: number;
|
|
109
|
+
dialogSize?: DialogSize;
|
|
110
|
+
}): Promise<File | null>;
|
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
import { Dialog } from '../../views';
|
|
2
|
+
import CropperDialog, {} from '../../views/core/dialog/components/cropper-dialog/cropper-dialog.svelte';
|
|
2
3
|
import LoadingDialog from '../../views/core/dialog/components/loading-dialog/loading-dialog.svelte';
|
|
3
4
|
import MsgDialog from '../../views/core/dialog/components/msg-dialog/msg-dialog.svelte';
|
|
5
|
+
import NumberFieldDialog from '../../views/core/dialog/components/number-field-dialog/number-field-dialog.svelte';
|
|
6
|
+
import PickerDialog from '../../views/core/dialog/components/picker-dialog/picker-dialog.svelte';
|
|
4
7
|
import TextFieldDialog from '../../views/core/dialog/components/text-field-dialog/text-field-dialog.svelte';
|
|
5
8
|
import TextareaFieldDialog from '../../views/core/dialog/components/textarea-field-dialog/textarea-field-dialog.svelte';
|
|
6
|
-
import {
|
|
7
|
-
import { isMobileScreen } from '../screen/screen-service';
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
import { mount } from 'svelte';
|
|
10
|
+
import { getDialogSize, isMobileScreen } from '../screen/screen-service';
|
|
11
|
+
import { cropImageFile, FilePickerAccepts, OutputImageFormatEnum, processImageFile } from '../utils/image-service';
|
|
12
|
+
export var DialogSizeEnum;
|
|
13
|
+
(function (DialogSizeEnum) {
|
|
14
|
+
DialogSizeEnum["XS"] = "xs";
|
|
15
|
+
DialogSizeEnum["SM"] = "sm";
|
|
16
|
+
DialogSizeEnum["MD"] = "md";
|
|
17
|
+
DialogSizeEnum["LG"] = "lg";
|
|
18
|
+
DialogSizeEnum["XL"] = "xl";
|
|
19
|
+
DialogSizeEnum["FULL"] = "full";
|
|
20
|
+
})(DialogSizeEnum || (DialogSizeEnum = {}));
|
|
12
21
|
function addDialog(props) {
|
|
13
22
|
const dialog = mount(Dialog, { target: document.getElementsByTagName('body')[0], props });
|
|
14
23
|
return dialog;
|
|
@@ -113,7 +122,7 @@ export async function openNumberFieldDialog({ title, value, label, name, maxleng
|
|
|
113
122
|
hasHeader: true,
|
|
114
123
|
hasHeaderBack: isMobileScreen(),
|
|
115
124
|
hasHeaderClose: !isMobileScreen(),
|
|
116
|
-
size:
|
|
125
|
+
size: getDialogSize(),
|
|
117
126
|
hasTitle: true,
|
|
118
127
|
title: title || 'Prompt',
|
|
119
128
|
hasFooter: true,
|
|
@@ -131,7 +140,7 @@ export async function openTextFieldDialog({ title, value, label, name, maxlength
|
|
|
131
140
|
hasHeader: true,
|
|
132
141
|
hasHeaderBack: isMobileScreen(),
|
|
133
142
|
hasHeaderClose: !isMobileScreen(),
|
|
134
|
-
size:
|
|
143
|
+
size: getDialogSize(),
|
|
135
144
|
hasTitle: true,
|
|
136
145
|
title: title || 'Prompt',
|
|
137
146
|
hasFooter: true,
|
|
@@ -149,7 +158,7 @@ export async function openTextareaFieldDialog({ title, value, label, name, maxle
|
|
|
149
158
|
hasHeader: true,
|
|
150
159
|
hasHeaderBack: isMobileScreen(),
|
|
151
160
|
hasHeaderClose: !isMobileScreen(),
|
|
152
|
-
size: isMobileScreen() ?
|
|
161
|
+
size: isMobileScreen() ? DialogSizeEnum.FULL : DialogSizeEnum.SM,
|
|
153
162
|
hasTitle: true,
|
|
154
163
|
title: title || 'Prompt',
|
|
155
164
|
hasFooter: true,
|
|
@@ -176,7 +185,7 @@ export async function openLoadingDialog({ msg = "Please wait...", loadingDialogC
|
|
|
176
185
|
* @param props
|
|
177
186
|
* @returns
|
|
178
187
|
*/
|
|
179
|
-
export async function openCropperDialog({ outputWidth, outputFormat =
|
|
188
|
+
export async function openCropperDialog({ outputWidth, outputFormat = OutputImageFormatEnum.WEBP, outputQuality = 0.8, outputType = 'file', inputImageFile, className, outputAspectRatio, ...params }) {
|
|
180
189
|
return await openDialog({
|
|
181
190
|
bodyComponent: CropperDialog,
|
|
182
191
|
props: {
|
|
@@ -186,6 +195,7 @@ export async function openCropperDialog({ outputWidth, outputFormat = 'webp', ou
|
|
|
186
195
|
outputType,
|
|
187
196
|
inputImageFile,
|
|
188
197
|
className,
|
|
198
|
+
outputAspectRatio,
|
|
189
199
|
},
|
|
190
200
|
...params,
|
|
191
201
|
hasHeader: true,
|
|
@@ -197,7 +207,7 @@ export async function openCropperDialog({ outputWidth, outputFormat = 'webp', ou
|
|
|
197
207
|
title: params.title || 'Crop Image',
|
|
198
208
|
hasHeaderBack: isMobileScreen(),
|
|
199
209
|
hasHeaderClose: !isMobileScreen(),
|
|
200
|
-
size:
|
|
210
|
+
size: getDialogSize(),
|
|
201
211
|
});
|
|
202
212
|
}
|
|
203
213
|
/**
|
|
@@ -264,9 +274,25 @@ export async function openFilePickerDialog(accepts = '*/*', options = { multiple
|
|
|
264
274
|
* @param options - Additional options for capturing images (e.g., required resolution, file size, output format).
|
|
265
275
|
* @returns A promise that resolves to a processed File object or an array of File objects, or null if no file was selected.
|
|
266
276
|
*/
|
|
267
|
-
export async function openImagePickerDialog(accepts = 'image/*', options) {
|
|
277
|
+
export async function openImagePickerDialog(accepts = 'image/*', options = {}) {
|
|
268
278
|
return new Promise((resolve, reject) => {
|
|
269
279
|
try {
|
|
280
|
+
options = options || {};
|
|
281
|
+
if (!options.maxWidth) {
|
|
282
|
+
options.maxWidth = 1920;
|
|
283
|
+
}
|
|
284
|
+
if (!options.maxHeight) {
|
|
285
|
+
options.maxHeight = options.maxWidth;
|
|
286
|
+
}
|
|
287
|
+
if (!options.quality || options.quality < 0) {
|
|
288
|
+
options.quality = 0.8;
|
|
289
|
+
}
|
|
290
|
+
if (options.quality > 1) {
|
|
291
|
+
options.quality = options.quality / 100;
|
|
292
|
+
}
|
|
293
|
+
if (options.outputFormat) {
|
|
294
|
+
options.outputFormat = OutputImageFormatEnum.WEBP;
|
|
295
|
+
}
|
|
270
296
|
// Create an input element of type 'file'
|
|
271
297
|
const inputElement = document.createElement('input');
|
|
272
298
|
inputElement.type = 'file';
|
|
@@ -309,3 +335,9 @@ export async function openImagePickerDialog(accepts = 'image/*', options) {
|
|
|
309
335
|
}
|
|
310
336
|
});
|
|
311
337
|
}
|
|
338
|
+
export async function openImagePickerDialogWithCropper({ outputFormat = OutputImageFormatEnum.WEBP, outputWidth = 800, outputQuality = 0.6, outputAspectRatio = 1, dialogSize = DialogSizeEnum.MD, } = {}) {
|
|
339
|
+
const file = (await openFilePickerDialog(FilePickerAccepts.image));
|
|
340
|
+
let croppedFile = await cropImageFile({ inputImageFile: file, outputFormat, outputWidth, outputQuality, outputAspectRatio, dialogSize });
|
|
341
|
+
return croppedFile;
|
|
342
|
+
}
|
|
343
|
+
;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ScreenSizeEnum } from "../../stores/screen-size/screen-size-store.svelte";
|
|
2
|
+
import { DialogSizeEnum } from "../dialog/dialog-service";
|
|
2
3
|
export declare const screenSize: {
|
|
3
4
|
size: ScreenSizeEnum;
|
|
4
5
|
readonly isXXL: boolean;
|
|
@@ -11,4 +12,5 @@ export declare const screenSize: {
|
|
|
11
12
|
export declare const handleScreenSizeUpdate: (size: number) => void;
|
|
12
13
|
export declare function isSmallScreen(): boolean;
|
|
13
14
|
export declare function isMobileScreen(): boolean;
|
|
15
|
+
export declare function getDialogSize(): DialogSizeEnum.SM | DialogSizeEnum.FULL;
|
|
14
16
|
export declare function isTouchDevice(): boolean;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createScreenSizeStore, ScreenSizeEnum } from "../../stores/screen-size/screen-size-store.svelte";
|
|
2
2
|
import { BROWSER } from "esm-env";
|
|
3
|
+
import { DialogSizeEnum } from "../dialog/dialog-service";
|
|
3
4
|
export const screenSize = createScreenSizeStore();
|
|
4
5
|
export const handleScreenSizeUpdate = (size) => {
|
|
5
6
|
// console.log('screenSizeChanged', size)
|
|
@@ -30,6 +31,9 @@ export function isSmallScreen() {
|
|
|
30
31
|
export function isMobileScreen() {
|
|
31
32
|
return isSmallScreen();
|
|
32
33
|
}
|
|
34
|
+
export function getDialogSize() {
|
|
35
|
+
return isMobileScreen() ? DialogSizeEnum.FULL : DialogSizeEnum.SM;
|
|
36
|
+
}
|
|
33
37
|
export function isTouchDevice() {
|
|
34
38
|
return 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0 || window.matchMedia("(pointer: coarse)").matches;
|
|
35
39
|
}
|
|
@@ -135,4 +135,6 @@ export declare function getFilenameExtension(filename: string): {
|
|
|
135
135
|
* const sizeString = fileSizeString(1024);
|
|
136
136
|
* console.log(sizeString); // Output: "1 kB"
|
|
137
137
|
*/
|
|
138
|
-
export declare function
|
|
138
|
+
export declare function formatFileSize(bytes?: number): string;
|
|
139
|
+
export declare function getExtFromFileType(type: string): string | null;
|
|
140
|
+
export declare function ellipsisFileNameAtCenter(name: string, sizeLimit?: number, startLength?: number, endLength?: number): string;
|
|
@@ -248,11 +248,54 @@ export function getFilenameExtension(filename) {
|
|
|
248
248
|
* const sizeString = fileSizeString(1024);
|
|
249
249
|
* console.log(sizeString); // Output: "1 kB"
|
|
250
250
|
*/
|
|
251
|
-
export function
|
|
252
|
-
if (
|
|
253
|
-
return '
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
251
|
+
export function formatFileSize(bytes = 0) {
|
|
252
|
+
if (bytes < 1024) {
|
|
253
|
+
return bytes + ' Bytes';
|
|
254
|
+
}
|
|
255
|
+
else if (bytes < 1024 * 1024) {
|
|
256
|
+
return (bytes / 1024).toFixed(2) + ' KB';
|
|
257
|
+
}
|
|
258
|
+
else if (bytes < 1024 * 1024 * 1024) {
|
|
259
|
+
return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
return (bytes / (1024 * 1024 * 1024)).toFixed(2) + ' GB';
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
export function getExtFromFileType(type) {
|
|
266
|
+
const mimeTypes = {
|
|
267
|
+
"image/jpeg": "jpg",
|
|
268
|
+
"image/png": "png",
|
|
269
|
+
"image/gif": "gif",
|
|
270
|
+
"image/webp": "webp",
|
|
271
|
+
"image/svg+xml": "svg",
|
|
272
|
+
"video/mp4": "mp4",
|
|
273
|
+
"video/webm": "webm",
|
|
274
|
+
"video/ogg": "ogv",
|
|
275
|
+
"audio/mpeg": "mp3",
|
|
276
|
+
"audio/ogg": "ogg",
|
|
277
|
+
"audio/wav": "wav",
|
|
278
|
+
"application/pdf": "pdf",
|
|
279
|
+
"application/json": "json",
|
|
280
|
+
"application/javascript": "js",
|
|
281
|
+
"text/html": "html",
|
|
282
|
+
"text/css": "css",
|
|
283
|
+
"text/plain": "txt",
|
|
284
|
+
"application/zip": "zip",
|
|
285
|
+
"application/x-rar-compressed": "rar",
|
|
286
|
+
"application/xml": "xml"
|
|
287
|
+
};
|
|
288
|
+
return mimeTypes[type] || null;
|
|
289
|
+
}
|
|
290
|
+
export function ellipsisFileNameAtCenter(name, sizeLimit = 15, startLength = 5, endLength = 3) {
|
|
291
|
+
name = name || '';
|
|
292
|
+
if (name.length > sizeLimit) {
|
|
293
|
+
name = [
|
|
294
|
+
name.substring(0, startLength),
|
|
295
|
+
'…',
|
|
296
|
+
name.substring(name.lastIndexOf('.') - endLength, name.length)
|
|
297
|
+
].join('');
|
|
298
|
+
return name;
|
|
299
|
+
}
|
|
300
|
+
return name;
|
|
258
301
|
}
|
|
@@ -1,4 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
import type { DialogSize } from "../../views";
|
|
2
|
+
export type ImageCapttures = ImageCapttureEnum.USER | ImageCapttureEnum.ENVIRONMENT;
|
|
3
|
+
export declare enum ImageCapttureEnum {
|
|
4
|
+
USER = "user",
|
|
5
|
+
ENVIRONMENT = "environment"
|
|
6
|
+
}
|
|
7
|
+
export type OutputImageFormats = OutputImageFormatEnum.JPG | OutputImageFormatEnum.WEBP | OutputImageFormatEnum.PNG;
|
|
8
|
+
export declare enum OutputImageFormatEnum {
|
|
9
|
+
WEBP = "image/webp",
|
|
10
|
+
JPG = "image/jpeg",
|
|
11
|
+
PNG = "image/png"
|
|
12
|
+
}
|
|
13
|
+
export declare class FilePickerAccepts {
|
|
14
|
+
static image: string;
|
|
15
|
+
static document: string;
|
|
16
|
+
static video: string;
|
|
17
|
+
static audio: string;
|
|
18
|
+
static text: string;
|
|
19
|
+
}
|
|
2
20
|
/**
|
|
3
21
|
* Processes an image file by resizing, reducing file size, and converting it to a specified format based on the provided options.
|
|
4
22
|
* @param file - The original image file.
|
|
@@ -9,7 +27,7 @@ export declare function processImageFile(file: File, options?: {
|
|
|
9
27
|
maxWidth?: number;
|
|
10
28
|
maxHeight?: number;
|
|
11
29
|
maxSizeInBytes?: number;
|
|
12
|
-
outputFormat?:
|
|
30
|
+
outputFormat?: OutputImageFormats;
|
|
13
31
|
quality?: number;
|
|
14
32
|
}): Promise<File>;
|
|
15
33
|
/**
|
|
@@ -79,3 +97,11 @@ export declare function readFileAsImage(file: File): Promise<HTMLImageElement>;
|
|
|
79
97
|
* });
|
|
80
98
|
*/
|
|
81
99
|
export declare function dataUrlToImage(dataUrl: string): Promise<HTMLImageElement>;
|
|
100
|
+
export declare function cropImageFile({ inputImageFile, outputFormat, outputWidth, outputQuality, outputAspectRatio, dialogSize, }: {
|
|
101
|
+
inputImageFile: File;
|
|
102
|
+
outputFormat?: OutputImageFormats;
|
|
103
|
+
outputWidth?: number;
|
|
104
|
+
outputQuality?: number;
|
|
105
|
+
outputAspectRatio?: number;
|
|
106
|
+
dialogSize?: DialogSize;
|
|
107
|
+
}): Promise<File | null>;
|
|
@@ -1,15 +1,50 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { DialogSizeEnum, openCropperDialog } from "../dialog/dialog-service";
|
|
2
|
+
import { getExtFromFileType, readFileAsDataURL } from "./file-service";
|
|
3
|
+
import { nanoid } from 'nanoid';
|
|
4
|
+
export var ImageCapttureEnum;
|
|
5
|
+
(function (ImageCapttureEnum) {
|
|
6
|
+
ImageCapttureEnum["USER"] = "user";
|
|
7
|
+
ImageCapttureEnum["ENVIRONMENT"] = "environment";
|
|
8
|
+
})(ImageCapttureEnum || (ImageCapttureEnum = {}));
|
|
9
|
+
export var OutputImageFormatEnum;
|
|
10
|
+
(function (OutputImageFormatEnum) {
|
|
11
|
+
OutputImageFormatEnum["WEBP"] = "image/webp";
|
|
12
|
+
OutputImageFormatEnum["JPG"] = "image/jpeg";
|
|
13
|
+
OutputImageFormatEnum["PNG"] = "image/png";
|
|
14
|
+
})(OutputImageFormatEnum || (OutputImageFormatEnum = {}));
|
|
15
|
+
export class FilePickerAccepts {
|
|
16
|
+
static image = '.png,.PNG,.jpg,.JPG,.jpeg,.JPEG,.webp,.WEBP';
|
|
17
|
+
static document = '.pdf,.PDF,.doc,.DOC,.docx,.DOCX,.xls,.XLS,.xlsx,.XLSX,.ppt,.PPT,.pptx,.PPTX,.txt,.TXT,';
|
|
18
|
+
static video = '.mp4,.MP4,.mov,.MOV,.avi,.AVI,.wmv,.WMV,.flv,.FLV,.mkv,.MKV,.webm,.WEBM,';
|
|
19
|
+
static audio = '.mp3,.MP3,.wav,.WAV,.aac,.AAC,.flac,.FLAC,.ogg,.OGG,.wma,.WMA,';
|
|
20
|
+
static text = '.txt,.TXT,';
|
|
21
|
+
}
|
|
3
22
|
/**
|
|
4
23
|
* Processes an image file by resizing, reducing file size, and converting it to a specified format based on the provided options.
|
|
5
24
|
* @param file - The original image file.
|
|
6
25
|
* @param options - Options for resizing, compressing, and converting the image.
|
|
7
26
|
* @returns A promise that resolves to a processed File object with the correct filename and extension.
|
|
8
27
|
*/
|
|
9
|
-
export async function processImageFile(file, options) {
|
|
10
|
-
// Return the original file if no processing is needed
|
|
11
|
-
if (!options?.maxWidth && !options?.maxHeight && !options?.maxSizeInBytes && !options?.outputFormat) {
|
|
12
|
-
|
|
28
|
+
export async function processImageFile(file, options = {}) {
|
|
29
|
+
// // Return the original file if no processing is needed
|
|
30
|
+
// if (!options?.maxWidth && !options?.maxHeight && !options?.maxSizeInBytes && !options?.outputFormat) {
|
|
31
|
+
// return file;
|
|
32
|
+
// }
|
|
33
|
+
options = options || {};
|
|
34
|
+
if (!options.maxWidth) {
|
|
35
|
+
options.maxWidth = 1920;
|
|
36
|
+
}
|
|
37
|
+
if (!options.maxHeight) {
|
|
38
|
+
options.maxHeight = options.maxWidth;
|
|
39
|
+
}
|
|
40
|
+
if (!options.quality || options.quality < 0) {
|
|
41
|
+
options.quality = 0.8;
|
|
42
|
+
}
|
|
43
|
+
if (options.quality > 1) {
|
|
44
|
+
options.quality = options.quality / 100;
|
|
45
|
+
}
|
|
46
|
+
if (options.outputFormat) {
|
|
47
|
+
options.outputFormat = OutputImageFormatEnum.WEBP;
|
|
13
48
|
}
|
|
14
49
|
// Read the image as a data URL
|
|
15
50
|
const imageDataUrl = await readFileAsDataURL(file);
|
|
@@ -192,3 +227,34 @@ export async function dataUrlToImage(dataUrl) {
|
|
|
192
227
|
img.src = dataUrl;
|
|
193
228
|
});
|
|
194
229
|
}
|
|
230
|
+
export async function cropImageFile({ inputImageFile, outputFormat = OutputImageFormatEnum.WEBP, outputWidth = 600, outputQuality = 0.6, outputAspectRatio = 1, dialogSize = DialogSizeEnum.MD, }) {
|
|
231
|
+
let imageFile = null;
|
|
232
|
+
let fileName = '';
|
|
233
|
+
if (inputImageFile) {
|
|
234
|
+
imageFile = (await openCropperDialog({
|
|
235
|
+
inputImageFile,
|
|
236
|
+
outputFormat,
|
|
237
|
+
outputWidth,
|
|
238
|
+
outputQuality,
|
|
239
|
+
outputAspectRatio,
|
|
240
|
+
size: dialogSize,
|
|
241
|
+
}));
|
|
242
|
+
if (imageFile) {
|
|
243
|
+
try {
|
|
244
|
+
// console.log('imageFile', imageFile);
|
|
245
|
+
let filenameNanoid = nanoid(10);
|
|
246
|
+
fileName = (imageFile.name || '').toLocaleLowerCase().trim().replace(/ /g, '_').substring(0, 4);
|
|
247
|
+
fileName = (fileName ? fileName + '-' + filenameNanoid : filenameNanoid) + `.${getExtFromFileType(outputFormat)}`;
|
|
248
|
+
}
|
|
249
|
+
catch (e) {
|
|
250
|
+
console.error(e);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
let newFile = null;
|
|
255
|
+
if (imageFile && fileName) {
|
|
256
|
+
// Add the file name to the file object, so that it can be used in the form.
|
|
257
|
+
newFile = new File([imageFile], fileName, { type: imageFile.type || 'image/webp' });
|
|
258
|
+
}
|
|
259
|
+
return newFile;
|
|
260
|
+
}
|
|
@@ -256,3 +256,5 @@ export declare function inchToPixel(inches: number): number;
|
|
|
256
256
|
*/
|
|
257
257
|
export declare function pixelToInch(pixels: number): number;
|
|
258
258
|
export declare function alphabetNanoid(length?: number, lowercase?: boolean): string;
|
|
259
|
+
export declare function sanitizePhoneNumber(input: string): string;
|
|
260
|
+
export declare function isChrome(): boolean;
|
|
@@ -403,3 +403,11 @@ export function alphabetNanoid(length = 10, lowercase = false) {
|
|
|
403
403
|
const nanoid = customAlphabet(alphabet, length);
|
|
404
404
|
return nanoid();
|
|
405
405
|
}
|
|
406
|
+
export function sanitizePhoneNumber(input) {
|
|
407
|
+
return input.replace(/\D/g, "");
|
|
408
|
+
}
|
|
409
|
+
export function isChrome() {
|
|
410
|
+
// Chrome's userAgent contains "Chrome", and its vendor contains "Google Inc"
|
|
411
|
+
// Note: Microsoft Edge's userAgent also contains "Chrome"
|
|
412
|
+
return /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
|
|
413
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
<script module lang="ts"></script>
|
|
2
2
|
|
|
3
3
|
<script lang="ts">import EasyCropperjs from "@cloudparker/easy-cropperjs-svelte";
|
|
4
|
+
import { OutputImageFormatEnum } from "../../../../../services";
|
|
4
5
|
let {
|
|
5
6
|
outputWidth,
|
|
6
|
-
outputFormat =
|
|
7
|
+
outputFormat = OutputImageFormatEnum.WEBP,
|
|
7
8
|
outputQuality = 0.8,
|
|
8
9
|
outputType = "file",
|
|
9
10
|
inputImageFile,
|
|
11
|
+
outputAspectRatio,
|
|
10
12
|
className,
|
|
11
13
|
setOnOkClick,
|
|
12
14
|
setResult,
|
|
@@ -18,9 +20,10 @@ let easyCropperjsRef = $state(null);
|
|
|
18
20
|
setOnOkClick(async () => {
|
|
19
21
|
console.log("setOnOkClick", easyCropperjsRef);
|
|
20
22
|
if (easyCropperjsRef) {
|
|
23
|
+
let targetOutoutImageFormat = outputFormat.split("/")[1] || "webp";
|
|
21
24
|
let res = await easyCropperjsRef.crop({
|
|
22
25
|
outputWidth,
|
|
23
|
-
outputFormat,
|
|
26
|
+
outputFormat: targetOutoutImageFormat,
|
|
24
27
|
outputQuality,
|
|
25
28
|
outputType
|
|
26
29
|
});
|
|
@@ -35,5 +38,10 @@ function handleCropped(result) {
|
|
|
35
38
|
</script>
|
|
36
39
|
|
|
37
40
|
<div class="h-full w-full overflow-hidden {className}">
|
|
38
|
-
<EasyCropperjs
|
|
41
|
+
<EasyCropperjs
|
|
42
|
+
bind:this={easyCropperjsRef}
|
|
43
|
+
{inputImageFile}
|
|
44
|
+
onCrop={handleCropped}
|
|
45
|
+
{outputAspectRatio}
|
|
46
|
+
/>
|
|
39
47
|
</div>
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
export type CropperDialogPropsType = {
|
|
2
2
|
outputAspectRatio?: number;
|
|
3
3
|
outputWidth?: number;
|
|
4
|
-
outputFormat?:
|
|
4
|
+
outputFormat?: OutputImageFormats;
|
|
5
5
|
outputQuality?: number;
|
|
6
6
|
outputType?: 'file' | 'base64';
|
|
7
7
|
inputImageFile?: File | null;
|
|
8
8
|
className?: string;
|
|
9
9
|
};
|
|
10
10
|
import type { DialogExports } from '../dialog/dialog.svelte';
|
|
11
|
+
import { type OutputImageFormats } from '../../../../../services';
|
|
11
12
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
12
13
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
13
14
|
$$bindings?: Bindings;
|
|
@@ -6,7 +6,7 @@ import ButtonClose from "../../../button/components/button-close-icon/button-clo
|
|
|
6
6
|
import {} from "svelte";
|
|
7
7
|
import "../../../../../tailwind.css";
|
|
8
8
|
import { mdiArrowLeft, mdiClose } from "../../../icon";
|
|
9
|
-
import { isMobileScreen } from "../../../../../services";
|
|
9
|
+
import { DialogSizeEnum, isMobileScreen } from "../../../../../services";
|
|
10
10
|
let {
|
|
11
11
|
backdropClassName = "",
|
|
12
12
|
bodyClassName = "",
|
|
@@ -42,7 +42,7 @@ let {
|
|
|
42
42
|
headerCloseIconPath = mdiClose,
|
|
43
43
|
hasHeaderBack = isMobileScreen(),
|
|
44
44
|
hasHeaderClose = !isMobileScreen(),
|
|
45
|
-
size = isMobileScreen() ?
|
|
45
|
+
size = isMobileScreen() ? DialogSizeEnum.FULL : DialogSizeEnum.SM,
|
|
46
46
|
id = "",
|
|
47
47
|
onClose,
|
|
48
48
|
onCloseClick,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* true -> Close dialog
|
|
5
5
|
*/
|
|
6
6
|
type DialogCloseButtonClickFunction = (ev: MouseEvent | TouchEvent) => Promise<boolean>;
|
|
7
|
-
export type DialogSize =
|
|
7
|
+
export type DialogSize = DialogSizeEnum.XS | DialogSizeEnum.SM | DialogSizeEnum.MD | DialogSizeEnum.LG | DialogSizeEnum.XL | DialogSizeEnum.FULL;
|
|
8
8
|
export type DialogProps = {
|
|
9
9
|
backdropClassName?: string;
|
|
10
10
|
bodyClassName?: string;
|
|
@@ -68,6 +68,7 @@ export type DialogExports = {
|
|
|
68
68
|
};
|
|
69
69
|
import { type Snippet } from 'svelte';
|
|
70
70
|
import '../../../../../tailwind.css';
|
|
71
|
+
import { DialogSizeEnum } from '../../../../../services';
|
|
71
72
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
72
73
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
73
74
|
$$bindings?: Bindings;
|