@nocios/crudify-components 2.0.36 → 2.0.38

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 (134) hide show
  1. package/coverage/components/CrudiaAutoGenerate.tsx.html +583 -0
  2. package/coverage/components/CrudiaFileField/CrudiaFileField.tsx.html +1276 -0
  3. package/coverage/components/CrudiaFileField/components/DeleteConfirmationDialog.tsx.html +355 -0
  4. package/coverage/components/CrudiaFileField/components/DropZone.tsx.html +433 -0
  5. package/coverage/components/CrudiaFileField/components/FileItemRow.tsx.html +751 -0
  6. package/coverage/components/CrudiaFileField/components/FileThumbnail.tsx.html +1195 -0
  7. package/coverage/components/CrudiaFileField/components/index.html +176 -0
  8. package/coverage/components/CrudiaFileField/components/index.ts.html +115 -0
  9. package/coverage/components/CrudiaFileField/hooks/index.html +146 -0
  10. package/coverage/components/CrudiaFileField/hooks/index.ts.html +112 -0
  11. package/coverage/components/CrudiaFileField/hooks/useDeleteConfirmation.ts.html +421 -0
  12. package/coverage/components/CrudiaFileField/hooks/useDragDrop.ts.html +403 -0
  13. package/coverage/components/CrudiaFileField/index.html +131 -0
  14. package/coverage/components/CrudiaFileField/index.ts.html +112 -0
  15. package/coverage/components/CrudiaFileField/utils/formatters.ts.html +163 -0
  16. package/coverage/components/CrudiaFileField/utils/icons.tsx.html +253 -0
  17. package/coverage/components/CrudiaFileField/utils/index.html +131 -0
  18. package/coverage/components/CrudiaMarkdownField.tsx.html +619 -0
  19. package/coverage/components/CrudifyLogin/Forms/CheckCodeForm.tsx.html +586 -0
  20. package/coverage/components/CrudifyLogin/Forms/ForgotPasswordForm.tsx.html +694 -0
  21. package/coverage/components/CrudifyLogin/Forms/LoginForm.tsx.html +835 -0
  22. package/coverage/components/CrudifyLogin/Forms/ResetPasswordForm.tsx.html +1180 -0
  23. package/coverage/components/CrudifyLogin/Forms/components/CodeInput.tsx.html +283 -0
  24. package/coverage/components/CrudifyLogin/Forms/components/FormAlert.tsx.html +202 -0
  25. package/coverage/components/CrudifyLogin/Forms/components/PasswordInput.tsx.html +340 -0
  26. package/coverage/components/CrudifyLogin/Forms/components/index.html +161 -0
  27. package/coverage/components/CrudifyLogin/Forms/components/index.ts.html +106 -0
  28. package/coverage/components/CrudifyLogin/Forms/index.html +161 -0
  29. package/coverage/components/CrudifyLogin/Forms/utils/errorTranslation.ts.html +268 -0
  30. package/coverage/components/CrudifyLogin/Forms/utils/index.html +161 -0
  31. package/coverage/components/CrudifyLogin/Forms/utils/index.ts.html +106 -0
  32. package/coverage/components/CrudifyLogin/Forms/utils/paramUtils.ts.html +478 -0
  33. package/coverage/components/CrudifyLogin/Forms/utils/validation.ts.html +289 -0
  34. package/coverage/components/CrudifyLogin/components/CrudifyInitializer.tsx.html +262 -0
  35. package/coverage/components/CrudifyLogin/components/index.html +116 -0
  36. package/coverage/components/CrudifyLogin/context/CrudifyProvider.tsx.html +382 -0
  37. package/coverage/components/CrudifyLogin/context/I18nProvider.tsx.html +397 -0
  38. package/coverage/components/CrudifyLogin/context/LoginStateProvider.tsx.html +1249 -0
  39. package/coverage/components/CrudifyLogin/context/index.html +146 -0
  40. package/coverage/components/CrudifyLogin/hooks/index.html +116 -0
  41. package/coverage/components/CrudifyLogin/hooks/useTranslationsFromUrl.ts.html +292 -0
  42. package/coverage/components/CrudifyLogin/index.html +116 -0
  43. package/coverage/components/CrudifyLogin/index.tsx.html +475 -0
  44. package/coverage/components/GlobalNotificationProvider.tsx.html +781 -0
  45. package/coverage/components/LoginComponent.tsx.html +727 -0
  46. package/coverage/components/PasswordRequirements/index.html +116 -0
  47. package/coverage/components/PasswordRequirements/index.tsx.html +226 -0
  48. package/coverage/components/PublicPolicies/FieldSelector/FieldSelector.tsx.html +982 -0
  49. package/coverage/components/PublicPolicies/FieldSelector/index.html +131 -0
  50. package/coverage/components/PublicPolicies/FieldSelector/index.ts.html +85 -0
  51. package/coverage/components/PublicPolicies/Policies.tsx.html +610 -0
  52. package/coverage/components/PublicPolicies/PolicyItem/PolicyItem.tsx.html +856 -0
  53. package/coverage/components/PublicPolicies/PolicyItem/index.html +131 -0
  54. package/coverage/components/PublicPolicies/PolicyItem/index.ts.html +85 -0
  55. package/coverage/components/PublicPolicies/constants.ts.html +127 -0
  56. package/coverage/components/PublicPolicies/index.html +131 -0
  57. package/coverage/components/SessionTimeIndicator/index.html +116 -0
  58. package/coverage/components/SessionTimeIndicator/index.tsx.html +505 -0
  59. package/coverage/components/UserProfile/UserProfileDisplay.tsx.html +826 -0
  60. package/coverage/components/UserProfile/index.html +131 -0
  61. package/coverage/components/UserProfile/index.ts.html +85 -0
  62. package/coverage/components/index.html +176 -0
  63. package/coverage/components/index.ts.html +160 -0
  64. package/coverage/core/CrossTabSyncManager.ts.html +814 -0
  65. package/coverage/core/CrudifyInitializationManager.ts.html +1132 -0
  66. package/coverage/core/SessionManager.ts.html +2764 -0
  67. package/coverage/core/index.html +146 -0
  68. package/coverage/coverage-final.json +52 -85
  69. package/coverage/hooks/index.html +131 -0
  70. package/coverage/hooks/useAutoGenerate.ts.html +562 -0
  71. package/coverage/hooks/useFileUpload/index.html +131 -0
  72. package/coverage/hooks/useFileUpload/index.ts.html +112 -0
  73. package/coverage/hooks/useFileUpload/services/index.html +116 -0
  74. package/coverage/hooks/useFileUpload/services/uploadService.ts.html +610 -0
  75. package/coverage/hooks/useFileUpload/useFileUpload.ts.html +1870 -0
  76. package/coverage/hooks/useFileUpload/utils/fileUtils.ts.html +271 -0
  77. package/coverage/hooks/useFileUpload/utils/index.html +146 -0
  78. package/coverage/hooks/useFileUpload/utils/mimeTypes.ts.html +235 -0
  79. package/coverage/hooks/useFileUpload/utils/validation.ts.html +379 -0
  80. package/coverage/hooks/useSession/constants.ts.html +217 -0
  81. package/coverage/hooks/useSession/hooks/index.html +176 -0
  82. package/coverage/hooks/useSession/hooks/useAuthEventSubscriber.ts.html +331 -0
  83. package/coverage/hooks/useSession/hooks/useCrossTabSync.ts.html +433 -0
  84. package/coverage/hooks/useSession/hooks/useSessionActions.ts.html +664 -0
  85. package/coverage/hooks/useSession/hooks/useSessionState.ts.html +295 -0
  86. package/coverage/hooks/useSession/hooks/useTokenRefreshScheduler.ts.html +490 -0
  87. package/coverage/hooks/useSession/index.html +161 -0
  88. package/coverage/hooks/useSession/index.ts.html +127 -0
  89. package/coverage/hooks/useSession/types.ts.html +427 -0
  90. package/coverage/hooks/useSession/useSession.ts.html +526 -0
  91. package/coverage/hooks/useSession/utils/index.html +131 -0
  92. package/coverage/hooks/useSession/utils/initializeSession.ts.html +424 -0
  93. package/coverage/hooks/useSession/utils/tokenUtils.ts.html +280 -0
  94. package/coverage/hooks/useUserProfile.ts.html +658 -0
  95. package/coverage/index.html +237 -357
  96. package/coverage/providers/SessionProvider.tsx.html +1150 -0
  97. package/coverage/providers/TranslationsProvider.tsx.html +1450 -0
  98. package/coverage/providers/index.html +131 -0
  99. package/coverage/services/credentialsEventBus.ts.html +310 -0
  100. package/coverage/services/index.html +131 -0
  101. package/coverage/services/translationService.ts.html +1318 -0
  102. package/coverage/translations/critical.ts.html +1195 -0
  103. package/coverage/translations/index.html +116 -0
  104. package/coverage/types/index.html +116 -0
  105. package/coverage/types/password.ts.html +178 -0
  106. package/coverage/utils/authEventBus.ts.html +454 -0
  107. package/coverage/utils/configResolver.ts.html +460 -0
  108. package/coverage/utils/cookieSync.ts.html +580 -0
  109. package/coverage/utils/errorHandler.ts.html +1264 -0
  110. package/coverage/utils/errorTranslation.ts.html +862 -0
  111. package/coverage/utils/index.html +296 -0
  112. package/coverage/utils/jwtUtils.ts.html +301 -0
  113. package/coverage/utils/logger.ts.html +901 -0
  114. package/coverage/utils/navigationTracker.ts.html +565 -0
  115. package/coverage/utils/passwordValidation.ts.html +259 -0
  116. package/coverage/utils/redirectSecurity.ts.html +715 -0
  117. package/coverage/utils/tenantConfig.ts.html +700 -0
  118. package/coverage/utils/tokenStorage.ts.html +1768 -0
  119. package/coverage/utils/webCrypto.ts.html +472 -0
  120. package/dist/{CrudiaMarkdownField-Bxl08sRG.d.mts → CrudiaMarkdownField-BvJn2GL8.d.mts} +5 -0
  121. package/dist/{CrudiaMarkdownField-DUJNOOzP.d.ts → CrudiaMarkdownField-CggOpcBM.d.ts} +5 -0
  122. package/dist/chunk-SYHNHKFA.mjs +1 -0
  123. package/dist/chunk-W4ZYKPOK.js +1 -0
  124. package/dist/components.d.mts +1 -1
  125. package/dist/components.d.ts +1 -1
  126. package/dist/components.js +1 -1
  127. package/dist/components.mjs +1 -1
  128. package/dist/index.d.mts +6 -2
  129. package/dist/index.d.ts +6 -2
  130. package/dist/index.js +2 -2
  131. package/dist/index.mjs +1 -1
  132. package/package.json +1 -1
  133. package/dist/chunk-QFACMV2I.mjs +0 -1
  134. package/dist/chunk-QZH3KSJZ.js +0 -1
@@ -0,0 +1,1276 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for components/CrudiaFileField/CrudiaFileField.tsx</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="../../prettify.css" />
9
+ <link rel="stylesheet" href="../../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(../../sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="../../index.html">All files</a> / <a href="index.html">components/CrudiaFileField</a> CrudiaFileField.tsx</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">97.73% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>388/397</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">87.75% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>43/49</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">100% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>3/3</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">97.73% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>388/397</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line high'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a>
113
+ <a name='L48'></a><a href='#L48'>48</a>
114
+ <a name='L49'></a><a href='#L49'>49</a>
115
+ <a name='L50'></a><a href='#L50'>50</a>
116
+ <a name='L51'></a><a href='#L51'>51</a>
117
+ <a name='L52'></a><a href='#L52'>52</a>
118
+ <a name='L53'></a><a href='#L53'>53</a>
119
+ <a name='L54'></a><a href='#L54'>54</a>
120
+ <a name='L55'></a><a href='#L55'>55</a>
121
+ <a name='L56'></a><a href='#L56'>56</a>
122
+ <a name='L57'></a><a href='#L57'>57</a>
123
+ <a name='L58'></a><a href='#L58'>58</a>
124
+ <a name='L59'></a><a href='#L59'>59</a>
125
+ <a name='L60'></a><a href='#L60'>60</a>
126
+ <a name='L61'></a><a href='#L61'>61</a>
127
+ <a name='L62'></a><a href='#L62'>62</a>
128
+ <a name='L63'></a><a href='#L63'>63</a>
129
+ <a name='L64'></a><a href='#L64'>64</a>
130
+ <a name='L65'></a><a href='#L65'>65</a>
131
+ <a name='L66'></a><a href='#L66'>66</a>
132
+ <a name='L67'></a><a href='#L67'>67</a>
133
+ <a name='L68'></a><a href='#L68'>68</a>
134
+ <a name='L69'></a><a href='#L69'>69</a>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a>
151
+ <a name='L86'></a><a href='#L86'>86</a>
152
+ <a name='L87'></a><a href='#L87'>87</a>
153
+ <a name='L88'></a><a href='#L88'>88</a>
154
+ <a name='L89'></a><a href='#L89'>89</a>
155
+ <a name='L90'></a><a href='#L90'>90</a>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a>
163
+ <a name='L98'></a><a href='#L98'>98</a>
164
+ <a name='L99'></a><a href='#L99'>99</a>
165
+ <a name='L100'></a><a href='#L100'>100</a>
166
+ <a name='L101'></a><a href='#L101'>101</a>
167
+ <a name='L102'></a><a href='#L102'>102</a>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a>
170
+ <a name='L105'></a><a href='#L105'>105</a>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a>
372
+ <a name='L307'></a><a href='#L307'>307</a>
373
+ <a name='L308'></a><a href='#L308'>308</a>
374
+ <a name='L309'></a><a href='#L309'>309</a>
375
+ <a name='L310'></a><a href='#L310'>310</a>
376
+ <a name='L311'></a><a href='#L311'>311</a>
377
+ <a name='L312'></a><a href='#L312'>312</a>
378
+ <a name='L313'></a><a href='#L313'>313</a>
379
+ <a name='L314'></a><a href='#L314'>314</a>
380
+ <a name='L315'></a><a href='#L315'>315</a>
381
+ <a name='L316'></a><a href='#L316'>316</a>
382
+ <a name='L317'></a><a href='#L317'>317</a>
383
+ <a name='L318'></a><a href='#L318'>318</a>
384
+ <a name='L319'></a><a href='#L319'>319</a>
385
+ <a name='L320'></a><a href='#L320'>320</a>
386
+ <a name='L321'></a><a href='#L321'>321</a>
387
+ <a name='L322'></a><a href='#L322'>322</a>
388
+ <a name='L323'></a><a href='#L323'>323</a>
389
+ <a name='L324'></a><a href='#L324'>324</a>
390
+ <a name='L325'></a><a href='#L325'>325</a>
391
+ <a name='L326'></a><a href='#L326'>326</a>
392
+ <a name='L327'></a><a href='#L327'>327</a>
393
+ <a name='L328'></a><a href='#L328'>328</a>
394
+ <a name='L329'></a><a href='#L329'>329</a>
395
+ <a name='L330'></a><a href='#L330'>330</a>
396
+ <a name='L331'></a><a href='#L331'>331</a>
397
+ <a name='L332'></a><a href='#L332'>332</a>
398
+ <a name='L333'></a><a href='#L333'>333</a>
399
+ <a name='L334'></a><a href='#L334'>334</a>
400
+ <a name='L335'></a><a href='#L335'>335</a>
401
+ <a name='L336'></a><a href='#L336'>336</a>
402
+ <a name='L337'></a><a href='#L337'>337</a>
403
+ <a name='L338'></a><a href='#L338'>338</a>
404
+ <a name='L339'></a><a href='#L339'>339</a>
405
+ <a name='L340'></a><a href='#L340'>340</a>
406
+ <a name='L341'></a><a href='#L341'>341</a>
407
+ <a name='L342'></a><a href='#L342'>342</a>
408
+ <a name='L343'></a><a href='#L343'>343</a>
409
+ <a name='L344'></a><a href='#L344'>344</a>
410
+ <a name='L345'></a><a href='#L345'>345</a>
411
+ <a name='L346'></a><a href='#L346'>346</a>
412
+ <a name='L347'></a><a href='#L347'>347</a>
413
+ <a name='L348'></a><a href='#L348'>348</a>
414
+ <a name='L349'></a><a href='#L349'>349</a>
415
+ <a name='L350'></a><a href='#L350'>350</a>
416
+ <a name='L351'></a><a href='#L351'>351</a>
417
+ <a name='L352'></a><a href='#L352'>352</a>
418
+ <a name='L353'></a><a href='#L353'>353</a>
419
+ <a name='L354'></a><a href='#L354'>354</a>
420
+ <a name='L355'></a><a href='#L355'>355</a>
421
+ <a name='L356'></a><a href='#L356'>356</a>
422
+ <a name='L357'></a><a href='#L357'>357</a>
423
+ <a name='L358'></a><a href='#L358'>358</a>
424
+ <a name='L359'></a><a href='#L359'>359</a>
425
+ <a name='L360'></a><a href='#L360'>360</a>
426
+ <a name='L361'></a><a href='#L361'>361</a>
427
+ <a name='L362'></a><a href='#L362'>362</a>
428
+ <a name='L363'></a><a href='#L363'>363</a>
429
+ <a name='L364'></a><a href='#L364'>364</a>
430
+ <a name='L365'></a><a href='#L365'>365</a>
431
+ <a name='L366'></a><a href='#L366'>366</a>
432
+ <a name='L367'></a><a href='#L367'>367</a>
433
+ <a name='L368'></a><a href='#L368'>368</a>
434
+ <a name='L369'></a><a href='#L369'>369</a>
435
+ <a name='L370'></a><a href='#L370'>370</a>
436
+ <a name='L371'></a><a href='#L371'>371</a>
437
+ <a name='L372'></a><a href='#L372'>372</a>
438
+ <a name='L373'></a><a href='#L373'>373</a>
439
+ <a name='L374'></a><a href='#L374'>374</a>
440
+ <a name='L375'></a><a href='#L375'>375</a>
441
+ <a name='L376'></a><a href='#L376'>376</a>
442
+ <a name='L377'></a><a href='#L377'>377</a>
443
+ <a name='L378'></a><a href='#L378'>378</a>
444
+ <a name='L379'></a><a href='#L379'>379</a>
445
+ <a name='L380'></a><a href='#L380'>380</a>
446
+ <a name='L381'></a><a href='#L381'>381</a>
447
+ <a name='L382'></a><a href='#L382'>382</a>
448
+ <a name='L383'></a><a href='#L383'>383</a>
449
+ <a name='L384'></a><a href='#L384'>384</a>
450
+ <a name='L385'></a><a href='#L385'>385</a>
451
+ <a name='L386'></a><a href='#L386'>386</a>
452
+ <a name='L387'></a><a href='#L387'>387</a>
453
+ <a name='L388'></a><a href='#L388'>388</a>
454
+ <a name='L389'></a><a href='#L389'>389</a>
455
+ <a name='L390'></a><a href='#L390'>390</a>
456
+ <a name='L391'></a><a href='#L391'>391</a>
457
+ <a name='L392'></a><a href='#L392'>392</a>
458
+ <a name='L393'></a><a href='#L393'>393</a>
459
+ <a name='L394'></a><a href='#L394'>394</a>
460
+ <a name='L395'></a><a href='#L395'>395</a>
461
+ <a name='L396'></a><a href='#L396'>396</a>
462
+ <a name='L397'></a><a href='#L397'>397</a>
463
+ <a name='L398'></a><a href='#L398'>398</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
464
+ <span class="cline-any cline-yes">1x</span>
465
+ <span class="cline-any cline-yes">1x</span>
466
+ <span class="cline-any cline-yes">1x</span>
467
+ <span class="cline-any cline-yes">1x</span>
468
+ <span class="cline-any cline-yes">1x</span>
469
+ <span class="cline-any cline-yes">1x</span>
470
+ <span class="cline-any cline-yes">1x</span>
471
+ <span class="cline-any cline-yes">1x</span>
472
+ <span class="cline-any cline-yes">1x</span>
473
+ <span class="cline-any cline-yes">1x</span>
474
+ <span class="cline-any cline-yes">1x</span>
475
+ <span class="cline-any cline-yes">1x</span>
476
+ <span class="cline-any cline-yes">1x</span>
477
+ <span class="cline-any cline-yes">1x</span>
478
+ <span class="cline-any cline-yes">1x</span>
479
+ <span class="cline-any cline-yes">1x</span>
480
+ <span class="cline-any cline-yes">1x</span>
481
+ <span class="cline-any cline-yes">1x</span>
482
+ <span class="cline-any cline-yes">1x</span>
483
+ <span class="cline-any cline-yes">1x</span>
484
+ <span class="cline-any cline-yes">1x</span>
485
+ <span class="cline-any cline-yes">1x</span>
486
+ <span class="cline-any cline-yes">1x</span>
487
+ <span class="cline-any cline-yes">1x</span>
488
+ <span class="cline-any cline-yes">1x</span>
489
+ <span class="cline-any cline-yes">1x</span>
490
+ <span class="cline-any cline-yes">1x</span>
491
+ <span class="cline-any cline-yes">1x</span>
492
+ <span class="cline-any cline-yes">1x</span>
493
+ <span class="cline-any cline-yes">1x</span>
494
+ <span class="cline-any cline-yes">1x</span>
495
+ <span class="cline-any cline-yes">1x</span>
496
+ <span class="cline-any cline-yes">1x</span>
497
+ <span class="cline-any cline-yes">1x</span>
498
+ <span class="cline-any cline-yes">1x</span>
499
+ <span class="cline-any cline-yes">1x</span>
500
+ <span class="cline-any cline-yes">1x</span>
501
+ <span class="cline-any cline-yes">1x</span>
502
+ <span class="cline-any cline-yes">1x</span>
503
+ <span class="cline-any cline-yes">1x</span>
504
+ <span class="cline-any cline-yes">1x</span>
505
+ <span class="cline-any cline-yes">1x</span>
506
+ <span class="cline-any cline-yes">1x</span>
507
+ <span class="cline-any cline-yes">1x</span>
508
+ <span class="cline-any cline-yes">1x</span>
509
+ <span class="cline-any cline-yes">1x</span>
510
+ <span class="cline-any cline-yes">1x</span>
511
+ <span class="cline-any cline-yes">1x</span>
512
+ <span class="cline-any cline-yes">1x</span>
513
+ <span class="cline-any cline-yes">1x</span>
514
+ <span class="cline-any cline-yes">1x</span>
515
+ <span class="cline-any cline-yes">1x</span>
516
+ <span class="cline-any cline-yes">1x</span>
517
+ <span class="cline-any cline-yes">1x</span>
518
+ <span class="cline-any cline-yes">1x</span>
519
+ <span class="cline-any cline-yes">1x</span>
520
+ <span class="cline-any cline-yes">1x</span>
521
+ <span class="cline-any cline-yes">1x</span>
522
+ <span class="cline-any cline-yes">1x</span>
523
+ <span class="cline-any cline-yes">1x</span>
524
+ <span class="cline-any cline-yes">1x</span>
525
+ <span class="cline-any cline-yes">1x</span>
526
+ <span class="cline-any cline-yes">1x</span>
527
+ <span class="cline-any cline-yes">1x</span>
528
+ <span class="cline-any cline-yes">1x</span>
529
+ <span class="cline-any cline-yes">1x</span>
530
+ <span class="cline-any cline-yes">1x</span>
531
+ <span class="cline-any cline-yes">108x</span>
532
+ <span class="cline-any cline-yes">108x</span>
533
+ <span class="cline-any cline-yes">108x</span>
534
+ <span class="cline-any cline-yes">108x</span>
535
+ <span class="cline-any cline-yes">108x</span>
536
+ <span class="cline-any cline-yes">108x</span>
537
+ <span class="cline-any cline-yes">108x</span>
538
+ <span class="cline-any cline-yes">108x</span>
539
+ <span class="cline-any cline-yes">108x</span>
540
+ <span class="cline-any cline-yes">108x</span>
541
+ <span class="cline-any cline-yes">108x</span>
542
+ <span class="cline-any cline-yes">108x</span>
543
+ <span class="cline-any cline-yes">108x</span>
544
+ <span class="cline-any cline-yes">108x</span>
545
+ <span class="cline-any cline-yes">108x</span>
546
+ <span class="cline-any cline-yes">108x</span>
547
+ <span class="cline-any cline-yes">108x</span>
548
+ <span class="cline-any cline-yes">108x</span>
549
+ <span class="cline-any cline-yes">108x</span>
550
+ <span class="cline-any cline-yes">108x</span>
551
+ <span class="cline-any cline-yes">108x</span>
552
+ <span class="cline-any cline-yes">108x</span>
553
+ <span class="cline-any cline-yes">108x</span>
554
+ <span class="cline-any cline-yes">108x</span>
555
+ <span class="cline-any cline-yes">108x</span>
556
+ <span class="cline-any cline-yes">108x</span>
557
+ <span class="cline-any cline-yes">108x</span>
558
+ <span class="cline-any cline-yes">108x</span>
559
+ <span class="cline-any cline-yes">108x</span>
560
+ <span class="cline-any cline-yes">108x</span>
561
+ <span class="cline-any cline-yes">108x</span>
562
+ <span class="cline-any cline-yes">108x</span>
563
+ <span class="cline-any cline-yes">108x</span>
564
+ <span class="cline-any cline-yes">108x</span>
565
+ <span class="cline-any cline-yes">108x</span>
566
+ <span class="cline-any cline-yes">108x</span>
567
+ <span class="cline-any cline-yes">108x</span>
568
+ <span class="cline-any cline-yes">37x</span>
569
+ <span class="cline-any cline-yes">37x</span>
570
+ <span class="cline-any cline-yes">37x</span>
571
+ <span class="cline-any cline-yes">28x</span>
572
+ <span class="cline-any cline-yes">28x</span>
573
+ <span class="cline-any cline-yes">28x</span>
574
+ <span class="cline-any cline-yes">28x</span>
575
+ <span class="cline-any cline-yes">28x</span>
576
+ <span class="cline-any cline-no">&nbsp;</span>
577
+ <span class="cline-any cline-no">&nbsp;</span>
578
+ <span class="cline-any cline-yes">28x</span>
579
+ <span class="cline-any cline-yes">37x</span>
580
+ <span class="cline-any cline-yes">37x</span>
581
+ <span class="cline-any cline-yes">37x</span>
582
+ <span class="cline-any cline-yes">108x</span>
583
+ <span class="cline-any cline-yes">108x</span>
584
+ <span class="cline-any cline-yes">108x</span>
585
+ <span class="cline-any cline-yes">108x</span>
586
+ <span class="cline-any cline-yes">108x</span>
587
+ <span class="cline-any cline-yes">108x</span>
588
+ <span class="cline-any cline-yes">108x</span>
589
+ <span class="cline-any cline-yes">108x</span>
590
+ <span class="cline-any cline-yes">108x</span>
591
+ <span class="cline-any cline-yes">108x</span>
592
+ <span class="cline-any cline-yes">108x</span>
593
+ <span class="cline-any cline-yes">108x</span>
594
+ <span class="cline-any cline-yes">108x</span>
595
+ <span class="cline-any cline-yes">108x</span>
596
+ <span class="cline-any cline-yes">108x</span>
597
+ <span class="cline-any cline-yes">108x</span>
598
+ <span class="cline-any cline-yes">108x</span>
599
+ <span class="cline-any cline-yes">108x</span>
600
+ <span class="cline-any cline-yes">108x</span>
601
+ <span class="cline-any cline-yes">108x</span>
602
+ <span class="cline-any cline-yes">108x</span>
603
+ <span class="cline-any cline-yes">108x</span>
604
+ <span class="cline-any cline-yes">108x</span>
605
+ <span class="cline-any cline-yes">108x</span>
606
+ <span class="cline-any cline-yes">108x</span>
607
+ <span class="cline-any cline-yes">108x</span>
608
+ <span class="cline-any cline-yes">108x</span>
609
+ <span class="cline-any cline-yes">108x</span>
610
+ <span class="cline-any cline-yes">108x</span>
611
+ <span class="cline-any cline-yes">108x</span>
612
+ <span class="cline-any cline-yes">108x</span>
613
+ <span class="cline-any cline-no">&nbsp;</span>
614
+ <span class="cline-any cline-yes">108x</span>
615
+ <span class="cline-any cline-yes">108x</span>
616
+ <span class="cline-any cline-yes">108x</span>
617
+ <span class="cline-any cline-yes">108x</span>
618
+ <span class="cline-any cline-yes">108x</span>
619
+ <span class="cline-any cline-yes">108x</span>
620
+ <span class="cline-any cline-yes">108x</span>
621
+ <span class="cline-any cline-yes">108x</span>
622
+ <span class="cline-any cline-yes">108x</span>
623
+ <span class="cline-any cline-yes">108x</span>
624
+ <span class="cline-any cline-yes">108x</span>
625
+ <span class="cline-any cline-yes">108x</span>
626
+ <span class="cline-any cline-yes">22x</span>
627
+ <span class="cline-any cline-yes">22x</span>
628
+ <span class="cline-any cline-yes">22x</span>
629
+ <span class="cline-any cline-yes">22x</span>
630
+ <span class="cline-any cline-yes">22x</span>
631
+ <span class="cline-any cline-yes">22x</span>
632
+ <span class="cline-any cline-yes">22x</span>
633
+ <span class="cline-any cline-no">&nbsp;</span>
634
+ <span class="cline-any cline-yes">22x</span>
635
+ <span class="cline-any cline-yes">22x</span>
636
+ <span class="cline-any cline-yes">22x</span>
637
+ <span class="cline-any cline-yes">22x</span>
638
+ <span class="cline-any cline-yes">22x</span>
639
+ <span class="cline-any cline-yes">108x</span>
640
+ <span class="cline-any cline-yes">108x</span>
641
+ <span class="cline-any cline-yes">108x</span>
642
+ <span class="cline-any cline-yes">108x</span>
643
+ <span class="cline-any cline-yes">66x</span>
644
+ <span class="cline-any cline-yes">108x</span>
645
+ <span class="cline-any cline-yes">108x</span>
646
+ <span class="cline-any cline-yes">108x</span>
647
+ <span class="cline-any cline-yes">108x</span>
648
+ <span class="cline-any cline-yes">108x</span>
649
+ <span class="cline-any cline-yes">108x</span>
650
+ <span class="cline-any cline-yes">108x</span>
651
+ <span class="cline-any cline-yes">1x</span>
652
+ <span class="cline-any cline-yes">1x</span>
653
+ <span class="cline-any cline-yes">1x</span>
654
+ <span class="cline-any cline-yes">1x</span>
655
+ <span class="cline-any cline-yes">1x</span>
656
+ <span class="cline-any cline-yes">1x</span>
657
+ <span class="cline-any cline-yes">1x</span>
658
+ <span class="cline-any cline-yes">1x</span>
659
+ <span class="cline-any cline-yes">1x</span>
660
+ <span class="cline-any cline-yes">1x</span>
661
+ <span class="cline-any cline-yes">1x</span>
662
+ <span class="cline-any cline-yes">108x</span>
663
+ <span class="cline-any cline-yes">108x</span>
664
+ <span class="cline-any cline-yes">108x</span>
665
+ <span class="cline-any cline-yes">108x</span>
666
+ <span class="cline-any cline-yes">108x</span>
667
+ <span class="cline-any cline-yes">108x</span>
668
+ <span class="cline-any cline-yes">108x</span>
669
+ <span class="cline-any cline-yes">108x</span>
670
+ <span class="cline-any cline-yes">108x</span>
671
+ <span class="cline-any cline-yes">108x</span>
672
+ <span class="cline-any cline-yes">108x</span>
673
+ <span class="cline-any cline-yes">108x</span>
674
+ <span class="cline-any cline-yes">108x</span>
675
+ <span class="cline-any cline-yes">108x</span>
676
+ <span class="cline-any cline-yes">108x</span>
677
+ <span class="cline-any cline-yes">108x</span>
678
+ <span class="cline-any cline-yes">108x</span>
679
+ <span class="cline-any cline-yes">108x</span>
680
+ <span class="cline-any cline-yes">108x</span>
681
+ <span class="cline-any cline-yes">108x</span>
682
+ <span class="cline-any cline-yes">108x</span>
683
+ <span class="cline-any cline-yes">108x</span>
684
+ <span class="cline-any cline-yes">108x</span>
685
+ <span class="cline-any cline-yes">108x</span>
686
+ <span class="cline-any cline-yes">108x</span>
687
+ <span class="cline-any cline-yes">108x</span>
688
+ <span class="cline-any cline-yes">108x</span>
689
+ <span class="cline-any cline-yes">108x</span>
690
+ <span class="cline-any cline-yes">108x</span>
691
+ <span class="cline-any cline-yes">5x</span>
692
+ <span class="cline-any cline-yes">5x</span>
693
+ <span class="cline-any cline-yes">5x</span>
694
+ <span class="cline-any cline-yes">5x</span>
695
+ <span class="cline-any cline-yes">5x</span>
696
+ <span class="cline-any cline-yes">5x</span>
697
+ <span class="cline-any cline-yes">5x</span>
698
+ <span class="cline-any cline-yes">5x</span>
699
+ <span class="cline-any cline-yes">5x</span>
700
+ <span class="cline-any cline-yes">5x</span>
701
+ <span class="cline-any cline-yes">108x</span>
702
+ <span class="cline-any cline-yes">108x</span>
703
+ <span class="cline-any cline-yes">108x</span>
704
+ <span class="cline-any cline-yes">108x</span>
705
+ <span class="cline-any cline-yes">108x</span>
706
+ <span class="cline-any cline-yes">108x</span>
707
+ <span class="cline-any cline-yes">108x</span>
708
+ <span class="cline-any cline-yes">108x</span>
709
+ <span class="cline-any cline-yes">108x</span>
710
+ <span class="cline-any cline-no">&nbsp;</span>
711
+ <span class="cline-any cline-no">&nbsp;</span>
712
+ <span class="cline-any cline-no">&nbsp;</span>
713
+ <span class="cline-any cline-yes">108x</span>
714
+ <span class="cline-any cline-yes">108x</span>
715
+ <span class="cline-any cline-yes">108x</span>
716
+ <span class="cline-any cline-yes">108x</span>
717
+ <span class="cline-any cline-yes">108x</span>
718
+ <span class="cline-any cline-yes">108x</span>
719
+ <span class="cline-any cline-yes">108x</span>
720
+ <span class="cline-any cline-yes">108x</span>
721
+ <span class="cline-any cline-yes">6x</span>
722
+ <span class="cline-any cline-yes">6x</span>
723
+ <span class="cline-any cline-yes">6x</span>
724
+ <span class="cline-any cline-yes">3x</span>
725
+ <span class="cline-any cline-yes">3x</span>
726
+ <span class="cline-any cline-yes">3x</span>
727
+ <span class="cline-any cline-yes">6x</span>
728
+ <span class="cline-any cline-yes">6x</span>
729
+ <span class="cline-any cline-yes">108x</span>
730
+ <span class="cline-any cline-yes">108x</span>
731
+ <span class="cline-any cline-yes">108x</span>
732
+ <span class="cline-any cline-yes">108x</span>
733
+ <span class="cline-any cline-yes">108x</span>
734
+ <span class="cline-any cline-yes">108x</span>
735
+ <span class="cline-any cline-yes">108x</span>
736
+ <span class="cline-any cline-yes">108x</span>
737
+ <span class="cline-any cline-yes">108x</span>
738
+ <span class="cline-any cline-yes">108x</span>
739
+ <span class="cline-any cline-yes">108x</span>
740
+ <span class="cline-any cline-yes">108x</span>
741
+ <span class="cline-any cline-yes">108x</span>
742
+ <span class="cline-any cline-yes">108x</span>
743
+ <span class="cline-any cline-yes">108x</span>
744
+ <span class="cline-any cline-yes">108x</span>
745
+ <span class="cline-any cline-yes">108x</span>
746
+ <span class="cline-any cline-yes">108x</span>
747
+ <span class="cline-any cline-yes">108x</span>
748
+ <span class="cline-any cline-yes">108x</span>
749
+ <span class="cline-any cline-yes">108x</span>
750
+ <span class="cline-any cline-yes">108x</span>
751
+ <span class="cline-any cline-yes">108x</span>
752
+ <span class="cline-any cline-yes">108x</span>
753
+ <span class="cline-any cline-yes">108x</span>
754
+ <span class="cline-any cline-yes">108x</span>
755
+ <span class="cline-any cline-yes">108x</span>
756
+ <span class="cline-any cline-yes">108x</span>
757
+ <span class="cline-any cline-yes">108x</span>
758
+ <span class="cline-any cline-yes">108x</span>
759
+ <span class="cline-any cline-yes">66x</span>
760
+ <span class="cline-any cline-yes">64x</span>
761
+ <span class="cline-any cline-yes">66x</span>
762
+ <span class="cline-any cline-no">&nbsp;</span>
763
+ <span class="cline-any cline-no">&nbsp;</span>
764
+ <span class="cline-any cline-yes">64x</span>
765
+ <span class="cline-any cline-yes">64x</span>
766
+ <span class="cline-any cline-yes">66x</span>
767
+ <span class="cline-any cline-yes">108x</span>
768
+ <span class="cline-any cline-yes">108x</span>
769
+ <span class="cline-any cline-yes">108x</span>
770
+ <span class="cline-any cline-yes">108x</span>
771
+ <span class="cline-any cline-yes">108x</span>
772
+ <span class="cline-any cline-yes">6x</span>
773
+ <span class="cline-any cline-yes">6x</span>
774
+ <span class="cline-any cline-yes">6x</span>
775
+ <span class="cline-any cline-yes">6x</span>
776
+ <span class="cline-any cline-yes">6x</span>
777
+ <span class="cline-any cline-yes">6x</span>
778
+ <span class="cline-any cline-yes">6x</span>
779
+ <span class="cline-any cline-yes">6x</span>
780
+ <span class="cline-any cline-yes">6x</span>
781
+ <span class="cline-any cline-yes">6x</span>
782
+ <span class="cline-any cline-yes">6x</span>
783
+ <span class="cline-any cline-yes">108x</span>
784
+ <span class="cline-any cline-yes">108x</span>
785
+ <span class="cline-any cline-yes">108x</span>
786
+ <span class="cline-any cline-yes">108x</span>
787
+ <span class="cline-any cline-yes">108x</span>
788
+ <span class="cline-any cline-yes">108x</span>
789
+ <span class="cline-any cline-yes">108x</span>
790
+ <span class="cline-any cline-yes">108x</span>
791
+ <span class="cline-any cline-yes">108x</span>
792
+ <span class="cline-any cline-yes">108x</span>
793
+ <span class="cline-any cline-yes">108x</span>
794
+ <span class="cline-any cline-yes">108x</span>
795
+ <span class="cline-any cline-yes">108x</span>
796
+ <span class="cline-any cline-yes">108x</span>
797
+ <span class="cline-any cline-yes">108x</span>
798
+ <span class="cline-any cline-yes">66x</span>
799
+ <span class="cline-any cline-yes">66x</span>
800
+ <span class="cline-any cline-yes">66x</span>
801
+ <span class="cline-any cline-yes">66x</span>
802
+ <span class="cline-any cline-yes">66x</span>
803
+ <span class="cline-any cline-yes">66x</span>
804
+ <span class="cline-any cline-yes">66x</span>
805
+ <span class="cline-any cline-yes">66x</span>
806
+ <span class="cline-any cline-yes">66x</span>
807
+ <span class="cline-any cline-yes">66x</span>
808
+ <span class="cline-any cline-yes">66x</span>
809
+ <span class="cline-any cline-yes">108x</span>
810
+ <span class="cline-any cline-yes">108x</span>
811
+ <span class="cline-any cline-yes">108x</span>
812
+ <span class="cline-any cline-yes">108x</span>
813
+ <span class="cline-any cline-yes">39x</span>
814
+ <span class="cline-any cline-yes">39x</span>
815
+ <span class="cline-any cline-yes">39x</span>
816
+ <span class="cline-any cline-yes">39x</span>
817
+ <span class="cline-any cline-yes">39x</span>
818
+ <span class="cline-any cline-yes">39x</span>
819
+ <span class="cline-any cline-yes">39x</span>
820
+ <span class="cline-any cline-yes">39x</span>
821
+ <span class="cline-any cline-yes">39x</span>
822
+ <span class="cline-any cline-yes">39x</span>
823
+ <span class="cline-any cline-yes">39x</span>
824
+ <span class="cline-any cline-yes">39x</span>
825
+ <span class="cline-any cline-yes">39x</span>
826
+ <span class="cline-any cline-yes">108x</span>
827
+ <span class="cline-any cline-yes">108x</span>
828
+ <span class="cline-any cline-yes">108x</span>
829
+ <span class="cline-any cline-yes">108x</span>
830
+ <span class="cline-any cline-yes">10x</span>
831
+ <span class="cline-any cline-yes">10x</span>
832
+ <span class="cline-any cline-yes">10x</span>
833
+ <span class="cline-any cline-yes">10x</span>
834
+ <span class="cline-any cline-yes">10x</span>
835
+ <span class="cline-any cline-yes">10x</span>
836
+ <span class="cline-any cline-yes">108x</span>
837
+ <span class="cline-any cline-yes">108x</span>
838
+ <span class="cline-any cline-yes">108x</span>
839
+ <span class="cline-any cline-yes">108x</span>
840
+ <span class="cline-any cline-yes">6x</span>
841
+ <span class="cline-any cline-yes">108x</span>
842
+ <span class="cline-any cline-yes">108x</span>
843
+ <span class="cline-any cline-yes">108x</span>
844
+ <span class="cline-any cline-yes">108x</span>
845
+ <span class="cline-any cline-yes">108x</span>
846
+ <span class="cline-any cline-yes">108x</span>
847
+ <span class="cline-any cline-yes">108x</span>
848
+ <span class="cline-any cline-yes">108x</span>
849
+ <span class="cline-any cline-yes">108x</span>
850
+ <span class="cline-any cline-yes">108x</span>
851
+ <span class="cline-any cline-yes">108x</span>
852
+ <span class="cline-any cline-yes">108x</span>
853
+ <span class="cline-any cline-yes">108x</span>
854
+ <span class="cline-any cline-yes">108x</span>
855
+ <span class="cline-any cline-yes">108x</span>
856
+ <span class="cline-any cline-yes">108x</span>
857
+ <span class="cline-any cline-yes">108x</span>
858
+ <span class="cline-any cline-yes">1x</span>
859
+ <span class="cline-any cline-yes">1x</span>
860
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
861
+ * File field component with:
862
+ * - Drag &amp; drop
863
+ * - File preview
864
+ * - Progress bar during upload
865
+ * - Delete files (soft delete)
866
+ * - Type and size validation
867
+ * - Single/multiple support
868
+ */
869
+ &nbsp;
870
+ import React, { useCallback, useRef } from "react";
871
+ import { logger } from "../../utils/logger";
872
+ import Box from "@mui/material/Box";
873
+ import Typography from "@mui/material/Typography";
874
+ import CircularProgress from "@mui/material/CircularProgress";
875
+ import List from "@mui/material/List";
876
+ import FormHelperText from "@mui/material/FormHelperText";
877
+ import { useFileUpload, type UseFileUploadOptions } from "../../hooks/useFileUpload";
878
+ import { useTranslations } from "../../providers/TranslationsProvider";
879
+ &nbsp;
880
+ // Import types from dedicated types file
881
+ import type { CrudiaFileFieldDeletionHandlers, CrudiaFileFieldProps } from "./types";
882
+ &nbsp;
883
+ // Import utilities
884
+ import { sanitizeHelperTextHtml } from "./utils/formatters";
885
+ &nbsp;
886
+ // Import extracted hooks
887
+ import { useDragDrop, useDeleteConfirmation } from "./hooks";
888
+ &nbsp;
889
+ // Import extracted components
890
+ import { FileItemRow, DropZone, DeleteConfirmationDialog } from "./components";
891
+ &nbsp;
892
+ // Re-export types for backwards compatibility
893
+ export type { CrudiaFileFieldDeletionHandlers, CrudiaFileFieldProps } from "./types";
894
+ &nbsp;
895
+ /**
896
+ * Main file field component
897
+ *
898
+ * @example
899
+ * ```tsx
900
+ * // Basic usage - single file
901
+ * &lt;CrudiaFileField
902
+ * label="Document"
903
+ * accept={["application/pdf"]}
904
+ * onChange={(filePaths) =&gt; setFormData({ ...formData, document: filePaths[0] })}
905
+ * /&gt;
906
+ *
907
+ * // Multiple files with limits
908
+ * &lt;CrudiaFileField
909
+ * label="Images"
910
+ * accept={["image/png", "image/jpeg"]}
911
+ * multiple
912
+ * maxFiles={5}
913
+ * minFiles={1}
914
+ * maxFileSize={5 * 1024 * 1024}
915
+ * onChange={(filePaths) =&gt; setFormData({ ...formData, images: filePaths })}
916
+ * /&gt;
917
+ *
918
+ * // With initial files (edit mode)
919
+ * &lt;CrudiaFileField
920
+ * label="Attachments"
921
+ * multiple
922
+ * initialFiles={existingFiles}
923
+ * onChange={handleFilesChange}
924
+ * /&gt;
925
+ * ```
926
+ */
927
+ export const CrudiaFileField: React.FC&lt;CrudiaFileFieldProps&gt; = ({
928
+ label,
929
+ accept,
930
+ maxFileSize = 10 * 1024 * 1024,
931
+ multiple = false,
932
+ maxFiles,
933
+ minFiles = 0,
934
+ required = false,
935
+ disabled = false,
936
+ error: externalError = false,
937
+ helperText: externalHelperText,
938
+ onChange,
939
+ onValidation,
940
+ initialFiles,
941
+ placeholder,
942
+ showFileList = true,
943
+ visibility = "private",
944
+ showPreview = true,
945
+ baseUrl,
946
+ onDeletionHandlersReady,
947
+ mode = "create",
948
+ }) =&gt; {
949
+ const { t } = useTranslations();
950
+ const inputRef = useRef&lt;HTMLInputElement&gt;(null);
951
+ &nbsp;
952
+ // Calcular límite efectivo de archivos
953
+ const effectiveMaxFiles = multiple ? maxFiles : 1;
954
+ const effectiveMinFiles = required ? Math.max(minFiles, 1) : minFiles;
955
+ &nbsp;
956
+ // Configurar opciones del hook
957
+ const uploadOptions: UseFileUploadOptions = {
958
+ acceptedTypes: accept,
959
+ maxFileSize,
960
+ maxFiles: effectiveMaxFiles,
961
+ minFiles: effectiveMinFiles,
962
+ visibility,
963
+ mode,
964
+ onFilesChange: (files) =&gt; {
965
+ const filePaths = files
966
+ .filter((f) =&gt; f.status === "completed" &amp;&amp; f.filePath)
967
+ .map((f) =&gt; {
968
+ const path = f.filePath as string;
969
+ // Return only the relative path (without baseUrl)
970
+ // baseUrl is only used for displaying/downloading, not for saving
971
+ // Ensure path starts with /
972
+ if (path.startsWith("/")) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
973
+ <span class="cstat-no" title="statement not covered" > return path;</span>
974
+ <span class="cstat-no" title="statement not covered" > }</span>
975
+ return `/${path}`;
976
+ });
977
+ onChange?.(filePaths);
978
+ },
979
+ };
980
+ &nbsp;
981
+ const {
982
+ files,
983
+ isUploading,
984
+ addFiles,
985
+ removeFile,
986
+ restoreFile,
987
+ retryUpload,
988
+ isValid,
989
+ validationError,
990
+ validationErrorKey,
991
+ validationErrorParams,
992
+ initializeFiles,
993
+ isTouched,
994
+ markAsTouched,
995
+ isSubmitted,
996
+ markAsSubmitted,
997
+ getPreviewUrl,
998
+ commitDeletions,
999
+ restorePendingDeletions,
1000
+ hasPendingDeletions,
1001
+ deleteFileImmediately,
1002
+ activeFiles,
1003
+ activeFileCount,
1004
+ waitForUploads,
1005
+ completedFilePaths,
1006
+ } = useFileUpload(uploadOptions);
1007
+ &nbsp;
1008
+ // Create a stable callback to get completed file paths
1009
+ const getCompletedFilePaths = useCallback(() =&gt; {
1010
+ <span class="cstat-no" title="statement not covered" > return completedFilePaths;</span>
1011
+ }, [completedFilePaths]);
1012
+ &nbsp;
1013
+ // Track if we've already initialized to avoid re-initializing on every render
1014
+ const hasInitializedRef = useRef(false);
1015
+ const initializationInProgressRef = useRef(false);
1016
+ &nbsp;
1017
+ // Initialize existing files - handles async loading of initialFiles
1018
+ // Pass baseUrl so the hook can extract relative paths from full URLs
1019
+ React.useEffect(() =&gt; {
1020
+ const shouldInitialize = initialFiles &amp;&amp; initialFiles.length &gt; 0 &amp;&amp; !hasInitializedRef.current &amp;&amp; !initializationInProgressRef.current;
1021
+ &nbsp;
1022
+ if (shouldInitialize) {
1023
+ initializationInProgressRef.current = true;
1024
+ &nbsp;
1025
+ (async () =&gt; {
1026
+ try {
1027
+ await initializeFiles(initialFiles, baseUrl);
1028
+ hasInitializedRef.current = true;
1029
+ <span class="branch-0 cbranch-no" title="branch not covered" > } catch (error) {</span>
1030
+ <span class="cstat-no" title="statement not covered" > logger.error("Failed to initialize files", { error });</span>
1031
+ } finally {
1032
+ initializationInProgressRef.current = false;
1033
+ }
1034
+ })();
1035
+ }
1036
+ }, [initialFiles, initializeFiles, baseUrl]);
1037
+ &nbsp;
1038
+ // Notify validation
1039
+ React.useEffect(() =&gt; {
1040
+ onValidation?.(isValid, validationError);
1041
+ }, [isValid, validationError, onValidation]);
1042
+ &nbsp;
1043
+ // Notify deletion handlers when ready
1044
+ // This effect intentionally runs when any handler/state changes
1045
+ // to keep the consumer updated with the latest values
1046
+ React.useEffect(() =&gt; {
1047
+ if (onDeletionHandlersReady) {
1048
+ onDeletionHandlersReady({
1049
+ commitDeletions,
1050
+ restorePendingDeletions,
1051
+ hasPendingDeletions,
1052
+ markAsSubmitted,
1053
+ isValid,
1054
+ isUploading,
1055
+ waitForUploads,
1056
+ getCompletedFilePaths,
1057
+ });
1058
+ }
1059
+ }, [
1060
+ onDeletionHandlersReady,
1061
+ commitDeletions,
1062
+ restorePendingDeletions,
1063
+ hasPendingDeletions,
1064
+ markAsSubmitted,
1065
+ isValid,
1066
+ isUploading,
1067
+ waitForUploads,
1068
+ getCompletedFilePaths,
1069
+ ]);
1070
+ &nbsp;
1071
+ // Use extracted drag &amp; drop hook
1072
+ const { isDragging, handleDragOver, handleDragLeave, handleDrop } = useDragDrop({
1073
+ disabled,
1074
+ onFilesDropped: addFiles,
1075
+ onInteraction: markAsTouched,
1076
+ });
1077
+ &nbsp;
1078
+ // Use extracted delete confirmation hook
1079
+ const deleteConfirmation = useDeleteConfirmation({
1080
+ deleteFileImmediately,
1081
+ });
1082
+ &nbsp;
1083
+ /**
1084
+ * Handles file selection from input
1085
+ */
1086
+ const handleFileSelect = useCallback(
1087
+ (event: React.ChangeEvent&lt;HTMLInputElement&gt;) =&gt; {
1088
+ markAsTouched();
1089
+ const selectedFiles = event.target.files;
1090
+ if (selectedFiles &amp;&amp; selectedFiles.length &gt; 0) {
1091
+ addFiles(selectedFiles);
1092
+ }
1093
+ // Reset input to allow selecting the same file
1094
+ if (inputRef.current) {
1095
+ inputRef.current.value = "";
1096
+ }
1097
+ },
1098
+ [addFiles, markAsTouched],
1099
+ );
1100
+ &nbsp;
1101
+ /**
1102
+ * Opens file selector
1103
+ * Note: We don't call markAsTouched() here to avoid showing errors prematurely
1104
+ * Errors should only show after user interaction with files or form submission
1105
+ */
1106
+ const handleClick = useCallback(() =&gt; {
1107
+ <span class="cstat-no" title="statement not covered" > if (!disabled) {</span>
1108
+ <span class="cstat-no" title="statement not covered" > inputRef.current?.click();</span>
1109
+ <span class="cstat-no" title="statement not covered" > }</span>
1110
+ }, [disabled]);
1111
+ &nbsp;
1112
+ /**
1113
+ * Handle remove click - shows confirmation for immediate deletions
1114
+ * or marks as pendingDeletion for existing files in edit mode
1115
+ */
1116
+ const handleRemoveClick = useCallback(
1117
+ async (fileId: string) =&gt; {
1118
+ const result = await removeFile(fileId);
1119
+ &nbsp;
1120
+ if (result.needsConfirmation) {
1121
+ // Show confirmation dialog
1122
+ deleteConfirmation.openConfirmation(fileId);
1123
+ }
1124
+ // If no confirmation needed, file was marked as pendingDeletion
1125
+ },
1126
+ [removeFile, deleteConfirmation],
1127
+ );
1128
+ &nbsp;
1129
+ /**
1130
+ * Generates accept string for input
1131
+ */
1132
+ const acceptString = accept?.join(",") || "";
1133
+ &nbsp;
1134
+ /**
1135
+ * Determines whether to show drop zone
1136
+ * Don't show when disabled (readonly mode only shows file list)
1137
+ * Use activeFileCount to allow uploading when files are pending deletion
1138
+ */
1139
+ const showDropZone = !disabled &amp;&amp; (multiple || activeFileCount === 0);
1140
+ &nbsp;
1141
+ /**
1142
+ * Determines final error text
1143
+ * - External errors always show
1144
+ * - Internal validation errors only show after form submission (isSubmitted)
1145
+ * - NOT when just clicking the dropzone (isTouched)
1146
+ */
1147
+ const showInternalValidationError = <span class="branch-0 cbranch-no" title="branch not covered" >isSubmitted &amp;&amp; !isValid;</span>
1148
+ const hasError = externalError || showInternalValidationError;
1149
+ const finalHelperText =
1150
+ externalHelperText || (<span class="branch-0 cbranch-no" title="branch not covered" >showInternalValidationError &amp;&amp; <span class="branch-0 cbranch-no" title="branch not covered" >validationErrorKey ? t</span>(validationErrorKey, validationErrorParams) : n</span>ull);
1151
+ &nbsp;
1152
+ /**
1153
+ * Generates placeholder text
1154
+ */
1155
+ const getPlaceholderText = (): string =&gt; {
1156
+ if (placeholder) return placeholder;
1157
+ &nbsp;
1158
+ if (isDragging) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1159
+ <span class="cstat-no" title="statement not covered" > return t("base.file.dropHere");</span>
1160
+ <span class="cstat-no" title="statement not covered" > }</span>
1161
+ &nbsp;
1162
+ return t("base.file.dragOrClick");
1163
+ };
1164
+ &nbsp;
1165
+ return (
1166
+ &lt;Box sx={{ width: "100%" }}&gt;
1167
+ {/* Label */}
1168
+ {label &amp;&amp; (
1169
+ &lt;Typography
1170
+ variant="body2"
1171
+ sx={{
1172
+ mb: 1,
1173
+ fontWeight: 500,
1174
+ color: hasError ? "error.main" : "text.primary",
1175
+ }}
1176
+ &gt;
1177
+ {label}
1178
+ {required &amp;&amp; &lt;span style={{ color: "red" }}&gt; *&lt;/span&gt;}
1179
+ &lt;/Typography&gt;
1180
+ )}
1181
+ &nbsp;
1182
+ {/* Hidden input */}
1183
+ &lt;input
1184
+ ref={inputRef}
1185
+ type="file"
1186
+ accept={acceptString}
1187
+ multiple={multiple}
1188
+ onChange={handleFileSelect}
1189
+ disabled={disabled}
1190
+ style={{ display: "none" }}
1191
+ /&gt;
1192
+ &nbsp;
1193
+ {/* Drop Zone */}
1194
+ {showDropZone &amp;&amp; (
1195
+ &lt;DropZone
1196
+ isDragging={isDragging}
1197
+ disabled={disabled}
1198
+ hasError={hasError}
1199
+ placeholder={getPlaceholderText()}
1200
+ accept={accept}
1201
+ onClick={handleClick}
1202
+ onDragOver={handleDragOver}
1203
+ onDragLeave={handleDragLeave}
1204
+ onDrop={handleDrop}
1205
+ /&gt;
1206
+ )}
1207
+ &nbsp;
1208
+ {/* File list with thumbnails - works in all modes (edit and readonly) */}
1209
+ {showFileList &amp;&amp; files.length &gt; 0 &amp;&amp; (
1210
+ &lt;List dense sx={{ mt: 1, p: 0 }}&gt;
1211
+ {files.map((file) =&gt; (
1212
+ &lt;FileItemRow
1213
+ key={file.id}
1214
+ file={file}
1215
+ baseUrl={baseUrl}
1216
+ disabled={disabled}
1217
+ onRemove={handleRemoveClick}
1218
+ onRestore={restoreFile}
1219
+ onRetry={retryUpload}
1220
+ /&gt;
1221
+ ))}
1222
+ &lt;/List&gt;
1223
+ )}
1224
+ &nbsp;
1225
+ {/* Upload progress indicator */}
1226
+ {isUploading &amp;&amp; (
1227
+ &lt;Box sx={{ display: "flex", alignItems: "center", gap: 1, mt: 1 }}&gt;
1228
+ &lt;CircularProgress size={16} /&gt;
1229
+ &lt;Typography variant="caption" color="text.secondary"&gt;
1230
+ {t("base.file.uploading")}
1231
+ &lt;/Typography&gt;
1232
+ &lt;/Box&gt;
1233
+ )}
1234
+ &nbsp;
1235
+ {/* Helper text / Error - renders HTML safely for formatting like &lt;b&gt; tags */}
1236
+ {finalHelperText &amp;&amp; (
1237
+ &lt;FormHelperText error={hasError} sx={{ mt: 0.5 }} dangerouslySetInnerHTML={{ __html: sanitizeHelperTextHtml(finalHelperText) }} /&gt;
1238
+ )}
1239
+ &nbsp;
1240
+ {/* Delete confirmation dialog */}
1241
+ &lt;DeleteConfirmationDialog
1242
+ open={deleteConfirmation.isOpen}
1243
+ isDeleting={deleteConfirmation.isDeleting}
1244
+ onConfirm={deleteConfirmation.handleConfirm}
1245
+ onCancel={deleteConfirmation.handleCancel}
1246
+ title={t("base.file.confirmDelete.title")}
1247
+ message={t("base.file.confirmDelete.message")}
1248
+ cancelText={t("base.file.confirmDelete.cancel")}
1249
+ confirmText={t("base.file.confirmDelete.confirm")}
1250
+ deletingText={t("base.file.deleting")}
1251
+ /&gt;
1252
+ &lt;/Box&gt;
1253
+ );
1254
+ };
1255
+ &nbsp;
1256
+ export default CrudiaFileField;
1257
+ &nbsp;</pre></td></tr></table></pre>
1258
+
1259
+ <div class='push'></div><!-- for sticky footer -->
1260
+ </div><!-- /wrapper -->
1261
+ <div class='footer quiet pad2 space-top1 center small'>
1262
+ Code coverage generated by
1263
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1264
+ at 2026-01-28T06:22:15.683Z
1265
+ </div>
1266
+ <script src="../../prettify.js"></script>
1267
+ <script>
1268
+ window.onload = function () {
1269
+ prettyPrint();
1270
+ };
1271
+ </script>
1272
+ <script src="../../sorter.js"></script>
1273
+ <script src="../../block-navigation.js"></script>
1274
+ </body>
1275
+ </html>
1276
+