@panneau/fields 5.0.0-alpha.3 → 5.0.0-alpha.5
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/README.md +67 -20
- package/dist/file/FileField.css +54 -0
- package/dist/file/FileField.d.ts +50 -0
- package/dist/file/FileField.d.ts.map +1 -0
- package/dist/file/FileField.js +198 -0
- package/dist/file/FileField.js.map +1 -0
- package/dist/file/FileField.module.js +22 -0
- package/dist/file/FileField.module.js.map +1 -0
- package/dist/file/index.d.ts +3 -0
- package/dist/file/index.d.ts.map +1 -0
- package/dist/file/index.js +1 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/localized/LocalizedField.d.ts.map +1 -1
- package/dist/localized/LocalizedField.js +1 -0
- package/dist/localized/LocalizedField.js.map +1 -1
- package/dist/relation/RelationField.d.ts.map +1 -1
- package/dist/relation/RelationField.js +24 -24
- package/dist/relation/RelationField.js.map +1 -1
- package/dist/shared/DefinitionField.d.ts +3 -1
- package/dist/shared/DefinitionField.d.ts.map +1 -1
- package/dist/shared/DefinitionField.js +80 -72
- package/dist/shared/DefinitionField.js.map +1 -1
- package/dist/shared/builtIn.d.ts +3 -2
- package/dist/shared/builtIn.d.ts.map +1 -1
- package/dist/shared/builtIn.js +5 -2
- package/dist/shared/builtIn.js.map +1 -1
- package/dist/shared/check.d.ts +27 -0
- package/dist/shared/check.d.ts.map +1 -0
- package/dist/shared/check.js +18 -0
- package/dist/shared/check.js.map +1 -0
- package/dist/shared/context.d.ts +15 -2
- package/dist/shared/context.d.ts.map +1 -1
- package/dist/shared/context.js +26 -18
- package/dist/shared/context.js.map +1 -1
- package/dist/shared/entry.d.ts +4 -0
- package/dist/shared/entry.d.ts.map +1 -1
- package/dist/shared/entry.js +12 -1
- package/dist/shared/entry.js.map +1 -1
- package/dist/shared/types.d.ts +2 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/slug/SlugField.css +18 -0
- package/dist/slug/SlugField.d.ts +31 -3
- package/dist/slug/SlugField.d.ts.map +1 -1
- package/dist/slug/SlugField.js +231 -159
- package/dist/slug/SlugField.js.map +1 -1
- package/dist/slug/SlugField.module.js +14 -0
- package/dist/slug/SlugField.module.js.map +1 -0
- package/dist/slug/index.d.ts +1 -1
- package/dist/slug/index.d.ts.map +1 -1
- package/dist/slug/index.js +1 -1
- package/dist/upload/FilePicker.css +24 -0
- package/dist/upload/FilePicker.d.ts +14 -0
- package/dist/upload/FilePicker.d.ts.map +1 -0
- package/dist/upload/FilePicker.js +47 -0
- package/dist/upload/FilePicker.js.map +1 -0
- package/dist/upload/FilePicker.module.js +12 -0
- package/dist/upload/FilePicker.module.js.map +1 -0
- package/dist/upload/UploadList.css +93 -0
- package/dist/upload/UploadList.d.ts +18 -0
- package/dist/upload/UploadList.d.ts.map +1 -0
- package/dist/upload/UploadList.js +144 -0
- package/dist/upload/UploadList.js.map +1 -0
- package/dist/upload/UploadList.module.js +32 -0
- package/dist/upload/UploadList.module.js.map +1 -0
- package/dist/upload/files.d.ts +5 -0
- package/dist/upload/files.d.ts.map +1 -0
- package/dist/upload/files.js +26 -0
- package/dist/upload/files.js.map +1 -0
- package/dist/upload/types.d.ts +58 -0
- package/dist/upload/types.d.ts.map +1 -0
- package/dist/upload/useRejectionMessage.d.ts +4 -0
- package/dist/upload/useRejectionMessage.d.ts.map +1 -0
- package/dist/upload/useRejectionMessage.js +25 -0
- package/dist/upload/useRejectionMessage.js.map +1 -0
- package/dist/upload/useUploads.d.ts +30 -0
- package/dist/upload/useUploads.d.ts.map +1 -0
- package/dist/upload/useUploads.js +115 -0
- package/dist/upload/useUploads.js.map +1 -0
- package/dist/uppy/index.d.ts +3 -0
- package/dist/uppy/index.d.ts.map +1 -0
- package/dist/uppy/index.js +1 -0
- package/dist/uppy/uploader.d.ts +44 -0
- package/dist/uppy/uploader.d.ts.map +1 -0
- package/dist/uppy/uploader.js +139 -0
- package/dist/uppy/uploader.js.map +1 -0
- package/package.json +30 -5
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import "./FilePicker.css";
|
|
2
|
+
//#region src/upload/FilePicker.module.css
|
|
3
|
+
var zone = "panneau-file-picker-zone";
|
|
4
|
+
var hint = "panneau-file-picker-hint";
|
|
5
|
+
var FilePicker_module_default = {
|
|
6
|
+
zone,
|
|
7
|
+
hint
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { FilePicker_module_default as default, hint, zone };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=FilePicker.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilePicker.module.js","names":[],"sources":["../../src/upload/FilePicker.module.css"],"sourcesContent":[".zone {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--panneau-space-2);\n padding: var(--panneau-space-3);\n border: var(--panneau-border-width) dashed var(--panneau-color-border-control);\n border-radius: var(--panneau-radius-md);\n}\n\n.zone[data-drop-target] {\n background-color: var(--panneau-color-accent-subtle);\n border-color: var(--panneau-color-accent);\n}\n\n.zone[data-focus-visible] {\n outline: 2px solid var(--panneau-color-focus);\n outline-offset: 2px;\n}\n\n.hint {\n font-size: var(--panneau-font-size-sm);\n color: var(--panneau-color-text-muted);\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
.panneau-upload-list-list {
|
|
2
|
+
display: grid;
|
|
3
|
+
gap: var(--panneau-space-2);
|
|
4
|
+
margin: 0;
|
|
5
|
+
padding: 0;
|
|
6
|
+
list-style: none;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.panneau-upload-list-item {
|
|
10
|
+
display: grid;
|
|
11
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: var(--panneau-space-1) var(--panneau-space-2);
|
|
14
|
+
padding: var(--panneau-space-2) var(--panneau-space-3);
|
|
15
|
+
background-color: var(--panneau-color-surface-sunken);
|
|
16
|
+
border: var(--panneau-border-width) solid var(--panneau-color-border);
|
|
17
|
+
border-radius: var(--panneau-radius-md);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.panneau-upload-list-failed {
|
|
21
|
+
border-color: var(--panneau-color-danger-border);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.panneau-upload-list-name {
|
|
25
|
+
overflow: hidden;
|
|
26
|
+
font-size: var(--panneau-font-size-sm);
|
|
27
|
+
font-weight: var(--panneau-font-weight-medium);
|
|
28
|
+
text-overflow: ellipsis;
|
|
29
|
+
white-space: nowrap;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.panneau-upload-list-buttons {
|
|
33
|
+
display: flex;
|
|
34
|
+
gap: var(--panneau-space-1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.panneau-upload-list-progress {
|
|
38
|
+
grid-column: 1 / -1;
|
|
39
|
+
display: grid;
|
|
40
|
+
gap: var(--panneau-space-1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.panneau-upload-list-status {
|
|
44
|
+
font-size: var(--panneau-font-size-sm);
|
|
45
|
+
color: var(--panneau-color-text-muted);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.panneau-upload-list-error {
|
|
49
|
+
grid-column: 1 / -1;
|
|
50
|
+
font-size: var(--panneau-font-size-sm);
|
|
51
|
+
color: var(--panneau-color-danger);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.panneau-upload-list-track {
|
|
55
|
+
height: 0.375rem;
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
background: var(--panneau-color-surface);
|
|
58
|
+
border-radius: var(--panneau-radius-full);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.panneau-upload-list-fill {
|
|
62
|
+
display: block;
|
|
63
|
+
height: 100%;
|
|
64
|
+
background: var(--panneau-color-accent);
|
|
65
|
+
border-radius: inherit;
|
|
66
|
+
transition: width var(--panneau-duration) ease-out;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.panneau-upload-list-indeterminate .panneau-upload-list-fill {
|
|
70
|
+
width: 30%;
|
|
71
|
+
animation: panneau-upload-list-slide 1.2s ease-in-out infinite;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@keyframes panneau-upload-list-slide {
|
|
75
|
+
from {
|
|
76
|
+
transform: translateX(-100%);
|
|
77
|
+
}
|
|
78
|
+
to {
|
|
79
|
+
transform: translateX(340%);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@media (prefers-reduced-motion: reduce) {
|
|
84
|
+
.panneau-upload-list-fill {
|
|
85
|
+
transition: none;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.panneau-upload-list-indeterminate .panneau-upload-list-fill {
|
|
89
|
+
width: 100%;
|
|
90
|
+
animation: none;
|
|
91
|
+
opacity: 0.5;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { UploadItem } from './types';
|
|
2
|
+
export interface UploadListProps {
|
|
3
|
+
/** The files being uploaded, from `useUploads()`. */
|
|
4
|
+
items: readonly UploadItem[];
|
|
5
|
+
onPause?: (id: string) => void;
|
|
6
|
+
onResume?: (id: string) => void;
|
|
7
|
+
onCancel?: (id: string) => void;
|
|
8
|
+
onRetry?: (id: string) => void;
|
|
9
|
+
/** Accessible name of the list. Defaults to "Uploads". */
|
|
10
|
+
'aria-label'?: string;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The files being uploaded: a progress bar for each, and buttons to pause and resume a file sent
|
|
15
|
+
* in parts, to cancel it, and to retry it when it failed. Renders nothing without files.
|
|
16
|
+
*/
|
|
17
|
+
export declare function UploadList({ items, onPause, onResume, onCancel, onRetry, 'aria-label': ariaLabel, className, }: UploadListProps): import("react").JSX.Element | null;
|
|
18
|
+
//# sourceMappingURL=UploadList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UploadList.d.ts","sourceRoot":"","sources":["../../src/upload/UploadList.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,MAAM,WAAW,eAAe;IAC5B,qDAAqD;IACrD,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EACvB,KAAK,EACL,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,YAAY,EAAE,SAAS,EACvB,SAAS,GACZ,EAAE,eAAe,sCAsGjB"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { cx } from "../shared/cx.js";
|
|
2
|
+
import { messages } from "../shared/messages.js";
|
|
3
|
+
import UploadList_module_default from "./UploadList.module.js";
|
|
4
|
+
import { formatSize } from "./files.js";
|
|
5
|
+
import { c } from "react/compiler-runtime";
|
|
6
|
+
import { IconButton, usePanneauIntl } from "@panneau/ui";
|
|
7
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { Pause, Play, RotateCcw, X } from "lucide-react";
|
|
9
|
+
import { ProgressBar } from "react-aria-components";
|
|
10
|
+
//#region src/upload/UploadList.tsx
|
|
11
|
+
/**
|
|
12
|
+
* The files being uploaded: a progress bar for each, and buttons to pause and resume a file sent
|
|
13
|
+
* in parts, to cancel it, and to retry it when it failed. Renders nothing without files.
|
|
14
|
+
*/
|
|
15
|
+
function UploadList(t0) {
|
|
16
|
+
const $ = c(22);
|
|
17
|
+
const { items, onPause, onResume, onCancel, onRetry, "aria-label": ariaLabel, className } = t0;
|
|
18
|
+
const intl = usePanneauIntl();
|
|
19
|
+
if (items.length === 0) return null;
|
|
20
|
+
let t1;
|
|
21
|
+
if ($[0] !== className) {
|
|
22
|
+
t1 = cx(UploadList_module_default.list, className);
|
|
23
|
+
$[0] = className;
|
|
24
|
+
$[1] = t1;
|
|
25
|
+
} else t1 = $[1];
|
|
26
|
+
let t2;
|
|
27
|
+
if ($[2] !== ariaLabel || $[3] !== intl) {
|
|
28
|
+
t2 = ariaLabel ?? intl.formatMessage(messages.uploads);
|
|
29
|
+
$[2] = ariaLabel;
|
|
30
|
+
$[3] = intl;
|
|
31
|
+
$[4] = t2;
|
|
32
|
+
} else t2 = $[4];
|
|
33
|
+
let t3;
|
|
34
|
+
if ($[5] !== intl || $[6] !== items || $[7] !== onCancel || $[8] !== onPause || $[9] !== onResume || $[10] !== onRetry) {
|
|
35
|
+
let t4;
|
|
36
|
+
if ($[12] !== intl || $[13] !== onCancel || $[14] !== onPause || $[15] !== onResume || $[16] !== onRetry) {
|
|
37
|
+
t4 = (item) => {
|
|
38
|
+
const { name } = item;
|
|
39
|
+
const failed = item.status === "failed";
|
|
40
|
+
const indeterminate = item.progress === null || item.status === "completing";
|
|
41
|
+
const status = {
|
|
42
|
+
uploading: intl.formatMessage(messages.uploading),
|
|
43
|
+
paused: intl.formatMessage(messages.uploadPaused),
|
|
44
|
+
completing: intl.formatMessage(messages.uploadCompleting),
|
|
45
|
+
failed: intl.formatMessage(messages.uploadFailed, { error: item.error ?? "" })
|
|
46
|
+
}[item.status];
|
|
47
|
+
const percent = item.progress === null ? null : Math.round(item.progress * 100);
|
|
48
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
49
|
+
className: cx(UploadList_module_default.item, failed && UploadList_module_default.failed),
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ jsxs("span", {
|
|
52
|
+
className: UploadList_module_default.name,
|
|
53
|
+
children: [name, item.size !== null ? ` · ${formatSize(item.size, intl.locale)}` : null]
|
|
54
|
+
}),
|
|
55
|
+
/* @__PURE__ */ jsxs("span", {
|
|
56
|
+
className: UploadList_module_default.buttons,
|
|
57
|
+
children: [
|
|
58
|
+
item.canPause && item.status === "uploading" && onPause ? /* @__PURE__ */ jsx(IconButton, {
|
|
59
|
+
icon: Pause,
|
|
60
|
+
size: "sm",
|
|
61
|
+
label: intl.formatMessage(messages.pauseUpload, { name }),
|
|
62
|
+
onPress: () => onPause(item.id)
|
|
63
|
+
}) : null,
|
|
64
|
+
item.status === "paused" && onResume ? /* @__PURE__ */ jsx(IconButton, {
|
|
65
|
+
icon: Play,
|
|
66
|
+
size: "sm",
|
|
67
|
+
label: intl.formatMessage(messages.resumeUpload, { name }),
|
|
68
|
+
onPress: () => onResume(item.id)
|
|
69
|
+
}) : null,
|
|
70
|
+
failed && onRetry ? /* @__PURE__ */ jsx(IconButton, {
|
|
71
|
+
icon: RotateCcw,
|
|
72
|
+
size: "sm",
|
|
73
|
+
label: intl.formatMessage(messages.retryUpload, { name }),
|
|
74
|
+
onPress: () => onRetry(item.id)
|
|
75
|
+
}) : null,
|
|
76
|
+
item.status !== "completing" && onCancel ? /* @__PURE__ */ jsx(IconButton, {
|
|
77
|
+
icon: X,
|
|
78
|
+
size: "sm",
|
|
79
|
+
label: intl.formatMessage(messages.cancelUpload, { name }),
|
|
80
|
+
onPress: () => onCancel(item.id)
|
|
81
|
+
}) : null
|
|
82
|
+
]
|
|
83
|
+
}),
|
|
84
|
+
failed ? /* @__PURE__ */ jsx("span", {
|
|
85
|
+
className: UploadList_module_default.error,
|
|
86
|
+
role: "alert",
|
|
87
|
+
children: status
|
|
88
|
+
}) : /* @__PURE__ */ jsx(ProgressBar, {
|
|
89
|
+
"aria-label": name,
|
|
90
|
+
className: cx(UploadList_module_default.progress, indeterminate && UploadList_module_default.indeterminate),
|
|
91
|
+
value: percent ?? 0,
|
|
92
|
+
isIndeterminate: indeterminate,
|
|
93
|
+
valueLabel: item.progress !== null && !indeterminate ? `${status} · ${intl.formatNumber(item.progress, { style: "percent" })}` : status,
|
|
94
|
+
children: (t5) => {
|
|
95
|
+
const { valueText } = t5;
|
|
96
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
97
|
+
className: UploadList_module_default.status,
|
|
98
|
+
children: valueText
|
|
99
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
100
|
+
className: UploadList_module_default.track,
|
|
101
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
102
|
+
className: UploadList_module_default.fill,
|
|
103
|
+
style: indeterminate ? void 0 : { width: `${String(percent ?? 0)}%` }
|
|
104
|
+
})
|
|
105
|
+
})] });
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
]
|
|
109
|
+
}, item.id);
|
|
110
|
+
};
|
|
111
|
+
$[12] = intl;
|
|
112
|
+
$[13] = onCancel;
|
|
113
|
+
$[14] = onPause;
|
|
114
|
+
$[15] = onResume;
|
|
115
|
+
$[16] = onRetry;
|
|
116
|
+
$[17] = t4;
|
|
117
|
+
} else t4 = $[17];
|
|
118
|
+
t3 = items.map(t4);
|
|
119
|
+
$[5] = intl;
|
|
120
|
+
$[6] = items;
|
|
121
|
+
$[7] = onCancel;
|
|
122
|
+
$[8] = onPause;
|
|
123
|
+
$[9] = onResume;
|
|
124
|
+
$[10] = onRetry;
|
|
125
|
+
$[11] = t3;
|
|
126
|
+
} else t3 = $[11];
|
|
127
|
+
let t4;
|
|
128
|
+
if ($[18] !== t1 || $[19] !== t2 || $[20] !== t3) {
|
|
129
|
+
t4 = /* @__PURE__ */ jsx("ul", {
|
|
130
|
+
className: t1,
|
|
131
|
+
"aria-label": t2,
|
|
132
|
+
children: t3
|
|
133
|
+
});
|
|
134
|
+
$[18] = t1;
|
|
135
|
+
$[19] = t2;
|
|
136
|
+
$[20] = t3;
|
|
137
|
+
$[21] = t4;
|
|
138
|
+
} else t4 = $[21];
|
|
139
|
+
return t4;
|
|
140
|
+
}
|
|
141
|
+
//#endregion
|
|
142
|
+
export { UploadList };
|
|
143
|
+
|
|
144
|
+
//# sourceMappingURL=UploadList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UploadList.js","names":["name","Pause","Play","RotateCcw","X","status","indeterminate","valueText","_c","styles","_Fragment"],"sources":["../../src/upload/UploadList.tsx"],"sourcesContent":["import { Pause, Play, RotateCcw, X } from 'lucide-react';\nimport { ProgressBar } from 'react-aria-components';\n\nimport { IconButton, usePanneauIntl } from '@panneau/ui';\n\nimport { cx } from '../shared/cx';\nimport { messages } from '../shared/messages';\nimport styles from './UploadList.module.css';\nimport { formatSize } from './files';\nimport type { UploadItem } from './types';\n\nexport interface UploadListProps {\n /** The files being uploaded, from `useUploads()`. */\n items: readonly UploadItem[];\n onPause?: (id: string) => void;\n onResume?: (id: string) => void;\n onCancel?: (id: string) => void;\n onRetry?: (id: string) => void;\n /** Accessible name of the list. Defaults to \"Uploads\". */\n 'aria-label'?: string;\n className?: string;\n}\n\n/**\n * The files being uploaded: a progress bar for each, and buttons to pause and resume a file sent\n * in parts, to cancel it, and to retry it when it failed. Renders nothing without files.\n */\nexport function UploadList({\n items,\n onPause,\n onResume,\n onCancel,\n onRetry,\n 'aria-label': ariaLabel,\n className,\n}: UploadListProps) {\n const intl = usePanneauIntl();\n if (items.length === 0) {\n return null;\n }\n return (\n <ul\n className={cx(styles.list, className)}\n aria-label={ariaLabel ?? intl.formatMessage(messages.uploads)}\n >\n {items.map((item) => {\n const { name } = item;\n const failed = item.status === 'failed';\n const indeterminate = item.progress === null || item.status === 'completing';\n const status = {\n uploading: intl.formatMessage(messages.uploading),\n paused: intl.formatMessage(messages.uploadPaused),\n completing: intl.formatMessage(messages.uploadCompleting),\n failed: intl.formatMessage(messages.uploadFailed, { error: item.error ?? '' }),\n }[item.status];\n const percent = item.progress === null ? null : Math.round(item.progress * 100);\n return (\n <li key={item.id} className={cx(styles.item, failed && styles.failed)}>\n <span className={styles.name}>\n {name}\n {item.size !== null ? ` · ${formatSize(item.size, intl.locale)}` : null}\n </span>\n <span className={styles.buttons}>\n {item.canPause && item.status === 'uploading' && onPause ? (\n <IconButton\n icon={Pause}\n size=\"sm\"\n label={intl.formatMessage(messages.pauseUpload, { name })}\n onPress={() => onPause(item.id)}\n />\n ) : null}\n {item.status === 'paused' && onResume ? (\n <IconButton\n icon={Play}\n size=\"sm\"\n label={intl.formatMessage(messages.resumeUpload, { name })}\n onPress={() => onResume(item.id)}\n />\n ) : null}\n {failed && onRetry ? (\n <IconButton\n icon={RotateCcw}\n size=\"sm\"\n label={intl.formatMessage(messages.retryUpload, { name })}\n onPress={() => onRetry(item.id)}\n />\n ) : null}\n {item.status !== 'completing' && onCancel ? (\n <IconButton\n icon={X}\n size=\"sm\"\n label={intl.formatMessage(messages.cancelUpload, { name })}\n onPress={() => onCancel(item.id)}\n />\n ) : null}\n </span>\n {failed ? (\n <span className={styles.error} role=\"alert\">\n {status}\n </span>\n ) : (\n <ProgressBar\n aria-label={name}\n className={cx(\n styles.progress,\n indeterminate && styles.indeterminate,\n )}\n value={percent ?? 0}\n isIndeterminate={indeterminate}\n valueLabel={\n item.progress !== null && !indeterminate\n ? `${status} · ${intl.formatNumber(item.progress, { style: 'percent' })}`\n : status\n }\n >\n {({ valueText }) => (\n <>\n <span className={styles.status}>{valueText}</span>\n <span className={styles.track}>\n <span\n className={styles.fill}\n style={\n indeterminate\n ? undefined\n : { width: `${String(percent ?? 0)}%` }\n }\n />\n </span>\n </>\n )}\n </ProgressBar>\n )}\n </li>\n );\n })}\n </ul>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import "./UploadList.css";
|
|
2
|
+
//#region src/upload/UploadList.module.css
|
|
3
|
+
var list = "panneau-upload-list-list";
|
|
4
|
+
var item = "panneau-upload-list-item";
|
|
5
|
+
var failed = "panneau-upload-list-failed";
|
|
6
|
+
var name = "panneau-upload-list-name";
|
|
7
|
+
var buttons = "panneau-upload-list-buttons";
|
|
8
|
+
var progress = "panneau-upload-list-progress";
|
|
9
|
+
var status = "panneau-upload-list-status";
|
|
10
|
+
var error = "panneau-upload-list-error";
|
|
11
|
+
var track = "panneau-upload-list-track";
|
|
12
|
+
var fill = "panneau-upload-list-fill";
|
|
13
|
+
var indeterminate = "panneau-upload-list-indeterminate";
|
|
14
|
+
var slide = "panneau-upload-list-slide";
|
|
15
|
+
var UploadList_module_default = {
|
|
16
|
+
list,
|
|
17
|
+
item,
|
|
18
|
+
failed,
|
|
19
|
+
name,
|
|
20
|
+
buttons,
|
|
21
|
+
progress,
|
|
22
|
+
status,
|
|
23
|
+
error,
|
|
24
|
+
track,
|
|
25
|
+
fill,
|
|
26
|
+
indeterminate,
|
|
27
|
+
slide
|
|
28
|
+
};
|
|
29
|
+
//#endregion
|
|
30
|
+
export { buttons, UploadList_module_default as default, error, failed, fill, indeterminate, item, list, name, progress, slide, status, track };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=UploadList.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UploadList.module.js","names":[],"sources":["../../src/upload/UploadList.module.css"],"sourcesContent":[".list {\n display: grid;\n gap: var(--panneau-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.item {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n gap: var(--panneau-space-1) var(--panneau-space-2);\n padding: var(--panneau-space-2) var(--panneau-space-3);\n background-color: var(--panneau-color-surface-sunken);\n border: var(--panneau-border-width) solid var(--panneau-color-border);\n border-radius: var(--panneau-radius-md);\n}\n\n.failed {\n border-color: var(--panneau-color-danger-border);\n}\n\n.name {\n overflow: hidden;\n font-size: var(--panneau-font-size-sm);\n font-weight: var(--panneau-font-weight-medium);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.buttons {\n display: flex;\n gap: var(--panneau-space-1);\n}\n\n.progress {\n grid-column: 1 / -1;\n display: grid;\n gap: var(--panneau-space-1);\n}\n\n.status {\n font-size: var(--panneau-font-size-sm);\n color: var(--panneau-color-text-muted);\n}\n\n.error {\n grid-column: 1 / -1;\n font-size: var(--panneau-font-size-sm);\n color: var(--panneau-color-danger);\n}\n\n.track {\n height: 0.375rem;\n overflow: hidden;\n background: var(--panneau-color-surface);\n border-radius: var(--panneau-radius-full);\n}\n\n.fill {\n display: block;\n height: 100%;\n background: var(--panneau-color-accent);\n border-radius: inherit;\n transition: width var(--panneau-duration) ease-out;\n}\n\n.indeterminate .fill {\n width: 30%;\n animation: slide 1.2s ease-in-out infinite;\n}\n\n@keyframes slide {\n from {\n transform: translateX(-100%);\n }\n to {\n transform: translateX(340%);\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .fill {\n transition: none;\n }\n\n .indeterminate .fill {\n width: 100%;\n animation: none;\n opacity: 0.5;\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Whether a MIME type matches one of the patterns of an `accept` rule (`image/*`, `application/pdf`). */
|
|
2
|
+
export declare function matchesMime(mime: string, patterns: readonly string[]): boolean;
|
|
3
|
+
/** A size in bytes, for people: `1.5 MB`. Uses the locale's number format. */
|
|
4
|
+
export declare function formatSize(bytes: number, locale?: string): string;
|
|
5
|
+
//# sourceMappingURL=files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/upload/files.ts"],"names":[],"mappings":"AAAA,0GAA0G;AAC1G,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAI9E;AAID,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAWjE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/upload/files.ts
|
|
2
|
+
/** Whether a MIME type matches one of the patterns of an `accept` rule (`image/*`, `application/pdf`). */
|
|
3
|
+
function matchesMime(mime, patterns) {
|
|
4
|
+
return patterns.some((pattern) => pattern.endsWith("/*") ? mime.startsWith(pattern.slice(0, -1)) : mime === pattern);
|
|
5
|
+
}
|
|
6
|
+
var UNITS = [
|
|
7
|
+
"B",
|
|
8
|
+
"KB",
|
|
9
|
+
"MB",
|
|
10
|
+
"GB",
|
|
11
|
+
"TB"
|
|
12
|
+
];
|
|
13
|
+
/** A size in bytes, for people: `1.5 MB`. Uses the locale's number format. */
|
|
14
|
+
function formatSize(bytes, locale) {
|
|
15
|
+
let value = bytes;
|
|
16
|
+
let unit = 0;
|
|
17
|
+
while (value >= 1024 && unit < UNITS.length - 1) {
|
|
18
|
+
value /= 1024;
|
|
19
|
+
unit += 1;
|
|
20
|
+
}
|
|
21
|
+
return `${new Intl.NumberFormat(locale, { maximumFractionDigits: unit === 0 || value >= 10 ? 0 : 1 }).format(value)} ${UNITS[unit] ?? "B"}`;
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { formatSize, matchesMime };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","names":[],"sources":["../../src/upload/files.ts"],"sourcesContent":["/** Whether a MIME type matches one of the patterns of an `accept` rule (`image/*`, `application/pdf`). */\nexport function matchesMime(mime: string, patterns: readonly string[]): boolean {\n return patterns.some((pattern) =>\n pattern.endsWith('/*') ? mime.startsWith(pattern.slice(0, -1)) : mime === pattern,\n );\n}\n\nconst UNITS = ['B', 'KB', 'MB', 'GB', 'TB'] as const;\n\n/** A size in bytes, for people: `1.5 MB`. Uses the locale's number format. */\nexport function formatSize(bytes: number, locale?: string): string {\n let value = bytes;\n let unit = 0;\n while (value >= 1024 && unit < UNITS.length - 1) {\n value /= 1024;\n unit += 1;\n }\n const number = new Intl.NumberFormat(locale, {\n maximumFractionDigits: unit === 0 || value >= 10 ? 0 : 1,\n }).format(value);\n return `${number} ${UNITS[unit] ?? 'B'}`;\n}\n"],"mappings":";;AACA,SAAgB,YAAY,MAAc,UAAsC;CAC5E,OAAO,SAAS,MAAM,YAClB,QAAQ,SAAS,IAAI,IAAI,KAAK,WAAW,QAAQ,MAAM,GAAG,EAAE,CAAC,IAAI,SAAS,OAC9E;AACJ;AAEA,IAAM,QAAQ;CAAC;CAAK;CAAM;CAAM;CAAM;AAAI;;AAG1C,SAAgB,WAAW,OAAe,QAAyB;CAC/D,IAAI,QAAQ;CACZ,IAAI,OAAO;CACX,OAAO,SAAS,QAAQ,OAAO,MAAM,SAAS,GAAG;EAC7C,SAAS;EACT,QAAQ;CACZ;CAIA,OAAO,GAHQ,IAAI,KAAK,aAAa,QAAQ,EACzC,uBAAuB,SAAS,KAAK,SAAS,KAAK,IAAI,EAC3D,CAAC,CAAC,CAAC,OAAO,KACA,EAAM,GAAI,MAAM,SAAS;AACvC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** Where a file is: sent to storage, paused, completed with the backend, or failed. */
|
|
2
|
+
export type UploadItemStatus = 'uploading' | 'paused' | 'completing' | 'failed';
|
|
3
|
+
/** A file being uploaded, as an upload list shows it. */
|
|
4
|
+
export interface UploadItem {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
size: number | null;
|
|
8
|
+
mime: string | null;
|
|
9
|
+
/** From 0 to 1, or null until the upload reports one. */
|
|
10
|
+
progress: number | null;
|
|
11
|
+
status: UploadItemStatus;
|
|
12
|
+
/** Why it failed. */
|
|
13
|
+
error: string | null;
|
|
14
|
+
/** Whether it can pause: only a file sent in parts can. */
|
|
15
|
+
canPause: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A file uploaded directly to storage: the reference that values send (`{ upload }`), with what
|
|
19
|
+
* the browser knows of the file, so that fields can show it and check it before saving. Backends
|
|
20
|
+
* only trust `upload`.
|
|
21
|
+
*/
|
|
22
|
+
export interface UploadedFile {
|
|
23
|
+
upload: string;
|
|
24
|
+
name: string;
|
|
25
|
+
mime: string | null;
|
|
26
|
+
size: number | null;
|
|
27
|
+
}
|
|
28
|
+
/** Why a file was refused before it was sent. */
|
|
29
|
+
export type UploadRejection = 'accept' | 'maxSize';
|
|
30
|
+
/** Uploads files and keeps their state, for an upload list. */
|
|
31
|
+
export interface Uploader {
|
|
32
|
+
/** The files being uploaded, in the order they were added. Done files leave the list. */
|
|
33
|
+
getItems(): readonly UploadItem[];
|
|
34
|
+
/** Calls the listener when the items change. Returns a function that unsubscribes. */
|
|
35
|
+
subscribe(listener: () => void): () => void;
|
|
36
|
+
/** Sends files. */
|
|
37
|
+
add(files: Iterable<File>): void;
|
|
38
|
+
pause(id: string): void;
|
|
39
|
+
resume(id: string): void;
|
|
40
|
+
/** Stops a file and removes it from the list. */
|
|
41
|
+
cancel(id: string): void;
|
|
42
|
+
/** Sends a failed file again. */
|
|
43
|
+
retry(id: string): void;
|
|
44
|
+
/** Stops every upload. The uploader can't be used after. */
|
|
45
|
+
destroy(): void;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Where fields that take files upload them directly to storage (decision 0025):
|
|
49
|
+
* `createUppyUploadSource()` of `@panneau/fields/uppy`, with the signing routes of the backend.
|
|
50
|
+
* Without one, fields give the files themselves, which the adapter sends in `multipart/form-data`.
|
|
51
|
+
*/
|
|
52
|
+
export interface UploadSource {
|
|
53
|
+
/** An uploader for a field, which calls `onUploaded` with each file once it is uploaded. */
|
|
54
|
+
createUploader(options: {
|
|
55
|
+
onUploaded: (file: UploadedFile) => void;
|
|
56
|
+
}): Uploader;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/upload/types.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,QAAQ,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEhF,yDAAyD;AACzD,MAAM,WAAW,UAAU;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,gBAAgB,CAAC;IACzB,qBAAqB;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,2DAA2D;IAC3D,QAAQ,EAAE,OAAO,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,iDAAiD;AACjD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEnD,+DAA+D;AAC/D,MAAM,WAAW,QAAQ;IACrB,yFAAyF;IACzF,QAAQ,IAAI,SAAS,UAAU,EAAE,CAAC;IAClC,sFAAsF;IACtF,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC5C,mBAAmB;IACnB,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,iDAAiD;IACjD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,iCAAiC;IACjC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,4DAA4D;IAC5D,OAAO,IAAI,IAAI,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IACzB,4FAA4F;IAC5F,cAAc,CAAC,OAAO,EAAE;QAAE,UAAU,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAA;KAAE,GAAG,QAAQ,CAAC;CACnF"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { UploadRejection } from './types';
|
|
2
|
+
/** The message of a file refused before it was sent, for a field's errors. */
|
|
3
|
+
export declare function useRejectionMessage(maxSize: number | null | undefined): (file: File, reason: UploadRejection) => string;
|
|
4
|
+
//# sourceMappingURL=useRejectionMessage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRejectionMessage.d.ts","sourceRoot":"","sources":["../../src/upload/useRejectionMessage.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACnC,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,KAAK,MAAM,CASjD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { messages } from "../shared/messages.js";
|
|
2
|
+
import { formatSize } from "./files.js";
|
|
3
|
+
import { c } from "react/compiler-runtime";
|
|
4
|
+
import { usePanneauIntl } from "@panneau/ui";
|
|
5
|
+
//#region src/upload/useRejectionMessage.ts
|
|
6
|
+
/** The message of a file refused before it was sent, for a field's errors. */
|
|
7
|
+
function useRejectionMessage(maxSize) {
|
|
8
|
+
const $ = c(3);
|
|
9
|
+
const intl = usePanneauIntl();
|
|
10
|
+
let t0;
|
|
11
|
+
if ($[0] !== intl || $[1] !== maxSize) {
|
|
12
|
+
t0 = (file, reason) => reason === "accept" ? intl.formatMessage(messages.rejectedType, { name: file.name }) : intl.formatMessage(messages.rejectedSize, {
|
|
13
|
+
name: file.name,
|
|
14
|
+
size: formatSize(maxSize ?? 0, intl.locale)
|
|
15
|
+
});
|
|
16
|
+
$[0] = intl;
|
|
17
|
+
$[1] = maxSize;
|
|
18
|
+
$[2] = t0;
|
|
19
|
+
} else t0 = $[2];
|
|
20
|
+
return t0;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { useRejectionMessage };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=useRejectionMessage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRejectionMessage.js","names":["_c"],"sources":["../../src/upload/useRejectionMessage.ts"],"sourcesContent":["import { usePanneauIntl } from '@panneau/ui';\n\nimport { messages } from '../shared/messages';\nimport { formatSize } from './files';\nimport type { UploadRejection } from './types';\n\n/** The message of a file refused before it was sent, for a field's errors. */\nexport function useRejectionMessage(\n maxSize: number | null | undefined,\n): (file: File, reason: UploadRejection) => string {\n const intl = usePanneauIntl();\n return (file, reason) =>\n reason === 'accept'\n ? intl.formatMessage(messages.rejectedType, { name: file.name })\n : intl.formatMessage(messages.rejectedSize, {\n name: file.name,\n size: formatSize(maxSize ?? 0, intl.locale),\n });\n}\n"],"mappings":";;;;;;AAOA,SAAO,oBAAA,SAAA;CAAA,MAAA,IAAAA,EAAA,CAAA;CAGH,MAAA,OAAa,eAAe;CAAE,IAAA;CAAA,IAAA,EAAA,OAAA,QAAA,EAAA,OAAA,SAAA;EACvB,MAAA,MAAA,WACH,WAAW,WACL,KAAI,cAAe,SAAQ,cAAe,EAAA,MAAQ,KAAI,KAAM,CAI3D,IAHD,KAAI,cAAe,SAAQ,cAAe;GAAA,MAChC,KAAI;GAAK,MACT,WAAW,WAAA,GAAc,KAAI,MAAO;EAC9C,CAAC;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OANL;AAMK"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { UploadItem, UploadRejection, UploadSource, UploadedFile } from './types';
|
|
2
|
+
export interface UseUploadsOptions {
|
|
3
|
+
/** Where files are uploaded. Without one, `add()` gives the files themselves. */
|
|
4
|
+
source: UploadSource | null;
|
|
5
|
+
/** Accepted MIME types (`image/*`). Others are refused before they are sent. */
|
|
6
|
+
accept?: readonly string[] | null;
|
|
7
|
+
/** Largest file, in bytes. Larger ones are refused before they are sent. */
|
|
8
|
+
maxSize?: number | null;
|
|
9
|
+
/** Called with each file once it is uploaded: its upload, or the file itself without a source. */
|
|
10
|
+
onUploaded: (file: UploadedFile | File) => void;
|
|
11
|
+
/** Called with each file refused before it was sent. */
|
|
12
|
+
onRejected?: (file: File, reason: UploadRejection) => void;
|
|
13
|
+
}
|
|
14
|
+
export interface UseUploadsResult {
|
|
15
|
+
/** The files being uploaded. */
|
|
16
|
+
items: readonly UploadItem[];
|
|
17
|
+
add: (files: Iterable<File>) => void;
|
|
18
|
+
pause: (id: string) => void;
|
|
19
|
+
resume: (id: string) => void;
|
|
20
|
+
cancel: (id: string) => void;
|
|
21
|
+
retry: (id: string) => void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Checks files against `accept` and `maxSize`, uploads them through an upload source, and gives
|
|
25
|
+
* the state of each file for an upload list. Without a source, files are given back as they are,
|
|
26
|
+
* to send in a multipart request. The uploader is made once per source, and stopped when the
|
|
27
|
+
* component unmounts.
|
|
28
|
+
*/
|
|
29
|
+
export declare function useUploads(options: UseUploadsOptions): UseUploadsResult;
|
|
30
|
+
//# sourceMappingURL=useUploads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUploads.d.ts","sourceRoot":"","sources":["../../src/upload/useUploads.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAY,MAAM,SAAS,CAAC;AAEjG,MAAM,WAAW,iBAAiB;IAC9B,iFAAiF;IACjF,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,gFAAgF;IAChF,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAClC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kGAAkG;IAClG,UAAU,EAAE,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD,wDAAwD;IACxD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;CAC9D;AAED,MAAM,WAAW,gBAAgB;IAC7B,gCAAgC;IAChC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IAC7B,GAAG,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC;IACrC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AAmBD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CA8CvE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { matchesMime } from "./files.js";
|
|
2
|
+
import { c } from "react/compiler-runtime";
|
|
3
|
+
import { useEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
4
|
+
//#region src/upload/useUploads.ts
|
|
5
|
+
var NO_ITEMS = [];
|
|
6
|
+
function rejects(file, { accept, maxSize }) {
|
|
7
|
+
if (accept !== null && accept !== void 0 && accept.length > 0 && !matchesMime(file.type, accept)) return "accept";
|
|
8
|
+
return maxSize !== null && maxSize !== void 0 && file.size > maxSize ? "maxSize" : null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Checks files against `accept` and `maxSize`, uploads them through an upload source, and gives
|
|
12
|
+
* the state of each file for an upload list. Without a source, files are given back as they are,
|
|
13
|
+
* to send in a multipart request. The uploader is made once per source, and stopped when the
|
|
14
|
+
* component unmounts.
|
|
15
|
+
*/
|
|
16
|
+
function useUploads(options) {
|
|
17
|
+
const $ = c(16);
|
|
18
|
+
const latest = useRef(options);
|
|
19
|
+
let t0;
|
|
20
|
+
if ($[0] !== options) {
|
|
21
|
+
t0 = () => {
|
|
22
|
+
latest.current = options;
|
|
23
|
+
};
|
|
24
|
+
$[0] = options;
|
|
25
|
+
$[1] = t0;
|
|
26
|
+
} else t0 = $[1];
|
|
27
|
+
useEffect(t0);
|
|
28
|
+
const { source } = options;
|
|
29
|
+
const [state, setState] = useState(null);
|
|
30
|
+
const uploader = state !== null && state.source === source ? state.uploader : null;
|
|
31
|
+
let t1;
|
|
32
|
+
let t2;
|
|
33
|
+
if ($[2] !== source) {
|
|
34
|
+
t1 = () => {
|
|
35
|
+
if (source === null) return;
|
|
36
|
+
const created = source.createUploader({ onUploaded: (file) => latest.current.onUploaded(file) });
|
|
37
|
+
setState({
|
|
38
|
+
source,
|
|
39
|
+
uploader: created
|
|
40
|
+
});
|
|
41
|
+
return () => created.destroy();
|
|
42
|
+
};
|
|
43
|
+
t2 = [source];
|
|
44
|
+
$[2] = source;
|
|
45
|
+
$[3] = t1;
|
|
46
|
+
$[4] = t2;
|
|
47
|
+
} else {
|
|
48
|
+
t1 = $[3];
|
|
49
|
+
t2 = $[4];
|
|
50
|
+
}
|
|
51
|
+
useEffect(t1, t2);
|
|
52
|
+
let t3;
|
|
53
|
+
let t4;
|
|
54
|
+
if ($[5] !== uploader) {
|
|
55
|
+
t3 = (listener) => uploader?.subscribe(listener) ?? _temp;
|
|
56
|
+
t4 = () => uploader?.getItems() ?? NO_ITEMS;
|
|
57
|
+
$[5] = uploader;
|
|
58
|
+
$[6] = t3;
|
|
59
|
+
$[7] = t4;
|
|
60
|
+
} else {
|
|
61
|
+
t3 = $[6];
|
|
62
|
+
t4 = $[7];
|
|
63
|
+
}
|
|
64
|
+
const items = useSyncExternalStore(t3, t4, _temp2);
|
|
65
|
+
let t5;
|
|
66
|
+
if ($[8] !== items || $[9] !== uploader) {
|
|
67
|
+
let t6;
|
|
68
|
+
let t7;
|
|
69
|
+
let t8;
|
|
70
|
+
let t9;
|
|
71
|
+
if ($[11] !== uploader) {
|
|
72
|
+
t6 = (id) => uploader?.pause(id);
|
|
73
|
+
t7 = (id_0) => uploader?.resume(id_0);
|
|
74
|
+
t8 = (id_1) => uploader?.cancel(id_1);
|
|
75
|
+
t9 = (id_2) => uploader?.retry(id_2);
|
|
76
|
+
$[11] = uploader;
|
|
77
|
+
$[12] = t6;
|
|
78
|
+
$[13] = t7;
|
|
79
|
+
$[14] = t8;
|
|
80
|
+
$[15] = t9;
|
|
81
|
+
} else {
|
|
82
|
+
t6 = $[12];
|
|
83
|
+
t7 = $[13];
|
|
84
|
+
t8 = $[14];
|
|
85
|
+
t9 = $[15];
|
|
86
|
+
}
|
|
87
|
+
t5 = {
|
|
88
|
+
items,
|
|
89
|
+
add(files) {
|
|
90
|
+
for (const file_0 of files) {
|
|
91
|
+
const rejection = rejects(file_0, latest.current);
|
|
92
|
+
if (rejection !== null) latest.current.onRejected?.(file_0, rejection);
|
|
93
|
+
else if (uploader === null) latest.current.onUploaded(file_0);
|
|
94
|
+
else uploader.add([file_0]);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
pause: t6,
|
|
98
|
+
resume: t7,
|
|
99
|
+
cancel: t8,
|
|
100
|
+
retry: t9
|
|
101
|
+
};
|
|
102
|
+
$[8] = items;
|
|
103
|
+
$[9] = uploader;
|
|
104
|
+
$[10] = t5;
|
|
105
|
+
} else t5 = $[10];
|
|
106
|
+
return t5;
|
|
107
|
+
}
|
|
108
|
+
function _temp2() {
|
|
109
|
+
return NO_ITEMS;
|
|
110
|
+
}
|
|
111
|
+
function _temp() {}
|
|
112
|
+
//#endregion
|
|
113
|
+
export { useUploads };
|
|
114
|
+
|
|
115
|
+
//# sourceMappingURL=useUploads.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUploads.js","names":["id","file","_c"],"sources":["../../src/upload/useUploads.ts"],"sourcesContent":["import { useEffect, useRef, useState, useSyncExternalStore } from 'react';\n\nimport { matchesMime } from './files';\nimport type { UploadItem, UploadRejection, UploadSource, UploadedFile, Uploader } from './types';\n\nexport interface UseUploadsOptions {\n /** Where files are uploaded. Without one, `add()` gives the files themselves. */\n source: UploadSource | null;\n /** Accepted MIME types (`image/*`). Others are refused before they are sent. */\n accept?: readonly string[] | null;\n /** Largest file, in bytes. Larger ones are refused before they are sent. */\n maxSize?: number | null;\n /** Called with each file once it is uploaded: its upload, or the file itself without a source. */\n onUploaded: (file: UploadedFile | File) => void;\n /** Called with each file refused before it was sent. */\n onRejected?: (file: File, reason: UploadRejection) => void;\n}\n\nexport interface UseUploadsResult {\n /** The files being uploaded. */\n items: readonly UploadItem[];\n add: (files: Iterable<File>) => void;\n pause: (id: string) => void;\n resume: (id: string) => void;\n cancel: (id: string) => void;\n retry: (id: string) => void;\n}\n\nconst NO_ITEMS: readonly UploadItem[] = [];\n\nfunction rejects(\n file: File,\n { accept, maxSize }: Pick<UseUploadsOptions, 'accept' | 'maxSize'>,\n): UploadRejection | null {\n if (\n accept !== null &&\n accept !== undefined &&\n accept.length > 0 &&\n !matchesMime(file.type, accept)\n ) {\n return 'accept';\n }\n return maxSize !== null && maxSize !== undefined && file.size > maxSize ? 'maxSize' : null;\n}\n\n/**\n * Checks files against `accept` and `maxSize`, uploads them through an upload source, and gives\n * the state of each file for an upload list. Without a source, files are given back as they are,\n * to send in a multipart request. The uploader is made once per source, and stopped when the\n * component unmounts.\n */\nexport function useUploads(options: UseUploadsOptions): UseUploadsResult {\n // The latest callbacks and limits, read when files are added or uploaded.\n const latest = useRef(options);\n useEffect(() => {\n latest.current = options;\n });\n const { source } = options;\n const [state, setState] = useState<{ source: UploadSource; uploader: Uploader } | null>(null);\n const uploader = state !== null && state.source === source ? state.uploader : null;\n\n useEffect(() => {\n if (source === null) {\n return undefined;\n }\n const created = source.createUploader({\n onUploaded: (file) => latest.current.onUploaded(file),\n });\n setState({ source, uploader: created });\n return () => created.destroy();\n }, [source]);\n\n const items = useSyncExternalStore(\n (listener) => uploader?.subscribe(listener) ?? (() => undefined),\n () => uploader?.getItems() ?? NO_ITEMS,\n () => NO_ITEMS,\n );\n\n return {\n items,\n add(files) {\n for (const file of files) {\n const rejection = rejects(file, latest.current);\n if (rejection !== null) {\n latest.current.onRejected?.(file, rejection);\n } else if (uploader === null) {\n latest.current.onUploaded(file);\n } else {\n uploader.add([file]);\n }\n }\n },\n pause: (id) => uploader?.pause(id),\n resume: (id) => uploader?.resume(id),\n cancel: (id) => uploader?.cancel(id),\n retry: (id) => uploader?.retry(id),\n };\n}\n"],"mappings":";;;;AA4BA,IAAM,WAAkC,CAAA;AAExC,SAAS,QACL,MACA,EAAE,QAAQ,WACY;CACtB,IACI,WAAW,QACX,WAAW,KAAA,KACX,OAAO,SAAS,KAChB,CAAC,YAAY,KAAK,MAAM,MAAM,GAE9B,OAAO;CAEX,OAAO,YAAY,QAAQ,YAAY,KAAA,KAAa,KAAK,OAAO,UAAU,YAAY;AAC1F;;;;;;;AAQA,SAAO,WAAA,SAAA;CAAA,MAAA,IAAAE,EAAA,EAAA;CAEH,MAAA,SAAe,OAAO,OAAO;CAAE,IAAA;CAAA,IAAA,EAAA,OAAA,SAAA;EACrB,WAAA;GACN,OAAM,UAAW;EAAH;EACjB,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA,KAAA,EAAA;CAFD,UAAU,EAET;CACD,MAAA,EAAA,WAAmB;CACnB,MAAA,CAAA,OAAA,YAA0B,SAA8D,IAAI;CAC5F,MAAA,WAAiB,UAAU,QAAQ,MAAK,WAAY,SAAS,MAAK,WAAjD;CAAkE,IAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,QAAA;EAEzE,WAAA;GACN,IAAI,WAAW,MAAI;GAGnB,MAAA,UAAgB,OAAM,eAAgB,EAAA,aACtB,SAAU,OAAM,QAAQ,WAAY,IAAI,EACxD,CAAC;GACD,SAAS;IAAA;IAAA,UAAoB;GAAQ,CAAC;GAAC,aAC1B,QAAO,QAAS;EAAC;EAC/B,KAAA,CAAC,MAAM;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA;EAAA,KAAA,EAAA;EAAA,KAAA,EAAA;CAAA;CATX,UAAU,IASP,EAAQ;CAAC,IAAA;CAAA,IAAA;CAAA,IAAA,EAAA,OAAA,UAAA;EAGR,MAAA,aAAc,UAAQ,UAAY,QAA6B,KAAjD;EACd,WAAM,UAAQ,SAAuB,KAA/B;EAAgC,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,KAAA;CAAA,OAAA;EAAA,KAAA,EAAA;EAAA,KAAA,EAAA;CAAA;CAF1C,MAAA,QAAc,qBACV,IACA,IACA,MACJ;CAAE,IAAA;CAAA,IAAA,EAAA,OAAA,SAAA,EAAA,OAAA,UAAA;EAAA,IAAA;EAAA,IAAA;EAAA,IAAA;EAAA,IAAA;EAAA,IAAA,EAAA,QAAA,UAAA;GAgBS,MAAA,OAAQ,UAAQ,MAAQ,EAAE;GACzB,MAAA,SAAQ,UAAQ,OAASF,IAAE;GAC3B,MAAA,SAAQ,UAAQ,OAASA,IAAE;GAC5B,MAAA,SAAQ,UAAQ,MAAQA,IAAE;GAAC,EAAA,MAAA;GAAA,EAAA,MAAA;GAAA,EAAA,MAAA;GAAA,EAAA,MAAA;GAAA,EAAA,MAAA;EAAA,OAAA;GAAA,KAAA,EAAA;GAAA,KAAA,EAAA;GAAA,KAAA,EAAA;GAAA,KAAA,EAAA;EAAA;EAjB/B,KAAA;GAAA;GAAA,IAAA,OAAA;IAGC,KAAK,MAAA,UAAc,OAAK;KACpB,MAAA,YAAkB,QAAQC,QAAM,OAAM,OAAQ;KAC9C,IAAI,cAAc,MACd,OAAM,QAAQ,aAAcA,QAAM,SAAS;UACxC,IAAI,aAAa,MACpB,OAAM,QAAQ,WAAYA,MAAI;UAE9B,SAAQ,IAAK,CAACA,MAAI,CAAC;IACtB;GACJ;GAAA,OAEE;GAA2B,QAC1B;GAA4B,QAC5B;GAA4B,OAC7B;EACX;EAAC,EAAA,KAAA;EAAA,EAAA,KAAA;EAAA,EAAA,MAAA;CAAA,OAAA,KAAA,EAAA;CAAA,OAlBM;AAkBN;AA7CE,SAAA,SAAA;CAAA,OAwBO;AAAQ;AAxBf,SAAA,QAAA,CAAA"}
|