@solidxai/core-ui 0.1.13-beta.1 → 0.1.13-beta.3

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.
Files changed (94) hide show
  1. package/dist/components/common/SolidFieldTooltip.d.ts.map +1 -1
  2. package/dist/components/common/SolidFieldTooltip.js +33 -1
  3. package/dist/components/common/SolidFieldTooltip.js.map +1 -1
  4. package/dist/components/common/SolidFieldTooltip.tsx +64 -8
  5. package/dist/components/core/chatter/SolidChatter.d.ts.map +1 -1
  6. package/dist/components/core/chatter/SolidChatter.js +4 -2
  7. package/dist/components/core/chatter/SolidChatter.js.map +1 -1
  8. package/dist/components/core/chatter/SolidChatter.tsx +4 -1
  9. package/dist/components/core/chatter/SolidChatterMentionMenu.d.ts +9 -0
  10. package/dist/components/core/chatter/SolidChatterMentionMenu.d.ts.map +1 -0
  11. package/dist/components/core/chatter/SolidChatterMentionMenu.js +18 -0
  12. package/dist/components/core/chatter/SolidChatterMentionMenu.js.map +1 -0
  13. package/dist/components/core/chatter/SolidChatterMentionMenu.tsx +45 -0
  14. package/dist/components/core/chatter/SolidChatterMessageBox.d.ts +1 -0
  15. package/dist/components/core/chatter/SolidChatterMessageBox.d.ts.map +1 -1
  16. package/dist/components/core/chatter/SolidChatterMessageBox.js +29 -5
  17. package/dist/components/core/chatter/SolidChatterMessageBox.js.map +1 -1
  18. package/dist/components/core/chatter/SolidChatterMessageBox.tsx +57 -4
  19. package/dist/components/core/chatter/SolidMessageComposer.d.ts.map +1 -1
  20. package/dist/components/core/chatter/SolidMessageComposer.js +33 -7
  21. package/dist/components/core/chatter/SolidMessageComposer.js.map +1 -1
  22. package/dist/components/core/chatter/SolidMessageComposer.tsx +61 -7
  23. package/dist/components/core/chatter/chatter.module.css +63 -0
  24. package/dist/components/core/chatter/chatterMentions.d.ts +17 -0
  25. package/dist/components/core/chatter/chatterMentions.d.ts.map +1 -0
  26. package/dist/components/core/chatter/chatterMentions.js +50 -0
  27. package/dist/components/core/chatter/chatterMentions.js.map +1 -0
  28. package/dist/components/core/chatter/chatterMentions.ts +59 -0
  29. package/dist/components/core/chatter/useChatterMentions.d.ts +26 -0
  30. package/dist/components/core/chatter/useChatterMentions.d.ts.map +1 -0
  31. package/dist/components/core/chatter/useChatterMentions.js +204 -0
  32. package/dist/components/core/chatter/useChatterMentions.js.map +1 -0
  33. package/dist/components/core/chatter/useChatterMentions.ts +160 -0
  34. package/dist/components/core/form/fields/SolidMediaMultipleField.d.ts.map +1 -1
  35. package/dist/components/core/form/fields/SolidMediaMultipleField.js +111 -106
  36. package/dist/components/core/form/fields/SolidMediaMultipleField.js.map +1 -1
  37. package/dist/components/core/form/fields/SolidMediaMultipleField.tsx +165 -134
  38. package/dist/components/core/form/fields/SolidMediaSingleField.d.ts.map +1 -1
  39. package/dist/components/core/form/fields/SolidMediaSingleField.js +81 -84
  40. package/dist/components/core/form/fields/SolidMediaSingleField.js.map +1 -1
  41. package/dist/components/core/form/fields/SolidMediaSingleField.tsx +97 -86
  42. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.d.ts +1 -1
  43. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.d.ts.map +1 -1
  44. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.js +4 -0
  45. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.js.map +1 -1
  46. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.tsx +6 -0
  47. package/dist/components/core/list/SolidListView.d.ts.map +1 -1
  48. package/dist/components/core/list/SolidListView.js +4 -3
  49. package/dist/components/core/list/SolidListView.js.map +1 -1
  50. package/dist/components/core/list/SolidListView.tsx +4 -3
  51. package/dist/components/core/list/columns/SolidMediaMultipleColumn.d.ts.map +1 -1
  52. package/dist/components/core/list/columns/SolidMediaMultipleColumn.js +42 -81
  53. package/dist/components/core/list/columns/SolidMediaMultipleColumn.js.map +1 -1
  54. package/dist/components/core/list/columns/SolidMediaMultipleColumn.tsx +90 -120
  55. package/dist/components/core/list/columns/SolidMediaSingleColumn.d.ts.map +1 -1
  56. package/dist/components/core/list/columns/SolidMediaSingleColumn.js +34 -42
  57. package/dist/components/core/list/columns/SolidMediaSingleColumn.js.map +1 -1
  58. package/dist/components/core/list/columns/SolidMediaSingleColumn.tsx +51 -46
  59. package/dist/components/core/model/CreateModel.d.ts.map +1 -1
  60. package/dist/components/core/model/CreateModel.js +3 -2
  61. package/dist/components/core/model/CreateModel.js.map +1 -1
  62. package/dist/components/core/model/CreateModel.tsx +4 -1
  63. package/dist/components/core/model/FieldMetaData.d.ts +1 -1
  64. package/dist/components/core/model/FieldMetaData.d.ts.map +1 -1
  65. package/dist/components/core/model/FieldMetaData.js +17 -17
  66. package/dist/components/core/model/FieldMetaData.js.map +1 -1
  67. package/dist/components/core/model/FieldMetaData.tsx +10 -2
  68. package/dist/components/shad-cn-ui/SolidTextarea.d.ts +1 -1
  69. package/dist/components/shad-cn-ui/SolidTextarea.d.ts.map +1 -1
  70. package/dist/components/shad-cn-ui/SolidTextarea.js +4 -3
  71. package/dist/components/shad-cn-ui/SolidTextarea.js.map +1 -1
  72. package/dist/components/shad-cn-ui/SolidTextarea.tsx +4 -2
  73. package/dist/helpers/downloadMediaFile.d.ts.map +1 -1
  74. package/dist/helpers/downloadMediaFile.js +10 -3
  75. package/dist/helpers/downloadMediaFile.js.map +1 -1
  76. package/dist/helpers/downloadMediaFile.tsx +13 -7
  77. package/dist/helpers/fileTypeIcon.d.ts +3 -2
  78. package/dist/helpers/fileTypeIcon.d.ts.map +1 -1
  79. package/dist/helpers/fileTypeIcon.js +11 -7
  80. package/dist/helpers/fileTypeIcon.js.map +1 -1
  81. package/dist/helpers/fileTypeIcon.tsx +12 -7
  82. package/dist/helpers/mediaType.d.ts +7 -0
  83. package/dist/helpers/mediaType.d.ts.map +1 -1
  84. package/dist/helpers/mediaType.js +39 -8
  85. package/dist/helpers/mediaType.js.map +1 -1
  86. package/dist/helpers/mediaType.ts +46 -7
  87. package/dist/helpers/mediaUrl.d.ts +2 -0
  88. package/dist/helpers/mediaUrl.d.ts.map +1 -0
  89. package/dist/helpers/mediaUrl.js +10 -0
  90. package/dist/helpers/mediaUrl.js.map +1 -0
  91. package/dist/helpers/mediaUrl.ts +11 -0
  92. package/dist/resources/globals.css +14 -0
  93. package/dist/resources/solid-tailwind-generated.css +1 -1
  94. package/package.json +1 -1
@@ -0,0 +1,160 @@
1
+ import { type ChangeEvent, type KeyboardEvent, type MouseEvent, type RefObject, useEffect, useState } from 'react';
2
+ import { useLazyGetusersQuery } from '../../../redux/api/userApi';
3
+ import { ChatterMention, getMentionCandidate } from './chatterMentions';
4
+
5
+ interface UseChatterMentionsProps {
6
+ value: string;
7
+ onChange: (value: string) => void;
8
+ textareaRef: RefObject<HTMLTextAreaElement | null>;
9
+ }
10
+
11
+ export const useChatterMentions = ({ value, onChange, textareaRef }: UseChatterMentionsProps) => {
12
+ const [mentions, setMentions] = useState<ChatterMention[]>([]);
13
+ const [mentionQuery, setMentionQuery] = useState('');
14
+ const [mentionRange, setMentionRange] = useState<{ start: number; end: number } | null>(null);
15
+ const [mentionSuggestions, setMentionSuggestions] = useState<any[]>([]);
16
+ const [activeMentionIndex, setActiveMentionIndex] = useState(0);
17
+ const [getUsers, { isFetching: isFetchingMentionUsers }] = useLazyGetusersQuery();
18
+
19
+ const closeMentionMenu = () => {
20
+ setMentionRange(null);
21
+ setMentionQuery('');
22
+ setMentionSuggestions([]);
23
+ setActiveMentionIndex(0);
24
+ };
25
+
26
+ const updateMentionState = (nextValue: string, cursorPosition: number) => {
27
+ const candidate = getMentionCandidate(nextValue, cursorPosition);
28
+ if (!candidate) {
29
+ closeMentionMenu();
30
+ return;
31
+ }
32
+
33
+ setMentionRange({ start: candidate.start, end: candidate.end });
34
+ setMentionQuery(candidate.query);
35
+ };
36
+
37
+ const handleMentionTextChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
38
+ const nextValue = event.target.value;
39
+ onChange(nextValue);
40
+ updateMentionState(nextValue, event.target.selectionStart ?? nextValue.length);
41
+ };
42
+
43
+ const handleMentionKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {
44
+ if (!mentionRange) return;
45
+
46
+ if (event.key === 'ArrowDown') {
47
+ event.preventDefault();
48
+ setActiveMentionIndex(prev => {
49
+ if (mentionSuggestions.length === 0) return 0;
50
+ return (prev + 1) % mentionSuggestions.length;
51
+ });
52
+ return;
53
+ }
54
+
55
+ if (event.key === 'ArrowUp') {
56
+ event.preventDefault();
57
+ setActiveMentionIndex(prev => {
58
+ if (mentionSuggestions.length === 0) return 0;
59
+ return (prev - 1 + mentionSuggestions.length) % mentionSuggestions.length;
60
+ });
61
+ return;
62
+ }
63
+
64
+ if (event.key === 'Enter' || event.key === 'Tab') {
65
+ if (mentionSuggestions[activeMentionIndex]) {
66
+ event.preventDefault();
67
+ handleSelectMention(mentionSuggestions[activeMentionIndex]);
68
+ }
69
+ return;
70
+ }
71
+
72
+ if (event.key === 'Escape') {
73
+ event.preventDefault();
74
+ closeMentionMenu();
75
+ }
76
+ };
77
+
78
+ const handleMentionKeyUp = (event: KeyboardEvent<HTMLTextAreaElement>) => {
79
+ if (['ArrowDown', 'ArrowUp', 'Enter', 'Tab', 'Escape'].includes(event.key)) return;
80
+ const target = event.currentTarget;
81
+ updateMentionState(target.value, target.selectionStart ?? target.value.length);
82
+ };
83
+
84
+ const handleMentionClick = (event: MouseEvent<HTMLTextAreaElement>) => {
85
+ updateMentionState(event.currentTarget.value, event.currentTarget.selectionStart ?? event.currentTarget.value.length);
86
+ };
87
+
88
+ const handleSelectMention = (user: any) => {
89
+ if (!mentionRange) return;
90
+ const username = user?.username;
91
+ if (!username) return;
92
+
93
+ const mention: ChatterMention = {
94
+ username,
95
+ display_name: user?.fullName || username,
96
+ id: String(user?.id),
97
+ };
98
+ const mentionText = `@${mention.username}`;
99
+ const nextValue = `${value.slice(0, mentionRange.start)}${mentionText} ${value.slice(mentionRange.end)}`;
100
+ const nextCursorPosition = mentionRange.start + mentionText.length + 1;
101
+
102
+ onChange(nextValue);
103
+ setMentions(prev => (
104
+ prev.some(item => item.id === mention.id || item.username === mention.username)
105
+ ? prev
106
+ : [...prev, mention]
107
+ ));
108
+ closeMentionMenu();
109
+
110
+ window.requestAnimationFrame(() => {
111
+ textareaRef.current?.focus();
112
+ textareaRef.current?.setSelectionRange(nextCursorPosition, nextCursorPosition);
113
+ });
114
+ };
115
+
116
+ const resetMentions = (nextMentions: ChatterMention[] = []) => {
117
+ setMentions(nextMentions);
118
+ closeMentionMenu();
119
+ };
120
+
121
+ useEffect(() => {
122
+ if (!mentionRange) return;
123
+
124
+ let isActive = true;
125
+ const timeout = window.setTimeout(async () => {
126
+ try {
127
+ const encodedQuery = encodeURIComponent(mentionQuery);
128
+ const queryString = mentionQuery
129
+ ? `filters[username][$containsi]=${encodedQuery}&limit=8`
130
+ : 'limit=8';
131
+ const response = await getUsers(queryString).unwrap();
132
+ if (!isActive) return;
133
+ setMentionSuggestions(response?.data?.records || []);
134
+ setActiveMentionIndex(0);
135
+ } catch (error) {
136
+ if (isActive) setMentionSuggestions([]);
137
+ }
138
+ }, 180);
139
+
140
+ return () => {
141
+ isActive = false;
142
+ window.clearTimeout(timeout);
143
+ };
144
+ }, [mentionQuery, mentionRange, getUsers]);
145
+
146
+ return {
147
+ mentions,
148
+ setMentions,
149
+ mentionRange,
150
+ mentionSuggestions,
151
+ activeMentionIndex,
152
+ isFetchingMentionUsers,
153
+ handleMentionTextChange,
154
+ handleMentionKeyDown,
155
+ handleMentionKeyUp,
156
+ handleMentionClick,
157
+ handleSelectMention,
158
+ resetMentions,
159
+ };
160
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"SolidMediaMultipleField.d.ts","sourceRoot":"","sources":["../../../../../src/components/core/form/fields/SolidMediaMultipleField.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAK3E,OAAO,EAA6B,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAMzG,qBAAa,uBAAwB,YAAW,WAAW;IAEvD,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,eAAe,CAAC,CAAyD;IACjF,OAAO,CAAC,eAAe,CAAC,CAA0B;gBACtC,YAAY,EAAE,eAAe,EAAE,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,IAAI,EAC/G,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI;IAM7C,cAAc,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,GAAG,GAAG;IAYnD,YAAY,IAAI,GAAG;IAKnB,gBAAgB,IAAI,GAAG,CAAC,MAAM;IAiD9B,MAAM,CAAC,MAAM,EAAE,YAAY;IAmC3B,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY;CAcjE;AAGD,eAAO,MAAM,kCAAkC,+DAAgE,8BAA8B,4CAwW5I,CAAA;AAED,eAAO,MAAM,kCAAkC,+DAAgE,8BAA8B,4CAqK5I,CAAA"}
1
+ {"version":3,"file":"SolidMediaMultipleField.d.ts","sourceRoot":"","sources":["../../../../../src/components/core/form/fields/SolidMediaMultipleField.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAO3E,OAAO,EAA6B,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAOzG,qBAAa,uBAAwB,YAAW,WAAW;IAEvD,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,eAAe,CAAC,CAAyD;IACjF,OAAO,CAAC,eAAe,CAAC,CAA0B;gBACtC,YAAY,EAAE,eAAe,EAAE,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,IAAI,EAC/G,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI;IAM7C,cAAc,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,GAAG,GAAG;IAYnD,YAAY,IAAI,GAAG;IAKnB,gBAAgB,IAAI,GAAG,CAAC,MAAM;IAiD9B,MAAM,CAAC,MAAM,EAAE,YAAY;IAmC3B,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY;CAcjE;AAGD,eAAO,MAAM,kCAAkC,+DAAgE,8BAA8B,4CA+X5I,CAAA;AAED,eAAO,MAAM,kCAAkC,+DAAgE,8BAA8B,4CA0K5I,CAAA"}
@@ -67,6 +67,8 @@ import { FileReaderExt } from "../../../../components/common/FileReaderExt";
67
67
  import getAcceptedFileTypes from "../../../../helpers/getAcceptedFileTypes";
68
68
  import { downloadMediaFile } from "../../../../helpers/downloadMediaFile";
69
69
  import { getExtensionComponent } from "../../../../helpers/registry";
70
+ import { openMediaInNewTab } from "../../../../helpers/mediaUrl";
71
+ import { getMediaPreviewKind, isLightboxMediaKind } from "../../../../helpers/mediaType";
70
72
  import { SolidFieldTooltip } from "../../../../components/common/SolidFieldTooltip";
71
73
  import { ERROR_MESSAGES } from "../../../../constants/error-messages";
72
74
  import styles from "./solidFields.module.css";
@@ -233,40 +235,42 @@ export var DefaultMediaMultipleFormEditWidget = function (_a) {
233
235
  var deleteMedia = useDeleteMediaMutation()[0];
234
236
  useEffect(function () {
235
237
  var fieldValue = formik === null || formik === void 0 ? void 0 : formik.values[fieldLayoutInfo.attrs.name];
236
- var objectUrls = [];
237
- if (Array.isArray(fieldValue) && fieldValue.length > 0) {
238
- var details_1 = [];
239
- fieldValue.forEach(function (file) {
240
- if (file instanceof File) {
241
- var fileUrl = URL.createObjectURL(file);
242
- objectUrls.push(fileUrl);
243
- details_1.push({
244
- name: file.name,
245
- type: file.type,
246
- size: file.size,
247
- mediaId: null,
248
- fileKey: buildMediaFieldKey(file),
249
- fileUrl: fileUrl
250
- });
251
- }
252
- else if (typeof file === "object" && file._full_url) {
253
- details_1.push({
254
- name: file.originalFileName,
255
- type: file.mimeType,
256
- size: file.fileSize,
257
- mediaId: getPersistedMediaId(file),
258
- fileKey: buildMediaFieldKey(file),
259
- fileUrl: file._full_url
260
- });
261
- }
262
- });
263
- setFileDetails(details_1);
264
- }
265
- else {
238
+ if (!Array.isArray(fieldValue) || fieldValue.length === 0) {
266
239
  setFileDetails([]);
240
+ return;
267
241
  }
242
+ var objectUrls = [];
243
+ var details = fieldValue
244
+ .map(function (file) {
245
+ if (file instanceof File) {
246
+ var fileUrl_1 = URL.createObjectURL(file);
247
+ objectUrls.push(fileUrl_1);
248
+ return {
249
+ name: file.name,
250
+ type: file.type,
251
+ size: file.size,
252
+ mediaId: null,
253
+ fileKey: buildMediaFieldKey(file),
254
+ fileUrl: fileUrl_1,
255
+ };
256
+ }
257
+ var fileUrl = file === null || file === void 0 ? void 0 : file._full_url;
258
+ if (!fileUrl) {
259
+ return null;
260
+ }
261
+ return {
262
+ name: file.originalFileName,
263
+ type: file.mimeType,
264
+ size: file.fileSize,
265
+ mediaId: getPersistedMediaId(file),
266
+ fileKey: buildMediaFieldKey(file),
267
+ fileUrl: fileUrl,
268
+ };
269
+ })
270
+ .filter(function (detail) { return detail !== null; });
271
+ setFileDetails(details);
268
272
  return function () {
269
- objectUrls.forEach(function (url) { return URL.revokeObjectURL(url); });
273
+ objectUrls.forEach(function (fileUrl) { return URL.revokeObjectURL(fileUrl); });
270
274
  };
271
275
  }, [formik.values, fieldLayoutInfo.attrs.name]);
272
276
  var handleDropImages = function (acceptedFiles) {
@@ -369,40 +373,41 @@ export var DefaultMediaMultipleFormEditWidget = function (_a) {
369
373
  setOpenLightbox: setOpenLightbox
370
374
  };
371
375
  var handleFileView = function (url) {
372
- var _a;
373
- var downloadOnlyExt = [
374
- "txt", "zip", "rar",
375
- "doc", "docx",
376
- "xls", "xlsx",
377
- "ppt", "pptx"
378
- ];
379
- var fileUrl = (url === null || url === void 0 ? void 0 : url.fileUrl) || "";
380
- var cleanUrl = fileUrl.split("?")[0];
381
- var ext = (_a = cleanUrl.split(".").pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
382
- if (ext && downloadOnlyExt.includes(ext)) {
383
- var link = document.createElement('a');
384
- link.href = url.fileUrl;
385
- link.download = ''; // or specify a file name like 'file.pdf'
386
- link.target = '_blank';
387
- document.body.appendChild(link);
388
- link.click();
389
- document.body.removeChild(link);
390
- }
391
- else {
376
+ var previewKind = getMediaPreviewKind({
377
+ url: url === null || url === void 0 ? void 0 : url.fileUrl,
378
+ fileName: url === null || url === void 0 ? void 0 : url.name,
379
+ mimeType: url === null || url === void 0 ? void 0 : url.type,
380
+ });
381
+ if (isLightboxMediaKind(previewKind)) {
392
382
  setLightboxUrls === null || setLightboxUrls === void 0 ? void 0 : setLightboxUrls([
393
- { src: url.fileUrl, downloadUrl: url.fileUrl },
383
+ {
384
+ src: url.fileUrl,
385
+ downloadUrl: url.fileUrl,
386
+ type: previewKind === "video" ? "video" : undefined
387
+ },
394
388
  ]);
395
389
  setOpenLightbox === null || setOpenLightbox === void 0 ? void 0 : setOpenLightbox(true);
390
+ return;
396
391
  }
392
+ openMediaInNewTab(url === null || url === void 0 ? void 0 : url.fileUrl);
397
393
  };
398
394
  return (_jsxs("div", { style: readOnlyPermission === true ? { filter: 'opacity(50%)', pointerEvents: 'none' } : {}, children: [_jsxs("div", { className: "".concat(styles.fieldWrapper, " relative"), children: [showFieldLabel != false &&
399
395
  _jsxs("label", { htmlFor: fieldLayoutInfo.attrs.name, className: "".concat(styles.fieldLabel, " form-field-label"), children: [fieldLabel, fieldMetadata.required && _jsx("span", { className: "text-red-500", children: " *" }), _jsx(SolidFieldTooltip, { fieldContext: fieldContext })] }), _jsxs("div", { className: "relative", children: [_jsxs("div", __assign({}, getRootProps(), { className: "solid-dropzone-wrapper", children: [_jsx("input", __assign({}, getInputProps())), _jsx(DropzonePlaceholder, { mediaTypes: fieldMetadata.mediaTypes, mediaMaxSizeKb: fieldMetadata.mediaMaxSizeKb })] })), isFormFieldValid(formik, fieldLayoutInfo.attrs.name) && (_jsx("div", { className: "absolute mt-1", children: _jsx(SolidMessage, { severity: "error", text: (_p = formik === null || formik === void 0 ? void 0 : formik.errors[fieldLayoutInfo.attrs.name]) === null || _p === void 0 ? void 0 : _p.toString() }) }))] }), fileSizeError &&
400
396
  _jsx(SolidMessage, { severity: "error", text: fileSizeError === null || fileSizeError === void 0 ? void 0 : fileSizeError.toString() })] }), fileDetails.length > 0 &&
401
- _jsx("div", { className: "solid-file-upload-wrapper", children: _jsxs("div", { className: "flex items-center md:gap-2", children: [_jsx(FileReaderExt, { fileDetails: fileDetails[0] }), _jsxs("div", { className: "w-full flex flex-col gap-1", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("p", { className: "m-0 w-9 font-normal text-[var(--primary-color)] solid-img-text-wrapper", style: { cursor: 'pointer' }, onClick: function () { return handleFileView(fileDetails[0]); }, children: fileDetails[0].name }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", className: "solid-file-icon-btn", disabled: isFieldDisabled || isFieldReadonly, "aria-label": "Download file", onClick: function () { var _a, _b; return downloadMediaFile((_a = fileDetails[0]) === null || _a === void 0 ? void 0 : _a.fileUrl, (_b = fileDetails[0]) === null || _b === void 0 ? void 0 : _b.name); }, children: _jsx(SolidIcon, { name: "si-download", "aria-hidden": true }) }), _jsx("button", { type: "button", className: "solid-file-icon-btn is-danger", disabled: isFieldDisabled || isFieldReadonly, "aria-label": "Remove file", onClick: function () { return confirmDeleteFile(fileDetails[0].fileKey); }, children: _jsx(SolidIcon, { name: "si-times", "aria-hidden": true }) })] })] }), _jsx("div", { className: "flex items-center gap-2 text-sm", children: formatFileSize(fileDetails[0].size) })] })] }) }), fileDetails.length > 1 &&
397
+ _jsx("div", { className: "".concat(styles.mediaAttachmentCard, " mt-4"), children: _jsxs("div", { className: "".concat(styles.mediaAttachmentRow, " flex items-center md:gap-2"), children: [_jsx(FileReaderExt, { fileDetails: fileDetails[0] }), _jsxs("div", { className: "".concat(styles.mediaAttachmentMeta, " w-full"), children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsx("button", { type: "button", className: styles.mediaAttachmentName, onClick: function () { return handleFileView(fileDetails[0]); }, title: fileDetails[0].name, children: fileDetails[0].name }), _jsxs("div", { className: "".concat(styles.mediaAttachmentActions, " flex items-center gap-2"), children: [_jsx("button", { type: "button", className: "solid-file-icon-btn", disabled: isFieldDisabled || isFieldReadonly, "aria-label": "Download file", onClick: function (event) {
398
+ var _a, _b;
399
+ event.preventDefault();
400
+ event.stopPropagation();
401
+ downloadMediaFile((_a = fileDetails[0]) === null || _a === void 0 ? void 0 : _a.fileUrl, (_b = fileDetails[0]) === null || _b === void 0 ? void 0 : _b.name);
402
+ }, children: _jsx(SolidIcon, { name: "si-download", "aria-hidden": true }) }), _jsx("button", { type: "button", className: "solid-file-icon-btn is-danger", disabled: isFieldDisabled || isFieldReadonly, "aria-label": "Remove file", onClick: function () { return confirmDeleteFile(fileDetails[0].fileKey); }, children: _jsx(SolidIcon, { name: "si-times", "aria-hidden": true }) })] })] }), _jsx("div", { className: styles.mediaAttachmentSize, children: formatFileSize(fileDetails[0].size) })] })] }) }), fileDetails.length > 1 &&
402
403
  _jsxs("div", { className: "flex items-center mt-1", children: [_jsxs("p", { className: "m-0", children: [fileDetails.length - 1, " items"] }), _jsx("div", { children: _jsx(SolidButton, { type: "button", size: "sm", variant: "ghost", onClick: function () { return setShowAllFiles(true); }, children: "View" }) })] }), _jsxs(SolidDialog, { open: isShowAllFiles, onOpenChange: setShowAllFiles, style: { minWidth: 450 }, children: [_jsxs(SolidDialogHeader, { children: [_jsx(SolidDialogTitle, { children: "Items Uploaded" }), _jsx(SolidDialogClose, {})] }), _jsx(SolidDialogBody, { children: fileDetails.length > 1 &&
403
404
  fileDetails.map(function (file, index) {
404
405
  var fileId = file.fileKey;
405
- return (_jsx("div", { className: "solid-file-upload-wrapper", children: _jsxs("div", { className: "flex items-center md:gap-2", children: [_jsx(FileReaderExt, { fileDetails: file }), _jsxs("div", { className: "w-full flex flex-col gap-1", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("p", { className: "m-0 w-11 font-normal text-[var(--primary-color)] solid-img-text-wrapper", style: { cursor: 'pointer' }, onClick: function () { return handleFileView(file); }, children: file.name }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { type: "button", className: "solid-file-icon-btn", disabled: isFieldDisabled || isFieldReadonly, "aria-label": "Download file", onClick: function () { return downloadMediaFile(file === null || file === void 0 ? void 0 : file.fileUrl, file === null || file === void 0 ? void 0 : file.name); }, children: _jsx(SolidIcon, { name: "si-download", "aria-hidden": true }) }), _jsx("button", { type: "button", className: "solid-file-icon-btn is-danger", disabled: isFieldDisabled || isFieldReadonly, "aria-label": "Remove file", onClick: function () { return confirmDeleteFile(fileId); }, children: _jsx(SolidIcon, { name: "si-times", "aria-hidden": true }) })] })] }), _jsx("div", { className: "flex items-center gap-2 text-sm", children: formatFileSize(file.size) })] })] }) }, fileId));
406
+ return (_jsx("div", { className: index === fileDetails.length - 1 ? "" : "mb-3", children: _jsx("div", { className: styles.mediaAttachmentCard, children: _jsxs("div", { className: "".concat(styles.mediaAttachmentRow, " flex items-center md:gap-2"), children: [_jsx(FileReaderExt, { fileDetails: file }), _jsxs("div", { className: "".concat(styles.mediaAttachmentMeta, " w-full"), children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsx("button", { type: "button", className: styles.mediaAttachmentName, onClick: function () { return handleFileView(file); }, title: file.name, children: file.name }), _jsxs("div", { className: "".concat(styles.mediaAttachmentActions, " flex items-center gap-2"), children: [_jsx("button", { type: "button", className: "solid-file-icon-btn", disabled: isFieldDisabled || isFieldReadonly, "aria-label": "Download file", onClick: function (event) {
407
+ event.preventDefault();
408
+ event.stopPropagation();
409
+ downloadMediaFile(file === null || file === void 0 ? void 0 : file.fileUrl, file === null || file === void 0 ? void 0 : file.name);
410
+ }, children: _jsx(SolidIcon, { name: "si-download", "aria-hidden": true }) }), _jsx("button", { type: "button", className: "solid-file-icon-btn is-danger", disabled: isFieldDisabled || isFieldReadonly, "aria-label": "Remove file", onClick: function () { return confirmDeleteFile(fileId); }, children: _jsx(SolidIcon, { name: "si-times", "aria-hidden": true }) })] })] }), _jsx("div", { className: styles.mediaAttachmentSize, children: formatFileSize(file.size) })] })] }) }) }, fileId));
406
411
  }) })] }), _jsxs(SolidDialog, { open: isDeleteImageDialogVisible, onOpenChange: setDeleteImageDialogVisible, className: "solid-shadcn-confirm-dialog", children: [_jsxs(SolidDialogHeader, { className: "solid-shadcn-dialog-head", children: [_jsx(SolidDialogTitle, { children: "Confirm Delete" }), _jsx(SolidDialogClose, {})] }), _jsx(SolidDialogSeparator, { className: "solid-shadcn-dialog-sep" }), _jsx(SolidDialogBody, { className: "solid-shadcn-dialog-body", children: _jsx("p", { className: "solid-shadcn-dialog-text", children: "Are you sure you want to delete this file?" }) }), _jsxs(SolidDialogFooter, { className: "solid-shadcn-dialog-actions", children: [_jsx(SolidButton, { variant: "destructive", size: "sm", autoFocus: true, onClick: deleteFile, children: "Delete" }), _jsx(SolidButton, { variant: "outline", size: "sm", onClick: function () { return setDeleteImageDialogVisible(false); }, children: "Cancel" })] })] })] }));
407
412
  };
408
413
  export var DefaultMediaMultipleFormViewWidget = function (_a) {
@@ -423,68 +428,68 @@ export var DefaultMediaMultipleFormViewWidget = function (_a) {
423
428
  };
424
429
  useEffect(function () {
425
430
  var fieldValue = formik === null || formik === void 0 ? void 0 : formik.values[fieldLayoutInfo.attrs.name];
426
- if (Array.isArray(fieldValue) && fieldValue.length > 0) {
427
- var urls_1 = [];
428
- var details_2 = [];
429
- var objectUrls_1 = [];
430
- fieldValue.forEach(function (file) {
431
- if (file instanceof File) {
432
- // New file (from local upload)
433
- var fileUrl = URL.createObjectURL(file);
434
- objectUrls_1.push(fileUrl); // Store URL for cleanup
435
- urls_1.push(fileUrl);
436
- details_2.push({
437
- name: file.name,
438
- type: file.type,
439
- size: file.size,
440
- id: "".concat(file.name, "-").concat(file.size),
441
- fileUrl: fileUrl // ✅ Store the generated object URL
442
- });
443
- }
444
- else if (typeof file === "object" && file._full_url) {
445
- urls_1.push(file._full_url);
446
- details_2.push({
447
- name: file.originalFileName,
448
- type: file.mimeType,
449
- size: file.fileSize,
450
- id: file.id,
451
- fileUrl: file._full_url
452
- });
453
- }
454
- });
455
- setFileDetails(details_2);
431
+ if (!Array.isArray(fieldValue) || fieldValue.length === 0) {
432
+ setFileDetails([]);
433
+ return;
456
434
  }
435
+ var objectUrls = [];
436
+ var details = fieldValue
437
+ .map(function (file) {
438
+ if (file instanceof File) {
439
+ var fileUrl_2 = URL.createObjectURL(file);
440
+ objectUrls.push(fileUrl_2);
441
+ return {
442
+ name: file.name,
443
+ type: file.type,
444
+ size: file.size,
445
+ id: "".concat(file.name, "-").concat(file.size),
446
+ fileUrl: fileUrl_2,
447
+ };
448
+ }
449
+ var fileUrl = file === null || file === void 0 ? void 0 : file._full_url;
450
+ if (!fileUrl) {
451
+ return null;
452
+ }
453
+ return {
454
+ name: file.originalFileName,
455
+ type: file.mimeType,
456
+ size: file.fileSize,
457
+ id: file.id,
458
+ fileUrl: fileUrl,
459
+ };
460
+ })
461
+ .filter(Boolean);
462
+ setFileDetails(details);
463
+ return function () {
464
+ objectUrls.forEach(function (fileUrl) { return URL.revokeObjectURL(fileUrl); });
465
+ };
457
466
  }, [formik.values, fieldLayoutInfo.attrs.name]);
458
467
  var handleFileView = function (url) {
459
- var _a;
460
- var downloadOnlyExt = [
461
- "txt", "zip", "rar",
462
- "doc", "docx",
463
- "xls", "xlsx",
464
- "ppt", "pptx"
465
- ];
466
- var fileUrl = (url === null || url === void 0 ? void 0 : url.fileUrl) || "";
467
- var cleanUrl = fileUrl.split("?")[0];
468
- var ext = (_a = cleanUrl.split(".").pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
469
- if (ext && downloadOnlyExt.includes(ext)) {
470
- var link = document.createElement('a');
471
- link.href = url.fileUrl;
472
- link.download = ''; // or specify a file name like 'file.pdf'
473
- link.target = '_blank';
474
- document.body.appendChild(link);
475
- link.click();
476
- document.body.removeChild(link);
477
- }
478
- else {
468
+ var previewKind = getMediaPreviewKind({
469
+ url: url === null || url === void 0 ? void 0 : url.fileUrl,
470
+ fileName: url === null || url === void 0 ? void 0 : url.name,
471
+ mimeType: url === null || url === void 0 ? void 0 : url.type,
472
+ });
473
+ if (isLightboxMediaKind(previewKind)) {
479
474
  setLightboxUrls === null || setLightboxUrls === void 0 ? void 0 : setLightboxUrls([
480
- { src: url.fileUrl, downloadUrl: url.fileUrl },
475
+ {
476
+ src: url.fileUrl,
477
+ downloadUrl: url.fileUrl,
478
+ type: previewKind === "video" ? "video" : undefined
479
+ },
481
480
  ]);
482
481
  setOpenLightbox === null || setOpenLightbox === void 0 ? void 0 : setOpenLightbox(true);
482
+ return;
483
483
  }
484
+ openMediaInNewTab(url === null || url === void 0 ? void 0 : url.fileUrl);
484
485
  };
485
486
  var renderMediaFileCard = function (file, className) {
486
487
  if (className === void 0) { className = ""; }
487
- return (_jsx("div", { className: "".concat(styles.mediaAttachmentCard, " ").concat(className).trim(), children: _jsxs("div", { className: "".concat(styles.mediaAttachmentRow, " flex items-center md:gap-2"), children: [_jsx(FileReaderExt, { fileDetails: file }), _jsxs("div", { className: "".concat(styles.mediaAttachmentMeta, " w-full"), children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsx("button", { type: "button", className: styles.mediaAttachmentName, onClick: function () { return handleFileView(file); }, title: file.name, children: file.name }), _jsx("div", { className: "".concat(styles.mediaAttachmentActions, " flex items-center md:gap-2"), children: _jsx("button", { type: "button", className: "solid-file-icon-btn", "aria-label": "Download file", onClick: function () { return downloadMediaFile(file === null || file === void 0 ? void 0 : file.fileUrl, file === null || file === void 0 ? void 0 : file.name); }, children: _jsx(SolidIcon, { name: "si-download", "aria-hidden": true }) }) })] }), _jsx("div", { className: styles.mediaAttachmentSize, children: formatFileSize(file.size) })] })] }) }));
488
+ return (_jsx("div", { className: "".concat(styles.mediaAttachmentCard, " ").concat(className).trim(), children: _jsxs("div", { className: "".concat(styles.mediaAttachmentRow, " flex items-center md:gap-2"), children: [_jsx(FileReaderExt, { fileDetails: file }), _jsxs("div", { className: "".concat(styles.mediaAttachmentMeta, " w-full"), children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsx("button", { type: "button", className: styles.mediaAttachmentName, onClick: function () { return handleFileView(file); }, title: file.name, children: file.name }), _jsx("div", { className: "".concat(styles.mediaAttachmentActions, " flex items-center md:gap-2"), children: _jsx("button", { type: "button", className: "solid-file-icon-btn", "aria-label": "Download file", onClick: function (event) {
489
+ event.preventDefault();
490
+ event.stopPropagation();
491
+ downloadMediaFile(file === null || file === void 0 ? void 0 : file.fileUrl, file === null || file === void 0 ? void 0 : file.name);
492
+ }, children: _jsx(SolidIcon, { name: "si-download", "aria-hidden": true }) }) })] }), _jsx("div", { className: styles.mediaAttachmentSize, children: formatFileSize(file.size) })] })] }) }));
488
493
  };
489
494
  return (_jsxs("div", { className: styles.fieldViewWrapper, children: [showFieldLabel != false &&
490
495
  _jsxs("p", { className: "".concat(styles.fieldViewLabel, " form-field-label"), children: [fieldLabel, _jsx(SolidFieldTooltip, { fieldContext: fieldContext })] }), fileDetails.length > 0 &&