@netlify/spark-ui 1.27.6 → 1.27.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/components/preact/DropZone/DropZone.d.ts +10 -3
- package/dist/components/preact/DropZone/DropZone.js +26 -24
- package/dist/components/preact/DropZone/useDropDeploy.d.ts +9 -1
- package/dist/components/preact/DropZone/useDropDeploy.js +47 -46
- package/package.json +1 -1
- package/packages/components/preact/DropZone/DropZone.tsx +17 -2
- package/packages/components/preact/DropZone/useDropDeploy.ts +13 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ComponentChildren } from 'preact';
|
|
2
2
|
import { DropClient } from './drop-core';
|
|
3
|
-
import { DeployedSite, TrackFn } from './useDropDeploy';
|
|
3
|
+
import { DeployedSite, DeployError, TrackFn } from './useDropDeploy';
|
|
4
4
|
interface Props {
|
|
5
5
|
/** Content the drop layer sits on top of. The zone is invisible until you drag over it. */
|
|
6
6
|
children?: ComponentChildren;
|
|
@@ -12,11 +12,18 @@ interface Props {
|
|
|
12
12
|
claimUrl?: (siteName: string) => string;
|
|
13
13
|
/** Called once the deploy is live. */
|
|
14
14
|
onDeploy?: (result: DeployedSite) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Called when a deploy fails, with a humanized `message` (ready to show a
|
|
17
|
+
* user — the same copy the built-in overlay uses) and the raw `reason`. Pair
|
|
18
|
+
* this with `showStatus={false}` to render your own error UI.
|
|
19
|
+
*/
|
|
20
|
+
onError?: (error: DeployError) => void;
|
|
15
21
|
/**
|
|
16
22
|
* Render the built-in status overlay (drag tint, spinner, progress bar, error).
|
|
17
23
|
* Set to `false` to suppress it entirely and keep your children visible, then
|
|
18
24
|
* drive your own feedback from the `data-state` attribute on the root element.
|
|
19
|
-
* Note: in this mode you're responsible for surfacing errors yourself
|
|
25
|
+
* Note: in this mode you're responsible for surfacing errors yourself — use
|
|
26
|
+
* `onError` to get the message.
|
|
20
27
|
*/
|
|
21
28
|
showStatus?: boolean;
|
|
22
29
|
/**
|
|
@@ -38,5 +45,5 @@ interface Props {
|
|
|
38
45
|
analyticsId?: string;
|
|
39
46
|
className?: string;
|
|
40
47
|
}
|
|
41
|
-
export default function DropZone({ children, apiBase, client, claimUrl, onDeploy, showStatus, onTrack, analyticsId, className, }: Props): import("preact").JSX.Element;
|
|
48
|
+
export default function DropZone({ children, apiBase, client, claimUrl, onDeploy, onError, showStatus, onTrack, analyticsId, className, }: Props): import("preact").JSX.Element;
|
|
42
49
|
export {};
|
|
@@ -1,52 +1,54 @@
|
|
|
1
1
|
import { u as e } from "../../../chunks/jsxRuntime.module.Bzuv3cXw.js";
|
|
2
|
-
import { A as k, d as
|
|
3
|
-
import { readFileList as
|
|
4
|
-
import { useDropDeploy as
|
|
2
|
+
import { A as k, d as $, y as E } from "../../../chunks/hooks.module.DRcxknIz.js";
|
|
3
|
+
import { readFileList as I, readDataTransfer as P } from "./drop-core/readFiles.js";
|
|
4
|
+
import { useDropDeploy as x } from "./useDropDeploy.js";
|
|
5
5
|
import { Fragment as D } from "preact";
|
|
6
|
-
import '../../../assets/DropZone.css';const
|
|
7
|
-
function
|
|
6
|
+
import '../../../assets/DropZone.css';const F = 120, M = (n) => `https://app.netlify.com/drop/${n}`;
|
|
7
|
+
function L({
|
|
8
8
|
children: n,
|
|
9
9
|
apiBase: l,
|
|
10
10
|
client: i,
|
|
11
|
-
claimUrl: s =
|
|
11
|
+
claimUrl: s = M,
|
|
12
12
|
onDeploy: u,
|
|
13
|
+
onError: w,
|
|
13
14
|
showStatus: f = !0,
|
|
14
15
|
onTrack: d,
|
|
15
16
|
analyticsId: g,
|
|
16
|
-
className:
|
|
17
|
+
className: A
|
|
17
18
|
}) {
|
|
18
|
-
const v = (r, t = {}) => d == null ? void 0 : d(r, g ? { dropzone_id: g, ...t } : t), { status: a, warning: h, busy: o, deploy: b, reset:
|
|
19
|
+
const v = (r, t = {}) => d == null ? void 0 : d(r, g ? { dropzone_id: g, ...t } : t), { status: a, warning: h, busy: o, deploy: b, reset: C } = x({
|
|
19
20
|
apiBase: l,
|
|
20
21
|
client: i,
|
|
21
22
|
claimUrl: s,
|
|
22
23
|
onDeploy: u,
|
|
24
|
+
onError: w,
|
|
23
25
|
track: v
|
|
24
|
-
}), { active: p, keepActive:
|
|
26
|
+
}), { active: p, keepActive: T, endDrag: _ } = O(), m = k(null), y = (r) => {
|
|
25
27
|
var t;
|
|
26
28
|
v("dropzone_browse_opened", { method: r }), (t = m.current) == null || t.click();
|
|
27
|
-
},
|
|
29
|
+
}, R = f && (p || o || a.kind === "error"), S = [
|
|
28
30
|
"n-dropzone",
|
|
29
31
|
p && "is-active",
|
|
30
32
|
o && "is-busy",
|
|
31
33
|
!f && "is-bare",
|
|
32
|
-
|
|
34
|
+
A
|
|
33
35
|
].filter(Boolean).join(" ");
|
|
34
36
|
return /* @__PURE__ */ e(
|
|
35
37
|
"div",
|
|
36
38
|
{
|
|
37
|
-
class:
|
|
39
|
+
class: S,
|
|
38
40
|
"data-state": a.kind,
|
|
39
41
|
role: "button",
|
|
40
42
|
tabIndex: o ? -1 : 0,
|
|
41
43
|
"aria-label": "Drop a site folder or zip here to deploy it, or press Enter to browse for files",
|
|
42
44
|
"aria-busy": o,
|
|
43
45
|
onDragOver: (r) => {
|
|
44
|
-
o || (r.preventDefault(),
|
|
46
|
+
o || (r.preventDefault(), T());
|
|
45
47
|
},
|
|
46
48
|
onDrop: (r) => {
|
|
47
|
-
if (r.preventDefault(),
|
|
49
|
+
if (r.preventDefault(), _(), o) return;
|
|
48
50
|
const t = r.dataTransfer;
|
|
49
|
-
t && b(() =>
|
|
51
|
+
t && b(() => P(t), "drag");
|
|
50
52
|
},
|
|
51
53
|
onClick: (r) => {
|
|
52
54
|
!o && r.target === r.currentTarget && y("click");
|
|
@@ -68,16 +70,16 @@ function K({
|
|
|
68
70
|
onChange: (r) => {
|
|
69
71
|
var z;
|
|
70
72
|
const t = r.currentTarget;
|
|
71
|
-
(z = t.files) != null && z.length && b(() =>
|
|
73
|
+
(z = t.files) != null && z.length && b(() => I(t.files), "browse"), t.value = "";
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
),
|
|
75
|
-
|
|
77
|
+
R && /* @__PURE__ */ e(
|
|
76
78
|
"div",
|
|
77
79
|
{
|
|
78
80
|
class: "n-dropzone-overlay n-fadeIn",
|
|
79
81
|
children: [
|
|
80
|
-
/* @__PURE__ */ e(
|
|
82
|
+
/* @__PURE__ */ e(U, { status: a, active: p, onReset: C }),
|
|
81
83
|
h && a.kind !== "error" && o && /* @__PURE__ */ e("p", { class: "n-dropzone-warning", role: "status", children: h })
|
|
82
84
|
]
|
|
83
85
|
},
|
|
@@ -87,15 +89,15 @@ function K({
|
|
|
87
89
|
}
|
|
88
90
|
);
|
|
89
91
|
}
|
|
90
|
-
function
|
|
91
|
-
const [n, l] =
|
|
92
|
-
return
|
|
93
|
-
l(!0), clearTimeout(i.current), i.current = setTimeout(() => l(!1),
|
|
92
|
+
function O() {
|
|
93
|
+
const [n, l] = $(!1), i = k();
|
|
94
|
+
return E(() => () => clearTimeout(i.current), []), { active: n, keepActive: () => {
|
|
95
|
+
l(!0), clearTimeout(i.current), i.current = setTimeout(() => l(!1), F);
|
|
94
96
|
}, endDrag: () => {
|
|
95
97
|
clearTimeout(i.current), l(!1);
|
|
96
98
|
} };
|
|
97
99
|
}
|
|
98
|
-
function
|
|
100
|
+
function U({
|
|
99
101
|
status: n,
|
|
100
102
|
active: l,
|
|
101
103
|
onReset: i
|
|
@@ -138,5 +140,5 @@ function c({ label: n }) {
|
|
|
138
140
|
] });
|
|
139
141
|
}
|
|
140
142
|
export {
|
|
141
|
-
|
|
143
|
+
L as default
|
|
142
144
|
};
|
|
@@ -8,6 +8,13 @@ export interface DeployedSite {
|
|
|
8
8
|
siteName: string;
|
|
9
9
|
siteId: string;
|
|
10
10
|
}
|
|
11
|
+
/** A deploy failure, handed to `onError` so consumers can render their own error UI. */
|
|
12
|
+
export interface DeployError {
|
|
13
|
+
/** Human-readable text ready to show a user — the same copy the built-in overlay displays. */
|
|
14
|
+
message: string;
|
|
15
|
+
/** The raw underlying reason (e.g. "drop failed: 429"), useful for logging. */
|
|
16
|
+
reason: string;
|
|
17
|
+
}
|
|
11
18
|
/** Finite states of a single deploy attempt. */
|
|
12
19
|
export type DeployStatus = {
|
|
13
20
|
kind: 'idle';
|
|
@@ -34,13 +41,14 @@ interface UseDropDeployOptions {
|
|
|
34
41
|
client?: DropClient;
|
|
35
42
|
claimUrl: (siteName: string) => string;
|
|
36
43
|
onDeploy?: (site: DeployedSite) => void;
|
|
44
|
+
onError?: (error: DeployError) => void;
|
|
37
45
|
track: TrackFn;
|
|
38
46
|
}
|
|
39
47
|
/**
|
|
40
48
|
* Owns the deploy state machine and its side effects (upload, local persistence,
|
|
41
49
|
* analytics, redirect), keeping DropZone a thin view over the returned `status`.
|
|
42
50
|
*/
|
|
43
|
-
export declare function useDropDeploy({ apiBase, client, claimUrl, onDeploy, track, }: UseDropDeployOptions): {
|
|
51
|
+
export declare function useDropDeploy({ apiBase, client, claimUrl, onDeploy, onError, track, }: UseDropDeployOptions): {
|
|
44
52
|
status: DeployStatus;
|
|
45
53
|
warning: string | null;
|
|
46
54
|
busy: boolean;
|
|
@@ -1,71 +1,72 @@
|
|
|
1
|
-
import { d as
|
|
2
|
-
import { renameSingleNonIndexHtmlToIndex as
|
|
3
|
-
import { AnonymousDropClient as
|
|
4
|
-
import { deployFiles as
|
|
5
|
-
import { humanizeDropError as
|
|
6
|
-
function
|
|
7
|
-
switch (
|
|
1
|
+
import { d as f, A as S } from "../../../chunks/hooks.module.DRcxknIz.js";
|
|
2
|
+
import { renameSingleNonIndexHtmlToIndex as b, getSingleNonIndexHtmlFileName as z, hasMultipleHtmlFilesWithoutIndex as F } from "./drop-core/readFiles.js";
|
|
3
|
+
import { AnonymousDropClient as H } from "./drop-core/client.js";
|
|
4
|
+
import { deployFiles as W } from "./drop-core/deploy.js";
|
|
5
|
+
import { humanizeDropError as $ } from "./drop-core/errors.js";
|
|
6
|
+
function v(n) {
|
|
7
|
+
switch (n.phase) {
|
|
8
8
|
case "creating":
|
|
9
9
|
return { kind: "creating" };
|
|
10
10
|
case "uploading":
|
|
11
|
-
return { kind: "uploading", uploaded:
|
|
11
|
+
return { kind: "uploading", uploaded: n.uploaded ?? 0, total: n.total ?? 0 };
|
|
12
12
|
case "processing":
|
|
13
13
|
case "ready":
|
|
14
14
|
return { kind: "processing" };
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
function
|
|
18
|
-
const
|
|
19
|
-
return
|
|
17
|
+
function A(n) {
|
|
18
|
+
const r = z(n);
|
|
19
|
+
return r ? `No index.html found — "${r}" won’t be served at the site root.` : F(n) ? "No index.html found — your site may not have a landing page." : null;
|
|
20
20
|
}
|
|
21
|
-
function
|
|
22
|
-
apiBase:
|
|
23
|
-
client:
|
|
24
|
-
claimUrl:
|
|
25
|
-
onDeploy:
|
|
26
|
-
|
|
21
|
+
function q({
|
|
22
|
+
apiBase: n,
|
|
23
|
+
client: r,
|
|
24
|
+
claimUrl: g,
|
|
25
|
+
onDeploy: s,
|
|
26
|
+
onError: a,
|
|
27
|
+
track: u
|
|
27
28
|
}) {
|
|
28
|
-
const [
|
|
29
|
-
async function
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
},
|
|
34
|
-
const
|
|
35
|
-
|
|
29
|
+
const [c, i] = f({ kind: "idle" }), [h, m] = f(null), y = S(r ?? new H(n)).current, k = c.kind !== "idle" && c.kind !== "error";
|
|
30
|
+
async function _(x, l) {
|
|
31
|
+
m(null), i({ kind: "reading" });
|
|
32
|
+
const p = (e, o, t) => {
|
|
33
|
+
i({ kind: "error", message: e }), u("dropzone_deploy_failed", { method: l, reason: o, ...t }), a == null || a({ message: e, reason: o });
|
|
34
|
+
}, w = (e, o) => {
|
|
35
|
+
const t = e instanceof Error ? e.message : String(e);
|
|
36
|
+
p($(e), t, o);
|
|
36
37
|
};
|
|
37
38
|
try {
|
|
38
|
-
const
|
|
39
|
-
if (!
|
|
40
|
-
|
|
39
|
+
const e = b(await x());
|
|
40
|
+
if (!e.length) {
|
|
41
|
+
p("No files found to deploy.", "No files found to deploy.", { file_count: 0 });
|
|
41
42
|
return;
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
+
l === "drag" && u("dropzone_files_dropped", { method: l, file_count: e.length }), m(A(e));
|
|
44
45
|
const {
|
|
45
|
-
url:
|
|
46
|
-
token:
|
|
47
|
-
deploy:
|
|
48
|
-
} = await
|
|
49
|
-
onProgress: (
|
|
46
|
+
url: o,
|
|
47
|
+
token: t,
|
|
48
|
+
deploy: d
|
|
49
|
+
} = await W(y, e, {
|
|
50
|
+
onProgress: (I) => i(v(I))
|
|
50
51
|
});
|
|
51
52
|
try {
|
|
52
|
-
localStorage.setItem("drop-token",
|
|
53
|
+
localStorage.setItem("drop-token", t), localStorage.setItem("dropSiteName", d.subdomain);
|
|
53
54
|
} catch {
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
-
method:
|
|
57
|
-
site_name:
|
|
58
|
-
file_count:
|
|
59
|
-
}),
|
|
60
|
-
} catch (
|
|
61
|
-
|
|
56
|
+
i({ kind: "redirecting" }), u("dropzone_deploy_succeeded", {
|
|
57
|
+
method: l,
|
|
58
|
+
site_name: d.subdomain,
|
|
59
|
+
file_count: e.length
|
|
60
|
+
}), s == null || s({ url: o, token: t, siteName: d.subdomain, siteId: d.id }), window.location.assign(`${g(d.subdomain)}#drop_token=${t}`);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
w(e);
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
|
-
function
|
|
65
|
-
|
|
65
|
+
function N() {
|
|
66
|
+
m(null), i({ kind: "idle" });
|
|
66
67
|
}
|
|
67
|
-
return { status:
|
|
68
|
+
return { status: c, warning: h, busy: k, deploy: _, reset: N };
|
|
68
69
|
}
|
|
69
70
|
export {
|
|
70
|
-
|
|
71
|
+
q as useDropDeploy
|
|
71
72
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from 'preact/hooks';
|
|
2
2
|
import type { ComponentChildren } from 'preact';
|
|
3
3
|
import { readDataTransfer, readFileList, type DropClient } from './drop-core';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
useDropDeploy,
|
|
6
|
+
type DeployedSite,
|
|
7
|
+
type DeployError,
|
|
8
|
+
type DeployStatus,
|
|
9
|
+
type TrackFn,
|
|
10
|
+
} from './useDropDeploy';
|
|
5
11
|
|
|
6
12
|
import './DropZone.css';
|
|
7
13
|
|
|
@@ -21,11 +27,18 @@ interface Props {
|
|
|
21
27
|
claimUrl?: (siteName: string) => string;
|
|
22
28
|
/** Called once the deploy is live. */
|
|
23
29
|
onDeploy?: (result: DeployedSite) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Called when a deploy fails, with a humanized `message` (ready to show a
|
|
32
|
+
* user — the same copy the built-in overlay uses) and the raw `reason`. Pair
|
|
33
|
+
* this with `showStatus={false}` to render your own error UI.
|
|
34
|
+
*/
|
|
35
|
+
onError?: (error: DeployError) => void;
|
|
24
36
|
/**
|
|
25
37
|
* Render the built-in status overlay (drag tint, spinner, progress bar, error).
|
|
26
38
|
* Set to `false` to suppress it entirely and keep your children visible, then
|
|
27
39
|
* drive your own feedback from the `data-state` attribute on the root element.
|
|
28
|
-
* Note: in this mode you're responsible for surfacing errors yourself
|
|
40
|
+
* Note: in this mode you're responsible for surfacing errors yourself — use
|
|
41
|
+
* `onError` to get the message.
|
|
29
42
|
*/
|
|
30
43
|
showStatus?: boolean;
|
|
31
44
|
/**
|
|
@@ -54,6 +67,7 @@ export default function DropZone({
|
|
|
54
67
|
client,
|
|
55
68
|
claimUrl = defaultClaimUrl,
|
|
56
69
|
onDeploy,
|
|
70
|
+
onError,
|
|
57
71
|
showStatus = true,
|
|
58
72
|
onTrack,
|
|
59
73
|
analyticsId,
|
|
@@ -69,6 +83,7 @@ export default function DropZone({
|
|
|
69
83
|
client,
|
|
70
84
|
claimUrl,
|
|
71
85
|
onDeploy,
|
|
86
|
+
onError,
|
|
72
87
|
track,
|
|
73
88
|
});
|
|
74
89
|
|
|
@@ -22,6 +22,14 @@ export interface DeployedSite {
|
|
|
22
22
|
siteId: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/** A deploy failure, handed to `onError` so consumers can render their own error UI. */
|
|
26
|
+
export interface DeployError {
|
|
27
|
+
/** Human-readable text ready to show a user — the same copy the built-in overlay displays. */
|
|
28
|
+
message: string;
|
|
29
|
+
/** The raw underlying reason (e.g. "drop failed: 429"), useful for logging. */
|
|
30
|
+
reason: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
/** Finite states of a single deploy attempt. */
|
|
26
34
|
export type DeployStatus =
|
|
27
35
|
| { kind: 'idle' }
|
|
@@ -40,6 +48,7 @@ interface UseDropDeployOptions {
|
|
|
40
48
|
client?: DropClient;
|
|
41
49
|
claimUrl: (siteName: string) => string;
|
|
42
50
|
onDeploy?: (site: DeployedSite) => void;
|
|
51
|
+
onError?: (error: DeployError) => void;
|
|
43
52
|
track: TrackFn;
|
|
44
53
|
}
|
|
45
54
|
|
|
@@ -77,6 +86,7 @@ export function useDropDeploy({
|
|
|
77
86
|
client,
|
|
78
87
|
claimUrl,
|
|
79
88
|
onDeploy,
|
|
89
|
+
onError,
|
|
80
90
|
track,
|
|
81
91
|
}: UseDropDeployOptions) {
|
|
82
92
|
const [status, setStatus] = useState<DeployStatus>({ kind: 'idle' });
|
|
@@ -96,9 +106,12 @@ export function useDropDeploy({
|
|
|
96
106
|
// included where the file set is known (it isn't if `read()` itself threw).
|
|
97
107
|
// `reason` goes to analytics as-is (raw, e.g. "drop failed: 429"); `message`
|
|
98
108
|
// is what the user sees, which for a caught error is humanized separately.
|
|
109
|
+
// `onError` gets both so a consumer (e.g. with `showStatus={false}`) can show
|
|
110
|
+
// the humanized message while keeping the raw reason for their own logging.
|
|
99
111
|
const fail = (message: string, reason: string, extra?: Record<string, unknown>) => {
|
|
100
112
|
setStatus({ kind: 'error', message });
|
|
101
113
|
track('dropzone_deploy_failed', { method: source, reason, ...extra });
|
|
114
|
+
onError?.({ message, reason });
|
|
102
115
|
};
|
|
103
116
|
|
|
104
117
|
const failFromError = (err: unknown, extra?: Record<string, unknown>) => {
|