@fctc/widget-logic 3.10.5 → 3.10.7
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/hooks.js +0 -1
- package/dist/hooks.mjs +0 -1
- package/dist/index.js +77 -53
- package/dist/index.mjs +77 -53
- package/dist/types.d.mts +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/widget.d.mts +10 -7
- package/dist/widget.d.ts +10 -7
- package/dist/widget.js +77 -52
- package/dist/widget.mjs +77 -52
- package/package.json +2 -2
package/dist/hooks.js
CHANGED
|
@@ -568,7 +568,6 @@ var useCompany = ({ service }) => {
|
|
|
568
568
|
(0, import_react7.useEffect)(() => {
|
|
569
569
|
if (current_company_id) {
|
|
570
570
|
const companyIDs = [current_company_id];
|
|
571
|
-
setAllowCompanies([...companyIDs]);
|
|
572
571
|
setCompanies(companyIDs);
|
|
573
572
|
}
|
|
574
573
|
}, [current_company_id]);
|
package/dist/hooks.mjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -4618,7 +4618,6 @@ var useCompany = ({ service }) => {
|
|
|
4618
4618
|
(0, import_react7.useEffect)(() => {
|
|
4619
4619
|
if (current_company_id) {
|
|
4620
4620
|
const companyIDs = [current_company_id];
|
|
4621
|
-
setAllowCompanies([...companyIDs]);
|
|
4622
4621
|
setCompanies(companyIDs);
|
|
4623
4622
|
}
|
|
4624
4623
|
}, [current_company_id]);
|
|
@@ -6194,12 +6193,33 @@ var colorFieldController = (props) => {
|
|
|
6194
6193
|
// src/widget/basic/binary-field/controller.ts
|
|
6195
6194
|
var import_react22 = require("react");
|
|
6196
6195
|
var import_utils16 = require("@fctc/interface-logic/utils");
|
|
6196
|
+
var ALLOWED_TYPES = [
|
|
6197
|
+
"image/jpeg",
|
|
6198
|
+
"image/png",
|
|
6199
|
+
"application/pdf",
|
|
6200
|
+
"video/mp4",
|
|
6201
|
+
"application/zip",
|
|
6202
|
+
"application/x-zip-compressed",
|
|
6203
|
+
"application/vnd.ms-excel",
|
|
6204
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
6205
|
+
"application/json"
|
|
6206
|
+
];
|
|
6207
|
+
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
6208
|
+
var MAX_TOTAL_SIZE = 50 * 1024 * 1024;
|
|
6197
6209
|
var binaryFieldController = (props) => {
|
|
6198
|
-
const {
|
|
6210
|
+
const {
|
|
6211
|
+
name,
|
|
6212
|
+
methods,
|
|
6213
|
+
readonly = false,
|
|
6214
|
+
value,
|
|
6215
|
+
filename,
|
|
6216
|
+
rootField,
|
|
6217
|
+
index
|
|
6218
|
+
} = props;
|
|
6199
6219
|
const inputId = (0, import_react22.useId)();
|
|
6200
|
-
const [
|
|
6201
|
-
const [
|
|
6202
|
-
const [
|
|
6220
|
+
const [selectedFile, setSelectedFile] = (0, import_react22.useState)(null);
|
|
6221
|
+
const [selectedPreview, setSelectedPreview] = (0, import_react22.useState)(null);
|
|
6222
|
+
const [initialFile, setInitialFile] = (0, import_react22.useState)(value || null);
|
|
6203
6223
|
const { setValue } = methods;
|
|
6204
6224
|
const binaryRef = (0, import_react22.useRef)(null);
|
|
6205
6225
|
const convertUrlToBase64 = async (url) => {
|
|
@@ -6208,9 +6228,7 @@ var binaryFieldController = (props) => {
|
|
|
6208
6228
|
const blob = await response.blob();
|
|
6209
6229
|
return new Promise((resolve, reject) => {
|
|
6210
6230
|
const reader = new FileReader();
|
|
6211
|
-
reader.onloadend = () =>
|
|
6212
|
-
resolve(reader.result);
|
|
6213
|
-
};
|
|
6231
|
+
reader.onloadend = () => resolve(reader.result);
|
|
6214
6232
|
reader.onerror = reject;
|
|
6215
6233
|
reader.readAsDataURL(blob);
|
|
6216
6234
|
});
|
|
@@ -6219,40 +6237,13 @@ var binaryFieldController = (props) => {
|
|
|
6219
6237
|
throw error;
|
|
6220
6238
|
}
|
|
6221
6239
|
};
|
|
6222
|
-
const extractBase64Data = (base64Url) =>
|
|
6223
|
-
|
|
6224
|
-
return base64Url.split("base64,")[1];
|
|
6225
|
-
}
|
|
6226
|
-
return base64Url;
|
|
6227
|
-
};
|
|
6228
|
-
const handleImageChange = async (e, onChange) => {
|
|
6229
|
-
if (readonly) return;
|
|
6230
|
-
const file = e?.target?.files?.[0];
|
|
6231
|
-
if (file) {
|
|
6232
|
-
const imageUrl = URL.createObjectURL(file);
|
|
6233
|
-
setSelectedImage(imageUrl);
|
|
6234
|
-
setInitialImage(null);
|
|
6235
|
-
onChange(file);
|
|
6236
|
-
const compressedBase64 = await convertUrlToBase64(imageUrl);
|
|
6237
|
-
const base64Data = extractBase64Data(compressedBase64);
|
|
6238
|
-
setValue(name, base64Data, {
|
|
6239
|
-
shouldDirty: true
|
|
6240
|
-
});
|
|
6241
|
-
}
|
|
6242
|
-
};
|
|
6243
|
-
const handleRemoveImage = (onChange) => {
|
|
6244
|
-
setSelectedImage(null);
|
|
6245
|
-
setInitialImage(null);
|
|
6246
|
-
onChange(null);
|
|
6247
|
-
};
|
|
6248
|
-
const isBlobUrl = (url) => {
|
|
6249
|
-
return /^blob:/.test(url);
|
|
6250
|
-
};
|
|
6240
|
+
const extractBase64Data = (base64Url) => base64Url.includes("base64,") ? base64Url.split("base64,")[1] : base64Url;
|
|
6241
|
+
const isBlobUrl = (url) => /^blob:/.test(url);
|
|
6251
6242
|
const checkIsImageLink = (url) => {
|
|
6252
6243
|
const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
|
|
6253
6244
|
return imageExtensions.test(url) || (0, import_utils16.isBase64Image)(url) || isBlobUrl(url);
|
|
6254
6245
|
};
|
|
6255
|
-
const
|
|
6246
|
+
const getBase64WithMimeType = (base64) => {
|
|
6256
6247
|
if (typeof base64 !== "string" || base64.length < 10) return null;
|
|
6257
6248
|
if ((0, import_utils16.isBase64Image)(base64)) return base64;
|
|
6258
6249
|
let mimeType = null;
|
|
@@ -6263,29 +6254,62 @@ var binaryFieldController = (props) => {
|
|
|
6263
6254
|
else if (base64.startsWith("UklGR")) mimeType = "image/webp";
|
|
6264
6255
|
return mimeType ? `data:${mimeType};base64,${base64}` : null;
|
|
6265
6256
|
};
|
|
6257
|
+
const handleFileChange = async (e, onChange) => {
|
|
6258
|
+
if (readonly) return;
|
|
6259
|
+
const file = e?.target?.files?.[0];
|
|
6260
|
+
if (!file) return;
|
|
6261
|
+
if (!ALLOWED_TYPES.includes(file.type)) {
|
|
6262
|
+
alert(`File type not allowed: ${file.type}`);
|
|
6263
|
+
return;
|
|
6264
|
+
}
|
|
6265
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
6266
|
+
alert(`File exceeds 10MB limit.`);
|
|
6267
|
+
return;
|
|
6268
|
+
}
|
|
6269
|
+
const fileUrl = URL.createObjectURL(file);
|
|
6270
|
+
setSelectedFile(file);
|
|
6271
|
+
setInitialFile(null);
|
|
6272
|
+
setSelectedPreview(fileUrl);
|
|
6273
|
+
onChange(file);
|
|
6274
|
+
if (file.type.startsWith("image/") || file.type === "application/json") {
|
|
6275
|
+
const base64 = await convertUrlToBase64(fileUrl);
|
|
6276
|
+
const base64Data = extractBase64Data(base64);
|
|
6277
|
+
setValue(name, base64Data, { shouldDirty: true });
|
|
6278
|
+
} else {
|
|
6279
|
+
setValue(name, file, { shouldDirty: true });
|
|
6280
|
+
}
|
|
6281
|
+
if (filename) {
|
|
6282
|
+
setValue(
|
|
6283
|
+
rootField ? `${rootField?.name}.${index}.${filename}` : filename,
|
|
6284
|
+
file?.name,
|
|
6285
|
+
{ shouldDirty: true }
|
|
6286
|
+
);
|
|
6287
|
+
}
|
|
6288
|
+
};
|
|
6289
|
+
const handleRemoveFile = (onChange) => {
|
|
6290
|
+
if (selectedPreview) URL.revokeObjectURL(selectedPreview);
|
|
6291
|
+
setSelectedFile(null);
|
|
6292
|
+
setSelectedPreview(null);
|
|
6293
|
+
setInitialFile(null);
|
|
6294
|
+
onChange(null);
|
|
6295
|
+
};
|
|
6266
6296
|
(0, import_react22.useEffect)(() => {
|
|
6267
6297
|
return () => {
|
|
6268
|
-
if (
|
|
6269
|
-
URL.revokeObjectURL(
|
|
6298
|
+
if (selectedPreview) {
|
|
6299
|
+
URL.revokeObjectURL(selectedPreview);
|
|
6270
6300
|
}
|
|
6271
6301
|
};
|
|
6272
|
-
}, [
|
|
6273
|
-
(0, import_react22.useEffect)(() => {
|
|
6274
|
-
if (binaryRef.current) {
|
|
6275
|
-
const isInsideTable2 = !!binaryRef.current.closest("table");
|
|
6276
|
-
setIsInsideTable(isInsideTable2);
|
|
6277
|
-
}
|
|
6278
|
-
}, []);
|
|
6302
|
+
}, [selectedPreview]);
|
|
6279
6303
|
return {
|
|
6280
6304
|
inputId,
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6305
|
+
selectedFile,
|
|
6306
|
+
selectedPreview,
|
|
6307
|
+
initialFile,
|
|
6284
6308
|
binaryRef,
|
|
6285
|
-
|
|
6286
|
-
|
|
6309
|
+
handleFileChange,
|
|
6310
|
+
handleRemoveFile,
|
|
6287
6311
|
checkIsImageLink,
|
|
6288
|
-
|
|
6312
|
+
getBase64WithMimeType
|
|
6289
6313
|
};
|
|
6290
6314
|
};
|
|
6291
6315
|
|
package/dist/index.mjs
CHANGED
|
@@ -4693,7 +4693,6 @@ var useCompany = ({ service }) => {
|
|
|
4693
4693
|
useEffect4(() => {
|
|
4694
4694
|
if (current_company_id) {
|
|
4695
4695
|
const companyIDs = [current_company_id];
|
|
4696
|
-
setAllowCompanies([...companyIDs]);
|
|
4697
4696
|
setCompanies(companyIDs);
|
|
4698
4697
|
}
|
|
4699
4698
|
}, [current_company_id]);
|
|
@@ -6274,12 +6273,33 @@ var colorFieldController = (props) => {
|
|
|
6274
6273
|
// src/widget/basic/binary-field/controller.ts
|
|
6275
6274
|
import { useEffect as useEffect13, useId as useId2, useRef as useRef4, useState as useState12 } from "react";
|
|
6276
6275
|
import { isBase64Image } from "@fctc/interface-logic/utils";
|
|
6276
|
+
var ALLOWED_TYPES = [
|
|
6277
|
+
"image/jpeg",
|
|
6278
|
+
"image/png",
|
|
6279
|
+
"application/pdf",
|
|
6280
|
+
"video/mp4",
|
|
6281
|
+
"application/zip",
|
|
6282
|
+
"application/x-zip-compressed",
|
|
6283
|
+
"application/vnd.ms-excel",
|
|
6284
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
6285
|
+
"application/json"
|
|
6286
|
+
];
|
|
6287
|
+
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
6288
|
+
var MAX_TOTAL_SIZE = 50 * 1024 * 1024;
|
|
6277
6289
|
var binaryFieldController = (props) => {
|
|
6278
|
-
const {
|
|
6290
|
+
const {
|
|
6291
|
+
name,
|
|
6292
|
+
methods,
|
|
6293
|
+
readonly = false,
|
|
6294
|
+
value,
|
|
6295
|
+
filename,
|
|
6296
|
+
rootField,
|
|
6297
|
+
index
|
|
6298
|
+
} = props;
|
|
6279
6299
|
const inputId = useId2();
|
|
6280
|
-
const [
|
|
6281
|
-
const [
|
|
6282
|
-
const [
|
|
6300
|
+
const [selectedFile, setSelectedFile] = useState12(null);
|
|
6301
|
+
const [selectedPreview, setSelectedPreview] = useState12(null);
|
|
6302
|
+
const [initialFile, setInitialFile] = useState12(value || null);
|
|
6283
6303
|
const { setValue } = methods;
|
|
6284
6304
|
const binaryRef = useRef4(null);
|
|
6285
6305
|
const convertUrlToBase64 = async (url) => {
|
|
@@ -6288,9 +6308,7 @@ var binaryFieldController = (props) => {
|
|
|
6288
6308
|
const blob = await response.blob();
|
|
6289
6309
|
return new Promise((resolve, reject) => {
|
|
6290
6310
|
const reader = new FileReader();
|
|
6291
|
-
reader.onloadend = () =>
|
|
6292
|
-
resolve(reader.result);
|
|
6293
|
-
};
|
|
6311
|
+
reader.onloadend = () => resolve(reader.result);
|
|
6294
6312
|
reader.onerror = reject;
|
|
6295
6313
|
reader.readAsDataURL(blob);
|
|
6296
6314
|
});
|
|
@@ -6299,40 +6317,13 @@ var binaryFieldController = (props) => {
|
|
|
6299
6317
|
throw error;
|
|
6300
6318
|
}
|
|
6301
6319
|
};
|
|
6302
|
-
const extractBase64Data = (base64Url) =>
|
|
6303
|
-
|
|
6304
|
-
return base64Url.split("base64,")[1];
|
|
6305
|
-
}
|
|
6306
|
-
return base64Url;
|
|
6307
|
-
};
|
|
6308
|
-
const handleImageChange = async (e, onChange) => {
|
|
6309
|
-
if (readonly) return;
|
|
6310
|
-
const file = e?.target?.files?.[0];
|
|
6311
|
-
if (file) {
|
|
6312
|
-
const imageUrl = URL.createObjectURL(file);
|
|
6313
|
-
setSelectedImage(imageUrl);
|
|
6314
|
-
setInitialImage(null);
|
|
6315
|
-
onChange(file);
|
|
6316
|
-
const compressedBase64 = await convertUrlToBase64(imageUrl);
|
|
6317
|
-
const base64Data = extractBase64Data(compressedBase64);
|
|
6318
|
-
setValue(name, base64Data, {
|
|
6319
|
-
shouldDirty: true
|
|
6320
|
-
});
|
|
6321
|
-
}
|
|
6322
|
-
};
|
|
6323
|
-
const handleRemoveImage = (onChange) => {
|
|
6324
|
-
setSelectedImage(null);
|
|
6325
|
-
setInitialImage(null);
|
|
6326
|
-
onChange(null);
|
|
6327
|
-
};
|
|
6328
|
-
const isBlobUrl = (url) => {
|
|
6329
|
-
return /^blob:/.test(url);
|
|
6330
|
-
};
|
|
6320
|
+
const extractBase64Data = (base64Url) => base64Url.includes("base64,") ? base64Url.split("base64,")[1] : base64Url;
|
|
6321
|
+
const isBlobUrl = (url) => /^blob:/.test(url);
|
|
6331
6322
|
const checkIsImageLink = (url) => {
|
|
6332
6323
|
const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
|
|
6333
6324
|
return imageExtensions.test(url) || isBase64Image(url) || isBlobUrl(url);
|
|
6334
6325
|
};
|
|
6335
|
-
const
|
|
6326
|
+
const getBase64WithMimeType = (base64) => {
|
|
6336
6327
|
if (typeof base64 !== "string" || base64.length < 10) return null;
|
|
6337
6328
|
if (isBase64Image(base64)) return base64;
|
|
6338
6329
|
let mimeType = null;
|
|
@@ -6343,29 +6334,62 @@ var binaryFieldController = (props) => {
|
|
|
6343
6334
|
else if (base64.startsWith("UklGR")) mimeType = "image/webp";
|
|
6344
6335
|
return mimeType ? `data:${mimeType};base64,${base64}` : null;
|
|
6345
6336
|
};
|
|
6337
|
+
const handleFileChange = async (e, onChange) => {
|
|
6338
|
+
if (readonly) return;
|
|
6339
|
+
const file = e?.target?.files?.[0];
|
|
6340
|
+
if (!file) return;
|
|
6341
|
+
if (!ALLOWED_TYPES.includes(file.type)) {
|
|
6342
|
+
alert(`File type not allowed: ${file.type}`);
|
|
6343
|
+
return;
|
|
6344
|
+
}
|
|
6345
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
6346
|
+
alert(`File exceeds 10MB limit.`);
|
|
6347
|
+
return;
|
|
6348
|
+
}
|
|
6349
|
+
const fileUrl = URL.createObjectURL(file);
|
|
6350
|
+
setSelectedFile(file);
|
|
6351
|
+
setInitialFile(null);
|
|
6352
|
+
setSelectedPreview(fileUrl);
|
|
6353
|
+
onChange(file);
|
|
6354
|
+
if (file.type.startsWith("image/") || file.type === "application/json") {
|
|
6355
|
+
const base64 = await convertUrlToBase64(fileUrl);
|
|
6356
|
+
const base64Data = extractBase64Data(base64);
|
|
6357
|
+
setValue(name, base64Data, { shouldDirty: true });
|
|
6358
|
+
} else {
|
|
6359
|
+
setValue(name, file, { shouldDirty: true });
|
|
6360
|
+
}
|
|
6361
|
+
if (filename) {
|
|
6362
|
+
setValue(
|
|
6363
|
+
rootField ? `${rootField?.name}.${index}.${filename}` : filename,
|
|
6364
|
+
file?.name,
|
|
6365
|
+
{ shouldDirty: true }
|
|
6366
|
+
);
|
|
6367
|
+
}
|
|
6368
|
+
};
|
|
6369
|
+
const handleRemoveFile = (onChange) => {
|
|
6370
|
+
if (selectedPreview) URL.revokeObjectURL(selectedPreview);
|
|
6371
|
+
setSelectedFile(null);
|
|
6372
|
+
setSelectedPreview(null);
|
|
6373
|
+
setInitialFile(null);
|
|
6374
|
+
onChange(null);
|
|
6375
|
+
};
|
|
6346
6376
|
useEffect13(() => {
|
|
6347
6377
|
return () => {
|
|
6348
|
-
if (
|
|
6349
|
-
URL.revokeObjectURL(
|
|
6378
|
+
if (selectedPreview) {
|
|
6379
|
+
URL.revokeObjectURL(selectedPreview);
|
|
6350
6380
|
}
|
|
6351
6381
|
};
|
|
6352
|
-
}, [
|
|
6353
|
-
useEffect13(() => {
|
|
6354
|
-
if (binaryRef.current) {
|
|
6355
|
-
const isInsideTable2 = !!binaryRef.current.closest("table");
|
|
6356
|
-
setIsInsideTable(isInsideTable2);
|
|
6357
|
-
}
|
|
6358
|
-
}, []);
|
|
6382
|
+
}, [selectedPreview]);
|
|
6359
6383
|
return {
|
|
6360
6384
|
inputId,
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6385
|
+
selectedFile,
|
|
6386
|
+
selectedPreview,
|
|
6387
|
+
initialFile,
|
|
6364
6388
|
binaryRef,
|
|
6365
|
-
|
|
6366
|
-
|
|
6389
|
+
handleFileChange,
|
|
6390
|
+
handleRemoveFile,
|
|
6367
6391
|
checkIsImageLink,
|
|
6368
|
-
|
|
6392
|
+
getBase64WithMimeType
|
|
6369
6393
|
};
|
|
6370
6394
|
};
|
|
6371
6395
|
|
package/dist/types.d.mts
CHANGED
package/dist/types.d.ts
CHANGED
package/dist/widget.d.mts
CHANGED
|
@@ -208,16 +208,19 @@ declare const colorFieldController: (props: IColorFieldProps) => {
|
|
|
208
208
|
savePickColor: (colorObject: any) => Promise<void>;
|
|
209
209
|
};
|
|
210
210
|
|
|
211
|
-
declare const binaryFieldController: (props: IInputFieldProps
|
|
211
|
+
declare const binaryFieldController: (props: IInputFieldProps & {
|
|
212
|
+
rootField?: any;
|
|
213
|
+
index?: number;
|
|
214
|
+
}) => {
|
|
212
215
|
inputId: string;
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
+
selectedFile: File | null;
|
|
217
|
+
selectedPreview: string | null;
|
|
218
|
+
initialFile: any;
|
|
216
219
|
binaryRef: react.RefObject<HTMLDivElement>;
|
|
217
|
-
|
|
218
|
-
|
|
220
|
+
handleFileChange: (e: ChangeEvent<HTMLInputElement>, onChange: (file: File | null) => void) => Promise<void>;
|
|
221
|
+
handleRemoveFile: (onChange: (file: File | null) => void) => void;
|
|
219
222
|
checkIsImageLink: (url: string) => boolean;
|
|
220
|
-
|
|
223
|
+
getBase64WithMimeType: (base64: string) => string | null;
|
|
221
224
|
};
|
|
222
225
|
|
|
223
226
|
declare const tableHeadController: (props: any) => {
|
package/dist/widget.d.ts
CHANGED
|
@@ -208,16 +208,19 @@ declare const colorFieldController: (props: IColorFieldProps) => {
|
|
|
208
208
|
savePickColor: (colorObject: any) => Promise<void>;
|
|
209
209
|
};
|
|
210
210
|
|
|
211
|
-
declare const binaryFieldController: (props: IInputFieldProps
|
|
211
|
+
declare const binaryFieldController: (props: IInputFieldProps & {
|
|
212
|
+
rootField?: any;
|
|
213
|
+
index?: number;
|
|
214
|
+
}) => {
|
|
212
215
|
inputId: string;
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
+
selectedFile: File | null;
|
|
217
|
+
selectedPreview: string | null;
|
|
218
|
+
initialFile: any;
|
|
216
219
|
binaryRef: react.RefObject<HTMLDivElement>;
|
|
217
|
-
|
|
218
|
-
|
|
220
|
+
handleFileChange: (e: ChangeEvent<HTMLInputElement>, onChange: (file: File | null) => void) => Promise<void>;
|
|
221
|
+
handleRemoveFile: (onChange: (file: File | null) => void) => void;
|
|
219
222
|
checkIsImageLink: (url: string) => boolean;
|
|
220
|
-
|
|
223
|
+
getBase64WithMimeType: (base64: string) => string | null;
|
|
221
224
|
};
|
|
222
225
|
|
|
223
226
|
declare const tableHeadController: (props: any) => {
|
package/dist/widget.js
CHANGED
|
@@ -5431,12 +5431,33 @@ var colorFieldController = (props) => {
|
|
|
5431
5431
|
// src/widget/basic/binary-field/controller.ts
|
|
5432
5432
|
var import_react22 = require("react");
|
|
5433
5433
|
var import_utils16 = require("@fctc/interface-logic/utils");
|
|
5434
|
+
var ALLOWED_TYPES = [
|
|
5435
|
+
"image/jpeg",
|
|
5436
|
+
"image/png",
|
|
5437
|
+
"application/pdf",
|
|
5438
|
+
"video/mp4",
|
|
5439
|
+
"application/zip",
|
|
5440
|
+
"application/x-zip-compressed",
|
|
5441
|
+
"application/vnd.ms-excel",
|
|
5442
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
5443
|
+
"application/json"
|
|
5444
|
+
];
|
|
5445
|
+
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
5446
|
+
var MAX_TOTAL_SIZE = 50 * 1024 * 1024;
|
|
5434
5447
|
var binaryFieldController = (props) => {
|
|
5435
|
-
const {
|
|
5448
|
+
const {
|
|
5449
|
+
name,
|
|
5450
|
+
methods,
|
|
5451
|
+
readonly = false,
|
|
5452
|
+
value,
|
|
5453
|
+
filename,
|
|
5454
|
+
rootField,
|
|
5455
|
+
index
|
|
5456
|
+
} = props;
|
|
5436
5457
|
const inputId = (0, import_react22.useId)();
|
|
5437
|
-
const [
|
|
5438
|
-
const [
|
|
5439
|
-
const [
|
|
5458
|
+
const [selectedFile, setSelectedFile] = (0, import_react22.useState)(null);
|
|
5459
|
+
const [selectedPreview, setSelectedPreview] = (0, import_react22.useState)(null);
|
|
5460
|
+
const [initialFile, setInitialFile] = (0, import_react22.useState)(value || null);
|
|
5440
5461
|
const { setValue } = methods;
|
|
5441
5462
|
const binaryRef = (0, import_react22.useRef)(null);
|
|
5442
5463
|
const convertUrlToBase64 = async (url) => {
|
|
@@ -5445,9 +5466,7 @@ var binaryFieldController = (props) => {
|
|
|
5445
5466
|
const blob = await response.blob();
|
|
5446
5467
|
return new Promise((resolve, reject) => {
|
|
5447
5468
|
const reader = new FileReader();
|
|
5448
|
-
reader.onloadend = () =>
|
|
5449
|
-
resolve(reader.result);
|
|
5450
|
-
};
|
|
5469
|
+
reader.onloadend = () => resolve(reader.result);
|
|
5451
5470
|
reader.onerror = reject;
|
|
5452
5471
|
reader.readAsDataURL(blob);
|
|
5453
5472
|
});
|
|
@@ -5456,40 +5475,13 @@ var binaryFieldController = (props) => {
|
|
|
5456
5475
|
throw error;
|
|
5457
5476
|
}
|
|
5458
5477
|
};
|
|
5459
|
-
const extractBase64Data = (base64Url) =>
|
|
5460
|
-
|
|
5461
|
-
return base64Url.split("base64,")[1];
|
|
5462
|
-
}
|
|
5463
|
-
return base64Url;
|
|
5464
|
-
};
|
|
5465
|
-
const handleImageChange = async (e, onChange) => {
|
|
5466
|
-
if (readonly) return;
|
|
5467
|
-
const file = e?.target?.files?.[0];
|
|
5468
|
-
if (file) {
|
|
5469
|
-
const imageUrl = URL.createObjectURL(file);
|
|
5470
|
-
setSelectedImage(imageUrl);
|
|
5471
|
-
setInitialImage(null);
|
|
5472
|
-
onChange(file);
|
|
5473
|
-
const compressedBase64 = await convertUrlToBase64(imageUrl);
|
|
5474
|
-
const base64Data = extractBase64Data(compressedBase64);
|
|
5475
|
-
setValue(name, base64Data, {
|
|
5476
|
-
shouldDirty: true
|
|
5477
|
-
});
|
|
5478
|
-
}
|
|
5479
|
-
};
|
|
5480
|
-
const handleRemoveImage = (onChange) => {
|
|
5481
|
-
setSelectedImage(null);
|
|
5482
|
-
setInitialImage(null);
|
|
5483
|
-
onChange(null);
|
|
5484
|
-
};
|
|
5485
|
-
const isBlobUrl = (url) => {
|
|
5486
|
-
return /^blob:/.test(url);
|
|
5487
|
-
};
|
|
5478
|
+
const extractBase64Data = (base64Url) => base64Url.includes("base64,") ? base64Url.split("base64,")[1] : base64Url;
|
|
5479
|
+
const isBlobUrl = (url) => /^blob:/.test(url);
|
|
5488
5480
|
const checkIsImageLink = (url) => {
|
|
5489
5481
|
const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
|
|
5490
5482
|
return imageExtensions.test(url) || (0, import_utils16.isBase64Image)(url) || isBlobUrl(url);
|
|
5491
5483
|
};
|
|
5492
|
-
const
|
|
5484
|
+
const getBase64WithMimeType = (base64) => {
|
|
5493
5485
|
if (typeof base64 !== "string" || base64.length < 10) return null;
|
|
5494
5486
|
if ((0, import_utils16.isBase64Image)(base64)) return base64;
|
|
5495
5487
|
let mimeType = null;
|
|
@@ -5500,29 +5492,62 @@ var binaryFieldController = (props) => {
|
|
|
5500
5492
|
else if (base64.startsWith("UklGR")) mimeType = "image/webp";
|
|
5501
5493
|
return mimeType ? `data:${mimeType};base64,${base64}` : null;
|
|
5502
5494
|
};
|
|
5495
|
+
const handleFileChange = async (e, onChange) => {
|
|
5496
|
+
if (readonly) return;
|
|
5497
|
+
const file = e?.target?.files?.[0];
|
|
5498
|
+
if (!file) return;
|
|
5499
|
+
if (!ALLOWED_TYPES.includes(file.type)) {
|
|
5500
|
+
alert(`File type not allowed: ${file.type}`);
|
|
5501
|
+
return;
|
|
5502
|
+
}
|
|
5503
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
5504
|
+
alert(`File exceeds 10MB limit.`);
|
|
5505
|
+
return;
|
|
5506
|
+
}
|
|
5507
|
+
const fileUrl = URL.createObjectURL(file);
|
|
5508
|
+
setSelectedFile(file);
|
|
5509
|
+
setInitialFile(null);
|
|
5510
|
+
setSelectedPreview(fileUrl);
|
|
5511
|
+
onChange(file);
|
|
5512
|
+
if (file.type.startsWith("image/") || file.type === "application/json") {
|
|
5513
|
+
const base64 = await convertUrlToBase64(fileUrl);
|
|
5514
|
+
const base64Data = extractBase64Data(base64);
|
|
5515
|
+
setValue(name, base64Data, { shouldDirty: true });
|
|
5516
|
+
} else {
|
|
5517
|
+
setValue(name, file, { shouldDirty: true });
|
|
5518
|
+
}
|
|
5519
|
+
if (filename) {
|
|
5520
|
+
setValue(
|
|
5521
|
+
rootField ? `${rootField?.name}.${index}.${filename}` : filename,
|
|
5522
|
+
file?.name,
|
|
5523
|
+
{ shouldDirty: true }
|
|
5524
|
+
);
|
|
5525
|
+
}
|
|
5526
|
+
};
|
|
5527
|
+
const handleRemoveFile = (onChange) => {
|
|
5528
|
+
if (selectedPreview) URL.revokeObjectURL(selectedPreview);
|
|
5529
|
+
setSelectedFile(null);
|
|
5530
|
+
setSelectedPreview(null);
|
|
5531
|
+
setInitialFile(null);
|
|
5532
|
+
onChange(null);
|
|
5533
|
+
};
|
|
5503
5534
|
(0, import_react22.useEffect)(() => {
|
|
5504
5535
|
return () => {
|
|
5505
|
-
if (
|
|
5506
|
-
URL.revokeObjectURL(
|
|
5536
|
+
if (selectedPreview) {
|
|
5537
|
+
URL.revokeObjectURL(selectedPreview);
|
|
5507
5538
|
}
|
|
5508
5539
|
};
|
|
5509
|
-
}, [
|
|
5510
|
-
(0, import_react22.useEffect)(() => {
|
|
5511
|
-
if (binaryRef.current) {
|
|
5512
|
-
const isInsideTable2 = !!binaryRef.current.closest("table");
|
|
5513
|
-
setIsInsideTable(isInsideTable2);
|
|
5514
|
-
}
|
|
5515
|
-
}, []);
|
|
5540
|
+
}, [selectedPreview]);
|
|
5516
5541
|
return {
|
|
5517
5542
|
inputId,
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5543
|
+
selectedFile,
|
|
5544
|
+
selectedPreview,
|
|
5545
|
+
initialFile,
|
|
5521
5546
|
binaryRef,
|
|
5522
|
-
|
|
5523
|
-
|
|
5547
|
+
handleFileChange,
|
|
5548
|
+
handleRemoveFile,
|
|
5524
5549
|
checkIsImageLink,
|
|
5525
|
-
|
|
5550
|
+
getBase64WithMimeType
|
|
5526
5551
|
};
|
|
5527
5552
|
};
|
|
5528
5553
|
|
package/dist/widget.mjs
CHANGED
|
@@ -5488,12 +5488,33 @@ var colorFieldController = (props) => {
|
|
|
5488
5488
|
// src/widget/basic/binary-field/controller.ts
|
|
5489
5489
|
import { useEffect as useEffect13, useId as useId2, useRef as useRef4, useState as useState12 } from "react";
|
|
5490
5490
|
import { isBase64Image } from "@fctc/interface-logic/utils";
|
|
5491
|
+
var ALLOWED_TYPES = [
|
|
5492
|
+
"image/jpeg",
|
|
5493
|
+
"image/png",
|
|
5494
|
+
"application/pdf",
|
|
5495
|
+
"video/mp4",
|
|
5496
|
+
"application/zip",
|
|
5497
|
+
"application/x-zip-compressed",
|
|
5498
|
+
"application/vnd.ms-excel",
|
|
5499
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
5500
|
+
"application/json"
|
|
5501
|
+
];
|
|
5502
|
+
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
5503
|
+
var MAX_TOTAL_SIZE = 50 * 1024 * 1024;
|
|
5491
5504
|
var binaryFieldController = (props) => {
|
|
5492
|
-
const {
|
|
5505
|
+
const {
|
|
5506
|
+
name,
|
|
5507
|
+
methods,
|
|
5508
|
+
readonly = false,
|
|
5509
|
+
value,
|
|
5510
|
+
filename,
|
|
5511
|
+
rootField,
|
|
5512
|
+
index
|
|
5513
|
+
} = props;
|
|
5493
5514
|
const inputId = useId2();
|
|
5494
|
-
const [
|
|
5495
|
-
const [
|
|
5496
|
-
const [
|
|
5515
|
+
const [selectedFile, setSelectedFile] = useState12(null);
|
|
5516
|
+
const [selectedPreview, setSelectedPreview] = useState12(null);
|
|
5517
|
+
const [initialFile, setInitialFile] = useState12(value || null);
|
|
5497
5518
|
const { setValue } = methods;
|
|
5498
5519
|
const binaryRef = useRef4(null);
|
|
5499
5520
|
const convertUrlToBase64 = async (url) => {
|
|
@@ -5502,9 +5523,7 @@ var binaryFieldController = (props) => {
|
|
|
5502
5523
|
const blob = await response.blob();
|
|
5503
5524
|
return new Promise((resolve, reject) => {
|
|
5504
5525
|
const reader = new FileReader();
|
|
5505
|
-
reader.onloadend = () =>
|
|
5506
|
-
resolve(reader.result);
|
|
5507
|
-
};
|
|
5526
|
+
reader.onloadend = () => resolve(reader.result);
|
|
5508
5527
|
reader.onerror = reject;
|
|
5509
5528
|
reader.readAsDataURL(blob);
|
|
5510
5529
|
});
|
|
@@ -5513,40 +5532,13 @@ var binaryFieldController = (props) => {
|
|
|
5513
5532
|
throw error;
|
|
5514
5533
|
}
|
|
5515
5534
|
};
|
|
5516
|
-
const extractBase64Data = (base64Url) =>
|
|
5517
|
-
|
|
5518
|
-
return base64Url.split("base64,")[1];
|
|
5519
|
-
}
|
|
5520
|
-
return base64Url;
|
|
5521
|
-
};
|
|
5522
|
-
const handleImageChange = async (e, onChange) => {
|
|
5523
|
-
if (readonly) return;
|
|
5524
|
-
const file = e?.target?.files?.[0];
|
|
5525
|
-
if (file) {
|
|
5526
|
-
const imageUrl = URL.createObjectURL(file);
|
|
5527
|
-
setSelectedImage(imageUrl);
|
|
5528
|
-
setInitialImage(null);
|
|
5529
|
-
onChange(file);
|
|
5530
|
-
const compressedBase64 = await convertUrlToBase64(imageUrl);
|
|
5531
|
-
const base64Data = extractBase64Data(compressedBase64);
|
|
5532
|
-
setValue(name, base64Data, {
|
|
5533
|
-
shouldDirty: true
|
|
5534
|
-
});
|
|
5535
|
-
}
|
|
5536
|
-
};
|
|
5537
|
-
const handleRemoveImage = (onChange) => {
|
|
5538
|
-
setSelectedImage(null);
|
|
5539
|
-
setInitialImage(null);
|
|
5540
|
-
onChange(null);
|
|
5541
|
-
};
|
|
5542
|
-
const isBlobUrl = (url) => {
|
|
5543
|
-
return /^blob:/.test(url);
|
|
5544
|
-
};
|
|
5535
|
+
const extractBase64Data = (base64Url) => base64Url.includes("base64,") ? base64Url.split("base64,")[1] : base64Url;
|
|
5536
|
+
const isBlobUrl = (url) => /^blob:/.test(url);
|
|
5545
5537
|
const checkIsImageLink = (url) => {
|
|
5546
5538
|
const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
|
|
5547
5539
|
return imageExtensions.test(url) || isBase64Image(url) || isBlobUrl(url);
|
|
5548
5540
|
};
|
|
5549
|
-
const
|
|
5541
|
+
const getBase64WithMimeType = (base64) => {
|
|
5550
5542
|
if (typeof base64 !== "string" || base64.length < 10) return null;
|
|
5551
5543
|
if (isBase64Image(base64)) return base64;
|
|
5552
5544
|
let mimeType = null;
|
|
@@ -5557,29 +5549,62 @@ var binaryFieldController = (props) => {
|
|
|
5557
5549
|
else if (base64.startsWith("UklGR")) mimeType = "image/webp";
|
|
5558
5550
|
return mimeType ? `data:${mimeType};base64,${base64}` : null;
|
|
5559
5551
|
};
|
|
5552
|
+
const handleFileChange = async (e, onChange) => {
|
|
5553
|
+
if (readonly) return;
|
|
5554
|
+
const file = e?.target?.files?.[0];
|
|
5555
|
+
if (!file) return;
|
|
5556
|
+
if (!ALLOWED_TYPES.includes(file.type)) {
|
|
5557
|
+
alert(`File type not allowed: ${file.type}`);
|
|
5558
|
+
return;
|
|
5559
|
+
}
|
|
5560
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
5561
|
+
alert(`File exceeds 10MB limit.`);
|
|
5562
|
+
return;
|
|
5563
|
+
}
|
|
5564
|
+
const fileUrl = URL.createObjectURL(file);
|
|
5565
|
+
setSelectedFile(file);
|
|
5566
|
+
setInitialFile(null);
|
|
5567
|
+
setSelectedPreview(fileUrl);
|
|
5568
|
+
onChange(file);
|
|
5569
|
+
if (file.type.startsWith("image/") || file.type === "application/json") {
|
|
5570
|
+
const base64 = await convertUrlToBase64(fileUrl);
|
|
5571
|
+
const base64Data = extractBase64Data(base64);
|
|
5572
|
+
setValue(name, base64Data, { shouldDirty: true });
|
|
5573
|
+
} else {
|
|
5574
|
+
setValue(name, file, { shouldDirty: true });
|
|
5575
|
+
}
|
|
5576
|
+
if (filename) {
|
|
5577
|
+
setValue(
|
|
5578
|
+
rootField ? `${rootField?.name}.${index}.${filename}` : filename,
|
|
5579
|
+
file?.name,
|
|
5580
|
+
{ shouldDirty: true }
|
|
5581
|
+
);
|
|
5582
|
+
}
|
|
5583
|
+
};
|
|
5584
|
+
const handleRemoveFile = (onChange) => {
|
|
5585
|
+
if (selectedPreview) URL.revokeObjectURL(selectedPreview);
|
|
5586
|
+
setSelectedFile(null);
|
|
5587
|
+
setSelectedPreview(null);
|
|
5588
|
+
setInitialFile(null);
|
|
5589
|
+
onChange(null);
|
|
5590
|
+
};
|
|
5560
5591
|
useEffect13(() => {
|
|
5561
5592
|
return () => {
|
|
5562
|
-
if (
|
|
5563
|
-
URL.revokeObjectURL(
|
|
5593
|
+
if (selectedPreview) {
|
|
5594
|
+
URL.revokeObjectURL(selectedPreview);
|
|
5564
5595
|
}
|
|
5565
5596
|
};
|
|
5566
|
-
}, [
|
|
5567
|
-
useEffect13(() => {
|
|
5568
|
-
if (binaryRef.current) {
|
|
5569
|
-
const isInsideTable2 = !!binaryRef.current.closest("table");
|
|
5570
|
-
setIsInsideTable(isInsideTable2);
|
|
5571
|
-
}
|
|
5572
|
-
}, []);
|
|
5597
|
+
}, [selectedPreview]);
|
|
5573
5598
|
return {
|
|
5574
5599
|
inputId,
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5600
|
+
selectedFile,
|
|
5601
|
+
selectedPreview,
|
|
5602
|
+
initialFile,
|
|
5578
5603
|
binaryRef,
|
|
5579
|
-
|
|
5580
|
-
|
|
5604
|
+
handleFileChange,
|
|
5605
|
+
handleRemoveFile,
|
|
5581
5606
|
checkIsImageLink,
|
|
5582
|
-
|
|
5607
|
+
getBase64WithMimeType
|
|
5583
5608
|
};
|
|
5584
5609
|
};
|
|
5585
5610
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fctc/widget-logic",
|
|
3
|
-
"version": "3.10.
|
|
3
|
+
"version": "3.10.7",
|
|
4
4
|
"types": "dist/index.d.ts",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"test": "jest"
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@fctc/interface-logic": "^3.5.
|
|
77
|
+
"@fctc/interface-logic": "^3.5.1",
|
|
78
78
|
"@headlessui/react": "^2.2.6",
|
|
79
79
|
"@tanstack/react-query": "^5.84.0",
|
|
80
80
|
"i18next": "^25.3.2",
|