@lifesg/react-design-system 3.4.0 → 3.5.0-canary.2
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/cjs/e-signature/e-signature-canvas.js +1 -1
- package/cjs/e-signature/e-signature-canvas.js.map +1 -1
- package/cjs/e-signature/e-signature.styles.js +19 -15
- package/cjs/e-signature/e-signature.styles.js.map +1 -1
- package/cjs/file-download/file-list-card/file-list-card.styles.js +1 -1
- package/cjs/file-download/file-list-card/file-list-card.styles.js.map +1 -1
- package/cjs/file-upload/file-item-edit.js +1 -1
- package/cjs/file-upload/file-item-edit.js.map +1 -1
- package/cjs/file-upload/file-item-edit.styles.js +12 -7
- package/cjs/file-upload/file-item-edit.styles.js.map +1 -1
- package/cjs/file-upload/file-list-item/file-list-item.js +1 -1
- package/cjs/file-upload/file-list-item/file-list-item.js.map +1 -1
- package/cjs/file-upload/file-list-item/file-list-item.styles.js +74 -52
- package/cjs/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
- package/cjs/file-upload/file-list.js +1 -1
- package/cjs/file-upload/file-list.js.map +1 -1
- package/cjs/file-upload/file-list.styles.js +4 -11
- package/cjs/file-upload/file-list.styles.js.map +1 -1
- package/cjs/file-upload/file-upload.js +1 -1
- package/cjs/file-upload/file-upload.js.map +1 -1
- package/cjs/footer/footer-helper.js +1 -1
- package/cjs/footer/footer-helper.js.map +1 -1
- package/cjs/form/form-label.style.js +11 -8
- package/cjs/form/form-label.style.js.map +1 -1
- package/cjs/index.js +1 -1
- package/cjs/navbar/drawer.js +1 -1
- package/cjs/navbar/drawer.js.map +1 -1
- package/cjs/navbar/navbar-logo-data.js +1 -1
- package/cjs/navbar/navbar-logo-data.js.map +1 -1
- package/cjs/navbar/navbar.js +1 -1
- package/cjs/navbar/navbar.js.map +1 -1
- package/cjs/shared/internal-calendar/calendar-manager.style.js +18 -17
- package/cjs/shared/internal-calendar/calendar-manager.style.js.map +1 -1
- package/cjs/theme/colour-primitive/specs/toteboard-colour-set.js +2 -0
- package/cjs/theme/colour-primitive/specs/toteboard-colour-set.js.map +1 -0
- package/cjs/theme/colour-primitive/theme-helper.js +1 -1
- package/cjs/theme/colour-primitive/theme-helper.js.map +1 -1
- package/cjs/theme/colour-semantic/theme-helper.js +1 -1
- package/cjs/theme/colour-semantic/theme-helper.js.map +1 -1
- package/cjs/theme/font/specs/toteboard-font-set.js +2 -0
- package/cjs/theme/font/specs/toteboard-font-set.js.map +1 -0
- package/cjs/theme/font/theme-helper.js +1 -1
- package/cjs/theme/font/theme-helper.js.map +1 -1
- package/cjs/theme/font-spec/specs/bookingsg-font-spec-set.js +1 -1
- package/cjs/theme/font-spec/specs/bookingsg-font-spec-set.js.map +1 -1
- package/cjs/theme/font-spec/specs/default-font-spec-set.js +1 -1
- package/cjs/theme/font-spec/specs/default-font-spec-set.js.map +1 -1
- package/cjs/theme/font-spec/specs/sgw-digital-lobby-font-spec-set.js +1 -1
- package/cjs/theme/font-spec/specs/sgw-digital-lobby-font-spec-set.js.map +1 -1
- package/cjs/theme/font-spec/specs/toteboard-font-spec-set.js +2 -0
- package/cjs/theme/font-spec/specs/toteboard-font-spec-set.js.map +1 -0
- package/cjs/theme/font-spec/theme-helper.js +1 -1
- package/cjs/theme/font-spec/theme-helper.js.map +1 -1
- package/cjs/theme/index.js +1 -1
- package/cjs/theme/index.js.map +1 -1
- package/cjs/time-range-picker/combobox-picker/combobox-picker.js +1 -1
- package/cjs/time-range-picker/combobox-picker/combobox-picker.js.map +1 -1
- package/cjs/time-range-picker/common.styles.js +7 -3
- package/cjs/time-range-picker/common.styles.js.map +1 -1
- package/cjs/time-range-picker/dial-picker/dial-picker.js +1 -1
- package/cjs/time-range-picker/dial-picker/dial-picker.js.map +1 -1
- package/cjs/timepicker/timepicker.styles.js +7 -3
- package/cjs/timepicker/timepicker.styles.js.map +1 -1
- package/cjs/typography/typography.styles.js +6 -6
- package/cjs/typography/typography.styles.js.map +1 -1
- package/cjs/util/merge-refs.js +1 -1
- package/cjs/util/merge-refs.js.map +1 -1
- package/e-signature/e-signature-canvas.js +1 -1
- package/e-signature/e-signature-canvas.js.map +1 -1
- package/e-signature/e-signature.styles.js +20 -16
- package/e-signature/e-signature.styles.js.map +1 -1
- package/file-download/file-list-card/file-list-card.styles.js +1 -1
- package/file-download/file-list-card/file-list-card.styles.js.map +1 -1
- package/file-upload/file-item-edit.d.ts +4 -1
- package/file-upload/file-item-edit.js +1 -1
- package/file-upload/file-item-edit.js.map +1 -1
- package/file-upload/file-item-edit.styles.js +21 -16
- package/file-upload/file-item-edit.styles.js.map +1 -1
- package/file-upload/file-list-item/file-list-item.d.ts +3 -1
- package/file-upload/file-list-item/file-list-item.js +1 -1
- package/file-upload/file-list-item/file-list-item.js.map +1 -1
- package/file-upload/file-list-item/file-list-item.styles.d.ts +14 -0
- package/file-upload/file-list-item/file-list-item.styles.js +67 -45
- package/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
- package/file-upload/file-list.d.ts +3 -0
- package/file-upload/file-list.js +1 -1
- package/file-upload/file-list.js.map +1 -1
- package/file-upload/file-list.styles.js +4 -11
- package/file-upload/file-list.styles.js.map +1 -1
- package/file-upload/file-upload.d.ts +1 -1
- package/file-upload/file-upload.js +1 -1
- package/file-upload/file-upload.js.map +1 -1
- package/file-upload/types.d.ts +5 -0
- package/footer/footer-helper.js +1 -1
- package/footer/footer-helper.js.map +1 -1
- package/form/form-label.style.js +12 -9
- package/form/form-label.style.js.map +1 -1
- package/index.js +1 -1
- package/navbar/drawer.js +1 -1
- package/navbar/drawer.js.map +1 -1
- package/navbar/navbar-logo-data.js +1 -1
- package/navbar/navbar-logo-data.js.map +1 -1
- package/navbar/navbar.js +1 -1
- package/navbar/navbar.js.map +1 -1
- package/package.json +1 -1
- package/shared/internal-calendar/calendar-manager.style.js +18 -17
- package/shared/internal-calendar/calendar-manager.style.js.map +1 -1
- package/theme/colour-primitive/specs/toteboard-colour-set.d.ts +2 -0
- package/theme/colour-primitive/specs/toteboard-colour-set.js +2 -0
- package/theme/colour-primitive/specs/toteboard-colour-set.js.map +1 -0
- package/theme/colour-primitive/theme-helper.js +1 -1
- package/theme/colour-primitive/theme-helper.js.map +1 -1
- package/theme/colour-semantic/theme-helper.js +1 -1
- package/theme/colour-semantic/theme-helper.js.map +1 -1
- package/theme/font/specs/toteboard-font-set.d.ts +2 -0
- package/theme/font/specs/toteboard-font-set.js +2 -0
- package/theme/font/specs/toteboard-font-set.js.map +1 -0
- package/theme/font/theme-helper.js +1 -1
- package/theme/font/theme-helper.js.map +1 -1
- package/theme/font-spec/specs/bookingsg-font-spec-set.js +1 -1
- package/theme/font-spec/specs/bookingsg-font-spec-set.js.map +1 -1
- package/theme/font-spec/specs/default-font-spec-set.js +1 -1
- package/theme/font-spec/specs/default-font-spec-set.js.map +1 -1
- package/theme/font-spec/specs/sgw-digital-lobby-font-spec-set.js +1 -1
- package/theme/font-spec/specs/sgw-digital-lobby-font-spec-set.js.map +1 -1
- package/theme/font-spec/specs/toteboard-font-spec-set.d.ts +2 -0
- package/theme/font-spec/specs/toteboard-font-spec-set.js +2 -0
- package/theme/font-spec/specs/toteboard-font-spec-set.js.map +1 -0
- package/theme/font-spec/theme-helper.js +1 -1
- package/theme/font-spec/theme-helper.js.map +1 -1
- package/theme/index.d.ts +19 -0
- package/theme/index.js +1 -1
- package/theme/index.js.map +1 -1
- package/theme/types.d.ts +3 -3
- package/time-range-picker/combobox-picker/combobox-picker.js +1 -1
- package/time-range-picker/combobox-picker/combobox-picker.js.map +1 -1
- package/time-range-picker/common.styles.d.ts +6 -2
- package/time-range-picker/common.styles.js +9 -5
- package/time-range-picker/common.styles.js.map +1 -1
- package/time-range-picker/dial-picker/dial-picker.js +1 -1
- package/time-range-picker/dial-picker/dial-picker.js.map +1 -1
- package/timepicker/timepicker.styles.js +7 -3
- package/timepicker/timepicker.styles.js.map +1 -1
- package/typography/typography.styles.js +4 -4
- package/typography/typography.styles.js.map +1 -1
- package/util/merge-refs.d.ts +1 -1
- package/util/merge-refs.js +1 -1
- package/util/merge-refs.js.map +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import i,{css as t}from"styled-components";import{Button as e}from"../button/button.js";import{IconButton as o}from"../icon-button/icon-button.js";import{Modal as
|
|
2
|
-
${i=>`\n ${n.MaxWidth.sm(i)},\n (orientation: landscape) and (max-height: ${
|
|
1
|
+
import i,{css as t}from"styled-components";import{Button as e}from"../button/button.js";import{IconButton as o}from"../icon-button/icon-button.js";import{Modal as r}from"../modal/index.js";import{MediaQuery as n,Breakpoint as a,Colour as d,Border as s,Radius as g,Spacing as c,Font as l}from"../theme/index.js";import{Typography as h}from"../typography/typography.js";const p=t`
|
|
2
|
+
${i=>`\n ${n.MaxWidth.sm(i)},\n (orientation: landscape) and (max-height: ${a["sm-max"](i)}px)\n `}
|
|
3
3
|
`,m=t`
|
|
4
|
-
${i=>`\n @media (orientation: landscape) and (max-height: ${
|
|
4
|
+
${i=>`\n @media (orientation: landscape) and (max-height: ${a["sm-max"](i)}px)\n `}
|
|
5
5
|
`,$=i.div`
|
|
6
6
|
position: relative;
|
|
7
7
|
display: flex;
|
|
@@ -34,6 +34,8 @@ import i,{css as t}from"styled-components";import{Button as e}from"../button/but
|
|
|
34
34
|
object-position: center;
|
|
35
35
|
width: calc(100% - (3rem + ${c["spacing-16"]}) * 2);
|
|
36
36
|
height: 100%;
|
|
37
|
+
|
|
38
|
+
${i=>{var t;return"dark"===(null===(t=i.theme)||void 0===t?void 0:t.colourMode)&&"filter: invert(1);"}}
|
|
37
39
|
`,f=i.div`
|
|
38
40
|
background: ${d["bg-primary-subtlest"]};
|
|
39
41
|
border: ${s["width-010"]} ${s.solid} ${d.border};
|
|
@@ -45,25 +47,25 @@ import i,{css as t}from"styled-components";import{Button as e}from"../button/but
|
|
|
45
47
|
flex: 1;
|
|
46
48
|
flex-direction: column;
|
|
47
49
|
align-items: center;
|
|
48
|
-
`,
|
|
50
|
+
`,v=i(h.BodySM)`
|
|
49
51
|
margin-top: ${c["spacing-16"]};
|
|
50
|
-
`,
|
|
52
|
+
`,w=i(r)`
|
|
51
53
|
/* increase specificity as the styles are overwritten */
|
|
52
54
|
&& {
|
|
53
55
|
height: 100%;
|
|
54
56
|
overflow-y: auto;
|
|
55
57
|
}
|
|
56
|
-
`,
|
|
58
|
+
`,y=i.div`
|
|
57
59
|
width: 100%;
|
|
58
60
|
margin: auto;
|
|
59
61
|
padding: ${c["layout-xxl"]} ${c["layout-sm"]};
|
|
60
62
|
|
|
61
|
-
${
|
|
63
|
+
${p} {
|
|
62
64
|
padding: 0;
|
|
63
65
|
width: 100%;
|
|
64
66
|
height: 100%;
|
|
65
67
|
}
|
|
66
|
-
`,j=i(
|
|
68
|
+
`,j=i(r.Box)`
|
|
67
69
|
width: 100%;
|
|
68
70
|
height: 29rem;
|
|
69
71
|
max-width: 672px;
|
|
@@ -71,7 +73,7 @@ import i,{css as t}from"styled-components";import{Button as e}from"../button/but
|
|
|
71
73
|
margin: 0 auto;
|
|
72
74
|
padding: ${c["spacing-16"]};
|
|
73
75
|
|
|
74
|
-
${
|
|
76
|
+
${p} {
|
|
75
77
|
display: flex;
|
|
76
78
|
flex-direction: column;
|
|
77
79
|
max-width: none;
|
|
@@ -83,13 +85,13 @@ import i,{css as t}from"styled-components";import{Button as e}from"../button/but
|
|
|
83
85
|
--close-button-right-inset: ${c["spacing-20"]};
|
|
84
86
|
}
|
|
85
87
|
`,k=i.h2`
|
|
86
|
-
${
|
|
88
|
+
${l["body-baseline-semibold"]}
|
|
87
89
|
color: ${d.text};
|
|
88
90
|
margin-bottom: ${c["spacing-16"]};
|
|
89
91
|
text-align: center;
|
|
90
92
|
|
|
91
|
-
${
|
|
92
|
-
${
|
|
93
|
+
${p} {
|
|
94
|
+
${l["body-md-semibold"]}
|
|
93
95
|
margin: ${c["spacing-12"]} 0;
|
|
94
96
|
}
|
|
95
97
|
`,M=i.div`
|
|
@@ -98,7 +100,7 @@ import i,{css as t}from"styled-components";import{Button as e}from"../button/but
|
|
|
98
100
|
border-radius: ${g.lg};
|
|
99
101
|
overflow: hidden;
|
|
100
102
|
|
|
101
|
-
${
|
|
103
|
+
${p} {
|
|
102
104
|
border-radius: 0;
|
|
103
105
|
flex: 1;
|
|
104
106
|
}
|
|
@@ -113,7 +115,7 @@ import i,{css as t}from"styled-components";import{Button as e}from"../button/but
|
|
|
113
115
|
background: ${d["bg-stronger"]};
|
|
114
116
|
margin: auto;
|
|
115
117
|
|
|
116
|
-
${
|
|
118
|
+
${p} {
|
|
117
119
|
aspect-ratio: 4/3;
|
|
118
120
|
}
|
|
119
121
|
${n.MaxWidth.sm} {
|
|
@@ -134,7 +136,7 @@ import i,{css as t}from"styled-components";import{Button as e}from"../button/but
|
|
|
134
136
|
background-color: ${d["border-strong"]};
|
|
135
137
|
pointer-events: none;
|
|
136
138
|
|
|
137
|
-
${
|
|
139
|
+
${p} {
|
|
138
140
|
width: calc(100% - ${c["spacing-40"]});
|
|
139
141
|
max-width: 300px;
|
|
140
142
|
left: 50%;
|
|
@@ -169,5 +171,7 @@ import i,{css as t}from"styled-components";import{Button as e}from"../button/but
|
|
|
169
171
|
overflow: hidden;
|
|
170
172
|
`,X=i.canvas`
|
|
171
173
|
cursor: crosshair;
|
|
172
|
-
|
|
174
|
+
|
|
175
|
+
${i=>{var t;return"dark"===(null===(t=i.theme)||void 0===t?void 0:t.colourMode)&&"filter: invert(1);"}}
|
|
176
|
+
`;export{b as AddSignatureButton,M as ESignatureContainer,W as ESignatureDrawable,u as EditSignatureButton,y as GrowContainer,v as Instructions,S as ModalActionButton,j as ModalBox,D as ModalButtons,k as ModalTitle,f as ProgressBox,w as ScrollableModal,$ as SignatureArea,X as SignatureCanvas,U as SignatureCanvasContainer,B as SignatureLine,x as SignaturePreviewImage};
|
|
173
177
|
//# sourceMappingURL=e-signature.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"e-signature.styles.js","sources":["../../src/e-signature/e-signature.styles.ts"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { Button } from \"../button\";\nimport { IconButton } from \"../icon-button\";\nimport { Modal } from \"../modal\";\nimport {\n Border,\n Breakpoint,\n Colour,\n Font,\n MediaQuery,\n Radius,\n Spacing,\n} from \"../theme\";\nimport { Typography } from \"../typography\";\n\n// =============================================================================\n// STYLE INTERFACES\n// =============================================================================\ninterface SignatureAreaProps {\n $disabled: boolean | undefined;\n}\n\n// =============================================================================\n// CUSTOM MEDIA QUERIES\n// =============================================================================\n// for mobileL and below in both orientations\nconst mobileMediaQuery = css`\n ${(props) => `\n ${MediaQuery.MaxWidth.sm(props)},\n (orientation: landscape) and (max-height: ${Breakpoint[\"sm-max\"](\n
|
|
1
|
+
{"version":3,"file":"e-signature.styles.js","sources":["../../src/e-signature/e-signature.styles.ts"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { Button } from \"../button\";\nimport { IconButton } from \"../icon-button\";\nimport { Modal } from \"../modal\";\nimport {\n Border,\n Breakpoint,\n Colour,\n Font,\n MediaQuery,\n Radius,\n Spacing,\n} from \"../theme\";\nimport { Typography } from \"../typography\";\n\n// =============================================================================\n// STYLE INTERFACES\n// =============================================================================\ninterface SignatureAreaProps {\n $disabled: boolean | undefined;\n}\n\n// =============================================================================\n// CUSTOM MEDIA QUERIES\n// =============================================================================\n// for mobileL and below in both orientations\nconst mobileMediaQuery = css`\n ${(props) => `\n ${MediaQuery.MaxWidth.sm(props)},\n (orientation: landscape) and (max-height: ${Breakpoint[\"sm-max\"](\n props\n )}px)\n `}\n`;\nconst mobileLandscapeMediaQuery = css`\n ${(props) => `\n @media (orientation: landscape) and (max-height: ${Breakpoint[\"sm-max\"](\n props\n )}px)\n `}\n`;\n\n// =============================================================================\n// STYLING\n// =============================================================================\n\n// -----------------------------------------------------------------------------\n// MAIN FIELD\n// -----------------------------------------------------------------------------\n\nexport const SignatureArea = styled.div<SignatureAreaProps>`\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n ${(props) =>\n css`\n ${Border.Util[\"dashed-default\"]({\n radius: Radius[\"sm\"],\n thickness: Border[\"width-040\"],\n colour: props.$disabled\n ? Colour[\"border-disabled\"]\n : Colour[\"border\"],\n })}\n\n background-color: ${props.$disabled\n ? Colour[\"bg-disabled\"]\n : Colour[\"bg\"]};\n `}\n height: 14.125rem;\n`;\n\nexport const AddSignatureButton = styled(Button.Default)`\n width: fit-content;\n margin: 0 ${Spacing[\"spacing-20\"]};\n\n &:disabled {\n border-color: ${Colour[\"border-strong\"]};\n }\n`;\n\nexport const EditSignatureButton = styled(IconButton)`\n position: absolute;\n top: ${Spacing[\"spacing-16\"]};\n right: ${Spacing[\"spacing-16\"]};\n\n &:disabled {\n border-color: ${Colour[\"border-strong\"]};\n }\n`;\n\nexport const SignaturePreviewImage = styled.img`\n display: block;\n object-fit: contain;\n object-position: center;\n width: calc(100% - (3rem + ${Spacing[\"spacing-16\"]}) * 2);\n height: 100%;\n\n ${(props) => props.theme?.colourMode === \"dark\" && `filter: invert(1);`}\n`;\n\nexport const ProgressBox = styled.div`\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n margin: 0 ${Spacing[\"spacing-20\"]};\n padding: ${Spacing[\"spacing-16\"]};\n display: flex;\n gap: ${Spacing[\"spacing-16\"]};\n flex: 1;\n flex-direction: column;\n align-items: center;\n`;\n\nexport const Instructions = styled(Typography.BodySM)`\n margin-top: ${Spacing[\"spacing-16\"]};\n`;\n\n// -----------------------------------------------------------------------------\n// SIGNATURE MODAL\n// -----------------------------------------------------------------------------\n\nexport const ScrollableModal = styled(Modal)`\n /* increase specificity as the styles are overwritten */\n && {\n height: 100%;\n overflow-y: auto;\n }\n`;\n\nexport const GrowContainer = styled.div`\n width: 100%;\n margin: auto;\n padding: ${Spacing[\"layout-xxl\"]} ${Spacing[\"layout-sm\"]};\n\n ${mobileMediaQuery} {\n padding: 0;\n width: 100%;\n height: 100%;\n }\n`;\n\nexport const ModalBox = styled(Modal.Box)`\n width: 100%;\n height: 29rem;\n max-width: 672px;\n max-height: none;\n margin: 0 auto;\n padding: ${Spacing[\"spacing-16\"]};\n\n ${mobileMediaQuery} {\n display: flex;\n flex-direction: column;\n max-width: none;\n height: 100%;\n border-radius: 0;\n padding: 0;\n\n --close-button-top-inset: ${Spacing[\"spacing-8\"]};\n --close-button-right-inset: ${Spacing[\"spacing-20\"]};\n }\n`;\n\nexport const ModalTitle = styled.h2`\n ${Font[\"body-baseline-semibold\"]}\n color: ${Colour[\"text\"]};\n margin-bottom: ${Spacing[\"spacing-16\"]};\n text-align: center;\n\n ${mobileMediaQuery} {\n ${Font[\"body-md-semibold\"]}\n margin: ${Spacing[\"spacing-12\"]} 0;\n }\n`;\n\nexport const ESignatureContainer = styled.div`\n width: 100%;\n height: 20rem;\n border-radius: ${Radius[\"lg\"]};\n overflow: hidden;\n\n ${mobileMediaQuery} {\n border-radius: 0;\n flex: 1;\n }\n\n ${mobileLandscapeMediaQuery} {\n background: ${Colour[\"bg-strong\"]};\n }\n`;\n\nexport const ESignatureDrawable = styled.div`\n position: relative;\n width: 100%;\n height: 100%;\n background: ${Colour[\"bg-stronger\"]};\n margin: auto;\n\n ${mobileMediaQuery} {\n aspect-ratio: 4/3;\n }\n ${MediaQuery.MaxWidth.sm} {\n width: 100%;\n height: auto;\n }\n ${mobileLandscapeMediaQuery} {\n width: auto;\n height: 100%;\n }\n`;\n\nexport const SignatureLine = styled.div`\n position: absolute;\n left: 50%;\n top: calc(75% - 1px);\n width: 300px;\n height: 2px;\n transform: translateX(-50%);\n background-color: ${Colour[\"border-strong\"]};\n pointer-events: none;\n\n ${mobileMediaQuery} {\n width: calc(100% - ${Spacing[\"spacing-40\"]});\n max-width: 300px;\n left: 50%;\n }\n`;\n\nexport const ModalButtons = styled.div`\n display: flex;\n justify-content: space-between;\n margin-top: ${Spacing[\"spacing-16\"]};\n\n ${MediaQuery.MaxWidth.sm} {\n flex-direction: column-reverse;\n margin: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-24\"]}\n ${Spacing[\"spacing-48\"]};\n gap: ${Spacing[\"spacing-16\"]};\n }\n\n ${mobileLandscapeMediaQuery} {\n flex-direction: row;\n margin: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-20\"]};\n }\n`;\n\nexport const ModalActionButton = styled(Button.Default)`\n width: 8.5rem;\n ${MediaQuery.MaxWidth.sm} {\n width: 100%;\n }\n ${mobileLandscapeMediaQuery} {\n height: 2.5rem;\n }\n`;\n\nexport const SignatureCanvasContainer = styled.div`\n width: 100%;\n height: 100%;\n overflow: hidden;\n`;\n\nexport const SignatureCanvas = styled.canvas`\n cursor: crosshair;\n\n ${(props) => props.theme?.colourMode === \"dark\" && `filter: invert(1);`}\n`;\n"],"names":["mobileMediaQuery","css","props","MediaQuery","MaxWidth","sm","Breakpoint","mobileLandscapeMediaQuery","SignatureArea","styled","div","Border","Util","radius","Radius","thickness","colour","$disabled","Colour","AddSignatureButton","Button","Default","Spacing","EditSignatureButton","IconButton","SignaturePreviewImage","img","_a","theme","colourMode","ProgressBox","Instructions","Typography","BodySM","ScrollableModal","Modal","GrowContainer","ModalBox","Box","ModalTitle","h2","Font","ESignatureContainer","ESignatureDrawable","SignatureLine","ModalButtons","ModalActionButton","SignatureCanvasContainer","SignatureCanvas","canvas"],"mappings":"gXA0BA,MAAMA,EAAmBC,CAAG;MACrBC,GAAU,aACPC,EAAWC,SAASC,GAAGH,0DACmBI,EAAW,UACnDJ;EAINK,EAA4BN,CAAG;MAC9BC,GAAU,8DAC0CI,EAAW,UAC1DJ;EAaCM,EAAgBC,EAAOC,GAAuB;;;;;MAKpDR,GACCD,CAAG;cACGU,EAAOC,KAAK,kBAAkB,CAC5BC,OAAQC,EAAW,GACnBC,UAAWJ,EAAO,aAClBK,OAAQd,EAAMe,UACRC,EAAO,mBACPA,EAAe;;gCAGLhB,EAAMe,UACpBC,EAAO,eACPA,EAAW;;;EAKhBC,EAAqBV,EAAOW,EAAOC,QAAQ;;gBAExCC,EAAQ;;;wBAGAJ,EAAO;;EAIlBK,EAAsBd,EAAOe,EAAW;;WAE1CF,EAAQ;aACNA,EAAQ;;;wBAGGJ,EAAO;;EAIlBO,EAAwBhB,EAAOiB,GAAG;;;;iCAIdJ,EAAQ;;;MAGlCpB,IAAS,IAAAyB,EAAC,MAA4B,kBAA5BA,EAAAzB,EAAM0B,4BAAOC,aAAyB,oBAAoB;EAG9DC,EAAcrB,EAAOC,GAAG;kBACnBQ,EAAO;cACXP,EAAO,gBAAgBA,EAAc,SAAKO,EAAe;qBAClDJ,EAAW;gBAChBQ,EAAQ;eACTA,EAAQ;;WAEZA,EAAQ;;;;EAMNS,EAAetB,EAAOuB,EAAWC,OAAO;kBACnCX,EAAQ;EAObY,EAAkBzB,EAAO0B,EAAM;;;;;;EAQ/BC,EAAgB3B,EAAOC,GAAG;;;eAGxBY,EAAQ,iBAAiBA,EAAQ;;MAE1CtB;;;;;EAOOqC,EAAW5B,EAAO0B,EAAMG,IAAI;;;;;;eAM1BhB,EAAQ;;MAEjBtB;;;;;;;;oCAQ8BsB,EAAQ;sCACNA,EAAQ;;EAIjCiB,EAAa9B,EAAO+B,EAAE;MAC7BC,EAAK;aACEvB,EAAa;qBACLI,EAAQ;;;MAGvBtB;UACIyC,EAAK;kBACGnB,EAAQ;;EAIboB,EAAsBjC,EAAOC,GAAG;;;qBAGxBI,EAAW;;;MAG1Bd;;;;;MAKAO;sBACgBW,EAAO;;EAIhByB,EAAqBlC,EAAOC,GAAG;;;;kBAI1BQ,EAAO;;;MAGnBlB;;;MAGAG,EAAWC,SAASC;;;;MAIpBE;;;;EAMOqC,EAAgBnC,EAAOC,GAAG;;;;;;;wBAOfQ,EAAO;;;MAGzBlB;6BACuBsB,EAAQ;;;;EAMxBuB,EAAepC,EAAOC,GAAG;;;kBAGpBY,EAAQ;;MAEpBnB,EAAWC,SAASC;;kBAERiB,EAAQ,iBAAiBA,EAAQ;cACrCA,EAAQ;eACPA,EAAQ;;;MAGjBf;;kBAEYe,EAAQ,iBAAiBA,EAAQ;;EAItCwB,EAAoBrC,EAAOW,EAAOC,QAAQ;;MAEjDlB,EAAWC,SAASC;;;MAGpBE;;;EAKOwC,EAA2BtC,EAAOC,GAAG;;;;EAMrCsC,EAAkBvC,EAAOwC,MAAM;;;MAGrC/C,IAAS,IAAAyB,EAAC,MAA4B,kBAA5BA,EAAAzB,EAAM0B,4BAAOC,aAAyB,oBAAoB;"}
|
|
@@ -111,7 +111,7 @@ import i,{css as r}from"styled-components";import{ExclamationCircleFillIcon as e
|
|
|
111
111
|
${m["body-sm-semibold"]}
|
|
112
112
|
color: ${d["text-error"]};
|
|
113
113
|
`,v=i(w)`
|
|
114
|
-
margin-top: ${l["spacing-
|
|
114
|
+
margin-top: ${l["spacing-8"]};
|
|
115
115
|
display: flex;
|
|
116
116
|
gap: ${l["spacing-4"]};
|
|
117
117
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-list-card.styles.js","sources":["../../../src/file-download/file-list-card/file-list-card.styles.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport { IconButton as DSIconButton } from \"../../icon-button\";\nimport { ComponentLoadingSpinner } from \"../../shared/component-loading-spinner\";\nimport { ImageWithFallback } from \"../../shared/image-with-fallback/image-with-fallback\";\nimport { lineClampCss } from \"../../shared/styles\";\nimport { Border, Colour, Font, MediaQuery, Radius, Spacing } from \"../../theme\";\n\n// =============================================================================\n// STYLE INTERFACES\n// =============================================================================\n\ninterface BoxStyleProps {\n $error?: boolean | undefined;\n}\n\ninterface ContentSectionStyleProps {\n $hasThumbnail?: boolean | undefined;\n}\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const Item = styled.li`\n display: flex;\n align-items: center;\n\n width: 100%;\n border: none;\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const Box = styled.div<BoxStyleProps>`\n display: flex;\n align-items: center;\n\n width: 100%;\n padding: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-32\"]};\n cursor: pointer;\n\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-16\"]};\n }\n\n &:hover {\n background: ${Colour[\"bg-hover\"]};\n }\n\n ${(props) => {\n if (props.$error) {\n return css`\n background: ${Colour[\"bg-error\"]};\n border-color: ${Colour[\"border-error\"]};\n\n &:hover {\n background: ${Colour[\"bg-error\"]};\n }\n `;\n }\n }}\n`;\n\nexport const ContentSection = styled.div<ContentSectionStyleProps>`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n\n ${(props) => {\n if (props.$hasThumbnail) {\n return css`\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: row;\n align-items: center;\n }\n `;\n }\n }}\n`;\n\nexport const NameSection = styled.div`\n display: flex;\n flex: 1;\n flex-direction: column;\n\n width: 100%;\n\n overflow-wrap: break-word;\n word-break: break-all;\n white-space: normal;\n`;\n\nexport const ExtendedNameSection = styled.div`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n`;\n\nexport const FileSizeSection = styled.div`\n display: flex;\n justify-content: flex-end;\n\n width: 5rem;\n margin-left: ${Spacing[\"spacing-8\"]};\n\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n justify-content: flex-start;\n\n width: 100%;\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-8\"]};\n\n ${lineClampCss(2)}\n }\n`;\n\nexport const ItemNameText = styled.div`\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n ${lineClampCss(2)}\n }\n`;\n\nexport const ItemDescriptionText = styled(ItemNameText)`\n ${Font[\"body-md-regular\"]}\n margin-top: ${Spacing[\"spacing-4\"]};\n`;\n\nexport const ErrorIcon = styled(ExclamationCircleFillIcon)`\n height: 1lh;\n width: 1em;\n flex-shrink: 0;\n color: ${Colour[\"icon-error-strong\"]};\n`;\n\nconst BaseErrorMessage = styled.div`\n ${Font[\"body-sm-semibold\"]}\n color: ${Colour[\"text-error\"]};\n`;\n\nexport const DesktopErrorMessage = styled(BaseErrorMessage)`\n margin-top: ${Spacing[\"spacing-
|
|
1
|
+
{"version":3,"file":"file-list-card.styles.js","sources":["../../../src/file-download/file-list-card/file-list-card.styles.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport { IconButton as DSIconButton } from \"../../icon-button\";\nimport { ComponentLoadingSpinner } from \"../../shared/component-loading-spinner\";\nimport { ImageWithFallback } from \"../../shared/image-with-fallback/image-with-fallback\";\nimport { lineClampCss } from \"../../shared/styles\";\nimport { Border, Colour, Font, MediaQuery, Radius, Spacing } from \"../../theme\";\n\n// =============================================================================\n// STYLE INTERFACES\n// =============================================================================\n\ninterface BoxStyleProps {\n $error?: boolean | undefined;\n}\n\ninterface ContentSectionStyleProps {\n $hasThumbnail?: boolean | undefined;\n}\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const Item = styled.li`\n display: flex;\n align-items: center;\n\n width: 100%;\n border: none;\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const Box = styled.div<BoxStyleProps>`\n display: flex;\n align-items: center;\n\n width: 100%;\n padding: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-32\"]};\n cursor: pointer;\n\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n padding: ${Spacing[\"spacing-16\"]};\n }\n\n &:hover {\n background: ${Colour[\"bg-hover\"]};\n }\n\n ${(props) => {\n if (props.$error) {\n return css`\n background: ${Colour[\"bg-error\"]};\n border-color: ${Colour[\"border-error\"]};\n\n &:hover {\n background: ${Colour[\"bg-error\"]};\n }\n `;\n }\n }}\n`;\n\nexport const ContentSection = styled.div<ContentSectionStyleProps>`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n\n ${(props) => {\n if (props.$hasThumbnail) {\n return css`\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: row;\n align-items: center;\n }\n `;\n }\n }}\n`;\n\nexport const NameSection = styled.div`\n display: flex;\n flex: 1;\n flex-direction: column;\n\n width: 100%;\n\n overflow-wrap: break-word;\n word-break: break-all;\n white-space: normal;\n`;\n\nexport const ExtendedNameSection = styled.div`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.lg} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n`;\n\nexport const FileSizeSection = styled.div`\n display: flex;\n justify-content: flex-end;\n\n width: 5rem;\n margin-left: ${Spacing[\"spacing-8\"]};\n\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n justify-content: flex-start;\n\n width: 100%;\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-8\"]};\n\n ${lineClampCss(2)}\n }\n`;\n\nexport const ItemNameText = styled.div`\n ${Font[\"body-md-regular\"]}\n color: ${Colour[\"text\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n ${lineClampCss(2)}\n }\n`;\n\nexport const ItemDescriptionText = styled(ItemNameText)`\n ${Font[\"body-md-regular\"]}\n margin-top: ${Spacing[\"spacing-4\"]};\n`;\n\nexport const ErrorIcon = styled(ExclamationCircleFillIcon)`\n height: 1lh;\n width: 1em;\n flex-shrink: 0;\n color: ${Colour[\"icon-error-strong\"]};\n`;\n\nconst BaseErrorMessage = styled.div`\n ${Font[\"body-sm-semibold\"]}\n color: ${Colour[\"text-error\"]};\n`;\n\nexport const DesktopErrorMessage = styled(BaseErrorMessage)`\n margin-top: ${Spacing[\"spacing-8\"]};\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n display: none;\n visibility: hidden;\n }\n`;\n\nexport const MobileErrorMessage = styled(BaseErrorMessage)`\n display: none;\n visibility: hidden;\n\n ${MediaQuery.MaxWidth.lg} {\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n visibility: visible;\n margin-top: ${Spacing[\"spacing-8\"]};\n }\n`;\n\nexport const Spinner = styled(ComponentLoadingSpinner)`\n color: ${Colour[\"icon-primary\"]};\n`;\n\nexport const ActionContainer = styled.div`\n display: flex;\n justify-content: flex-end;\n align-items: center;\n\n margin-left: ${Spacing[\"spacing-32\"]};\n\n ${MediaQuery.MaxWidth.lg} {\n margin-left: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const IconButton = styled(DSIconButton)`\n min-width: unset;\n\n &:not(:last-child) {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const ThumbnailContainer = styled.div`\n width: auto;\n margin-right: ${Spacing[\"spacing-32\"]};\n\n display: flex;\n flex-shrink: 0;\n flex-direction: column;\n justify-content: center;\n\n ${MediaQuery.MaxWidth.lg} {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const Thumbnail = styled(ImageWithFallback)`\n border-radius: ${Radius[\"sm\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n\n width: 96px;\n height: 96px;\n aspect-ratio: 1;\n object-fit: cover;\n\n ${MediaQuery.MaxWidth.lg} {\n width: 64px;\n height: 64px;\n }\n`;\n"],"names":["Item","styled","li","Spacing","Box","div","Colour","Border","Radius","MediaQuery","MaxWidth","lg","props","$error","css","ContentSection","$hasThumbnail","NameSection","ExtendedNameSection","FileSizeSection","Font","lineClampCss","ItemNameText","ErrorIcon","ExclamationCircleFillIcon","BaseErrorMessage","DesktopErrorMessage","MobileErrorMessage","Spinner","ComponentLoadingSpinner","ActionContainer","IconButton","DSIconButton","ThumbnailContainer","Thumbnail","ImageWithFallback"],"mappings":"ojBAuBO,MAAMA,EAAOC,EAAOC,EAAE;;;;;;;;yBAQJC,EAAQ;;EAIpBC,EAAMH,EAAOI,GAAkB;;;;;eAK7BF,EAAQ,iBAAiBA,EAAQ;;;kBAG9BG,EAAO;cACXC,EAAO,gBAAgBA,EAAc,SAAKD,EAAe;qBAClDE,EAAW;;MAE1BC,EAAWC,SAASC;mBACPR,EAAQ;;;;sBAILG,EAAO;;;MAGtBM,IACC,GAAIA,EAAMC,OACN,OAAOC,CAAG;8BACQR,EAAO;gCACLA,EAAO;;;kCAGLA,EAAO;;aAGjC;EAIKS,EAAiBd,EAAOI,GAA6B;;;;;MAK5DI,EAAWC,SAASC;;;;;;MAMnBC,IACC,GAAIA,EAAMI,cACN,OAAOF,CAAG;kBACJL,EAAWC,SAASC;;;;aAK9B;EAIKM,EAAchB,EAAOI,GAAG;;;;;;;;;;EAYxBa,EAAsBjB,EAAOI,GAAG;;;;;MAKvCI,EAAWC,SAASC;;;;;EAObQ,EAAkBlB,EAAOI,GAAG;;;;;mBAKtBF,EAAQ;;MAErBiB,EAAK;aACEd,EAAa;;MAEpBG,EAAWC,SAASC;;;;;sBAKJR,EAAQ;;UAEpBkB,EAAa;;EAIVC,EAAerB,EAAOI,GAAG;MAChCe,EAAK;aACEd,EAAa;;MAEpBG,EAAWC,SAASC;UAChBU,EAAa;;EAIYpB,EAAOqB,EAAa;MACjDF,EAAK;kBACOjB,EAAQ;QAGboB,EAAYtB,EAAOuB,EAA0B;;;;aAI7ClB,EAAO;EAGdmB,EAAmBxB,EAAOI,GAAG;MAC7Be,EAAK;aACEd,EAAO;EAGPoB,EAAsBzB,EAAOwB,EAAiB;kBACzCtB,EAAQ;;WAEfA,EAAQ;;MAEbM,EAAWC,SAASC;;;;EAMbgB,EAAqB1B,EAAOwB,EAAiB;;;;MAIpDhB,EAAWC,SAASC;;eAEXR,EAAQ;;sBAEDA,EAAQ;;EAIjByB,EAAU3B,EAAO4B,EAAwB;aACzCvB,EAAO;EAGPwB,EAAkB7B,EAAOI,GAAG;;;;;mBAKtBF,EAAQ;;MAErBM,EAAWC,SAASC;uBACHR,EAAQ;;EAIlB4B,EAAa9B,EAAO+B,EAAa;;;;wBAItB7B,EAAQ;;EAInB8B,EAAqBhC,EAAOI,GAAG;;oBAExBF,EAAQ;;;;;;;MAOtBM,EAAWC,SAASC;wBACFR,EAAQ;;EAInB+B,EAAYjC,EAAOkC,EAAkB;qBAC7B3B,EAAW;cAClBD,EAAO,gBAAgBA,EAAc,SAAKD,EAAe;;;;;;;MAOjEG,EAAWC,SAASC;;;;"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { FileItemProps } from "./types";
|
|
2
|
+
import { FormLabelProps } from "../form/types";
|
|
2
3
|
interface Props {
|
|
3
4
|
fileItem: FileItemProps;
|
|
4
5
|
wrapperWidth: number;
|
|
5
6
|
fileDescriptionMaxLength?: number | undefined;
|
|
7
|
+
descriptionRequired?: boolean | undefined;
|
|
8
|
+
descriptionLabel?: FormLabelProps | undefined;
|
|
6
9
|
onSave: (description: string) => void;
|
|
7
10
|
onCancel: () => void;
|
|
8
11
|
onBlur: (value: string) => void;
|
|
9
12
|
}
|
|
10
|
-
export declare const FileItemEdit: ({ fileItem, fileDescriptionMaxLength, wrapperWidth, onSave, onCancel, onBlur, }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export declare const FileItemEdit: ({ fileItem, fileDescriptionMaxLength, descriptionRequired, descriptionLabel, wrapperWidth, onSave, onCancel, onBlur, }: Props) => import("react/jsx-runtime").JSX.Element;
|
|
11
14
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useState as i,useRef as r,useCallback as n,useEffect as l}from"react";import{Form as a}from"../form/index.js";import"../util/calendar-helper.js";import"../util/date-helper.js";import"../util/date-input-helper.js";import"../util/simple-id-generator.js";import{StringHelper as o}from"../util/string-helper.js";import"@react-aria/live-announcer";import{Item as s,ContentSection as
|
|
1
|
+
import{jsxs as e,jsx as t}from"react/jsx-runtime";import{useState as i,useRef as r,useCallback as n,useEffect as l}from"react";import{Form as a}from"../form/index.js";import"../util/calendar-helper.js";import"../util/date-helper.js";import"../util/date-input-helper.js";import"../util/simple-id-generator.js";import{StringHelper as o}from"../util/string-helper.js";import"@react-aria/live-announcer";import{Item as s,ContentSection as d,DetailsSection as c,ActionButtonsSection as m,ActionButton as u,NameSection as p,FileNameText as h,FileSizeText as f}from"./file-item-edit.styles.js";import{FileListItemThumbnail as b}from"./file-list-item/file-list-item-thumbnail.js";import{FileUploadHelper as g}from"./helper.js";const y=({fileItem:y,fileDescriptionMaxLength:j,descriptionRequired:x=!0,descriptionLabel:v,wrapperWidth:C,onSave:D,onCancel:$,onBlur:w})=>{const{id:T,name:I,size:L,type:B,truncateText:M=!0,thumbnailImageDataUrl:P}=y,[S,k]=i(),[z,E]=i(""),F=r(null),R=r(null),U=n((e=>{if(!M)return e;const t=R&&R.current?R.current.getBoundingClientRect().width:0;return o.truncateOneLine(e,t,t/2,t/2/8,16)}),[M]);l((()=>{k(U(I))}),[C,U,I]),l((()=>{E(y.description||"")}),[y]);const _=!!P||B===g.PDF_MIME_TYPE;return e(s,{"data-testid":`${T}-edit-display`,children:[e(d,{children:[_&&t(b,{thumbnailImageDataUrl:P,fileType:B}),e(c,{children:[e(p,{ref:R,children:[t(h,{weight:"semibold",children:S}),t(f,{children:g.formatFileSizeDisplay(L)})]}),t(a.Textarea,{ref:F,id:`${T}-description-textarea`,"data-testid":`${T}-textarea`,value:z,maxLength:j,onChange:e=>{E(e.target.value)},onBlur:e=>{w(e.target.value)},rows:3,label:null!=v?v:{children:"Photo description",subtitle:"Describe this photo to users who may not be able to see the image."}})]})]}),e(m,{$thumbnail:_,children:[t(u,{"data-testid":`${T}-save-button`,type:"button",disabled:(()=>{if(!x)return!1;return 0===z.trim().length})(),onClick:()=>{F.current&&D(F.current.value.trim())},children:"Save"}),t(u,{type:"button",styleType:"secondary","data-testid":`${T}-cancel-button`,onClick:$,children:"Cancel"})]})]})};export{y as FileItemEdit};
|
|
2
2
|
//# sourceMappingURL=file-item-edit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-item-edit.js","sources":["../../src/file-upload/file-item-edit.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Form } from \"../form\";\nimport { StringHelper } from \"../util\";\nimport {\n ActionButton,\n ActionButtonsSection,\n ContentSection,\n DetailsSection,\n FileNameText,\n FileSizeText,\n Item,\n NameSection,\n} from \"./file-item-edit.styles\";\nimport { FileListItemThumbnail } from \"./file-list-item/file-list-item-thumbnail\";\nimport { FileUploadHelper } from \"./helper\";\nimport { FileItemProps } from \"./types\";\n\ninterface Props {\n fileItem: FileItemProps;\n wrapperWidth: number;\n fileDescriptionMaxLength?: number | undefined;\n onSave: (description: string) => void;\n onCancel: () => void;\n onBlur: (value: string) => void;\n}\n\nexport const FileItemEdit = ({\n fileItem,\n fileDescriptionMaxLength,\n wrapperWidth,\n onSave,\n onCancel,\n onBlur,\n}: Props) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n type,\n truncateText = true,\n thumbnailImageDataUrl,\n } = fileItem;\n\n const [formattedName, setFormattedName] = useState<string>();\n const [currentDescription, setCurrentDescription] = useState<string>(\"\");\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const nameSectionRef = useRef<HTMLDivElement>(null);\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = useCallback(\n (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n nameSectionRef && nameSectionRef.current\n ? nameSectionRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateOneLine(\n value,\n widthOfElement,\n widthOfElement / 2,\n widthOfElement / 2 / 8, // Arbitrary\n 16 // Font size\n );\n },\n [truncateText]\n );\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n setFormattedName(getTruncatedText(name));\n }, [wrapperWidth, getTruncatedText, name]);\n\n useEffect(() => {\n setCurrentDescription(fileItem.description || \"\");\n }, [fileItem]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleSave = () => {\n if (textareaRef.current) {\n onSave(textareaRef.current.value.trim());\n }\n };\n\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n setCurrentDescription(event.target.value);\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLTextAreaElement>) => {\n onBlur(event.target.value);\n };\n\n const shouldDisableSave = () => {\n const trimmedDescription = currentDescription.trim();\n return trimmedDescription.length === 0;\n };\n\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl || type === FileUploadHelper.PDF_MIME_TYPE;\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderFileNameAndSize = () => (\n <NameSection ref={nameSectionRef}>\n <FileNameText weight=\"semibold\">{formattedName}</FileNameText>\n <FileSizeText>\n {FileUploadHelper.formatFileSizeDisplay(size)}\n </FileSizeText>\n </NameSection>\n );\n\n return (\n <Item data-testid={`${id}-edit-display`}>\n <ContentSection>\n {shouldShowThumbnail && (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl}\n fileType={type}\n />\n )}\n <DetailsSection>\n {renderFileNameAndSize()}\n <Form.Textarea\n ref={textareaRef}\n id={`${id}-description-textarea`}\n data-testid={`${id}-textarea`}\n value={currentDescription}\n maxLength={fileDescriptionMaxLength}\n onChange={handleChange}\n onBlur={handleBlur}\n rows={3}\n
|
|
1
|
+
{"version":3,"file":"file-item-edit.js","sources":["../../src/file-upload/file-item-edit.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { Form } from \"../form\";\nimport { StringHelper } from \"../util\";\nimport {\n ActionButton,\n ActionButtonsSection,\n ContentSection,\n DetailsSection,\n FileNameText,\n FileSizeText,\n Item,\n NameSection,\n} from \"./file-item-edit.styles\";\nimport { FileListItemThumbnail } from \"./file-list-item/file-list-item-thumbnail\";\nimport { FileUploadHelper } from \"./helper\";\nimport { FileItemProps } from \"./types\";\nimport { FormLabelProps } from \"../form/types\";\n\ninterface Props {\n fileItem: FileItemProps;\n wrapperWidth: number;\n fileDescriptionMaxLength?: number | undefined;\n descriptionRequired?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n onSave: (description: string) => void;\n onCancel: () => void;\n onBlur: (value: string) => void;\n}\n\nexport const FileItemEdit = ({\n fileItem,\n fileDescriptionMaxLength,\n descriptionRequired = true,\n descriptionLabel,\n wrapperWidth,\n onSave,\n onCancel,\n onBlur,\n}: Props) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n type,\n truncateText = true,\n thumbnailImageDataUrl,\n } = fileItem;\n\n const [formattedName, setFormattedName] = useState<string>();\n const [currentDescription, setCurrentDescription] = useState<string>(\"\");\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const nameSectionRef = useRef<HTMLDivElement>(null);\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = useCallback(\n (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n nameSectionRef && nameSectionRef.current\n ? nameSectionRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateOneLine(\n value,\n widthOfElement,\n widthOfElement / 2,\n widthOfElement / 2 / 8, // Arbitrary\n 16 // Font size\n );\n },\n [truncateText]\n );\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n setFormattedName(getTruncatedText(name));\n }, [wrapperWidth, getTruncatedText, name]);\n\n useEffect(() => {\n setCurrentDescription(fileItem.description || \"\");\n }, [fileItem]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleSave = () => {\n if (textareaRef.current) {\n onSave(textareaRef.current.value.trim());\n }\n };\n\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n setCurrentDescription(event.target.value);\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLTextAreaElement>) => {\n onBlur(event.target.value);\n };\n\n const shouldDisableSave = () => {\n if (!descriptionRequired) return false;\n const trimmedDescription = currentDescription.trim();\n return trimmedDescription.length === 0;\n };\n\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl || type === FileUploadHelper.PDF_MIME_TYPE;\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderFileNameAndSize = () => (\n <NameSection ref={nameSectionRef}>\n <FileNameText weight=\"semibold\">{formattedName}</FileNameText>\n <FileSizeText>\n {FileUploadHelper.formatFileSizeDisplay(size)}\n </FileSizeText>\n </NameSection>\n );\n\n return (\n <Item data-testid={`${id}-edit-display`}>\n <ContentSection>\n {shouldShowThumbnail && (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl}\n fileType={type}\n />\n )}\n <DetailsSection>\n {renderFileNameAndSize()}\n <Form.Textarea\n ref={textareaRef}\n id={`${id}-description-textarea`}\n data-testid={`${id}-textarea`}\n value={currentDescription}\n maxLength={fileDescriptionMaxLength}\n onChange={handleChange}\n onBlur={handleBlur}\n rows={3}\n label={\n descriptionLabel ?? {\n children: \"Photo description\",\n subtitle:\n \"Describe this photo to users who may not be able to see the image.\",\n }\n }\n />\n </DetailsSection>\n </ContentSection>\n <ActionButtonsSection $thumbnail={shouldShowThumbnail}>\n <ActionButton\n data-testid={`${id}-save-button`}\n type=\"button\"\n disabled={shouldDisableSave()}\n onClick={handleSave}\n >\n Save\n </ActionButton>\n <ActionButton\n type=\"button\"\n styleType=\"secondary\"\n data-testid={`${id}-cancel-button`}\n onClick={onCancel}\n >\n Cancel\n </ActionButton>\n </ActionButtonsSection>\n </Item>\n );\n};\n"],"names":["FileItemEdit","fileItem","fileDescriptionMaxLength","descriptionRequired","descriptionLabel","wrapperWidth","onSave","onCancel","onBlur","id","name","size","type","truncateText","thumbnailImageDataUrl","formattedName","setFormattedName","useState","currentDescription","setCurrentDescription","textareaRef","useRef","nameSectionRef","getTruncatedText","useCallback","value","widthOfElement","current","getBoundingClientRect","width","StringHelper","truncateOneLine","useEffect","description","shouldShowThumbnail","FileUploadHelper","PDF_MIME_TYPE","_jsxs","Item","children","ContentSection","_jsx","FileListItemThumbnail","fileType","DetailsSection","NameSection","ref","FileNameText","weight","FileSizeText","formatFileSizeDisplay","Form","Textarea","maxLength","onChange","event","target","rows","label","subtitle","ActionButtonsSection","$thumbnail","ActionButton","disabled","trim","length","shouldDisableSave","onClick","styleType"],"mappings":"+sBA6BO,MAAMA,EAAe,EACxBC,WACAC,2BACAC,uBAAsB,EACtBC,mBACAC,eACAC,SACAC,WACAC,aAKA,MAAMC,GACFA,EAAEC,KACFA,EAAIC,KACJA,EAAIC,KACJA,EAAIC,aACJA,GAAe,EAAIC,sBACnBA,GACAb,GAEGc,EAAeC,GAAoBC,KACnCC,EAAoBC,GAAyBF,EAAiB,IAE/DG,EAAcC,EAA4B,MAC1CC,EAAiBD,EAAuB,MAKxCE,EAAmBC,GACpBC,IACG,IAAKZ,EAAc,OAAOY,EAE1B,MAAMC,EACFJ,GAAkBA,EAAeK,QAC3BL,EAAeK,QAAQC,wBAAwBC,MAC/C,EAEV,OAAOC,EAAaC,gBAChBN,EACAC,EACAA,EAAiB,EACjBA,EAAiB,EAAI,EACrB,GACH,GAEL,CAACb,IAMLmB,GAAU,KACNhB,EAAiBO,EAAiBb,GAAM,GACzC,CAACL,EAAckB,EAAkBb,IAEpCsB,GAAU,KACNb,EAAsBlB,EAASgC,aAAe,GAAG,GAClD,CAAChC,IAKJ,MAoBMiC,IACApB,GAAyBF,IAASuB,EAAiBC,cAczD,OACIC,EAACC,EAAI,CAAA,cAAc,GAAG7B,iBAAiB8B,SAAA,CACnCF,EAACG,aACIN,GACGO,EAACC,EAAqB,CAClB5B,sBAAuBA,EACvB6B,SAAU/B,IAGlByB,EAACO,EAAc,CAAAL,SAAA,CAjBvBF,EAACQ,EAAW,CAACC,IAAKxB,EAAciB,SAAA,CAC5BE,EAACM,EAAY,CAACC,OAAO,oBAAYjC,IACjC0B,EAACQ,EAAY,CAAAV,SACRJ,EAAiBe,sBAAsBvC,QAgBpC8B,EAACU,EAAKC,SAAQ,CACVN,IAAK1B,EACLX,GAAI,GAAGA,yBAAyB,cACnB,GAAGA,aAChBgB,MAAOP,EACPmC,UAAWnD,EACXoD,SA9CEC,IAClBpC,EAAsBoC,EAAMC,OAAO/B,MAAM,EA8CzBjB,OA3CA+C,IAChB/C,EAAO+C,EAAMC,OAAO/B,MAAM,EA2CVgC,KAAM,EACNC,MACItD,QAAAA,EAAoB,CAChBmC,SAAU,oBACVoB,SACI,8EAMxBtB,EAACuB,EAAoB,CAAAC,WAAa3B,EAAmBK,SAAA,CACjDE,EAACqB,EAAY,CAAA,cACI,GAAGrD,gBAChBG,KAAK,SACLmD,SAvDU,MACtB,IAAK5D,EAAqB,OAAO,EAEjC,OAAqC,IADVe,EAAmB8C,OACpBC,MAAY,EAoDhBC,GACVC,QAtEG,KACX/C,EAAYO,SACZrB,EAAOc,EAAYO,QAAQF,MAAMuC,OACrC,EAmE+BzB,SAAA,SAIvBE,EAACqB,EAAY,CACTlD,KAAK,SACLwD,UAAU,0BACG,GAAG3D,kBAChB0D,QAAS5D,EAAQgC,SAAA,gBAKtB"}
|
|
@@ -1,43 +1,48 @@
|
|
|
1
|
-
import t,{css as i}from"styled-components";import{Button as n}from"../button/button.js";import{Spacing as o,
|
|
1
|
+
import t,{css as i}from"styled-components";import{Button as n}from"../button/button.js";import{Spacing as o,Colour as a,Border as r,Radius as e,MediaQuery as d}from"../theme/index.js";import{Typography as l}from"../typography/typography.js";const m=t.li`
|
|
2
2
|
display: flex;
|
|
3
3
|
flex-direction: column;
|
|
4
|
-
padding: ${o["spacing-32"]}
|
|
5
|
-
background:
|
|
4
|
+
padding: ${o["spacing-32"]};
|
|
5
|
+
background: ${a["bg-primary-subtlest"]};
|
|
6
|
+
border: ${r["width-010"]} ${r.solid} ${a.border};
|
|
7
|
+
border-radius: ${e.sm};
|
|
6
8
|
|
|
7
9
|
&:not(:last-child) {
|
|
8
|
-
|
|
10
|
+
margin-bottom: ${o["spacing-16"]};
|
|
9
11
|
}
|
|
10
|
-
`,
|
|
12
|
+
`,s=t.div`
|
|
11
13
|
display: flex;
|
|
12
14
|
align-items: flex-start;
|
|
13
15
|
margin-bottom: ${o["spacing-16"]};
|
|
14
16
|
width: 100%;
|
|
15
|
-
`,
|
|
17
|
+
`,p=t.div`
|
|
16
18
|
display: flex;
|
|
17
19
|
flex: 1;
|
|
18
20
|
flex-direction: column;
|
|
19
|
-
`,
|
|
21
|
+
`,g=t.div`
|
|
20
22
|
width: 100%;
|
|
21
23
|
display: flex;
|
|
22
24
|
justify-content: space-between;
|
|
23
25
|
margin-bottom: ${o["spacing-16"]};
|
|
24
26
|
|
|
25
|
-
${
|
|
27
|
+
${d.MaxWidth.md} {
|
|
26
28
|
flex-direction: column;
|
|
27
29
|
justify-content: flex-start;
|
|
28
30
|
}
|
|
29
|
-
`,
|
|
31
|
+
`,c=t(l.BodyMD)`
|
|
30
32
|
display: flex;
|
|
31
33
|
flex: 1;
|
|
32
34
|
margin-right: ${o["spacing-16"]};
|
|
33
35
|
|
|
34
|
-
${
|
|
36
|
+
${d.MaxWidth.md} {
|
|
35
37
|
margin-right: 0;
|
|
36
38
|
margin-bottom: ${o["spacing-8"]};
|
|
37
39
|
}
|
|
38
|
-
`,
|
|
40
|
+
`,f=t(l.BodyMD)`
|
|
41
|
+
color: ${a["text-subtler"]};
|
|
42
|
+
`,x=t.div`
|
|
39
43
|
display: flex;
|
|
40
|
-
|
|
44
|
+
justify-content: flex-end;
|
|
45
|
+
${d.MaxWidth.md} {
|
|
41
46
|
flex-direction: column;
|
|
42
47
|
}
|
|
43
48
|
|
|
@@ -46,21 +51,21 @@ import t,{css as i}from"styled-components";import{Button as n}from"../button/but
|
|
|
46
51
|
96px + ${o["spacing-32"]}
|
|
47
52
|
); // thumbnail width + right margin
|
|
48
53
|
|
|
49
|
-
${
|
|
54
|
+
${d.MaxWidth.md} {
|
|
50
55
|
margin-left: 0;
|
|
51
56
|
}
|
|
52
57
|
`}}
|
|
53
|
-
|
|
58
|
+
`,$=t(n.Small)`
|
|
54
59
|
width: 7.5rem;
|
|
55
60
|
&:not(:last-of-type) {
|
|
56
61
|
margin-right: ${o["spacing-16"]};
|
|
57
62
|
}
|
|
58
63
|
|
|
59
|
-
${
|
|
64
|
+
${d.MaxWidth.md} {
|
|
60
65
|
width: 100%;
|
|
61
66
|
&:not(:last-of-type) {
|
|
62
67
|
margin-bottom: ${o["spacing-16"]};
|
|
63
68
|
}
|
|
64
69
|
}
|
|
65
|
-
`;export{
|
|
70
|
+
`;export{$ as ActionButton,x as ActionButtonsSection,s as ContentSection,p as DetailsSection,c as FileNameText,f as FileSizeText,m as Item,g as NameSection};
|
|
66
71
|
//# sourceMappingURL=file-item-edit.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-item-edit.styles.js","sources":["../../src/file-upload/file-item-edit.styles.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { Button } from \"../button/button\";\nimport { Border, Colour, MediaQuery, Spacing } from \"../theme\";\nimport { Typography } from \"../typography\";\n\n// =============================================================================\n// STYLE INTERFACE\n// =============================================================================\ninterface ActionButtonSectionStyleProps {\n $thumbnail?: boolean | undefined;\n}\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const Item = styled.li`\n display: flex;\n flex-direction: column;\n padding: ${Spacing[\"spacing-32\"]}
|
|
1
|
+
{"version":3,"file":"file-item-edit.styles.js","sources":["../../src/file-upload/file-item-edit.styles.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { Button } from \"../button/button\";\nimport { Border, Colour, MediaQuery, Radius, Spacing } from \"../theme\";\nimport { Typography } from \"../typography\";\n\n// =============================================================================\n// STYLE INTERFACE\n// =============================================================================\ninterface ActionButtonSectionStyleProps {\n $thumbnail?: boolean | undefined;\n}\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const Item = styled.li`\n display: flex;\n flex-direction: column;\n padding: ${Spacing[\"spacing-32\"]};\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border.solid} ${Colour.border};\n border-radius: ${Radius[\"sm\"]};\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n`;\n\nexport const ContentSection = styled.div`\n display: flex;\n align-items: flex-start;\n margin-bottom: ${Spacing[\"spacing-16\"]};\n width: 100%;\n`;\n\nexport const DetailsSection = styled.div`\n display: flex;\n flex: 1;\n flex-direction: column;\n`;\n\nexport const NameSection = styled.div`\n width: 100%;\n display: flex;\n justify-content: space-between;\n margin-bottom: ${Spacing[\"spacing-16\"]};\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n justify-content: flex-start;\n }\n`;\n\nexport const FileNameText = styled(Typography.BodyMD)`\n display: flex;\n flex: 1;\n margin-right: ${Spacing[\"spacing-16\"]};\n\n ${MediaQuery.MaxWidth.md} {\n margin-right: 0;\n margin-bottom: ${Spacing[\"spacing-8\"]};\n }\n`;\n\nexport const FileSizeText = styled(Typography.BodyMD)`\n color: ${Colour[\"text-subtler\"]};\n`;\n\nexport const ActionButtonsSection = styled.div<ActionButtonSectionStyleProps>`\n display: flex;\n justify-content: flex-end;\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n }\n\n ${(props) => {\n if (props.$thumbnail) {\n return css`\n margin-left: calc(\n 96px + ${Spacing[\"spacing-32\"]}\n ); // thumbnail width + right margin\n\n ${MediaQuery.MaxWidth.md} {\n margin-left: 0;\n }\n `;\n }\n }}\n`;\n\nexport const ActionButton = styled(Button.Small)`\n width: 7.5rem;\n &:not(:last-of-type) {\n margin-right: ${Spacing[\"spacing-16\"]};\n }\n\n ${MediaQuery.MaxWidth.md} {\n width: 100%;\n &:not(:last-of-type) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n }\n`;\n"],"names":["Item","styled","li","Spacing","Colour","Border","solid","border","Radius","ContentSection","div","DetailsSection","NameSection","MediaQuery","MaxWidth","md","FileNameText","Typography","BodyMD","FileSizeText","ActionButtonsSection","props","$thumbnail","css","ActionButton","Button","Small"],"mappings":"iPAeO,MAAMA,EAAOC,EAAOC,EAAE;;;eAGdC,EAAQ;kBACLC,EAAO;cACXC,EAAO,gBAAgBA,EAAOC,SAASF,EAAOG;qBACvCC,EAAW;;;yBAGPL,EAAQ;;EAIpBM,EAAiBR,EAAOS,GAAG;;;qBAGnBP,EAAQ;;EAIhBQ,EAAiBV,EAAOS,GAAG;;;;EAM3BE,EAAcX,EAAOS,GAAG;;;;qBAIhBP,EAAQ;;MAEvBU,EAAWC,SAASC;;;;EAMbC,EAAef,EAAOgB,EAAWC,OAAO;;;oBAGjCf,EAAQ;;MAEtBU,EAAWC,SAASC;;yBAEDZ,EAAQ;;EAIpBgB,EAAelB,EAAOgB,EAAWC,OAAO;aACxCd,EAAO;EAGPgB,EAAuBnB,EAAOS,GAAkC;;;MAGvEG,EAAWC,SAASC;;;;MAInBM,IACC,GAAIA,EAAMC,WACN,OAAOC,CAAG;;6BAEOpB,EAAQ;;;kBAGnBU,EAAWC,SAASC;;;aAI9B;EAIKS,EAAevB,EAAOwB,EAAOC,MAAM;;;wBAGxBvB,EAAQ;;;MAG1BU,EAAWC,SAASC;;;6BAGGZ,EAAQ;;;"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { FormLabelProps } from "../../form/types";
|
|
1
2
|
import { FileListItemProps } from "./types";
|
|
2
3
|
interface Props extends FileListItemProps {
|
|
3
4
|
readOnly?: boolean | undefined;
|
|
5
|
+
descriptionLabel?: FormLabelProps | undefined;
|
|
4
6
|
}
|
|
5
|
-
export declare const FileListItem: import("react").MemoExoticComponent<({ fileItem, editable, sortable, wrapperWidth, disabled, readOnly, onDelete, onEditClick, }: Props) => import("react/jsx-runtime").JSX.Element>;
|
|
7
|
+
export declare const FileListItem: import("react").MemoExoticComponent<({ fileItem, editable, sortable, wrapperWidth, disabled, readOnly, descriptionLabel, onDelete, onEditClick, }: Props) => import("react/jsx-runtime").JSX.Element>;
|
|
6
8
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as e,jsx as t,Fragment as i}from"react/jsx-runtime";import{useSortable as r}from"../../external/@dnd-kit/sortable/dist/sortable.esm.js";import{CSS as l}from"../../external/@dnd-kit/utilities/dist/utilities.esm.js";import{BinIcon as n}from"@lifesg/react-icons/bin";import{PencilIcon as
|
|
1
|
+
import{jsxs as e,jsx as t,Fragment as i}from"react/jsx-runtime";import{useSortable as r}from"../../external/@dnd-kit/sortable/dist/sortable.esm.js";import{CSS as l}from"../../external/@dnd-kit/utilities/dist/utilities.esm.js";import{BinIcon as n}from"@lifesg/react-icons/bin";import{PencilIcon as d}from"@lifesg/react-icons/pencil";import{memo as a,useState as o,useContext as s,useRef as c,useCallback as h,useEffect as p}from"react";import{ProgressBar as m}from"../../shared/progress-bar/progress-bar.js";import"../../util/calendar-helper.js";import"../../util/date-helper.js";import"../../util/date-input-helper.js";import"../../util/simple-id-generator.js";import{StringHelper as u}from"../../util/string-helper.js";import"@react-aria/live-announcer";import{FileUploadContext as b}from"../context.js";import{FileUploadHelper as $}from"../helper.js";import{FileListItemThumbnail as g}from"./file-list-item-thumbnail.js";import{Item as y,DragHandleIcon as f,Box as T,ContentSection as j,IconButton as D,ActionContainer as w,NameSection as v,DesktopErrorMessage as k,ErrorIcon as z,FileSizeSection as C,FileSizeText as P,MobileErrorMessage as x,DescriptionFileSizeText as I,ItemText as E,ItemDescriptionLabel as M,ItemDescriptionText as O,ExtendedNameSection as K}from"./file-list-item.styles.js";const _=a((({fileItem:a,editable:_,sortable:F,wrapperWidth:L,disabled:R,readOnly:S,descriptionLabel:U,onDelete:Y,onEditClick:B})=>{const{id:N,name:W,size:q,description:A,progress:G=1,errorMessage:H,thumbnailImageDataUrl:J,truncateText:Q=!0}=a,[V,X]=o(),{activeId:Z}=s(b),{attributes:ee,listeners:te,setNodeRef:ie,transform:re,transition:le}=r({id:N}),ne=c(null),de={transform:l.Translate.toString(re),transition:le},ae=Object.assign(Object.assign({style:de},ee),te),oe=G<1,se=$.formatFileSizeDisplay(q),ce=!!A&&!!_,he=Z?Z===N?"self":"others":"none",pe=h((e=>{if(!Q)return e;const t=ne&&ne.current?ne.current.getBoundingClientRect().width:0;return u.truncateOneLine(e,t,t/2,t/2/8,16)}),[Q]);p((()=>{X(pe(W))}),[L,pe,W]);const me=()=>{Y()},ue=()=>{B&&B()},be=e=>{F&&e.stopPropagation()},$e=()=>R||!!Z,ge=()=>!!F&&!S,ye=()=>{var r;return e(i,{children:[t(E,{weight:A?"semibold":"regular",children:V}),A&&e(i,{children:[t(M,{children:null!==(r=null==U?void 0:U.children)&&void 0!==r?r:"Photo description"}),t(O,{children:A})]})]})};return e(y,Object.assign({id:N,ref:ie,$sortable:ge(),$disabled:$e(),$focusType:he},ge()?ae:{},{children:[ge()&&t(f,{"data-testid":`${N}-drag-handle`,$disabled:$e(),$active:"self"===he}),e(T,{$focused:"self"===he,$error:!!H,$loading:oe,$disabled:$e(),$editable:_,$hasDescription:!!A,children:[(()=>{const r=!!J||a.type===$.PDF_MIME_TYPE,l=H?e(i,{children:[e(v,{ref:ne,children:[ye(),H&&e(k,{weight:"semibold",children:[t(z,{"aria-hidden":!0}),H]})]}),t(C,{children:t(P,{children:se})}),H&&e(x,{weight:"semibold",children:[t(z,{"aria-hidden":!0}),H]})]}):(r=>{const l=r||a.type===$.PDF_MIME_TYPE?t(g,{thumbnailImageDataUrl:r||"",fileType:a.type,"data-testid":`${N}-thumbnail`}):null;return e(i,ce?{children:[l,e(K,{ref:ne,children:[t(E,{weight:"semibold",children:V}),t(M,{children:null!==(o=null==U?void 0:U.children)&&void 0!==o?o:"Photo description"}),t(O,{children:A}),t(I,{children:se}),!S&&ce&&e(w,{$editable:_,$error:!1,$loading:!1,$hasDescription:!0,children:[t(D,{"data-testid":`${N}-edit-button`,"data-no-dnd":"true",type:"button",styleType:"light",sizeType:"small","aria-label":`edit ${W}`,disabled:$e(),onClick:ue,onKeyDown:be,children:t(d,{"aria-hidden":!0})},"edit"),t(D,{"data-testid":`${N}-delete-button`,"data-no-dnd":"true",type:"button",styleType:"light",sizeType:"small","aria-label":`delete ${W}`,disabled:$e(),onClick:me,onKeyDown:be,children:t(n,{"aria-hidden":!0})},"delete")]})]})]}:{children:[l,e(v,{ref:ne,children:[ye(),!oe&&t(I,{children:se})]})]});var o})(J);return t(j,{$hasThumbnail:r,children:l})})(),!S&&!ce&&(()=>{let r;return r=H?t(D,{"data-testid":`${N}-error-delete-button`,"data-no-dnd":"true",type:"button",styleType:"light",sizeType:"small","aria-label":`delete ${W}, error: ${H}`,onClick:me,children:t(n,{"aria-hidden":!0})}):oe?t(m,{progress:G,"data-testid":`${N}-progress-bar`}):e(i,{children:[_&&t(D,{"data-testid":`${N}-edit-button`,"data-no-dnd":"true",type:"button",styleType:"light",sizeType:"small","aria-label":`edit ${W}`,disabled:$e(),onClick:ue,onKeyDown:be,children:t(d,{"aria-hidden":!0})},"edit"),t(D,{"data-testid":`${N}-delete-button`,"data-no-dnd":"true",type:"button",styleType:"light",sizeType:"small","aria-label":`delete ${W}`,disabled:$e(),onClick:me,onKeyDown:be,children:t(n,{"aria-hidden":!0})},"delete")]}),t(w,{$editable:_,$error:!!H,$loading:oe,$hasDescription:!!A,children:r})})()]})]}))}));export{_ as FileListItem};
|
|
2
2
|
//# sourceMappingURL=file-list-item.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-list-item.js","sources":["../../../src/file-upload/file-list-item/file-list-item.tsx"],"sourcesContent":["import { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { BinIcon } from \"@lifesg/react-icons/bin\";\nimport { PencilIcon } from \"@lifesg/react-icons/pencil\";\nimport { memo, useCallback, useContext, useEffect, useRef, useState } from \"react\";\nimport { ProgressBar } from \"../../shared/progress-bar\";\nimport { StringHelper } from \"../../util\";\nimport { FileUploadContext } from \"../context\";\nimport { FileUploadHelper } from \"../helper\";\nimport { FileListItemThumbnail } from \"./file-list-item-thumbnail\";\nimport {\n ActionContainer,\n Box,\n ContentSection,\n DesktopErrorMessage,\n DragHandleIcon,\n ErrorIcon,\n ExtendedNameSection,\n FileSizeSection,\n FileSizeText,\n IconButton,\n Item,\n ItemDescriptionText,\n ItemFocusType,\n ItemText,\n MobileErrorMessage,\n NameSection,\n} from \"./file-list-item.styles\";\nimport { FileListItemProps } from \"./types\";\n\ninterface Props extends FileListItemProps {\n readOnly?: boolean | undefined;\n}\n\nconst Component = ({\n fileItem,\n editable,\n sortable,\n wrapperWidth,\n disabled,\n readOnly,\n onDelete,\n onEditClick,\n}: Props) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n description,\n progress = 1,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n } = fileItem;\n const [formattedName, setFormattedName] = useState<string>();\n const { activeId } = useContext(FileUploadContext);\n\n // Sortable mechanism\n const { attributes, listeners, setNodeRef, transform, transition } =\n useSortable({ id });\n const detailSectionRef = useRef<HTMLDivElement>(null);\n const style = {\n transform: CSS.Translate.toString(transform),\n transition,\n };\n\n const sortableProps = {\n style,\n ...attributes,\n ...listeners,\n };\n\n // Local variables\n const isLoading = progress < 1;\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const focusType: ItemFocusType = activeId\n ? activeId === id\n ? \"self\"\n : \"others\"\n : \"none\";\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = useCallback(\n (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n detailSectionRef && detailSectionRef.current\n ? detailSectionRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateOneLine(\n value,\n widthOfElement,\n widthOfElement / 2,\n widthOfElement / 2 / 8, // Arbitrary\n 16 // Font size\n );\n },\n [truncateText]\n );\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n setFormattedName(getTruncatedText(name));\n }, [wrapperWidth, getTruncatedText, name]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDelete = () => {\n onDelete();\n };\n\n const handleEdit = () => {\n if (onEditClick) {\n onEditClick();\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n /**\n * Circumvent issue of keydown action activating the sort mechanism\n * rather than the actual action\n */\n if (sortable) {\n event.stopPropagation();\n }\n };\n\n const shouldDisable = () => disabled || !!activeId;\n\n const shouldEnableSort = () => !!sortable && !readOnly;\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderNameDescription = () => (\n <>\n <ItemText weight={description ? \"semibold\" : \"regular\"}>\n {formattedName}\n </ItemText>\n {description && (\n <ItemDescriptionText>{description}</ItemDescriptionText>\n )}\n </>\n );\n\n const renderErrorState = () => (\n <>\n <NameSection ref={detailSectionRef}>\n {renderNameDescription()}\n {errorMessage && (\n <DesktopErrorMessage weight=\"semibold\">\n <ErrorIcon aria-hidden />\n {errorMessage}\n </DesktopErrorMessage>\n )}\n </NameSection>\n <FileSizeSection>\n <FileSizeText>{fileSize}</FileSizeText>\n </FileSizeSection>\n {errorMessage && (\n <MobileErrorMessage weight=\"semibold\">\n <ErrorIcon aria-hidden />\n {errorMessage}\n </MobileErrorMessage>\n )}\n </>\n );\n\n const renderWithThumbnail = (thumbnailImageDataUrl: string) => (\n <>\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl}\n fileType={fileItem.type}\n data-testid={`${id}-thumbnail`}\n />\n <ExtendedNameSection>\n <NameSection ref={detailSectionRef}>\n {renderNameDescription()}\n </NameSection>\n <FileSizeSection>\n <FileSizeText>{fileSize}</FileSizeText>\n </FileSizeSection>\n </ExtendedNameSection>\n </>\n );\n\n const renderDefault = () => (\n <>\n <NameSection ref={detailSectionRef}>\n {renderNameDescription()}\n </NameSection>\n <FileSizeSection $hideInMobile={isLoading}>\n <FileSizeText>{fileSize}</FileSizeText>\n </FileSizeSection>\n </>\n );\n\n const renderContents = () => {\n let content: JSX.Element;\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n if (errorMessage) {\n content = renderErrorState();\n } else if (shouldShowThumbnail) {\n content = renderWithThumbnail(thumbnailImageDataUrl || \"\");\n } else {\n content = renderDefault();\n }\n\n return (\n <ContentSection $hasThumbnail={shouldShowThumbnail}>\n {content}\n </ContentSection>\n );\n };\n\n const renderActions = () => {\n let content: JSX.Element;\n\n if (errorMessage) {\n content = (\n <IconButton\n data-testid={`${id}-error-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}, error: ${errorMessage}`}\n onClick={handleDelete}\n >\n <BinIcon aria-hidden />\n </IconButton>\n );\n } else if (isLoading) {\n content = (\n <ProgressBar\n progress={progress}\n data-testid={`${id}-progress-bar`}\n />\n );\n } else {\n content = (\n <>\n {editable && (\n <IconButton\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={shouldDisable()}\n onClick={handleEdit}\n onKeyDown={handleKeyDown}\n >\n <PencilIcon aria-hidden />\n </IconButton>\n )}\n <IconButton\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={shouldDisable()}\n onClick={handleDelete}\n onKeyDown={handleKeyDown}\n >\n <BinIcon aria-hidden />\n </IconButton>\n </>\n );\n }\n\n return (\n <ActionContainer\n $editable={editable}\n $error={!!errorMessage}\n $loading={isLoading}\n >\n {content}\n </ActionContainer>\n );\n };\n\n return (\n <Item\n id={id}\n ref={setNodeRef}\n $sortable={shouldEnableSort()}\n $disabled={shouldDisable()}\n $focusType={focusType}\n {...(shouldEnableSort() ? sortableProps : {})}\n >\n {shouldEnableSort() && (\n <DragHandleIcon\n data-testid={`${id}-drag-handle`}\n $disabled={shouldDisable()}\n $active={focusType === \"self\"}\n />\n )}\n <Box\n $focused={focusType === \"self\"}\n $error={!!errorMessage}\n $loading={isLoading}\n $disabled={shouldDisable()}\n $editable={editable}\n >\n {renderContents()}\n {!readOnly && renderActions()}\n </Box>\n </Item>\n );\n};\n\nexport const FileListItem = memo(Component);\n"],"names":["FileListItem","memo","fileItem","editable","sortable","wrapperWidth","disabled","readOnly","onDelete","onEditClick","id","name","size","description","progress","errorMessage","thumbnailImageDataUrl","truncateText","formattedName","setFormattedName","useState","activeId","useContext","FileUploadContext","attributes","listeners","setNodeRef","transform","transition","useSortable","detailSectionRef","useRef","style","CSS","Translate","toString","sortableProps","isLoading","fileSize","FileUploadHelper","formatFileSizeDisplay","focusType","getTruncatedText","useCallback","value","widthOfElement","current","getBoundingClientRect","width","StringHelper","truncateOneLine","useEffect","handleDelete","handleEdit","handleKeyDown","event","stopPropagation","shouldDisable","shouldEnableSort","renderNameDescription","_jsxs","_Fragment","children","_jsx","ItemText","weight","ItemDescriptionText","Item","Object","assign","ref","$sortable","$disabled","$focusType","DragHandleIcon","$active","Box","$focused","$loading","$editable","content","shouldShowThumbnail","type","PDF_MIME_TYPE","NameSection","DesktopErrorMessage","ErrorIcon","FileSizeSection","FileSizeText","MobileErrorMessage","FileListItemThumbnail","fileType","ExtendedNameSection","renderWithThumbnail","$hideInMobile","ContentSection","$hasThumbnail","renderContents","IconButton","styleType","sizeType","onClick","BinIcon","ProgressBar","onKeyDown","PencilIcon","ActionContainer","$error","renderActions"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"file-list-item.js","sources":["../../../src/file-upload/file-list-item/file-list-item.tsx"],"sourcesContent":["import { useSortable } from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { BinIcon } from \"@lifesg/react-icons/bin\";\nimport { PencilIcon } from \"@lifesg/react-icons/pencil\";\nimport {\n memo,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { ProgressBar } from \"../../shared/progress-bar\";\nimport { StringHelper } from \"../../util\";\nimport { FileUploadContext } from \"../context\";\nimport { FileUploadHelper } from \"../helper\";\nimport { FileListItemThumbnail } from \"./file-list-item-thumbnail\";\nimport {\n ActionContainer,\n Box,\n ContentSection,\n DescriptionFileSizeText,\n DesktopErrorMessage,\n DragHandleIcon,\n ErrorIcon,\n ExtendedNameSection,\n FileSizeSection,\n FileSizeText,\n IconButton,\n Item,\n ItemDescriptionLabel,\n ItemDescriptionText,\n ItemFocusType,\n ItemText,\n MobileErrorMessage,\n NameSection,\n} from \"./file-list-item.styles\";\nimport { FormLabelProps } from \"../../form/types\";\nimport { FileListItemProps } from \"./types\";\n\ninterface Props extends FileListItemProps {\n readOnly?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n}\n\nconst Component = ({\n fileItem,\n editable,\n sortable,\n wrapperWidth,\n disabled,\n readOnly,\n descriptionLabel,\n onDelete,\n onEditClick,\n}: Props) => {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const {\n id,\n name,\n size,\n description,\n progress = 1,\n errorMessage,\n thumbnailImageDataUrl,\n truncateText = true,\n } = fileItem;\n const [formattedName, setFormattedName] = useState<string>();\n const { activeId } = useContext(FileUploadContext);\n\n // Sortable mechanism\n const { attributes, listeners, setNodeRef, transform, transition } =\n useSortable({ id });\n const detailSectionRef = useRef<HTMLDivElement>(null);\n const style = {\n transform: CSS.Translate.toString(transform),\n transition,\n };\n\n const sortableProps = {\n style,\n ...attributes,\n ...listeners,\n };\n\n // Local variables\n const isLoading = progress < 1;\n const fileSize = FileUploadHelper.formatFileSizeDisplay(size);\n const hasInlineActions = !!description && !!editable;\n const focusType: ItemFocusType = activeId\n ? activeId === id\n ? \"self\"\n : \"others\"\n : \"none\";\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const getTruncatedText = useCallback(\n (value: string) => {\n if (!truncateText) return value;\n\n const widthOfElement =\n detailSectionRef && detailSectionRef.current\n ? detailSectionRef.current.getBoundingClientRect().width\n : 0;\n\n return StringHelper.truncateOneLine(\n value,\n widthOfElement,\n widthOfElement / 2,\n widthOfElement / 2 / 8, // Arbitrary\n 16 // Font size\n );\n },\n [truncateText]\n );\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n setFormattedName(getTruncatedText(name));\n }, [wrapperWidth, getTruncatedText, name]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleDelete = () => {\n onDelete();\n };\n\n const handleEdit = () => {\n if (onEditClick) {\n onEditClick();\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n /**\n * Circumvent issue of keydown action activating the sort mechanism\n * rather than the actual action\n */\n if (sortable) {\n event.stopPropagation();\n }\n };\n\n const shouldDisable = () => disabled || !!activeId;\n\n const shouldEnableSort = () => !!sortable && !readOnly;\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderNameDescription = () => (\n <>\n <ItemText weight={description ? \"semibold\" : \"regular\"}>\n {formattedName}\n </ItemText>\n {description && (\n <>\n <ItemDescriptionLabel>\n {descriptionLabel?.children ?? \"Photo description\"}\n </ItemDescriptionLabel>\n <ItemDescriptionText>{description}</ItemDescriptionText>\n </>\n )}\n </>\n );\n\n const renderErrorState = () => (\n <>\n <NameSection ref={detailSectionRef}>\n {renderNameDescription()}\n {errorMessage && (\n <DesktopErrorMessage weight=\"semibold\">\n <ErrorIcon aria-hidden />\n {errorMessage}\n </DesktopErrorMessage>\n )}\n </NameSection>\n <FileSizeSection>\n <FileSizeText>{fileSize}</FileSizeText>\n </FileSizeSection>\n {errorMessage && (\n <MobileErrorMessage weight=\"semibold\">\n <ErrorIcon aria-hidden />\n {errorMessage}\n </MobileErrorMessage>\n )}\n </>\n );\n\n const renderInlineActions = () => (\n <ActionContainer\n $editable={editable}\n $error={false}\n $loading={false}\n $hasDescription={true}\n >\n <IconButton\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={shouldDisable()}\n onClick={handleEdit}\n onKeyDown={handleKeyDown}\n >\n <PencilIcon aria-hidden />\n </IconButton>\n <IconButton\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={shouldDisable()}\n onClick={handleDelete}\n onKeyDown={handleKeyDown}\n >\n <BinIcon aria-hidden />\n </IconButton>\n </ActionContainer>\n );\n\n const renderDescriptionContent = () => (\n <ExtendedNameSection ref={detailSectionRef}>\n <ItemText weight=\"semibold\">{formattedName}</ItemText>\n <ItemDescriptionLabel>\n {descriptionLabel?.children ?? \"Photo description\"}\n </ItemDescriptionLabel>\n <ItemDescriptionText>{description}</ItemDescriptionText>\n <DescriptionFileSizeText>{fileSize}</DescriptionFileSizeText>\n {!readOnly && hasInlineActions && renderInlineActions()}\n </ExtendedNameSection>\n );\n\n const renderFileContent = (thumbnailImageDataUrl?: string) => {\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n const thumbnail = shouldShowThumbnail ? (\n <FileListItemThumbnail\n thumbnailImageDataUrl={thumbnailImageDataUrl || \"\"}\n fileType={fileItem.type}\n data-testid={`${id}-thumbnail`}\n />\n ) : null;\n\n if (hasInlineActions) {\n return (\n <>\n {thumbnail}\n {renderDescriptionContent()}\n </>\n );\n }\n\n return (\n <>\n {thumbnail}\n <NameSection ref={detailSectionRef}>\n {renderNameDescription()}\n {!isLoading && (\n <DescriptionFileSizeText>\n {fileSize}\n </DescriptionFileSizeText>\n )}\n </NameSection>\n </>\n );\n };\n\n const renderContents = () => {\n const shouldShowThumbnail =\n !!thumbnailImageDataUrl ||\n fileItem.type === FileUploadHelper.PDF_MIME_TYPE;\n\n const content = errorMessage\n ? renderErrorState()\n : renderFileContent(thumbnailImageDataUrl);\n\n return (\n <ContentSection $hasThumbnail={shouldShowThumbnail}>\n {content}\n </ContentSection>\n );\n };\n\n const renderActions = () => {\n let content: JSX.Element;\n\n if (errorMessage) {\n content = (\n <IconButton\n data-testid={`${id}-error-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}, error: ${errorMessage}`}\n onClick={handleDelete}\n >\n <BinIcon aria-hidden />\n </IconButton>\n );\n } else if (isLoading) {\n content = (\n <ProgressBar\n progress={progress}\n data-testid={`${id}-progress-bar`}\n />\n );\n } else {\n content = (\n <>\n {editable && (\n <IconButton\n key=\"edit\"\n data-testid={`${id}-edit-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`edit ${name}`}\n disabled={shouldDisable()}\n onClick={handleEdit}\n onKeyDown={handleKeyDown}\n >\n <PencilIcon aria-hidden />\n </IconButton>\n )}\n <IconButton\n key=\"delete\"\n data-testid={`${id}-delete-button`}\n data-no-dnd=\"true\"\n type=\"button\"\n styleType=\"light\"\n sizeType=\"small\"\n aria-label={`delete ${name}`}\n disabled={shouldDisable()}\n onClick={handleDelete}\n onKeyDown={handleKeyDown}\n >\n <BinIcon aria-hidden />\n </IconButton>\n </>\n );\n }\n\n return (\n <ActionContainer\n $editable={editable}\n $error={!!errorMessage}\n $loading={isLoading}\n $hasDescription={!!description}\n >\n {content}\n </ActionContainer>\n );\n };\n\n return (\n <Item\n id={id}\n ref={setNodeRef}\n $sortable={shouldEnableSort()}\n $disabled={shouldDisable()}\n $focusType={focusType}\n {...(shouldEnableSort() ? sortableProps : {})}\n >\n {shouldEnableSort() && (\n <DragHandleIcon\n data-testid={`${id}-drag-handle`}\n $disabled={shouldDisable()}\n $active={focusType === \"self\"}\n />\n )}\n <Box\n $focused={focusType === \"self\"}\n $error={!!errorMessage}\n $loading={isLoading}\n $disabled={shouldDisable()}\n $editable={editable}\n $hasDescription={!!description}\n >\n {renderContents()}\n {!readOnly && !hasInlineActions && renderActions()}\n </Box>\n </Item>\n );\n};\n\nexport const FileListItem = memo(Component);\n"],"names":["FileListItem","memo","fileItem","editable","sortable","wrapperWidth","disabled","readOnly","descriptionLabel","onDelete","onEditClick","id","name","size","description","progress","errorMessage","thumbnailImageDataUrl","truncateText","formattedName","setFormattedName","useState","activeId","useContext","FileUploadContext","attributes","listeners","setNodeRef","transform","transition","useSortable","detailSectionRef","useRef","style","CSS","Translate","toString","sortableProps","isLoading","fileSize","FileUploadHelper","formatFileSizeDisplay","hasInlineActions","focusType","getTruncatedText","useCallback","value","widthOfElement","current","getBoundingClientRect","width","StringHelper","truncateOneLine","useEffect","handleDelete","handleEdit","handleKeyDown","event","stopPropagation","shouldDisable","shouldEnableSort","renderNameDescription","_jsxs","_jsx","ItemText","weight","children","_Fragment","ItemDescriptionLabel","_a","ItemDescriptionText","Item","ref","$sortable","$disabled","$focusType","DragHandleIcon","Box","$error","$loading","$editable","shouldShowThumbnail","type","PDF_MIME_TYPE","content","NameSection","DesktopErrorMessage","ErrorIcon","FileSizeSection","FileSizeText","MobileErrorMessage","thumbnail","FileListItemThumbnail","fileType","ExtendedNameSection","DescriptionFileSizeText","ActionContainer","$hasDescription","IconButton","styleType","sizeType","onClick","onKeyDown","PencilIcon","BinIcon","renderFileContent","ContentSection","$hasThumbnail","renderContents","ProgressBar","renderActions"],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ interface BoxStyleProps {
|
|
|
14
14
|
$focused?: boolean | undefined;
|
|
15
15
|
$loading?: boolean | undefined;
|
|
16
16
|
$editable?: boolean | undefined;
|
|
17
|
+
$hasDescription?: boolean | undefined;
|
|
17
18
|
}
|
|
18
19
|
interface ContentSectionStyleProps {
|
|
19
20
|
$hasThumbnail?: boolean | undefined;
|
|
@@ -22,6 +23,7 @@ interface ActionContainerStyleProps {
|
|
|
22
23
|
$editable?: boolean | undefined;
|
|
23
24
|
$error?: boolean | undefined;
|
|
24
25
|
$loading?: boolean | undefined;
|
|
26
|
+
$hasDescription?: boolean | undefined;
|
|
25
27
|
}
|
|
26
28
|
interface FileSizeSectionStyleProps {
|
|
27
29
|
$hideInMobile?: boolean | undefined;
|
|
@@ -51,6 +53,17 @@ export declare const FileSizeText: import("styled-components/dist/types").IStyle
|
|
|
51
53
|
as?: import("styled-components").WebTarget | undefined;
|
|
52
54
|
forwardedAs?: import("styled-components").WebTarget | undefined;
|
|
53
55
|
}, never>>> & string;
|
|
56
|
+
export declare const DescriptionFileSizeText: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("../..").TypographyProps & {
|
|
57
|
+
ref?: import("react").RefObject<HTMLParagraphElement> | undefined;
|
|
58
|
+
} & {
|
|
59
|
+
as?: import("styled-components").WebTarget | undefined;
|
|
60
|
+
forwardedAs?: import("styled-components").WebTarget | undefined;
|
|
61
|
+
}, never> & Partial<Pick<import("../..").TypographyProps & {
|
|
62
|
+
ref?: import("react").RefObject<HTMLParagraphElement> | undefined;
|
|
63
|
+
} & {
|
|
64
|
+
as?: import("styled-components").WebTarget | undefined;
|
|
65
|
+
forwardedAs?: import("styled-components").WebTarget | undefined;
|
|
66
|
+
}, never>>> & string;
|
|
54
67
|
export declare const ItemText: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("../..").TypographyProps & {
|
|
55
68
|
ref?: import("react").RefObject<HTMLParagraphElement> | undefined;
|
|
56
69
|
} & {
|
|
@@ -62,6 +75,7 @@ export declare const ItemText: import("styled-components/dist/types").IStyledCom
|
|
|
62
75
|
as?: import("styled-components").WebTarget | undefined;
|
|
63
76
|
forwardedAs?: import("styled-components").WebTarget | undefined;
|
|
64
77
|
}, never>>> & string;
|
|
78
|
+
export declare const ItemDescriptionLabel: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>>> & string;
|
|
65
79
|
export declare const ItemDescriptionText: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("../..").TypographyProps & {
|
|
66
80
|
ref?: import("react").RefObject<HTMLParagraphElement> | undefined;
|
|
67
81
|
} & {
|