react-input-material 0.0.433 → 0.0.435
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/FileInput.js +1 -1
- package/components/FileInput.styles.css +3 -3
- package/components/GenericAnimate.d.ts +5 -3
- package/components/GenericAnimate.js +1 -1
- package/components/GenericInput.js +1 -1
- package/components/GenericInput.styles.css +1 -1
- package/components/Inputs.js +1 -1
- package/components/Inputs.styles.css +2 -2
- package/components/Interval.js +1 -1
- package/components/Interval.styles.css +2 -2
- package/components/RequireableCheckbox.styles.css +1 -1
- package/index.js +1 -1
- package/index.styles.css +6 -6
- package/package.json +4 -2
- package/type.d.ts +5 -0
- package/components/Dummy.tsx +0 -58
- package/components/FileInput.tsx +0 -1010
- package/components/GenericAnimate.tsx +0 -88
- package/components/GenericInput.tsx +0 -2875
- package/components/Inputs.tsx +0 -585
- package/components/Interval.tsx +0 -436
- package/components/RequireableCheckbox.tsx +0 -520
- package/components/WrapConfigurations.tsx +0 -127
- package/components/WrapStrict.tsx +0 -43
- package/components/WrapThemeProvider.tsx +0 -48
- package/components/WrapTooltip.tsx +0 -67
package/components/FileInput.tsx
DELETED
|
@@ -1,1010 +0,0 @@
|
|
|
1
|
-
// #!/usr/bin/env babel-node
|
|
2
|
-
// -*- coding: utf-8 -*-
|
|
3
|
-
/** @module FileInput */
|
|
4
|
-
'use strict'
|
|
5
|
-
/* !
|
|
6
|
-
region header
|
|
7
|
-
[Project page](https://torben.website/react-material-input)
|
|
8
|
-
|
|
9
|
-
Copyright Torben Sickert (info["~at~"]torben.website) 16.12.2012
|
|
10
|
-
|
|
11
|
-
License
|
|
12
|
-
-------
|
|
13
|
-
|
|
14
|
-
This library written by Torben Sickert stand under a creative commons
|
|
15
|
-
naming 3.0 unported license.
|
|
16
|
-
See https://creativecommons.org/licenses/by/3.0/deed.de
|
|
17
|
-
endregion
|
|
18
|
-
*/
|
|
19
|
-
// region imports
|
|
20
|
-
import {blobToBase64String, dataURLToBlob} from 'blob-util'
|
|
21
|
-
import Tools from 'clientnode'
|
|
22
|
-
import {Mapping} from 'clientnode/type'
|
|
23
|
-
import {
|
|
24
|
-
FocusEvent as ReactFocusEvent,
|
|
25
|
-
ForwardedRef,
|
|
26
|
-
forwardRef,
|
|
27
|
-
memo as memorize,
|
|
28
|
-
MouseEvent as ReactMouseEvent,
|
|
29
|
-
MutableRefObject,
|
|
30
|
-
ReactElement,
|
|
31
|
-
SyntheticEvent,
|
|
32
|
-
useEffect,
|
|
33
|
-
useImperativeHandle,
|
|
34
|
-
useRef,
|
|
35
|
-
useState
|
|
36
|
-
} from 'react'
|
|
37
|
-
import {
|
|
38
|
-
Card,
|
|
39
|
-
CardActionButton,
|
|
40
|
-
CardActionButtons,
|
|
41
|
-
CardActions,
|
|
42
|
-
CardMedia,
|
|
43
|
-
CardPrimaryAction
|
|
44
|
-
} from '@rmwc/card'
|
|
45
|
-
import {CircularProgress} from '@rmwc/circular-progress'
|
|
46
|
-
import {Theme} from '@rmwc/theme'
|
|
47
|
-
import {Typography} from '@rmwc/typography'
|
|
48
|
-
|
|
49
|
-
/*
|
|
50
|
-
"namedExport" version of css-loader:
|
|
51
|
-
|
|
52
|
-
import {
|
|
53
|
-
fileInputClassName,
|
|
54
|
-
fileInputDownloadClassName,
|
|
55
|
-
fileInputIframeWrapperPaddingClassName,
|
|
56
|
-
fileInputNativeClassName,
|
|
57
|
-
fileInputTextRepresentationClassName
|
|
58
|
-
} from './FileInput.module'
|
|
59
|
-
*/
|
|
60
|
-
import cssClassNames from './FileInput.module'
|
|
61
|
-
import GenericInput from './GenericInput'
|
|
62
|
-
import {WrapConfigurations} from './WrapConfigurations'
|
|
63
|
-
import {
|
|
64
|
-
deriveMissingPropertiesFromState,
|
|
65
|
-
determineInitialValue,
|
|
66
|
-
determineValidationState as determineBaseValidationState,
|
|
67
|
-
getConsolidatedProperties as getBaseConsolidatedProperties,
|
|
68
|
-
mapPropertiesIntoModel,
|
|
69
|
-
translateKnownSymbols,
|
|
70
|
-
triggerCallbackIfExists,
|
|
71
|
-
wrapStateSetter
|
|
72
|
-
} from '../helper'
|
|
73
|
-
import {
|
|
74
|
-
defaultFileInputModelState as defaultModelState,
|
|
75
|
-
DefaultFileInputProperties as DefaultProperties,
|
|
76
|
-
defaultFileInputProperties as defaultProperties,
|
|
77
|
-
defaultFileNameInputProperties,
|
|
78
|
-
FileInputAdapter as Adapter,
|
|
79
|
-
FileInputModelState as ModelState,
|
|
80
|
-
FileInputProperties as Properties,
|
|
81
|
-
FileInputProps as Props,
|
|
82
|
-
FileValue,
|
|
83
|
-
FileInputValueState as ValueState,
|
|
84
|
-
fileInputPropertyTypes as propertyTypes,
|
|
85
|
-
InputAdapter,
|
|
86
|
-
InputProperties,
|
|
87
|
-
InputProps,
|
|
88
|
-
FileRepresentationType as RepresentationType,
|
|
89
|
-
FileInputComponent
|
|
90
|
-
} from '../type'
|
|
91
|
-
// endregion
|
|
92
|
-
// region constants
|
|
93
|
-
const CSS_CLASS_NAMES:Mapping = cssClassNames as Mapping
|
|
94
|
-
/*
|
|
95
|
-
NOTE: Caused by a bug transpiling regular expression which ignores needed
|
|
96
|
-
escape sequences for "/" when using the nativ regular expression type.
|
|
97
|
-
*/
|
|
98
|
-
const IMAGE_CONTENT_TYPE_REGULAR_EXPRESSION = new RegExp(
|
|
99
|
-
'^image\\/(?:p?jpe?g|png|svg(?:\\+xml)?|vnd\\.microsoft\\.icon|gif|tiff|' +
|
|
100
|
-
'webp|vnd\\.wap\\.wbmp|x-(?:icon|jng|ms-bmp))$',
|
|
101
|
-
'i'
|
|
102
|
-
)
|
|
103
|
-
const TEXT_CONTENT_TYPE_REGULAR_EXPRESSION = new RegExp(
|
|
104
|
-
'^(?:application\\/xml)|(?:text\\/(?:plain|x-ndpb[wy]html|(?:x-)?csv' +
|
|
105
|
-
'|x?html?|xml))$',
|
|
106
|
-
'i'
|
|
107
|
-
)
|
|
108
|
-
const REPRESENTABLE_TEXT_CONTENT_TYPE_REGULAR_EXPRESSION =
|
|
109
|
-
// Plain version:
|
|
110
|
-
/^text\/plain$/i
|
|
111
|
-
// Rendered version:
|
|
112
|
-
// /^(application\/xml)|(text\/(plain|x?html?|xml))$/i
|
|
113
|
-
const VIDEO_CONTENT_TYPE_REGULAR_EXPRESSION = new RegExp(
|
|
114
|
-
'^video\\/(?:(?:x-)?(?:x-)?webm|3gpp|mp2t|mp4|mpeg|quicktime|(?:x-)?flv' +
|
|
115
|
-
'|(?:x-)?m4v|(?:x-)mng|x-ms-as|x-ms-wmv|x-msvideo)' +
|
|
116
|
-
'|(?:application\\/(?:x-)?shockwave-flash)$',
|
|
117
|
-
'i'
|
|
118
|
-
)
|
|
119
|
-
// endregion
|
|
120
|
-
// region helper
|
|
121
|
-
export const preserveStaticFileBaseNameInputGenerator:Properties[
|
|
122
|
-
'generateFileNameInputProperties'
|
|
123
|
-
] = (
|
|
124
|
-
prototype:InputProps<string>, {name, value: {name: fileName}}
|
|
125
|
-
):InputProps<string> => ({
|
|
126
|
-
...prototype,
|
|
127
|
-
disabled: true,
|
|
128
|
-
value:
|
|
129
|
-
name +
|
|
130
|
-
(fileName?.includes('.') ?
|
|
131
|
-
fileName.substring(fileName.lastIndexOf('.')) :
|
|
132
|
-
''
|
|
133
|
-
)
|
|
134
|
-
})
|
|
135
|
-
/**
|
|
136
|
-
* Determines which type of file we have to present.
|
|
137
|
-
* @param contentType - File type to derive representation type from.
|
|
138
|
-
* @returns Nothing.
|
|
139
|
-
*/
|
|
140
|
-
export const determineRepresentationType = (
|
|
141
|
-
contentType:string
|
|
142
|
-
):RepresentationType => {
|
|
143
|
-
contentType = contentType.replace(/; *charset=.+$/, '')
|
|
144
|
-
|
|
145
|
-
if (TEXT_CONTENT_TYPE_REGULAR_EXPRESSION.test(contentType)) {
|
|
146
|
-
if (REPRESENTABLE_TEXT_CONTENT_TYPE_REGULAR_EXPRESSION.test(
|
|
147
|
-
contentType
|
|
148
|
-
))
|
|
149
|
-
return 'renderableText'
|
|
150
|
-
|
|
151
|
-
return 'text'
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (IMAGE_CONTENT_TYPE_REGULAR_EXPRESSION.test(contentType))
|
|
155
|
-
return 'image'
|
|
156
|
-
|
|
157
|
-
if (VIDEO_CONTENT_TYPE_REGULAR_EXPRESSION.test(contentType))
|
|
158
|
-
return 'video'
|
|
159
|
-
|
|
160
|
-
return 'binary'
|
|
161
|
-
}
|
|
162
|
-
export const determineValidationState = <P extends DefaultProperties>(
|
|
163
|
-
properties:P, invalidName:boolean, currentState:ModelState
|
|
164
|
-
):boolean => determineBaseValidationState<P>(
|
|
165
|
-
properties,
|
|
166
|
-
currentState,
|
|
167
|
-
{
|
|
168
|
-
invalidMaximumSize: ():boolean => (
|
|
169
|
-
typeof properties.model.maximumSize === 'number' &&
|
|
170
|
-
properties.model.maximumSize <
|
|
171
|
-
(properties.model.value?.blob?.size || 0)
|
|
172
|
-
),
|
|
173
|
-
invalidMinimumSize: ():boolean => (
|
|
174
|
-
typeof properties.model.minimumSize === 'number' &&
|
|
175
|
-
properties.model.minimumSize >
|
|
176
|
-
(properties.model.value?.blob?.size || 0)
|
|
177
|
-
),
|
|
178
|
-
invalidName: ():boolean => invalidName,
|
|
179
|
-
invalidContentTypePattern: ():boolean => (
|
|
180
|
-
typeof properties.model.value?.blob?.type === 'string' &&
|
|
181
|
-
([] as Array<null|RegExp|string>)
|
|
182
|
-
.concat(properties.model.contentTypeRegularExpressionPattern)
|
|
183
|
-
.some((expression:null|RegExp|string):boolean =>
|
|
184
|
-
typeof expression === 'string' &&
|
|
185
|
-
!(new RegExp(expression))
|
|
186
|
-
.test(properties.model.value!.blob!.type!) ||
|
|
187
|
-
expression !== null &&
|
|
188
|
-
typeof expression === 'object' &&
|
|
189
|
-
!expression.test(properties.model.value!.blob!.type!)
|
|
190
|
-
)
|
|
191
|
-
),
|
|
192
|
-
invalidInvertedContentTypePattern: ():boolean => (
|
|
193
|
-
typeof properties.model.value?.blob?.type === 'string' &&
|
|
194
|
-
([] as Array<null|RegExp|string>)
|
|
195
|
-
.concat(
|
|
196
|
-
properties.model
|
|
197
|
-
.invertedContentTypeRegularExpressionPattern
|
|
198
|
-
)
|
|
199
|
-
.some((expression:null|RegExp|string):boolean =>
|
|
200
|
-
typeof expression === 'string' &&
|
|
201
|
-
(new RegExp(expression))
|
|
202
|
-
.test(properties.model.value!.blob!.type!) ||
|
|
203
|
-
expression !== null &&
|
|
204
|
-
typeof expression === 'object' &&
|
|
205
|
-
expression.test(properties.model.value!.blob!.type!)
|
|
206
|
-
)
|
|
207
|
-
)
|
|
208
|
-
}
|
|
209
|
-
)
|
|
210
|
-
export const readBinaryDataIntoText = (
|
|
211
|
-
blob:Blob, encoding = 'utf-8'
|
|
212
|
-
):Promise<string> =>
|
|
213
|
-
new Promise<string>((
|
|
214
|
-
resolve:(_value:string) => void, reject:(_reason:Error) => void
|
|
215
|
-
):void => {
|
|
216
|
-
const fileReader:FileReader = new FileReader()
|
|
217
|
-
|
|
218
|
-
fileReader.onload = (event:Event):void => {
|
|
219
|
-
let content:string =
|
|
220
|
-
(event.target as unknown as {result:string}).result
|
|
221
|
-
// Remove preceding BOM.
|
|
222
|
-
if (
|
|
223
|
-
content.length &&
|
|
224
|
-
encoding.endsWith('-sig') &&
|
|
225
|
-
content.charCodeAt(0) === 0xFEFF
|
|
226
|
-
)
|
|
227
|
-
content = content.slice(1)
|
|
228
|
-
// Normalize line endings to unix format.
|
|
229
|
-
content = content.replace(/\r\n/g, '\n')
|
|
230
|
-
resolve(content)
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
fileReader.onabort = ():void => reject(new Error('abort'))
|
|
234
|
-
fileReader.onerror = ():void => reject(new Error())
|
|
235
|
-
|
|
236
|
-
fileReader.readAsText(
|
|
237
|
-
blob,
|
|
238
|
-
encoding.endsWith('-sig') ?
|
|
239
|
-
encoding.substring(0, encoding.length - '-sig'.length) :
|
|
240
|
-
encoding
|
|
241
|
-
)
|
|
242
|
-
})
|
|
243
|
-
// endregion
|
|
244
|
-
/* eslint-disable jsdoc/require-description-complete-sentence */
|
|
245
|
-
/**
|
|
246
|
-
* Validateable checkbox wrapper component.
|
|
247
|
-
* @property static:displayName - Descriptive name for component to show in web
|
|
248
|
-
* developer tools.
|
|
249
|
-
*
|
|
250
|
-
* Dataflow:
|
|
251
|
-
*
|
|
252
|
-
* 1. On-Render all states are merged with given properties into a normalized
|
|
253
|
-
* property object.
|
|
254
|
-
* 2. Properties, corresponding state values and sub node instances are saved
|
|
255
|
-
* into a "ref" object (to make them accessible from the outside e.g. for
|
|
256
|
-
* wrapper like web-components).
|
|
257
|
-
* 3. Event handler saves corresponding data modifications into state and
|
|
258
|
-
* normalized properties object.
|
|
259
|
-
* 4. All state changes except selection changes trigger an "onChange" event
|
|
260
|
-
* which delivers the consolidated properties object (with latest
|
|
261
|
-
* modifications included).
|
|
262
|
-
*
|
|
263
|
-
* @property static:displayName - Descriptive name for component to show in web
|
|
264
|
-
* developer tools.
|
|
265
|
-
*
|
|
266
|
-
* @param props - Given components properties.
|
|
267
|
-
* @param reference - Reference object to forward internal state.
|
|
268
|
-
*
|
|
269
|
-
* @returns React elements.
|
|
270
|
-
*/
|
|
271
|
-
export const FileInputInner = function(
|
|
272
|
-
props:Props, reference?:ForwardedRef<Adapter>
|
|
273
|
-
):ReactElement {
|
|
274
|
-
// region property aggregation
|
|
275
|
-
/**
|
|
276
|
-
* Calculate external properties (a set of all configurable properties).
|
|
277
|
-
* @param properties - Properties to merge.
|
|
278
|
-
*
|
|
279
|
-
* @returns External properties object.
|
|
280
|
-
*/
|
|
281
|
-
const getConsolidatedProperties = (properties:Props):Properties => {
|
|
282
|
-
const result:DefaultProperties =
|
|
283
|
-
mapPropertiesIntoModel<Props, DefaultProperties>(
|
|
284
|
-
properties, FileInput.defaultProperties.model
|
|
285
|
-
)
|
|
286
|
-
|
|
287
|
-
determineValidationState(
|
|
288
|
-
result,
|
|
289
|
-
// TODO not available
|
|
290
|
-
false
|
|
291
|
-
/*
|
|
292
|
-
nameInputReference.current?.properties.invalid ??
|
|
293
|
-
result.fileNameInputProperties.invalid ??
|
|
294
|
-
result.model.fileName.invalid ??
|
|
295
|
-
result.model!.state.invalidName
|
|
296
|
-
*/,
|
|
297
|
-
result.model.state
|
|
298
|
-
)
|
|
299
|
-
|
|
300
|
-
return getBaseConsolidatedProperties<Props, Properties>(result)
|
|
301
|
-
}
|
|
302
|
-
// endregion
|
|
303
|
-
// region event handler
|
|
304
|
-
/**
|
|
305
|
-
* Triggered on blur events.
|
|
306
|
-
* @param event - Event object.
|
|
307
|
-
*
|
|
308
|
-
* @returns Nothing.
|
|
309
|
-
*/
|
|
310
|
-
const onBlur = (event:SyntheticEvent):void => setValueState((
|
|
311
|
-
oldValueState:ValueState
|
|
312
|
-
):ValueState => {
|
|
313
|
-
let changed = false
|
|
314
|
-
|
|
315
|
-
if (oldValueState.modelState.focused) {
|
|
316
|
-
properties.focused = false
|
|
317
|
-
changed = true
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (!oldValueState.modelState.visited) {
|
|
321
|
-
properties.visited = true
|
|
322
|
-
changed = true
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (changed) {
|
|
326
|
-
onChange(event)
|
|
327
|
-
|
|
328
|
-
triggerCallbackIfExists<Properties>(
|
|
329
|
-
properties,
|
|
330
|
-
'changeState',
|
|
331
|
-
controlled,
|
|
332
|
-
properties.model.state,
|
|
333
|
-
event,
|
|
334
|
-
properties
|
|
335
|
-
)
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
triggerCallbackIfExists<Properties>(
|
|
339
|
-
properties, 'blur', controlled, event, properties
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
return changed ?
|
|
343
|
-
{...oldValueState, modelState: properties.model.state} :
|
|
344
|
-
oldValueState
|
|
345
|
-
})
|
|
346
|
-
/**
|
|
347
|
-
* Triggered on any change events. Consolidates properties object and
|
|
348
|
-
* triggers given on change callbacks.
|
|
349
|
-
* @param event - Potential event object.
|
|
350
|
-
*
|
|
351
|
-
* @returns Nothing.
|
|
352
|
-
*/
|
|
353
|
-
const onChange = (event?:SyntheticEvent):void => {
|
|
354
|
-
if (nameInputReference.current?.properties)
|
|
355
|
-
properties.model.fileName =
|
|
356
|
-
nameInputReference.current.properties.model
|
|
357
|
-
|
|
358
|
-
const consolidatedProperties:Properties = getConsolidatedProperties(
|
|
359
|
-
/*
|
|
360
|
-
Workaround since "Type" isn't identified as subset of
|
|
361
|
-
"RecursivePartial<Type>" yet.
|
|
362
|
-
*/
|
|
363
|
-
properties as unknown as Props
|
|
364
|
-
)
|
|
365
|
-
// NOTE: Avoid recursive merging of deprecated value properties.
|
|
366
|
-
delete properties.model.value
|
|
367
|
-
delete properties.value
|
|
368
|
-
// NOTE: Avoid trying to write into a readonly object.
|
|
369
|
-
properties.styles = Tools.copy(properties.styles)
|
|
370
|
-
|
|
371
|
-
Tools.extend(true, properties, consolidatedProperties)
|
|
372
|
-
|
|
373
|
-
triggerCallbackIfExists<Properties>(
|
|
374
|
-
properties, 'change', controlled, properties, event
|
|
375
|
-
)
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Triggered when ever the value changes.
|
|
379
|
-
* @param eventSourceOrName - Event object or new value.
|
|
380
|
-
* @param event - Optional event object (if not provided as first
|
|
381
|
-
* argument).
|
|
382
|
-
* @param inputProperties - Current properties state.
|
|
383
|
-
* @param attachBlobProperty - Indicates whether additional data is added
|
|
384
|
-
* through post processed data properties.
|
|
385
|
-
*
|
|
386
|
-
* @returns Nothing.
|
|
387
|
-
*/
|
|
388
|
-
const onChangeValue = (
|
|
389
|
-
eventSourceOrName:FileValue|null|string|SyntheticEvent,
|
|
390
|
-
event?:SyntheticEvent|undefined,
|
|
391
|
-
inputProperties?:InputProperties<string>|undefined,
|
|
392
|
-
attachBlobProperty = false
|
|
393
|
-
):void => {
|
|
394
|
-
if (!(properties.model.mutable && properties.model.writable))
|
|
395
|
-
return
|
|
396
|
-
|
|
397
|
-
if (
|
|
398
|
-
eventSourceOrName &&
|
|
399
|
-
fileInputReference.current &&
|
|
400
|
-
(eventSourceOrName as SyntheticEvent).target ===
|
|
401
|
-
fileInputReference.current
|
|
402
|
-
) {
|
|
403
|
-
event = eventSourceOrName as SyntheticEvent
|
|
404
|
-
|
|
405
|
-
if ((event.target as unknown as {files:FileList}).files?.length) {
|
|
406
|
-
const blob:File =
|
|
407
|
-
(event.target as unknown as {files:FileList}).files[0]
|
|
408
|
-
|
|
409
|
-
properties.value = {blob, name: blob.name}
|
|
410
|
-
|
|
411
|
-
properties.value.name =
|
|
412
|
-
properties.generateFileNameInputProperties(
|
|
413
|
-
{
|
|
414
|
-
disabled: properties.disabled,
|
|
415
|
-
value: blob.name,
|
|
416
|
-
...defaultFileNameInputProperties,
|
|
417
|
-
model: properties.model.fileName,
|
|
418
|
-
onChangeValue,
|
|
419
|
-
default: properties.value.name
|
|
420
|
-
},
|
|
421
|
-
properties as
|
|
422
|
-
Omit<Properties, 'value'> &
|
|
423
|
-
{value:FileValue & {name:string}}
|
|
424
|
-
)?.value ||
|
|
425
|
-
blob.name
|
|
426
|
-
} else
|
|
427
|
-
return
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
setValueState((oldValueState:ValueState):ValueState => {
|
|
431
|
-
if (eventSourceOrName === null)
|
|
432
|
-
properties.value = eventSourceOrName
|
|
433
|
-
else if (typeof eventSourceOrName === 'string')
|
|
434
|
-
/*
|
|
435
|
-
NOTE: A name can only be changed if a blob is available
|
|
436
|
-
beforehand.
|
|
437
|
-
*/
|
|
438
|
-
properties.value = {
|
|
439
|
-
...oldValueState.value, name: eventSourceOrName
|
|
440
|
-
}
|
|
441
|
-
else if (
|
|
442
|
-
typeof (eventSourceOrName as FileValue).source === 'string' ||
|
|
443
|
-
typeof (eventSourceOrName as FileValue).url === 'string'
|
|
444
|
-
)
|
|
445
|
-
if (attachBlobProperty)
|
|
446
|
-
properties.value = {
|
|
447
|
-
...oldValueState.value, ...eventSourceOrName
|
|
448
|
-
}
|
|
449
|
-
else
|
|
450
|
-
properties.value = eventSourceOrName as FileValue
|
|
451
|
-
|
|
452
|
-
if (Tools.equals(oldValueState.value, properties.value))
|
|
453
|
-
return oldValueState
|
|
454
|
-
|
|
455
|
-
let stateChanged = false
|
|
456
|
-
|
|
457
|
-
const result:ValueState = {
|
|
458
|
-
...oldValueState, value: properties.value as FileValue|null
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
if (oldValueState.modelState.pristine) {
|
|
462
|
-
properties.dirty = true
|
|
463
|
-
properties.pristine = false
|
|
464
|
-
stateChanged = true
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
onChange(event)
|
|
468
|
-
|
|
469
|
-
if (determineValidationState(
|
|
470
|
-
properties as unknown as DefaultProperties,
|
|
471
|
-
nameInputReference.current?.properties?.invalid || false,
|
|
472
|
-
oldValueState.modelState
|
|
473
|
-
))
|
|
474
|
-
stateChanged = true
|
|
475
|
-
|
|
476
|
-
triggerCallbackIfExists<Properties>(
|
|
477
|
-
properties,
|
|
478
|
-
'changeValue',
|
|
479
|
-
controlled,
|
|
480
|
-
properties.value,
|
|
481
|
-
event,
|
|
482
|
-
properties
|
|
483
|
-
)
|
|
484
|
-
|
|
485
|
-
if (stateChanged) {
|
|
486
|
-
result.modelState = properties.model.state
|
|
487
|
-
|
|
488
|
-
triggerCallbackIfExists<Properties>(
|
|
489
|
-
properties,
|
|
490
|
-
'changeState',
|
|
491
|
-
controlled,
|
|
492
|
-
properties.model.state,
|
|
493
|
-
event,
|
|
494
|
-
properties
|
|
495
|
-
)
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
if (attachBlobProperty)
|
|
500
|
-
result.attachBlobProperty = true
|
|
501
|
-
|
|
502
|
-
return result
|
|
503
|
-
})
|
|
504
|
-
}
|
|
505
|
-
/**
|
|
506
|
-
* Triggered on click events.
|
|
507
|
-
* @param event - Mouse event object.
|
|
508
|
-
*
|
|
509
|
-
* @returns Nothing.
|
|
510
|
-
*/
|
|
511
|
-
const onClick = (event:ReactMouseEvent):void => {
|
|
512
|
-
triggerCallbackIfExists<Properties>(
|
|
513
|
-
properties, 'click', controlled, event, properties
|
|
514
|
-
)
|
|
515
|
-
|
|
516
|
-
onTouch(event)
|
|
517
|
-
}
|
|
518
|
-
/**
|
|
519
|
-
* Triggered on focus events.
|
|
520
|
-
* @param event - Focus event object.
|
|
521
|
-
*
|
|
522
|
-
* @returns Nothing.
|
|
523
|
-
*/
|
|
524
|
-
const onFocus = (event:ReactFocusEvent):void => {
|
|
525
|
-
triggerCallbackIfExists<Properties>(
|
|
526
|
-
properties, 'focus', controlled, event, properties
|
|
527
|
-
)
|
|
528
|
-
|
|
529
|
-
onTouch(event)
|
|
530
|
-
}
|
|
531
|
-
/**
|
|
532
|
-
* Triggers on start interacting with the input.
|
|
533
|
-
* @param event - Event object which triggered interaction.
|
|
534
|
-
*
|
|
535
|
-
* @returns Nothing.
|
|
536
|
-
*/
|
|
537
|
-
const onTouch = (event:ReactFocusEvent|ReactMouseEvent):void =>
|
|
538
|
-
setValueState((oldValueState:ValueState):ValueState => {
|
|
539
|
-
let changedState = false
|
|
540
|
-
|
|
541
|
-
if (!oldValueState.modelState.focused) {
|
|
542
|
-
properties.focused = true
|
|
543
|
-
changedState = true
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
if (oldValueState.modelState.untouched) {
|
|
547
|
-
properties.touched = true
|
|
548
|
-
properties.untouched = false
|
|
549
|
-
changedState = true
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
let result:ValueState = oldValueState
|
|
553
|
-
|
|
554
|
-
if (changedState) {
|
|
555
|
-
onChange(event)
|
|
556
|
-
|
|
557
|
-
result = {...oldValueState, modelState: properties.model.state}
|
|
558
|
-
|
|
559
|
-
triggerCallbackIfExists<Properties>(
|
|
560
|
-
properties,
|
|
561
|
-
'changeState',
|
|
562
|
-
controlled,
|
|
563
|
-
properties.model.state,
|
|
564
|
-
event,
|
|
565
|
-
properties
|
|
566
|
-
)
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
triggerCallbackIfExists<Properties>(
|
|
570
|
-
properties, 'touch', controlled, event, properties
|
|
571
|
-
)
|
|
572
|
-
|
|
573
|
-
return result
|
|
574
|
-
})
|
|
575
|
-
// endregion
|
|
576
|
-
// region properties
|
|
577
|
-
/// region references
|
|
578
|
-
const deleteButtonReference:MutableRefObject<HTMLButtonElement|null> =
|
|
579
|
-
useRef<HTMLButtonElement>(null)
|
|
580
|
-
const downloadLinkReference:MutableRefObject<HTMLAnchorElement|null> =
|
|
581
|
-
useRef<HTMLAnchorElement>(null)
|
|
582
|
-
const fileInputReference:MutableRefObject<HTMLInputElement|null> =
|
|
583
|
-
useRef<HTMLInputElement>(null)
|
|
584
|
-
const nameInputReference:MutableRefObject<InputAdapter<string>|null> =
|
|
585
|
-
useRef<InputAdapter<string>>(null)
|
|
586
|
-
const uploadButtonReference:MutableRefObject<HTMLDivElement|null> =
|
|
587
|
-
useRef<HTMLDivElement>(null)
|
|
588
|
-
/// endregion
|
|
589
|
-
const givenProps:Props = translateKnownSymbols(props)
|
|
590
|
-
|
|
591
|
-
const initialValue:FileValue|null = determineInitialValue<FileValue>(
|
|
592
|
-
givenProps, FileInput.defaultProperties.model.default
|
|
593
|
-
)
|
|
594
|
-
/*
|
|
595
|
-
NOTE: Extend default properties with given properties while letting
|
|
596
|
-
default property object untouched for unchanged usage in other
|
|
597
|
-
instances.
|
|
598
|
-
*/
|
|
599
|
-
const givenProperties:Props = Tools.extend(
|
|
600
|
-
true, Tools.copy(FileInput.defaultProperties), givenProps
|
|
601
|
-
)
|
|
602
|
-
/*
|
|
603
|
-
NOTE: This values have to share the same state item since they have to
|
|
604
|
-
be updated in one event loop (set state callback).
|
|
605
|
-
*/
|
|
606
|
-
let [valueState, setValueState] = useState<ValueState>({
|
|
607
|
-
attachBlobProperty: false,
|
|
608
|
-
modelState: {...FileInput.defaultModelState},
|
|
609
|
-
value: initialValue
|
|
610
|
-
})
|
|
611
|
-
|
|
612
|
-
const controlled:boolean =
|
|
613
|
-
!givenProperties.enforceUncontrolled &&
|
|
614
|
-
(
|
|
615
|
-
givenProps.model?.value !== undefined ||
|
|
616
|
-
givenProps.value !== undefined
|
|
617
|
-
) &&
|
|
618
|
-
Boolean(givenProps.onChange || givenProps.onChangeValue)
|
|
619
|
-
|
|
620
|
-
deriveMissingPropertiesFromState(givenProperties, valueState)
|
|
621
|
-
|
|
622
|
-
const properties:Properties = getConsolidatedProperties(givenProperties)
|
|
623
|
-
|
|
624
|
-
/*
|
|
625
|
-
NOTE: We have to merge asynchronous determined missing value properties
|
|
626
|
-
to avoid endless rendering loops when a value is provided via
|
|
627
|
-
properties.
|
|
628
|
-
*/
|
|
629
|
-
if (valueState.attachBlobProperty && valueState.value)
|
|
630
|
-
properties.value =
|
|
631
|
-
Tools.extend<FileValue>(true, valueState.value, properties.value!)
|
|
632
|
-
|
|
633
|
-
/// region synchronize uncontrolled properties into state
|
|
634
|
-
const currentValueState:ValueState = {
|
|
635
|
-
attachBlobProperty: false,
|
|
636
|
-
modelState: properties.model.state,
|
|
637
|
-
value: properties.value as FileValue|null
|
|
638
|
-
}
|
|
639
|
-
/*
|
|
640
|
-
NOTE: If value is controlled only trigger/save state changes when model
|
|
641
|
-
state has changed.
|
|
642
|
-
*/
|
|
643
|
-
if (
|
|
644
|
-
valueState.attachBlobProperty ||
|
|
645
|
-
!(controlled || Tools.equals(properties.value, valueState.value)) ||
|
|
646
|
-
!Tools.equals(properties.model.state, valueState.modelState)
|
|
647
|
-
)
|
|
648
|
-
setValueState(currentValueState)
|
|
649
|
-
if (controlled)
|
|
650
|
-
setValueState =
|
|
651
|
-
wrapStateSetter<ValueState>(setValueState, currentValueState)
|
|
652
|
-
/// endregion
|
|
653
|
-
useImperativeHandle(
|
|
654
|
-
reference,
|
|
655
|
-
():Adapter & {
|
|
656
|
-
references:{
|
|
657
|
-
deleteButtonReference:MutableRefObject<HTMLButtonElement|null>,
|
|
658
|
-
downloadLinkReference:MutableRefObject<HTMLAnchorElement|null>,
|
|
659
|
-
fileInputReference:MutableRefObject<HTMLInputElement|null>,
|
|
660
|
-
nameInputReference:MutableRefObject<InputAdapter<string>|null>,
|
|
661
|
-
uploadButtonReference:MutableRefObject<HTMLDivElement|null>
|
|
662
|
-
}
|
|
663
|
-
} => ({
|
|
664
|
-
properties,
|
|
665
|
-
references: {
|
|
666
|
-
deleteButtonReference,
|
|
667
|
-
downloadLinkReference,
|
|
668
|
-
fileInputReference,
|
|
669
|
-
nameInputReference,
|
|
670
|
-
uploadButtonReference
|
|
671
|
-
},
|
|
672
|
-
state: {
|
|
673
|
-
modelState: properties.model.state,
|
|
674
|
-
...(controlled ? {} : {value: properties.value})
|
|
675
|
-
}
|
|
676
|
-
})
|
|
677
|
-
)
|
|
678
|
-
// endregion
|
|
679
|
-
useEffect(():void => {
|
|
680
|
-
(async ():Promise<void> => {
|
|
681
|
-
let valueChanged:null|Partial<FileValue> = null
|
|
682
|
-
if (
|
|
683
|
-
properties.value?.blob &&
|
|
684
|
-
properties.value.blob instanceof Blob &&
|
|
685
|
-
!properties.value.source
|
|
686
|
-
)
|
|
687
|
-
valueChanged = {
|
|
688
|
-
source: TEXT_CONTENT_TYPE_REGULAR_EXPRESSION.test(
|
|
689
|
-
properties.value.blob.type
|
|
690
|
-
) ?
|
|
691
|
-
await readBinaryDataIntoText(
|
|
692
|
-
properties.value.blob
|
|
693
|
-
) :
|
|
694
|
-
typeof Blob === 'undefined' ?
|
|
695
|
-
(properties.value.toString as
|
|
696
|
-
unknown as
|
|
697
|
-
(_encoding:string) => string
|
|
698
|
-
)('base64') :
|
|
699
|
-
await blobToBase64String(properties.value.blob)
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
if (properties.value?.source) {
|
|
703
|
-
if (!properties.value.blob)
|
|
704
|
-
if (properties.value.url?.startsWith('data:'))
|
|
705
|
-
valueChanged = {
|
|
706
|
-
blob: dataURLToBlob(properties.value.source)
|
|
707
|
-
}
|
|
708
|
-
else if (properties.sourceToBlobOptions)
|
|
709
|
-
valueChanged = {
|
|
710
|
-
blob: new Blob(
|
|
711
|
-
[properties.value.source],
|
|
712
|
-
properties.sourceToBlobOptions
|
|
713
|
-
)
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
if (!properties.value.url && properties.value.blob?.type) {
|
|
717
|
-
const source = TEXT_CONTENT_TYPE_REGULAR_EXPRESSION.test(
|
|
718
|
-
properties.value.blob.type
|
|
719
|
-
) ?
|
|
720
|
-
btoa(properties.value.source) :
|
|
721
|
-
properties.value.source
|
|
722
|
-
|
|
723
|
-
valueChanged = {
|
|
724
|
-
url:
|
|
725
|
-
`data:${properties.value.blob.type};base64,` +
|
|
726
|
-
source
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
if (valueChanged)
|
|
732
|
-
onChangeValue(valueChanged, undefined, undefined, true)
|
|
733
|
-
})()
|
|
734
|
-
.catch(console.error)
|
|
735
|
-
})
|
|
736
|
-
// region render
|
|
737
|
-
const representationType:RepresentationType =
|
|
738
|
-
properties.value?.blob?.type ?
|
|
739
|
-
determineRepresentationType(properties.value.blob.type) :
|
|
740
|
-
'binary'
|
|
741
|
-
const invalid:boolean = (
|
|
742
|
-
properties.invalid &&
|
|
743
|
-
(
|
|
744
|
-
properties.showInitialValidationState ||
|
|
745
|
-
/*
|
|
746
|
-
Material inputs show their validation state at least after a
|
|
747
|
-
blur event so we synchronize error appearances.
|
|
748
|
-
*/
|
|
749
|
-
properties.visited
|
|
750
|
-
)
|
|
751
|
-
)
|
|
752
|
-
|
|
753
|
-
return <WrapConfigurations
|
|
754
|
-
strict={FileInput.strict}
|
|
755
|
-
themeConfiguration={properties.themeConfiguration}
|
|
756
|
-
tooltip={properties.tooltip}
|
|
757
|
-
>
|
|
758
|
-
<Card
|
|
759
|
-
className={
|
|
760
|
-
[CSS_CLASS_NAMES['file-input']]
|
|
761
|
-
.concat(properties.className ?? [])
|
|
762
|
-
.join(' ')
|
|
763
|
-
}
|
|
764
|
-
onBlur={onBlur}
|
|
765
|
-
onClick={onClick}
|
|
766
|
-
onFocus={onFocus}
|
|
767
|
-
style={properties.styles}
|
|
768
|
-
>
|
|
769
|
-
<CardPrimaryAction>
|
|
770
|
-
{properties.value?.url ?
|
|
771
|
-
representationType === 'image' ?
|
|
772
|
-
<CardMedia
|
|
773
|
-
{...properties.media}
|
|
774
|
-
style={{
|
|
775
|
-
backgroundImage: `url(${properties.value.url})`
|
|
776
|
-
}}
|
|
777
|
-
/> :
|
|
778
|
-
representationType === 'video' ?
|
|
779
|
-
<video autoPlay loop muted>
|
|
780
|
-
<source
|
|
781
|
-
src={properties.value.url}
|
|
782
|
-
type={properties.value.blob!.type}
|
|
783
|
-
/>
|
|
784
|
-
</video> :
|
|
785
|
-
representationType === 'renderableText' ?
|
|
786
|
-
<div className={
|
|
787
|
-
[CSS_CLASS_NAMES[
|
|
788
|
-
'file-input__iframe-wrapper'
|
|
789
|
-
]]
|
|
790
|
-
.concat(
|
|
791
|
-
['text/html', 'text/plain']
|
|
792
|
-
.includes(
|
|
793
|
-
properties.value.blob!
|
|
794
|
-
.type!
|
|
795
|
-
) ?
|
|
796
|
-
CSS_CLASS_NAMES[
|
|
797
|
-
'file-input__iframe-' +
|
|
798
|
-
'wrapper--padding'
|
|
799
|
-
] :
|
|
800
|
-
[]
|
|
801
|
-
)
|
|
802
|
-
.join(' ')
|
|
803
|
-
}>
|
|
804
|
-
<iframe
|
|
805
|
-
frameBorder="no"
|
|
806
|
-
scrolling="no"
|
|
807
|
-
src={properties.value.url}
|
|
808
|
-
/>
|
|
809
|
-
</div> :
|
|
810
|
-
properties.value?.source &&
|
|
811
|
-
representationType === 'text' ?
|
|
812
|
-
<pre
|
|
813
|
-
className={CSS_CLASS_NAMES[
|
|
814
|
-
'file-input__text-representation'
|
|
815
|
-
]}
|
|
816
|
-
>
|
|
817
|
-
{properties.value.source}
|
|
818
|
-
</pre> :
|
|
819
|
-
'' :
|
|
820
|
-
properties.value?.blob &&
|
|
821
|
-
properties.value.blob instanceof Blob ?
|
|
822
|
-
// NOTE: Only blobs have to red asynchronously.
|
|
823
|
-
<CircularProgress size="large" /> :
|
|
824
|
-
''
|
|
825
|
-
}
|
|
826
|
-
<div>
|
|
827
|
-
<Typography tag="h2" use="headline6">
|
|
828
|
-
{invalid ?
|
|
829
|
-
<Theme use="error">{
|
|
830
|
-
properties.description ?
|
|
831
|
-
properties.description :
|
|
832
|
-
properties.name
|
|
833
|
-
}</Theme> :
|
|
834
|
-
properties.description ?
|
|
835
|
-
properties.description :
|
|
836
|
-
properties.name
|
|
837
|
-
}
|
|
838
|
-
</Typography>
|
|
839
|
-
{properties.declaration ?
|
|
840
|
-
<Typography
|
|
841
|
-
style={{marginTop: '-1rem'}}
|
|
842
|
-
tag="h3"
|
|
843
|
-
theme="textSecondaryOnBackground"
|
|
844
|
-
use="subtitle2"
|
|
845
|
-
>
|
|
846
|
-
{invalid ?
|
|
847
|
-
<Theme use="error">
|
|
848
|
-
{properties.declaration}
|
|
849
|
-
</Theme> :
|
|
850
|
-
properties.declaration
|
|
851
|
-
}
|
|
852
|
-
</Typography> :
|
|
853
|
-
''
|
|
854
|
-
}
|
|
855
|
-
{properties.value ?
|
|
856
|
-
<GenericInput
|
|
857
|
-
ref={nameInputReference}
|
|
858
|
-
{...properties.generateFileNameInputProperties(
|
|
859
|
-
{
|
|
860
|
-
disabled: properties.disabled,
|
|
861
|
-
value: properties.value?.name,
|
|
862
|
-
...defaultFileNameInputProperties,
|
|
863
|
-
model: properties.model.fileName,
|
|
864
|
-
onChangeValue: onChangeValue,
|
|
865
|
-
default: properties.value.name
|
|
866
|
-
},
|
|
867
|
-
properties as
|
|
868
|
-
Omit<Properties, 'value'> &
|
|
869
|
-
{value:FileValue & {name:string}}
|
|
870
|
-
)}
|
|
871
|
-
/> :
|
|
872
|
-
''
|
|
873
|
-
}
|
|
874
|
-
{properties.children ?
|
|
875
|
-
properties.children({
|
|
876
|
-
declaration: properties.declaration,
|
|
877
|
-
invalid,
|
|
878
|
-
properties,
|
|
879
|
-
value: properties.value
|
|
880
|
-
}) :
|
|
881
|
-
''
|
|
882
|
-
}
|
|
883
|
-
</div>
|
|
884
|
-
{/* TODO use "accept" attribute for better validation. */}
|
|
885
|
-
<input
|
|
886
|
-
disabled={properties.disabled}
|
|
887
|
-
className={CSS_CLASS_NAMES['file-input__native']}
|
|
888
|
-
id={properties.id || properties.name}
|
|
889
|
-
name={properties.name}
|
|
890
|
-
onChange={onChangeValue}
|
|
891
|
-
ref={fileInputReference}
|
|
892
|
-
type="file"
|
|
893
|
-
/>
|
|
894
|
-
</CardPrimaryAction>
|
|
895
|
-
{!properties.disabled || properties.value ?
|
|
896
|
-
<CardActions>
|
|
897
|
-
<CardActionButtons>
|
|
898
|
-
{!properties.disabled ?
|
|
899
|
-
<CardActionButton
|
|
900
|
-
onClick={():void =>
|
|
901
|
-
fileInputReference.current?.click()
|
|
902
|
-
}
|
|
903
|
-
ref={uploadButtonReference}
|
|
904
|
-
ripple={properties.ripple}
|
|
905
|
-
>
|
|
906
|
-
{properties.value ?
|
|
907
|
-
properties.editButton :
|
|
908
|
-
properties.newButton
|
|
909
|
-
}
|
|
910
|
-
</CardActionButton> :
|
|
911
|
-
''
|
|
912
|
-
}
|
|
913
|
-
{properties.value ?
|
|
914
|
-
<>
|
|
915
|
-
{!properties.disabled ?
|
|
916
|
-
<CardActionButton
|
|
917
|
-
onClick={
|
|
918
|
-
():void => onChangeValue(null)
|
|
919
|
-
}
|
|
920
|
-
ref={deleteButtonReference}
|
|
921
|
-
ripple={properties.ripple}
|
|
922
|
-
>
|
|
923
|
-
{properties.deleteButton}
|
|
924
|
-
</CardActionButton> :
|
|
925
|
-
''
|
|
926
|
-
}
|
|
927
|
-
{properties.value.url ?
|
|
928
|
-
<CardActionButton
|
|
929
|
-
onClick={():void =>
|
|
930
|
-
downloadLinkReference
|
|
931
|
-
.current?.click()
|
|
932
|
-
}
|
|
933
|
-
ripple={properties.ripple}
|
|
934
|
-
>
|
|
935
|
-
<a
|
|
936
|
-
className={CSS_CLASS_NAMES[
|
|
937
|
-
'file-input__download'
|
|
938
|
-
]}
|
|
939
|
-
download={properties.value.name}
|
|
940
|
-
href={properties.value.url}
|
|
941
|
-
ref={downloadLinkReference}
|
|
942
|
-
target="_blank"
|
|
943
|
-
{...(properties.value.blob?.type ?
|
|
944
|
-
{type:
|
|
945
|
-
properties.value.blob.type
|
|
946
|
-
} :
|
|
947
|
-
{}
|
|
948
|
-
)}
|
|
949
|
-
>{properties.downloadButton}</a>
|
|
950
|
-
</CardActionButton> :
|
|
951
|
-
''
|
|
952
|
-
}
|
|
953
|
-
</> :
|
|
954
|
-
''
|
|
955
|
-
}
|
|
956
|
-
</CardActionButtons>
|
|
957
|
-
</CardActions> :
|
|
958
|
-
''
|
|
959
|
-
}
|
|
960
|
-
</Card>
|
|
961
|
-
</WrapConfigurations>
|
|
962
|
-
// endregion
|
|
963
|
-
}
|
|
964
|
-
/* eslint-enable jsdoc/require-description-complete-sentence */
|
|
965
|
-
// NOTE: This is useful in react dev tools.
|
|
966
|
-
FileInputInner.displayName = 'FileInput'
|
|
967
|
-
/**
|
|
968
|
-
* Wrapping web component compatible react component.
|
|
969
|
-
* @property static:defaultModelState - Initial model state.
|
|
970
|
-
* @property static:defaultProperties - Initial property configuration.
|
|
971
|
-
* @property static:propTypes - Triggers reacts runtime property value checks.
|
|
972
|
-
* @property static:strict - Indicates whether we should wrap render output in
|
|
973
|
-
* reacts strict component.
|
|
974
|
-
* @property static:wrapped - Wrapped component.
|
|
975
|
-
*
|
|
976
|
-
* @param props - Given components properties.
|
|
977
|
-
* @param reference - Reference object to forward internal state.
|
|
978
|
-
*
|
|
979
|
-
* @returns React elements.
|
|
980
|
-
*/
|
|
981
|
-
export const FileInput:FileInputComponent =
|
|
982
|
-
memorize(forwardRef(FileInputInner)) as unknown as FileInputComponent
|
|
983
|
-
// region static properties
|
|
984
|
-
/// region web-component hints
|
|
985
|
-
FileInput.wrapped = FileInputInner
|
|
986
|
-
FileInput.webComponentAdapterWrapped = 'react'
|
|
987
|
-
/// endregion
|
|
988
|
-
FileInput.defaultModelState = defaultModelState
|
|
989
|
-
/*
|
|
990
|
-
NOTE: We set values to "undefined" to identify whether these values where
|
|
991
|
-
provided via "props" and should shadow a state saved valued.
|
|
992
|
-
*/
|
|
993
|
-
FileInput.defaultProperties = {
|
|
994
|
-
...defaultProperties,
|
|
995
|
-
model: {
|
|
996
|
-
...defaultProperties.model,
|
|
997
|
-
// Trigger initial determination.
|
|
998
|
-
state: undefined as unknown as ModelState,
|
|
999
|
-
value: undefined
|
|
1000
|
-
},
|
|
1001
|
-
value: undefined
|
|
1002
|
-
}
|
|
1003
|
-
FileInput.propTypes = propertyTypes
|
|
1004
|
-
FileInput.strict = false
|
|
1005
|
-
// endregion
|
|
1006
|
-
export default FileInput
|
|
1007
|
-
// region vim modline
|
|
1008
|
-
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
|
1009
|
-
// vim: foldmethod=marker foldmarker=region,endregion:
|
|
1010
|
-
// endregion
|