@panneau/fields 5.0.0-alpha.6 → 5.0.0-alpha.7
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/dist/boolean/BooleanField.js +78 -17
- package/dist/boolean/BooleanField.js.map +1 -1
- package/dist/color/ColorField.js.map +1 -1
- package/dist/date/DateField.js.map +1 -1
- package/dist/datetime/DateTimeField.js +107 -20
- package/dist/datetime/DateTimeField.js.map +1 -1
- package/dist/duration/DurationField.js +126 -41
- package/dist/duration/DurationField.js.map +1 -1
- package/dist/email/EmailField.js.map +1 -1
- package/dist/embed/EmbedField.js +185 -69
- package/dist/embed/EmbedField.js.map +1 -1
- package/dist/file/FileField.d.ts.map +1 -1
- package/dist/file/FileField.js +167 -77
- package/dist/file/FileField.js.map +1 -1
- package/dist/group/GroupField.js.map +1 -1
- package/dist/json/JsonField.js +104 -22
- package/dist/json/JsonField.js.map +1 -1
- package/dist/locales/index.js.map +1 -1
- package/dist/localized/LocalizedField.js.map +1 -1
- package/dist/location/LocationField.d.ts.map +1 -1
- package/dist/location/LocationField.js +351 -138
- package/dist/location/LocationField.js.map +1 -1
- package/dist/location/LocationMap.d.ts.map +1 -1
- package/dist/location/LocationMap.js +155 -65
- package/dist/location/LocationMap.js.map +1 -1
- package/dist/location/leafletCss.js.map +1 -1
- package/dist/location/nominatim.js.map +1 -1
- package/dist/missing/MissingField.d.ts +3 -2
- package/dist/missing/MissingField.d.ts.map +1 -1
- package/dist/missing/MissingField.js +3 -2
- package/dist/missing/MissingField.js.map +1 -1
- package/dist/number/NumberField.js.map +1 -1
- package/dist/range/RangeField.js +82 -11
- package/dist/range/RangeField.js.map +1 -1
- package/dist/relation/RelationField.js +485 -145
- package/dist/relation/RelationField.js.map +1 -1
- package/dist/repeater/RepeaterField.js +118 -34
- package/dist/repeater/RepeaterField.js.map +1 -1
- package/dist/select/SelectField.js.map +1 -1
- package/dist/shared/DefinitionField.js.map +1 -1
- package/dist/shared/builtIn.js.map +1 -1
- package/dist/shared/check.js.map +1 -1
- package/dist/shared/context.js.map +1 -1
- package/dist/shared/cx.js.map +1 -1
- package/dist/shared/dates.js.map +1 -1
- package/dist/shared/embed.js.map +1 -1
- package/dist/shared/entry.js.map +1 -1
- package/dist/shared/relation.js.map +1 -1
- package/dist/slug/SlugField.d.ts.map +1 -1
- package/dist/slug/SlugField.js +184 -36
- package/dist/slug/SlugField.js.map +1 -1
- package/dist/tags/TagsField.js.map +1 -1
- package/dist/tel/TelField.js.map +1 -1
- package/dist/text/TextField.js.map +1 -1
- package/dist/textarea/TextAreaField.js.map +1 -1
- package/dist/time/TimeField.js +64 -10
- package/dist/time/TimeField.js.map +1 -1
- package/dist/upload/FilePicker.js +107 -24
- package/dist/upload/FilePicker.js.map +1 -1
- package/dist/upload/UploadList.js.map +1 -1
- package/dist/upload/files.js.map +1 -1
- package/dist/upload/useRejectionMessage.js.map +1 -1
- package/dist/upload/useUploads.js.map +1 -1
- package/dist/uppy/uploader.js.map +1 -1
- package/dist/url/UrlField.js +69 -14
- package/dist/url/UrlField.js.map +1 -1
- package/package.json +4 -4
package/dist/tel/TelField.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TelField.js","names":["
|
|
1
|
+
{"version":3,"file":"TelField.js","names":["getFieldProps","isString","FieldEntryProps","TextField","TextFieldProps","TelFieldProps","Omit","TelField","t0","$","_c","onBlur","onChange","props","value","t1","trimmed","trim","t2","TelFieldEntry","_c"],"sources":["../../src/tel/TelField.tsx"],"sourcesContent":["import { getFieldProps, isString } from '../shared/entry';\nimport type { FieldEntryProps } from '../shared/types';\nimport { TextField, type TextFieldProps } from '../text/TextField';\n\nexport type TelFieldProps = Omit<TextFieldProps, 'type' | 'inputMode'>;\n\n/**\n * A phone number, as typed, with the phone keyboard on phones. Spaces around it are removed on\n * blur. A `pattern` rule constrains its format when a project needs one.\n */\nexport function TelField({ value, onChange, onBlur, ...props }: TelFieldProps) {\n return (\n <TextField\n autoComplete=\"tel\"\n {...props}\n type=\"tel\"\n inputMode=\"tel\"\n value={value}\n onChange={onChange}\n onBlur={() => {\n const trimmed = value?.trim() ?? null;\n if (trimmed !== value) {\n onChange?.(trimmed === '' ? null : trimmed);\n }\n onBlur?.();\n }}\n />\n );\n}\n\n/** The `tel` type. */\nexport function TelFieldEntry(props: FieldEntryProps) {\n return (\n <TelField\n {...getFieldProps(props)}\n value={isString(props.value) ? props.value : null}\n onChange={props.onChange}\n />\n );\n}\n"],"mappings":";;;;;;;;;AAUA,SAAOO,SAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAL,EAAA,OAAAD,IAAA;EAAkB,CAAA,CAAAM,OAAAF,UAAAD,QAAA,GAAAE,SAAAL;EAAoDC,EAAA,KAAAD;EAAAC,EAAA,KAAAE;EAAAF,EAAA,KAAAG;EAAAH,EAAA,KAAAI;EAAAJ,EAAA,KAAAK;CAAA,OAAA;EAAAH,SAAAF,EAAA;EAAAG,WAAAH,EAAA;EAAAI,QAAAJ,EAAA;EAAAK,QAAAL,EAAA;CAAA;CAAA,IAAAM;CAAA,IAAAN,EAAA,OAAAE,UAAAF,EAAA,OAAAG,YAAAH,EAAA,OAAAK,OAAA;EASzDC,WAAA;GACJ,MAAAC,UAAgBF,OAAKG,KAAe,KAApB;GAChB,IAAID,YAAYF,OACZF,WAAWI,YAAY,KAAZ,OAAAA,OAA+B;GAE9CL,SAAS;EAAC;EACbF,EAAA,KAAAE;EAAAF,EAAA,KAAAG;EAAAH,EAAA,KAAAK;EAAAL,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAAA,IAAAS;CAAA,IAAAT,EAAA,OAAAG,YAAAH,EAAA,QAAAI,SAAAJ,EAAA,QAAAM,MAAAN,EAAA,QAAAK,OAAA;EAbLI,KAAA,oBAAC,WAAD;GACiB,cAAA;GAAK,GACdL;GACC,MAAA;GACK,WAAA;GACHC;GACGF;GACF,QAAAG;EAMP,CAAA;EACHN,EAAA,KAAAG;EAAAH,EAAA,MAAAI;EAAAJ,EAAA,MAAAM;EAAAN,EAAA,MAAAK;EAAAL,EAAA,MAAAS;CAAA,OAAAA,KAAAT,EAAA;CAAA,OAdFS;AAcE;;AAKV,SAAOC,cAAAN,OAAA;CAAA,MAAAJ,IAAAC,EAAA,CAAA;CAAA,IAAAF;CAAA,IAAAC,EAAA,OAAAI,OAAA;EAGSL,KAAAR,cAAca,KAAK;EAACJ,EAAA,KAAAI;EAAAJ,EAAA,KAAAD;CAAA,OAAAA,KAAAC,EAAA;CACjB,MAAAM,KAAAd,SAASY,MAAKC,KAA2B,IAAjBD,MAAKC,QAA7B;CAA0C,IAAAI;CAAA,IAAAT,EAAA,OAAAI,MAAAD,YAAAH,EAAA,OAAAD,MAAAC,EAAA,OAAAM,IAAA;EAFrDG,KAAA,oBAAC,UAAD;GAAS,GACDV;GACG,OAAAO;GACG,UAAAF,MAAKD;EAAS,CAAA;EAC1BH,EAAA,KAAAI,MAAAD;EAAAH,EAAA,KAAAD;EAAAC,EAAA,KAAAM;EAAAN,EAAA,KAAAS;CAAA,OAAAA,KAAAT,EAAA;CAAA,OAJFS;AAIE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextField.js","names":["
|
|
1
|
+
{"version":3,"file":"TextField.js","names":["ReactNode","TextInput","usePanneauIntl","getFieldProps","getRuleNumber","getSetting","isString","messages","FieldEntryProps","FieldProps","TextFieldProps","placeholder","maxLength","prefix","suffix","type","inputMode","autoComplete","controlClassName","inputClassName","useCountedDescription","description","value","$","_c","intl","undefined","t0","formatMessage","characterCount","count","length","max","t1","t2","TextField","disabled","onChange","props","readOnly","required","shownDescription","next","t3","TextFieldEntry","field","t4","t5","t6","t7","t8","_c","_Fragment"],"sources":["../../src/text/TextField.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport { TextInput, usePanneauIntl } from '@panneau/ui';\n\nimport { getFieldProps, getRuleNumber, getSetting, isString } from '../shared/entry';\nimport { messages } from '../shared/messages';\nimport type { FieldEntryProps, FieldProps } from '../shared/types';\n\nexport interface TextFieldProps extends FieldProps<string> {\n placeholder?: string;\n /** Shows a count of characters against this maximum. It doesn't stop typing. */\n maxLength?: number;\n /** Content before the text, inside the control. */\n prefix?: ReactNode;\n /** Content after the text, inside the control. */\n suffix?: ReactNode;\n /** Type of the input. Defaults to `text`. */\n type?: 'text' | 'email' | 'url' | 'tel' | 'password' | 'search';\n inputMode?: 'text' | 'email' | 'url' | 'tel' | 'search' | 'numeric' | 'decimal' | 'none';\n autoComplete?: string;\n controlClassName?: string;\n inputClassName?: string;\n}\n\n/** The description of a text field, with its character count. */\nexport function useCountedDescription(\n description: ReactNode,\n value: string | null | undefined,\n maxLength: number | undefined,\n): ReactNode {\n const intl = usePanneauIntl();\n if (maxLength === undefined) {\n return description;\n }\n const count = intl.formatMessage(messages.characterCount, {\n count: (value ?? '').length,\n max: maxLength,\n });\n if (description === undefined || description === null) {\n return count;\n }\n return (\n <>\n {description} <span>{count}</span>\n </>\n );\n}\n\n/** A single-line text. An empty text is `null`. */\nexport function TextField({\n value,\n onChange,\n description,\n maxLength,\n disabled,\n readOnly,\n required,\n ...props\n}: TextFieldProps) {\n const shownDescription = useCountedDescription(description, value, maxLength);\n return (\n <TextInput\n {...props}\n value={value ?? ''}\n onChange={(next) => onChange?.(next === '' ? null : next)}\n description={shownDescription}\n isDisabled={disabled}\n isReadOnly={readOnly}\n isRequired={required}\n />\n );\n}\n\n/** The `text` type: settings `prefix` and `suffix`, and a character count from the `max` rule. */\nexport function TextFieldEntry(props: FieldEntryProps) {\n const { field } = props;\n const prefix = getSetting(field, 'prefix', isString);\n const suffix = getSetting(field, 'suffix', isString);\n const max = getRuleNumber(field, 'max');\n return (\n <TextField\n {...getFieldProps(props)}\n value={isString(props.value) ? props.value : null}\n onChange={props.onChange}\n {...(max !== undefined ? { maxLength: max } : {})}\n {...(prefix !== undefined ? { prefix } : {})}\n {...(suffix !== undefined ? { suffix } : {})}\n />\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextAreaField.js","names":["
|
|
1
|
+
{"version":3,"file":"TextAreaField.js","names":["TextArea","getFieldProps","getRuleNumber","getSetting","isNumber","isString","FieldEntryProps","FieldProps","useCountedDescription","TextAreaFieldProps","placeholder","maxLength","rows","textAreaClassName","TextAreaField","t0","$","_c","description","disabled","onChange","props","readOnly","required","value","shownDescription","t1","t2","next","t3","TextAreaFieldEntry","field","max","t4","undefined","t5","t6","_c"],"sources":["../../src/textarea/TextAreaField.tsx"],"sourcesContent":["import { TextArea } from '@panneau/ui';\n\nimport { getFieldProps, getRuleNumber, getSetting, isNumber, isString } from '../shared/entry';\nimport type { FieldEntryProps, FieldProps } from '../shared/types';\nimport { useCountedDescription } from '../text/TextField';\n\nexport interface TextAreaFieldProps extends FieldProps<string> {\n placeholder?: string;\n /** Shows a count of characters against this maximum. It doesn't stop typing. */\n maxLength?: number;\n /** Visible lines. Defaults to 4. */\n rows?: number;\n textAreaClassName?: string;\n}\n\n/** A text of several lines. An empty text is `null`. */\nexport function TextAreaField({\n value,\n onChange,\n description,\n maxLength,\n disabled,\n readOnly,\n required,\n ...props\n}: TextAreaFieldProps) {\n const shownDescription = useCountedDescription(description, value, maxLength);\n return (\n <TextArea\n {...props}\n value={value ?? ''}\n onChange={(next) => onChange?.(next === '' ? null : next)}\n description={shownDescription}\n isDisabled={disabled}\n isReadOnly={readOnly}\n isRequired={required}\n />\n );\n}\n\n/** The `textarea` type: setting `rows`, and a character count from the `max` rule. */\nexport function TextAreaFieldEntry(props: FieldEntryProps) {\n const max = getRuleNumber(props.field, 'max');\n const rows = getSetting(props.field, 'rows', isNumber);\n return (\n <TextAreaField\n {...getFieldProps(props)}\n value={isString(props.value) ? props.value : null}\n onChange={props.onChange}\n {...(max !== undefined ? { maxLength: max } : {})}\n {...(rows !== undefined ? { rows } : {})}\n />\n );\n}\n"],"mappings":"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"}
|
package/dist/time/TimeField.js
CHANGED
|
@@ -5,16 +5,70 @@ import { TimeInput } from "@panneau/ui";
|
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
//#region src/time/TimeField.tsx
|
|
7
7
|
/** A time of day as a string, `09:30` (or `09:30:15` with seconds). */
|
|
8
|
-
function TimeField(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
function TimeField(t0) {
|
|
9
|
+
const $ = c(21);
|
|
10
|
+
let disabled;
|
|
11
|
+
let onChange;
|
|
12
|
+
let props;
|
|
13
|
+
let readOnly;
|
|
14
|
+
let required;
|
|
15
|
+
let t1;
|
|
16
|
+
let value;
|
|
17
|
+
if ($[0] !== t0) {
|
|
18
|
+
({value, onChange, withSeconds: t1, disabled, readOnly, required, ...props} = t0);
|
|
19
|
+
$[0] = t0;
|
|
20
|
+
$[1] = disabled;
|
|
21
|
+
$[2] = onChange;
|
|
22
|
+
$[3] = props;
|
|
23
|
+
$[4] = readOnly;
|
|
24
|
+
$[5] = required;
|
|
25
|
+
$[6] = t1;
|
|
26
|
+
$[7] = value;
|
|
27
|
+
} else {
|
|
28
|
+
disabled = $[1];
|
|
29
|
+
onChange = $[2];
|
|
30
|
+
props = $[3];
|
|
31
|
+
readOnly = $[4];
|
|
32
|
+
required = $[5];
|
|
33
|
+
t1 = $[6];
|
|
34
|
+
value = $[7];
|
|
35
|
+
}
|
|
36
|
+
const withSeconds = t1 === void 0 ? false : t1;
|
|
37
|
+
const t2 = withSeconds ? "second" : "minute";
|
|
38
|
+
let t3;
|
|
39
|
+
if ($[8] !== value) {
|
|
40
|
+
t3 = toTime(value);
|
|
41
|
+
$[8] = value;
|
|
42
|
+
$[9] = t3;
|
|
43
|
+
} else t3 = $[9];
|
|
44
|
+
let t4;
|
|
45
|
+
if ($[10] !== onChange || $[11] !== withSeconds) {
|
|
46
|
+
t4 = (next) => onChange?.(next === null ? null : fromTime(next, withSeconds));
|
|
47
|
+
$[10] = onChange;
|
|
48
|
+
$[11] = withSeconds;
|
|
49
|
+
$[12] = t4;
|
|
50
|
+
} else t4 = $[12];
|
|
51
|
+
let t5;
|
|
52
|
+
if ($[13] !== disabled || $[14] !== props || $[15] !== readOnly || $[16] !== required || $[17] !== t2 || $[18] !== t3 || $[19] !== t4) {
|
|
53
|
+
t5 = /* @__PURE__ */ jsx(TimeInput, {
|
|
54
|
+
...props,
|
|
55
|
+
granularity: t2,
|
|
56
|
+
value: t3,
|
|
57
|
+
onChange: t4,
|
|
58
|
+
isDisabled: disabled,
|
|
59
|
+
isReadOnly: readOnly,
|
|
60
|
+
isRequired: required
|
|
61
|
+
});
|
|
62
|
+
$[13] = disabled;
|
|
63
|
+
$[14] = props;
|
|
64
|
+
$[15] = readOnly;
|
|
65
|
+
$[16] = required;
|
|
66
|
+
$[17] = t2;
|
|
67
|
+
$[18] = t3;
|
|
68
|
+
$[19] = t4;
|
|
69
|
+
$[20] = t5;
|
|
70
|
+
} else t5 = $[20];
|
|
71
|
+
return t5;
|
|
18
72
|
}
|
|
19
73
|
/** The `time` type: setting `withSeconds`. */
|
|
20
74
|
function TimeFieldEntry(props) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeField.js","names":["_c"],"sources":["../../src/time/TimeField.tsx"],"sourcesContent":["import { TimeInput } from '@panneau/ui';\n\nimport { fromTime, toTime } from '../shared/dates';\nimport { getFieldProps, isString } from '../shared/entry';\nimport type { FieldEntryProps, FieldProps } from '../shared/types';\n\nexport interface TimeFieldProps extends FieldProps<string> {\n /** Shows and writes seconds (`09:30:15`). */\n withSeconds?: boolean;\n /** Defaults to the locale's. */\n hourCycle?: 12 | 24;\n controlClassName?: string;\n}\n\n/** A time of day as a string, `09:30` (or `09:30:15` with seconds). */\nexport function TimeField({\n value,\n onChange,\n withSeconds = false,\n disabled,\n readOnly,\n required,\n ...props\n}: TimeFieldProps) {\n return (\n <TimeInput\n {...props}\n granularity={withSeconds ? 'second' : 'minute'}\n value={toTime(value)}\n onChange={(next) => onChange?.(next === null ? null : fromTime(next, withSeconds))}\n isDisabled={disabled}\n isReadOnly={readOnly}\n isRequired={required}\n />\n );\n}\n\n/** The `time` type: setting `withSeconds`. */\nexport function TimeFieldEntry(props: FieldEntryProps) {\n return (\n <TimeField\n {...getFieldProps(props)}\n value={isString(props.value) ? props.value : null}\n onChange={props.onChange}\n withSeconds={props.field.settings?.withSeconds === true}\n />\n );\n}\n"],"mappings":";;;;;;;AAeA,
|
|
1
|
+
{"version":3,"file":"TimeField.js","names":["TimeInput","fromTime","toTime","getFieldProps","isString","FieldEntryProps","FieldProps","TimeFieldProps","withSeconds","hourCycle","controlClassName","TimeField","t0","$","_c","disabled","onChange","props","readOnly","required","t1","value","undefined","t2","t3","t4","next","t5","TimeFieldEntry","field","settings","_c"],"sources":["../../src/time/TimeField.tsx"],"sourcesContent":["import { TimeInput } from '@panneau/ui';\n\nimport { fromTime, toTime } from '../shared/dates';\nimport { getFieldProps, isString } from '../shared/entry';\nimport type { FieldEntryProps, FieldProps } from '../shared/types';\n\nexport interface TimeFieldProps extends FieldProps<string> {\n /** Shows and writes seconds (`09:30:15`). */\n withSeconds?: boolean;\n /** Defaults to the locale's. */\n hourCycle?: 12 | 24;\n controlClassName?: string;\n}\n\n/** A time of day as a string, `09:30` (or `09:30:15` with seconds). */\nexport function TimeField({\n value,\n onChange,\n withSeconds = false,\n disabled,\n readOnly,\n required,\n ...props\n}: TimeFieldProps) {\n return (\n <TimeInput\n {...props}\n granularity={withSeconds ? 'second' : 'minute'}\n value={toTime(value)}\n onChange={(next) => onChange?.(next === null ? null : fromTime(next, withSeconds))}\n isDisabled={disabled}\n isReadOnly={readOnly}\n isRequired={required}\n />\n );\n}\n\n/** The `time` type: setting `withSeconds`. */\nexport function TimeFieldEntry(props: FieldEntryProps) {\n return (\n <TimeField\n {...getFieldProps(props)}\n value={isString(props.value) ? props.value : null}\n onChange={props.onChange}\n withSeconds={props.field.settings?.withSeconds === true}\n />\n );\n}\n"],"mappings":";;;;;;;AAeA,SAAOW,UAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAC;CAAA,IAAAR,EAAA,OAAAD,IAAA;EAAmB,CAAA,CAAAS,OAAAL,UAAAR,aAAAY,IAAAL,UAAAG,UAAAC,UAAA,GAAAF,SAAAL;EAQTC,EAAA,KAAAD;EAAAC,EAAA,KAAAE;EAAAF,EAAA,KAAAG;EAAAH,EAAA,KAAAI;EAAAJ,EAAA,KAAAK;EAAAL,EAAA,KAAAM;EAAAN,EAAA,KAAAO;EAAAP,EAAA,KAAAQ;CAAA,OAAA;EAAAN,WAAAF,EAAA;EAAAG,WAAAH,EAAA;EAAAI,QAAAJ,EAAA;EAAAK,WAAAL,EAAA;EAAAM,WAAAN,EAAA;EAAAO,KAAAP,EAAA;EAAAQ,QAAAR,EAAA;CAAA;CALb,MAAAL,cAAAY,OAAAE,KAAAA,IAAA,QAAAF;CASqB,MAAAG,KAAAf,cAAA,WAAA;CAAiC,IAAAgB;CAAA,IAAAX,EAAA,OAAAQ,OAAA;EACvCG,KAAAtB,OAAOmB,KAAK;EAACR,EAAA,KAAAQ;EAAAR,EAAA,KAAAW;CAAA,OAAAA,KAAAX,EAAA;CAAA,IAAAY;CAAA,IAAAZ,EAAA,QAAAG,YAAAH,EAAA,QAAAL,aAAA;EACViB,MAAAC,SAAUV,WAAWU,SAAS,OAAT,OAAuBzB,SAASyB,MAAMlB,WAAW,CAAC;EAACK,EAAA,MAAAG;EAAAH,EAAA,MAAAL;EAAAK,EAAA,MAAAY;CAAA,OAAAA,KAAAZ,EAAA;CAAA,IAAAc;CAAA,IAAAd,EAAA,QAAAE,YAAAF,EAAA,QAAAI,SAAAJ,EAAA,QAAAK,YAAAL,EAAA,QAAAM,YAAAN,EAAA,QAAAU,MAAAV,EAAA,QAAAW,MAAAX,EAAA,QAAAY,IAAA;EAJtFE,KAAA,oBAAC,WAAD;GAAU,GACFV;GACS,aAAAM;GACN,OAAAC;GACG,UAAAC;GACEV,YAAAA;GACAG,YAAAA;GACAC,YAAAA;EAAQ,CAAA;EACtBN,EAAA,MAAAE;EAAAF,EAAA,MAAAI;EAAAJ,EAAA,MAAAK;EAAAL,EAAA,MAAAM;EAAAN,EAAA,MAAAU;EAAAV,EAAA,MAAAW;EAAAX,EAAA,MAAAY;EAAAZ,EAAA,MAAAc;CAAA,OAAAA,KAAAd,EAAA;CAAA,OARFc;AAQE;;AAKV,SAAOC,eAAAX,OAAA;CAAA,MAAAJ,IAAAC,EAAA,CAAA;CAAA,IAAAF;CAAA,IAAAC,EAAA,OAAAI,OAAA;EAGSL,KAAAT,cAAcc,KAAK;EAACJ,EAAA,KAAAI;EAAAJ,EAAA,KAAAD;CAAA,OAAAA,KAAAC,EAAA;CACjB,MAAAO,KAAAhB,SAASa,MAAKI,KAA2B,IAAjBJ,MAAKI,QAA7B;CAEM,MAAAE,KAAAN,MAAKY,MAAMC,UAAsBtB,gBAAK;CAAI,IAAAgB;CAAA,IAAAX,EAAA,OAAAI,MAAAD,YAAAH,EAAA,OAAAD,MAAAC,EAAA,OAAAO,MAAAP,EAAA,OAAAU,IAAA;EAJ3DC,KAAA,oBAAC,WAAD;GAAU,GACFZ;GACG,OAAAQ;GACG,UAAAH,MAAKD;GACF,aAAAO;EAA0C,CAAA;EACzDV,EAAA,KAAAI,MAAAD;EAAAH,EAAA,KAAAD;EAAAC,EAAA,KAAAO;EAAAP,EAAA,KAAAU;EAAAV,EAAA,KAAAW;CAAA,OAAAA,KAAAX,EAAA;CAAA,OALFW;AAKE"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cx } from "../shared/cx.js";
|
|
2
2
|
import { messages } from "../shared/messages.js";
|
|
3
3
|
import FilePicker_module_default from "./FilePicker.module.js";
|
|
4
|
+
import { c } from "react/compiler-runtime";
|
|
4
5
|
import { Button, usePanneauIntl } from "@panneau/ui";
|
|
5
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { Upload } from "lucide-react";
|
|
@@ -10,36 +11,118 @@ async function readDrop(items) {
|
|
|
10
11
|
return (await Promise.all(items.map((item) => item.kind === "file" ? item.getFile() : Promise.resolve(null)))).filter((file) => file !== null);
|
|
11
12
|
}
|
|
12
13
|
/** A button that opens the file dialog, in a zone where files can be dropped. */
|
|
13
|
-
function FilePicker(
|
|
14
|
+
function FilePicker(t0) {
|
|
15
|
+
const $ = c(34);
|
|
16
|
+
const { onSelect, accept, multiple: t1, isDisabled: t2, label, className } = t0;
|
|
17
|
+
const multiple = t1 === void 0 ? false : t1;
|
|
18
|
+
const isDisabled = t2 === void 0 ? false : t2;
|
|
14
19
|
const intl = usePanneauIntl();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
let t3;
|
|
21
|
+
if ($[0] !== className) {
|
|
22
|
+
t3 = cx(FilePicker_module_default.zone, className);
|
|
23
|
+
$[0] = className;
|
|
24
|
+
$[1] = t3;
|
|
25
|
+
} else t3 = $[1];
|
|
26
|
+
let t4;
|
|
27
|
+
if ($[2] !== intl) {
|
|
28
|
+
t4 = intl.formatMessage(messages.dropZone);
|
|
29
|
+
$[2] = intl;
|
|
30
|
+
$[3] = t4;
|
|
31
|
+
} else t4 = $[3];
|
|
32
|
+
let t5;
|
|
33
|
+
if ($[4] !== multiple || $[5] !== onSelect) {
|
|
34
|
+
t5 = (event) => {
|
|
20
35
|
readDrop(event.items).then((files) => {
|
|
21
36
|
if (files.length > 0) onSelect(multiple ? files : files.slice(0, 1));
|
|
22
37
|
});
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
38
|
+
};
|
|
39
|
+
$[4] = multiple;
|
|
40
|
+
$[5] = onSelect;
|
|
41
|
+
$[6] = t5;
|
|
42
|
+
} else t5 = $[6];
|
|
43
|
+
let t6;
|
|
44
|
+
if ($[7] !== accept) {
|
|
45
|
+
t6 = accept !== null && accept !== void 0 && accept.length > 0 ? { acceptedFileTypes: accept } : {};
|
|
46
|
+
$[7] = accept;
|
|
47
|
+
$[8] = t6;
|
|
48
|
+
} else t6 = $[8];
|
|
49
|
+
let t7;
|
|
50
|
+
if ($[9] !== onSelect) {
|
|
51
|
+
t7 = (list) => {
|
|
52
|
+
const files_0 = list === null ? [] : [...list];
|
|
53
|
+
if (files_0.length > 0) onSelect(files_0);
|
|
54
|
+
};
|
|
55
|
+
$[9] = onSelect;
|
|
56
|
+
$[10] = t7;
|
|
57
|
+
} else t7 = $[10];
|
|
58
|
+
let t8;
|
|
59
|
+
if ($[11] !== intl || $[12] !== label || $[13] !== multiple) {
|
|
60
|
+
t8 = label ?? intl.formatMessage(multiple ? messages.chooseFiles : messages.chooseFile);
|
|
61
|
+
$[11] = intl;
|
|
62
|
+
$[12] = label;
|
|
63
|
+
$[13] = multiple;
|
|
64
|
+
$[14] = t8;
|
|
65
|
+
} else t8 = $[14];
|
|
66
|
+
let t9;
|
|
67
|
+
if ($[15] !== isDisabled || $[16] !== t8) {
|
|
68
|
+
t9 = /* @__PURE__ */ jsx(Button, {
|
|
69
|
+
size: "sm",
|
|
70
|
+
appearance: "outline",
|
|
71
|
+
icon: Upload,
|
|
72
|
+
isDisabled,
|
|
73
|
+
children: t8
|
|
74
|
+
});
|
|
75
|
+
$[15] = isDisabled;
|
|
76
|
+
$[16] = t8;
|
|
77
|
+
$[17] = t9;
|
|
78
|
+
} else t9 = $[17];
|
|
79
|
+
let t10;
|
|
80
|
+
if ($[18] !== multiple || $[19] !== t6 || $[20] !== t7 || $[21] !== t9) {
|
|
81
|
+
t10 = /* @__PURE__ */ jsx(FileTrigger, {
|
|
82
|
+
...t6,
|
|
26
83
|
allowsMultiple: multiple,
|
|
27
|
-
onSelect:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
84
|
+
onSelect: t7,
|
|
85
|
+
children: t9
|
|
86
|
+
});
|
|
87
|
+
$[18] = multiple;
|
|
88
|
+
$[19] = t6;
|
|
89
|
+
$[20] = t7;
|
|
90
|
+
$[21] = t9;
|
|
91
|
+
$[22] = t10;
|
|
92
|
+
} else t10 = $[22];
|
|
93
|
+
let t11;
|
|
94
|
+
if ($[23] !== intl) {
|
|
95
|
+
t11 = intl.formatMessage(messages.dropHere);
|
|
96
|
+
$[23] = intl;
|
|
97
|
+
$[24] = t11;
|
|
98
|
+
} else t11 = $[24];
|
|
99
|
+
let t12;
|
|
100
|
+
if ($[25] !== t11) {
|
|
101
|
+
t12 = /* @__PURE__ */ jsx("span", {
|
|
39
102
|
className: FilePicker_module_default.hint,
|
|
40
|
-
children:
|
|
41
|
-
})
|
|
42
|
-
|
|
103
|
+
children: t11
|
|
104
|
+
});
|
|
105
|
+
$[25] = t11;
|
|
106
|
+
$[26] = t12;
|
|
107
|
+
} else t12 = $[26];
|
|
108
|
+
let t13;
|
|
109
|
+
if ($[27] !== isDisabled || $[28] !== t10 || $[29] !== t12 || $[30] !== t3 || $[31] !== t4 || $[32] !== t5) {
|
|
110
|
+
t13 = /* @__PURE__ */ jsxs(DropZone, {
|
|
111
|
+
className: t3,
|
|
112
|
+
"aria-label": t4,
|
|
113
|
+
isDisabled,
|
|
114
|
+
onDrop: t5,
|
|
115
|
+
children: [t10, t12]
|
|
116
|
+
});
|
|
117
|
+
$[27] = isDisabled;
|
|
118
|
+
$[28] = t10;
|
|
119
|
+
$[29] = t12;
|
|
120
|
+
$[30] = t3;
|
|
121
|
+
$[31] = t4;
|
|
122
|
+
$[32] = t5;
|
|
123
|
+
$[33] = t13;
|
|
124
|
+
} else t13 = $[33];
|
|
125
|
+
return t13;
|
|
43
126
|
}
|
|
44
127
|
//#endregion
|
|
45
128
|
export { FilePicker };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilePicker.js","names":["files","styles"],"sources":["../../src/upload/FilePicker.tsx"],"sourcesContent":["import { Upload } from 'lucide-react';\nimport { type DropItem, DropZone, FileTrigger } from 'react-aria-components';\n\nimport { Button, usePanneauIntl } from '@panneau/ui';\n\nimport { cx } from '../shared/cx';\nimport { messages } from '../shared/messages';\nimport styles from './FilePicker.module.css';\n\nexport interface FilePickerProps {\n /** Called with the files chosen or dropped. */\n onSelect: (files: File[]) => void;\n /** Accepted MIME types, which the file dialog offers. */\n accept?: readonly string[] | null;\n multiple?: boolean;\n isDisabled?: boolean;\n /** Text of the button. Defaults to \"Choose a file\", or \"Choose files\" with `multiple`. */\n label?: string;\n className?: string;\n}\n\nasync function readDrop(items: DropItem[]): Promise<File[]> {\n const files = await Promise.all(\n items.map((item) => (item.kind === 'file' ? item.getFile() : Promise.resolve(null))),\n );\n return files.filter((file): file is File => file !== null);\n}\n\n/** A button that opens the file dialog, in a zone where files can be dropped. */\nexport function FilePicker({\n onSelect,\n accept,\n multiple = false,\n isDisabled = false,\n label,\n className,\n}: FilePickerProps) {\n const intl = usePanneauIntl();\n return (\n <DropZone\n className={cx(styles.zone, className)}\n aria-label={intl.formatMessage(messages.dropZone)}\n isDisabled={isDisabled}\n onDrop={(event) => {\n void readDrop(event.items).then((files) => {\n if (files.length > 0) {\n onSelect(multiple ? files : files.slice(0, 1));\n }\n });\n }}\n >\n <FileTrigger\n {...(accept !== null && accept !== undefined && accept.length > 0\n ? { acceptedFileTypes: accept }\n : {})}\n allowsMultiple={multiple}\n onSelect={(list) => {\n const files = list === null ? [] : [...list];\n if (files.length > 0) {\n onSelect(files);\n }\n }}\n >\n <Button size=\"sm\" appearance=\"outline\" icon={Upload} isDisabled={isDisabled}>\n {label ??\n intl.formatMessage(multiple ? messages.chooseFiles : messages.chooseFile)}\n </Button>\n </FileTrigger>\n <span className={styles.hint}>{intl.formatMessage(messages.dropHere)}</span>\n </DropZone>\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"FilePicker.js","names":["Upload","DropItem","DropZone","FileTrigger","Button","usePanneauIntl","cx","messages","styles","FilePickerProps","onSelect","files","File","accept","multiple","isDisabled","label","className","readDrop","items","Promise","all","map","item","kind","getFile","resolve","filter","file","FilePicker","t0","$","_c","t1","t2","undefined","intl","t3","zone","t4","formatMessage","dropZone","t5","event","then","length","slice","t6","acceptedFileTypes","t7","list","files_0","t8","chooseFiles","chooseFile","t9","t10","t11","dropHere","t12","hint","t13","_c","styles"],"sources":["../../src/upload/FilePicker.tsx"],"sourcesContent":["import { Upload } from 'lucide-react';\nimport { type DropItem, DropZone, FileTrigger } from 'react-aria-components';\n\nimport { Button, usePanneauIntl } from '@panneau/ui';\n\nimport { cx } from '../shared/cx';\nimport { messages } from '../shared/messages';\nimport styles from './FilePicker.module.css';\n\nexport interface FilePickerProps {\n /** Called with the files chosen or dropped. */\n onSelect: (files: File[]) => void;\n /** Accepted MIME types, which the file dialog offers. */\n accept?: readonly string[] | null;\n multiple?: boolean;\n isDisabled?: boolean;\n /** Text of the button. Defaults to \"Choose a file\", or \"Choose files\" with `multiple`. */\n label?: string;\n className?: string;\n}\n\nasync function readDrop(items: DropItem[]): Promise<File[]> {\n const files = await Promise.all(\n items.map((item) => (item.kind === 'file' ? item.getFile() : Promise.resolve(null))),\n );\n return files.filter((file): file is File => file !== null);\n}\n\n/** A button that opens the file dialog, in a zone where files can be dropped. */\nexport function FilePicker({\n onSelect,\n accept,\n multiple = false,\n isDisabled = false,\n label,\n className,\n}: FilePickerProps) {\n const intl = usePanneauIntl();\n return (\n <DropZone\n className={cx(styles.zone, className)}\n aria-label={intl.formatMessage(messages.dropZone)}\n isDisabled={isDisabled}\n onDrop={(event) => {\n void readDrop(event.items).then((files) => {\n if (files.length > 0) {\n onSelect(multiple ? files : files.slice(0, 1));\n }\n });\n }}\n >\n <FileTrigger\n {...(accept !== null && accept !== undefined && accept.length > 0\n ? { acceptedFileTypes: accept }\n : {})}\n allowsMultiple={multiple}\n onSelect={(list) => {\n const files = list === null ? [] : [...list];\n if (files.length > 0) {\n onSelect(files);\n }\n }}\n >\n <Button size=\"sm\" appearance=\"outline\" icon={Upload} isDisabled={isDisabled}>\n {label ??\n intl.formatMessage(multiple ? messages.chooseFiles : messages.chooseFile)}\n </Button>\n </FileTrigger>\n <span className={styles.hint}>{intl.formatMessage(messages.dropHere)}</span>\n </DropZone>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +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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"}
|
|
1
|
+
{"version":3,"file":"UploadList.js","names":["Pause","Play","RotateCcw","X","ProgressBar","IconButton","usePanneauIntl","cx","messages","styles","formatSize","UploadItem","UploadListProps","items","onPause","id","onResume","onCancel","onRetry","className","UploadList","t0","$","_c","ariaLabel","intl","length","t1","list","t2","formatMessage","uploads","t3","t4","item","name","failed","status","indeterminate","progress","uploading","paused","uploadPaused","completing","uploadCompleting","uploadFailed","error","percent","Math","round","size","locale","buttons","canPause","pauseUpload","resumeUpload","retryUpload","cancelUpload","formatNumber","style","t5","valueText","track","fill","undefined","width","String","map","_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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"}
|
package/dist/upload/files.js.map
CHANGED
|
@@ -1 +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,
|
|
1
|
+
{"version":3,"file":"files.js","names":["matchesMime","mime","patterns","some","pattern","endsWith","startsWith","slice","UNITS","const","formatSize","bytes","locale","value","unit","length","number","Intl","NumberFormat","maximumFractionDigits","format"],"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,SAAgBA,YAAYC,MAAcC,UAAsC;CAC5E,OAAOA,SAASC,MAAMC,YAClBA,QAAQC,SAAS,IAAI,IAAIJ,KAAKK,WAAWF,QAAQG,MAAM,GAAG,EAAE,CAAC,IAAIN,SAASG,OAC9E;AACJ;AAEA,IAAMI,QAAQ;CAAC;CAAK;CAAM;CAAM;CAAM;AAAI;;AAG1C,SAAgBE,WAAWC,OAAeC,QAAyB;CAC/D,IAAIC,QAAQF;CACZ,IAAIG,OAAO;CACX,OAAOD,SAAS,QAAQC,OAAON,MAAMO,SAAS,GAAG;EAC7CF,SAAS;EACTC,QAAQ;CACZ;CAIA,OAAO,GAHQ,IAAIG,KAAKC,aAAaN,QAAQ,EACzCO,uBAAuBL,SAAS,KAAKD,SAAS,KAAK,IAAI,EAC3D,CAAC,CAAC,CAACO,OAAOP,KACAG,EAAM,GAAIR,MAAMM,SAAS;AACvC"}
|
|
@@ -1 +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,
|
|
1
|
+
{"version":3,"file":"useRejectionMessage.js","names":["usePanneauIntl","messages","formatSize","UploadRejection","useRejectionMessage","maxSize","$","_c","intl","t0","file","reason","formatMessage","rejectedType","name","rejectedSize","size","locale","_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,SAAOI,oBAAAC,SAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAGH,MAAAC,OAAaR,eAAe;CAAE,IAAAS;CAAA,IAAAH,EAAA,OAAAE,QAAAF,EAAA,OAAAD,SAAA;EACvBI,MAAAC,MAAAC,WACHA,WAAW,WACLH,KAAII,cAAeX,SAAQY,cAAe,EAAAC,MAAQJ,KAAII,KAAM,CAI3D,IAHDN,KAAII,cAAeX,SAAQc,cAAe;GAAAD,MAChCJ,KAAII;GAAKE,MACTd,WAAWG,WAAA,GAAcG,KAAIS,MAAO;EAC9C,CAAC;EAACX,EAAA,KAAAE;EAAAF,EAAA,KAAAD;EAAAC,EAAA,KAAAG;CAAA,OAAAA,KAAAH,EAAA;CAAA,OANLG;AAMK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUploads.js","names":["
|
|
1
|
+
{"version":3,"file":"useUploads.js","names":["useEffect","useRef","useState","useSyncExternalStore","matchesMime","UploadItem","UploadRejection","UploadSource","UploadedFile","Uploader","UseUploadsOptions","source","accept","maxSize","onUploaded","file","File","onRejected","reason","UseUploadsResult","items","add","files","Iterable","pause","id","resume","cancel","retry","NO_ITEMS","rejects","Pick","undefined","length","type","size","useUploads","options","$","_c","latest","t0","current","state","setState","uploader","t1","t2","created","createUploader","destroy","t3","t4","listener","subscribe","_temp","getItems","_temp2","t5","t6","t7","t8","t9","id_0","id_1","id_2","file_0","rejection","_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":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploader.js","names":[],"sources":["../../src/uppy/uploader.ts"],"sourcesContent":["import AwsS3 from '@uppy/aws-s3';\nimport Uppy, { type Body, type Meta, type UppyFile } from '@uppy/core';\n\nimport type { Upload, UploadSignRequest } from '@panneau/protocol';\n\nimport type {\n UploadItem,\n UploadItemStatus,\n UploadSource,\n UploadedFile,\n Uploader,\n} from '../upload/types';\n\n/**\n * Signs and completes direct uploads: `adapter.presignedUploads()` of `@panneau/data` (or\n * `createPresignedUploads()`) gives one.\n */\nexport interface PresignedUploadsLike {\n signRequest(\n request: UploadSignRequest,\n ): Promise<{ url: string; key?: string; headers?: Record<string, string> }>;\n complete(key: string, options?: { name?: string }): Promise<Upload>;\n}\n\nexport interface UppyUploadSourceOptions {\n /** Files larger than this, in bytes, are sent in parts, which can pause and resume. Defaults to 10 MB. */\n multipartThreshold?: number;\n /**\n * Installs what sends files on each Uppy instance: `@uppy/aws-s3` with the backend's\n * signatures by default. Tests install a fake one.\n */\n install?: (uppy: Uppy<Meta, Body>, uploads: PresignedUploadsLike) => void;\n}\n\nconst MB = 1024 * 1024;\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction installAwsS3(uppy: Uppy<Meta, Body>, uploads: PresignedUploadsLike, threshold: number) {\n uppy.use(AwsS3<Meta, Body>, {\n // Uppy's request types are interfaces; the protocol's schema is an open object.\n signRequest: (request) => uploads.signRequest({ ...request }),\n shouldUseMultipart: (file) => (file.size ?? 0) > threshold,\n });\n}\n\n/**\n * An uploader on Uppy 6: files go to S3-compatible storage with URLs that the backend signs, in\n * parts when they are large, then each upload is completed with the backend.\n */\nexport function createUppyUploader(\n uploads: PresignedUploadsLike,\n {\n onUploaded,\n multipartThreshold = 10 * MB,\n install = (uppy, presigned) => installAwsS3(uppy, presigned, multipartThreshold),\n }: UppyUploadSourceOptions & { onUploaded: (file: UploadedFile, upload: Upload) => void },\n): Uploader {\n const uppy = new Uppy<Meta, Body>({ autoProceed: true, allowMultipleUploadBatches: true });\n install(uppy, uploads);\n\n // What Uppy doesn't track: files being completed with the backend, and why one failed.\n const completing = new Set<string>();\n const failures = new Map<string, string>();\n const listeners = new Set<() => void>();\n let items: readonly UploadItem[] = [];\n\n const toItem = (file: UppyFile<Meta, Body>): UploadItem => {\n const { bytesUploaded, bytesTotal } = file.progress;\n const failure = failures.get(file.id) ?? null;\n let status: UploadItemStatus = 'uploading';\n if (failure !== null) {\n status = 'failed';\n } else if (completing.has(file.id)) {\n status = 'completing';\n } else if (file.isPaused === true) {\n status = 'paused';\n }\n return {\n id: file.id,\n name: file.name,\n size: file.size,\n mime: file.type !== '' ? file.type : null,\n progress:\n typeof bytesUploaded === 'number' && bytesTotal !== null && bytesTotal > 0\n ? Math.min(1, bytesUploaded / bytesTotal)\n : null,\n status,\n error: failure,\n canPause: (file.size ?? 0) > multipartThreshold,\n };\n };\n\n const update = () => {\n items = uppy.getFiles().map(toItem);\n listeners.forEach((listener) => listener());\n };\n\n const forget = (id: string) => {\n completing.delete(id);\n failures.delete(id);\n if (uppy.getFile(id) !== undefined) {\n uppy.removeFile(id);\n }\n };\n\n uppy.on('state-update', update);\n uppy.on('upload-error', (file, error) => {\n if (file !== undefined) {\n failures.set(file.id, errorMessage(error));\n update();\n }\n });\n uppy.on('upload-success', (file, response) => {\n if (file === undefined) {\n return;\n }\n const key = typeof response.body?.key === 'string' ? response.body.key : null;\n if (key === null) {\n failures.set(file.id, 'The storage gave no key for this file.');\n update();\n return;\n }\n completing.add(file.id);\n update();\n uploads\n .complete(key, { name: file.name })\n .then((upload) => {\n forget(file.id);\n onUploaded(\n {\n upload: upload.id,\n name: upload.name ?? file.name,\n mime: upload.mime ?? (file.type !== '' ? file.type : null),\n size: upload.size ?? file.size,\n },\n upload,\n );\n })\n .catch((error: unknown) => {\n completing.delete(file.id);\n failures.set(file.id, errorMessage(error));\n update();\n });\n });\n\n return {\n getItems: () => items,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n add(files) {\n for (const file of files) {\n uppy.addFile({ name: file.name, type: file.type, data: file });\n }\n },\n pause(id) {\n if (uppy.getFile(id)?.isPaused !== true) {\n uppy.pauseResume(id);\n }\n },\n resume(id) {\n if (uppy.getFile(id)?.isPaused === true) {\n uppy.pauseResume(id);\n }\n },\n cancel(id) {\n forget(id);\n update();\n },\n retry(id) {\n if (!failures.has(id)) {\n return;\n }\n failures.delete(id);\n update();\n void uppy.retryUpload(id);\n },\n destroy() {\n listeners.clear();\n uppy.destroy();\n },\n };\n}\n\n/**\n * The upload source of fields on Uppy 6 (`@uppy/core` and `@uppy/aws-s3`, optional peer\n * dependencies of this entry point): pass it as `uploadSource` to `FieldsProvider` or\n * `FormView`, with the signing routes of the backend.\n *\n * ```ts\n * const uploadSource = createUppyUploadSource(adapter.presignedUploads());\n * ```\n */\nexport function createUppyUploadSource(\n uploads: PresignedUploadsLike,\n options: UppyUploadSourceOptions = {},\n): UploadSource {\n return {\n createUploader: ({ onUploaded }) => createUppyUploader(uploads, { ...options, onUploaded }),\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"uploader.js","names":["AwsS3","Uppy","Body","Meta","UppyFile","Upload","UploadSignRequest","UploadItem","UploadItemStatus","UploadSource","UploadedFile","Uploader","PresignedUploadsLike","signRequest","request","Promise","url","key","headers","Record","complete","options","name","UppyUploadSourceOptions","multipartThreshold","install","uppy","uploads","MB","errorMessage","error","Error","message","String","installAwsS3","threshold","use","shouldUseMultipart","file","size","createUppyUploader","onUploaded","presigned","upload","autoProceed","allowMultipleUploadBatches","completing","Set","failures","Map","listeners","items","toItem","bytesUploaded","bytesTotal","progress","failure","get","id","status","has","isPaused","mime","type","Math","min","canPause","update","getFiles","map","forEach","listener","forget","delete","getFile","undefined","removeFile","on","set","response","body","add","then","catch","getItems","subscribe","files","addFile","data","pause","pauseResume","resume","cancel","retry","retryUpload","destroy","clear","createUppyUploadSource","createUploader"],"sources":["../../src/uppy/uploader.ts"],"sourcesContent":["import AwsS3 from '@uppy/aws-s3';\nimport Uppy, { type Body, type Meta, type UppyFile } from '@uppy/core';\n\nimport type { Upload, UploadSignRequest } from '@panneau/protocol';\n\nimport type {\n UploadItem,\n UploadItemStatus,\n UploadSource,\n UploadedFile,\n Uploader,\n} from '../upload/types';\n\n/**\n * Signs and completes direct uploads: `adapter.presignedUploads()` of `@panneau/data` (or\n * `createPresignedUploads()`) gives one.\n */\nexport interface PresignedUploadsLike {\n signRequest(\n request: UploadSignRequest,\n ): Promise<{ url: string; key?: string; headers?: Record<string, string> }>;\n complete(key: string, options?: { name?: string }): Promise<Upload>;\n}\n\nexport interface UppyUploadSourceOptions {\n /** Files larger than this, in bytes, are sent in parts, which can pause and resume. Defaults to 10 MB. */\n multipartThreshold?: number;\n /**\n * Installs what sends files on each Uppy instance: `@uppy/aws-s3` with the backend's\n * signatures by default. Tests install a fake one.\n */\n install?: (uppy: Uppy<Meta, Body>, uploads: PresignedUploadsLike) => void;\n}\n\nconst MB = 1024 * 1024;\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction installAwsS3(uppy: Uppy<Meta, Body>, uploads: PresignedUploadsLike, threshold: number) {\n uppy.use(AwsS3<Meta, Body>, {\n // Uppy's request types are interfaces; the protocol's schema is an open object.\n signRequest: (request) => uploads.signRequest({ ...request }),\n shouldUseMultipart: (file) => (file.size ?? 0) > threshold,\n });\n}\n\n/**\n * An uploader on Uppy 6: files go to S3-compatible storage with URLs that the backend signs, in\n * parts when they are large, then each upload is completed with the backend.\n */\nexport function createUppyUploader(\n uploads: PresignedUploadsLike,\n {\n onUploaded,\n multipartThreshold = 10 * MB,\n install = (uppy, presigned) => installAwsS3(uppy, presigned, multipartThreshold),\n }: UppyUploadSourceOptions & { onUploaded: (file: UploadedFile, upload: Upload) => void },\n): Uploader {\n const uppy = new Uppy<Meta, Body>({ autoProceed: true, allowMultipleUploadBatches: true });\n install(uppy, uploads);\n\n // What Uppy doesn't track: files being completed with the backend, and why one failed.\n const completing = new Set<string>();\n const failures = new Map<string, string>();\n const listeners = new Set<() => void>();\n let items: readonly UploadItem[] = [];\n\n const toItem = (file: UppyFile<Meta, Body>): UploadItem => {\n const { bytesUploaded, bytesTotal } = file.progress;\n const failure = failures.get(file.id) ?? null;\n let status: UploadItemStatus = 'uploading';\n if (failure !== null) {\n status = 'failed';\n } else if (completing.has(file.id)) {\n status = 'completing';\n } else if (file.isPaused === true) {\n status = 'paused';\n }\n return {\n id: file.id,\n name: file.name,\n size: file.size,\n mime: file.type !== '' ? file.type : null,\n progress:\n typeof bytesUploaded === 'number' && bytesTotal !== null && bytesTotal > 0\n ? Math.min(1, bytesUploaded / bytesTotal)\n : null,\n status,\n error: failure,\n canPause: (file.size ?? 0) > multipartThreshold,\n };\n };\n\n const update = () => {\n items = uppy.getFiles().map(toItem);\n listeners.forEach((listener) => listener());\n };\n\n const forget = (id: string) => {\n completing.delete(id);\n failures.delete(id);\n if (uppy.getFile(id) !== undefined) {\n uppy.removeFile(id);\n }\n };\n\n uppy.on('state-update', update);\n uppy.on('upload-error', (file, error) => {\n if (file !== undefined) {\n failures.set(file.id, errorMessage(error));\n update();\n }\n });\n uppy.on('upload-success', (file, response) => {\n if (file === undefined) {\n return;\n }\n const key = typeof response.body?.key === 'string' ? response.body.key : null;\n if (key === null) {\n failures.set(file.id, 'The storage gave no key for this file.');\n update();\n return;\n }\n completing.add(file.id);\n update();\n uploads\n .complete(key, { name: file.name })\n .then((upload) => {\n forget(file.id);\n onUploaded(\n {\n upload: upload.id,\n name: upload.name ?? file.name,\n mime: upload.mime ?? (file.type !== '' ? file.type : null),\n size: upload.size ?? file.size,\n },\n upload,\n );\n })\n .catch((error: unknown) => {\n completing.delete(file.id);\n failures.set(file.id, errorMessage(error));\n update();\n });\n });\n\n return {\n getItems: () => items,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n add(files) {\n for (const file of files) {\n uppy.addFile({ name: file.name, type: file.type, data: file });\n }\n },\n pause(id) {\n if (uppy.getFile(id)?.isPaused !== true) {\n uppy.pauseResume(id);\n }\n },\n resume(id) {\n if (uppy.getFile(id)?.isPaused === true) {\n uppy.pauseResume(id);\n }\n },\n cancel(id) {\n forget(id);\n update();\n },\n retry(id) {\n if (!failures.has(id)) {\n return;\n }\n failures.delete(id);\n update();\n void uppy.retryUpload(id);\n },\n destroy() {\n listeners.clear();\n uppy.destroy();\n },\n };\n}\n\n/**\n * The upload source of fields on Uppy 6 (`@uppy/core` and `@uppy/aws-s3`, optional peer\n * dependencies of this entry point): pass it as `uploadSource` to `FieldsProvider` or\n * `FormView`, with the signing routes of the backend.\n *\n * ```ts\n * const uploadSource = createUppyUploadSource(adapter.presignedUploads());\n * ```\n */\nexport function createUppyUploadSource(\n uploads: PresignedUploadsLike,\n options: UppyUploadSourceOptions = {},\n): UploadSource {\n return {\n createUploader: ({ onUploaded }) => createUppyUploader(uploads, { ...options, onUploaded }),\n };\n}\n"],"mappings":"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"}
|