@drawbridge/components 0.1.5 → 0.1.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.
@@ -1,4 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useQueryClient } from "@tanstack/react-query";
2
3
  import { capitalize, formatDateString } from "@drawbridge/drawbridge-utils";
3
4
  import Accordion from "./accordion.mjs";
4
5
  import Paged from "./paged.mjs";
@@ -23,6 +24,14 @@ const indicatorType = (status) => {
23
24
  if (status === "partial" || status === "skipped") return "warning";
24
25
  return "inactive";
25
26
  };
27
+ const replyExcerpt = (response, length = 300) => {
28
+ const wrapped = response && typeof response === "object" && !Array.isArray(response) && Object.keys(response).length === 1 && "body" in response;
29
+ const reply = wrapped ? response.body : response;
30
+ if (reply === void 0 || reply === null) return null;
31
+ const text = (typeof reply === "string" ? reply : JSON.stringify(reply)).replace(/<(script|style)\b[\s\S]*?<\/\1>/gi, " ").replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim();
32
+ if (!text) return null;
33
+ return text.length > length ? text.slice(0, length) + "\u2026" : text;
34
+ };
26
35
  const StepItem = ({
27
36
  updatedAt,
28
37
  error: chunkError,
@@ -35,6 +44,7 @@ const StepItem = ({
35
44
  }) => {
36
45
  const error = chunkError || status === "failed" && message || null;
37
46
  const notice = error || status === "skipped" && message || null;
47
+ const reply = error ? replyExcerpt(response) : null;
38
48
  return /* @__PURE__ */ jsxs(
39
49
  "div",
40
50
  {
@@ -102,13 +112,51 @@ const StepItem = ({
102
112
  }
103
113
  )
104
114
  },
105
- children: notice ? /* @__PURE__ */ jsx(
106
- CardTask,
115
+ children: notice ? /* @__PURE__ */ jsxs(
116
+ "div",
107
117
  {
108
118
  ...{
109
- message: notice,
110
- type: error ? "error" : "warning"
111
- }
119
+ className: "space-y-3"
120
+ },
121
+ children: [
122
+ /* @__PURE__ */ jsx(
123
+ CardTask,
124
+ {
125
+ ...{
126
+ message: notice,
127
+ type: error ? "error" : "warning"
128
+ }
129
+ }
130
+ ),
131
+ reply && /* @__PURE__ */ jsxs(
132
+ "div",
133
+ {
134
+ ...{
135
+ className: "space-y-1"
136
+ },
137
+ children: [
138
+ /* @__PURE__ */ jsx(
139
+ "p",
140
+ {
141
+ ...{
142
+ className: "text-xs text-gray-dark"
143
+ },
144
+ children: "Response"
145
+ }
146
+ ),
147
+ /* @__PURE__ */ jsx(
148
+ "p",
149
+ {
150
+ ...{
151
+ className: "text-xs break-words"
152
+ },
153
+ children: reply
154
+ }
155
+ )
156
+ ]
157
+ }
158
+ )
159
+ ]
112
160
  }
113
161
  ) : /* @__PURE__ */ jsx(
114
162
  CodeFormater,
@@ -141,11 +189,15 @@ const groupTitle = ({ count, email, items, kind, pending }) => {
141
189
  const entries = count + " new " + (count === 1 ? "entry" : "entries");
142
190
  return "Team notification \u2014 " + entries + (pending ? ", sending" : "");
143
191
  };
144
- const rowLabel = ({ item, kind }) => {
145
- if (kind !== "notify") return item == null ? void 0 : item.slug;
192
+ const rowLabel = ({ item, kind, labels = [] }) => {
193
+ var _a;
194
+ if (kind !== "notify") return ((_a = labels.find((option) => option.value === (item == null ? void 0 : item.slug))) == null ? void 0 : _a.key) || (item == null ? void 0 : item.slug);
146
195
  return NOTIFY_LABELS[item == null ? void 0 : item.status] || NOTIFY_LABELS.succeeded;
147
196
  };
148
- const Group = ({ group }) => {
197
+ const Group = ({
198
+ group,
199
+ labels
200
+ }) => {
149
201
  const { items, kind } = group;
150
202
  return /* @__PURE__ */ jsxs("div", { children: [
151
203
  /* @__PURE__ */ jsx(
@@ -172,7 +224,7 @@ const Group = ({ group }) => {
172
224
  {
173
225
  ...{
174
226
  ...item,
175
- label: rowLabel({ item, kind })
227
+ label: rowLabel({ item, kind, labels })
176
228
  }
177
229
  },
178
230
  key
@@ -186,6 +238,8 @@ const Steps = ({
186
238
  limit = 24,
187
239
  organization
188
240
  }) => {
241
+ var _a, _b, _c, _d;
242
+ const labels = (_d = (_c = (_b = (_a = useQueryClient().getQueryData(["app"])) == null ? void 0 : _a.enums) == null ? void 0 : _b.step) == null ? void 0 : _c.type) == null ? void 0 : _d.options;
189
243
  return /* @__PURE__ */ jsx(
190
244
  Paged,
191
245
  {
@@ -211,7 +265,8 @@ const Steps = ({
211
265
  Group,
212
266
  {
213
267
  ...{
214
- group
268
+ group,
269
+ labels
215
270
  }
216
271
  },
217
272
  key
@@ -225,5 +280,6 @@ var steps_default = Steps;
225
280
  export {
226
281
  steps_default as default,
227
282
  groupTitle,
283
+ replyExcerpt,
228
284
  rowLabel
229
285
  };
@@ -30,6 +30,7 @@ __export(template_dashboard_exports, {
30
30
  Refetch: () => Refetch,
31
31
  TemplateDashboardError: () => TemplateDashboardError,
32
32
  TemplateDashboardResource: () => TemplateDashboardResource,
33
+ TemplateDashboardTasks: () => TemplateDashboardTasks,
33
34
  default: () => template_dashboard_default
34
35
  });
35
36
  module.exports = __toCommonJS(template_dashboard_exports);
@@ -382,55 +383,74 @@ const TemplateDashboardTasks = ({
382
383
  });
383
384
  const array = [...items];
384
385
  const first = array.shift();
385
- const openAll = () => {
386
- open({
387
- title: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
388
- "span",
389
- {
390
- ...{
391
- className: "flex items-center space-x-3"
392
- },
393
- children: [
394
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Next steps" }),
395
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
396
- import_badge.default,
397
- {
398
- ...{
399
- type: "warning"
400
- },
401
- children: array.length + 1
402
- }
403
- )
404
- ]
405
- }
406
- ),
407
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
408
- "div",
409
- {
410
- ...{
411
- className: "p-6"
412
- },
413
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
414
- import_list.default,
386
+ const nextSteps = () => ({
387
+ title: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
388
+ "span",
389
+ {
390
+ ...{
391
+ className: "flex items-center space-x-3"
392
+ },
393
+ children: [
394
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Next steps" }),
395
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
396
+ import_badge.default,
415
397
  {
416
398
  ...{
417
- items: [
418
- {
419
- ...first,
420
- onClick: () => close()
421
- },
422
- ...array.map((props) => ({
423
- ...props,
424
- onClick: () => close()
425
- }))
426
- ]
427
- }
399
+ type: "warning"
400
+ },
401
+ children: array.length + 1
428
402
  }
429
403
  )
430
- }
431
- )
432
- });
404
+ ]
405
+ }
406
+ ),
407
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
408
+ "div",
409
+ {
410
+ ...{
411
+ className: "p-6"
412
+ },
413
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
414
+ import_list.default,
415
+ {
416
+ ...{
417
+ items: [
418
+ {
419
+ ...first,
420
+ onClick: () => close()
421
+ },
422
+ ...array.map((props) => ({
423
+ ...props,
424
+ onClick: () => close()
425
+ }))
426
+ ]
427
+ }
428
+ }
429
+ )
430
+ }
431
+ )
432
+ });
433
+ const shown = (0, import_react.useRef)(null);
434
+ const openAll = () => {
435
+ const props = nextSteps();
436
+ shown.current = props.children;
437
+ open(props);
433
438
  };
439
+ (0, import_react.useEffect)(
440
+ () => {
441
+ const drawer = queryClient.getQueryData(["drawer"]);
442
+ if (!shown.current || !(drawer == null ? void 0 : drawer.active) || drawer.children !== shown.current) return;
443
+ if (!first) {
444
+ shown.current = null;
445
+ close();
446
+ return;
447
+ }
448
+ openAll();
449
+ },
450
+ // The tasks are the trigger; the rest follows them.
451
+ // eslint-disable-next-line react-hooks/exhaustive-deps
452
+ [items]
453
+ );
434
454
  if (first) {
435
455
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
436
456
  "div",
@@ -733,5 +753,6 @@ var template_dashboard_default = TemplateDashboard;
733
753
  0 && (module.exports = {
734
754
  Refetch,
735
755
  TemplateDashboardError,
736
- TemplateDashboardResource
756
+ TemplateDashboardResource,
757
+ TemplateDashboardTasks
737
758
  });
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { isValidElement, useEffect, useState } from "react";
2
+ import { isValidElement, useEffect, useRef, useState } from "react";
3
3
  import { keepPreviousData, useIsFetching, useQueryClient } from "@tanstack/react-query";
4
4
  import { notFound } from "next/navigation";
5
5
  import { isTransientError } from "@drawbridge/drawbridge-utils/fetch";
@@ -347,55 +347,74 @@ const TemplateDashboardTasks = ({
347
347
  });
348
348
  const array = [...items];
349
349
  const first = array.shift();
350
- const openAll = () => {
351
- open({
352
- title: /* @__PURE__ */ jsxs(
353
- "span",
354
- {
355
- ...{
356
- className: "flex items-center space-x-3"
357
- },
358
- children: [
359
- /* @__PURE__ */ jsx("span", { children: "Next steps" }),
360
- /* @__PURE__ */ jsx(
361
- Badge,
362
- {
363
- ...{
364
- type: "warning"
365
- },
366
- children: array.length + 1
367
- }
368
- )
369
- ]
370
- }
371
- ),
372
- children: /* @__PURE__ */ jsx(
373
- "div",
374
- {
375
- ...{
376
- className: "p-6"
377
- },
378
- children: /* @__PURE__ */ jsx(
379
- List,
350
+ const nextSteps = () => ({
351
+ title: /* @__PURE__ */ jsxs(
352
+ "span",
353
+ {
354
+ ...{
355
+ className: "flex items-center space-x-3"
356
+ },
357
+ children: [
358
+ /* @__PURE__ */ jsx("span", { children: "Next steps" }),
359
+ /* @__PURE__ */ jsx(
360
+ Badge,
380
361
  {
381
362
  ...{
382
- items: [
383
- {
384
- ...first,
385
- onClick: () => close()
386
- },
387
- ...array.map((props) => ({
388
- ...props,
389
- onClick: () => close()
390
- }))
391
- ]
392
- }
363
+ type: "warning"
364
+ },
365
+ children: array.length + 1
393
366
  }
394
367
  )
395
- }
396
- )
397
- });
368
+ ]
369
+ }
370
+ ),
371
+ children: /* @__PURE__ */ jsx(
372
+ "div",
373
+ {
374
+ ...{
375
+ className: "p-6"
376
+ },
377
+ children: /* @__PURE__ */ jsx(
378
+ List,
379
+ {
380
+ ...{
381
+ items: [
382
+ {
383
+ ...first,
384
+ onClick: () => close()
385
+ },
386
+ ...array.map((props) => ({
387
+ ...props,
388
+ onClick: () => close()
389
+ }))
390
+ ]
391
+ }
392
+ }
393
+ )
394
+ }
395
+ )
396
+ });
397
+ const shown = useRef(null);
398
+ const openAll = () => {
399
+ const props = nextSteps();
400
+ shown.current = props.children;
401
+ open(props);
398
402
  };
403
+ useEffect(
404
+ () => {
405
+ const drawer = queryClient.getQueryData(["drawer"]);
406
+ if (!shown.current || !(drawer == null ? void 0 : drawer.active) || drawer.children !== shown.current) return;
407
+ if (!first) {
408
+ shown.current = null;
409
+ close();
410
+ return;
411
+ }
412
+ openAll();
413
+ },
414
+ // The tasks are the trigger; the rest follows them.
415
+ // eslint-disable-next-line react-hooks/exhaustive-deps
416
+ [items]
417
+ );
399
418
  if (first) {
400
419
  return /* @__PURE__ */ jsx(
401
420
  "div",
@@ -698,5 +717,6 @@ export {
698
717
  Refetch,
699
718
  TemplateDashboardError,
700
719
  TemplateDashboardResource,
720
+ TemplateDashboardTasks,
701
721
  template_dashboard_default as default
702
722
  };
@@ -439,10 +439,12 @@ const TemplateSocketOrganization = ({
439
439
  queryKey: ["organization-members", params.organization]
440
440
  });
441
441
  },
442
- // Sync wrote or cleared a workflow's run-time issue. The open workflow
443
- // page shows it, the list carries it, and the dashboard's Next steps
444
- // and the sidebar Workflows dot are built server-side off the org and
445
- // menu queries — so all four refetch.
442
+ // @story workflows/list
443
+ // Sync emits this on every workflow status change, on delete, and when
444
+ // a run-time issue is written or cleared. The open workflow page shows
445
+ // it, the list carries it, and the dashboard's Next steps and the
446
+ // sidebar Workflows dot are built server-side off the org and menu
447
+ // queries — so all four refetch.
446
448
  "organization.workflows": () => {
447
449
  queryClient.invalidateQueries({
448
450
  queryKey: ["organization-workflows", params.organization]
@@ -456,6 +458,12 @@ const TemplateSocketOrganization = ({
456
458
  queryClient.invalidateQueries({
457
459
  queryKey: ["menu", "organization", params.organization]
458
460
  });
461
+ queryClient.invalidateQueries({
462
+ queryKey: ["organizations"]
463
+ });
464
+ queryClient.invalidateQueries({
465
+ queryKey: ["shared"]
466
+ });
459
467
  },
460
468
  // A running workflow's steps transition ( insert + status change ) in
461
469
  // sync, which coalesces the burst into one emit per org room. The
@@ -481,6 +489,7 @@ const TemplateSocketOrganization = ({
481
489
  ["organization-connection", params == null ? void 0 : params.organization],
482
490
  ["organization-campaign-products", params == null ? void 0 : params.organization],
483
491
  ["organization-workflows", params == null ? void 0 : params.organization],
492
+ ["organization-workflow", params == null ? void 0 : params.organization],
484
493
  ["organization-workflow-catalog", params == null ? void 0 : params.organization],
485
494
  ["organization-workflow-steps"],
486
495
  ["organization-contacts", params == null ? void 0 : params.organization],
@@ -404,10 +404,12 @@ const TemplateSocketOrganization = ({
404
404
  queryKey: ["organization-members", params.organization]
405
405
  });
406
406
  },
407
- // Sync wrote or cleared a workflow's run-time issue. The open workflow
408
- // page shows it, the list carries it, and the dashboard's Next steps
409
- // and the sidebar Workflows dot are built server-side off the org and
410
- // menu queries — so all four refetch.
407
+ // @story workflows/list
408
+ // Sync emits this on every workflow status change, on delete, and when
409
+ // a run-time issue is written or cleared. The open workflow page shows
410
+ // it, the list carries it, and the dashboard's Next steps and the
411
+ // sidebar Workflows dot are built server-side off the org and menu
412
+ // queries — so all four refetch.
411
413
  "organization.workflows": () => {
412
414
  queryClient.invalidateQueries({
413
415
  queryKey: ["organization-workflows", params.organization]
@@ -421,6 +423,12 @@ const TemplateSocketOrganization = ({
421
423
  queryClient.invalidateQueries({
422
424
  queryKey: ["menu", "organization", params.organization]
423
425
  });
426
+ queryClient.invalidateQueries({
427
+ queryKey: ["organizations"]
428
+ });
429
+ queryClient.invalidateQueries({
430
+ queryKey: ["shared"]
431
+ });
424
432
  },
425
433
  // A running workflow's steps transition ( insert + status change ) in
426
434
  // sync, which coalesces the burst into one emit per org room. The
@@ -446,6 +454,7 @@ const TemplateSocketOrganization = ({
446
454
  ["organization-connection", params == null ? void 0 : params.organization],
447
455
  ["organization-campaign-products", params == null ? void 0 : params.organization],
448
456
  ["organization-workflows", params == null ? void 0 : params.organization],
457
+ ["organization-workflow", params == null ? void 0 : params.organization],
449
458
  ["organization-workflow-catalog", params == null ? void 0 : params.organization],
450
459
  ["organization-workflow-steps"],
451
460
  ["organization-contacts", params == null ? void 0 : params.organization],
@@ -0,0 +1,63 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var video_exports = {};
19
+ __export(video_exports, {
20
+ provideHls: () => provideHls,
21
+ startSeek: () => startSeek,
22
+ videoErrorAction: () => videoErrorAction,
23
+ videoOverlay: () => videoOverlay
24
+ });
25
+ module.exports = __toCommonJS(video_exports);
26
+ const provideHls = (Hls, target) => {
27
+ if (Hls && target && !target.Hls) target.Hls = Hls;
28
+ };
29
+ const videoErrorAction = ({
30
+ data,
31
+ error,
32
+ mp4,
33
+ url
34
+ }) => {
35
+ if (data && !data.fatal) return "ignore";
36
+ if ((error == null ? void 0 : error.name) === "AbortError") return "ignore";
37
+ if ((error == null ? void 0 : error.name) === "NotAllowedError") return "fail";
38
+ return mp4 && url !== mp4 ? "retry" : "fail";
39
+ };
40
+ const videoOverlay = ({
41
+ failed,
42
+ poster,
43
+ videoPaintable
44
+ }) => {
45
+ if (videoPaintable) return null;
46
+ if (poster) return "poster";
47
+ return failed ? "warning" : "loader";
48
+ };
49
+ const SHOWN_START = 1e-3;
50
+ const startSeek = ({
51
+ reset,
52
+ wasReset
53
+ }) => {
54
+ if (reset) return 0;
55
+ return wasReset ? SHOWN_START : null;
56
+ };
57
+ // Annotate the CommonJS export names for ESM import in node:
58
+ 0 && (module.exports = {
59
+ provideHls,
60
+ startSeek,
61
+ videoErrorAction,
62
+ videoOverlay
63
+ });
@@ -0,0 +1,37 @@
1
+ const provideHls = (Hls, target) => {
2
+ if (Hls && target && !target.Hls) target.Hls = Hls;
3
+ };
4
+ const videoErrorAction = ({
5
+ data,
6
+ error,
7
+ mp4,
8
+ url
9
+ }) => {
10
+ if (data && !data.fatal) return "ignore";
11
+ if ((error == null ? void 0 : error.name) === "AbortError") return "ignore";
12
+ if ((error == null ? void 0 : error.name) === "NotAllowedError") return "fail";
13
+ return mp4 && url !== mp4 ? "retry" : "fail";
14
+ };
15
+ const videoOverlay = ({
16
+ failed,
17
+ poster,
18
+ videoPaintable
19
+ }) => {
20
+ if (videoPaintable) return null;
21
+ if (poster) return "poster";
22
+ return failed ? "warning" : "loader";
23
+ };
24
+ const SHOWN_START = 1e-3;
25
+ const startSeek = ({
26
+ reset,
27
+ wasReset
28
+ }) => {
29
+ if (reset) return 0;
30
+ return wasReset ? SHOWN_START : null;
31
+ };
32
+ export {
33
+ provideHls,
34
+ startSeek,
35
+ videoErrorAction,
36
+ videoOverlay
37
+ };
package/dist/video.js CHANGED
@@ -36,8 +36,13 @@ var import_dynamic = __toESM(require("next/dynamic"));
36
36
  var import_react = require("react");
37
37
  var import_loader = __toESM(require("./icons/loader"));
38
38
  var import_warning = __toESM(require("./icons/warning"));
39
+ var import_video = require("./shared/lib/video");
39
40
  const ReactPlayer = (0, import_dynamic.default)(
40
- () => import("react-player/lazy"),
41
+ () => Promise.all([
42
+ import("hls.js").then((module2) => (0, import_video.provideHls)(module2.default || module2, window)).catch(() => {
43
+ }),
44
+ import("react-player/lazy")
45
+ ]).then(([, player]) => player),
41
46
  {
42
47
  ssr: false
43
48
  }
@@ -67,17 +72,22 @@ const Video = ({
67
72
  }) => {
68
73
  var _a, _b, _c, _d;
69
74
  const durationFired = (0, import_react.useRef)(false);
75
+ const errored = (0, import_react.useRef)(false);
70
76
  const [player, setPlayer] = (0, import_react.useState)();
71
77
  const [videoUrl, setVideoUrl] = (0, import_react.useState)(hls ? hls : mp4);
72
78
  const [mountPlayer, setMountPlayer] = (0, import_react.useState)(!defer);
73
79
  const [posterPainted, setPosterPainted] = (0, import_react.useState)(false);
74
80
  const [videoPaintable, setVideoPaintable] = (0, import_react.useState)(false);
75
81
  const [failed, setFailed] = (0, import_react.useState)(false);
82
+ const wasReset = (0, import_react.useRef)(reset);
76
83
  (0, import_react.useEffect)(
77
84
  () => {
78
- if (player && reset) {
79
- player.seekTo(0, "seconds");
85
+ if (!player) return;
86
+ const target = (0, import_video.startSeek)({ reset, wasReset: wasReset.current });
87
+ if (target !== null) {
88
+ player.seekTo(target, "seconds");
80
89
  }
90
+ wasReset.current = reset;
81
91
  },
82
92
  [player, reset]
83
93
  );
@@ -109,6 +119,11 @@ const Video = ({
109
119
  },
110
120
  [defer, mountPlayer, poster, posterPainted]
111
121
  );
122
+ const overlay = (0, import_video.videoOverlay)({
123
+ failed,
124
+ poster,
125
+ videoPaintable
126
+ });
112
127
  const inner = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.Fragment, { children: [
113
128
  mountPlayer && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
114
129
  ReactPlayer,
@@ -154,11 +169,19 @@ const Video = ({
154
169
  onTime == null ? void 0 : onTime(seconds);
155
170
  },
156
171
  progressInterval: 100,
157
- onError: () => {
158
- if (mp4 && videoUrl !== mp4) {
172
+ onError: (error, data) => {
173
+ const action = (0, import_video.videoErrorAction)({
174
+ data,
175
+ error,
176
+ mp4,
177
+ url: videoUrl
178
+ });
179
+ if (action === "ignore" || errored.current) return;
180
+ if (action === "retry") {
159
181
  setVideoUrl(mp4);
160
182
  return;
161
183
  }
184
+ errored.current = true;
162
185
  setFailed(true);
163
186
  onError();
164
187
  },
@@ -183,7 +206,7 @@ const Video = ({
183
206
  }
184
207
  }
185
208
  ),
186
- !videoPaintable && poster && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
209
+ overlay === "poster" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
187
210
  "img",
188
211
  {
189
212
  ...{
@@ -204,7 +227,7 @@ const Video = ({
204
227
  }
205
228
  }
206
229
  ),
207
- !videoPaintable && !poster && !failed && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
230
+ overlay === "loader" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
208
231
  "div",
209
232
  {
210
233
  ...{
@@ -227,7 +250,7 @@ const Video = ({
227
250
  )
228
251
  }
229
252
  ),
230
- failed && !poster && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
253
+ overlay === "warning" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
231
254
  "div",
232
255
  {
233
256
  ...{