UNPKG

@talend/react-forms

Version:

React forms library based on json schema form.

195 lines (190 loc) 6.75 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PRESIGNED_URL_TRIGGER_ACTION = exports.FileWidget = void 0; exports.base64Decode = base64Decode; exports.default = void 0; exports.getFileName = getFileName; var _react = require("react"); var _reactI18next = require("react-i18next"); var _propTypes = _interopRequireDefault(require("prop-types")); var _designSystem = require("@talend/design-system"); var _constants = require("../../../constants"); var _labels = require("../../utils/labels"); var _properties = require("../../utils/properties"); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } /* eslint-disable jsx-a11y/no-autofocus */ const PRESIGNED_URL_TRIGGER_ACTION = exports.PRESIGNED_URL_TRIGGER_ACTION = 'generatePresignedURL'; const BASE64_NAME = ';name='; const BASE64_PREFIX = ';base64,'; /** * Decode the base64 file name with multi-byte character support * @param {string} filename The base64 value of the file name * @returns {string} The decoded file name */ function base64Decode(filename) { return decodeURIComponent(atob(filename).split('').map(c => { return `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`; }).join('')); } /** * Extract the file name from the value * @param {string} value The base64 value of the file. * Looks like `data:text/xml;name=test.xml;base64,PD94bWwgdmVyc2l...` * @param {Object} schema The widget schema to get triggers. * @returns {string} The file name, for example: `test.xml`. */ function getFileName(value, schema) { if (value && value.indexOf(BASE64_NAME) !== -1) { return value.slice(value.indexOf(BASE64_NAME) + BASE64_NAME.length, value.indexOf(BASE64_PREFIX)); } if (value && schema && schema.triggers) { const uploadTrigger = schema.triggers.find(trigger => trigger.action === PRESIGNED_URL_TRIGGER_ACTION); if (uploadTrigger) { return base64Decode(value.split('.')[1]); } } return value; } /** * Add the file name to the data url. * @param {string} value The base64 value of the file. * Looks like `data:text/xml;base64,PD94bWwgdmVyc2l...` * @param {string} fileName The file name, for exemple `test.xml`. * @returns {(string|undefined)} the base 64 encoding of the file with the file name within. * Looks like `data:text/xml;name=test.xml;base64,PD94bWwgdmVyc2l...` * Or undefined if value is undefined. */ function getBase64(value, fileName) { if (value && value.indexOf(BASE64_NAME) === -1) { const fileNamePos = value.indexOf(BASE64_PREFIX); if (fileNamePos !== -1) { return [value.slice(0, fileNamePos), BASE64_NAME, fileName, value.slice(fileNamePos)].join(''); } } return value; } const FileWidget = props => { const { id, isValid, errorMessage, onFinish, onChange, onTrigger, schema, valueIsUpdating, value } = props; const { accept, autoFocus, description, disabled = false, placeholder, readOnly = false, title, labelProps, required } = schema; const [loading, setLoading] = (0, _react.useState)(false); const handleOnChange = event => { event.persist(); const fileList = event.target.files; if (fileList.length > 0) { const file = fileList[0]; if (schema.triggers && schema.triggers.some(trigger => trigger.action === PRESIGNED_URL_TRIGGER_ACTION)) { setLoading(true); Promise.all(schema.triggers.map(trigger => { if (trigger.action === PRESIGNED_URL_TRIGGER_ACTION && trigger.onEvent === 'change') { return onTrigger(event, { trigger, schema }); } return Promise.resolve(); })).finally(() => setLoading(false)); } else { const reader = new FileReader(); reader.onload = () => { const data = getBase64(reader.result, file.name); onChange(event, { schema, value: data }); }; reader.readAsDataURL(file); } } else { onChange(event, { schema, value: '' }); } }; return /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, { children: loading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_designSystem.SkeletonInput, {}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_designSystem.Form.File, { label: (0, _labels.getLabelProps)(title, labelProps, schema.hint, required), required: required, accept: accept, autoFocus: autoFocus, name: `input-filename-${id}`, id: `input-${id}`, disabled: disabled || valueIsUpdating, onBlur: event => onFinish(event, { schema }), onChange: handleOnChange, onDrop: handleOnChange, placeholder: placeholder, readOnly: readOnly, files: value && [getFileName(value, schema)], description: errorMessage || description, hasError: !isValid, "aria-invalid": !isValid, "aria-required": schema.required, ...(0, _properties.extractDataAttributes)(schema) }) }); }; exports.FileWidget = FileWidget; if (process.env.NODE_ENV !== 'production') { FileWidget.propTypes = { id: _propTypes.default.string, isValid: _propTypes.default.bool, errorMessage: _propTypes.default.string, onChange: _propTypes.default.func.isRequired, onFinish: _propTypes.default.func.isRequired, onTrigger: _propTypes.default.func, required: _propTypes.default.bool, schema: _propTypes.default.shape({ accept: _propTypes.default.string, autoFocus: _propTypes.default.bool, description: _propTypes.default.string, disabled: _propTypes.default.bool, placeholder: _propTypes.default.string, readOnly: _propTypes.default.bool, required: _propTypes.default.bool, title: _propTypes.default.string, labelProps: _propTypes.default.object, type: _propTypes.default.string, triggers: _propTypes.default.arrayOf(_propTypes.default.object), hint: _propTypes.default.shape({ icon: _propTypes.default.string, className: _propTypes.default.string, overlayComponent: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.string]).isRequired, overlayPlacement: _propTypes.default.string }) }), value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]), valueIsUpdating: _propTypes.default.bool }; } FileWidget.defaultProps = { isValid: true, schema: {} }; var _default = exports.default = (0, _reactI18next.withTranslation)(_constants.I18N_DOMAIN_FORMS)(FileWidget); //# sourceMappingURL=File.component.js.map