@headless-adminapp/fluent 0.0.17-alpha.27 → 0.0.17-alpha.29

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.
@@ -70,6 +70,7 @@ function RelatedViewSelector(props) {
70
70
  outlineStyle: 'none',
71
71
  textTransform: 'none',
72
72
  columnGap: react_components_1.tokens.spacingHorizontalSNudge,
73
+ color: react_components_1.tokens.colorNeutralForeground2,
73
74
  }, children: [strings.related, (0, jsx_runtime_1.jsx)(icons_1.Icons.ChevronDown, { size: 16 })] }) }), (0, jsx_runtime_1.jsx)(react_components_1.MenuPopover, { children: (0, jsx_runtime_1.jsx)(react_components_1.MenuList, { children: data.map((item) => {
74
75
  var _a, _b;
75
76
  return ((0, jsx_runtime_1.jsx)(react_components_1.MenuItem, { onClick: () => props.onSelect(item), children: (_b = (_a = item.localizedPluralLabels) === null || _a === void 0 ? void 0 : _a[language]) !== null && _b !== void 0 ? _b : item.pluralLabel }, item.key));
@@ -41,7 +41,12 @@ function SectionContainer({ section }) {
41
41
  ? (_b = fieldState.error) === null || _b === void 0 ? void 0 : _b.message
42
42
  : '';
43
43
  const label = (_g = (_f = (_d = (_c = control.localizedLabels) === null || _c === void 0 ? void 0 : _c[language]) !== null && _d !== void 0 ? _d : (_e = attribute.localizedLabels) === null || _e === void 0 ? void 0 : _e[language]) !== null && _f !== void 0 ? _f : control.label) !== null && _g !== void 0 ? _g : attribute.label;
44
- return ((0, jsx_runtime_1.jsx)(SectionControl_1.SectionControlWrapper, { label: label, labelPosition: section.labelPosition, required: attribute.required, isError: isError, errorMessage: errorMessage, children: (0, jsx_runtime_1.jsx)(Control, { attribute: attribute, name: control.attributeName, value: field.value, onChange: field.onChange, onBlur: field.onBlur, errorMessage: errorMessage, isError: isError, disabled: readonly, label: label, placeholder: label, allowNavigation: true, allowNewRecord: true }) }));
44
+ return ((0, jsx_runtime_1.jsx)(SectionControl_1.SectionControlWrapper, { label: label, labelPosition: section.labelPosition, required: attribute.required, isError: isError, errorMessage: errorMessage, children: (0, jsx_runtime_1.jsx)(Control, { attribute: attribute, name: control.attributeName, value: field.value, onChange: field.onChange, onBlur: field.onBlur, errorMessage: errorMessage, isError: isError, disabled: readonly, label: label, placeholder: label, allowNavigation: true, allowNewRecord: true, fileServiceContext: {
45
+ type: 'entity-form',
46
+ recordId,
47
+ attributeName: control.attributeName,
48
+ logicalName: schema.logicalName,
49
+ } }) }));
45
50
  } }, control.attributeName) }, control.attributeName));
46
51
  }
47
52
  case 'editablegrid': {
@@ -10,6 +10,7 @@ export interface StandardControlProps {
10
10
  placeholder?: string;
11
11
  onChange: (value: any) => void;
12
12
  onBlur: () => void;
13
+ fileServiceContext?: Record<string, unknown>;
13
14
  disabled?: boolean;
14
15
  borderOnFocusOnly?: boolean;
15
16
  hideLabel?: boolean;
@@ -9,6 +9,7 @@ const hooks_1 = require("@headless-adminapp/app/metadata/hooks");
9
9
  const transport_1 = require("@headless-adminapp/app/transport");
10
10
  const react_1 = require("react");
11
11
  const componentStore_1 = require("../componentStore");
12
+ const AttachmentControl_1 = require("../form/controls/AttachmentControl");
12
13
  const AttachmentsControl_1 = require("../form/controls/AttachmentsControl");
13
14
  const CurrencyControl_1 = require("../form/controls/CurrencyControl");
14
15
  const DateControl_1 = require("../form/controls/DateControl");
@@ -26,7 +27,7 @@ const TelephoneControl_1 = require("../form/controls/TelephoneControl");
26
27
  const TextAreaControl_1 = require("../form/controls/TextAreaControl");
27
28
  const TextControl_1 = require("../form/controls/TextControl");
28
29
  const StandardControl = (props) => {
29
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
30
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
30
31
  const { attribute, label: _label, isError,
31
32
  // errorMessage,
32
33
  name, value, onBlur, onChange,
@@ -44,6 +45,7 @@ const StandardControl = (props) => {
44
45
  : (_a = _placeholder !== null && _placeholder !== void 0 ? _placeholder : _label) !== null && _a !== void 0 ? _a : attribute.label;
45
46
  // const required = quickViewControl ? false : attribute.required;
46
47
  const dataService = (0, transport_1.useDataService)();
48
+ const fileService = (0, transport_1.useFileService)();
47
49
  const { schemaStore, experienceStore } = (0, hooks_1.useMetadata)();
48
50
  // const { openQuickCreate } = useQuickCreateForm();
49
51
  switch (attribute.type) {
@@ -148,8 +150,12 @@ const StandardControl = (props) => {
148
150
  const Control = (_s = componentStore_1.componentStore.getComponent('Form.MultiSelectControl')) !== null && _s !== void 0 ? _s : MultiSelectControl_1.default;
149
151
  return ((0, jsx_runtime_1.jsx)(Control, { name: name, value: value, onChange: onChange, onBlur: onBlur, error: isError, disabled: isDisabled, options: attribute.options, placeholder: placeholder, borderOnFocusOnly: borderOnFocusOnly, readOnly: readOnly }));
150
152
  }
153
+ case 'attachment': {
154
+ const Control = (_t = componentStore_1.componentStore.getComponent('Form.AttachmentControl')) !== null && _t !== void 0 ? _t : AttachmentControl_1.AttachmentControl;
155
+ return ((0, jsx_runtime_1.jsx)(Control, { fileService: fileService, format: attribute.format, location: attribute.location, name: name, value: value, onChange: onChange, onBlur: onBlur, error: isError, disabled: isDisabled, placeholder: placeholder, borderOnFocusOnly: borderOnFocusOnly, readOnly: readOnly, fileServiceContext: props.fileServiceContext }));
156
+ }
151
157
  case 'attachments': {
152
- const Control = (_t = componentStore_1.componentStore.getComponent('Form.AttachmentsControl')) !== null && _t !== void 0 ? _t : AttachmentsControl_1.AttachmentsControl;
158
+ const Control = (_u = componentStore_1.componentStore.getComponent('Form.AttachmentsControl')) !== null && _u !== void 0 ? _u : AttachmentsControl_1.AttachmentsControl;
153
159
  return ((0, jsx_runtime_1.jsx)(Control, { name: name, value: value, onChange: onChange, onBlur: onBlur, error: isError, disabled: isDisabled, placeholder: placeholder, borderOnFocusOnly: borderOnFocusOnly, readOnly: readOnly }));
154
160
  }
155
161
  // case 'attachment': {
@@ -0,0 +1,17 @@
1
+ import { AttachmentAttribute, FileObject } from '@headless-adminapp/core/attributes/AttachmentAttribute';
2
+ import { IFileService } from '@headless-adminapp/core/transport';
3
+ import { FC } from 'react';
4
+ import { ControlProps } from './types';
5
+ export interface AttachmentImageControlProps extends ControlProps<FileObject> {
6
+ fileService: IFileService;
7
+ fileServiceContext?: Record<string, unknown>;
8
+ location: AttachmentAttribute['location'];
9
+ }
10
+ interface AttachmentControlProps extends ControlProps<FileObject> {
11
+ fileService: IFileService;
12
+ fileServiceContext?: Record<string, unknown>;
13
+ location: AttachmentAttribute['location'];
14
+ format: AttachmentAttribute['format'];
15
+ }
16
+ export declare const AttachmentControl: FC<AttachmentControlProps>;
17
+ export {};
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.AttachmentControl = void 0;
13
+ const jsx_runtime_1 = require("react/jsx-runtime");
14
+ const react_components_1 = require("@fluentui/react-components");
15
+ const hooks_1 = require("@headless-adminapp/app/dialog/hooks");
16
+ const utils_1 = require("@headless-adminapp/core/utils");
17
+ const icons_1 = require("@headless-adminapp/icons");
18
+ const react_query_1 = require("@tanstack/react-query");
19
+ const react_1 = require("react");
20
+ function useAttachmentSelector({ fileService, fileServiceContext, location, onChange, }) {
21
+ const openErrorDialog = (0, hooks_1.useOpenErrorDialog)();
22
+ const { isPending, mutate: handleFile } = (0, react_query_1.useMutation)({
23
+ mutationFn: (file) => __awaiter(this, void 0, void 0, function* () {
24
+ if (location === 'local') {
25
+ return (0, utils_1.fileToObject)(file);
26
+ }
27
+ else {
28
+ const url = yield fileService.uploadFile(file, {
29
+ context: fileServiceContext,
30
+ });
31
+ return (0, utils_1.urlToFileObject)(url);
32
+ }
33
+ }),
34
+ onSuccess: (fileObject) => {
35
+ onChange === null || onChange === void 0 ? void 0 : onChange(fileObject);
36
+ },
37
+ onError: (error) => {
38
+ console.error(error);
39
+ openErrorDialog({
40
+ title: 'Failed to upload file',
41
+ text: error.message,
42
+ });
43
+ },
44
+ });
45
+ const selectFile = (accept) => {
46
+ const input = document.createElement('input');
47
+ input.type = 'file';
48
+ if (accept) {
49
+ input.accept = accept;
50
+ }
51
+ input.onchange = (event) => __awaiter(this, void 0, void 0, function* () {
52
+ const files = event.target.files;
53
+ if (!(files === null || files === void 0 ? void 0 : files.length)) {
54
+ return;
55
+ }
56
+ const file = files[0];
57
+ handleFile(file);
58
+ });
59
+ input.click();
60
+ };
61
+ return {
62
+ isProcessing: isPending,
63
+ selectFile,
64
+ };
65
+ }
66
+ const AttachmentImageControl = ({ value, disabled, readOnly, onChange, fileService, fileServiceContext, location, }) => {
67
+ const { isProcessing, selectFile } = useAttachmentSelector({
68
+ fileService,
69
+ fileServiceContext,
70
+ location,
71
+ onChange,
72
+ });
73
+ if (!value) {
74
+ return ((0, jsx_runtime_1.jsx)("div", { style: { position: 'relative', display: 'flex' }, children: (0, jsx_runtime_1.jsx)("div", { style: {
75
+ width: 100,
76
+ height: 100,
77
+ backgroundColor: react_components_1.tokens.colorNeutralBackground2,
78
+ borderRadius: react_components_1.tokens.borderRadiusMedium,
79
+ display: 'flex',
80
+ justifyContent: 'center',
81
+ alignItems: 'center',
82
+ color: react_components_1.tokens.colorNeutralForeground4,
83
+ cursor: 'pointer',
84
+ pointerEvents: disabled || readOnly || isProcessing ? 'none' : 'auto',
85
+ }, onClick: () => selectFile('image/*'), children: isProcessing ? (0, jsx_runtime_1.jsx)(react_components_1.Spinner, { size: "small" }) : (0, jsx_runtime_1.jsx)(icons_1.Icons.Image, {}) }) }));
86
+ }
87
+ return ((0, jsx_runtime_1.jsx)("div", { style: { position: 'relative', display: 'flex' }, children: (0, jsx_runtime_1.jsxs)("div", { style: {
88
+ maxWidth: '100%',
89
+ height: 100,
90
+ position: 'relative',
91
+ }, children: [(0, jsx_runtime_1.jsx)("img", { src: value.url, style: {
92
+ maxHeight: '100%',
93
+ maxWidth: '100%',
94
+ objectFit: 'contain',
95
+ borderRadius: react_components_1.tokens.borderRadiusMedium,
96
+ } }), (0, jsx_runtime_1.jsx)("div", { style: { position: 'absolute', top: 0, right: 0 }, children: (0, jsx_runtime_1.jsx)(ActionMenu, { format: 'image', value: value, disabled: disabled, readOnly: readOnly, onChange: onChange, onChangeClick: () => selectFile('image/*') }) }), isProcessing && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: {
97
+ position: 'absolute',
98
+ inset: 0,
99
+ backgroundColor: react_components_1.tokens.colorNeutralBackground1,
100
+ opacity: 0.7,
101
+ } }), (0, jsx_runtime_1.jsx)("div", { style: {
102
+ position: 'absolute',
103
+ inset: 0,
104
+ display: 'flex',
105
+ alignItems: 'center',
106
+ justifyContent: 'center',
107
+ }, children: (0, jsx_runtime_1.jsx)(react_components_1.Spinner, { size: "small" }) })] }))] }) }));
108
+ };
109
+ const AttachmentControl = ({ value, disabled, readOnly, id, name, onBlur, onChange, placeholder, fileService, fileServiceContext, location, format, }) => {
110
+ const { isProcessing, selectFile } = useAttachmentSelector({
111
+ fileService,
112
+ fileServiceContext,
113
+ location,
114
+ onChange,
115
+ });
116
+ const accept = (0, react_1.useMemo)(() => {
117
+ switch (format) {
118
+ case 'image':
119
+ return 'image/*';
120
+ case 'video':
121
+ return 'video/*';
122
+ case 'audio':
123
+ return 'audio/*';
124
+ case 'document':
125
+ return '.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.csv';
126
+ default:
127
+ return '';
128
+ }
129
+ }, [format]);
130
+ const FormatIcon = (0, react_1.useMemo)(() => {
131
+ switch (format) {
132
+ case 'video':
133
+ return icons_1.Icons.Video;
134
+ case 'audio':
135
+ return icons_1.Icons.Audio;
136
+ default:
137
+ return icons_1.Icons.Document;
138
+ }
139
+ }, [format]);
140
+ if (format === 'image') {
141
+ return ((0, jsx_runtime_1.jsx)(AttachmentImageControl, { value: value, disabled: disabled, readOnly: readOnly, id: id, name: name, onBlur: onBlur, onChange: onChange, placeholder: placeholder, fileService: fileService, fileServiceContext: fileServiceContext, location: location }));
142
+ }
143
+ if (!value) {
144
+ return ((0, jsx_runtime_1.jsx)("div", { style: { position: 'relative', overflow: 'hidden' }, children: (0, jsx_runtime_1.jsx)("div", { style: {
145
+ width: '100%',
146
+ }, children: (0, jsx_runtime_1.jsxs)("div", { style: {
147
+ width: '100%',
148
+ height: 30,
149
+ borderRadius: react_components_1.tokens.borderRadiusMedium,
150
+ backgroundColor: react_components_1.tokens.colorNeutralBackground2,
151
+ display: 'flex',
152
+ paddingLeft: react_components_1.tokens.spacingHorizontalS,
153
+ gap: react_components_1.tokens.spacingHorizontalS,
154
+ alignItems: 'center',
155
+ overflow: 'hidden',
156
+ color: react_components_1.tokens.colorNeutralForeground4,
157
+ cursor: 'pointer',
158
+ pointerEvents: disabled || readOnly || isProcessing ? 'none' : 'auto',
159
+ }, onClick: () => selectFile(accept), children: [(0, jsx_runtime_1.jsx)(FormatIcon, { size: 16 }), (0, jsx_runtime_1.jsx)(react_components_1.Body1, { style: {
160
+ overflow: 'hidden',
161
+ textOverflow: 'ellipsis',
162
+ whiteSpace: 'nowrap',
163
+ flex: 1,
164
+ }, children: placeholder || 'Select a file' }), isProcessing && ((0, jsx_runtime_1.jsx)("div", { style: { paddingRight: react_components_1.tokens.spacingHorizontalS }, children: (0, jsx_runtime_1.jsx)(react_components_1.Spinner, { size: "extra-tiny" }) }))] }) }) }));
165
+ }
166
+ return ((0, jsx_runtime_1.jsx)("div", { style: { position: 'relative', overflow: 'hidden' }, children: (0, jsx_runtime_1.jsx)("div", { style: {
167
+ width: '100%',
168
+ }, children: (0, jsx_runtime_1.jsxs)("div", { style: {
169
+ width: '100%',
170
+ height: 30,
171
+ borderRadius: react_components_1.tokens.borderRadiusMedium,
172
+ backgroundColor: react_components_1.tokens.colorNeutralBackground2,
173
+ display: 'flex',
174
+ paddingLeft: react_components_1.tokens.spacingHorizontalS,
175
+ gap: react_components_1.tokens.spacingHorizontalS,
176
+ alignItems: 'center',
177
+ overflow: 'hidden',
178
+ }, children: [(0, jsx_runtime_1.jsx)(FormatIcon, { size: 16 }), (0, jsx_runtime_1.jsx)(react_components_1.Body1, { style: {
179
+ overflow: 'hidden',
180
+ textOverflow: 'ellipsis',
181
+ whiteSpace: 'nowrap',
182
+ flex: 1,
183
+ }, children: value.name || value.url }), isProcessing && ((0, jsx_runtime_1.jsx)("div", { style: { paddingRight: react_components_1.tokens.spacingHorizontalS }, children: (0, jsx_runtime_1.jsx)(react_components_1.Spinner, { size: "extra-tiny" }) })), !isProcessing && ((0, jsx_runtime_1.jsx)(ActionMenu, { format: format, value: value, disabled: disabled, readOnly: readOnly, onChange: onChange, onChangeClick: () => selectFile(accept) }))] }) }) }));
184
+ };
185
+ exports.AttachmentControl = AttachmentControl;
186
+ const ActionMenu = ({ format, value, disabled, readOnly, onChange, onChangeClick, }) => {
187
+ const openConfirmDialog = (0, hooks_1.useOpenConfirmDialog)();
188
+ const FileOpenIcon = (0, react_1.useMemo)(() => {
189
+ switch (format) {
190
+ case 'video':
191
+ case 'audio':
192
+ return icons_1.Icons.Play;
193
+ default:
194
+ return icons_1.Icons.OpenInNew;
195
+ }
196
+ }, [format]);
197
+ const OpenText = (0, react_1.useMemo)(() => {
198
+ switch (format) {
199
+ case 'video':
200
+ return 'Play';
201
+ case 'audio':
202
+ return 'Play';
203
+ default:
204
+ return 'Open';
205
+ }
206
+ }, [format]);
207
+ return ((0, jsx_runtime_1.jsxs)(react_components_1.Menu, { positioning: "before-top", hasIcons: true, children: [(0, jsx_runtime_1.jsx)(react_components_1.MenuTrigger, { children: (0, jsx_runtime_1.jsx)(react_components_1.Button, { appearance: "transparent", icon: (0, jsx_runtime_1.jsx)(icons_1.Icons.MoreVertical, {}) }) }), (0, jsx_runtime_1.jsx)(react_components_1.MenuPopover, { children: (0, jsx_runtime_1.jsxs)(react_components_1.MenuList, { children: [(0, jsx_runtime_1.jsx)(react_components_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(FileOpenIcon, {}), onClick: () => {
208
+ window.open(value.url, '_blank');
209
+ }, children: OpenText }), (0, jsx_runtime_1.jsx)(react_components_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(icons_1.Icons.Copy, {}), onClick: () => {
210
+ navigator.clipboard.writeText(value.url).catch(() => { });
211
+ }, children: "Copy Url" }), !(disabled || readOnly) && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_components_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(icons_1.Icons.Edit, {}), onClick: () => {
212
+ onChangeClick === null || onChangeClick === void 0 ? void 0 : onChangeClick();
213
+ }, children: "Change" }), (0, jsx_runtime_1.jsx)(react_components_1.MenuDivider, {}), (0, jsx_runtime_1.jsx)(react_components_1.MenuItem, { icon: (0, jsx_runtime_1.jsx)(icons_1.Icons.Delete, {}), onClick: () => __awaiter(void 0, void 0, void 0, function* () {
214
+ const result = yield openConfirmDialog({
215
+ title: 'Remove file',
216
+ text: 'Are you sure you want to remove this file?',
217
+ confirmButtonLabel: 'Remove',
218
+ cancelButtonLabel: 'Cancel',
219
+ });
220
+ if (!(result === null || result === void 0 ? void 0 : result.confirmed)) {
221
+ return;
222
+ }
223
+ onChange === null || onChange === void 0 ? void 0 : onChange(null);
224
+ }), children: "Remove" })] }))] }) })] }));
225
+ };
@@ -1,8 +1,6 @@
1
1
  import { FileObject } from '@headless-adminapp/core/attributes/AttachmentAttribute';
2
2
  import { FC } from 'react';
3
3
  import { ControlProps } from './types';
4
- export declare function fileToObject(file: File): Promise<FileObject>;
5
- export declare function dataUrlToFile(dataUrl: string, name: string): File;
6
4
  export interface AttachmentsControlProps extends ControlProps<FileObject[]> {
7
5
  }
8
6
  export declare const AttachmentsControl: FC<AttachmentsControlProps>;
@@ -10,39 +10,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.AttachmentsControl = void 0;
13
- exports.fileToObject = fileToObject;
14
- exports.dataUrlToFile = dataUrlToFile;
15
13
  const jsx_runtime_1 = require("react/jsx-runtime");
16
14
  const react_components_1 = require("@fluentui/react-components");
15
+ const utils_1 = require("@headless-adminapp/core/utils");
17
16
  const icons_1 = require("@headless-adminapp/icons");
18
17
  const react_1 = require("react");
19
- function fileToObject(file) {
20
- return new Promise((resolve, reject) => {
21
- const reader = new FileReader();
22
- reader.onload = () => {
23
- resolve({
24
- name: file.name,
25
- type: file.type,
26
- size: file.size,
27
- url: reader.result,
28
- });
29
- };
30
- reader.onerror = (error) => {
31
- reject(error);
32
- };
33
- reader.readAsDataURL(file);
34
- });
35
- }
36
- function dataUrlToFile(dataUrl, name) {
37
- const byteString = atob(dataUrl.split(',')[1]);
38
- const mimeString = dataUrl.split(',')[0].split(':')[1].split(';')[0];
39
- const ab = new ArrayBuffer(byteString.length);
40
- const ia = new Uint8Array(ab);
41
- for (let i = 0; i < byteString.length; i++) {
42
- ia[i] = byteString.charCodeAt(i);
43
- }
44
- return new File([ab], name, { type: mimeString });
45
- }
46
18
  const AttachmentsControl = ({ onChange, id, onBlur, onFocus, disabled, readOnly, value, }) => {
47
19
  const inputRef = (0, react_1.useRef)(null);
48
20
  return ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', flexDirection: 'column' }, children: [(0, jsx_runtime_1.jsxs)(react_components_1.TagPicker, { appearance: "filled-darker", disabled: disabled, open: false, children: [(0, jsx_runtime_1.jsx)(react_components_1.TagPickerControl, { onFocus: onFocus, onBlur: onBlur, id: id, style: { paddingBlock: react_components_1.tokens.spacingVerticalXXS }, expandIcon: null, children: (0, jsx_runtime_1.jsxs)(react_components_1.TagGroup, { style: {
@@ -65,7 +37,7 @@ const AttachmentsControl = ({ onChange, id, onBlur, onFocus, disabled, readOnly,
65
37
  }, children: "Add" }))] }) }), (0, jsx_runtime_1.jsx)(react_components_1.TagPickerList, {})] }), (0, jsx_runtime_1.jsx)("input", { ref: inputRef, type: "file", multiple: true, style: { display: 'none' }, onChange: (event) => __awaiter(void 0, void 0, void 0, function* () {
66
38
  const files = event.target.files;
67
39
  if (files === null || files === void 0 ? void 0 : files.length) {
68
- const fileObjects = yield Promise.all(Array.from(files).map((file) => fileToObject(file)));
40
+ const fileObjects = yield Promise.all(Array.from(files).map((file) => (0, utils_1.fileToObject)(file)));
69
41
  onChange === null || onChange === void 0 ? void 0 : onChange([...(value !== null && value !== void 0 ? value : []), ...fileObjects]);
70
42
  }
71
43
  }) })] }));
@@ -0,0 +1,4 @@
1
+ import { FileObject } from '@headless-adminapp/core/attributes/AttachmentAttribute';
2
+ export declare function fileToObject(file: File): Promise<FileObject>;
3
+ export declare function dataUrlToFile(dataUrl: string, name: string): File;
4
+ export declare function urlToFileObject(url: string, name?: string): FileObject;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fileToObject = fileToObject;
4
+ exports.dataUrlToFile = dataUrlToFile;
5
+ exports.urlToFileObject = urlToFileObject;
6
+ // TODO: Move to core
7
+ function fileToObject(file) {
8
+ return new Promise((resolve, reject) => {
9
+ const reader = new FileReader();
10
+ reader.onload = () => {
11
+ resolve({
12
+ name: file.name,
13
+ type: file.type,
14
+ size: file.size,
15
+ url: reader.result,
16
+ });
17
+ };
18
+ reader.onerror = (error) => {
19
+ reject(error);
20
+ };
21
+ reader.readAsDataURL(file);
22
+ });
23
+ }
24
+ function dataUrlToFile(dataUrl, name) {
25
+ const byteString = atob(dataUrl.split(',')[1]);
26
+ const mimeString = dataUrl.split(',')[0].split(':')[1].split(';')[0];
27
+ const ab = new ArrayBuffer(byteString.length);
28
+ const ia = new Uint8Array(ab);
29
+ for (let i = 0; i < byteString.length; i++) {
30
+ ia[i] = byteString.charCodeAt(i);
31
+ }
32
+ return new File([ab], name, { type: mimeString });
33
+ }
34
+ function urlToFileObject(url, name) {
35
+ const fileName = name || url.split('/').pop() || 'file';
36
+ return {
37
+ name: fileName,
38
+ size: 0,
39
+ type: '',
40
+ url,
41
+ };
42
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@headless-adminapp/fluent",
3
- "version": "0.0.17-alpha.27",
3
+ "version": "0.0.17-alpha.29",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -47,5 +47,5 @@
47
47
  "uuid": "11.0.3",
48
48
  "yup": "^1.4.0"
49
49
  },
50
- "gitHead": "249b7141dedc93a334d3d918d134bd167cecd6ae"
50
+ "gitHead": "85977e78c12fe81f708b974c32c8089e9184f553"
51
51
  }
package/types/index.d.ts CHANGED
@@ -32,6 +32,13 @@ declare module '@headless-adminapp/icons/types' {
32
32
  ExportCsv: Icon;
33
33
  ExportExcel: Icon;
34
34
  Entity: Icon;
35
+ OpenInNew: Icon;
36
+ Play: Icon;
37
+ Audio: Icon;
38
+ Video: Icon;
39
+ Copy: Icon;
40
+ Document: Icon;
41
+ Image: Icon;
35
42
  }
36
43
  }
37
44
  export {};