@onehat/ui 0.4.114 → 0.4.116
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/package.json +1 -1
- package/src/Components/Buttons/Button.js +18 -3
- package/src/Components/Container/Container.js +115 -19
- package/src/Components/Form/Form.js +89 -11
- package/src/Components/Form/FormContext.js +7 -0
- package/src/PlatformImports/Web/Attachments.js +8 -4
- package/src/Styles/Global.css +10 -5
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { cloneElement, forwardRef, isValidElement, useRef } from 'react';
|
|
1
|
+
import { cloneElement, forwardRef, isValidElement, useContext, useRef } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Button,
|
|
4
4
|
ButtonText,
|
|
@@ -10,9 +10,12 @@ import addIconProps from '../../Functions/addIconProps.js';
|
|
|
10
10
|
import clsx from 'clsx';
|
|
11
11
|
import withComponent from '../Hoc/withComponent.js';
|
|
12
12
|
import withTooltip from '../Hoc/withTooltip.js';
|
|
13
|
+
import FormContext from '../Form/FormContext.js';
|
|
13
14
|
import _ from 'lodash';
|
|
14
15
|
|
|
15
16
|
const ButtonComponent = forwardRef((props, ref) => {
|
|
17
|
+
|
|
18
|
+
const formContext = useContext(FormContext);
|
|
16
19
|
let {
|
|
17
20
|
self,
|
|
18
21
|
text, // the text to display on the button
|
|
@@ -32,6 +35,16 @@ const ButtonComponent = forwardRef((props, ref) => {
|
|
|
32
35
|
propsToPass.onPress = propsToPass.handler; // alias
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
const {
|
|
39
|
+
disableOnInvalid,
|
|
40
|
+
...propsToPassWithoutDisableOnInvalid
|
|
41
|
+
} = propsToPass;
|
|
42
|
+
propsToPass = propsToPassWithoutDisableOnInvalid;
|
|
43
|
+
|
|
44
|
+
if (_.isNil(propsToPass.isDisabled) && disableOnInvalid && formContext && !formContext.isValid) {
|
|
45
|
+
propsToPass.isDisabled = true;
|
|
46
|
+
}
|
|
47
|
+
|
|
35
48
|
if (icon) {
|
|
36
49
|
if (isValidElement(icon)) {
|
|
37
50
|
if (_icon) {
|
|
@@ -64,8 +77,10 @@ const ButtonComponent = forwardRef((props, ref) => {
|
|
|
64
77
|
'flex',
|
|
65
78
|
'flex-row',
|
|
66
79
|
'items-center',
|
|
67
|
-
'disabled:opacity-40',
|
|
68
|
-
'disabled:cursor-not-allowed',
|
|
80
|
+
'data-[disabled=true]:opacity-40',
|
|
81
|
+
'data-[disabled=true]:cursor-not-allowed',
|
|
82
|
+
'web:disabled:opacity-40',
|
|
83
|
+
'web:disabled:cursor-not-allowed',
|
|
69
84
|
);
|
|
70
85
|
if (isExpandToFillVertical) {
|
|
71
86
|
// IMPORTANT! Otherwise the button will cut off the vertical content due to size classes automatically added by Gluestack (e.g. h-10)
|
|
@@ -115,6 +115,7 @@ function Container(props) {
|
|
|
115
115
|
southRef = useRef(null),
|
|
116
116
|
eastRef = useRef(null),
|
|
117
117
|
westRef = useRef(null),
|
|
118
|
+
centerWidthRef = useRef(null), // used to store the width of the center area, which is used to calculate max widths for east and west
|
|
118
119
|
northHeightRef = useRef(northInitialHeight),
|
|
119
120
|
southHeightRef = useRef(southInitialHeight),
|
|
120
121
|
eastWidthRef = useRef(eastInitialWidth),
|
|
@@ -202,6 +203,12 @@ function Container(props) {
|
|
|
202
203
|
localEastIsCollapsedRef.current = bool;
|
|
203
204
|
}
|
|
204
205
|
|
|
206
|
+
if (!bool) {
|
|
207
|
+
setSideWidth('east', getEastWidth() ?? eastInitialWidth, {
|
|
208
|
+
ignoreCollapsedCheck: true,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
205
212
|
if (id) {
|
|
206
213
|
setSaved(id + '-eastIsCollapsed', bool);
|
|
207
214
|
}
|
|
@@ -220,6 +227,12 @@ function Container(props) {
|
|
|
220
227
|
localWestIsCollapsedRef.current = bool;
|
|
221
228
|
}
|
|
222
229
|
|
|
230
|
+
if (!bool) {
|
|
231
|
+
setSideWidth('west', getWestWidth() ?? westInitialWidth, {
|
|
232
|
+
ignoreCollapsedCheck: true,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
223
236
|
if (id) {
|
|
224
237
|
setSaved(id + '-westIsCollapsed', bool);
|
|
225
238
|
}
|
|
@@ -253,24 +266,76 @@ function Container(props) {
|
|
|
253
266
|
getSouthHeight = () => {
|
|
254
267
|
return southHeightRef.current;
|
|
255
268
|
},
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
269
|
+
setCenterWidth = (width) => {
|
|
270
|
+
centerWidthRef.current = width;
|
|
271
|
+
},
|
|
272
|
+
getCenterWidth = () => {
|
|
273
|
+
return centerWidthRef.current;
|
|
274
|
+
},
|
|
275
|
+
getMaxSideWidth = () => {
|
|
276
|
+
const width = getCenterWidth();
|
|
277
|
+
if (!_.isFinite(width) || width <= 0) {
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return width;
|
|
282
|
+
},
|
|
283
|
+
clampSideWidth = (width) => {
|
|
284
|
+
if (_.isNil(width)) {
|
|
285
|
+
return width;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const maxSideWidth = getMaxSideWidth();
|
|
289
|
+
if (_.isNil(maxSideWidth)) {
|
|
290
|
+
return width;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return Math.min(width, maxSideWidth);
|
|
294
|
+
},
|
|
295
|
+
setSideWidth = (side, width, opts = {}) => {
|
|
296
|
+
const
|
|
297
|
+
{
|
|
298
|
+
ignoreCollapsedCheck = false,
|
|
299
|
+
} = opts,
|
|
300
|
+
isCollapsed = side === 'east' ? getEastIsCollapsed() : getWestIsCollapsed();
|
|
301
|
+
|
|
302
|
+
if (!ignoreCollapsedCheck && isCollapsed) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const clampedWidth = clampSideWidth(width);
|
|
307
|
+
if (side === 'east') {
|
|
308
|
+
eastWidthRef.current = clampedWidth;
|
|
259
309
|
if (id) {
|
|
260
|
-
setSaved(id + '-eastWidth',
|
|
310
|
+
setSaved(id + '-eastWidth', clampedWidth);
|
|
261
311
|
}
|
|
312
|
+
} else {
|
|
313
|
+
westWidthRef.current = clampedWidth;
|
|
314
|
+
if (id) {
|
|
315
|
+
setSaved(id + '-westWidth', clampedWidth);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
normalizeSideWidthForRender = (width, initialWidth) => {
|
|
320
|
+
if (_.isNil(width)) {
|
|
321
|
+
return width;
|
|
262
322
|
}
|
|
323
|
+
|
|
324
|
+
const maxSideWidth = getMaxSideWidth();
|
|
325
|
+
if (_.isNil(maxSideWidth)) {
|
|
326
|
+
return _.isFinite(initialWidth) && initialWidth > 0 ? initialWidth : width;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return Math.min(width, maxSideWidth);
|
|
330
|
+
},
|
|
331
|
+
setEastWidth = (width) => {
|
|
332
|
+
setSideWidth('east', width);
|
|
263
333
|
},
|
|
264
334
|
getEastWidth = () => {
|
|
265
335
|
return eastWidthRef.current;
|
|
266
336
|
},
|
|
267
337
|
setWestWidth = (width) => {
|
|
268
|
-
|
|
269
|
-
westWidthRef.current = width;
|
|
270
|
-
if (id) {
|
|
271
|
-
setSaved(id + '-westWidth', width);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
338
|
+
setSideWidth('west', width);
|
|
274
339
|
},
|
|
275
340
|
getWestWidth = () => {
|
|
276
341
|
return westWidthRef.current;
|
|
@@ -409,6 +474,7 @@ function Container(props) {
|
|
|
409
474
|
if (!isReady) {
|
|
410
475
|
return null;
|
|
411
476
|
}
|
|
477
|
+
|
|
412
478
|
|
|
413
479
|
let componentProps = { _panel: { ...center?.props?._panel }, },
|
|
414
480
|
wrapperProps = null,
|
|
@@ -533,11 +599,17 @@ function Container(props) {
|
|
|
533
599
|
width: 33,
|
|
534
600
|
};
|
|
535
601
|
} else {
|
|
536
|
-
const eastWidth = getEastWidth();
|
|
602
|
+
const eastWidth = normalizeSideWidthForRender(getEastWidth(), eastInitialWidth);
|
|
537
603
|
if (_.isNil(eastWidth)) {
|
|
538
|
-
wrapperProps.style = {
|
|
604
|
+
wrapperProps.style = {
|
|
605
|
+
flex: eastInitialFlex || 50,
|
|
606
|
+
maxWidth: '100%',
|
|
607
|
+
};
|
|
539
608
|
} else {
|
|
540
|
-
wrapperProps.style = {
|
|
609
|
+
wrapperProps.style = {
|
|
610
|
+
width: eastWidth,
|
|
611
|
+
maxWidth: '100%',
|
|
612
|
+
};
|
|
541
613
|
}
|
|
542
614
|
}
|
|
543
615
|
componentProps._panel.collapseDirection = HORIZONTAL;
|
|
@@ -576,11 +648,17 @@ function Container(props) {
|
|
|
576
648
|
width: 33,
|
|
577
649
|
};
|
|
578
650
|
} else {
|
|
579
|
-
const westWidth = getWestWidth();
|
|
651
|
+
const westWidth = normalizeSideWidthForRender(getWestWidth(), westInitialWidth);
|
|
580
652
|
if (_.isNil(westWidth)) {
|
|
581
|
-
wrapperProps.style = {
|
|
653
|
+
wrapperProps.style = {
|
|
654
|
+
flex: westInitialFlex || 50,
|
|
655
|
+
maxWidth: '100%',
|
|
656
|
+
};
|
|
582
657
|
} else {
|
|
583
|
-
wrapperProps.style = {
|
|
658
|
+
wrapperProps.style = {
|
|
659
|
+
width: westWidth,
|
|
660
|
+
maxWidth: '100%',
|
|
661
|
+
};
|
|
584
662
|
}
|
|
585
663
|
}
|
|
586
664
|
componentProps._panel.collapseDirection = HORIZONTAL;
|
|
@@ -600,13 +678,31 @@ function Container(props) {
|
|
|
600
678
|
{cloneElement(west, componentProps)}
|
|
601
679
|
</BoxNative>;
|
|
602
680
|
}
|
|
603
|
-
return <VStack className="Container-all
|
|
681
|
+
return <VStack className="Container-all flex-1 min-w-0">
|
|
604
682
|
{northComponent}
|
|
605
683
|
{!getNorthIsCollapsed() && northSplitter}
|
|
606
|
-
<HStack
|
|
684
|
+
<HStack
|
|
685
|
+
className="Container-mid w-full flex-[100] min-w-0"
|
|
686
|
+
onLayout={(e) => {
|
|
687
|
+
// Measure available horizontal space for side panels.
|
|
688
|
+
const width = parseFloat(e.nativeEvent.layout.width);
|
|
689
|
+
if (width && width !== getCenterWidth()) {
|
|
690
|
+
// Save latest width and clamp east/west if they exceed it.
|
|
691
|
+
setCenterWidth(width);
|
|
692
|
+
if (getEastWidth() > width) {
|
|
693
|
+
setEastWidth(width);
|
|
694
|
+
}
|
|
695
|
+
if (getWestWidth() > width) {
|
|
696
|
+
setWestWidth(width);
|
|
697
|
+
}
|
|
698
|
+
// Trigger a render so updated widths are applied immediately.
|
|
699
|
+
forceUpdate();
|
|
700
|
+
}
|
|
701
|
+
}}
|
|
702
|
+
>
|
|
607
703
|
{westComponent}
|
|
608
704
|
{!getWestIsCollapsed() && westSplitter}
|
|
609
|
-
<VStack className="Container-center h-full overflow-auto flex-[100]">
|
|
705
|
+
<VStack className="Container-center h-full overflow-auto flex-[100] min-w-0">
|
|
610
706
|
{centerComponent}
|
|
611
707
|
</VStack>
|
|
612
708
|
{!getEastIsCollapsed() && eastSplitter}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useCallback, useState, useRef, isValidElement, } from 'react';
|
|
1
|
+
import { useEffect, useCallback, useState, useRef, isValidElement, cloneElement, Children, } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Box,
|
|
4
4
|
HStack,
|
|
@@ -59,6 +59,7 @@ import Xmark from '../Icons/Xmark.js';
|
|
|
59
59
|
import Check from '../Icons/Check.js';
|
|
60
60
|
import Footer from '../Layout/Footer.js';
|
|
61
61
|
import Label from '../Form/Label.js';
|
|
62
|
+
import FormContext from '../Form/FormContext.js';
|
|
62
63
|
import _ from 'lodash';
|
|
63
64
|
|
|
64
65
|
// TODO: memoize field Components
|
|
@@ -261,6 +262,7 @@ function Form(props) {
|
|
|
261
262
|
context: { isPhantom },
|
|
262
263
|
}),
|
|
263
264
|
currentEditorMode = getEditorMode(),
|
|
265
|
+
resolvedEditorMode = currentEditorMode || props.editorMode || null,
|
|
264
266
|
buildFromColumnsConfig = () => {
|
|
265
267
|
// Only used in InlineEditor
|
|
266
268
|
// Build the fields that match the current columnsConfig in the grid
|
|
@@ -1119,12 +1121,63 @@ function Form(props) {
|
|
|
1119
1121
|
alert(errors.message);
|
|
1120
1122
|
}
|
|
1121
1123
|
},
|
|
1124
|
+
decorateAdditionalFooterItems = (elements) => {
|
|
1125
|
+
const decorateElement = (element) => {
|
|
1126
|
+
if (!isValidElement(element)) {
|
|
1127
|
+
return element;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
const
|
|
1131
|
+
elementProps = element.props || {},
|
|
1132
|
+
propsToInject = {};
|
|
1133
|
+
|
|
1134
|
+
if (elementProps.disableOnInvalid && !formState.isValid) {
|
|
1135
|
+
propsToInject.isDisabled = true;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
if (typeof elementProps.onPress === 'function' && (elementProps.disableOnInvalid || elementProps.skipSubmit || elementProps.submitWithForm)) {
|
|
1139
|
+
const originalOnPress = elementProps.onPress;
|
|
1140
|
+
if (elementProps.skipSubmit) {
|
|
1141
|
+
propsToInject.onPress = () => originalOnPress();
|
|
1142
|
+
} else {
|
|
1143
|
+
propsToInject.onPress = (e) => handleSubmit(originalOnPress, onSubmitError)(e);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
if (elementProps.children) {
|
|
1148
|
+
propsToInject.children = Children.map(elementProps.children, decorateElement);
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
if (_.isEmpty(propsToInject)) {
|
|
1152
|
+
return element;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
return cloneElement(element, propsToInject);
|
|
1156
|
+
};
|
|
1157
|
+
|
|
1158
|
+
return Children.map(elements, decorateElement);
|
|
1159
|
+
},
|
|
1122
1160
|
doReset = (values) => {
|
|
1123
1161
|
reset(values);
|
|
1124
1162
|
if (onReset) {
|
|
1125
1163
|
onReset(values, formSetValue, formGetValues, trigger);
|
|
1126
1164
|
}
|
|
1127
1165
|
},
|
|
1166
|
+
resetFromRecord = () => {
|
|
1167
|
+
if (!record || _.isArray(record) || record.isDestroyed) {
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
const
|
|
1172
|
+
currentValues = formGetValues(),
|
|
1173
|
+
recordValues = record.submitValues || record,
|
|
1174
|
+
nextValues = {
|
|
1175
|
+
...currentValues,
|
|
1176
|
+
..._.pick(recordValues, Object.keys(currentValues)),
|
|
1177
|
+
};
|
|
1178
|
+
|
|
1179
|
+
doReset(nextValues);
|
|
1180
|
+
},
|
|
1128
1181
|
onSaveDecorated = async (data, e) => {
|
|
1129
1182
|
// reset the form after a save
|
|
1130
1183
|
const result = await onSave(data, e);
|
|
@@ -1189,6 +1242,21 @@ function Form(props) {
|
|
|
1189
1242
|
}
|
|
1190
1243
|
}, [record]);
|
|
1191
1244
|
|
|
1245
|
+
useEffect(() => {
|
|
1246
|
+
// If this form is bound to a single record, reset the form whenever that record emits a 'reload' event.
|
|
1247
|
+
// This ensures the form stays in sync with the latest data for that record.
|
|
1248
|
+
|
|
1249
|
+
if (skipAll || !isSingle || !record?.on || !record?.off) {
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
record.on('reload', resetFromRecord);
|
|
1254
|
+
|
|
1255
|
+
return () => {
|
|
1256
|
+
record.off('reload', resetFromRecord);
|
|
1257
|
+
};
|
|
1258
|
+
}, [record, skipAll, isSingle]);
|
|
1259
|
+
|
|
1192
1260
|
useEffect(() => {
|
|
1193
1261
|
if (skipAll) {
|
|
1194
1262
|
return;
|
|
@@ -1313,10 +1381,18 @@ function Form(props) {
|
|
|
1313
1381
|
showCancelBtn = false,
|
|
1314
1382
|
showSaveBtn = false,
|
|
1315
1383
|
showSubmitBtn = false,
|
|
1316
|
-
isAddMode =
|
|
1317
|
-
isEditableMode =
|
|
1318
|
-
|
|
1319
|
-
|
|
1384
|
+
isAddMode = resolvedEditorMode === EDITOR_MODE__ADD,
|
|
1385
|
+
isEditableMode = (() => {
|
|
1386
|
+
// Keep explicit editor modes authoritative, but preserve legacy modal behavior:
|
|
1387
|
+
// if no mode is supplied, treat forms with onSave as editable so Save can render.
|
|
1388
|
+
if (resolvedEditorMode === EDITOR_MODE__ADD || resolvedEditorMode === EDITOR_MODE__EDIT) {
|
|
1389
|
+
return true;
|
|
1390
|
+
}
|
|
1391
|
+
if (resolvedEditorMode === EDITOR_MODE__VIEW) {
|
|
1392
|
+
return false;
|
|
1393
|
+
}
|
|
1394
|
+
return !!onSave;
|
|
1395
|
+
})();
|
|
1320
1396
|
if (containerWidth) { // we need to render this component twice in order to get the container width. Skip this on first render
|
|
1321
1397
|
|
|
1322
1398
|
// create editor
|
|
@@ -1341,7 +1417,7 @@ function Form(props) {
|
|
|
1341
1417
|
additionalButtons = buildAdditionalButtons(additionalEditButtons);
|
|
1342
1418
|
|
|
1343
1419
|
if (inArray(editorType, [EDITOR_TYPE__SIDE, EDITOR_TYPE__SMART, EDITOR_TYPE__WINDOWED]) &&
|
|
1344
|
-
isSingle &&
|
|
1420
|
+
isSingle && resolvedEditorMode === EDITOR_MODE__EDIT &&
|
|
1345
1421
|
(onBack || onViewMode || isEditorModeControlledByParent)) {
|
|
1346
1422
|
modeHeader = <Toolbar>
|
|
1347
1423
|
<HStack className="flex-1 items-center">
|
|
@@ -1377,7 +1453,7 @@ function Form(props) {
|
|
|
1377
1453
|
/>}
|
|
1378
1454
|
</Toolbar>;
|
|
1379
1455
|
}
|
|
1380
|
-
if (
|
|
1456
|
+
if (resolvedEditorMode === EDITOR_MODE__EDIT && !_.isEmpty(additionalButtons)) {
|
|
1381
1457
|
formButtons = <Toolbar className="justify-end flex-wrap gap-2">
|
|
1382
1458
|
{additionalButtons}
|
|
1383
1459
|
</Toolbar>;
|
|
@@ -1402,7 +1478,7 @@ function Form(props) {
|
|
|
1402
1478
|
if (_.isEmpty(formState.dirtyFields) && !isPhantom && !isAddMode) {
|
|
1403
1479
|
isSaveDisabled = true;
|
|
1404
1480
|
}
|
|
1405
|
-
if (onDelete &&
|
|
1481
|
+
if (onDelete && resolvedEditorMode === EDITOR_MODE__EDIT && isSingle) {
|
|
1406
1482
|
showDeleteBtn = true;
|
|
1407
1483
|
}
|
|
1408
1484
|
if (!isEditorViewOnly && isEditableMode && !hideResetButton) {
|
|
@@ -1444,7 +1520,7 @@ function Form(props) {
|
|
|
1444
1520
|
}
|
|
1445
1521
|
footerItems =
|
|
1446
1522
|
<>
|
|
1447
|
-
{additionalFooterItems}
|
|
1523
|
+
{decorateAdditionalFooterItems(additionalFooterItems)}
|
|
1448
1524
|
{!additionalFooterItems && additionalFooterButtons && _.map(additionalFooterButtons, (props, ix) => {
|
|
1449
1525
|
let isDisabled = false;
|
|
1450
1526
|
if (props.disableOnInvalid) {
|
|
@@ -1597,7 +1673,8 @@ function Form(props) {
|
|
|
1597
1673
|
className += ' ' + props.className;
|
|
1598
1674
|
}
|
|
1599
1675
|
const scrollToTopAnchor = <Box ref={(el) => (ancillaryItemsRef.current[0] = el)} className="h-0" />;
|
|
1600
|
-
return <
|
|
1676
|
+
return <FormContext.Provider value={{ isValid: formState.isValid }}>
|
|
1677
|
+
<VStackNative
|
|
1601
1678
|
ref={formRef}
|
|
1602
1679
|
{...testProps(self)}
|
|
1603
1680
|
style={style}
|
|
@@ -1639,7 +1716,8 @@ function Form(props) {
|
|
|
1639
1716
|
{isFabVisible && fab}
|
|
1640
1717
|
|
|
1641
1718
|
</>}
|
|
1642
|
-
</VStackNative
|
|
1719
|
+
</VStackNative>
|
|
1720
|
+
</FormContext.Provider>;
|
|
1643
1721
|
}
|
|
1644
1722
|
|
|
1645
1723
|
// helper fns
|
|
@@ -93,7 +93,7 @@ function FileCardCustom(props) {
|
|
|
93
93
|
onPress={() => {
|
|
94
94
|
downloadInBackground(downloadUrl);
|
|
95
95
|
}}
|
|
96
|
-
className="Pressable px-3 py-1 items-center flex-row rounded-[5px] border border-primary.700"
|
|
96
|
+
className="Pressable max-w-full px-3 py-1 items-center flex-row rounded-[5px] border border-primary.700"
|
|
97
97
|
>
|
|
98
98
|
{isDownloading &&
|
|
99
99
|
<Spinner className="mr-2" />}
|
|
@@ -103,7 +103,7 @@ function FileCardCustom(props) {
|
|
|
103
103
|
icon={Eye}
|
|
104
104
|
onPress={() => onSee(id)}
|
|
105
105
|
/>}
|
|
106
|
-
<Text>{filename}</Text>
|
|
106
|
+
<Text className="max-w-[220px] truncate">{filename}</Text>
|
|
107
107
|
{onDelete &&
|
|
108
108
|
<IconButton
|
|
109
109
|
className="ml-1"
|
|
@@ -868,7 +868,9 @@ function AttachmentsElement(props) {
|
|
|
868
868
|
className={clsx(
|
|
869
869
|
'AttachmentsElement-HStack',
|
|
870
870
|
'flex-1',
|
|
871
|
+
'w-full',
|
|
871
872
|
'min-h-0',
|
|
873
|
+
'min-w-0',
|
|
872
874
|
'overflow-y-auto',
|
|
873
875
|
'gap-2',
|
|
874
876
|
'flex-wrap',
|
|
@@ -908,7 +910,7 @@ function AttachmentsElement(props) {
|
|
|
908
910
|
|
|
909
911
|
return <Box
|
|
910
912
|
key={file.id}
|
|
911
|
-
className="mr-2"
|
|
913
|
+
className="mr-2 min-w-0 max-w-full"
|
|
912
914
|
>
|
|
913
915
|
{useFileMosaic &&
|
|
914
916
|
<DraggableFileMosaic
|
|
@@ -1142,7 +1144,7 @@ function AttachmentsElement(props) {
|
|
|
1142
1144
|
className: '!hidden',
|
|
1143
1145
|
deleteFiles: false,
|
|
1144
1146
|
}}
|
|
1145
|
-
className="attachments-dropzone flex-1 h-full" //
|
|
1147
|
+
className="attachments-dropzone flex-1 h-full min-w-0 overflow-x-hidden" // Keep horizontal containment while allowing vertical scrolling
|
|
1146
1148
|
onUploadStart={onUploadStart}
|
|
1147
1149
|
onUploadFinish={onUploadFinish}
|
|
1148
1150
|
background={styles.ATTACHMENTS_BG}
|
|
@@ -1285,6 +1287,8 @@ function AttachmentsElement(props) {
|
|
|
1285
1287
|
'AttachmentsElement',
|
|
1286
1288
|
'testx',
|
|
1287
1289
|
'w-full',
|
|
1290
|
+
'min-w-0',
|
|
1291
|
+
'overflow-x-hidden',
|
|
1288
1292
|
'h-[400px]',
|
|
1289
1293
|
'border-2',
|
|
1290
1294
|
'rounded-[5px]',
|
package/src/Styles/Global.css
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
html, body {
|
|
2
|
-
/* -webkit-user-select: none;
|
|
3
|
-
user-select: none; */
|
|
4
|
-
}
|
|
5
|
-
|
|
6
1
|
/* to fix the inline editor */
|
|
7
2
|
[data-testid="gridContainer"] > [data-testid="ScrollView"] > div {
|
|
8
3
|
height: 100%;
|
|
9
4
|
}
|
|
10
5
|
|
|
11
6
|
/* Custom styles for attachments dropzone */
|
|
7
|
+
.attachments-dropzone {
|
|
8
|
+
width: 100%;
|
|
9
|
+
min-width: 0;
|
|
10
|
+
overflow-x: hidden;
|
|
11
|
+
}
|
|
12
|
+
|
|
12
13
|
.attachments-dropzone .files-ui-dropzone-children-container {
|
|
13
14
|
padding: 0 !important;
|
|
15
|
+
width: 100%;
|
|
16
|
+
min-width: 0;
|
|
17
|
+
min-height: 0;
|
|
18
|
+
overflow-x: hidden;
|
|
14
19
|
}
|