@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.
Files changed (148) hide show
  1. package/cjs/e-signature/e-signature-canvas.js +1 -1
  2. package/cjs/e-signature/e-signature-canvas.js.map +1 -1
  3. package/cjs/e-signature/e-signature.styles.js +19 -15
  4. package/cjs/e-signature/e-signature.styles.js.map +1 -1
  5. package/cjs/file-download/file-list-card/file-list-card.styles.js +1 -1
  6. package/cjs/file-download/file-list-card/file-list-card.styles.js.map +1 -1
  7. package/cjs/file-upload/file-item-edit.js +1 -1
  8. package/cjs/file-upload/file-item-edit.js.map +1 -1
  9. package/cjs/file-upload/file-item-edit.styles.js +12 -7
  10. package/cjs/file-upload/file-item-edit.styles.js.map +1 -1
  11. package/cjs/file-upload/file-list-item/file-list-item.js +1 -1
  12. package/cjs/file-upload/file-list-item/file-list-item.js.map +1 -1
  13. package/cjs/file-upload/file-list-item/file-list-item.styles.js +74 -52
  14. package/cjs/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
  15. package/cjs/file-upload/file-list.js +1 -1
  16. package/cjs/file-upload/file-list.js.map +1 -1
  17. package/cjs/file-upload/file-list.styles.js +4 -11
  18. package/cjs/file-upload/file-list.styles.js.map +1 -1
  19. package/cjs/file-upload/file-upload.js +1 -1
  20. package/cjs/file-upload/file-upload.js.map +1 -1
  21. package/cjs/footer/footer-helper.js +1 -1
  22. package/cjs/footer/footer-helper.js.map +1 -1
  23. package/cjs/form/form-label.style.js +11 -8
  24. package/cjs/form/form-label.style.js.map +1 -1
  25. package/cjs/index.js +1 -1
  26. package/cjs/navbar/drawer.js +1 -1
  27. package/cjs/navbar/drawer.js.map +1 -1
  28. package/cjs/navbar/navbar-logo-data.js +1 -1
  29. package/cjs/navbar/navbar-logo-data.js.map +1 -1
  30. package/cjs/navbar/navbar.js +1 -1
  31. package/cjs/navbar/navbar.js.map +1 -1
  32. package/cjs/shared/internal-calendar/calendar-manager.style.js +18 -17
  33. package/cjs/shared/internal-calendar/calendar-manager.style.js.map +1 -1
  34. package/cjs/theme/colour-primitive/specs/toteboard-colour-set.js +2 -0
  35. package/cjs/theme/colour-primitive/specs/toteboard-colour-set.js.map +1 -0
  36. package/cjs/theme/colour-primitive/theme-helper.js +1 -1
  37. package/cjs/theme/colour-primitive/theme-helper.js.map +1 -1
  38. package/cjs/theme/colour-semantic/theme-helper.js +1 -1
  39. package/cjs/theme/colour-semantic/theme-helper.js.map +1 -1
  40. package/cjs/theme/font/specs/toteboard-font-set.js +2 -0
  41. package/cjs/theme/font/specs/toteboard-font-set.js.map +1 -0
  42. package/cjs/theme/font/theme-helper.js +1 -1
  43. package/cjs/theme/font/theme-helper.js.map +1 -1
  44. package/cjs/theme/font-spec/specs/bookingsg-font-spec-set.js +1 -1
  45. package/cjs/theme/font-spec/specs/bookingsg-font-spec-set.js.map +1 -1
  46. package/cjs/theme/font-spec/specs/default-font-spec-set.js +1 -1
  47. package/cjs/theme/font-spec/specs/default-font-spec-set.js.map +1 -1
  48. package/cjs/theme/font-spec/specs/sgw-digital-lobby-font-spec-set.js +1 -1
  49. package/cjs/theme/font-spec/specs/sgw-digital-lobby-font-spec-set.js.map +1 -1
  50. package/cjs/theme/font-spec/specs/toteboard-font-spec-set.js +2 -0
  51. package/cjs/theme/font-spec/specs/toteboard-font-spec-set.js.map +1 -0
  52. package/cjs/theme/font-spec/theme-helper.js +1 -1
  53. package/cjs/theme/font-spec/theme-helper.js.map +1 -1
  54. package/cjs/theme/index.js +1 -1
  55. package/cjs/theme/index.js.map +1 -1
  56. package/cjs/time-range-picker/combobox-picker/combobox-picker.js +1 -1
  57. package/cjs/time-range-picker/combobox-picker/combobox-picker.js.map +1 -1
  58. package/cjs/time-range-picker/common.styles.js +7 -3
  59. package/cjs/time-range-picker/common.styles.js.map +1 -1
  60. package/cjs/time-range-picker/dial-picker/dial-picker.js +1 -1
  61. package/cjs/time-range-picker/dial-picker/dial-picker.js.map +1 -1
  62. package/cjs/timepicker/timepicker.styles.js +7 -3
  63. package/cjs/timepicker/timepicker.styles.js.map +1 -1
  64. package/cjs/typography/typography.styles.js +6 -6
  65. package/cjs/typography/typography.styles.js.map +1 -1
  66. package/cjs/util/merge-refs.js +1 -1
  67. package/cjs/util/merge-refs.js.map +1 -1
  68. package/e-signature/e-signature-canvas.js +1 -1
  69. package/e-signature/e-signature-canvas.js.map +1 -1
  70. package/e-signature/e-signature.styles.js +20 -16
  71. package/e-signature/e-signature.styles.js.map +1 -1
  72. package/file-download/file-list-card/file-list-card.styles.js +1 -1
  73. package/file-download/file-list-card/file-list-card.styles.js.map +1 -1
  74. package/file-upload/file-item-edit.d.ts +4 -1
  75. package/file-upload/file-item-edit.js +1 -1
  76. package/file-upload/file-item-edit.js.map +1 -1
  77. package/file-upload/file-item-edit.styles.js +21 -16
  78. package/file-upload/file-item-edit.styles.js.map +1 -1
  79. package/file-upload/file-list-item/file-list-item.d.ts +3 -1
  80. package/file-upload/file-list-item/file-list-item.js +1 -1
  81. package/file-upload/file-list-item/file-list-item.js.map +1 -1
  82. package/file-upload/file-list-item/file-list-item.styles.d.ts +14 -0
  83. package/file-upload/file-list-item/file-list-item.styles.js +67 -45
  84. package/file-upload/file-list-item/file-list-item.styles.js.map +1 -1
  85. package/file-upload/file-list.d.ts +3 -0
  86. package/file-upload/file-list.js +1 -1
  87. package/file-upload/file-list.js.map +1 -1
  88. package/file-upload/file-list.styles.js +4 -11
  89. package/file-upload/file-list.styles.js.map +1 -1
  90. package/file-upload/file-upload.d.ts +1 -1
  91. package/file-upload/file-upload.js +1 -1
  92. package/file-upload/file-upload.js.map +1 -1
  93. package/file-upload/types.d.ts +5 -0
  94. package/footer/footer-helper.js +1 -1
  95. package/footer/footer-helper.js.map +1 -1
  96. package/form/form-label.style.js +12 -9
  97. package/form/form-label.style.js.map +1 -1
  98. package/index.js +1 -1
  99. package/navbar/drawer.js +1 -1
  100. package/navbar/drawer.js.map +1 -1
  101. package/navbar/navbar-logo-data.js +1 -1
  102. package/navbar/navbar-logo-data.js.map +1 -1
  103. package/navbar/navbar.js +1 -1
  104. package/navbar/navbar.js.map +1 -1
  105. package/package.json +1 -1
  106. package/shared/internal-calendar/calendar-manager.style.js +18 -17
  107. package/shared/internal-calendar/calendar-manager.style.js.map +1 -1
  108. package/theme/colour-primitive/specs/toteboard-colour-set.d.ts +2 -0
  109. package/theme/colour-primitive/specs/toteboard-colour-set.js +2 -0
  110. package/theme/colour-primitive/specs/toteboard-colour-set.js.map +1 -0
  111. package/theme/colour-primitive/theme-helper.js +1 -1
  112. package/theme/colour-primitive/theme-helper.js.map +1 -1
  113. package/theme/colour-semantic/theme-helper.js +1 -1
  114. package/theme/colour-semantic/theme-helper.js.map +1 -1
  115. package/theme/font/specs/toteboard-font-set.d.ts +2 -0
  116. package/theme/font/specs/toteboard-font-set.js +2 -0
  117. package/theme/font/specs/toteboard-font-set.js.map +1 -0
  118. package/theme/font/theme-helper.js +1 -1
  119. package/theme/font/theme-helper.js.map +1 -1
  120. package/theme/font-spec/specs/bookingsg-font-spec-set.js +1 -1
  121. package/theme/font-spec/specs/bookingsg-font-spec-set.js.map +1 -1
  122. package/theme/font-spec/specs/default-font-spec-set.js +1 -1
  123. package/theme/font-spec/specs/default-font-spec-set.js.map +1 -1
  124. package/theme/font-spec/specs/sgw-digital-lobby-font-spec-set.js +1 -1
  125. package/theme/font-spec/specs/sgw-digital-lobby-font-spec-set.js.map +1 -1
  126. package/theme/font-spec/specs/toteboard-font-spec-set.d.ts +2 -0
  127. package/theme/font-spec/specs/toteboard-font-spec-set.js +2 -0
  128. package/theme/font-spec/specs/toteboard-font-spec-set.js.map +1 -0
  129. package/theme/font-spec/theme-helper.js +1 -1
  130. package/theme/font-spec/theme-helper.js.map +1 -1
  131. package/theme/index.d.ts +19 -0
  132. package/theme/index.js +1 -1
  133. package/theme/index.js.map +1 -1
  134. package/theme/types.d.ts +3 -3
  135. package/time-range-picker/combobox-picker/combobox-picker.js +1 -1
  136. package/time-range-picker/combobox-picker/combobox-picker.js.map +1 -1
  137. package/time-range-picker/common.styles.d.ts +6 -2
  138. package/time-range-picker/common.styles.js +9 -5
  139. package/time-range-picker/common.styles.js.map +1 -1
  140. package/time-range-picker/dial-picker/dial-picker.js +1 -1
  141. package/time-range-picker/dial-picker/dial-picker.js.map +1 -1
  142. package/timepicker/timepicker.styles.js +7 -3
  143. package/timepicker/timepicker.styles.js.map +1 -1
  144. package/typography/typography.styles.js +4 -4
  145. package/typography/typography.styles.js.map +1 -1
  146. package/util/merge-refs.d.ts +1 -1
  147. package/util/merge-refs.js +1 -1
  148. package/util/merge-refs.js.map +1 -1
@@ -1,4 +1,4 @@
1
- import i,{css as o}from"styled-components";import{DragHandleIcon as e}from"@lifesg/react-icons/drag-handle";import{ExclamationCircleFillIcon as t}from"@lifesg/react-icons/exclamation-circle-fill";import{IconButton as r}from"../../icon-button/icon-button.js";import{Spacing as n,Colour as d,Border as a,Radius as l,MediaQuery as s,Shadow as c}from"../../theme/index.js";import{Typography as m}from"../../typography/typography.js";const g=i.li`
1
+ import i,{css as t}from"styled-components";import{DragHandleIcon as o}from"@lifesg/react-icons/drag-handle";import{ExclamationCircleFillIcon as e}from"@lifesg/react-icons/exclamation-circle-fill";import{IconButton as r}from"../../icon-button/icon-button.js";import{Spacing as n,Colour as a,Border as d,Radius as l,MediaQuery as s,Shadow as c,Font as m}from"../../theme/index.js";import{Typography as $}from"../../typography/typography.js";const g=i.li`
2
2
  display: flex;
3
3
  align-items: center;
4
4
  width: 100%;
@@ -8,14 +8,14 @@ import i,{css as o}from"styled-components";import{DragHandleIcon as e}from"@life
8
8
  margin-bottom: ${n["spacing-16"]};
9
9
  }
10
10
 
11
- ${i=>i.$disabled&&"none"===i.$focusType?o`
11
+ ${i=>i.$disabled&&"none"===i.$focusType?t`
12
12
  cursor: not-allowed;
13
- `:i.$sortable&&"self"===i.$focusType?o`
13
+ `:i.$sortable&&"self"===i.$focusType?t`
14
14
  cursor: grabbing;
15
15
  // Following recommendation by the library for touch events
16
16
  // https://docs.dndkit.com/api-documentation/sensors/touch#recommendations
17
17
  touch-action: manipulation;
18
- `:i.$sortable?o`
18
+ `:i.$sortable?t`
19
19
  &:hover {
20
20
  cursor: grab;
21
21
  }
@@ -23,20 +23,20 @@ import i,{css as o}from"styled-components";import{DragHandleIcon as e}from"@life
23
23
  // https://docs.dndkit.com/api-documentation/sensors/touch#recommendations
24
24
  touch-action: manipulation;
25
25
  `:void 0}
26
- `,$=i(e)`
26
+ `,p=i(o)`
27
27
  margin-right: ${n["spacing-16"]};
28
28
  height: 1.5rem;
29
29
  width: 1.5rem;
30
- color: ${d.icon};
30
+ color: ${a.icon};
31
31
 
32
- ${i=>i.$active?o`
33
- color: ${d["icon-primary"]};
34
- `:i.$disabled?o`
35
- color: ${d["icon-disabled"]};
32
+ ${i=>i.$active?t`
33
+ color: ${a["icon-primary"]};
34
+ `:i.$disabled?t`
35
+ color: ${a["icon-disabled"]};
36
36
  `:void 0};
37
- `,p=i.div`
38
- background: ${d["bg-primary-subtlest"]};
39
- border: ${a["width-010"]} ${a.solid} ${d.border};
37
+ `,f=i.div`
38
+ background: ${a["bg-primary-subtlest"]};
39
+ border: ${d["width-010"]} ${d.solid} ${a.border};
40
40
  border-radius: ${l.sm};
41
41
  padding: ${n["spacing-16"]} ${n["spacing-32"]};
42
42
  display: flex;
@@ -47,17 +47,17 @@ import i,{css as o}from"styled-components";import{DragHandleIcon as e}from"@life
47
47
  padding: ${n["spacing-16"]};
48
48
  }
49
49
 
50
- ${i=>i.$focused?o`
51
- border-color: ${d["border-focus"]};
50
+ ${i=>i.$focused?t`
51
+ border-color: ${a["border-focus"]};
52
52
  box-shadow: ${c["xs-focus-strong"]};
53
- `:i.$disabled?o`
54
- border-color: ${d["border-disabled"]};
55
- `:i.$error?o`
56
- background: ${d["bg-error"]};
57
- border-color: ${d["border-error"]};
53
+ `:i.$disabled?t`
54
+ border-color: ${a["border-disabled"]};
55
+ `:i.$error?t`
56
+ background: ${a["bg-error"]};
57
+ border-color: ${a["border-error"]};
58
58
  `:void 0}
59
59
 
60
- ${i=>{if(!i.$error&&(i.$loading||i.$editable))return o`
60
+ ${i=>{if(!i.$error&&(i.$loading||i.$editable))return t`
61
61
  ${s.MaxWidth.md} {
62
62
  flex-direction: column;
63
63
  align-items: flex-start;
@@ -74,56 +74,71 @@ import i,{css as o}from"styled-components";import{DragHandleIcon as e}from"@life
74
74
  align-items: flex-start;
75
75
  }
76
76
 
77
- ${i=>{if(i.$hasThumbnail)return o`
77
+ ${i=>{if(i.$hasThumbnail)return t`
78
78
  ${s.MaxWidth.md} {
79
79
  flex-direction: row;
80
80
  align-items: center;
81
81
  }
82
82
  `}}
83
- `,f=i.div`
83
+ `,b=i.div`
84
84
  display: flex;
85
85
  flex: 1;
86
86
  flex-direction: column;
87
87
  width: 100%;
88
- `,b=i.div`
88
+ `,x=i.div`
89
89
  display: flex;
90
90
  flex: 1;
91
- align-items: center;
91
+ flex-direction: column;
92
+ align-items: flex-start;
92
93
 
93
94
  ${s.MaxWidth.md} {
94
- flex-direction: column;
95
- align-items: flex-start;
96
95
  width: 100%;
97
96
  }
98
- `,x=i.div`
97
+ `,u=i.div`
99
98
  display: flex;
100
99
  width: 5rem;
101
100
  margin-left: ${n["spacing-8"]};
102
101
  justify-content: flex-end;
103
102
 
103
+ ${x} > & {
104
+ width: auto;
105
+ margin-left: 0;
106
+ margin-top: ${n["spacing-16"]};
107
+ justify-content: flex-start;
108
+ }
109
+
104
110
  ${s.MaxWidth.md} {
105
- ${i=>i.$hideInMobile?o`
111
+ ${i=>i.$hideInMobile?t`
106
112
  display: none;
107
113
  visibility: hidden;
108
- `:o`
114
+ `:t`
109
115
  width: 100%;
110
116
  margin-left: 0;
111
117
  margin-top: ${n["spacing-8"]};
112
118
  justify-content: flex-start;
113
119
  `}
114
120
  }
115
- `,u=i(m.BodyMD)`
116
- color: ${d["text-subtler"]};
117
- `,y=i(m.BodyMD)``,v=i(y)`
121
+ `,y=i($.BodyMD)`
122
+ color: ${a["text-subtler"]};
123
+ `,w=i($.BodyMD)`
124
+ color: ${a["text-subtler"]};
125
+ margin-top: ${n["spacing-16"]};
126
+ `,v=i($.BodyMD)``,M=i.span`
127
+ ${m["form-label"]}
128
+ font-weight: ${m.Spec["weight-semibold"]};
129
+ color: ${a["text-subtle"]};
130
+ display: block;
131
+ margin-top: ${n["spacing-16"]};
132
+ `,W=i(v)`
118
133
  margin-top: ${n["spacing-4"]};
119
- `,w=i(t)`
134
+ `,j=i(e)`
120
135
  height: 1lh;
121
136
  width: 1em;
122
137
  flex-shrink: 0;
123
- color: ${d["icon-error-strong"]};
124
- `,M=i(m.BodySM)`
125
- color: ${d["text-error"]};
126
- `,W=i(M)`
138
+ color: ${a["icon-error-strong"]};
139
+ `,k=i($.BodySM)`
140
+ color: ${a["text-error"]};
141
+ `,B=i(k)`
127
142
  margin-top: ${n["spacing-4"]};
128
143
  display: flex;
129
144
  gap: ${n["spacing-4"]};
@@ -132,7 +147,7 @@ import i,{css as o}from"styled-components";import{DragHandleIcon as e}from"@life
132
147
  display: none;
133
148
  visibility: hidden;
134
149
  }
135
- `,j=i(M)`
150
+ `,D=i(k)`
136
151
  display: none;
137
152
  visibility: hidden;
138
153
 
@@ -142,31 +157,38 @@ import i,{css as o}from"styled-components";import{DragHandleIcon as e}from"@life
142
157
  visibility: visible;
143
158
  margin-top: ${n["spacing-8"]};
144
159
  }
145
- `,k=i.div`
160
+ `,I=i.div`
146
161
  width: 6rem;
147
162
  margin-left: ${n["spacing-32"]};
148
163
  display: flex;
149
164
  justify-content: flex-end;
150
165
  align-items: center;
151
166
 
167
+ ${i=>{if(i.$hasDescription&&i.$editable&&!i.$error&&!i.$loading)return t`
168
+ width: 100%;
169
+ margin-left: 0;
170
+ margin-top: ${n["spacing-16"]};
171
+ justify-content: flex-end;
172
+ `}}
173
+
152
174
  ${s.MaxWidth.md} {
153
175
  width: fit-content;
154
176
 
155
- ${i=>i.$loading&&!i.$error?o`
177
+ ${i=>i.$loading&&!i.$error?t`
156
178
  margin-left: 0;
157
179
  margin-top: ${n["spacing-16"]};
158
180
  width: 100%;
159
- `:i.$editable&&!i.$error?o`
181
+ `:i.$editable&&!i.$error?t`
160
182
  margin-left: 0;
161
183
  margin-top: ${n["spacing-16"]};
162
184
  align-self: flex-end;
163
185
  `:void 0}
164
186
  }
165
- `,B=i(r)`
187
+ `,T=i(r)`
166
188
  min-width: unset;
167
189
 
168
190
  &:not(:last-child) {
169
- margin-right: ${n["spacing-16"]};
191
+ margin-right: ${n["spacing-8"]};
170
192
  }
171
- `;export{k as ActionContainer,M as BaseErrorMessage,p as Box,h as ContentSection,W as DesktopErrorMessage,$ as DragHandleIcon,w as ErrorIcon,b as ExtendedNameSection,x as FileSizeSection,u as FileSizeText,B as IconButton,g as Item,v as ItemDescriptionText,y as ItemText,j as MobileErrorMessage,f as NameSection};
193
+ `;export{I as ActionContainer,k as BaseErrorMessage,f as Box,h as ContentSection,w as DescriptionFileSizeText,B as DesktopErrorMessage,p as DragHandleIcon,j as ErrorIcon,x as ExtendedNameSection,u as FileSizeSection,y as FileSizeText,T as IconButton,g as Item,M as ItemDescriptionLabel,W as ItemDescriptionText,v as ItemText,D as MobileErrorMessage,b as NameSection};
172
194
  //# sourceMappingURL=file-list-item.styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-list-item.styles.js","sources":["../../../src/file-upload/file-list-item/file-list-item.styles.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { DragHandleIcon as DSDragHandleIcon } from \"@lifesg/react-icons/drag-handle\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport { IconButton as DSIconButton } from \"../../icon-button\";\nimport {\n Border,\n Colour,\n MediaQuery,\n Radius,\n Shadow,\n Spacing,\n} from \"../../theme\";\nimport { Typography } from \"../../typography\";\n\n// =============================================================================\n// STYLE INTERFACES\n// =============================================================================\nexport type ItemFocusType = \"self\" | \"others\" | \"none\";\ninterface ItemStyleProps {\n $sortable: boolean;\n $disabled?: boolean | undefined;\n $focusType: ItemFocusType;\n}\n\ninterface DragHandleIconStyleProps {\n $disabled?: boolean | undefined;\n $active?: boolean | undefined;\n}\n\ninterface BoxStyleProps {\n $error?: boolean | undefined;\n $disabled?: boolean | undefined;\n $focused?: boolean | undefined;\n $loading?: boolean | undefined;\n $editable?: boolean | undefined;\n}\n\ninterface ContentSectionStyleProps {\n $hasThumbnail?: boolean | undefined;\n}\n\ninterface ActionContainerStyleProps {\n $editable?: boolean | undefined;\n $error?: boolean | undefined;\n $loading?: boolean | undefined;\n}\n\ninterface FileSizeSectionStyleProps {\n $hideInMobile?: boolean | undefined;\n}\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const Item = styled.li<ItemStyleProps>`\n display: flex;\n align-items: center;\n width: 100%;\n border: none;\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n\n ${(props) => {\n if (props.$disabled && props.$focusType === \"none\") {\n // Show disabled cursor only if no dragging is happening\n return css`\n cursor: not-allowed;\n `;\n } else if (props.$sortable && props.$focusType === \"self\") {\n return css`\n cursor: grabbing;\n // Following recommendation by the library for touch events\n // https://docs.dndkit.com/api-documentation/sensors/touch#recommendations\n touch-action: manipulation;\n `;\n } else if (props.$sortable) {\n return css`\n &:hover {\n cursor: grab;\n }\n // Following recommendation by the library for touch events\n // https://docs.dndkit.com/api-documentation/sensors/touch#recommendations\n touch-action: manipulation;\n `;\n }\n }}\n`;\n\nexport const DragHandleIcon = styled(\n DSDragHandleIcon\n)<DragHandleIconStyleProps>`\n margin-right: ${Spacing[\"spacing-16\"]};\n height: 1.5rem;\n width: 1.5rem;\n color: ${Colour[\"icon\"]};\n\n ${(props) => {\n if (props.$active) {\n return css`\n color: ${Colour[\"icon-primary\"]};\n `;\n }\n\n if (props.$disabled) {\n return css`\n color: ${Colour[\"icon-disabled\"]};\n `;\n }\n }};\n`;\n\nexport const Box = styled.div<BoxStyleProps>`\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n padding: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-32\"]};\n display: flex;\n align-items: center;\n width: 100%;\n\n ${MediaQuery.MaxWidth.md} {\n padding: ${Spacing[\"spacing-16\"]};\n }\n\n ${(props) => {\n if (props.$focused) {\n return css`\n border-color: ${Colour[\"border-focus\"]};\n box-shadow: ${Shadow[\"xs-focus-strong\"]};\n `;\n } else if (props.$disabled) {\n return css`\n border-color: ${Colour[\"border-disabled\"]};\n `;\n } else if (props.$error) {\n return css`\n background: ${Colour[\"bg-error\"]};\n border-color: ${Colour[\"border-error\"]};\n `;\n }\n }}\n\n ${(props) => {\n if (!props.$error && (props.$loading || props.$editable)) {\n return css`\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n align-items: flex-start;\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.md} {\n flex-direction: column;\n width: 100%;\n align-items: flex-start;\n }\n\n ${(props) => {\n if (props.$hasThumbnail) {\n return css`\n ${MediaQuery.MaxWidth.md} {\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 width: 100%;\n`;\n\nexport const ExtendedNameSection = styled.div`\n display: flex;\n flex: 1;\n align-items: center;\n\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n align-items: flex-start;\n width: 100%;\n }\n`;\n\nexport const FileSizeSection = styled.div<FileSizeSectionStyleProps>`\n display: flex;\n width: 5rem;\n margin-left: ${Spacing[\"spacing-8\"]};\n justify-content: flex-end;\n\n ${MediaQuery.MaxWidth.md} {\n ${(props) => {\n if (props.$hideInMobile) {\n return css`\n display: none;\n visibility: hidden;\n `;\n } else {\n return css`\n width: 100%;\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-8\"]};\n justify-content: flex-start;\n `;\n }\n }}\n }\n`;\n\nexport const FileSizeText = styled(Typography.BodyMD)`\n color: ${Colour[\"text-subtler\"]};\n`;\n\nexport const ItemText = styled(Typography.BodyMD)``;\n\nexport const ItemDescriptionText = styled(ItemText)`\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\nexport const BaseErrorMessage = styled(Typography.BodySM)`\n color: ${Colour[\"text-error\"]};\n`;\n\nexport const DesktopErrorMessage = styled(BaseErrorMessage)`\n margin-top: ${Spacing[\"spacing-4\"]};\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n\n ${MediaQuery.MaxWidth.md} {\n display: none;\n visibility: hidden;\n }\n`;\n\nexport const MobileErrorMessage = styled(BaseErrorMessage)`\n display: none;\n visibility: hidden;\n\n ${MediaQuery.MaxWidth.md} {\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n visibility: visible;\n margin-top: ${Spacing[\"spacing-8\"]};\n }\n`;\n\nexport const ActionContainer = styled.div<ActionContainerStyleProps>`\n width: 6rem;\n margin-left: ${Spacing[\"spacing-32\"]};\n display: flex;\n justify-content: flex-end;\n align-items: center;\n\n ${MediaQuery.MaxWidth.md} {\n width: fit-content;\n\n ${(props) => {\n if (props.$loading && !props.$error) {\n return css`\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-16\"]};\n width: 100%;\n `;\n } else if (props.$editable && !props.$error) {\n return css`\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-16\"]};\n align-self: flex-end;\n `;\n }\n }}\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"],"names":["Item","styled","li","Spacing","props","$disabled","$focusType","css","$sortable","DragHandleIcon","DSDragHandleIcon","Colour","$active","Box","div","Border","Radius","MediaQuery","MaxWidth","md","$focused","Shadow","$error","$loading","$editable","ContentSection","$hasThumbnail","NameSection","ExtendedNameSection","FileSizeSection","$hideInMobile","FileSizeText","Typography","BodyMD","ItemText","ItemDescriptionText","ErrorIcon","ExclamationCircleFillIcon","BaseErrorMessage","BodySM","DesktopErrorMessage","MobileErrorMessage","ActionContainer","IconButton","DSIconButton"],"mappings":"6aAsDO,MAAMA,EAAOC,EAAOC,EAAkB;;;;;;;yBAOpBC,EAAQ;;;MAG1BC,GACKA,EAAMC,WAAkC,SAArBD,EAAME,WAElBC,CAAG;;cAGHH,EAAMI,WAAkC,SAArBJ,EAAME,WACzBC,CAAG;;;;;cAMHH,EAAMI,UACND,CAAG;;;;;;;mBADP;EAaFE,EAAiBR,EAC1BS,EACuB;oBACPP,EAAQ;;;aAGfQ,EAAa;;MAEnBP,GACKA,EAAMQ,QACCL,CAAG;yBACGI,EAAO;cAIpBP,EAAMC,UACCE,CAAG;yBACGI,EAAO;mBAFxB;EAQKE,EAAMZ,EAAOa,GAAkB;kBAC1BH,EAAO;cACXI,EAAO,gBAAgBA,EAAc,SAAKJ,EAAe;qBAClDK,EAAW;eACjBb,EAAQ,iBAAiBA,EAAQ;;;;;MAK1Cc,EAAWC,SAASC;mBACPhB,EAAQ;;;MAGpBC,GACKA,EAAMgB,SACCb,CAAG;gCACUI,EAAO;8BACTU,EAAO;cAElBjB,EAAMC,UACNE,CAAG;gCACUI,EAAO;cAEpBP,EAAMkB,OACNf,CAAG;8BACQI,EAAO;gCACLA,EAAO;mBAHxB;;MAQRP,IACC,IAAKA,EAAMkB,SAAWlB,EAAMmB,UAAYnB,EAAMoB,WAC1C,OAAOjB,CAAG;kBACJU,EAAWC,SAASC;;;;aAK9B;EAIKM,EAAiBxB,EAAOa,GAA6B;;;;;MAK5DG,EAAWC,SAASC;;;;;;MAMnBf,IACC,GAAIA,EAAMsB,cACN,OAAOnB,CAAG;kBACJU,EAAWC,SAASC;;;;aAK9B;EAIKQ,EAAc1B,EAAOa,GAAG;;;;;EAOxBc,EAAsB3B,EAAOa,GAAG;;;;;MAKvCG,EAAWC,SAASC;;;;;EAObU,EAAkB5B,EAAOa,GAA8B;;;mBAGjDX,EAAQ;;;MAGrBc,EAAWC,SAASC;UACff,GACKA,EAAM0B,cACCvB,CAAG;;;kBAKHA,CAAG;;;kCAGQJ,EAAQ;;;;EAQ7B4B,EAAe9B,EAAO+B,EAAWC,OAAO;aACxCtB,EAAO;EAGPuB,EAAWjC,EAAO+B,EAAWC,OAAO,GAEpCE,EAAsBlC,EAAOiC,EAAS;kBACjC/B,EAAQ;EAGbiC,EAAYnC,EAAOoC,EAA0B;;;;aAI7C1B,EAAO;EAGP2B,EAAmBrC,EAAO+B,EAAWO,OAAO;aAC5C5B,EAAO;EAGP6B,EAAsBvC,EAAOqC,EAAiB;kBACzCnC,EAAQ;;WAEfA,EAAQ;;MAEbc,EAAWC,SAASC;;;;EAMbsB,EAAqBxC,EAAOqC,EAAiB;;;;MAIpDrB,EAAWC,SAASC;;eAEXhB,EAAQ;;sBAEDA,EAAQ;;EAIjBuC,EAAkBzC,EAAOa,GAA8B;;mBAEjDX,EAAQ;;;;;MAKrBc,EAAWC,SAASC;;;UAGff,GACKA,EAAMmB,WAAanB,EAAMkB,OAClBf,CAAG;;kCAEQJ,EAAQ;;kBAGnBC,EAAMoB,YAAcpB,EAAMkB,OAC1Bf,CAAG;;kCAEQJ,EAAQ;;uBAHvB;;EAWNwC,EAAa1C,EAAO2C,EAAa;;;;wBAItBzC,EAAQ;;"}
1
+ {"version":3,"file":"file-list-item.styles.js","sources":["../../../src/file-upload/file-list-item/file-list-item.styles.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\nimport { DragHandleIcon as DSDragHandleIcon } from \"@lifesg/react-icons/drag-handle\";\nimport { ExclamationCircleFillIcon } from \"@lifesg/react-icons/exclamation-circle-fill\";\nimport { IconButton as DSIconButton } from \"../../icon-button\";\nimport {\n Border,\n Colour,\n Font,\n MediaQuery,\n Radius,\n Shadow,\n Spacing,\n} from \"../../theme\";\nimport { Typography } from \"../../typography\";\n\n// =============================================================================\n// STYLE INTERFACES\n// =============================================================================\nexport type ItemFocusType = \"self\" | \"others\" | \"none\";\ninterface ItemStyleProps {\n $sortable: boolean;\n $disabled?: boolean | undefined;\n $focusType: ItemFocusType;\n}\n\ninterface DragHandleIconStyleProps {\n $disabled?: boolean | undefined;\n $active?: boolean | undefined;\n}\n\ninterface BoxStyleProps {\n $error?: boolean | undefined;\n $disabled?: boolean | undefined;\n $focused?: boolean | undefined;\n $loading?: boolean | undefined;\n $editable?: boolean | undefined;\n $hasDescription?: boolean | undefined;\n}\n\ninterface ContentSectionStyleProps {\n $hasThumbnail?: boolean | undefined;\n}\n\ninterface ActionContainerStyleProps {\n $editable?: boolean | undefined;\n $error?: boolean | undefined;\n $loading?: boolean | undefined;\n $hasDescription?: boolean | undefined;\n}\n\ninterface FileSizeSectionStyleProps {\n $hideInMobile?: boolean | undefined;\n}\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const Item = styled.li<ItemStyleProps>`\n display: flex;\n align-items: center;\n width: 100%;\n border: none;\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n\n ${(props) => {\n if (props.$disabled && props.$focusType === \"none\") {\n // Show disabled cursor only if no dragging is happening\n return css`\n cursor: not-allowed;\n `;\n } else if (props.$sortable && props.$focusType === \"self\") {\n return css`\n cursor: grabbing;\n // Following recommendation by the library for touch events\n // https://docs.dndkit.com/api-documentation/sensors/touch#recommendations\n touch-action: manipulation;\n `;\n } else if (props.$sortable) {\n return css`\n &:hover {\n cursor: grab;\n }\n // Following recommendation by the library for touch events\n // https://docs.dndkit.com/api-documentation/sensors/touch#recommendations\n touch-action: manipulation;\n `;\n }\n }}\n`;\n\nexport const DragHandleIcon = styled(\n DSDragHandleIcon\n)<DragHandleIconStyleProps>`\n margin-right: ${Spacing[\"spacing-16\"]};\n height: 1.5rem;\n width: 1.5rem;\n color: ${Colour[\"icon\"]};\n\n ${(props) => {\n if (props.$active) {\n return css`\n color: ${Colour[\"icon-primary\"]};\n `;\n }\n\n if (props.$disabled) {\n return css`\n color: ${Colour[\"icon-disabled\"]};\n `;\n }\n }};\n`;\n\nexport const Box = styled.div<BoxStyleProps>`\n background: ${Colour[\"bg-primary-subtlest\"]};\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${Colour[\"border\"]};\n border-radius: ${Radius[\"sm\"]};\n padding: ${Spacing[\"spacing-16\"]} ${Spacing[\"spacing-32\"]};\n display: flex;\n align-items: center;\n width: 100%;\n\n ${MediaQuery.MaxWidth.md} {\n padding: ${Spacing[\"spacing-16\"]};\n }\n\n ${(props) => {\n if (props.$focused) {\n return css`\n border-color: ${Colour[\"border-focus\"]};\n box-shadow: ${Shadow[\"xs-focus-strong\"]};\n `;\n } else if (props.$disabled) {\n return css`\n border-color: ${Colour[\"border-disabled\"]};\n `;\n } else if (props.$error) {\n return css`\n background: ${Colour[\"bg-error\"]};\n border-color: ${Colour[\"border-error\"]};\n `;\n }\n }}\n\n ${(props) => {\n if (!props.$error && (props.$loading || props.$editable)) {\n return css`\n ${MediaQuery.MaxWidth.md} {\n flex-direction: column;\n align-items: flex-start;\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.md} {\n flex-direction: column;\n width: 100%;\n align-items: flex-start;\n }\n\n ${(props) => {\n if (props.$hasThumbnail) {\n return css`\n ${MediaQuery.MaxWidth.md} {\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 width: 100%;\n`;\n\nexport const ExtendedNameSection = styled.div`\n display: flex;\n flex: 1;\n flex-direction: column;\n align-items: flex-start;\n\n ${MediaQuery.MaxWidth.md} {\n width: 100%;\n }\n`;\n\nexport const FileSizeSection = styled.div<FileSizeSectionStyleProps>`\n display: flex;\n width: 5rem;\n margin-left: ${Spacing[\"spacing-8\"]};\n justify-content: flex-end;\n\n ${ExtendedNameSection} > & {\n width: auto;\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-16\"]};\n justify-content: flex-start;\n }\n\n ${MediaQuery.MaxWidth.md} {\n ${(props) => {\n if (props.$hideInMobile) {\n return css`\n display: none;\n visibility: hidden;\n `;\n } else {\n return css`\n width: 100%;\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-8\"]};\n justify-content: flex-start;\n `;\n }\n }}\n }\n`;\n\nexport const FileSizeText = styled(Typography.BodyMD)`\n color: ${Colour[\"text-subtler\"]};\n`;\n\nexport const DescriptionFileSizeText = styled(Typography.BodyMD)`\n color: ${Colour[\"text-subtler\"]};\n margin-top: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const ItemText = styled(Typography.BodyMD)``;\n\nexport const ItemDescriptionLabel = styled.span`\n ${Font[\"form-label\"]}\n font-weight: ${Font.Spec[\"weight-semibold\"]};\n color: ${Colour[\"text-subtle\"]};\n display: block;\n margin-top: ${Spacing[\"spacing-16\"]};\n`;\n\nexport const ItemDescriptionText = styled(ItemText)`\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\nexport const BaseErrorMessage = styled(Typography.BodySM)`\n color: ${Colour[\"text-error\"]};\n`;\n\nexport const DesktopErrorMessage = styled(BaseErrorMessage)`\n margin-top: ${Spacing[\"spacing-4\"]};\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n\n ${MediaQuery.MaxWidth.md} {\n display: none;\n visibility: hidden;\n }\n`;\n\nexport const MobileErrorMessage = styled(BaseErrorMessage)`\n display: none;\n visibility: hidden;\n\n ${MediaQuery.MaxWidth.md} {\n display: flex;\n gap: ${Spacing[\"spacing-4\"]};\n visibility: visible;\n margin-top: ${Spacing[\"spacing-8\"]};\n }\n`;\n\nexport const ActionContainer = styled.div<ActionContainerStyleProps>`\n width: 6rem;\n margin-left: ${Spacing[\"spacing-32\"]};\n display: flex;\n justify-content: flex-end;\n align-items: center;\n\n ${(props) => {\n if (\n props.$hasDescription &&\n props.$editable &&\n !props.$error &&\n !props.$loading\n ) {\n return css`\n width: 100%;\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-16\"]};\n justify-content: flex-end;\n `;\n }\n }}\n\n ${MediaQuery.MaxWidth.md} {\n width: fit-content;\n\n ${(props) => {\n if (props.$loading && !props.$error) {\n return css`\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-16\"]};\n width: 100%;\n `;\n } else if (props.$editable && !props.$error) {\n return css`\n margin-left: 0;\n margin-top: ${Spacing[\"spacing-16\"]};\n align-self: flex-end;\n `;\n }\n }}\n }\n`;\n\nexport const IconButton = styled(DSIconButton)`\n min-width: unset;\n\n &:not(:last-child) {\n margin-right: ${Spacing[\"spacing-8\"]};\n }\n`;\n"],"names":["Item","styled","li","Spacing","props","$disabled","$focusType","css","$sortable","DragHandleIcon","DSDragHandleIcon","Colour","$active","Box","div","Border","Radius","MediaQuery","MaxWidth","md","$focused","Shadow","$error","$loading","$editable","ContentSection","$hasThumbnail","NameSection","ExtendedNameSection","FileSizeSection","$hideInMobile","FileSizeText","Typography","BodyMD","DescriptionFileSizeText","ItemText","ItemDescriptionLabel","span","Font","Spec","ItemDescriptionText","ErrorIcon","ExclamationCircleFillIcon","BaseErrorMessage","BodySM","DesktopErrorMessage","MobileErrorMessage","ActionContainer","$hasDescription","IconButton","DSIconButton"],"mappings":"ubAyDO,MAAMA,EAAOC,EAAOC,EAAkB;;;;;;;yBAOpBC,EAAQ;;;MAG1BC,GACKA,EAAMC,WAAkC,SAArBD,EAAME,WAElBC,CAAG;;cAGHH,EAAMI,WAAkC,SAArBJ,EAAME,WACzBC,CAAG;;;;;cAMHH,EAAMI,UACND,CAAG;;;;;;;mBADP;EAaFE,EAAiBR,EAC1BS,EACuB;oBACPP,EAAQ;;;aAGfQ,EAAa;;MAEnBP,GACKA,EAAMQ,QACCL,CAAG;yBACGI,EAAO;cAIpBP,EAAMC,UACCE,CAAG;yBACGI,EAAO;mBAFxB;EAQKE,EAAMZ,EAAOa,GAAkB;kBAC1BH,EAAO;cACXI,EAAO,gBAAgBA,EAAc,SAAKJ,EAAe;qBAClDK,EAAW;eACjBb,EAAQ,iBAAiBA,EAAQ;;;;;MAK1Cc,EAAWC,SAASC;mBACPhB,EAAQ;;;MAGpBC,GACKA,EAAMgB,SACCb,CAAG;gCACUI,EAAO;8BACTU,EAAO;cAElBjB,EAAMC,UACNE,CAAG;gCACUI,EAAO;cAEpBP,EAAMkB,OACNf,CAAG;8BACQI,EAAO;gCACLA,EAAO;mBAHxB;;MAQRP,IACC,IAAKA,EAAMkB,SAAWlB,EAAMmB,UAAYnB,EAAMoB,WAC1C,OAAOjB,CAAG;kBACJU,EAAWC,SAASC;;;;aAK9B;EAIKM,EAAiBxB,EAAOa,GAA6B;;;;;MAK5DG,EAAWC,SAASC;;;;;;MAMnBf,IACC,GAAIA,EAAMsB,cACN,OAAOnB,CAAG;kBACJU,EAAWC,SAASC;;;;aAK9B;EAIKQ,EAAc1B,EAAOa,GAAG;;;;;EAOxBc,EAAsB3B,EAAOa,GAAG;;;;;;MAMvCG,EAAWC,SAASC;;;EAKbU,EAAkB5B,EAAOa,GAA8B;;;mBAGjDX,EAAQ;;;MAGrByB;;;sBAGgBzB,EAAQ;;;;MAIxBc,EAAWC,SAASC;UACff,GACKA,EAAM0B,cACCvB,CAAG;;;kBAKHA,CAAG;;;kCAGQJ,EAAQ;;;;EAQ7B4B,EAAe9B,EAAO+B,EAAWC,OAAO;aACxCtB,EAAO;EAGPuB,EAA0BjC,EAAO+B,EAAWC,OAAO;aACnDtB,EAAO;kBACFR,EAAQ;EAGbgC,EAAWlC,EAAO+B,EAAWC,OAAO,GAEpCG,EAAuBnC,EAAOoC,IAAI;MACzCC,EAAK;mBACQA,EAAKC,KAAK;aAChB5B,EAAO;;kBAEFR,EAAQ;EAGbqC,EAAsBvC,EAAOkC,EAAS;kBACjChC,EAAQ;EAGbsC,EAAYxC,EAAOyC,EAA0B;;;;aAI7C/B,EAAO;EAGPgC,EAAmB1C,EAAO+B,EAAWY,OAAO;aAC5CjC,EAAO;EAGPkC,EAAsB5C,EAAO0C,EAAiB;kBACzCxC,EAAQ;;WAEfA,EAAQ;;MAEbc,EAAWC,SAASC;;;;EAMb2B,EAAqB7C,EAAO0C,EAAiB;;;;MAIpD1B,EAAWC,SAASC;;eAEXhB,EAAQ;;sBAEDA,EAAQ;;EAIjB4C,EAAkB9C,EAAOa,GAA8B;;mBAEjDX,EAAQ;;;;;MAKpBC,IACC,GACIA,EAAM4C,iBACN5C,EAAMoB,YACLpB,EAAMkB,SACNlB,EAAMmB,SAEP,OAAOhB,CAAG;;;8BAGQJ,EAAQ;;aAG9B;;MAGFc,EAAWC,SAASC;;;UAGff,GACKA,EAAMmB,WAAanB,EAAMkB,OAClBf,CAAG;;kCAEQJ,EAAQ;;kBAGnBC,EAAMoB,YAAcpB,EAAMkB,OAC1Bf,CAAG;;kCAEQJ,EAAQ;;uBAHvB;;EAWN8C,EAAahD,EAAOiD,EAAa;;;;wBAItB/C,EAAQ;;"}
@@ -1,9 +1,12 @@
1
1
  import React from "react";
2
2
  import { FileItemProps } from "./types";
3
+ import { FormLabelProps } from "../form/types";
3
4
  interface Props {
4
5
  fileItems: FileItemProps[] | undefined;
5
6
  editableFileItems: boolean;
6
7
  fileDescriptionMaxLength?: number | undefined;
8
+ descriptionRequired?: boolean | undefined;
9
+ descriptionLabel?: FormLabelProps | undefined;
7
10
  sortable?: boolean | undefined;
8
11
  disabled?: boolean | undefined;
9
12
  readOnly?: boolean | undefined;
@@ -1,2 +1,2 @@
1
- import{jsx as e,jsxs as r,Fragment as t}from"react/jsx-runtime";import{useSensors as i,useSensor as s,DndContext as o,KeyboardSensor as n,TouchSensor as l}from"../external/@dnd-kit/core/dist/core.esm.js";import{SortableContext as d,verticalListSortingStrategy as a,arrayMove as c,sortableKeyboardCoordinates as p}from"../external/@dnd-kit/sortable/dist/sortable.esm.js";import{forwardRef as f,useState as u,useContext as m,useRef as g,useImperativeHandle as h,useEffect as y}from"react";import{useResizeDetector as b}from"../external/react-resize-detector/build/index.esm.js";import{FileUploadContext as v}from"./context.js";import{MouseSensor as j}from"./custom-sensors.js";import{FileItemEdit as x}from"./file-item-edit.js";import{FileListItem as $}from"./file-list-item/file-list-item.js";import{ListWrapper as I,EditableItemsContainer as O}from"./file-list.styles.js";import{FileUploadHelper as M}from"./helper.js";import{VisuallyHidden as D}from"../shared/accessibility/index.js";const S=f((function({fileItems:f=[],editableFileItems:S,fileDescriptionMaxLength:k,sortable:w,disabled:A,readOnly:C,onItemUpdate:E,onItemDelete:F,onSort:B},L){const[W,z]=u({}),{setActiveId:G}=m(v),[K,N]=u(""),R=g({});h(L,(()=>({focus:()=>{var e;null===(e=U.current)||void 0===e||e.focus()}})));const{width:T=0,ref:U}=b(),q=g({}),H=i(s(j,{activationConstraint:{distance:8}}),s(l,{activationConstraint:{delay:150,tolerance:5}}),s(n,{coordinateGetter:p})),J=e=>{delete q.current[e]};y((()=>{const e=te(f);((e,r)=>{const t=Object.keys(e),i=Object.keys(r);if(t.length!==i.length)return!1;for(const t of i)if(e[t]!==r[t])return!1;return!0})(W,e)||z(e)}),[f,S,C]),y((()=>{var e;if(!f||0===f.length)return void N("");const r=Date.now(),t=[];for(const i of f){const s=R.current[i.id];if(i.errorMessage)"error"!==(null==s?void 0:s.status)&&(t.push("string"==typeof i.errorMessage?`Error uploading ${i.name}: ${i.errorMessage}`:`Error uploading ${i.name}`),R.current[i.id]={progress:null!==(e=i.progress)&&void 0!==e?e:1,timestamp:r,status:"error"});else if(void 0!==i.progress)if(i.progress>=1)"complete"!==(null==s?void 0:s.status)&&(t.push(`${i.name} upload is complete`),R.current[i.id]={progress:1,timestamp:r,status:"complete"});else if("number"==typeof i.progress&&i.progress<1){(!s||"in-progress"!==s.status)&&(t.push(`Starting upload of ${i.name}`),R.current[i.id]={progress:i.progress,timestamp:r,status:"in-progress"})}}t.length>0&&N(t.join(", "))}),[f]);const P=e=>r=>{ie(e.id,"display"),J(e.id);const t=Object.assign(Object.assign({},e),{description:r});E(t)},Q=e=>r=>{q.current[e.id]=r},V=e=>()=>{e.description&&0!==e.description.length?ie(e.id,"display"):F(e),J(e.id)},X=e=>()=>{ie(e.id,"edit")},Y=e=>()=>{F(e),U.current&&U.current.focus()},Z=e=>{if(B&&f){const{active:r,over:t}=e;if(t&&r.id!==t.id){const e=f.findIndex((e=>e.id===r.id)),i=f.findIndex((e=>e.id===t.id)),s=c(f,e,i);B(s)}}G(void 0)},_=e=>{const{active:r}=e;G(r.id)},ee=e=>S&&M.isSupportedImageType(e.type),re=e=>!e.errorMessage&&!C&&!("number"==typeof e.progress&&e.progress<1)&&ee(e)&&!e.description,te=e=>{if(!e||0===e.length)return{};const r={};for(const t of e)t.errorMessage?r[t.id]="error":W[t.id]?r[t.id]=W[t.id]:r[t.id]=re(t)?"edit":"display";return r},ie=(e,r)=>{z((t=>Object.assign(Object.assign({},t),{[e]:r})))},se=()=>f&&f.length>1&&w&&Object.values(W).every((e=>"display"===e)),oe=()=>{if(0===f.length)return"No files uploaded";const e=f.filter((e=>!(null==e?void 0:e.errorMessage)&&(1===e.progress||void 0===e.progress))).length,r=f.filter((e=>"number"==typeof e.progress&&e.progress<1)).length,t=f.filter((e=>e.errorMessage)).length;if(0===e&&0===r&&0===t)return"File list";const i=[e>0?`${e} completed files`:"",r>0?`${r} file in progress`:"",t>0?`${t} ${t>1?"files":"file"} with error`:""].filter(Boolean);return`${C?"Read-only file list":"File list"}. ${i.join(", ")}`},ne=()=>{const r=((e,r)=>{if(!e||0===e.length)return[];const t=[];for(const i of e)if("edit"===r[i.id]){const e=t[t.length-1];Array.isArray(e)?e.push(i):t.push([i])}else t.push(i);return t})(f,W);return 0===r.length?null:r.map(((r,t)=>Array.isArray(r)?((r,t)=>{const i=r.map((r=>{const t=Object.assign({},r);return void 0!==q.current[r.id]&&(t.description=q.current[r.id]),e(x,{fileItem:t,wrapperWidth:T,fileDescriptionMaxLength:k,onSave:P(r),onCancel:V(r),onBlur:Q(r)},r.id)}));return e(O,{children:e("ul",{children:i})},`editable-${t}`)})(r,t):e($,{fileItem:r,editable:ee(r),wrapperWidth:T,sortable:se(),disabled:A,readOnly:C,onDelete:Y(r),onEditClick:X(r)},r.id)))},le=()=>r(t,{children:[e(D,{"aria-live":"polite","aria-atomic":"true",children:K}),e(I,{tabIndex:-1,$readOnly:C,ref:U,"aria-label":oe(),children:ne()})]});return A||C||!se()?le():e(o,{sensors:H,onDragEnd:Z,onDragStart:_,children:e(d,{items:f,strategy:a,children:le()})})}));export{S as FileList};
1
+ import{jsx as e,jsxs as r,Fragment as t}from"react/jsx-runtime";import{useSensors as i,useSensor as s,DndContext as o,KeyboardSensor as n,TouchSensor as l}from"../external/@dnd-kit/core/dist/core.esm.js";import{SortableContext as d,verticalListSortingStrategy as a,arrayMove as c,sortableKeyboardCoordinates as p}from"../external/@dnd-kit/sortable/dist/sortable.esm.js";import{forwardRef as f,useState as u,useContext as m,useRef as g,useImperativeHandle as h,useEffect as b}from"react";import{useResizeDetector as y}from"../external/react-resize-detector/build/index.esm.js";import{FileUploadContext as v}from"./context.js";import{MouseSensor as j}from"./custom-sensors.js";import{FileItemEdit as x}from"./file-item-edit.js";import{FileListItem as $}from"./file-list-item/file-list-item.js";import{ListWrapper as I,EditableItemsContainer as O}from"./file-list.styles.js";import{FileUploadHelper as M}from"./helper.js";import{VisuallyHidden as D}from"../shared/accessibility/index.js";const S=f((function({fileItems:f=[],editableFileItems:S,fileDescriptionMaxLength:k,descriptionRequired:w,descriptionLabel:A,sortable:L,disabled:C,readOnly:E,onItemUpdate:F,onItemDelete:R,onSort:q},B){const[W,z]=u({}),{setActiveId:G}=m(v),[K,N]=u(""),T=g({});h(B,(()=>({focus:()=>{var e;null===(e=H.current)||void 0===e||e.focus()}})));const{width:U=0,ref:H}=y(),J=g({}),P=i(s(j,{activationConstraint:{distance:8}}),s(l,{activationConstraint:{delay:150,tolerance:5}}),s(n,{coordinateGetter:p})),Q=e=>{delete J.current[e]};b((()=>{const e=se(f);((e,r)=>{const t=Object.keys(e),i=Object.keys(r);if(t.length!==i.length)return!1;for(const t of i)if(e[t]!==r[t])return!1;return!0})(W,e)||z(e)}),[f,S,E]),b((()=>{var e;if(!f||0===f.length)return void N("");const r=Date.now(),t=[];for(const i of f){const s=T.current[i.id];if(i.errorMessage)"error"!==(null==s?void 0:s.status)&&(t.push("string"==typeof i.errorMessage?`Error uploading ${i.name}: ${i.errorMessage}`:`Error uploading ${i.name}`),T.current[i.id]={progress:null!==(e=i.progress)&&void 0!==e?e:1,timestamp:r,status:"error"});else if(void 0!==i.progress)if(i.progress>=1)"complete"!==(null==s?void 0:s.status)&&(t.push(`${i.name} upload is complete`),T.current[i.id]={progress:1,timestamp:r,status:"complete"});else if("number"==typeof i.progress&&i.progress<1){(!s||"in-progress"!==s.status)&&(t.push(`Starting upload of ${i.name}`),T.current[i.id]={progress:i.progress,timestamp:r,status:"in-progress"})}}t.length>0&&N(t.join(", "))}),[f]);const V=e=>r=>{oe(e.id,"display"),Q(e.id);const t=Object.assign(Object.assign({},e),{description:r});F(t)},X=e=>r=>{J.current[e.id]=r},Y=e=>()=>{e.description&&0!==e.description.length?oe(e.id,"display"):R(e),Q(e.id)},Z=e=>()=>{oe(e.id,"edit")},_=e=>()=>{R(e),H.current&&H.current.focus()},ee=e=>{if(q&&f){const{active:r,over:t}=e;if(t&&r.id!==t.id){const e=f.findIndex((e=>e.id===r.id)),i=f.findIndex((e=>e.id===t.id)),s=c(f,e,i);q(s)}}G(void 0)},re=e=>{const{active:r}=e;G(r.id)},te=e=>S&&M.isSupportedImageType(e.type),ie=e=>!e.errorMessage&&!E&&!("number"==typeof e.progress&&e.progress<1)&&te(e)&&!e.description,se=e=>{if(!e||0===e.length)return{};const r={};for(const t of e)t.errorMessage?r[t.id]="error":W[t.id]?r[t.id]=W[t.id]:r[t.id]=ie(t)?"edit":"display";return r},oe=(e,r)=>{z((t=>Object.assign(Object.assign({},t),{[e]:r})))},ne=()=>f&&f.length>1&&L&&Object.values(W).every((e=>"display"===e)),le=()=>{if(0===f.length)return"No files uploaded";const e=f.filter((e=>!(null==e?void 0:e.errorMessage)&&(1===e.progress||void 0===e.progress))).length,r=f.filter((e=>"number"==typeof e.progress&&e.progress<1)).length,t=f.filter((e=>e.errorMessage)).length;if(0===e&&0===r&&0===t)return"File list";const i=[e>0?`${e} completed files`:"",r>0?`${r} file in progress`:"",t>0?`${t} ${t>1?"files":"file"} with error`:""].filter(Boolean);return`${E?"Read-only file list":"File list"}. ${i.join(", ")}`},de=()=>{const r=((e,r)=>{if(!e||0===e.length)return[];const t=[];for(const i of e)if("edit"===r[i.id]){const e=t[t.length-1];Array.isArray(e)?e.push(i):t.push([i])}else t.push(i);return t})(f,W);return 0===r.length?null:r.map(((r,t)=>Array.isArray(r)?((r,t)=>{const i=r.map((r=>{const t=Object.assign({},r);return void 0!==J.current[r.id]&&(t.description=J.current[r.id]),e(x,{fileItem:t,wrapperWidth:U,fileDescriptionMaxLength:k,descriptionRequired:w,descriptionLabel:A,onSave:V(r),onCancel:Y(r),onBlur:X(r)},r.id)}));return e(O,{children:e("ul",{children:i})},`editable-${t}`)})(r,t):e($,{fileItem:r,editable:te(r),wrapperWidth:U,sortable:ne(),disabled:C,readOnly:E,descriptionLabel:A,onDelete:_(r),onEditClick:Z(r)},r.id)))},ae=()=>r(t,{children:[e(D,{"aria-live":"polite","aria-atomic":"true",children:K}),e(I,{tabIndex:-1,$readOnly:E,ref:H,"aria-label":le(),children:de()})]});return C||E||!ne()?ae():e(o,{sensors:P,onDragEnd:ee,onDragStart:re,children:e(d,{items:f,strategy:a,children:ae()})})}));export{S as FileList};
2
2
  //# sourceMappingURL=file-list.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-list.js","sources":["../../src/file-upload/file-list.tsx"],"sourcesContent":["import {\n DndContext,\n DragEndEvent,\n DragStartEvent,\n KeyboardSensor,\n TouchSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport {\n SortableContext,\n arrayMove,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport React, {\n forwardRef,\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\nimport { FileUploadContext } from \"./context\";\nimport { MouseSensor } from \"./custom-sensors\";\nimport { FileItemEdit } from \"./file-item-edit\";\nimport { FileListItem } from \"./file-list-item\";\nimport { EditableItemsContainer, ListWrapper } from \"./file-list.styles\";\nimport { FileUploadHelper } from \"./helper\";\nimport { FileItemProps } from \"./types\";\nimport { VisuallyHidden } from \"../shared/accessibility\";\n\n// =============================================================================\n// INTERFACES\n// =============================================================================\ntype RenderMode = \"edit\" | \"display\" | \"error\";\n\ntype FileItemRenderModes = Record<string, RenderMode>;\ntype FileEditedDescriptions = Record<string, string>;\n\ntype RenderItem = FileItemProps | FileItemProps[];\n\ninterface Props {\n fileItems: FileItemProps[] | undefined;\n editableFileItems: boolean;\n fileDescriptionMaxLength?: number | undefined;\n sortable?: boolean | undefined;\n disabled?: boolean | undefined;\n readOnly?: boolean | undefined;\n onItemUpdate: (item: FileItemProps) => void;\n onItemDelete: (item: FileItemProps) => void;\n onSort?: ((reorderedFileItems: FileItemProps[]) => void) | undefined;\n}\n\ntype AnnouncementProgress = Record<\n string,\n {\n progress: number;\n timestamp: number;\n status: \"in-progress\" | \"complete\" | \"error\";\n }\n>;\n\nexport interface FileListRef {\n focus: () => void;\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\nfunction Component(\n {\n fileItems = [],\n editableFileItems,\n fileDescriptionMaxLength,\n sortable,\n disabled,\n readOnly,\n onItemUpdate,\n onItemDelete,\n onSort,\n }: Props,\n ref: React.Ref<FileListRef>\n) {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const [renderModes, setRenderModes] = useState<FileItemRenderModes>({});\n const { setActiveId } = useContext(FileUploadContext);\n\n // Progress announcement state (for aria-live) - announces start and completion only\n const [progressAnnouncement, setProgressAnnouncement] = useState(\"\");\n const lastAnnouncedRef = useRef<AnnouncementProgress>({});\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n wrapperRef.current?.focus();\n },\n }));\n const { width: wrapperWidth = 0, ref: wrapperRef } = useResizeDetector();\n\n // Keep track of edited description without re-rendering\n const descriptionsValueRef = useRef<FileEditedDescriptions>({});\n\n /**\n * As the default drag sensors interfere with click events\n * on the file items, we'll need to configure the sensor to\n * only activate the drag if the mouse moves a certain distance\n */\n const sensors = useSensors(\n useSensor(MouseSensor, {\n activationConstraint: {\n distance: 8, // mouse drag of 8px then activate the drag event\n },\n }),\n useSensor(TouchSensor, {\n activationConstraint: {\n delay: 150,\n tolerance: 5,\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n // =========================================================================\n // REF METHODS\n // =========================================================================\n const removeDescription = (itemId: string) => {\n delete descriptionsValueRef.current[itemId];\n };\n\n const shallowCompareRenderModes = (\n prev: FileItemRenderModes,\n next: FileItemRenderModes\n ) => {\n const prevKeys = Object.keys(prev);\n const nextKeys = Object.keys(next);\n if (prevKeys.length !== nextKeys.length) {\n return false;\n }\n for (const k of nextKeys) {\n if (prev[k] !== next[k]) {\n return false;\n }\n }\n return true;\n };\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n const nextModes = getItemsRenderMode(fileItems);\n const prevModes = renderModes;\n // We perform shallowCompare to avoid infinite re-render loop\n if (shallowCompareRenderModes(prevModes, nextModes)) {\n return;\n }\n setRenderModes(nextModes);\n }, [fileItems, editableFileItems, readOnly]);\n\n // Progress announcements only at start and completion\n useEffect(() => {\n if (!fileItems || fileItems.length === 0) {\n setProgressAnnouncement(\"\");\n return;\n }\n const now = Date.now();\n const messages: string[] = [];\n\n for (const item of fileItems) {\n const fileStatus = lastAnnouncedRef.current[item.id];\n\n if (item.errorMessage) {\n if (fileStatus?.status !== \"error\") {\n messages.push(\n typeof item.errorMessage === \"string\"\n ? `Error uploading ${item.name}: ${item.errorMessage}`\n : `Error uploading ${item.name}`\n );\n lastAnnouncedRef.current[item.id] = {\n progress: item.progress ?? 1,\n timestamp: now,\n status: \"error\",\n };\n }\n continue;\n }\n\n if (item.progress === undefined) {\n continue;\n }\n\n if (item.progress >= 1) {\n if (fileStatus?.status !== \"complete\") {\n messages.push(`${item.name} upload is complete`);\n lastAnnouncedRef.current[item.id] = {\n progress: 1,\n timestamp: now,\n status: \"complete\",\n };\n }\n continue;\n }\n\n // In progress - only announce start, not progress updates\n if (typeof item.progress === \"number\" && item.progress < 1) {\n // Only announce when starting upload (no previous status or status was not in-progress)\n const shouldAnnounce =\n !fileStatus || fileStatus.status !== \"in-progress\";\n\n if (shouldAnnounce) {\n messages.push(`Starting upload of ${item.name}`);\n lastAnnouncedRef.current[item.id] = {\n progress: item.progress,\n timestamp: now,\n status: \"in-progress\",\n };\n }\n }\n }\n\n if (messages.length > 0) {\n // Update aria-live region once with aggregated message\n setProgressAnnouncement(messages.join(\", \"));\n }\n }, [fileItems]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleSaveEdit = (item: FileItemProps) => (description: string) => {\n updateRenderModes(item.id, \"display\");\n removeDescription(item.id);\n\n const updatedItem = { ...item, description };\n onItemUpdate(updatedItem);\n };\n\n const handleBlurEdit = (item: FileItemProps) => (value: string) => {\n descriptionsValueRef.current[item.id] = value;\n };\n\n const handleCancel = (item: FileItemProps) => () => {\n if (!item.description || item.description.length === 0) {\n // New addition\n onItemDelete(item);\n } else {\n updateRenderModes(item.id, \"display\");\n }\n removeDescription(item.id);\n };\n\n const handleInitiateEdit = (item: FileItemProps) => () => {\n updateRenderModes(item.id, \"edit\");\n };\n\n const handleDelete = (item: FileItemProps) => () => {\n onItemDelete(item);\n if (wrapperRef.current) {\n wrapperRef.current.focus();\n }\n };\n\n const handleDragEnd = (event: DragEndEvent) => {\n if (onSort && fileItems) {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const oldIndex = fileItems.findIndex(\n (item) => item.id === active.id\n );\n const newIndex = fileItems.findIndex(\n (item) => item.id === over.id\n );\n\n const updatedFileItems = arrayMove(\n fileItems,\n oldIndex,\n newIndex\n );\n\n onSort(updatedFileItems);\n }\n }\n\n setActiveId(undefined);\n };\n\n const handleDragStart = (event: DragStartEvent) => {\n const { active } = event;\n setActiveId(active.id as string);\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const checkEditable = (item: FileItemProps) => {\n return (\n editableFileItems &&\n FileUploadHelper.isSupportedImageType(item.type)\n );\n };\n\n const shouldRenderEditMode = (item: FileItemProps) => {\n return (\n !item.errorMessage &&\n !readOnly &&\n !(typeof item.progress === \"number\" && item.progress < 1) &&\n checkEditable(item) &&\n !item.description\n );\n };\n\n const getItemsRenderMode = (\n fileItems: FileItemProps[] | undefined\n ): FileItemRenderModes => {\n if (!fileItems || fileItems.length === 0) return {};\n\n const newRenderModes: FileItemRenderModes = {};\n\n for (const item of fileItems) {\n if (item.errorMessage) {\n newRenderModes[item.id] = \"error\";\n } else if (!renderModes[item.id]) {\n newRenderModes[item.id] = shouldRenderEditMode(item)\n ? \"edit\"\n : \"display\";\n } else {\n newRenderModes[item.id] = renderModes[item.id];\n }\n }\n\n return newRenderModes;\n };\n\n const updateRenderModes = (itemId: string, mode: RenderMode) => {\n setRenderModes((prevRenderModes) => {\n return {\n ...prevRenderModes,\n [itemId]: mode,\n };\n });\n };\n\n /**\n * Due to a UI requirement, we will render the items\n * with edit modes as a group\n */\n const getArrangedItems = (\n fileItems: FileItemProps[] | undefined,\n renderModes: FileItemRenderModes\n ) => {\n if (!fileItems || fileItems.length === 0) return [];\n\n const arrangedItems: RenderItem[] = [];\n\n for (const fileItem of fileItems) {\n if (renderModes[fileItem.id] === \"edit\") {\n const previousElement = arrangedItems[arrangedItems.length - 1];\n if (Array.isArray(previousElement)) {\n previousElement.push(fileItem);\n } else {\n arrangedItems.push([fileItem]);\n }\n } else {\n arrangedItems.push(fileItem);\n }\n }\n\n return arrangedItems;\n };\n\n const areAllItemsInDisplayViews = () => {\n return Object.values(renderModes).every((mode) => mode === \"display\");\n };\n\n const shouldEnableSort = () => {\n return (\n fileItems &&\n fileItems.length > 1 &&\n sortable &&\n areAllItemsInDisplayViews()\n );\n };\n\n /**\n * If there are no files, return \"No files uploaded\".\n * If readOnly is true, return \"Read-only file list\".\n * If there are files, return a summary of the file statuses.\n * For example, \"File list. 2 completed files, 1 file in progress, 1 file with error\".\n *\n * @returns aria label\n */\n const getWrapperAriaLabel = () => {\n if (fileItems.length === 0) {\n return \"No files uploaded\";\n }\n const completedCount = fileItems.filter(\n (item) =>\n !item?.errorMessage &&\n (item.progress === 1 || item.progress === undefined)\n ).length;\n const inProgressCount = fileItems.filter(\n (item) => typeof item.progress === \"number\" && item.progress < 1\n ).length;\n const errorCount = fileItems.filter((item) => item.errorMessage).length;\n if (completedCount === 0 && inProgressCount === 0 && errorCount === 0) {\n return `File list`;\n }\n const completedText =\n completedCount > 0 ? `${completedCount} completed files` : \"\";\n const inProgressText =\n inProgressCount > 0 ? `${inProgressCount} file in progress` : \"\";\n const errorText =\n errorCount > 0\n ? `${errorCount} ${\n errorCount > 1 ? \"files\" : \"file\"\n } with error`\n : \"\";\n const parts = [completedText, inProgressText, errorText].filter(\n Boolean\n );\n const prefix = readOnly ? \"Read-only file list\" : \"File list\";\n return `${prefix}. ${parts.join(\", \")}`;\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderItemsInEditMode = (\n fileItems: FileItemProps[],\n keyToUse: number\n ) => {\n const itemsToRender = fileItems.map((item) => {\n const updatedFileItem = { ...item };\n if (descriptionsValueRef.current[item.id] !== undefined) {\n updatedFileItem.description =\n descriptionsValueRef.current[item.id];\n }\n\n return (\n <FileItemEdit\n key={item.id}\n fileItem={updatedFileItem}\n wrapperWidth={wrapperWidth}\n fileDescriptionMaxLength={fileDescriptionMaxLength}\n onSave={handleSaveEdit(item)}\n onCancel={handleCancel(item)}\n onBlur={handleBlurEdit(item)}\n />\n );\n });\n\n return (\n <EditableItemsContainer key={`editable-${keyToUse}`}>\n <ul>{itemsToRender}</ul>\n </EditableItemsContainer>\n );\n };\n\n const renderItems = () => {\n const arrangedItems = getArrangedItems(fileItems, renderModes);\n\n if (arrangedItems.length === 0) return null;\n\n return arrangedItems.map((item, index) => {\n if (Array.isArray(item)) {\n return renderItemsInEditMode(item, index);\n } else {\n return (\n <FileListItem\n key={item.id}\n fileItem={item}\n editable={checkEditable(item)}\n wrapperWidth={wrapperWidth}\n sortable={shouldEnableSort()}\n disabled={disabled}\n readOnly={readOnly}\n onDelete={handleDelete(item)}\n onEditClick={handleInitiateEdit(item)}\n />\n );\n }\n });\n };\n\n /**\n * Renders the progress status of each file upload.\n * In progress: 25% complete for uploading filename.pdf\n * Complete: filename.pdf upload is complete\n * Error: Error uploading filename.pdf: error message\n *\n * @returns A visually hidden element announcing the progress status.\n */\n const renderProgressStatus = () => (\n <VisuallyHidden aria-live=\"polite\" aria-atomic=\"true\">\n {progressAnnouncement}\n </VisuallyHidden>\n );\n\n const renderItemsWithWrapper = () => {\n return (\n <>\n {renderProgressStatus()}\n <ListWrapper\n tabIndex={-1}\n $readOnly={readOnly}\n ref={wrapperRef}\n aria-label={getWrapperAriaLabel()}\n >\n {renderItems()}\n </ListWrapper>\n </>\n );\n };\n\n if (disabled || readOnly || !shouldEnableSort()) {\n return renderItemsWithWrapper();\n } else {\n return (\n <DndContext\n sensors={sensors}\n onDragEnd={handleDragEnd}\n onDragStart={handleDragStart}\n >\n <SortableContext\n items={fileItems}\n strategy={verticalListSortingStrategy}\n >\n {renderItemsWithWrapper()}\n </SortableContext>\n </DndContext>\n );\n }\n}\n\nexport const FileList = forwardRef<FileListRef, Props>(Component);\n"],"names":["FileList","forwardRef","fileItems","editableFileItems","fileDescriptionMaxLength","sortable","disabled","readOnly","onItemUpdate","onItemDelete","onSort","ref","renderModes","setRenderModes","useState","setActiveId","useContext","FileUploadContext","progressAnnouncement","setProgressAnnouncement","lastAnnouncedRef","useRef","useImperativeHandle","focus","_a","wrapperRef","current","width","wrapperWidth","useResizeDetector","descriptionsValueRef","sensors","useSensors","useSensor","MouseSensor","activationConstraint","distance","TouchSensor","delay","tolerance","KeyboardSensor","coordinateGetter","sortableKeyboardCoordinates","removeDescription","itemId","useEffect","nextModes","getItemsRenderMode","prev","next","prevKeys","Object","keys","nextKeys","length","k","shallowCompareRenderModes","now","Date","messages","item","fileStatus","id","errorMessage","status","push","name","progress","timestamp","undefined","join","handleSaveEdit","description","updateRenderModes","updatedItem","assign","handleBlurEdit","value","handleCancel","handleInitiateEdit","handleDelete","handleDragEnd","event","active","over","oldIndex","findIndex","newIndex","updatedFileItems","arrayMove","handleDragStart","checkEditable","FileUploadHelper","isSupportedImageType","type","shouldRenderEditMode","newRenderModes","mode","prevRenderModes","shouldEnableSort","values","every","getWrapperAriaLabel","completedCount","filter","inProgressCount","errorCount","parts","Boolean","renderItems","arrangedItems","fileItem","previousElement","Array","isArray","getArrangedItems","map","index","keyToUse","itemsToRender","updatedFileItem","_jsx","FileItemEdit","onSave","onCancel","onBlur","EditableItemsContainer","children","renderItemsInEditMode","FileListItem","editable","onDelete","onEditClick","renderItemsWithWrapper","_jsxs","_Fragment","VisuallyHidden","ListWrapper","tabIndex","$readOnly","DndContext","onDragEnd","onDragStart","SortableContext","items","strategy","verticalListSortingStrategy"],"mappings":"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"}
1
+ {"version":3,"file":"file-list.js","sources":["../../src/file-upload/file-list.tsx"],"sourcesContent":["import {\n DndContext,\n DragEndEvent,\n DragStartEvent,\n KeyboardSensor,\n TouchSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport {\n SortableContext,\n arrayMove,\n sortableKeyboardCoordinates,\n verticalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport React, {\n forwardRef,\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\nimport { FileUploadContext } from \"./context\";\nimport { MouseSensor } from \"./custom-sensors\";\nimport { FileItemEdit } from \"./file-item-edit\";\nimport { FileListItem } from \"./file-list-item\";\nimport { EditableItemsContainer, ListWrapper } from \"./file-list.styles\";\nimport { FileUploadHelper } from \"./helper\";\nimport { FileItemProps } from \"./types\";\nimport { FormLabelProps } from \"../form/types\";\nimport { VisuallyHidden } from \"../shared/accessibility\";\n\n// =============================================================================\n// INTERFACES\n// =============================================================================\ntype RenderMode = \"edit\" | \"display\" | \"error\";\n\ntype FileItemRenderModes = Record<string, RenderMode>;\ntype FileEditedDescriptions = Record<string, string>;\n\ntype RenderItem = FileItemProps | FileItemProps[];\n\ninterface Props {\n fileItems: FileItemProps[] | undefined;\n editableFileItems: boolean;\n fileDescriptionMaxLength?: number | undefined;\n descriptionRequired?: boolean | undefined;\n descriptionLabel?: FormLabelProps | undefined;\n sortable?: boolean | undefined;\n disabled?: boolean | undefined;\n readOnly?: boolean | undefined;\n onItemUpdate: (item: FileItemProps) => void;\n onItemDelete: (item: FileItemProps) => void;\n onSort?: ((reorderedFileItems: FileItemProps[]) => void) | undefined;\n}\n\ntype AnnouncementProgress = Record<\n string,\n {\n progress: number;\n timestamp: number;\n status: \"in-progress\" | \"complete\" | \"error\";\n }\n>;\n\nexport interface FileListRef {\n focus: () => void;\n}\n\n// =============================================================================\n// COMPONENT\n// =============================================================================\n\nfunction Component(\n {\n fileItems = [],\n editableFileItems,\n fileDescriptionMaxLength,\n descriptionRequired,\n descriptionLabel,\n sortable,\n disabled,\n readOnly,\n onItemUpdate,\n onItemDelete,\n onSort,\n }: Props,\n ref: React.Ref<FileListRef>\n) {\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const [renderModes, setRenderModes] = useState<FileItemRenderModes>({});\n const { setActiveId } = useContext(FileUploadContext);\n\n // Progress announcement state (for aria-live) - announces start and completion only\n const [progressAnnouncement, setProgressAnnouncement] = useState(\"\");\n const lastAnnouncedRef = useRef<AnnouncementProgress>({});\n\n useImperativeHandle(ref, () => ({\n focus: () => {\n wrapperRef.current?.focus();\n },\n }));\n const { width: wrapperWidth = 0, ref: wrapperRef } = useResizeDetector();\n\n // Keep track of edited description without re-rendering\n const descriptionsValueRef = useRef<FileEditedDescriptions>({});\n\n /**\n * As the default drag sensors interfere with click events\n * on the file items, we'll need to configure the sensor to\n * only activate the drag if the mouse moves a certain distance\n */\n const sensors = useSensors(\n useSensor(MouseSensor, {\n activationConstraint: {\n distance: 8, // mouse drag of 8px then activate the drag event\n },\n }),\n useSensor(TouchSensor, {\n activationConstraint: {\n delay: 150,\n tolerance: 5,\n },\n }),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n // =========================================================================\n // REF METHODS\n // =========================================================================\n const removeDescription = (itemId: string) => {\n delete descriptionsValueRef.current[itemId];\n };\n\n const shallowCompareRenderModes = (\n prev: FileItemRenderModes,\n next: FileItemRenderModes\n ) => {\n const prevKeys = Object.keys(prev);\n const nextKeys = Object.keys(next);\n if (prevKeys.length !== nextKeys.length) {\n return false;\n }\n for (const k of nextKeys) {\n if (prev[k] !== next[k]) {\n return false;\n }\n }\n return true;\n };\n\n // =========================================================================\n // EFFECTS\n // =========================================================================\n useEffect(() => {\n const nextModes = getItemsRenderMode(fileItems);\n const prevModes = renderModes;\n // We perform shallowCompare to avoid infinite re-render loop\n if (shallowCompareRenderModes(prevModes, nextModes)) {\n return;\n }\n setRenderModes(nextModes);\n }, [fileItems, editableFileItems, readOnly]);\n\n // Progress announcements only at start and completion\n useEffect(() => {\n if (!fileItems || fileItems.length === 0) {\n setProgressAnnouncement(\"\");\n return;\n }\n const now = Date.now();\n const messages: string[] = [];\n\n for (const item of fileItems) {\n const fileStatus = lastAnnouncedRef.current[item.id];\n\n if (item.errorMessage) {\n if (fileStatus?.status !== \"error\") {\n messages.push(\n typeof item.errorMessage === \"string\"\n ? `Error uploading ${item.name}: ${item.errorMessage}`\n : `Error uploading ${item.name}`\n );\n lastAnnouncedRef.current[item.id] = {\n progress: item.progress ?? 1,\n timestamp: now,\n status: \"error\",\n };\n }\n continue;\n }\n\n if (item.progress === undefined) {\n continue;\n }\n\n if (item.progress >= 1) {\n if (fileStatus?.status !== \"complete\") {\n messages.push(`${item.name} upload is complete`);\n lastAnnouncedRef.current[item.id] = {\n progress: 1,\n timestamp: now,\n status: \"complete\",\n };\n }\n continue;\n }\n\n // In progress - only announce start, not progress updates\n if (typeof item.progress === \"number\" && item.progress < 1) {\n // Only announce when starting upload (no previous status or status was not in-progress)\n const shouldAnnounce =\n !fileStatus || fileStatus.status !== \"in-progress\";\n\n if (shouldAnnounce) {\n messages.push(`Starting upload of ${item.name}`);\n lastAnnouncedRef.current[item.id] = {\n progress: item.progress,\n timestamp: now,\n status: \"in-progress\",\n };\n }\n }\n }\n\n if (messages.length > 0) {\n // Update aria-live region once with aggregated message\n setProgressAnnouncement(messages.join(\", \"));\n }\n }, [fileItems]);\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleSaveEdit = (item: FileItemProps) => (description: string) => {\n updateRenderModes(item.id, \"display\");\n removeDescription(item.id);\n\n const updatedItem = { ...item, description };\n onItemUpdate(updatedItem);\n };\n\n const handleBlurEdit = (item: FileItemProps) => (value: string) => {\n descriptionsValueRef.current[item.id] = value;\n };\n\n const handleCancel = (item: FileItemProps) => () => {\n if (!item.description || item.description.length === 0) {\n // New addition\n onItemDelete(item);\n } else {\n updateRenderModes(item.id, \"display\");\n }\n removeDescription(item.id);\n };\n\n const handleInitiateEdit = (item: FileItemProps) => () => {\n updateRenderModes(item.id, \"edit\");\n };\n\n const handleDelete = (item: FileItemProps) => () => {\n onItemDelete(item);\n if (wrapperRef.current) {\n wrapperRef.current.focus();\n }\n };\n\n const handleDragEnd = (event: DragEndEvent) => {\n if (onSort && fileItems) {\n const { active, over } = event;\n\n if (over && active.id !== over.id) {\n const oldIndex = fileItems.findIndex(\n (item) => item.id === active.id\n );\n const newIndex = fileItems.findIndex(\n (item) => item.id === over.id\n );\n\n const updatedFileItems = arrayMove(\n fileItems,\n oldIndex,\n newIndex\n );\n\n onSort(updatedFileItems);\n }\n }\n\n setActiveId(undefined);\n };\n\n const handleDragStart = (event: DragStartEvent) => {\n const { active } = event;\n setActiveId(active.id as string);\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const checkEditable = (item: FileItemProps) => {\n return (\n editableFileItems &&\n FileUploadHelper.isSupportedImageType(item.type)\n );\n };\n\n const shouldRenderEditMode = (item: FileItemProps) => {\n return (\n !item.errorMessage &&\n !readOnly &&\n !(typeof item.progress === \"number\" && item.progress < 1) &&\n checkEditable(item) &&\n !item.description\n );\n };\n\n const getItemsRenderMode = (\n fileItems: FileItemProps[] | undefined\n ): FileItemRenderModes => {\n if (!fileItems || fileItems.length === 0) return {};\n\n const newRenderModes: FileItemRenderModes = {};\n\n for (const item of fileItems) {\n if (item.errorMessage) {\n newRenderModes[item.id] = \"error\";\n } else if (!renderModes[item.id]) {\n newRenderModes[item.id] = shouldRenderEditMode(item)\n ? \"edit\"\n : \"display\";\n } else {\n newRenderModes[item.id] = renderModes[item.id];\n }\n }\n\n return newRenderModes;\n };\n\n const updateRenderModes = (itemId: string, mode: RenderMode) => {\n setRenderModes((prevRenderModes) => {\n return {\n ...prevRenderModes,\n [itemId]: mode,\n };\n });\n };\n\n /**\n * Due to a UI requirement, we will render the items\n * with edit modes as a group\n */\n const getArrangedItems = (\n fileItems: FileItemProps[] | undefined,\n renderModes: FileItemRenderModes\n ) => {\n if (!fileItems || fileItems.length === 0) return [];\n\n const arrangedItems: RenderItem[] = [];\n\n for (const fileItem of fileItems) {\n if (renderModes[fileItem.id] === \"edit\") {\n const previousElement = arrangedItems[arrangedItems.length - 1];\n if (Array.isArray(previousElement)) {\n previousElement.push(fileItem);\n } else {\n arrangedItems.push([fileItem]);\n }\n } else {\n arrangedItems.push(fileItem);\n }\n }\n\n return arrangedItems;\n };\n\n const areAllItemsInDisplayViews = () => {\n return Object.values(renderModes).every((mode) => mode === \"display\");\n };\n\n const shouldEnableSort = () => {\n return (\n fileItems &&\n fileItems.length > 1 &&\n sortable &&\n areAllItemsInDisplayViews()\n );\n };\n\n /**\n * If there are no files, return \"No files uploaded\".\n * If readOnly is true, return \"Read-only file list\".\n * If there are files, return a summary of the file statuses.\n * For example, \"File list. 2 completed files, 1 file in progress, 1 file with error\".\n *\n * @returns aria label\n */\n const getWrapperAriaLabel = () => {\n if (fileItems.length === 0) {\n return \"No files uploaded\";\n }\n const completedCount = fileItems.filter(\n (item) =>\n !item?.errorMessage &&\n (item.progress === 1 || item.progress === undefined)\n ).length;\n const inProgressCount = fileItems.filter(\n (item) => typeof item.progress === \"number\" && item.progress < 1\n ).length;\n const errorCount = fileItems.filter((item) => item.errorMessage).length;\n if (completedCount === 0 && inProgressCount === 0 && errorCount === 0) {\n return `File list`;\n }\n const completedText =\n completedCount > 0 ? `${completedCount} completed files` : \"\";\n const inProgressText =\n inProgressCount > 0 ? `${inProgressCount} file in progress` : \"\";\n const errorText =\n errorCount > 0\n ? `${errorCount} ${\n errorCount > 1 ? \"files\" : \"file\"\n } with error`\n : \"\";\n const parts = [completedText, inProgressText, errorText].filter(\n Boolean\n );\n const prefix = readOnly ? \"Read-only file list\" : \"File list\";\n return `${prefix}. ${parts.join(\", \")}`;\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderItemsInEditMode = (\n fileItems: FileItemProps[],\n keyToUse: number\n ) => {\n const itemsToRender = fileItems.map((item) => {\n const updatedFileItem = { ...item };\n if (descriptionsValueRef.current[item.id] !== undefined) {\n updatedFileItem.description =\n descriptionsValueRef.current[item.id];\n }\n\n return (\n <FileItemEdit\n key={item.id}\n fileItem={updatedFileItem}\n wrapperWidth={wrapperWidth}\n fileDescriptionMaxLength={fileDescriptionMaxLength}\n descriptionRequired={descriptionRequired}\n descriptionLabel={descriptionLabel}\n onSave={handleSaveEdit(item)}\n onCancel={handleCancel(item)}\n onBlur={handleBlurEdit(item)}\n />\n );\n });\n\n return (\n <EditableItemsContainer key={`editable-${keyToUse}`}>\n <ul>{itemsToRender}</ul>\n </EditableItemsContainer>\n );\n };\n\n const renderItems = () => {\n const arrangedItems = getArrangedItems(fileItems, renderModes);\n\n if (arrangedItems.length === 0) return null;\n\n return arrangedItems.map((item, index) => {\n if (Array.isArray(item)) {\n return renderItemsInEditMode(item, index);\n } else {\n return (\n <FileListItem\n key={item.id}\n fileItem={item}\n editable={checkEditable(item)}\n wrapperWidth={wrapperWidth}\n sortable={shouldEnableSort()}\n disabled={disabled}\n readOnly={readOnly}\n descriptionLabel={descriptionLabel}\n onDelete={handleDelete(item)}\n onEditClick={handleInitiateEdit(item)}\n />\n );\n }\n });\n };\n\n /**\n * Renders the progress status of each file upload.\n * In progress: 25% complete for uploading filename.pdf\n * Complete: filename.pdf upload is complete\n * Error: Error uploading filename.pdf: error message\n *\n * @returns A visually hidden element announcing the progress status.\n */\n const renderProgressStatus = () => (\n <VisuallyHidden aria-live=\"polite\" aria-atomic=\"true\">\n {progressAnnouncement}\n </VisuallyHidden>\n );\n\n const renderItemsWithWrapper = () => {\n return (\n <>\n {renderProgressStatus()}\n <ListWrapper\n tabIndex={-1}\n $readOnly={readOnly}\n ref={wrapperRef}\n aria-label={getWrapperAriaLabel()}\n >\n {renderItems()}\n </ListWrapper>\n </>\n );\n };\n\n if (disabled || readOnly || !shouldEnableSort()) {\n return renderItemsWithWrapper();\n } else {\n return (\n <DndContext\n sensors={sensors}\n onDragEnd={handleDragEnd}\n onDragStart={handleDragStart}\n >\n <SortableContext\n items={fileItems}\n strategy={verticalListSortingStrategy}\n >\n {renderItemsWithWrapper()}\n </SortableContext>\n </DndContext>\n );\n }\n}\n\nexport const FileList = forwardRef<FileListRef, Props>(Component);\n"],"names":["FileList","forwardRef","fileItems","editableFileItems","fileDescriptionMaxLength","descriptionRequired","descriptionLabel","sortable","disabled","readOnly","onItemUpdate","onItemDelete","onSort","ref","renderModes","setRenderModes","useState","setActiveId","useContext","FileUploadContext","progressAnnouncement","setProgressAnnouncement","lastAnnouncedRef","useRef","useImperativeHandle","focus","_a","wrapperRef","current","width","wrapperWidth","useResizeDetector","descriptionsValueRef","sensors","useSensors","useSensor","MouseSensor","activationConstraint","distance","TouchSensor","delay","tolerance","KeyboardSensor","coordinateGetter","sortableKeyboardCoordinates","removeDescription","itemId","useEffect","nextModes","getItemsRenderMode","prev","next","prevKeys","Object","keys","nextKeys","length","k","shallowCompareRenderModes","now","Date","messages","item","fileStatus","id","errorMessage","status","push","name","progress","timestamp","undefined","join","handleSaveEdit","description","updateRenderModes","updatedItem","assign","handleBlurEdit","value","handleCancel","handleInitiateEdit","handleDelete","handleDragEnd","event","active","over","oldIndex","findIndex","newIndex","updatedFileItems","arrayMove","handleDragStart","checkEditable","FileUploadHelper","isSupportedImageType","type","shouldRenderEditMode","newRenderModes","mode","prevRenderModes","shouldEnableSort","values","every","getWrapperAriaLabel","completedCount","filter","inProgressCount","errorCount","parts","Boolean","renderItems","arrangedItems","fileItem","previousElement","Array","isArray","getArrangedItems","map","index","keyToUse","itemsToRender","updatedFileItem","_jsx","FileItemEdit","onSave","onCancel","onBlur","EditableItemsContainer","children","renderItemsInEditMode","FileListItem","editable","onDelete","onEditClick","renderItemsWithWrapper","_jsxs","_Fragment","VisuallyHidden","ListWrapper","tabIndex","$readOnly","DndContext","onDragEnd","onDragStart","SortableContext","items","strategy","verticalListSortingStrategy"],"mappings":"+9BAqiBaA,EAAWC,GA1dxB,UACIC,UACIA,EAAY,GAAEC,kBACdA,EAAiBC,yBACjBA,EAAwBC,oBACxBA,EAAmBC,iBACnBA,EAAgBC,SAChBA,EAAQC,SACRA,EAAQC,SACRA,EAAQC,aACRA,EAAYC,aACZA,EAAYC,OACZA,GAEJC,GAKA,MAAOC,EAAaC,GAAkBC,EAA8B,CAAA,IAC9DC,YAAEA,GAAgBC,EAAWC,IAG5BC,EAAsBC,GAA2BL,EAAS,IAC3DM,EAAmBC,EAA6B,IAEtDC,EAAoBX,GAAK,KAAA,CACrBY,MAAO,WACe,QAAlBC,EAAAC,EAAWC,eAAO,IAAAF,GAAAA,EAAED,OAAO,MAGnC,MAAQI,MAAOC,EAAe,EAAGjB,IAAKc,GAAeI,IAG/CC,EAAuBT,EAA+B,IAOtDU,EAAUC,EACZC,EAAUC,EAAa,CACnBC,qBAAsB,CAClBC,SAAU,KAGlBH,EAAUI,EAAa,CACnBF,qBAAsB,CAClBG,MAAO,IACPC,UAAW,KAGnBN,EAAUO,EAAgB,CACtBC,iBAAkBC,KAOpBC,EAAqBC,WAChBd,EAAqBJ,QAAQkB,EAAO,EAuB/CC,GAAU,KACN,MAAMC,EAAYC,GAAmB/C,GArBP,EAC9BgD,EACAC,KAEA,MAAMC,EAAWC,OAAOC,KAAKJ,GACvBK,EAAWF,OAAOC,KAAKH,GAC7B,GAAIC,EAASI,SAAWD,EAASC,OAC7B,OAAO,EAEX,IAAK,MAAMC,KAAKF,EACZ,GAAIL,EAAKO,KAAON,EAAKM,GACjB,OAAO,EAGf,OAAO,CAAI,EAUPC,CAFc5C,EAEuBkC,IAGzCjC,EAAeiC,EAAU,GAC1B,CAAC9C,EAAWC,EAAmBM,IAGlCsC,GAAU,WACN,IAAK7C,GAAkC,IAArBA,EAAUsD,OAExB,YADAnC,EAAwB,IAG5B,MAAMsC,EAAMC,KAAKD,MACXE,EAAqB,GAE3B,IAAK,MAAMC,KAAQ5D,EAAW,CAC1B,MAAM6D,EAAazC,EAAiBM,QAAQkC,EAAKE,IAEjD,GAAIF,EAAKG,aACsB,WAAvBF,aAAU,EAAVA,EAAYG,UACZL,EAASM,KACwB,iBAAtBL,EAAKG,aACN,mBAAmBH,EAAKM,SAASN,EAAKG,eACtC,mBAAmBH,EAAKM,QAElC9C,EAAiBM,QAAQkC,EAAKE,IAAM,CAChCK,iBAAU3C,EAAAoC,EAAKO,wBAAY,EAC3BC,UAAWX,EACXO,OAAQ,eAMpB,QAAsBK,IAAlBT,EAAKO,SAIT,GAAIP,EAAKO,UAAY,EACU,cAAvBN,aAAU,EAAVA,EAAYG,UACZL,EAASM,KAAK,GAAGL,EAAKM,2BACtB9C,EAAiBM,QAAQkC,EAAKE,IAAM,CAChCK,SAAU,EACVC,UAAWX,EACXO,OAAQ,kBAOpB,GAA6B,iBAAlBJ,EAAKO,UAAyBP,EAAKO,SAAW,EAAG,GAGnDN,GAAoC,gBAAtBA,EAAWG,UAG1BL,EAASM,KAAK,sBAAsBL,EAAKM,QACzC9C,EAAiBM,QAAQkC,EAAKE,IAAM,CAChCK,SAAUP,EAAKO,SACfC,UAAWX,EACXO,OAAQ,eAGpB,CACJ,CAEIL,EAASL,OAAS,GAElBnC,EAAwBwC,EAASW,KAAK,MAC1C,GACD,CAACtE,IAKJ,MAAMuE,EAAkBX,GAAyBY,IAC7CC,GAAkBb,EAAKE,GAAI,WAC3BnB,EAAkBiB,EAAKE,IAEvB,MAAMY,EAAWvB,OAAAwB,OAAAxB,OAAAwB,OAAA,CAAA,EAAQf,GAAI,CAAEY,gBAC/BhE,EAAakE,EAAY,EAGvBE,EAAkBhB,GAAyBiB,IAC7C/C,EAAqBJ,QAAQkC,EAAKE,IAAMe,CAAK,EAG3CC,EAAgBlB,GAAwB,KACrCA,EAAKY,aAA2C,IAA5BZ,EAAKY,YAAYlB,OAItCmB,GAAkBb,EAAKE,GAAI,WAF3BrD,EAAamD,GAIjBjB,EAAkBiB,EAAKE,GAAG,EAGxBiB,EAAsBnB,GAAwB,KAChDa,GAAkBb,EAAKE,GAAI,OAAO,EAGhCkB,EAAgBpB,GAAwB,KAC1CnD,EAAamD,GACTnC,EAAWC,SACXD,EAAWC,QAAQH,OACvB,EAGE0D,GAAiBC,IACnB,GAAIxE,GAAUV,EAAW,CACrB,MAAMmF,OAAEA,EAAMC,KAAEA,GAASF,EAEzB,GAAIE,GAAQD,EAAOrB,KAAOsB,EAAKtB,GAAI,CAC/B,MAAMuB,EAAWrF,EAAUsF,WACtB1B,GAASA,EAAKE,KAAOqB,EAAOrB,KAE3ByB,EAAWvF,EAAUsF,WACtB1B,GAASA,EAAKE,KAAOsB,EAAKtB,KAGzB0B,EAAmBC,EACrBzF,EACAqF,EACAE,GAGJ7E,EAAO8E,EACX,CACJ,CAEAzE,OAAYsD,EAAU,EAGpBqB,GAAmBR,IACrB,MAAMC,OAAEA,GAAWD,EACnBnE,EAAYoE,EAAOrB,GAAa,EAM9B6B,GAAiB/B,GAEf3D,GACA2F,EAAiBC,qBAAqBjC,EAAKkC,MAI7CC,GAAwBnC,IAErBA,EAAKG,eACLxD,KAC0B,iBAAlBqD,EAAKO,UAAyBP,EAAKO,SAAW,IACvDwB,GAAc/B,KACbA,EAAKY,YAIRzB,GACF/C,IAEA,IAAKA,GAAkC,IAArBA,EAAUsD,OAAc,MAAO,CAAA,EAEjD,MAAM0C,EAAsC,CAAA,EAE5C,IAAK,MAAMpC,KAAQ5D,EACX4D,EAAKG,aACLiC,EAAepC,EAAKE,IAAM,QAClBlD,EAAYgD,EAAKE,IAKzBkC,EAAepC,EAAKE,IAAMlD,EAAYgD,EAAKE,IAJ3CkC,EAAepC,EAAKE,IAAMiC,GAAqBnC,GACzC,OACA,UAMd,OAAOoC,CAAc,EAGnBvB,GAAoB,CAAC7B,EAAgBqD,KACvCpF,GAAgBqF,GACZ/C,OAAAwB,OAAAxB,OAAAwB,OAAA,CAAA,EACOuB,GAAe,CAClBtD,CAACA,GAASqD,KAEhB,EAmCAE,GAAmB,IAEjBnG,GACAA,EAAUsD,OAAS,GACnBjD,GAPG8C,OAAOiD,OAAOxF,GAAayF,OAAOJ,GAAkB,YAATA,IAoBhDK,GAAsB,KACxB,GAAyB,IAArBtG,EAAUsD,OACV,MAAO,oBAEX,MAAMiD,EAAiBvG,EAAUwG,QAC5B5C,KACIA,eAAAA,EAAMG,gBACY,IAAlBH,EAAKO,eAAoCE,IAAlBT,EAAKO,YACnCb,OACImD,EAAkBzG,EAAUwG,QAC7B5C,GAAkC,iBAAlBA,EAAKO,UAAyBP,EAAKO,SAAW,IACjEb,OACIoD,EAAa1G,EAAUwG,QAAQ5C,GAASA,EAAKG,eAAcT,OACjE,GAAuB,IAAnBiD,GAA4C,IAApBE,GAAwC,IAAfC,EACjD,MAAO,YAEX,MAUMC,EAAQ,CATVJ,EAAiB,EAAI,GAAGA,oBAAmC,GAE3DE,EAAkB,EAAI,GAAGA,qBAAqC,GAE9DC,EAAa,EACP,GAAGA,KACCA,EAAa,EAAI,QAAU,oBAE/B,IAC+CF,OACrDI,SAGJ,MAAO,GADQrG,EAAW,sBAAwB,gBAC7BoG,EAAMrC,KAAK,OAAO,EAuCrCuC,GAAc,KAChB,MAAMC,EAnHe,EACrB9G,EACAY,KAEA,IAAKZ,GAAkC,IAArBA,EAAUsD,OAAc,MAAO,GAEjD,MAAMwD,EAA8B,GAEpC,IAAK,MAAMC,KAAY/G,EACnB,GAAiC,SAA7BY,EAAYmG,EAASjD,IAAgB,CACrC,MAAMkD,EAAkBF,EAAcA,EAAcxD,OAAS,GACzD2D,MAAMC,QAAQF,GACdA,EAAgB/C,KAAK8C,GAErBD,EAAc7C,KAAK,CAAC8C,GAE5B,MACID,EAAc7C,KAAK8C,GAI3B,OAAOD,CAAa,EA8FEK,CAAiBnH,EAAWY,GAElD,OAA6B,IAAzBkG,EAAcxD,OAAqB,KAEhCwD,EAAcM,KAAI,CAACxD,EAAMyD,IACxBJ,MAAMC,QAAQtD,GAvCI,EAC1B5D,EACAsH,KAEA,MAAMC,EAAgBvH,EAAUoH,KAAKxD,IACjC,MAAM4D,EAAerE,OAAAwB,OAAA,CAAA,EAAQf,GAM7B,YAL8CS,IAA1CvC,EAAqBJ,QAAQkC,EAAKE,MAClC0D,EAAgBhD,YACZ1C,EAAqBJ,QAAQkC,EAAKE,KAItC2D,EAACC,EAAY,CAETX,SAAUS,EACV5F,aAAcA,EACd1B,yBAA0BA,EAC1BC,oBAAqBA,EACrBC,iBAAkBA,EAClBuH,OAAQpD,EAAeX,GACvBgE,SAAU9C,EAAalB,GACvBiE,OAAQjD,EAAehB,IARlBA,EAAKE,GASZ,IAIV,OACI2D,EAACK,EAAsB,CAAAC,SACnBN,EAAA,KAAA,CAAAM,SAAKR,KADoB,YAAYD,IAEhB,EAWdU,CAAsBpE,EAAMyD,GAG/BI,EAACQ,EAAY,CAETlB,SAAUnD,EACVsE,SAAUvC,GAAc/B,GACxBhC,aAAcA,EACdvB,SAAU8F,KACV7F,SAAUA,EACVC,SAAUA,EACVH,iBAAkBA,EAClB+H,SAAUnD,EAAapB,GACvBwE,YAAarD,EAAmBnB,IAT3BA,EAAKE,KAaxB,EAiBAuE,GAAyB,IAEvBC,EAAAC,EAAA,CAAAR,SAAA,CAPJN,EAACe,EAAc,CAAA,YAAW,uBAAqB,OAAMT,SAChD7G,IAQGuG,EAACgB,EAAW,CACRC,UAAU,EAAEC,UACDpI,EACXI,IAAKc,EAAU,aACH6E,KAAqByB,SAEhClB,UAMjB,OAAIvG,GAAYC,IAAa4F,KAClBkC,KAGHZ,EAACmB,EAAU,CACP7G,QAASA,EACT8G,UAAW5D,GACX6D,YAAapD,GAAeqC,SAE5BN,EAACsB,EAAe,CACZC,MAAOhJ,EACPiJ,SAAUC,EAA2BnB,SAEpCM,QAKrB"}
@@ -1,20 +1,13 @@
1
- import t from"styled-components";import{Spacing as o,Border as i,Colour as r}from"../theme/index.js";const e=t.ul`
1
+ import t from"styled-components";import{Spacing as o}from"../theme/index.js";const n=t.ul`
2
2
  list-style-type: none;
3
3
  margin-bottom: ${t=>t.$readOnly?"0":o["spacing-32"]};
4
- `,n=t.li`
5
- border-top: ${i["width-010"]} ${i.solid} ${r.border};
6
- border-bottom: ${i["width-010"]} ${i.solid} ${r.border};
7
-
4
+ `,e=t.li`
8
5
  &:not(:last-child) {
9
- margin-bottom: ${o["spacing-32"]};
10
- }
11
-
12
- &:not(:first-child) {
13
- margin-top: ${o["spacing-32"]};
6
+ margin-bottom: ${o["spacing-16"]};
14
7
  }
15
8
 
16
9
  ul {
17
10
  list-style-type: none;
18
11
  }
19
- `;export{n as EditableItemsContainer,e as ListWrapper};
12
+ `;export{e as EditableItemsContainer,n as ListWrapper};
20
13
  //# sourceMappingURL=file-list.styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-list.styles.js","sources":["../../src/file-upload/file-list.styles.tsx"],"sourcesContent":["import styled from \"styled-components\";\nimport { Border, Colour, Spacing } from \"../theme\";\n\n// =============================================================================\n// STYLE INTERFACE\n// =============================================================================\ninterface ListWrapperStyleProps {\n $readOnly?: boolean | undefined;\n}\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const ListWrapper = styled.ul<ListWrapperStyleProps>`\n list-style-type: none;\n margin-bottom: ${(props) =>\n props.$readOnly ? \"0\" : Spacing[\"spacing-32\"]};\n`;\n\nexport const EditableItemsContainer = styled.li`\n border-top: ${Border[\"width-010\"]} ${Border.solid} ${Colour.border};\n border-bottom: ${Border[\"width-010\"]} ${Border.solid} ${Colour.border};\n\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-32\"]};\n }\n\n &:not(:first-child) {\n margin-top: ${Spacing[\"spacing-32\"]};\n }\n\n ul {\n list-style-type: none;\n }\n`;\n"],"names":["ListWrapper","styled","ul","props","$readOnly","Spacing","EditableItemsContainer","li","Border","solid","Colour","border"],"mappings":"qGAaO,MAAMA,EAAcC,EAAOC,EAAyB;;qBAErCC,GACdA,EAAMC,UAAY,IAAMC,EAAQ;EAG3BC,EAAyBL,EAAOM,EAAE;kBAC7BC,EAAO,gBAAgBA,EAAOC,SAASC,EAAOC;qBAC3CH,EAAO,gBAAgBA,EAAOC,SAASC,EAAOC;;;yBAG1CN,EAAQ;;;;sBAIXA,EAAQ;;;;;;"}
1
+ {"version":3,"file":"file-list.styles.js","sources":["../../src/file-upload/file-list.styles.tsx"],"sourcesContent":["import styled from \"styled-components\";\nimport { Spacing } from \"../theme\";\n\n// =============================================================================\n// STYLE INTERFACE\n// =============================================================================\ninterface ListWrapperStyleProps {\n $readOnly?: boolean | undefined;\n}\n\n// =============================================================================\n// STYLING\n// =============================================================================\nexport const ListWrapper = styled.ul<ListWrapperStyleProps>`\n list-style-type: none;\n margin-bottom: ${(props) =>\n props.$readOnly ? \"0\" : Spacing[\"spacing-32\"]};\n`;\n\nexport const EditableItemsContainer = styled.li`\n &:not(:last-child) {\n margin-bottom: ${Spacing[\"spacing-16\"]};\n }\n\n ul {\n list-style-type: none;\n }\n`;\n"],"names":["ListWrapper","styled","ul","props","$readOnly","Spacing","EditableItemsContainer","li"],"mappings":"6EAaO,MAAMA,EAAcC,EAAOC,EAAyB;;qBAErCC,GACdA,EAAMC,UAAY,IAAMC,EAAQ;EAG3BC,EAAyBL,EAAOM,EAAE;;yBAEtBF,EAAQ;;;;;;"}
@@ -1,2 +1,2 @@
1
1
  import { FileUploadProps } from "./types";
2
- export declare const FileUpload: ({ styleType, fileItems, title, description, maxFiles, warning, className, name, id, "data-testid": testId, accept, capture, multiple, disabled, sortable, fileDescriptionMaxLength, editableFileItems, errorMessage, readOnly, customLabels, onChange, onDelete, onEdit, onSort, }: FileUploadProps) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const FileUpload: ({ styleType, fileItems, title, description, maxFiles, warning, className, name, id, "data-testid": testId, accept, capture, multiple, disabled, sortable, fileDescriptionMaxLength, editableFileItems, descriptionRequired, descriptionLabel, errorMessage, readOnly, customLabels, onChange, onDelete, onEdit, onSort, }: FileUploadProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,2 +1,2 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useRef as r,useState as l}from"react";import{FileUploadContext as o}from"./context.js";import{FileUploadDropzone as i}from"./dropzone.js";import{FileList as n}from"./file-list.js";import{TextContainer as d,WarningAlert as a,ErrorAlert as s,UploadButtonContainer as c,UploadButton as p,UploadButtonText as u,Title as m,TitleContainer as f,Description as h,DescriptionContainer as b}from"./file-upload.styles.js";const y=({styleType:y="bordered",fileItems:g,title:v,description:I,maxFiles:x,warning:D,className:j,name:F,id:L,"data-testid":w,accept:z,capture:B,multiple:C,disabled:M,sortable:N=!1,fileDescriptionMaxLength:O,editableFileItems:S=!1,errorMessage:T,readOnly:U,customLabels:k,onChange:A,onDelete:E,onEdit:P,onSort:$})=>{const q={uploadButton:(null==k?void 0:k.uploadButtonLabel)||"Upload files"},G=r(null),H=r(null),[J,K]=l(),Q=()=>!(!x||!g)&&g.length>=x;return e(o.Provider,{value:{activeId:J,setActiveId:K},children:t(i,{ref:G,onChange:e=>{var t;!M&&A&&(A(e),null===(t=H.current)||void 0===t||t.focus())},id:L?`${L}-dropzone`:"dropzone",accept:z,capture:B,border:"bordered"===y,className:j,"data-testid":w,name:F,multiple:C,disabled:M||Q()||U,children:[!(!v&&!I)&&t(d,{children:[v?e("string"==typeof v?m:f,{children:v}):null,I?e("string"==typeof I?h:b,{children:I}):null]}),!!D&&e(a,{type:"warning",children:D}),e(n,{ref:H,fileItems:g,editableFileItems:S,fileDescriptionMaxLength:O,sortable:N,disabled:M,readOnly:U,onItemDelete:e=>{var t;E&&(E(e),null===(t=H.current)||void 0===t||t.focus())},onItemUpdate:e=>{P&&P(e)},onSort:e=>{$&&$(e)}}),T&&e(s,{type:"error",children:T}),!U&&t(c,{children:[e(p,{type:"button",styleType:"secondary",disabled:!!J||M||Q(),onClick:e=>{M||(e.preventDefault(),G.current&&G.current.openFileDialog())},children:q.uploadButton}),e(u,{weight:"semibold",children:"or drop them here"})]})]})})};export{y as FileUpload};
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import{useRef as r,useState as i}from"react";import{FileUploadContext as l}from"./context.js";import{FileUploadDropzone as o}from"./dropzone.js";import{FileList as n}from"./file-list.js";import{TextContainer as d,WarningAlert as a,ErrorAlert as s,UploadButtonContainer as c,UploadButton as p,UploadButtonText as u,Title as m,TitleContainer as f,Description as h,DescriptionContainer as b}from"./file-upload.styles.js";const y=({styleType:y="bordered",fileItems:g,title:v,description:I,maxFiles:x,warning:D,className:L,name:j,id:F,"data-testid":w,accept:z,capture:B,multiple:C,disabled:M,sortable:q=!1,fileDescriptionMaxLength:N,editableFileItems:O=!1,descriptionRequired:R=!0,descriptionLabel:S,errorMessage:T,readOnly:U,customLabels:k,onChange:A,onDelete:E,onEdit:P,onSort:$})=>{const G={uploadButton:(null==k?void 0:k.uploadButtonLabel)||"Upload files"},H=r(null),J=r(null),[K,Q]=i(),V=()=>!(!x||!g)&&g.length>=x;return e(l.Provider,{value:{activeId:K,setActiveId:Q},children:t(o,{ref:H,onChange:e=>{var t;!M&&A&&(A(e),null===(t=J.current)||void 0===t||t.focus())},id:F?`${F}-dropzone`:"dropzone",accept:z,capture:B,border:"bordered"===y,className:L,"data-testid":w,name:j,multiple:C,disabled:M||V()||U,children:[!(!v&&!I)&&t(d,{children:[v?e("string"==typeof v?m:f,{children:v}):null,I?e("string"==typeof I?h:b,{children:I}):null]}),!!D&&e(a,{type:"warning",children:D}),e(n,{ref:J,fileItems:g,editableFileItems:O,descriptionRequired:R,descriptionLabel:S,fileDescriptionMaxLength:N,sortable:q,disabled:M,readOnly:U,onItemDelete:e=>{var t;E&&(E(e),null===(t=J.current)||void 0===t||t.focus())},onItemUpdate:e=>{P&&P(e)},onSort:e=>{$&&$(e)}}),T&&e(s,{type:"error",children:T}),!U&&t(c,{children:[e(p,{type:"button",styleType:"secondary",disabled:!!K||M||V(),onClick:e=>{M||(e.preventDefault(),H.current&&H.current.openFileDialog())},children:G.uploadButton}),e(u,{weight:"semibold",children:"or drop them here"})]})]})})};export{y as FileUpload};
2
2
  //# sourceMappingURL=file-upload.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-upload.js","sources":["../../src/file-upload/file-upload.tsx"],"sourcesContent":["import { useRef, useState } from \"react\";\nimport { FileUploadContext } from \"./context\";\nimport { DropzoneElement, FileUploadDropzone } from \"./dropzone\";\nimport { FileList, FileListRef } from \"./file-list\";\nimport {\n Description,\n DescriptionContainer,\n ErrorAlert,\n TextContainer,\n Title,\n TitleContainer,\n UploadButton,\n UploadButtonContainer,\n UploadButtonText,\n WarningAlert,\n} from \"./file-upload.styles\";\nimport { FileItemProps, FileUploadProps } from \"./types\";\n\nexport const FileUpload = ({\n styleType = \"bordered\",\n fileItems,\n title,\n description,\n maxFiles,\n warning,\n className,\n name,\n id,\n \"data-testid\": testId,\n accept,\n capture,\n multiple,\n disabled,\n sortable = false,\n fileDescriptionMaxLength,\n editableFileItems = false,\n errorMessage,\n readOnly,\n customLabels,\n onChange,\n onDelete,\n onEdit,\n onSort,\n}: FileUploadProps) => {\n const labels = {\n uploadButton: customLabels?.uploadButtonLabel || \"Upload files\",\n };\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const dropzoneRef = useRef<DropzoneElement>(null);\n const fileListRef = useRef<FileListRef>(null);\n const [activeId, setActiveId] = useState<string>();\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleChange = (files: File[]) => {\n if (!disabled && onChange) {\n onChange(files);\n fileListRef.current?.focus();\n }\n };\n\n const handleItemDelete = (item: FileItemProps) => {\n if (onDelete) {\n onDelete(item);\n fileListRef.current?.focus();\n }\n };\n\n const handleUploadButtonClick = (\n event: React.MouseEvent<HTMLButtonElement>\n ) => {\n if (!disabled) {\n event.preventDefault();\n if (dropzoneRef.current) {\n dropzoneRef.current.openFileDialog();\n }\n }\n };\n\n const handleItemUpdate = (updatedItem: FileItemProps) => {\n if (onEdit) {\n onEdit(updatedItem);\n }\n };\n\n const handleSort = (updatedItems: FileItemProps[]) => {\n if (onSort) {\n onSort(updatedItems);\n }\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const reachedMaxFiles = () => {\n return maxFiles && fileItems ? fileItems.length >= maxFiles : false;\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderTitle = () => {\n if (!title) {\n return null;\n }\n\n if (typeof title === \"string\") {\n return <Title>{title}</Title>;\n }\n\n return <TitleContainer>{title}</TitleContainer>;\n };\n\n const renderDescription = () => {\n if (!description) {\n return null;\n }\n\n if (typeof description === \"string\") {\n return <Description>{description}</Description>;\n }\n\n return <DescriptionContainer>{description}</DescriptionContainer>;\n };\n\n return (\n <FileUploadContext.Provider value={{ activeId, setActiveId }}>\n <FileUploadDropzone\n ref={dropzoneRef}\n onChange={handleChange}\n id={id ? `${id}-dropzone` : \"dropzone\"}\n accept={accept}\n capture={capture}\n border={styleType === \"bordered\"}\n className={className}\n data-testid={testId}\n name={name}\n multiple={multiple}\n disabled={disabled || reachedMaxFiles() || readOnly}\n >\n {!!(title || description) && (\n <TextContainer>\n {renderTitle()}\n {renderDescription()}\n </TextContainer>\n )}\n {!!warning && (\n <WarningAlert type=\"warning\">{warning}</WarningAlert>\n )}\n <FileList\n ref={fileListRef}\n fileItems={fileItems}\n editableFileItems={editableFileItems}\n fileDescriptionMaxLength={fileDescriptionMaxLength}\n sortable={sortable}\n disabled={disabled}\n readOnly={readOnly}\n onItemDelete={handleItemDelete}\n onItemUpdate={handleItemUpdate}\n onSort={handleSort}\n />\n {errorMessage && (\n <ErrorAlert type=\"error\">{errorMessage}</ErrorAlert>\n )}\n {!readOnly && (\n <UploadButtonContainer>\n <UploadButton\n type=\"button\"\n styleType=\"secondary\"\n disabled={\n !!activeId || disabled || reachedMaxFiles()\n }\n onClick={handleUploadButtonClick}\n >\n {labels.uploadButton}\n </UploadButton>\n <UploadButtonText weight=\"semibold\">\n or drop them here\n </UploadButtonText>\n </UploadButtonContainer>\n )}\n </FileUploadDropzone>\n </FileUploadContext.Provider>\n );\n};\n"],"names":["FileUpload","styleType","fileItems","title","description","maxFiles","warning","className","name","id","testId","accept","capture","multiple","disabled","sortable","fileDescriptionMaxLength","editableFileItems","errorMessage","readOnly","customLabels","onChange","onDelete","onEdit","onSort","labels","uploadButton","uploadButtonLabel","dropzoneRef","useRef","fileListRef","activeId","setActiveId","useState","reachedMaxFiles","length","_jsx","FileUploadContext","Provider","value","children","_jsxs","FileUploadDropzone","ref","files","_a","current","focus","border","TextContainer","Title","TitleContainer","Description","DescriptionContainer","WarningAlert","type","FileList","onItemDelete","item","onItemUpdate","updatedItem","updatedItems","ErrorAlert","UploadButtonContainer","UploadButton","onClick","event","preventDefault","openFileDialog","UploadButtonText","weight"],"mappings":"odAkBO,MAAMA,EAAa,EACtBC,YAAY,WACZC,YACAC,QACAC,cACAC,WACAC,UACAC,YACAC,OACAC,KACA,cAAeC,EACfC,SACAC,UACAC,WACAC,WACAC,YAAW,EACXC,2BACAC,qBAAoB,EACpBC,eACAC,WACAC,eACAC,WACAC,WACAC,SACAC,aAEA,MAAMC,EAAS,CACXC,cAAcN,eAAAA,EAAcO,oBAAqB,gBAK/CC,EAAcC,EAAwB,MACtCC,EAAcD,EAAoB,OACjCE,EAAUC,GAAeC,IA6C1BC,EAAkB,OACb7B,IAAYH,IAAYA,EAAUiC,QAAU9B,EA8BvD,OACI+B,EAACC,EAAkBC,UAASC,MAAO,CAAER,WAAUC,eAAaQ,SACxDC,EAACC,EAAkB,CACfC,IAAKf,EACLP,SA3EUuB,WACb9B,GAAYO,IACbA,EAASuB,GACU,QAAnBC,EAAAf,EAAYgB,eAAO,IAAAD,GAAAA,EAAEE,QACzB,EAwEQtC,GAAIA,EAAK,GAAGA,aAAgB,WAC5BE,OAAQA,EACRC,QAASA,EACToC,OAAsB,aAAd/C,EACRM,UAAWA,EAAS,cACPG,EACbF,KAAMA,EACNK,SAAUA,EACVC,SAAUA,GAAYoB,KAAqBf,eAEvChB,IAASC,IACTqC,EAACQ,EAAa,CAAAT,SAAA,CAvCrBrC,EAKMiC,EADU,iBAAVjC,EACC+C,EAGJC,EAHS,CAAAX,SAAErC,IAJR,KAWNC,EAKMgC,EADgB,iBAAhBhC,EACCgD,EAGJC,EAHe,CAAAb,SAAEpC,IAJd,UA+BAE,GACC8B,EAACkB,GAAaC,KAAK,UAASf,SAAElC,IAElC8B,EAACoB,EAAQ,CACLb,IAAKb,EACL5B,UAAWA,EACXe,kBAAmBA,EACnBD,yBAA0BA,EAC1BD,SAAUA,EACVD,SAAUA,EACVK,SAAUA,EACVsC,aAhGUC,UAClBpC,IACAA,EAASoC,GACU,QAAnBb,EAAAf,EAAYgB,eAAO,IAAAD,GAAAA,EAAEE,QACzB,EA6FYY,aA/EUC,IAClBrC,GACAA,EAAOqC,EACX,EA6EYpC,OA1EIqC,IACZrC,GACAA,EAAOqC,EACX,IAyES3C,GACGkB,EAAC0B,EAAU,CAACP,KAAK,QAAOf,SAAEtB,KAE5BC,GACEsB,EAACsB,EAAqB,CAAAvB,SAAA,CAClBJ,EAAC4B,EAAY,CACTT,KAAK,SACLtD,UAAU,YACVa,WACMiB,GAAYjB,GAAYoB,IAE9B+B,QAvGpBC,IAEKpD,IACDoD,EAAMC,iBACFvC,EAAYkB,SACZlB,EAAYkB,QAAQsB,iBAE5B,EAgGoD5B,SAE/Bf,EAAOC,eAEZU,EAACiC,EAAgB,CAACC,OAAO,WAAU9B,SAAA,6BAMtB"}
1
+ {"version":3,"file":"file-upload.js","sources":["../../src/file-upload/file-upload.tsx"],"sourcesContent":["import { useRef, useState } from \"react\";\nimport { FileUploadContext } from \"./context\";\nimport { DropzoneElement, FileUploadDropzone } from \"./dropzone\";\nimport { FileList, FileListRef } from \"./file-list\";\nimport {\n Description,\n DescriptionContainer,\n ErrorAlert,\n TextContainer,\n Title,\n TitleContainer,\n UploadButton,\n UploadButtonContainer,\n UploadButtonText,\n WarningAlert,\n} from \"./file-upload.styles\";\nimport { FileItemProps, FileUploadProps } from \"./types\";\n\nexport const FileUpload = ({\n styleType = \"bordered\",\n fileItems,\n title,\n description,\n maxFiles,\n warning,\n className,\n name,\n id,\n \"data-testid\": testId,\n accept,\n capture,\n multiple,\n disabled,\n sortable = false,\n fileDescriptionMaxLength,\n editableFileItems = false,\n descriptionRequired = true,\n descriptionLabel,\n errorMessage,\n readOnly,\n customLabels,\n onChange,\n onDelete,\n onEdit,\n onSort,\n}: FileUploadProps) => {\n const labels = {\n uploadButton: customLabels?.uploadButtonLabel || \"Upload files\",\n };\n // =========================================================================\n // CONST, STATE, REFS\n // =========================================================================\n const dropzoneRef = useRef<DropzoneElement>(null);\n const fileListRef = useRef<FileListRef>(null);\n const [activeId, setActiveId] = useState<string>();\n\n // =========================================================================\n // EVENT HANDLERS\n // =========================================================================\n const handleChange = (files: File[]) => {\n if (!disabled && onChange) {\n onChange(files);\n fileListRef.current?.focus();\n }\n };\n\n const handleItemDelete = (item: FileItemProps) => {\n if (onDelete) {\n onDelete(item);\n fileListRef.current?.focus();\n }\n };\n\n const handleUploadButtonClick = (\n event: React.MouseEvent<HTMLButtonElement>\n ) => {\n if (!disabled) {\n event.preventDefault();\n if (dropzoneRef.current) {\n dropzoneRef.current.openFileDialog();\n }\n }\n };\n\n const handleItemUpdate = (updatedItem: FileItemProps) => {\n if (onEdit) {\n onEdit(updatedItem);\n }\n };\n\n const handleSort = (updatedItems: FileItemProps[]) => {\n if (onSort) {\n onSort(updatedItems);\n }\n };\n\n // =========================================================================\n // HELPER FUNCTIONS\n // =========================================================================\n const reachedMaxFiles = () => {\n return maxFiles && fileItems ? fileItems.length >= maxFiles : false;\n };\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const renderTitle = () => {\n if (!title) {\n return null;\n }\n\n if (typeof title === \"string\") {\n return <Title>{title}</Title>;\n }\n\n return <TitleContainer>{title}</TitleContainer>;\n };\n\n const renderDescription = () => {\n if (!description) {\n return null;\n }\n\n if (typeof description === \"string\") {\n return <Description>{description}</Description>;\n }\n\n return <DescriptionContainer>{description}</DescriptionContainer>;\n };\n\n return (\n <FileUploadContext.Provider value={{ activeId, setActiveId }}>\n <FileUploadDropzone\n ref={dropzoneRef}\n onChange={handleChange}\n id={id ? `${id}-dropzone` : \"dropzone\"}\n accept={accept}\n capture={capture}\n border={styleType === \"bordered\"}\n className={className}\n data-testid={testId}\n name={name}\n multiple={multiple}\n disabled={disabled || reachedMaxFiles() || readOnly}\n >\n {!!(title || description) && (\n <TextContainer>\n {renderTitle()}\n {renderDescription()}\n </TextContainer>\n )}\n {!!warning && (\n <WarningAlert type=\"warning\">{warning}</WarningAlert>\n )}\n <FileList\n ref={fileListRef}\n fileItems={fileItems}\n editableFileItems={editableFileItems}\n descriptionRequired={descriptionRequired}\n descriptionLabel={descriptionLabel}\n fileDescriptionMaxLength={fileDescriptionMaxLength}\n sortable={sortable}\n disabled={disabled}\n readOnly={readOnly}\n onItemDelete={handleItemDelete}\n onItemUpdate={handleItemUpdate}\n onSort={handleSort}\n />\n {errorMessage && (\n <ErrorAlert type=\"error\">{errorMessage}</ErrorAlert>\n )}\n {!readOnly && (\n <UploadButtonContainer>\n <UploadButton\n type=\"button\"\n styleType=\"secondary\"\n disabled={\n !!activeId || disabled || reachedMaxFiles()\n }\n onClick={handleUploadButtonClick}\n >\n {labels.uploadButton}\n </UploadButton>\n <UploadButtonText weight=\"semibold\">\n or drop them here\n </UploadButtonText>\n </UploadButtonContainer>\n )}\n </FileUploadDropzone>\n </FileUploadContext.Provider>\n );\n};\n"],"names":["FileUpload","styleType","fileItems","title","description","maxFiles","warning","className","name","id","testId","accept","capture","multiple","disabled","sortable","fileDescriptionMaxLength","editableFileItems","descriptionRequired","descriptionLabel","errorMessage","readOnly","customLabels","onChange","onDelete","onEdit","onSort","labels","uploadButton","uploadButtonLabel","dropzoneRef","useRef","fileListRef","activeId","setActiveId","useState","reachedMaxFiles","length","_jsx","FileUploadContext","Provider","value","children","_jsxs","FileUploadDropzone","ref","files","_a","current","focus","border","TextContainer","Title","TitleContainer","Description","DescriptionContainer","WarningAlert","type","FileList","onItemDelete","item","onItemUpdate","updatedItem","updatedItems","ErrorAlert","UploadButtonContainer","UploadButton","onClick","event","preventDefault","openFileDialog","UploadButtonText","weight"],"mappings":"odAkBO,MAAMA,EAAa,EACtBC,YAAY,WACZC,YACAC,QACAC,cACAC,WACAC,UACAC,YACAC,OACAC,KACA,cAAeC,EACfC,SACAC,UACAC,WACAC,WACAC,YAAW,EACXC,2BACAC,qBAAoB,EACpBC,uBAAsB,EACtBC,mBACAC,eACAC,WACAC,eACAC,WACAC,WACAC,SACAC,aAEA,MAAMC,EAAS,CACXC,cAAcN,eAAAA,EAAcO,oBAAqB,gBAK/CC,EAAcC,EAAwB,MACtCC,EAAcD,EAAoB,OACjCE,EAAUC,GAAeC,IA6C1BC,EAAkB,OACb/B,IAAYH,IAAYA,EAAUmC,QAAUhC,EA8BvD,OACIiC,EAACC,EAAkBC,UAASC,MAAO,CAAER,WAAUC,eAAaQ,SACxDC,EAACC,EAAkB,CACfC,IAAKf,EACLP,SA3EUuB,WACbhC,GAAYS,IACbA,EAASuB,GACU,QAAnBC,EAAAf,EAAYgB,eAAO,IAAAD,GAAAA,EAAEE,QACzB,EAwEQxC,GAAIA,EAAK,GAAGA,aAAgB,WAC5BE,OAAQA,EACRC,QAASA,EACTsC,OAAsB,aAAdjD,EACRM,UAAWA,gBACEG,EACbF,KAAMA,EACNK,SAAUA,EACVC,SAAUA,GAAYsB,KAAqBf,EAAQqB,SAAA,IAE/CvC,IAASC,IACTuC,EAACQ,EAAa,CAAAT,SAAA,CAvCrBvC,EAKMmC,EADU,iBAAVnC,EACCiD,EAGJC,EAHS,CAAAX,SAAEvC,IAJR,KAWNC,EAKMkC,EADgB,iBAAhBlC,EACCkD,EAGJC,EAHe,CAAAb,SAAEtC,IAJd,UA+BAE,GACCgC,EAACkB,EAAY,CAACC,KAAK,UAASf,SAAEpC,IAElCgC,EAACoB,GACGb,IAAKb,EACL9B,UAAWA,EACXe,kBAAmBA,EACnBC,oBAAqBA,EACrBC,iBAAkBA,EAClBH,yBAA0BA,EAC1BD,SAAUA,EACVD,SAAUA,EACVO,SAAUA,EACVsC,aAlGUC,UAClBpC,IACAA,EAASoC,GACU,QAAnBb,EAAAf,EAAYgB,eAAO,IAAAD,GAAAA,EAAEE,QACzB,EA+FYY,aAjFUC,IAClBrC,GACAA,EAAOqC,EACX,EA+EYpC,OA5EIqC,IACZrC,GACAA,EAAOqC,EACX,IA2ES3C,GACGkB,EAAC0B,EAAU,CAACP,KAAK,QAAOf,SAAEtB,KAE5BC,GACEsB,EAACsB,EAAqB,CAAAvB,SAAA,CAClBJ,EAAC4B,EAAY,CACTT,KAAK,SACLxD,UAAU,YACVa,WACMmB,GAAYnB,GAAYsB,IAE9B+B,QAzGpBC,IAEKtD,IACDsD,EAAMC,iBACFvC,EAAYkB,SACZlB,EAAYkB,QAAQsB,iBAE5B,EAkGoD5B,SAE/Bf,EAAOC,eAEZU,EAACiC,EAAgB,CAACC,OAAO,WAAU9B,SAAA,6BAMtB"}
@@ -1,3 +1,4 @@
1
+ import { FormLabelProps } from "../form/types";
1
2
  export interface FileItemProps {
2
3
  id: string;
3
4
  /** The name of the file */
@@ -44,6 +45,10 @@ export interface FileUploadProps extends FileInputProps {
44
45
  editableFileItems?: boolean | undefined;
45
46
  /** The max length of the description of the file (only image files) */
46
47
  fileDescriptionMaxLength?: number | undefined;
48
+ /** When false, save button is enabled even with empty description. Default: true */
49
+ descriptionRequired?: boolean | undefined;
50
+ /** Overrides default label and subtext for description field */
51
+ descriptionLabel?: FormLabelProps | undefined;
47
52
  /** Specifies if sorting is enabled for the file items */
48
53
  sortable?: boolean | undefined;
49
54
  /** The general error message for the component */
@@ -1,2 +1,2 @@
1
- import e from"../external/dayjs/dayjs.min.js";import{getDefaultDisclaimerLinks as t}from"./footer-disclaimer-links-data.js";var r;!function(r){r.getCopyrightInfo=(t=new Date,r)=>{const i=s(r);return`${`${(new Date).getFullYear()} ${i}`} Last updated ${e(t).format("D MMMM YYYY")}`};const s=e=>{switch(e){case"lifesg":return"LifeSG, Government of Singapore.";case"bookingsg":return"BookingSG, Government of Singapore.";case"mylegacy":return"MyLegacy@LifeSG, Government of Singapore.";case"ccube":return"Citizen Collective Common, Government of Singapore.";case"imda":return"IMDA, Government of Singapore.";default:return"Government of Singapore."}};r.getFooterLogoAttribute=e=>{switch(e){case"lifesg":return{src:"https://assets.life.gov.sg/react-design-system/img/logo/lifesg-primary-logo.svg",alt:"LifeSG",style:{width:"4rem"}};case"bookingsg":return{src:"https://home.booking.gov.sg/images/bookingsg/footer.svg",alt:"BookingSG",style:{width:"4rem"}};case"mylegacy":return{src:"https://mylegacy.life.gov.sg/images/site-logo.png",alt:"MyLegacy",style:{width:"10rem",maxHeight:"2rem"}};case"ccube":return{src:"https://assets.life.gov.sg/ccube/logo-ccube.svg",alt:"Citizen Collective Common",style:{width:"10rem"}};case"supportgowhere":return{src:"https://assets.life.gov.sg/react-design-system/img/logo/sgw-logo.png",alt:"SupportGoWhere",style:{width:"10rem"}};default:return{}}},r.getDisclaimerLinks=(e,r)=>{const s=t(e);return{privacy:Object.assign(Object.assign(Object.assign({},s.privacy),r&&r.privacy?r.privacy:{}),{children:"Privacy Statement"}),termsOfUse:Object.assign(Object.assign(Object.assign({},s.termsOfUse),r&&r.termsOfUse?r.termsOfUse:{}),{children:"Terms of Use"}),reportVulnerability:Object.assign(Object.assign(Object.assign({},s.reportVulnerability),r&&r.reportVulnerability?r.reportVulnerability:{}),{children:"Report Vulnerability"})}}}(r||(r={}));export{r as FooterHelper};
1
+ import e from"../external/dayjs/dayjs.min.js";import{getDefaultDisclaimerLinks as t}from"./footer-disclaimer-links-data.js";var s;!function(s){s.getCopyrightInfo=(t=new Date,s)=>{const o=r(s);return`${`${(new Date).getFullYear()} ${o}`} Last updated ${e(t).format("D MMMM YYYY")}`};const r=e=>{switch(e){case"lifesg":return"LifeSG, Government of Singapore.";case"bookingsg":return"BookingSG, Government of Singapore.";case"mylegacy":return"MyLegacy@LifeSG, Government of Singapore.";case"ccube":return"Citizen Collective Common, Government of Singapore.";case"imda":return"IMDA, Government of Singapore.";default:return"Government of Singapore."}};s.getFooterLogoAttribute=e=>{switch(e){case"lifesg":return{src:"https://assets.life.gov.sg/react-design-system/img/logo/lifesg-primary-logo.svg",alt:"LifeSG",style:{width:"4rem"}};case"bookingsg":return{src:"https://home.booking.gov.sg/images/bookingsg/footer.svg",alt:"BookingSG",style:{width:"4rem"}};case"mylegacy":return{src:"https://mylegacy.life.gov.sg/images/site-logo.png",alt:"MyLegacy",style:{width:"10rem",maxHeight:"2rem"}};case"ccube":return{src:"https://assets.life.gov.sg/ccube/logo-ccube.svg",alt:"Citizen Collective Common",style:{width:"10rem"}};case"supportgowhere":return{src:"https://assets.life.gov.sg/react-design-system/img/logo/sgw-logo.png",alt:"SupportGoWhere",style:{width:"10rem"}};case"toteboard":return{src:"https://assets.life.gov.sg/react-design-system/img/logo/tote-board-logo.svg",alt:"Tote Board",style:{width:"4rem"}};default:return{}}},s.getDisclaimerLinks=(e,s)=>{const r=t(e);return{privacy:Object.assign(Object.assign(Object.assign({},r.privacy),s&&s.privacy?s.privacy:{}),{children:"Privacy Statement"}),termsOfUse:Object.assign(Object.assign(Object.assign({},r.termsOfUse),s&&s.termsOfUse?s.termsOfUse:{}),{children:"Terms of Use"}),reportVulnerability:Object.assign(Object.assign(Object.assign({},r.reportVulnerability),s&&s.reportVulnerability?s.reportVulnerability:{}),{children:"Report Vulnerability"})}}}(s||(s={}));export{s as FooterHelper};
2
2
  //# sourceMappingURL=footer-helper.js.map