@drawbridge/components 0.1.4 → 0.1.6

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.
Files changed (37) hide show
  1. package/README.md +6 -2
  2. package/dist/bridge/template-subdomain-gallery.js +3 -1
  3. package/dist/bridge/template-subdomain-gallery.mjs +3 -1
  4. package/dist/bridge/template-subdomain.js +8 -2
  5. package/dist/bridge/template-subdomain.mjs +8 -2
  6. package/dist/dashboard/card-task.js +13 -15
  7. package/dist/dashboard/card-task.mjs +13 -15
  8. package/dist/dashboard/drawer-subscription.js +2 -2
  9. package/dist/dashboard/drawer-subscription.mjs +2 -2
  10. package/dist/dashboard/form-action.js +70 -60
  11. package/dist/dashboard/form-action.mjs +71 -61
  12. package/dist/dashboard/form-organization-campaign-link.js +3 -1
  13. package/dist/dashboard/form-organization-campaign-link.mjs +3 -1
  14. package/dist/dashboard/form-organization-connection.js +2 -1
  15. package/dist/dashboard/form-organization-connection.mjs +2 -1
  16. package/dist/dashboard/lib/connection-controls.js +6 -2
  17. package/dist/dashboard/lib/connection-controls.mjs +4 -1
  18. package/dist/dashboard/recharts.js +5 -1
  19. package/dist/dashboard/recharts.mjs +5 -1
  20. package/dist/dashboard/steps.js +67 -10
  21. package/dist/dashboard/steps.mjs +66 -10
  22. package/dist/dashboard/table.js +10 -0
  23. package/dist/dashboard/table.mjs +10 -1
  24. package/dist/dashboard/template-dashboard.js +79 -55
  25. package/dist/dashboard/template-dashboard.mjs +78 -55
  26. package/dist/dashboard/template-socket.js +18 -5
  27. package/dist/dashboard/template-socket.mjs +18 -5
  28. package/dist/shared/lib/video.js +63 -0
  29. package/dist/shared/lib/video.mjs +37 -0
  30. package/dist/video.js +31 -8
  31. package/dist/video.mjs +31 -8
  32. package/package.json +13 -7
  33. package/types/dashboard/form-action.d.ts +5 -2
  34. package/types/dashboard/lib/connection-controls.d.ts +10 -0
  35. package/types/dashboard/recharts.d.ts +3 -0
  36. package/types/dashboard/table.d.ts +2 -0
  37. package/types/shared/lib/video.d.ts +9 -0
@@ -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",
@@ -585,19 +604,23 @@ const TemplateDashboardResource = ({
585
604
  refetchOnMount,
586
605
  ...chrome
587
606
  }) => {
607
+ const dynamic = Object.values(chrome).some((value) => value instanceof Function);
588
608
  const errorHandler = error || ((query) => {
589
609
  var _a, _b, _c;
590
- if (((_a = query == null ? void 0 : query.error) == null ? void 0 : _a.status) === 403 || isTransientError(query == null ? void 0 : query.error)) return /* @__PURE__ */ jsx(TemplateDashboard, { children: /* @__PURE__ */ jsx(
591
- TemplateDashboardError,
592
- {
593
- ...{
594
- error: {
595
- ...(_b = query == null ? void 0 : query.error) == null ? void 0 : _b.data,
596
- message: (_c = query == null ? void 0 : query.error) == null ? void 0 : _c.message
610
+ if (((_a = query == null ? void 0 : query.error) == null ? void 0 : _a.status) === 403 || isTransientError(query == null ? void 0 : query.error)) {
611
+ const panel = /* @__PURE__ */ jsx(
612
+ TemplateDashboardError,
613
+ {
614
+ ...{
615
+ error: {
616
+ ...(_b = query == null ? void 0 : query.error) == null ? void 0 : _b.data,
617
+ message: (_c = query == null ? void 0 : query.error) == null ? void 0 : _c.message
618
+ }
597
619
  }
598
620
  }
599
- }
600
- ) });
621
+ );
622
+ return dynamic ? /* @__PURE__ */ jsx(TemplateDashboard, { children: panel }) : panel;
623
+ }
601
624
  notFound();
602
625
  });
603
626
  const provider = {
@@ -619,7 +642,6 @@ const TemplateDashboardResource = ({
619
642
  }
620
643
  };
621
644
  const resolve = (value, data) => value instanceof Function ? value(data) : value;
622
- const dynamic = Object.values(chrome).some((value) => value instanceof Function);
623
645
  if (!dynamic) return /* @__PURE__ */ jsx(
624
646
  TemplateDashboard,
625
647
  {
@@ -695,5 +717,6 @@ export {
695
717
  Refetch,
696
718
  TemplateDashboardError,
697
719
  TemplateDashboardResource,
720
+ TemplateDashboardTasks,
698
721
  template_dashboard_default as default
699
722
  };
@@ -171,6 +171,9 @@ const TemplateSocketCampaign = ({
171
171
  queryClient.invalidateQueries({
172
172
  queryKey: ["organization-campaign-prize-draws", prize]
173
173
  });
174
+ queryClient.invalidateQueries({
175
+ queryKey: ["organization-campaign-prizes", params.organization, params.campaign]
176
+ });
174
177
  }
175
178
  },
176
179
  // The live handler applies leads as a delta, which can't be replayed after
@@ -184,7 +187,8 @@ const TemplateSocketCampaign = ({
184
187
  resync: [
185
188
  ["campaign", params == null ? void 0 : params.campaign],
186
189
  ["campaign-advertisements", params == null ? void 0 : params.organization, params == null ? void 0 : params.campaign],
187
- ["organization-campaign-advertisement"]
190
+ ["organization-campaign-advertisement"],
191
+ ["organization-campaign-prizes", params == null ? void 0 : params.organization, params == null ? void 0 : params.campaign]
188
192
  ]
189
193
  });
190
194
  return children;
@@ -435,10 +439,12 @@ const TemplateSocketOrganization = ({
435
439
  queryKey: ["organization-members", params.organization]
436
440
  });
437
441
  },
438
- // Sync wrote or cleared a workflow's run-time issue. The open workflow
439
- // page shows it, the list carries it, and the dashboard's Next steps
440
- // and the sidebar Workflows dot are built server-side off the org and
441
- // 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.
442
448
  "organization.workflows": () => {
443
449
  queryClient.invalidateQueries({
444
450
  queryKey: ["organization-workflows", params.organization]
@@ -452,6 +458,12 @@ const TemplateSocketOrganization = ({
452
458
  queryClient.invalidateQueries({
453
459
  queryKey: ["menu", "organization", params.organization]
454
460
  });
461
+ queryClient.invalidateQueries({
462
+ queryKey: ["organizations"]
463
+ });
464
+ queryClient.invalidateQueries({
465
+ queryKey: ["shared"]
466
+ });
455
467
  },
456
468
  // A running workflow's steps transition ( insert + status change ) in
457
469
  // sync, which coalesces the burst into one emit per org room. The
@@ -477,6 +489,7 @@ const TemplateSocketOrganization = ({
477
489
  ["organization-connection", params == null ? void 0 : params.organization],
478
490
  ["organization-campaign-products", params == null ? void 0 : params.organization],
479
491
  ["organization-workflows", params == null ? void 0 : params.organization],
492
+ ["organization-workflow", params == null ? void 0 : params.organization],
480
493
  ["organization-workflow-catalog", params == null ? void 0 : params.organization],
481
494
  ["organization-workflow-steps"],
482
495
  ["organization-contacts", params == null ? void 0 : params.organization],
@@ -136,6 +136,9 @@ const TemplateSocketCampaign = ({
136
136
  queryClient.invalidateQueries({
137
137
  queryKey: ["organization-campaign-prize-draws", prize]
138
138
  });
139
+ queryClient.invalidateQueries({
140
+ queryKey: ["organization-campaign-prizes", params.organization, params.campaign]
141
+ });
139
142
  }
140
143
  },
141
144
  // The live handler applies leads as a delta, which can't be replayed after
@@ -149,7 +152,8 @@ const TemplateSocketCampaign = ({
149
152
  resync: [
150
153
  ["campaign", params == null ? void 0 : params.campaign],
151
154
  ["campaign-advertisements", params == null ? void 0 : params.organization, params == null ? void 0 : params.campaign],
152
- ["organization-campaign-advertisement"]
155
+ ["organization-campaign-advertisement"],
156
+ ["organization-campaign-prizes", params == null ? void 0 : params.organization, params == null ? void 0 : params.campaign]
153
157
  ]
154
158
  });
155
159
  return children;
@@ -400,10 +404,12 @@ const TemplateSocketOrganization = ({
400
404
  queryKey: ["organization-members", params.organization]
401
405
  });
402
406
  },
403
- // Sync wrote or cleared a workflow's run-time issue. The open workflow
404
- // page shows it, the list carries it, and the dashboard's Next steps
405
- // and the sidebar Workflows dot are built server-side off the org and
406
- // 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.
407
413
  "organization.workflows": () => {
408
414
  queryClient.invalidateQueries({
409
415
  queryKey: ["organization-workflows", params.organization]
@@ -417,6 +423,12 @@ const TemplateSocketOrganization = ({
417
423
  queryClient.invalidateQueries({
418
424
  queryKey: ["menu", "organization", params.organization]
419
425
  });
426
+ queryClient.invalidateQueries({
427
+ queryKey: ["organizations"]
428
+ });
429
+ queryClient.invalidateQueries({
430
+ queryKey: ["shared"]
431
+ });
420
432
  },
421
433
  // A running workflow's steps transition ( insert + status change ) in
422
434
  // sync, which coalesces the burst into one emit per org room. The
@@ -442,6 +454,7 @@ const TemplateSocketOrganization = ({
442
454
  ["organization-connection", params == null ? void 0 : params.organization],
443
455
  ["organization-campaign-products", params == null ? void 0 : params.organization],
444
456
  ["organization-workflows", params == null ? void 0 : params.organization],
457
+ ["organization-workflow", params == null ? void 0 : params.organization],
445
458
  ["organization-workflow-catalog", params == null ? void 0 : params.organization],
446
459
  ["organization-workflow-steps"],
447
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
  ...{
package/dist/video.mjs CHANGED
@@ -4,8 +4,13 @@ import dynamic from "next/dynamic";
4
4
  import { Fragment, useEffect, useRef, useState } from "react";
5
5
  import Loader from "./icons/loader.mjs";
6
6
  import Warning from "./icons/warning.mjs";
7
+ import { provideHls, startSeek, videoErrorAction, videoOverlay } from "./shared/lib/video.mjs";
7
8
  const ReactPlayer = dynamic(
8
- () => import("react-player/lazy"),
9
+ () => Promise.all([
10
+ import("hls.js").then((module) => provideHls(module.default || module, window)).catch(() => {
11
+ }),
12
+ import("react-player/lazy")
13
+ ]).then(([, player]) => player),
9
14
  {
10
15
  ssr: false
11
16
  }
@@ -35,17 +40,22 @@ const Video = ({
35
40
  }) => {
36
41
  var _a, _b, _c, _d;
37
42
  const durationFired = useRef(false);
43
+ const errored = useRef(false);
38
44
  const [player, setPlayer] = useState();
39
45
  const [videoUrl, setVideoUrl] = useState(hls ? hls : mp4);
40
46
  const [mountPlayer, setMountPlayer] = useState(!defer);
41
47
  const [posterPainted, setPosterPainted] = useState(false);
42
48
  const [videoPaintable, setVideoPaintable] = useState(false);
43
49
  const [failed, setFailed] = useState(false);
50
+ const wasReset = useRef(reset);
44
51
  useEffect(
45
52
  () => {
46
- if (player && reset) {
47
- player.seekTo(0, "seconds");
53
+ if (!player) return;
54
+ const target = startSeek({ reset, wasReset: wasReset.current });
55
+ if (target !== null) {
56
+ player.seekTo(target, "seconds");
48
57
  }
58
+ wasReset.current = reset;
49
59
  },
50
60
  [player, reset]
51
61
  );
@@ -77,6 +87,11 @@ const Video = ({
77
87
  },
78
88
  [defer, mountPlayer, poster, posterPainted]
79
89
  );
90
+ const overlay = videoOverlay({
91
+ failed,
92
+ poster,
93
+ videoPaintable
94
+ });
80
95
  const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
81
96
  mountPlayer && /* @__PURE__ */ jsx(
82
97
  ReactPlayer,
@@ -122,11 +137,19 @@ const Video = ({
122
137
  onTime == null ? void 0 : onTime(seconds);
123
138
  },
124
139
  progressInterval: 100,
125
- onError: () => {
126
- if (mp4 && videoUrl !== mp4) {
140
+ onError: (error, data) => {
141
+ const action = videoErrorAction({
142
+ data,
143
+ error,
144
+ mp4,
145
+ url: videoUrl
146
+ });
147
+ if (action === "ignore" || errored.current) return;
148
+ if (action === "retry") {
127
149
  setVideoUrl(mp4);
128
150
  return;
129
151
  }
152
+ errored.current = true;
130
153
  setFailed(true);
131
154
  onError();
132
155
  },
@@ -151,7 +174,7 @@ const Video = ({
151
174
  }
152
175
  }
153
176
  ),
154
- !videoPaintable && poster && /* @__PURE__ */ jsx(
177
+ overlay === "poster" && /* @__PURE__ */ jsx(
155
178
  "img",
156
179
  {
157
180
  ...{
@@ -172,7 +195,7 @@ const Video = ({
172
195
  }
173
196
  }
174
197
  ),
175
- !videoPaintable && !poster && !failed && /* @__PURE__ */ jsx(
198
+ overlay === "loader" && /* @__PURE__ */ jsx(
176
199
  "div",
177
200
  {
178
201
  ...{
@@ -195,7 +218,7 @@ const Video = ({
195
218
  )
196
219
  }
197
220
  ),
198
- failed && !poster && /* @__PURE__ */ jsx(
221
+ overlay === "warning" && /* @__PURE__ */ jsx(
199
222
  "div",
200
223
  {
201
224
  ...{
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawbridge/components",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "exports": {
5
5
  "./advertisement": {
6
6
  "types": "./types/advertisement.d.ts",
@@ -1437,6 +1437,11 @@
1437
1437
  "import": "./dist/shared/lib/icon-labels.mjs",
1438
1438
  "default": "./dist/shared/lib/icon-labels.js"
1439
1439
  },
1440
+ "./shared/lib/video": {
1441
+ "types": "./types/shared/lib/video.d.ts",
1442
+ "import": "./dist/shared/lib/video.mjs",
1443
+ "default": "./dist/shared/lib/video.js"
1444
+ },
1440
1445
  "./shared/lib/yup": {
1441
1446
  "types": "./types/shared/lib/yup.d.ts",
1442
1447
  "import": "./dist/shared/lib/yup.mjs",
@@ -1510,15 +1515,15 @@
1510
1515
  "exports": "node scripts/exports.js",
1511
1516
  "test": ". \"$HOME/.nvm/nvm.sh\" && nvm use && node --test",
1512
1517
  "build": ". \"$HOME/.nvm/nvm.sh\" && nvm use && tsup && node scripts/esm-extensions.js && node --test && npm publish",
1513
- "storybook": "storybook dev -p 6006",
1514
- "storybook:build": "storybook build",
1515
- "test-storybook": "vitest --project=storybook",
1518
+ "app": "storybook dev -p 3003",
1519
+ "app:build": "storybook build",
1520
+ "test:app": "vitest --project=storybook",
1516
1521
  "dev": "tsup --watch --onSuccess \"node scripts/esm-extensions.js\""
1517
1522
  },
1518
1523
  "peerDependencies": {
1519
1524
  "@analytics/google-tag-manager": ">=0.5.5",
1520
1525
  "@drawbridge/drawbridge-telemetry": ">=0.0.19",
1521
- "@drawbridge/drawbridge-utils": ">=0.0.221",
1526
+ "@drawbridge/drawbridge-utils": ">=0.0.222",
1522
1527
  "@headlessui/react": ">=2.1.2",
1523
1528
  "@hookform/resolvers": ">=3.1.1",
1524
1529
  "@sentry/nextjs": ">=10.58.0",
@@ -1636,9 +1641,9 @@
1636
1641
  },
1637
1642
  "devDependencies": {
1638
1643
  "@analytics/google-tag-manager": "0.5.5",
1639
- "@drawbridge/drawbridge-agents": "0.1.74",
1644
+ "@drawbridge/drawbridge-agents": "0.1.90",
1640
1645
  "@drawbridge/drawbridge-telemetry": "0.0.19",
1641
- "@drawbridge/drawbridge-utils": "0.0.221",
1646
+ "@drawbridge/drawbridge-utils": "0.0.222",
1642
1647
  "@headlessui/react": "2.2.9",
1643
1648
  "@hookform/resolvers": "3.1.1",
1644
1649
  "@sentry/nextjs": "10.58.0",
@@ -1694,6 +1699,7 @@
1694
1699
  "@dnd-kit/utilities": "3.2.2",
1695
1700
  "embla-carousel-fade": "8.6.0",
1696
1701
  "embla-carousel-react": "8.6.0",
1702
+ "hls.js": "1.6.19",
1697
1703
  "react-floater": "0.7.9",
1698
1704
  "react-phone-number-input": "3.4.12",
1699
1705
  "react-player": "2.16.0"
@@ -3,12 +3,15 @@ import { ComponentType, ReactNode } from 'react';
3
3
  export interface FormActionProps {
4
4
  // The submit button's label; defaults to 'Confirm'.
5
5
  action?: ReactNode;
6
- // The mutation run on submit.
7
- callback: () => Promise<unknown>;
6
+ // The mutation run on submit. It receives the form's values: any field the
7
+ // children render through a Controller (form context), seeded by defaultValues.
8
+ callback: ( values: Record<string, unknown> ) => Promise<unknown>;
8
9
  // Shows a secondary button beside the action.
9
10
  cancel?: { action?: ReactNode; onClick?: () => void };
10
11
  children?: ReactNode;
11
12
  className?: string;
13
+ // Initial values for fields rendered in the children.
14
+ defaultValues?: Record<string, unknown>;
12
15
  disabled?: boolean;
13
16
  fineprint?: ReactNode;
14
17
  onError?: ( error: Error ) => void;