@fctc/widget-logic 5.2.8 → 5.3.0

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/index.d.mts CHANGED
@@ -2,7 +2,7 @@ export { useAddEntity, useButton, useChangeOrderPreparationState, useChangeStatu
2
2
  export { ActionResultType, AppProvider, CompanyTuple, ContextProfile, CurrentCompany, RecordMenu, UseMenuReturn, ViewResponse, useAppProvider, useCallAction, useCallActionType, useClickOutside, useCompany, useCompanyType, useConfig, useConfigType, useDebounce, useDetail, useGetAction, useGetRowIds, useGetSpecification, useListData, useListDataType, useMenu, useMenuType, useProfile, useUser, useUserType, useViewV2, useViewV2Type } from './hooks.mjs';
3
3
  export * from '@fctc/interface-logic/configs';
4
4
  export { CheckIcon, ChevronBottomIcon, CloseIcon, EyeIcon, FilterIcon, GroupByIcon, LoadingIcon, SearchIcon } from './icons.mjs';
5
- export { ISelctionStateProps, ITableHeadProps, ITableProps, binaryFieldController, colorFieldController, copyLinkButtonController, dateFieldController, downLoadBinaryController, downloadFileController, durationController, many2manyFieldController, many2manyTagsController, many2oneButtonController, many2oneFieldController, priorityFieldController, searchController, statusDropdownController, tableController, tableGroupController, tableHeadController } from './widget.mjs';
5
+ export { ISelctionStateProps, ITableHeadProps, ITableProps, binaryFieldController, colorFieldController, copyLinkButtonController, dateFieldController, downLoadBinaryController, downloadFileController, durationController, many2manyBinaryController, many2manyFieldController, many2manyTagsController, many2oneButtonController, many2oneFieldController, priorityFieldController, searchController, statusDropdownController, tableController, tableGroupController, tableHeadController } from './widget.mjs';
6
6
  export * from '@fctc/interface-logic/types';
7
7
  export { IInputFieldProps, ValuePropsType } from './types.mjs';
8
8
  export { STORAGES, combineContexts, convertFieldsToArray, countSum, getDateRange, languages, mergeButtons, setStorageItemAsync, useStorageState } from './utils.mjs';
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { useAddEntity, useButton, useChangeOrderPreparationState, useChangeStatu
2
2
  export { ActionResultType, AppProvider, CompanyTuple, ContextProfile, CurrentCompany, RecordMenu, UseMenuReturn, ViewResponse, useAppProvider, useCallAction, useCallActionType, useClickOutside, useCompany, useCompanyType, useConfig, useConfigType, useDebounce, useDetail, useGetAction, useGetRowIds, useGetSpecification, useListData, useListDataType, useMenu, useMenuType, useProfile, useUser, useUserType, useViewV2, useViewV2Type } from './hooks.js';
3
3
  export * from '@fctc/interface-logic/configs';
4
4
  export { CheckIcon, ChevronBottomIcon, CloseIcon, EyeIcon, FilterIcon, GroupByIcon, LoadingIcon, SearchIcon } from './icons.js';
5
- export { ISelctionStateProps, ITableHeadProps, ITableProps, binaryFieldController, colorFieldController, copyLinkButtonController, dateFieldController, downLoadBinaryController, downloadFileController, durationController, many2manyFieldController, many2manyTagsController, many2oneButtonController, many2oneFieldController, priorityFieldController, searchController, statusDropdownController, tableController, tableGroupController, tableHeadController } from './widget.js';
5
+ export { ISelctionStateProps, ITableHeadProps, ITableProps, binaryFieldController, colorFieldController, copyLinkButtonController, dateFieldController, downLoadBinaryController, downloadFileController, durationController, many2manyBinaryController, many2manyFieldController, many2manyTagsController, many2oneButtonController, many2oneFieldController, priorityFieldController, searchController, statusDropdownController, tableController, tableGroupController, tableHeadController } from './widget.js';
6
6
  export * from '@fctc/interface-logic/types';
7
7
  export { IInputFieldProps, ValuePropsType } from './types.js';
8
8
  export { STORAGES, combineContexts, convertFieldsToArray, countSum, getDateRange, languages, mergeButtons, setStorageItemAsync, useStorageState } from './utils.js';
package/dist/index.js CHANGED
@@ -4057,6 +4057,7 @@ __export(index_exports, {
4057
4057
  durationController: () => durationController,
4058
4058
  getDateRange: () => getDateRange,
4059
4059
  languages: () => languages,
4060
+ many2manyBinaryController: () => many2manyBinaryController,
4060
4061
  many2manyFieldController: () => many2manyFieldController,
4061
4062
  many2manyTagsController: () => many2manyTagsController,
4062
4063
  many2oneButtonController: () => many2oneButtonController,
@@ -4257,6 +4258,7 @@ var languages = [
4257
4258
  { id: "vi_VN", name: "VIE" },
4258
4259
  { id: "en_US", name: "ENG" }
4259
4260
  ];
4261
+ var isBlobUrl = (url) => url.startsWith("blob:");
4260
4262
 
4261
4263
  // src/utils/function.ts
4262
4264
  var import_react2 = require("react");
@@ -6344,6 +6346,77 @@ var binaryFieldController = (props) => {
6344
6346
 
6345
6347
  // src/widget/basic/many2many-binary-field/controller.tsx
6346
6348
  var import_react23 = require("react");
6349
+ var many2manyBinaryController = (props) => {
6350
+ const {
6351
+ name,
6352
+ methods,
6353
+ value,
6354
+ onChange: handleOnchange,
6355
+ service,
6356
+ xNode,
6357
+ path
6358
+ } = props;
6359
+ const inputId = (0, import_react23.useId)();
6360
+ const { useUploadFile: useUploadFile2 } = (0, provider_exports.useService)();
6361
+ const { mutateAsync } = useUploadFile2();
6362
+ const binaryRef = (0, import_react23.useRef)(null);
6363
+ const [initialFiles, setInitialFiles] = (0, import_react23.useState)(
6364
+ Array.isArray(value) ? value : value ? [value] : []
6365
+ );
6366
+ const checkIsImageLink = (url) => {
6367
+ const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
6368
+ return imageExtensions.test(url) || (0, utils_exports.isBase64Image)(url) || isBlobUrl(url);
6369
+ };
6370
+ const sanitizeForBE = (list) => list.filter((x) => x?.datas && !isBlobUrl(x.datas)).map((x) => ({ name: x.name, datas: x.datas, mimetype: x.mimetype }));
6371
+ const handleFileChange = async (files, e, oldValues) => {
6372
+ try {
6373
+ const uploadedUrls = await Promise.all(
6374
+ files.map(async (f) => {
6375
+ const formData = new FormData();
6376
+ formData.append("file", f);
6377
+ const res = await mutateAsync({ formData, service, xNode, path });
6378
+ return res?.url;
6379
+ })
6380
+ );
6381
+ const uploadedItems = files.map((f, i) => ({
6382
+ name: f.name,
6383
+ datas: uploadedUrls[i] ?? "",
6384
+ mimetype: f.type
6385
+ }));
6386
+ const finalList = [...oldValues, ...uploadedItems];
6387
+ methods?.setValue(name, finalList, { shouldDirty: true });
6388
+ const payloadForBE = sanitizeForBE(finalList);
6389
+ handleOnchange && handleOnchange(name ?? "", payloadForBE);
6390
+ } catch (err) {
6391
+ console.error(err);
6392
+ } finally {
6393
+ e.target.value = "";
6394
+ }
6395
+ };
6396
+ const handleRemoveAt = (idx) => {
6397
+ const current = methods?.getValues(name) || [];
6398
+ const next = current.filter((_, i) => i !== idx);
6399
+ setInitialFiles((p) => p.filter((_, i) => i !== idx));
6400
+ methods?.setValue(name, next.length ? next : null, { shouldDirty: true });
6401
+ const payloadForBE = next.length ? sanitizeForBE(next) : null;
6402
+ handleOnchange && handleOnchange(name ?? "", payloadForBE);
6403
+ };
6404
+ const handleRemoveAll = () => {
6405
+ setInitialFiles([]);
6406
+ methods?.setValue(name, null, { shouldDirty: true });
6407
+ handleOnchange && handleOnchange(name ?? "", null);
6408
+ };
6409
+ return {
6410
+ inputId,
6411
+ initialFiles,
6412
+ binaryRef,
6413
+ handleFileChange,
6414
+ handleRemoveAt,
6415
+ handleRemoveAll,
6416
+ checkIsImageLink,
6417
+ setInitialFiles
6418
+ };
6419
+ };
6347
6420
 
6348
6421
  // src/widget/advance/table/table-head/controller.ts
6349
6422
  var import_react24 = require("react");
@@ -7005,6 +7078,7 @@ __reExport(index_exports, types_exports, module.exports);
7005
7078
  durationController,
7006
7079
  getDateRange,
7007
7080
  languages,
7081
+ many2manyBinaryController,
7008
7082
  many2manyFieldController,
7009
7083
  many2manyTagsController,
7010
7084
  many2oneButtonController,
package/dist/index.mjs CHANGED
@@ -4061,6 +4061,7 @@ __export(index_exports, {
4061
4061
  durationController: () => durationController,
4062
4062
  getDateRange: () => getDateRange,
4063
4063
  languages: () => languages,
4064
+ many2manyBinaryController: () => many2manyBinaryController,
4064
4065
  many2manyFieldController: () => many2manyFieldController,
4065
4066
  many2manyTagsController: () => many2manyTagsController,
4066
4067
  many2oneButtonController: () => many2oneButtonController,
@@ -4346,6 +4347,7 @@ var languages = [
4346
4347
  { id: "vi_VN", name: "VIE" },
4347
4348
  { id: "en_US", name: "ENG" }
4348
4349
  ];
4350
+ var isBlobUrl = (url) => url.startsWith("blob:");
4349
4351
 
4350
4352
  // src/utils/function.ts
4351
4353
  import { useCallback as useCallback2, useEffect, useReducer } from "react";
@@ -6439,6 +6441,77 @@ var binaryFieldController = (props) => {
6439
6441
 
6440
6442
  // src/widget/basic/many2many-binary-field/controller.tsx
6441
6443
  import { useId as useId2, useRef as useRef4, useState as useState13 } from "react";
6444
+ var many2manyBinaryController = (props) => {
6445
+ const {
6446
+ name,
6447
+ methods,
6448
+ value,
6449
+ onChange: handleOnchange,
6450
+ service,
6451
+ xNode,
6452
+ path
6453
+ } = props;
6454
+ const inputId = useId2();
6455
+ const { useUploadFile: useUploadFile2 } = (0, provider_exports.useService)();
6456
+ const { mutateAsync } = useUploadFile2();
6457
+ const binaryRef = useRef4(null);
6458
+ const [initialFiles, setInitialFiles] = useState13(
6459
+ Array.isArray(value) ? value : value ? [value] : []
6460
+ );
6461
+ const checkIsImageLink = (url) => {
6462
+ const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
6463
+ return imageExtensions.test(url) || (0, utils_exports.isBase64Image)(url) || isBlobUrl(url);
6464
+ };
6465
+ const sanitizeForBE = (list) => list.filter((x) => x?.datas && !isBlobUrl(x.datas)).map((x) => ({ name: x.name, datas: x.datas, mimetype: x.mimetype }));
6466
+ const handleFileChange = async (files, e, oldValues) => {
6467
+ try {
6468
+ const uploadedUrls = await Promise.all(
6469
+ files.map(async (f) => {
6470
+ const formData = new FormData();
6471
+ formData.append("file", f);
6472
+ const res = await mutateAsync({ formData, service, xNode, path });
6473
+ return res?.url;
6474
+ })
6475
+ );
6476
+ const uploadedItems = files.map((f, i) => ({
6477
+ name: f.name,
6478
+ datas: uploadedUrls[i] ?? "",
6479
+ mimetype: f.type
6480
+ }));
6481
+ const finalList = [...oldValues, ...uploadedItems];
6482
+ methods?.setValue(name, finalList, { shouldDirty: true });
6483
+ const payloadForBE = sanitizeForBE(finalList);
6484
+ handleOnchange && handleOnchange(name ?? "", payloadForBE);
6485
+ } catch (err) {
6486
+ console.error(err);
6487
+ } finally {
6488
+ e.target.value = "";
6489
+ }
6490
+ };
6491
+ const handleRemoveAt = (idx) => {
6492
+ const current = methods?.getValues(name) || [];
6493
+ const next = current.filter((_, i) => i !== idx);
6494
+ setInitialFiles((p) => p.filter((_, i) => i !== idx));
6495
+ methods?.setValue(name, next.length ? next : null, { shouldDirty: true });
6496
+ const payloadForBE = next.length ? sanitizeForBE(next) : null;
6497
+ handleOnchange && handleOnchange(name ?? "", payloadForBE);
6498
+ };
6499
+ const handleRemoveAll = () => {
6500
+ setInitialFiles([]);
6501
+ methods?.setValue(name, null, { shouldDirty: true });
6502
+ handleOnchange && handleOnchange(name ?? "", null);
6503
+ };
6504
+ return {
6505
+ inputId,
6506
+ initialFiles,
6507
+ binaryRef,
6508
+ handleFileChange,
6509
+ handleRemoveAt,
6510
+ handleRemoveAll,
6511
+ checkIsImageLink,
6512
+ setInitialFiles
6513
+ };
6514
+ };
6442
6515
 
6443
6516
  // src/widget/advance/table/table-head/controller.ts
6444
6517
  import { useMemo as useMemo10, useRef as useRef5 } from "react";
@@ -7104,6 +7177,7 @@ export {
7104
7177
  durationController,
7105
7178
  getDateRange,
7106
7179
  languages,
7180
+ many2manyBinaryController,
7107
7181
  many2manyFieldController,
7108
7182
  many2manyTagsController,
7109
7183
  many2oneButtonController,
package/dist/widget.d.mts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react from 'react';
2
+ import { ChangeEvent } from 'react';
2
3
  import { IInputFieldProps } from './types.mjs';
3
4
  import moment from 'moment';
4
5
  import '@fctc/interface-logic/types';
@@ -232,6 +233,26 @@ declare const binaryFieldController: (props: IBinaryFieldProps) => {
232
233
  url: any;
233
234
  };
234
235
 
236
+ type UploadDeps = {
237
+ service?: any;
238
+ xNode?: any;
239
+ path?: any;
240
+ };
241
+
242
+ declare const many2manyBinaryController: (props: IInputFieldProps & UploadDeps & {
243
+ rootField?: any;
244
+ index?: number;
245
+ }) => {
246
+ inputId: string;
247
+ initialFiles: any[];
248
+ binaryRef: react.RefObject<HTMLDivElement>;
249
+ handleFileChange: (files: any, e: ChangeEvent<HTMLInputElement>, oldValues: any) => Promise<void>;
250
+ handleRemoveAt: (idx: number) => void;
251
+ handleRemoveAll: () => void;
252
+ checkIsImageLink: (url: string) => boolean;
253
+ setInitialFiles: react.Dispatch<react.SetStateAction<any[]>>;
254
+ };
255
+
235
256
  declare const tableHeadController: (props: any) => {
236
257
  handleCheckBoxAll: (event: React.ChangeEvent<HTMLInputElement>) => void;
237
258
  checkedAll: any;
@@ -319,4 +340,4 @@ declare const searchController: ({ viewData, model, domain, context, fieldsList,
319
340
  hoveredIndexSearchList: number | null;
320
341
  };
321
342
 
322
- export { type ISelctionStateProps, type ITableHeadProps, type ITableProps, binaryFieldController, colorFieldController, copyLinkButtonController, dateFieldController, downLoadBinaryController, downloadFileController, durationController, many2manyFieldController, many2manyTagsController, many2oneButtonController, many2oneFieldController, priorityFieldController, searchController, statusDropdownController, tableController, tableGroupController, tableHeadController };
343
+ export { type ISelctionStateProps, type ITableHeadProps, type ITableProps, binaryFieldController, colorFieldController, copyLinkButtonController, dateFieldController, downLoadBinaryController, downloadFileController, durationController, many2manyBinaryController, many2manyFieldController, many2manyTagsController, many2oneButtonController, many2oneFieldController, priorityFieldController, searchController, statusDropdownController, tableController, tableGroupController, tableHeadController };
package/dist/widget.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react from 'react';
2
+ import { ChangeEvent } from 'react';
2
3
  import { IInputFieldProps } from './types.js';
3
4
  import moment from 'moment';
4
5
  import '@fctc/interface-logic/types';
@@ -232,6 +233,26 @@ declare const binaryFieldController: (props: IBinaryFieldProps) => {
232
233
  url: any;
233
234
  };
234
235
 
236
+ type UploadDeps = {
237
+ service?: any;
238
+ xNode?: any;
239
+ path?: any;
240
+ };
241
+
242
+ declare const many2manyBinaryController: (props: IInputFieldProps & UploadDeps & {
243
+ rootField?: any;
244
+ index?: number;
245
+ }) => {
246
+ inputId: string;
247
+ initialFiles: any[];
248
+ binaryRef: react.RefObject<HTMLDivElement>;
249
+ handleFileChange: (files: any, e: ChangeEvent<HTMLInputElement>, oldValues: any) => Promise<void>;
250
+ handleRemoveAt: (idx: number) => void;
251
+ handleRemoveAll: () => void;
252
+ checkIsImageLink: (url: string) => boolean;
253
+ setInitialFiles: react.Dispatch<react.SetStateAction<any[]>>;
254
+ };
255
+
235
256
  declare const tableHeadController: (props: any) => {
236
257
  handleCheckBoxAll: (event: React.ChangeEvent<HTMLInputElement>) => void;
237
258
  checkedAll: any;
@@ -319,4 +340,4 @@ declare const searchController: ({ viewData, model, domain, context, fieldsList,
319
340
  hoveredIndexSearchList: number | null;
320
341
  };
321
342
 
322
- export { type ISelctionStateProps, type ITableHeadProps, type ITableProps, binaryFieldController, colorFieldController, copyLinkButtonController, dateFieldController, downLoadBinaryController, downloadFileController, durationController, many2manyFieldController, many2manyTagsController, many2oneButtonController, many2oneFieldController, priorityFieldController, searchController, statusDropdownController, tableController, tableGroupController, tableHeadController };
343
+ export { type ISelctionStateProps, type ITableHeadProps, type ITableProps, binaryFieldController, colorFieldController, copyLinkButtonController, dateFieldController, downLoadBinaryController, downloadFileController, durationController, many2manyBinaryController, many2manyFieldController, many2manyTagsController, many2oneButtonController, many2oneFieldController, priorityFieldController, searchController, statusDropdownController, tableController, tableGroupController, tableHeadController };
package/dist/widget.js CHANGED
@@ -4042,6 +4042,7 @@ __export(widget_exports, {
4042
4042
  downLoadBinaryController: () => downLoadBinaryController,
4043
4043
  downloadFileController: () => downloadFileController,
4044
4044
  durationController: () => durationController,
4045
+ many2manyBinaryController: () => many2manyBinaryController,
4045
4046
  many2manyFieldController: () => many2manyFieldController,
4046
4047
  many2manyTagsController: () => many2manyTagsController,
4047
4048
  many2oneButtonController: () => many2oneButtonController,
@@ -4147,6 +4148,7 @@ var languages = [
4147
4148
  { id: "vi_VN", name: "VIE" },
4148
4149
  { id: "en_US", name: "ENG" }
4149
4150
  ];
4151
+ var isBlobUrl = (url) => url.startsWith("blob:");
4150
4152
 
4151
4153
  // src/utils/function.ts
4152
4154
  var import_react3 = require("react");
@@ -5582,6 +5584,77 @@ var binaryFieldController = (props) => {
5582
5584
 
5583
5585
  // src/widget/basic/many2many-binary-field/controller.tsx
5584
5586
  var import_react23 = require("react");
5587
+ var many2manyBinaryController = (props) => {
5588
+ const {
5589
+ name,
5590
+ methods,
5591
+ value,
5592
+ onChange: handleOnchange,
5593
+ service,
5594
+ xNode,
5595
+ path
5596
+ } = props;
5597
+ const inputId = (0, import_react23.useId)();
5598
+ const { useUploadFile: useUploadFile2 } = (0, provider_exports.useService)();
5599
+ const { mutateAsync } = useUploadFile2();
5600
+ const binaryRef = (0, import_react23.useRef)(null);
5601
+ const [initialFiles, setInitialFiles] = (0, import_react23.useState)(
5602
+ Array.isArray(value) ? value : value ? [value] : []
5603
+ );
5604
+ const checkIsImageLink = (url) => {
5605
+ const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
5606
+ return imageExtensions.test(url) || (0, utils_exports.isBase64Image)(url) || isBlobUrl(url);
5607
+ };
5608
+ const sanitizeForBE = (list) => list.filter((x) => x?.datas && !isBlobUrl(x.datas)).map((x) => ({ name: x.name, datas: x.datas, mimetype: x.mimetype }));
5609
+ const handleFileChange = async (files, e, oldValues) => {
5610
+ try {
5611
+ const uploadedUrls = await Promise.all(
5612
+ files.map(async (f) => {
5613
+ const formData = new FormData();
5614
+ formData.append("file", f);
5615
+ const res = await mutateAsync({ formData, service, xNode, path });
5616
+ return res?.url;
5617
+ })
5618
+ );
5619
+ const uploadedItems = files.map((f, i) => ({
5620
+ name: f.name,
5621
+ datas: uploadedUrls[i] ?? "",
5622
+ mimetype: f.type
5623
+ }));
5624
+ const finalList = [...oldValues, ...uploadedItems];
5625
+ methods?.setValue(name, finalList, { shouldDirty: true });
5626
+ const payloadForBE = sanitizeForBE(finalList);
5627
+ handleOnchange && handleOnchange(name ?? "", payloadForBE);
5628
+ } catch (err) {
5629
+ console.error(err);
5630
+ } finally {
5631
+ e.target.value = "";
5632
+ }
5633
+ };
5634
+ const handleRemoveAt = (idx) => {
5635
+ const current = methods?.getValues(name) || [];
5636
+ const next = current.filter((_, i) => i !== idx);
5637
+ setInitialFiles((p) => p.filter((_, i) => i !== idx));
5638
+ methods?.setValue(name, next.length ? next : null, { shouldDirty: true });
5639
+ const payloadForBE = next.length ? sanitizeForBE(next) : null;
5640
+ handleOnchange && handleOnchange(name ?? "", payloadForBE);
5641
+ };
5642
+ const handleRemoveAll = () => {
5643
+ setInitialFiles([]);
5644
+ methods?.setValue(name, null, { shouldDirty: true });
5645
+ handleOnchange && handleOnchange(name ?? "", null);
5646
+ };
5647
+ return {
5648
+ inputId,
5649
+ initialFiles,
5650
+ binaryRef,
5651
+ handleFileChange,
5652
+ handleRemoveAt,
5653
+ handleRemoveAll,
5654
+ checkIsImageLink,
5655
+ setInitialFiles
5656
+ };
5657
+ };
5585
5658
 
5586
5659
  // src/widget/advance/table/table-head/controller.ts
5587
5660
  var import_react24 = require("react");
@@ -6195,6 +6268,7 @@ var searchController = ({
6195
6268
  downLoadBinaryController,
6196
6269
  downloadFileController,
6197
6270
  durationController,
6271
+ many2manyBinaryController,
6198
6272
  many2manyFieldController,
6199
6273
  many2manyTagsController,
6200
6274
  many2oneButtonController,
package/dist/widget.mjs CHANGED
@@ -4214,6 +4214,7 @@ var languages = [
4214
4214
  { id: "vi_VN", name: "VIE" },
4215
4215
  { id: "en_US", name: "ENG" }
4216
4216
  ];
4217
+ var isBlobUrl = (url) => url.startsWith("blob:");
4217
4218
 
4218
4219
  // src/utils/function.ts
4219
4220
  import { useCallback as useCallback2, useEffect as useEffect2, useReducer } from "react";
@@ -5654,6 +5655,77 @@ var binaryFieldController = (props) => {
5654
5655
 
5655
5656
  // src/widget/basic/many2many-binary-field/controller.tsx
5656
5657
  import { useId as useId2, useRef as useRef4, useState as useState13 } from "react";
5658
+ var many2manyBinaryController = (props) => {
5659
+ const {
5660
+ name,
5661
+ methods,
5662
+ value,
5663
+ onChange: handleOnchange,
5664
+ service,
5665
+ xNode,
5666
+ path
5667
+ } = props;
5668
+ const inputId = useId2();
5669
+ const { useUploadFile: useUploadFile2 } = (0, provider_exports.useService)();
5670
+ const { mutateAsync } = useUploadFile2();
5671
+ const binaryRef = useRef4(null);
5672
+ const [initialFiles, setInitialFiles] = useState13(
5673
+ Array.isArray(value) ? value : value ? [value] : []
5674
+ );
5675
+ const checkIsImageLink = (url) => {
5676
+ const imageExtensions = /\.(jpg|jpeg|png|gif|bmp|webp|svg|tiff|ico)$/i;
5677
+ return imageExtensions.test(url) || (0, utils_exports.isBase64Image)(url) || isBlobUrl(url);
5678
+ };
5679
+ const sanitizeForBE = (list) => list.filter((x) => x?.datas && !isBlobUrl(x.datas)).map((x) => ({ name: x.name, datas: x.datas, mimetype: x.mimetype }));
5680
+ const handleFileChange = async (files, e, oldValues) => {
5681
+ try {
5682
+ const uploadedUrls = await Promise.all(
5683
+ files.map(async (f) => {
5684
+ const formData = new FormData();
5685
+ formData.append("file", f);
5686
+ const res = await mutateAsync({ formData, service, xNode, path });
5687
+ return res?.url;
5688
+ })
5689
+ );
5690
+ const uploadedItems = files.map((f, i) => ({
5691
+ name: f.name,
5692
+ datas: uploadedUrls[i] ?? "",
5693
+ mimetype: f.type
5694
+ }));
5695
+ const finalList = [...oldValues, ...uploadedItems];
5696
+ methods?.setValue(name, finalList, { shouldDirty: true });
5697
+ const payloadForBE = sanitizeForBE(finalList);
5698
+ handleOnchange && handleOnchange(name ?? "", payloadForBE);
5699
+ } catch (err) {
5700
+ console.error(err);
5701
+ } finally {
5702
+ e.target.value = "";
5703
+ }
5704
+ };
5705
+ const handleRemoveAt = (idx) => {
5706
+ const current = methods?.getValues(name) || [];
5707
+ const next = current.filter((_, i) => i !== idx);
5708
+ setInitialFiles((p) => p.filter((_, i) => i !== idx));
5709
+ methods?.setValue(name, next.length ? next : null, { shouldDirty: true });
5710
+ const payloadForBE = next.length ? sanitizeForBE(next) : null;
5711
+ handleOnchange && handleOnchange(name ?? "", payloadForBE);
5712
+ };
5713
+ const handleRemoveAll = () => {
5714
+ setInitialFiles([]);
5715
+ methods?.setValue(name, null, { shouldDirty: true });
5716
+ handleOnchange && handleOnchange(name ?? "", null);
5717
+ };
5718
+ return {
5719
+ inputId,
5720
+ initialFiles,
5721
+ binaryRef,
5722
+ handleFileChange,
5723
+ handleRemoveAt,
5724
+ handleRemoveAll,
5725
+ checkIsImageLink,
5726
+ setInitialFiles
5727
+ };
5728
+ };
5657
5729
 
5658
5730
  // src/widget/advance/table/table-head/controller.ts
5659
5731
  import { useMemo as useMemo10, useRef as useRef5 } from "react";
@@ -6267,6 +6339,7 @@ export {
6267
6339
  downLoadBinaryController,
6268
6340
  downloadFileController,
6269
6341
  durationController,
6342
+ many2manyBinaryController,
6270
6343
  many2manyFieldController,
6271
6344
  many2manyTagsController,
6272
6345
  many2oneButtonController,
package/package.json CHANGED
@@ -1,92 +1,92 @@
1
- {
2
- "name": "@fctc/widget-logic",
3
- "version": "5.2.8",
4
- "types": "dist/index.d.ts",
5
- "main": "dist/index.cjs",
6
- "module": "dist/index.mjs",
7
- "exports": {
8
- ".": {
9
- "types": "./dist/index.d.ts",
10
- "import": "./dist/index.mjs",
11
- "require": "./dist/index.cjs"
12
- },
13
- "./hooks": {
14
- "types": "./dist/hooks.d.ts",
15
- "import": "./dist/hooks.mjs",
16
- "require": "./dist/hooks.cjs"
17
- },
18
- "./widget": {
19
- "types": "./dist/widget.d.ts",
20
- "import": "./dist/widget.mjs",
21
- "require": "./dist/widget.cjs"
22
- },
23
- "./icons": {
24
- "types": "./dist/icons.d.ts",
25
- "import": "./dist/icons.mjs",
26
- "require": "./dist/icons.cjs"
27
- },
28
- "./utils": {
29
- "types": "./dist/utils.d.ts",
30
- "import": "./dist/utils.mjs",
31
- "require": "./dist/utils.cjs"
32
- },
33
- "./store": {
34
- "types": "./dist/store.d.ts",
35
- "import": "./dist/store.mjs",
36
- "require": "./dist/store.cjs"
37
- },
38
- "./config": {
39
- "types": "./dist/config.d.ts",
40
- "import": "./dist/config.mjs",
41
- "require": "./dist/config.cjs"
42
- },
43
- "./constants": {
44
- "types": "./dist/constants.d.ts",
45
- "import": "./dist/constants.mjs",
46
- "require": "./dist/constants.cjs"
47
- },
48
- "./environment": {
49
- "types": "./dist/environment.d.ts",
50
- "import": "./dist/environment.mjs",
51
- "require": "./dist/environment.cjs"
52
- },
53
- "./provider": {
54
- "types": "./dist/provider.d.ts",
55
- "import": "./dist/provider.mjs",
56
- "require": "./dist/provider.cjs"
57
- },
58
- "./services": {
59
- "types": "./dist/services.d.ts",
60
- "import": "./dist/services.mjs",
61
- "require": "./dist/services.cjs"
62
- },
63
- "./types": {
64
- "types": "./dist/types.d.ts",
65
- "import": "./dist/types.mjs",
66
- "require": "./dist/types.cjs"
67
- }
68
- },
69
- "files": [
70
- "dist"
71
- ],
72
- "scripts": {
73
- "build": "tsup",
74
- "test": "jest"
75
- },
76
- "dependencies": {
77
- "@fctc/interface-logic": "^4.5.3",
78
- "@tanstack/react-query": "^5.84.0",
79
- "i18next": "^25.3.2",
80
- "i18next-browser-languagedetector": "^8.2.0",
81
- "react-i18next": "^15.6.1"
82
- },
83
- "devDependencies": {
84
- "@types/react": "^18.3.1",
85
- "jest": "^29.7.0",
86
- "react": "18.0.0",
87
- "tsup": "^8.0.0",
88
- "typescript": "^5.8.2"
89
- },
90
- "packageManager": "yarn@1.22.0",
91
- "peerDependencies": {}
92
- }
1
+ {
2
+ "name": "@fctc/widget-logic",
3
+ "version": "5.3.0",
4
+ "types": "dist/index.d.ts",
5
+ "main": "dist/index.cjs",
6
+ "module": "dist/index.mjs",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.cjs"
12
+ },
13
+ "./hooks": {
14
+ "types": "./dist/hooks.d.ts",
15
+ "import": "./dist/hooks.mjs",
16
+ "require": "./dist/hooks.cjs"
17
+ },
18
+ "./widget": {
19
+ "types": "./dist/widget.d.ts",
20
+ "import": "./dist/widget.mjs",
21
+ "require": "./dist/widget.cjs"
22
+ },
23
+ "./icons": {
24
+ "types": "./dist/icons.d.ts",
25
+ "import": "./dist/icons.mjs",
26
+ "require": "./dist/icons.cjs"
27
+ },
28
+ "./utils": {
29
+ "types": "./dist/utils.d.ts",
30
+ "import": "./dist/utils.mjs",
31
+ "require": "./dist/utils.cjs"
32
+ },
33
+ "./store": {
34
+ "types": "./dist/store.d.ts",
35
+ "import": "./dist/store.mjs",
36
+ "require": "./dist/store.cjs"
37
+ },
38
+ "./config": {
39
+ "types": "./dist/config.d.ts",
40
+ "import": "./dist/config.mjs",
41
+ "require": "./dist/config.cjs"
42
+ },
43
+ "./constants": {
44
+ "types": "./dist/constants.d.ts",
45
+ "import": "./dist/constants.mjs",
46
+ "require": "./dist/constants.cjs"
47
+ },
48
+ "./environment": {
49
+ "types": "./dist/environment.d.ts",
50
+ "import": "./dist/environment.mjs",
51
+ "require": "./dist/environment.cjs"
52
+ },
53
+ "./provider": {
54
+ "types": "./dist/provider.d.ts",
55
+ "import": "./dist/provider.mjs",
56
+ "require": "./dist/provider.cjs"
57
+ },
58
+ "./services": {
59
+ "types": "./dist/services.d.ts",
60
+ "import": "./dist/services.mjs",
61
+ "require": "./dist/services.cjs"
62
+ },
63
+ "./types": {
64
+ "types": "./dist/types.d.ts",
65
+ "import": "./dist/types.mjs",
66
+ "require": "./dist/types.cjs"
67
+ }
68
+ },
69
+ "files": [
70
+ "dist"
71
+ ],
72
+ "scripts": {
73
+ "build": "tsup",
74
+ "test": "jest"
75
+ },
76
+ "dependencies": {
77
+ "@fctc/interface-logic": "^4.5.4",
78
+ "@tanstack/react-query": "^5.84.0",
79
+ "i18next": "^25.3.2",
80
+ "i18next-browser-languagedetector": "^8.2.0",
81
+ "react-i18next": "^15.6.1"
82
+ },
83
+ "devDependencies": {
84
+ "@types/react": "^18.3.1",
85
+ "jest": "^29.7.0",
86
+ "react": "18.0.0",
87
+ "tsup": "^8.0.0",
88
+ "typescript": "^5.8.2"
89
+ },
90
+ "packageManager": "yarn@1.22.0",
91
+ "peerDependencies": {}
92
+ }