@blakesteve/roster 5.2.1 → 5.4.0

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 (72) hide show
  1. package/README.md +205 -21
  2. package/dist/components/atoms/Avatar/Avatar.cjs +1 -1
  3. package/dist/components/atoms/Avatar/Avatar.js +1 -1
  4. package/dist/components/atoms/Avatar/avatar-variants.cjs +1 -1
  5. package/dist/components/atoms/Avatar/avatar-variants.js +1 -1
  6. package/dist/components/atoms/Button/button-variants.cjs +1 -1
  7. package/dist/components/atoms/Button/button-variants.js +3 -3
  8. package/dist/components/atoms/Card/card-variants.cjs +1 -1
  9. package/dist/components/atoms/Card/card-variants.js +3 -2
  10. package/dist/components/atoms/Checkbox/Checkbox.cjs +1 -1
  11. package/dist/components/atoms/Checkbox/Checkbox.d.ts +5 -0
  12. package/dist/components/atoms/Checkbox/Checkbox.js +54 -40
  13. package/dist/components/atoms/Checkbox/checkbox-variants.cjs +1 -1
  14. package/dist/components/atoms/Checkbox/checkbox-variants.js +1 -1
  15. package/dist/components/atoms/InlineCode/inline-code-variants.cjs +1 -1
  16. package/dist/components/atoms/InlineCode/inline-code-variants.js +1 -1
  17. package/dist/components/atoms/Input/input-variants.cjs +1 -1
  18. package/dist/components/atoms/Input/input-variants.js +17 -7
  19. package/dist/components/atoms/LabeledDivider/LabeledDivider.cjs +1 -1
  20. package/dist/components/atoms/LabeledDivider/LabeledDivider.js +6 -6
  21. package/dist/components/atoms/MultiSelect/MultiSelect.cjs +1 -1
  22. package/dist/components/atoms/MultiSelect/MultiSelect.js +19 -18
  23. package/dist/components/atoms/PasswordInput/PasswordInput.cjs +1 -1
  24. package/dist/components/atoms/PasswordInput/PasswordInput.js +1 -1
  25. package/dist/components/atoms/Select/select-variants.cjs +1 -1
  26. package/dist/components/atoms/Select/select-variants.js +9 -2
  27. package/dist/components/atoms/Switch/switch-variants.cjs +1 -1
  28. package/dist/components/atoms/Switch/switch-variants.js +1 -1
  29. package/dist/components/atoms/Textarea/textarea-variants.cjs +1 -1
  30. package/dist/components/atoms/Textarea/textarea-variants.js +17 -11
  31. package/dist/components/atoms/Tooltip/Tooltip.cjs +1 -1
  32. package/dist/components/atoms/Tooltip/Tooltip.js +1 -1
  33. package/dist/components/molecules/Accordion/Accordion.cjs +1 -1
  34. package/dist/components/molecules/Accordion/Accordion.js +19 -19
  35. package/dist/components/molecules/Alert/Alert.cjs +1 -1
  36. package/dist/components/molecules/Alert/Alert.js +1 -1
  37. package/dist/components/molecules/CheckboxGroup/CheckboxGroup.cjs +1 -1
  38. package/dist/components/molecules/CheckboxGroup/CheckboxGroup.js +28 -27
  39. package/dist/components/molecules/MediaPreview/MediaPreview.cjs +1 -0
  40. package/dist/components/molecules/MediaPreview/MediaPreview.d.ts +27 -0
  41. package/dist/components/molecules/MediaPreview/MediaPreview.js +55 -0
  42. package/dist/components/molecules/Toast/Toast.cjs +1 -1
  43. package/dist/components/molecules/Toast/Toast.js +1 -1
  44. package/dist/components/organisms/Dialog/Dialog.cjs +1 -1
  45. package/dist/components/organisms/Dialog/Dialog.d.ts +9 -1
  46. package/dist/components/organisms/Dialog/Dialog.js +26 -20
  47. package/dist/components/organisms/ModerationQueue/ModerationQueue.cjs +1 -0
  48. package/dist/components/organisms/ModerationQueue/ModerationQueue.d.ts +73 -0
  49. package/dist/components/organisms/ModerationQueue/ModerationQueue.js +430 -0
  50. package/dist/components/organisms/ModerationQueue/QueueEditDialog.cjs +1 -0
  51. package/dist/components/organisms/ModerationQueue/QueueEditDialog.d.ts +8 -0
  52. package/dist/components/organisms/ModerationQueue/QueueEditDialog.js +37 -0
  53. package/dist/components/organisms/ModerationQueue/QueueEditSheet.cjs +1 -0
  54. package/dist/components/organisms/ModerationQueue/QueueEditSheet.d.ts +12 -0
  55. package/dist/components/organisms/ModerationQueue/QueueEditSheet.js +30 -0
  56. package/dist/components/organisms/ModerationQueue/queue-actions.cjs +1 -0
  57. package/dist/components/organisms/ModerationQueue/queue-actions.d.ts +157 -0
  58. package/dist/components/organisms/ModerationQueue/queue-actions.js +6 -0
  59. package/dist/components/organisms/Navbar/Navbar.cjs +1 -1
  60. package/dist/components/organisms/Navbar/Navbar.js +2 -2
  61. package/dist/components/organisms/Sheet/Sheet.cjs +1 -1
  62. package/dist/components/organisms/Sheet/Sheet.js +1 -1
  63. package/dist/index.d.ts +5 -0
  64. package/dist/internal/popup.cjs +1 -1
  65. package/dist/internal/popup.js +1 -1
  66. package/dist/lib/utils.cjs +1 -1
  67. package/dist/lib/utils.js +16 -11
  68. package/dist/meta.json +3 -3
  69. package/dist/roster.cjs +1 -1
  70. package/dist/roster.css +1 -1
  71. package/dist/roster.js +118 -108
  72. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { jsxs as o, jsx as t } from "react/jsx-runtime";
2
+ import { jsxs as d, jsx as t } from "react/jsx-runtime";
3
3
  import P from "react";
4
4
  import { Description as _ } from "../../../node_modules/@headlessui/react/dist/components/description/description.js";
5
5
  import { Field as S } from "../../../node_modules/@headlessui/react/dist/components/field/field.js";
@@ -17,13 +17,13 @@ const Q = (s) => s.length > 0 && Array.isArray(s[0].options), U = {
17
17
  lg: "rst:text-base"
18
18
  }, or = ({
19
19
  options: s,
20
- value: d,
20
+ value: c,
21
21
  onChange: k,
22
- label: x,
23
- helperText: c,
22
+ label: b,
23
+ helperText: l,
24
24
  errorMessage: i,
25
- maxHeight: b,
26
- disabled: l = !1,
25
+ maxHeight: p,
26
+ disabled: n = !1,
27
27
  variant: N,
28
28
  size: a = "md",
29
29
  columns: w,
@@ -33,16 +33,16 @@ const Q = (s) => s.length > 0 && Array.isArray(s[0].options), U = {
33
33
  panelClassName: L,
34
34
  "aria-describedby": j,
35
35
  "aria-invalid": A,
36
- ...p
36
+ ...v
37
37
  }) => {
38
- const n = !!i, v = R(n, { ...p, "aria-invalid": A }), B = V(p), m = b !== void 0, u = P.useId(), C = [j, c || i ? u : void 0].filter(Boolean).join(" ") || void 0, D = (r, f) => {
38
+ const o = !!i, u = R(o, { ...v, "aria-invalid": A }), B = V(v), m = p !== void 0, f = P.useId(), C = [j, l || i ? f : void 0].filter(Boolean).join(" ") || void 0, D = (r, x) => {
39
39
  k(
40
- f ? [...d, r] : d.filter((O) => O !== r)
40
+ x ? [...c, r] : c.filter((O) => O !== r)
41
41
  );
42
- }, F = (r) => /* @__PURE__ */ o(
42
+ }, F = (r) => /* @__PURE__ */ d(
43
43
  S,
44
44
  {
45
- disabled: l || r.disabled,
45
+ disabled: n || r.disabled,
46
46
  className: "rst:flex rst:items-start rst:gap-2",
47
47
  children: [
48
48
  /* @__PURE__ */ t(
@@ -50,13 +50,14 @@ const Q = (s) => s.length > 0 && Array.isArray(s[0].options), U = {
50
50
  {
51
51
  size: a ?? "md",
52
52
  colorScheme: I,
53
- checked: d.includes(r.value),
54
- onChange: (f) => D(r.value, f),
55
- "aria-invalid": v || void 0,
53
+ checked: c.includes(r.value),
54
+ onChange: (x) => D(r.value, x),
55
+ "aria-invalid": u || void 0,
56
+ "aria-describedby": o ? f : void 0,
56
57
  className: "rst:mt-0.5 rst:shrink-0"
57
58
  }
58
59
  ),
59
- /* @__PURE__ */ o("div", { className: "rst:flex rst:min-w-0 rst:flex-col", children: [
60
+ /* @__PURE__ */ d("div", { className: "rst:flex rst:min-w-0 rst:flex-col", children: [
60
61
  /* @__PURE__ */ t(
61
62
  Z,
62
63
  {
@@ -75,30 +76,30 @@ const Q = (s) => s.length > 0 && Array.isArray(s[0].options), U = {
75
76
  },
76
77
  r.value
77
78
  ), y = (r) => /* @__PURE__ */ t("div", { className: e(K({ columns: w, size: a })), children: r.map(F) });
78
- return /* @__PURE__ */ o(
79
+ return /* @__PURE__ */ d(
79
80
  h,
80
81
  {
81
- disabled: l,
82
+ disabled: n,
82
83
  className: e(
83
84
  "rst:font-ui rst:flex rst:flex-col rst:gap-1.5 rst:min-w-0",
84
85
  E
85
86
  ),
86
87
  ...B,
87
- "aria-invalid": v || void 0,
88
+ "aria-invalid": u || void 0,
88
89
  "aria-describedby": C,
89
90
  children: [
90
- x && /* @__PURE__ */ t(g, { className: "rst:block rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)] rst:text-left rst:data-disabled:opacity-50", children: x }),
91
+ b && /* @__PURE__ */ t(g, { className: "rst:block rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)] rst:text-left rst:data-disabled:opacity-50", children: b }),
91
92
  /* @__PURE__ */ t(
92
93
  "div",
93
94
  {
94
95
  className: e(
95
- J({ variant: N, size: a, error: n }),
96
+ J({ variant: N, size: a, error: o }),
96
97
  m && "rst:overflow-y-auto rst:custom-scrollbar rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:focus-visible:ring-offset-2 rst:ring-offset-background",
97
98
  /* Deprecated name first, so the current one wins when both are set. */
98
99
  L,
99
100
  G
100
101
  ),
101
- style: m ? { maxHeight: b } : void 0,
102
+ style: m ? { maxHeight: p } : void 0,
102
103
  tabIndex: m ? 0 : void 0,
103
104
  children: Q(s) ? s.map((r) => (
104
105
  /* Nested fieldset per category, so the heading is the group's
@@ -111,7 +112,7 @@ const Q = (s) => s.length > 0 && Array.isArray(s[0].options), U = {
111
112
  `as={Eyebrow}` overrides Legend's own `as="div"` — it is
112
113
  spread after — so these render as <span>. The registration is
113
114
  what matters and it is unchanged. */
114
- /* @__PURE__ */ o(h, { className: "rst:flex rst:flex-col rst:gap-2", children: [
115
+ /* @__PURE__ */ d(h, { className: "rst:flex rst:flex-col rst:gap-2", children: [
115
116
  /* @__PURE__ */ t(
116
117
  g,
117
118
  {
@@ -127,16 +128,16 @@ const Q = (s) => s.length > 0 && Array.isArray(s[0].options), U = {
127
128
  )) : y(s)
128
129
  }
129
130
  ),
130
- (c || i) && /* @__PURE__ */ t(
131
+ (l || i) && /* @__PURE__ */ t(
131
132
  "p",
132
133
  {
133
- id: u,
134
+ id: f,
134
135
  className: e(
135
136
  "rst:text-xs rst:text-left",
136
- n ? "rst:text-error-600 rst:dark:text-error-400 rst:font-medium" : "rst:text-gray-500 rst:dark:text-gray-400",
137
- l && "rst:opacity-50"
137
+ o ? "rst:text-error-600 rst:dark:text-error-400 rst:font-medium" : "rst:text-gray-500 rst:dark:text-gray-400",
138
+ n && "rst:opacity-50"
138
139
  ),
139
- children: i || c
140
+ children: i || l
140
141
  }
141
142
  )
142
143
  ]
@@ -0,0 +1 @@
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),m=require("react"),i=require("../../../lib/utils.cjs");function h({src:e,href:t,alt:s,unavailableLabel:n="Preview unavailable",openLabel:a="Open original",onUnavailable:u,className:o,...g}){const[x,b]=m.useState(null),f=!e||x===e,c="rst:font-ui rst:h-28 rst:w-36 rst:shrink-0 rst:rounded-md rst:border rst:border-[var(--roster-card-border)]";if(f){const d=r.jsxs(r.Fragment,{children:[r.jsx("span",{children:n}),t?r.jsxs("span",{className:"rst:font-semibold rst:underline",children:[a,r.jsx("span",{"aria-hidden":"true",children:" ↗"})]}):null]}),l=i.cn(c,"rst:flex rst:flex-col rst:items-center rst:justify-center rst:gap-1 rst:border-dashed rst:px-2 rst:text-center rst:text-xs rst:text-gray-600 rst:dark:text-gray-300",o);return t?r.jsx("a",{href:t,target:"_blank",rel:"noreferrer",className:i.cn(l,"rst:hover:bg-gray-50 rst:dark:hover:bg-gray-800 rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring"),"aria-label":`${n}. ${a}, in a new tab: ${s}`,children:d}):r.jsx("span",{role:"img","aria-label":`${n}: ${s}`,className:l,children:d})}return r.jsx("img",{...g,src:e,alt:s,className:i.cn(c,"rst:object-cover",o),onError:()=>{b(e),u?.()}})}exports.MediaPreview=h;
@@ -0,0 +1,27 @@
1
+ import { ImgHTMLAttributes } from 'react';
2
+ export interface MediaPreviewProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, "src" | "alt" | "onError"> {
3
+ /** The thumbnail. Missing or failing to load, the preview falls back. */
4
+ src?: string | null;
5
+ /** The original, opened from the fallback. Without it the fallback says so. */
6
+ href?: string | null;
7
+ /** What the image shows. Required: a preview in a queue is content. */
8
+ alt: string;
9
+ /** What the fallback says before "Open original". */
10
+ unavailableLabel?: string;
11
+ /** The link's own words. */
12
+ openLabel?: string;
13
+ /** Called once when the thumbnail fails, for an app that keeps a count. */
14
+ onUnavailable?: () => void;
15
+ }
16
+ /**
17
+ * A thumbnail that admits when it can't render.
18
+ *
19
+ * Previews fail in ordinary ways: a short-lived signed link that expired, or a
20
+ * format the browser can't draw, such as a photo straight off a phone. The
21
+ * browser's answer is a broken-image glyph, which tells a reviewer nothing
22
+ * and hides the one thing they may need to see before deciding. This swaps it
23
+ * for a card that says the preview is unavailable and links to the original,
24
+ * in the same footprint, so a row of previews doesn't jump.
25
+ */
26
+ declare function MediaPreview({ src, href, alt, unavailableLabel, openLabel, onUnavailable, className, ...props }: MediaPreviewProps): import("react/jsx-runtime").JSX.Element;
27
+ export { MediaPreview };
@@ -0,0 +1,55 @@
1
+ "use client";
2
+ import { jsx as r, jsxs as m, Fragment as x } from "react/jsx-runtime";
3
+ import { useState as p } from "react";
4
+ import { cn as i } from "../../../lib/utils.js";
5
+ function $({
6
+ src: e,
7
+ href: t,
8
+ alt: s,
9
+ unavailableLabel: n = "Preview unavailable",
10
+ openLabel: o = "Open original",
11
+ onUnavailable: g,
12
+ className: a,
13
+ ...u
14
+ }) {
15
+ const [f, b] = p(null), h = !e || f === e, d = "rst:font-ui rst:h-28 rst:w-36 rst:shrink-0 rst:rounded-md rst:border rst:border-[var(--roster-card-border)]";
16
+ if (h) {
17
+ const l = /* @__PURE__ */ m(x, { children: [
18
+ /* @__PURE__ */ r("span", { children: n }),
19
+ t ? /* @__PURE__ */ m("span", { className: "rst:font-semibold rst:underline", children: [
20
+ o,
21
+ /* @__PURE__ */ r("span", { "aria-hidden": "true", children: " ↗" })
22
+ ] }) : null
23
+ ] }), c = i(
24
+ d,
25
+ "rst:flex rst:flex-col rst:items-center rst:justify-center rst:gap-1 rst:border-dashed rst:px-2 rst:text-center rst:text-xs rst:text-gray-600 rst:dark:text-gray-300",
26
+ a
27
+ );
28
+ return t ? /* @__PURE__ */ r(
29
+ "a",
30
+ {
31
+ href: t,
32
+ target: "_blank",
33
+ rel: "noreferrer",
34
+ className: i(c, "rst:hover:bg-gray-50 rst:dark:hover:bg-gray-800 rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring"),
35
+ "aria-label": `${n}. ${o}, in a new tab: ${s}`,
36
+ children: l
37
+ }
38
+ ) : /* @__PURE__ */ r("span", { role: "img", "aria-label": `${n}: ${s}`, className: c, children: l });
39
+ }
40
+ return /* @__PURE__ */ r(
41
+ "img",
42
+ {
43
+ ...u,
44
+ src: e,
45
+ alt: s,
46
+ className: i(d, "rst:object-cover", a),
47
+ onError: () => {
48
+ b(e), g?.();
49
+ }
50
+ }
51
+ );
52
+ }
53
+ export {
54
+ $ as MediaPreview
55
+ };
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),p=require("react"),c=require("../../../node_modules/@fortawesome/react-fontawesome/dist/index.cjs"),s=require("../../../node_modules/@fortawesome/free-solid-svg-icons/index.cjs"),l=require("../../../lib/utils.cjs"),g=require("./toast-variants.cjs");function x(r){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const a in r)if(a!=="default"){const n=Object.getOwnPropertyDescriptor(r,a);Object.defineProperty(t,a,n.get?n:{enumerable:!0,get:()=>r[a]})}}return t.default=r,Object.freeze(t)}const j=x(p),h={success:s.faCircleCheck,error:s.faCircleExclamation,amber:s.faTriangleExclamation,info:s.faCircleInfo,primary:s.faCircleInfo,neutral:s.faCircleInfo},u=j.forwardRef(({className:r,colorScheme:t="neutral",variant:a="soft",title:n,icon:i,onDismiss:o,dismissLabel:f="Dismiss",children:d,...m},b)=>e.jsxs("div",{ref:b,className:l.cn(g.toastVariants({colorScheme:t,variant:a}),r),...m,children:[i!==null&&e.jsx("span",{"aria-hidden":"true",className:"rst:mt-0.5 rst:shrink-0",children:i??e.jsx(c.FontAwesomeIcon,{icon:h[t??"neutral"],className:"rst:h-4 rst:w-4"})}),e.jsxs("div",{className:"rst:flex rst:min-w-0 rst:flex-col rst:gap-0.5",children:[n&&e.jsx("p",{className:"rst:font-semibold",children:n}),e.jsx("div",{className:"rst:min-w-0 rst:break-words",children:d})]}),o&&e.jsx("button",{type:"button",onClick:o,"aria-label":f,className:l.cn("rst:-mr-1 rst:ml-auto rst:shrink-0 rst:cursor-pointer rst:rounded rst:opacity-70 rst:hover:opacity-100","rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:ring-offset-background rst:focus-visible:ring-offset-2"),children:e.jsx(c.FontAwesomeIcon,{icon:s.faXmark,className:"rst:h-3.5 rst:w-3.5","aria-hidden":"true"})})]}));u.displayName="Toast";exports.Toast=u;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),p=require("react"),c=require("../../../node_modules/@fortawesome/react-fontawesome/dist/index.cjs"),r=require("../../../node_modules/@fortawesome/free-solid-svg-icons/index.cjs"),l=require("../../../lib/utils.cjs"),g=require("./toast-variants.cjs");function x(s){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(s){for(const a in s)if(a!=="default"){const n=Object.getOwnPropertyDescriptor(s,a);Object.defineProperty(t,a,n.get?n:{enumerable:!0,get:()=>s[a]})}}return t.default=s,Object.freeze(t)}const j=x(p),h={success:r.faCircleCheck,error:r.faCircleExclamation,amber:r.faTriangleExclamation,info:r.faCircleInfo,primary:r.faCircleInfo,neutral:r.faCircleInfo},u=j.forwardRef(({className:s,colorScheme:t="neutral",variant:a="soft",title:n,icon:i,onDismiss:o,dismissLabel:f="Dismiss",children:d,...m},b)=>e.jsxs("div",{ref:b,className:l.cn(g.toastVariants({colorScheme:t,variant:a}),s),...m,children:[i!==null&&e.jsx("span",{"aria-hidden":"true",className:"rst:mt-0.5 rst:shrink-0",children:i??e.jsx(c.FontAwesomeIcon,{icon:h[t??"neutral"],className:"rst:h-4 rst:w-4"})}),e.jsxs("div",{className:"rst:flex rst:min-w-0 rst:flex-col rst:gap-0.5",children:[n&&e.jsx("p",{className:"rst:font-semibold",children:n}),e.jsx("div",{className:"rst:min-w-0 rst:break-words",children:d})]}),o&&e.jsx("button",{type:"button",onClick:o,"aria-label":f,className:l.cn("rst:-mr-1 rst:ml-auto rst:shrink-0 rst:cursor-pointer rst:rounded-sm rst:opacity-70 rst:hover:opacity-100","rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:ring-offset-background rst:focus-visible:ring-offset-2"),children:e.jsx(c.FontAwesomeIcon,{icon:r.faXmark,className:"rst:h-3.5 rst:w-3.5","aria-hidden":"true"})})]}));u.displayName="Toast";exports.Toast=u;
@@ -48,7 +48,7 @@ const w = {
48
48
  onClick: e,
49
49
  "aria-label": f,
50
50
  className: l(
51
- "rst:-mr-1 rst:ml-auto rst:shrink-0 rst:cursor-pointer rst:rounded rst:opacity-70 rst:hover:opacity-100",
51
+ "rst:-mr-1 rst:ml-auto rst:shrink-0 rst:cursor-pointer rst:rounded-sm rst:opacity-70 rst:hover:opacity-100",
52
52
  "rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:ring-offset-background rst:focus-visible:ring-offset-2"
53
53
  ),
54
54
  children: /* @__PURE__ */ r(n, { icon: v, className: "rst:h-3.5 rst:w-3.5", "aria-hidden": "true" })
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),t=require("react"),p=require("../../../node_modules/@fortawesome/react-fontawesome/dist/index.cjs"),h=require("../../../node_modules/@fortawesome/free-solid-svg-icons/index.cjs"),o=require("../../../node_modules/class-variance-authority/dist/index.cjs"),s=require("../../../lib/utils.cjs"),j=require("../../../internal/page-inert.cjs"),a=require("../../../node_modules/@headlessui/react/dist/components/dialog/dialog.cjs"),d=require("../../../node_modules/@headlessui/react/dist/components/transition/transition.cjs"),k=o.cva("rst:relative rst:w-full rst:transform rst:overflow-hidden rst:rounded-2xl rst:p-6 rst:text-left rst:align-middle rst:elevation-overlay rst:transition-all rst:border",{variants:{size:{xs:"rst:max-w-xs",sm:"rst:max-w-sm",md:"rst:max-w-md",lg:"rst:max-w-lg",xl:"rst:max-w-xl","2xl":"rst:max-w-2xl","3xl":"rst:max-w-3xl",full:"rst:max-w-[95vw] rst:m-4"},variant:{white:"rst:bg-[var(--roster-popover-bg)] rst:border-[var(--roster-popover-border)] rst:text-[var(--roster-popover-text)]",slate:"rst:bg-gray-700 rst:border-gray-600 rst:text-gray-100 rst:dark:bg-gray-900 rst:dark:border-gray-800 rst:[--roster-ring:var(--roster-primary-400,#5ea3de)] rst:[--roster-ring-offset:var(--roster-gray-700,#44403c)] rst:dark:[--roster-ring-offset:var(--roster-gray-900,#1c1917)] rst:[--roster-control-text:var(--roster-gray-100,#f5f5f4)] rst:[--roster-control-border:var(--roster-gray-400,#a8a29e)] rst:[--roster-control-border-focus:var(--roster-primary-400,#5ea3de)]",primary:"rst:bg-primary-700 rst:border-primary-600 rst:text-white rst:dark:bg-primary-950 rst:dark:border-primary-900 rst:[--roster-ring:var(--roster-primary-400,#5ea3de)] rst:[--roster-ring-offset:var(--roster-primary-700,#084063)] rst:dark:[--roster-ring-offset:var(--roster-primary-950,#021724)] rst:[--roster-control-text:var(--roster-gray-100,#f5f5f4)] rst:[--roster-control-border:var(--roster-gray-400,#a8a29e)] rst:[--roster-control-border-focus:var(--roster-primary-400,#5ea3de)]",glass:"rst:bg-white/80 rst:border-white/20 rst:backdrop-blur-xl rst:text-gray-900 rst:dark:bg-slate-900/80 rst:dark:border-slate-700/50 rst:dark:text-white"},status:{default:"",destructive:"rst:border-t-4 rst:border-t-error-500",success:"rst:border-t-4 rst:border-t-success-500"}},defaultVariants:{size:"md",variant:"white",status:"default"}}),w=o.cva("rst:text-xl rst:font-bold rst:leading-6 rst:text-inherit"),N=o.cva("rst:mt-1 rst:text-sm rst:text-inherit rst:opacity-75"),q=o.cva("rst:inline-flex rst:size-11 rst:shrink-0 rst:items-center rst:justify-center rst:-m-3 rst:cursor-pointer rst:rounded-md rst:bg-transparent rst:text-inherit rst:opacity-50 rst:hover:opacity-100 rst:focus:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:focus-visible:ring-offset-2 rst:ring-offset-background rst:transition-opacity"),F=({isOpen:u,onClose:i,title:m,description:n,size:x,variant:l,status:g,children:f,className:v})=>{const[b,y]=t.useState(!1);t.useLayoutEffect(()=>{y(!0)},[]);const e=u&&b,c=t.useRef(null);return t.useLayoutEffect(()=>{if(e)return j.lockPage(c.current)},[e]),r.jsxs(r.Fragment,{children:[e&&r.jsx("span",{ref:c,hidden:!0}),r.jsxs(a.Dialog,{open:e,as:"div",className:"rst:font-ui rst:relative rst:z-50",onClose:i,children:[r.jsx(d.TransitionChild,{as:t.Fragment,enter:"rst:ease-out rst:duration-300",enterFrom:"rst:opacity-0",enterTo:"rst:opacity-100",leave:"rst:ease-in rst:duration-200",leaveFrom:"rst:opacity-100",leaveTo:"rst:opacity-0",children:r.jsx(a.DialogBackdrop,{className:s.cn("rst:fixed rst:inset-0 rst:transition-opacity",l==="glass"?"rst:bg-slate-900/40 rst:dark:bg-black/60":"rst:bg-slate-900/60 rst:dark:bg-black/80 rst:backdrop-blur-sm")})}),r.jsx("div",{className:"rst:fixed rst:inset-0 rst:overflow-y-auto",children:r.jsx("div",{className:"rst:flex rst:min-h-full rst:items-center rst:justify-center rst:p-4 rst:text-center",children:r.jsx(d.TransitionChild,{as:t.Fragment,enter:"rst:ease-out rst:duration-300",enterFrom:"rst:opacity-0 rst:scale-95",enterTo:"rst:opacity-100 rst:scale-100",leave:"rst:ease-in rst:duration-200",leaveFrom:"rst:opacity-100 rst:scale-100",leaveTo:"rst:opacity-0 rst:scale-95",children:r.jsxs(a.DialogPanel,{className:s.cn(k({size:x,variant:l,status:g}),v),children:[r.jsxs("div",{className:"rst:flex rst:items-start rst:justify-between",children:[r.jsxs("div",{children:[r.jsx(a.DialogTitle,{as:"h2",className:s.cn(w()),children:m}),n&&r.jsx("p",{className:s.cn(N()),children:n})]}),r.jsx("div",{className:"rst:ml-4 rst:flex rst:shrink-0",children:r.jsx("button",{type:"button",onClick:i,className:s.cn(q()),"aria-label":"Close dialog",children:r.jsx(p.FontAwesomeIcon,{icon:h.faXmark,className:"rst:h-5 rst:w-5"})})})]}),r.jsx("div",{className:"rst:mt-6",children:f})]})})})})]})]})};exports.Dialog=F;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),t=require("react"),h=require("../../../node_modules/@fortawesome/react-fontawesome/dist/index.cjs"),k=require("../../../node_modules/@fortawesome/free-solid-svg-icons/index.cjs"),o=require("../../../node_modules/class-variance-authority/dist/index.cjs"),s=require("../../../lib/utils.cjs"),j=require("../../../internal/page-inert.cjs"),a=require("../../../node_modules/@headlessui/react/dist/components/dialog/dialog.cjs"),d=require("../../../node_modules/@headlessui/react/dist/components/transition/transition.cjs"),w=o.cva("rst:relative rst:w-full rst:transform rst:overflow-hidden rst:rounded-2xl rst:p-6 rst:text-left rst:align-middle rst:elevation-overlay rst:transition-all rst:border",{variants:{size:{xs:"rst:max-w-xs",sm:"rst:max-w-sm",md:"rst:max-w-md",lg:"rst:max-w-lg",xl:"rst:max-w-xl","2xl":"rst:max-w-2xl","3xl":"rst:max-w-3xl",full:"rst:max-w-[95vw] rst:m-4"},variant:{white:"rst:bg-[var(--roster-popover-bg)] rst:border-[var(--roster-popover-border)] rst:text-[var(--roster-popover-text)]",slate:"rst:bg-gray-700 rst:border-gray-600 rst:text-gray-100 rst:dark:bg-gray-900 rst:dark:border-gray-800 rst:[--roster-ring:var(--roster-primary-400,#5ea3de)] rst:[--roster-ring-offset:var(--roster-gray-700,#44403c)] rst:dark:[--roster-ring-offset:var(--roster-gray-900,#1c1917)] rst:[--roster-control-text:var(--roster-gray-100,#f5f5f4)] rst:[--roster-control-border:var(--roster-gray-400,#a8a29e)] rst:[--roster-control-border-focus:var(--roster-primary-400,#5ea3de)]",primary:"rst:bg-primary-700 rst:border-primary-600 rst:text-primary-700-ink rst:dark:text-white rst:dark:bg-primary-950 rst:dark:border-primary-900 rst:[--roster-ring:var(--roster-primary-400,#5ea3de)] rst:[--roster-ring-offset:var(--roster-primary-700,#084063)] rst:dark:[--roster-ring-offset:var(--roster-primary-950,#021724)] rst:[--roster-control-text:var(--roster-gray-100,#f5f5f4)] rst:[--roster-control-border:var(--roster-gray-400,#a8a29e)] rst:[--roster-control-border-focus:var(--roster-primary-400,#5ea3de)]",glass:"rst:bg-white/80 rst:border-white/20 rst:backdrop-blur-xl rst:text-gray-900 rst:dark:bg-slate-900/80 rst:dark:border-slate-700/50 rst:dark:text-white"},status:{default:"",destructive:"rst:border-t-4 rst:border-t-error-500",success:"rst:border-t-4 rst:border-t-success-500"}},defaultVariants:{size:"md",variant:"white",status:"default"}}),N=o.cva("rst:text-xl rst:font-bold rst:leading-6 rst:text-inherit"),_=o.cva("rst:mt-1 rst:text-sm rst:text-inherit rst:opacity-75"),q=o.cva("rst:inline-flex rst:size-11 rst:shrink-0 rst:items-center rst:justify-center rst:-m-3 rst:cursor-pointer rst:rounded-md rst:bg-transparent rst:text-inherit rst:opacity-50 rst:hover:opacity-100 rst:focus:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:focus-visible:ring-offset-2 rst:ring-offset-background rst:transition-opacity"),F=({isOpen:u,onClose:i,title:m,description:n,size:x,variant:l,status:g,children:f,className:v,onAfterClose:b})=>{const[p,y]=t.useState(!1);t.useLayoutEffect(()=>{y(!0)},[]);const e=u&&p,c=t.useRef(null);return t.useLayoutEffect(()=>{if(e)return j.lockPage(c.current)},[e]),r.jsxs(r.Fragment,{children:[e&&r.jsx("span",{ref:c,hidden:!0}),r.jsxs(a.Dialog,{open:e,as:"div",className:"rst:font-ui rst:relative rst:z-50",onClose:i,children:[r.jsx(d.TransitionChild,{as:t.Fragment,enter:"rst:ease-out rst:duration-300",enterFrom:"rst:opacity-0",enterTo:"rst:opacity-100",leave:"rst:ease-in rst:duration-200",leaveFrom:"rst:opacity-100",leaveTo:"rst:opacity-0",children:r.jsx(a.DialogBackdrop,{className:s.cn("rst:fixed rst:inset-0 rst:transition-opacity",l==="glass"?"rst:bg-[var(--roster-backdrop,color-mix(in_oklab,oklch(20.8%_0.042_265.755)_40%,transparent))] rst:dark:bg-[var(--roster-backdrop,color-mix(in_oklab,var(--roster-black,#1e1c1a)_60%,transparent))]":"rst:bg-[var(--roster-backdrop,color-mix(in_oklab,oklch(20.8%_0.042_265.755)_60%,transparent))] rst:dark:bg-[var(--roster-backdrop,color-mix(in_oklab,var(--roster-black,#1e1c1a)_80%,transparent))] rst:backdrop-blur-backdrop")})}),r.jsx("div",{className:"rst:fixed rst:inset-0 rst:overflow-y-auto",children:r.jsx("div",{className:"rst:flex rst:min-h-full rst:items-center rst:justify-center rst:p-4 rst:text-center",children:r.jsx(d.TransitionChild,{as:t.Fragment,enter:"rst:ease-out rst:duration-300",enterFrom:"rst:opacity-0 rst:scale-95",enterTo:"rst:opacity-100 rst:scale-100",leave:"rst:ease-in rst:duration-200",leaveFrom:"rst:opacity-100 rst:scale-100",leaveTo:"rst:opacity-0 rst:scale-95",afterLeave:b,children:r.jsxs(a.DialogPanel,{className:s.cn(w({size:x,variant:l,status:g}),v),children:[r.jsxs("div",{className:"rst:flex rst:items-start rst:justify-between",children:[r.jsxs("div",{children:[r.jsx(a.DialogTitle,{as:"h2",className:s.cn(N()),children:m}),n&&r.jsx("p",{className:s.cn(_()),children:n})]}),r.jsx("div",{className:"rst:ml-4 rst:flex rst:shrink-0",children:r.jsx("button",{type:"button",onClick:i,className:s.cn(q()),"aria-label":"Close dialog",children:r.jsx(h.FontAwesomeIcon,{icon:k.faXmark,className:"rst:h-5 rst:w-5"})})})]}),r.jsx("div",{className:"rst:mt-6",children:f})]})})})})]})]})};exports.Dialog=F;
@@ -12,6 +12,14 @@ export interface DialogProps extends VariantProps<typeof dialogVariants> {
12
12
  description?: string;
13
13
  children: ReactNode;
14
14
  className?: string;
15
+ /**
16
+ * Called once the dialog has finished closing, after its leave transition.
17
+ * The place to move focus somewhere other than where it was before the
18
+ * dialog opened, for instance when that element no longer exists. Not
19
+ * called for a close cut short by reopening, nor when the dialog unmounts
20
+ * while open.
21
+ */
22
+ onAfterClose?: () => void;
15
23
  }
16
- declare const Dialog: ({ isOpen, onClose, title, description, size, variant, status, children, className, }: DialogProps) => import("react/jsx-runtime").JSX.Element;
24
+ declare const Dialog: ({ isOpen, onClose, title, description, size, variant, status, children, className, onAfterClose, }: DialogProps) => import("react/jsx-runtime").JSX.Element;
17
25
  export { Dialog };
@@ -1,14 +1,14 @@
1
1
  "use client";
2
- import { jsxs as t, Fragment as h, jsx as r } from "react/jsx-runtime";
3
- import { useState as k, useLayoutEffect as c, useRef as w, Fragment as d } from "react";
4
- import { FontAwesomeIcon as N } from "../../../node_modules/@fortawesome/react-fontawesome/dist/index.js";
2
+ import { jsxs as t, Fragment as k, jsx as r } from "react/jsx-runtime";
3
+ import { useState as w, useLayoutEffect as c, useRef as N, Fragment as d } from "react";
4
+ import { FontAwesomeIcon as _ } from "../../../node_modules/@fortawesome/react-fontawesome/dist/index.js";
5
5
  import { faXmark as F } from "../../../node_modules/@fortawesome/free-solid-svg-icons/index.js";
6
6
  import { cva as a } from "../../../node_modules/class-variance-authority/dist/index.js";
7
7
  import { cn as s } from "../../../lib/utils.js";
8
8
  import { lockPage as T } from "../../../internal/page-inert.js";
9
9
  import { Dialog as j, DialogBackdrop as z, DialogPanel as D, DialogTitle as V } from "../../../node_modules/@headlessui/react/dist/components/dialog/dialog.js";
10
10
  import { TransitionChild as m } from "../../../node_modules/@headlessui/react/dist/components/transition/transition.js";
11
- const C = /* @__PURE__ */ a(
11
+ const L = /* @__PURE__ */ a(
12
12
  "rst:relative rst:w-full rst:transform rst:overflow-hidden rst:rounded-2xl rst:p-6 rst:text-left rst:align-middle rst:elevation-overlay rst:transition-all rst:border",
13
13
  {
14
14
  variants: {
@@ -56,9 +56,13 @@ const C = /* @__PURE__ */ a(
56
56
  4.07 / 6.93 for the border.
57
57
 
58
58
  `white` and `glass` are not here on purpose: both follow the page's
59
- scheme, so the page-level tokens are already right for them. */
59
+ scheme, so the page-level tokens are already right for them.
60
+
61
+ `primary`'s text is its fill's ink token, as on every other solid
62
+ fill, so a light primary gets dark text. Dark stays white: that
63
+ fill is primary-950, which has no ink token. */
60
64
  slate: "rst:bg-gray-700 rst:border-gray-600 rst:text-gray-100 rst:dark:bg-gray-900 rst:dark:border-gray-800 rst:[--roster-ring:var(--roster-primary-400,#5ea3de)] rst:[--roster-ring-offset:var(--roster-gray-700,#44403c)] rst:dark:[--roster-ring-offset:var(--roster-gray-900,#1c1917)] rst:[--roster-control-text:var(--roster-gray-100,#f5f5f4)] rst:[--roster-control-border:var(--roster-gray-400,#a8a29e)] rst:[--roster-control-border-focus:var(--roster-primary-400,#5ea3de)]",
61
- primary: "rst:bg-primary-700 rst:border-primary-600 rst:text-white rst:dark:bg-primary-950 rst:dark:border-primary-900 rst:[--roster-ring:var(--roster-primary-400,#5ea3de)] rst:[--roster-ring-offset:var(--roster-primary-700,#084063)] rst:dark:[--roster-ring-offset:var(--roster-primary-950,#021724)] rst:[--roster-control-text:var(--roster-gray-100,#f5f5f4)] rst:[--roster-control-border:var(--roster-gray-400,#a8a29e)] rst:[--roster-control-border-focus:var(--roster-primary-400,#5ea3de)]",
65
+ primary: "rst:bg-primary-700 rst:border-primary-600 rst:text-primary-700-ink rst:dark:text-white rst:dark:bg-primary-950 rst:dark:border-primary-900 rst:[--roster-ring:var(--roster-primary-400,#5ea3de)] rst:[--roster-ring-offset:var(--roster-primary-700,#084063)] rst:dark:[--roster-ring-offset:var(--roster-primary-950,#021724)] rst:[--roster-control-text:var(--roster-gray-100,#f5f5f4)] rst:[--roster-control-border:var(--roster-gray-400,#a8a29e)] rst:[--roster-control-border-focus:var(--roster-primary-400,#5ea3de)]",
62
66
  glass: "rst:bg-white/80 rst:border-white/20 rst:backdrop-blur-xl rst:text-gray-900 rst:dark:bg-slate-900/80 rst:dark:border-slate-700/50 rst:dark:text-white"
63
67
  },
64
68
  status: {
@@ -73,28 +77,29 @@ const C = /* @__PURE__ */ a(
73
77
  status: "default"
74
78
  }
75
79
  }
76
- ), L = /* @__PURE__ */ a("rst:text-xl rst:font-bold rst:leading-6 rst:text-inherit"), P = /* @__PURE__ */ a("rst:mt-1 rst:text-sm rst:text-inherit rst:opacity-75"), R = /* @__PURE__ */ a(
80
+ ), C = /* @__PURE__ */ a("rst:text-xl rst:font-bold rst:leading-6 rst:text-inherit"), P = /* @__PURE__ */ a("rst:mt-1 rst:text-sm rst:text-inherit rst:opacity-75"), R = /* @__PURE__ */ a(
77
81
  "rst:inline-flex rst:size-11 rst:shrink-0 rst:items-center rst:justify-center rst:-m-3 rst:cursor-pointer rst:rounded-md rst:bg-transparent rst:text-inherit rst:opacity-50 rst:hover:opacity-100 rst:focus:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:focus-visible:ring-offset-2 rst:ring-offset-background rst:transition-opacity"
78
82
  ), $ = ({
79
83
  isOpen: f,
80
84
  onClose: o,
81
- title: g,
85
+ title: p,
82
86
  description: i,
83
- size: p,
87
+ size: b,
84
88
  variant: n,
85
- status: u,
89
+ status: g,
86
90
  children: v,
87
- className: b
91
+ className: u,
92
+ onAfterClose: x
88
93
  }) => {
89
- const [x, y] = k(!1);
94
+ const [y, h] = w(!1);
90
95
  c(() => {
91
- y(!0);
96
+ h(!0);
92
97
  }, []);
93
- const e = f && x, l = w(null);
98
+ const e = f && y, l = N(null);
94
99
  return c(() => {
95
100
  if (e)
96
101
  return T(l.current);
97
- }, [e]), /* @__PURE__ */ t(h, { children: [
102
+ }, [e]), /* @__PURE__ */ t(k, { children: [
98
103
  e && /* @__PURE__ */ r("span", { ref: l, hidden: !0 }),
99
104
  /* @__PURE__ */ t(
100
105
  j,
@@ -119,7 +124,7 @@ const C = /* @__PURE__ */ a(
119
124
  {
120
125
  className: s(
121
126
  "rst:fixed rst:inset-0 rst:transition-opacity",
122
- n === "glass" ? "rst:bg-slate-900/40 rst:dark:bg-black/60" : "rst:bg-slate-900/60 rst:dark:bg-black/80 rst:backdrop-blur-sm"
127
+ n === "glass" ? "rst:bg-[var(--roster-backdrop,color-mix(in_oklab,oklch(20.8%_0.042_265.755)_40%,transparent))] rst:dark:bg-[var(--roster-backdrop,color-mix(in_oklab,var(--roster-black,#1e1c1a)_60%,transparent))]" : "rst:bg-[var(--roster-backdrop,color-mix(in_oklab,oklch(20.8%_0.042_265.755)_60%,transparent))] rst:dark:bg-[var(--roster-backdrop,color-mix(in_oklab,var(--roster-black,#1e1c1a)_80%,transparent))] rst:backdrop-blur-backdrop"
123
128
  )
124
129
  }
125
130
  )
@@ -135,17 +140,18 @@ const C = /* @__PURE__ */ a(
135
140
  leave: "rst:ease-in rst:duration-200",
136
141
  leaveFrom: "rst:opacity-100 rst:scale-100",
137
142
  leaveTo: "rst:opacity-0 rst:scale-95",
143
+ afterLeave: x,
138
144
  children: /* @__PURE__ */ t(
139
145
  D,
140
146
  {
141
147
  className: s(
142
- C({ size: p, variant: n, status: u }),
143
- b
148
+ L({ size: b, variant: n, status: g }),
149
+ u
144
150
  ),
145
151
  children: [
146
152
  /* @__PURE__ */ t("div", { className: "rst:flex rst:items-start rst:justify-between", children: [
147
153
  /* @__PURE__ */ t("div", { children: [
148
- /* @__PURE__ */ r(V, { as: "h2", className: s(L()), children: g }),
154
+ /* @__PURE__ */ r(V, { as: "h2", className: s(C()), children: p }),
149
155
  i && /* @__PURE__ */ r("p", { className: s(P()), children: i })
150
156
  ] }),
151
157
  /* @__PURE__ */ r("div", { className: "rst:ml-4 rst:flex rst:shrink-0", children: /* @__PURE__ */ r(
@@ -155,7 +161,7 @@ const C = /* @__PURE__ */ a(
155
161
  onClick: o,
156
162
  className: s(R()),
157
163
  "aria-label": "Close dialog",
158
- children: /* @__PURE__ */ r(N, { icon: F, className: "rst:h-5 rst:w-5" })
164
+ children: /* @__PURE__ */ r(_, { icon: F, className: "rst:h-5 rst:w-5" })
159
165
  }
160
166
  ) })
161
167
  ] }),
@@ -0,0 +1 @@
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),a=require("react"),z=require("../../../lib/utils.cjs"),xe=require("../../atoms/Button/Button.cjs"),Oe=require("../../atoms/Card/Card.cjs"),he=require("../../atoms/Spinner/Spinner.cjs"),Pe=require("../../atoms/Textarea/Textarea.cjs"),Z=require("../../molecules/Alert/Alert.cjs"),ze=require("../../molecules/EmptyState/EmptyState.cjs"),De=require("../../molecules/RadioGroup/RadioGroup.cjs"),He=require("./queue-actions.cjs"),pe={primary:{colorScheme:"primary",variant:"solid"},success:{colorScheme:"success",variant:"solid"},danger:{colorScheme:"error",variant:"soft"},neutral:{colorScheme:"neutral",variant:"outline"}},Ke={edit:He.editAction},R=o=>o.edit?o:null,Qe=o=>o===0?"None left.":`${o} left.`,Ge=o=>Math.min(6,Math.max(1,o)),We=o=>o instanceof Error&&o.message?o.message:"Something went wrong.";function B(o,f){const p={...o};return delete p[f],p}function _({busy:o=!1,blocked:f=!1,onClick:p,children:j,className:v,...y}){const g=o||f;return n.jsx(xe.Button,{size:"lg",...y,"aria-disabled":g||void 0,"aria-busy":o||void 0,startIcon:o?n.jsx(he.Spinner,{size:"sm",variant:"current"}):void 0,className:z.cn(f&&!o&&"rst:cursor-not-allowed rst:opacity-50",v),onClick:T=>{if(g){T.preventDefault();return}p?.(T)},children:j})}function Je({label:o,hideLabel:f=!1,headingLevel:p=2,itemHeadingLevel:j,items:v,getKey:y,itemLabel:g,renderMeta:T,renderContent:ve,actions:D,status:ee="ready",error:be,onRetry:te,empty:re={title:"Nothing waiting"},density:ne="comfortable",footer:ye,className:Se}){const je=typeof D=="function"?D(Ke):D,N=a.useId(),q=a.useRef(null),k=v.map(y),E=a.useRef(new Map);E.current=new Map(v.map((e,t)=>[k[t],e]));const[H,qe]=a.useState({}),$=a.useRef({}),se=e=>{$.current=e($.current),qe($.current)},[oe,F]=a.useState({}),[ce,ke]=a.useState({}),x=a.useRef({}),h=(e,t)=>{x.current=t?{...x.current,[e]:t}:B(x.current,e),ke(x.current)},[K,$e]=a.useState({text:"",n:0}),Q=a.useRef([]),w=a.useRef(null),ie=a.useCallback(e=>{Q.current.push(e),!w.current&&(w.current=setTimeout(()=>{w.current=null;const t=Q.current.join(" ");Q.current=[],$e(r=>({text:t,n:r.n+1}))},0))},[]);a.useLayoutEffect(()=>()=>{w.current&&clearTimeout(w.current)},[]);const[Re,Ne]=a.useState(0),G=a.useRef(null),S=a.useCallback(e=>{G.current=e,Ne(t=>t+1)},[]),ae=a.useCallback(e=>{const t=q.current;if(!t)return null;const r="key"in e?CSS.escape(e.key):"";switch(e.kind){case"item":return t.querySelector(`[data-queue-item="${r}"]`);case"empty":return t.querySelector("[data-queue-empty]");case"trigger":return t.querySelector(`[data-queue-item="${r}"] [data-queue-action="${CSS.escape(e.actionId)}"]`);case"step":return t.querySelector(`[data-queue-item="${r}"] [data-queue-step]`)}},[]);a.useLayoutEffect(()=>{const e=G.current;if(!e)return;G.current=null,(ae(e)??q.current?.querySelector("[data-queue-item]")??q.current?.querySelector("[data-queue-empty]"))?.focus()},[Re,ae]);const W=a.useRef(null),we=e=>()=>{W.current=e},Ce=e=>{e.relatedTarget&&!q.current?.contains(e.relatedTarget)&&(W.current=null)},A=e=>{if(W.current!==e)return!1;const t=document.activeElement;return!t||t===document.body?!0:q.current?.contains(t)?!!t.closest(`[data-queue-item="${CSS.escape(e)}"]`):!1},C=a.useRef(null),M=(e,t)=>{C.current=t,h(e.key,{...e,open:!1})},le=a.useRef(k),J=a.useRef(new Map),[,Ie]=a.useState(0),U=a.useRef(new Set),ue=(e,t,r)=>{const c=t.indexOf(e),d=t.slice(c+1).find(i=>r.has(i));if(d)return{kind:"item",key:d};const s=t.slice(0,c).reverse().find(i=>r.has(i));return s?{kind:"item",key:s}:{kind:"empty"}};a.useLayoutEffect(()=>{const e=le.current;le.current=k;const t=new Set(k),r=J.current;J.current=new Map;const c=[];let d=!1;for(const[s,i]of r){const l=t.has(s);c.push(i.announce??i.sentence),l||(d=!0),U.current.delete(s);const u=l?{kind:"trigger",key:s,actionId:i.actionId}:e.includes(s)?ue(s,e,t):null,m=x.current[s];if(m?.surface)M(m,u??{kind:"empty"});else{const I=A(s);m&&h(s,null),u&&I&&S(u)}}for(const s of e.filter(i=>!t.has(i))){if(r.has(s))continue;F(m=>s in m?B(m,s):m);const i=ue(s,e,t),l=C.current;if(l&&"key"in l&&l.key===s&&(C.current=i),$.current[s]){U.current.add(s),A(s)&&S(i);continue}const u=x.current[s];if(u&&!(u.surface&&!u.open))if(c.push(`${u.label} was decided elsewhere.`),d=!0,u.surface)M(u,i);else{const m=A(s);h(s,null),m&&S(i)}else!u&&A(s)&&S(i)}c.length&&ie(`${c.join(" ")}${d?` ${Qe(k.length)}`:""}`)});const L=async(e,t,r,c)=>{const d=E.current.get(e)??t,s=g(d),i=r.edit?R(r).run:r.run;se(l=>({...l,[e]:r.id})),F(l=>B(l,e));try{const l=await i(d,c);J.current.set(e,{actionId:r.id,sentence:`${r.done??r.label}: ${s}.`,announce:l?l.announce:void 0}),Ie(u=>u+1)}catch(l){const u=We(l);ie(`${r.label} didn't go through for ${s}. ${u}`);const m=x.current[e];U.current.delete(e)?m?.surface?M(m,{kind:"empty"}):m&&h(e,null):m?h(e,{...m,error:u}):F(I=>({...I,[e]:u}))}finally{se(l=>B(l,e))}},Be=(e,t)=>{const r=y(e),c=R(t);if(!t.confirm&&!t.reason&&!c){L(r,e,t,{});return}F(d=>B(d,r)),h(r,{key:r,label:g(e),item:e,action:t,draft:c?c.edit.initial(e):void 0,reason:{},surface:!!c?.edit.surface,open:!0}),c?.edit.surface||S({kind:"step",key:r})},V=e=>{const t=x.current[e];if(!t||$.current[e])return;const r={kind:"trigger",key:e,actionId:t.action.id};t.surface?M(t,r):(h(e,null),S(r))},Te=e=>{const t=x.current[e];!t||$.current[e]||ge(t,E.current.get(e)??t.item)||(t.action.edit?L(e,t.item,t.action,{draft:t.draft}):t.action.reason?L(e,t.item,t.action,{reason:Ue(t.reason)}):L(e,t.item,t.action,{}))},Ee=e=>{const t=C.current;C.current=null,h(e,null),t&&S(t)},Fe=`h${p}`,de=j??Ge(p+1),Ae=`h${de}`,X=`${N}-label`,fe=(e,t)=>{const{action:r}=e,c=R(r),d=E.current.get(e.key)??e.item,s=!!H[e.key],i=ge(e,d),l=`${N}-step-${t}-message`,u=n.jsx(_,{...pe[r.tone??"neutral"],busy:s,blocked:!!i,"aria-describedby":i?l:void 0,onClick:()=>Te(e.key),"data-queue-submit":"",children:c?c.edit.submitLabel:r.label}),m=n.jsx(_,{variant:"ghost",colorScheme:"neutral",blocked:s,onClick:()=>V(e.key),children:"Cancel"}),I=n.jsxs(n.Fragment,{children:[r.reason&&n.jsx(Ve,{id:`${N}-step-${t}`,step:r.reason,value:e.reason,disabled:s,onChange:Y=>h(e.key,{...x.current[e.key],reason:Y})}),c&&n.jsx(c.edit.Form,{item:d,value:e.draft,onChange:Y=>h(e.key,{...x.current[e.key],draft:Y})}),i&&n.jsx("p",{id:l,className:"rst:text-sm rst:text-error-600 rst:dark:text-error-400","data-queue-validation":"",children:i}),e.error&&n.jsx(Z.Alert,{colorScheme:"error",role:"group","aria-live":"off",children:e.error})]});return{submitButton:u,cancelButton:m,fields:I}},Me=(e,t)=>{const{submitButton:r,cancelButton:c,fields:d}=fe(e,t),s=`${N}-step-${t}-prompt`,i=R(e.action),l=e.action.confirm?.prompt??e.action.reason?.prompt??i?.edit.title;return n.jsxs("div",{role:"group","aria-labelledby":s,tabIndex:-1,"data-queue-step":"",onKeyDown:u=>{u.key==="Escape"&&(u.stopPropagation(),V(e.key))},className:"rst:flex rst:flex-col rst:gap-3 rst:rounded-lg rst:border rst:border-[var(--roster-card-border)] rst:p-4 rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring",children:[n.jsx("p",{id:s,className:"rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)]",children:l}),i?.edit.description&&n.jsx("p",{className:"rst:text-sm rst:text-gray-600 rst:dark:text-gray-300",children:i.edit.description}),d,n.jsxs("div",{className:"rst:flex rst:flex-wrap rst:gap-2",children:[r,c]})]})},Le=(e,t)=>{const r=H[t];return n.jsx("div",{role:"group","aria-label":`Decide: ${g(e)}`,className:"rst:flex rst:flex-wrap rst:gap-2",children:je.filter(c=>!c.hidden?.(e)).map(c=>n.jsx(_,{...pe[c.tone??"neutral"],"data-queue-action":c.id,busy:r===c.id,blocked:!!r&&r!==c.id,onClick:()=>Be(e,c),children:c.label},c.id))})},b=Object.values(ce).find(e=>e.surface)??null,O=b?R(b.action):null,me=O?.edit.surface,P=b?fe(b,-1):null;return n.jsxs("section",{ref:q,"aria-labelledby":X,onBlur:Ce,className:z.cn("rst:font-ui rst:flex rst:flex-col rst:gap-4",Se),children:[n.jsx(Fe,{id:X,className:z.cn("rst:text-lg rst:font-semibold rst:text-[var(--roster-control-text)]",f&&"rst:sr-only"),children:o}),n.jsxs("div",{role:"status","aria-live":"polite","aria-atomic":"true",className:"rst:sr-only","data-queue-live":"","data-queue-live-n":K.n,children:[K.text,K.n%2?" ":""]}),ee==="loading"?n.jsx("div",{className:"rst:flex rst:justify-center rst:py-12","aria-busy":"true",children:n.jsx(he.Spinner,{size:"lg",label:`Loading ${o}`})}):ee==="error"?n.jsx(Z.Alert,{colorScheme:"error",children:n.jsxs("div",{className:"rst:flex rst:flex-col rst:items-start rst:gap-3",children:[n.jsx("div",{children:be??"The queue couldn't load."}),te&&n.jsx(xe.Button,{size:"lg",variant:"outline",colorScheme:"neutral",onClick:te,children:"Retry"})]})}):v.length===0?n.jsx(ze.EmptyState,{title:re.title,description:re.description,headingLevel:de,tabIndex:-1,"data-queue-empty":"",className:"rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring"}):n.jsx("ul",{role:"list","aria-labelledby":X,className:"rst:m-0 rst:flex rst:list-none rst:flex-col rst:gap-3 rst:p-0",children:v.map((e,t)=>{const r=k[t],c=`${N}-item-${t}`,d=T?.(e),s=ce[r];return n.jsx("li",{children:n.jsx("article",{"data-queue-item":r,tabIndex:-1,"aria-labelledby":c,onFocus:we(r),className:"rst:rounded-xl rst:focus-visible:outline-hidden rst:focus-visible:ring-2 rst:focus-visible:ring-ring rst:focus-visible:ring-offset-2 rst:ring-offset-background",children:n.jsx(Oe.Card,{padding:ne==="compact"?"sm":"md",children:n.jsxs("div",{className:z.cn("rst:flex rst:flex-col",ne==="compact"?"rst:gap-3":"rst:gap-4"),children:[n.jsxs("div",{className:"rst:flex rst:flex-wrap rst:items-baseline rst:gap-x-3 rst:gap-y-1",children:[n.jsx(Ae,{id:c,className:"rst:text-base rst:font-semibold",children:g(e)}),d&&n.jsx("div",{className:"rst:flex rst:flex-wrap rst:items-center rst:gap-2 rst:text-sm rst:text-gray-600 rst:dark:text-gray-300",children:d})]}),n.jsx("div",{className:"rst:min-w-0",children:ve(e)}),oe[r]&&n.jsx(Z.Alert,{colorScheme:"error",role:"group","aria-live":"off",children:oe[r]}),s&&!s.surface?Me(s,t):Le(e,r)]})})})},r)})}),ye,me&&b&&O&&P&&n.jsx(me,{open:b.open,title:O.edit.title,description:O.edit.description,busy:!!H[b.key],onCancel:()=>V(b.key),onAfterClose:()=>Ee(b.key),submitButton:P.submitButton,cancelButton:P.cancelButton,children:n.jsx("div",{className:"rst:flex rst:flex-col rst:gap-4",children:P.fields})})]})}function ge(o,f){const p=R(o.action);if(p)return p.edit.validate?.(o.draft,f);if(o.action.reason){if(o.action.reason.required&&!o.reason.value)return"Pick a reason.";if(o.action.reason.note==="required"&&!o.reason.note?.trim())return"Add a note."}}function Ue(o){const f=o.note?.trim();return{...o.value?{value:o.value}:{},...f?{note:f}:{}}}function Ve({id:o,step:f,value:p,disabled:j,onChange:v}){const y=f.note??"optional";return n.jsxs(n.Fragment,{children:[f.options&&f.options.length>0&&n.jsx(De.RadioGroup,{label:f.required?"Reason":"Reason (optional)",options:f.options,value:p.value??"",onChange:g=>v({...p,value:g}),disabled:j}),y!=="none"&&n.jsx(Pe.Textarea,{id:`${o}-note`,label:f.noteLabel??(y==="required"?"Note":"Note (optional)"),rows:3,value:p.note??"",onChange:g=>v({...p,note:g.target.value}),disabled:j})]})}exports.ModerationQueue=Je;
@@ -0,0 +1,73 @@
1
+ import { ReactNode } from 'react';
2
+ import { QueueAction, QueueActionKit, QueueCheckedEditAction, QueueHeadingLevel } from './queue-actions';
3
+ export interface ModerationQueueProps<T> {
4
+ /** The queue's heading, and the list's accessible name. */
5
+ label: string;
6
+ /** Keep the heading for assistive technology only, when the page already titles the queue. */
7
+ hideLabel?: boolean;
8
+ /** The queue heading's level. `2` by default. */
9
+ headingLevel?: QueueHeadingLevel;
10
+ /** Each item's heading level. One below `headingLevel` by default. */
11
+ itemHeadingLevel?: QueueHeadingLevel;
12
+ /** What's waiting. Remove an item once its decision lands; the queue notices. */
13
+ items: readonly T[];
14
+ getKey: (item: T) => string;
15
+ /** The item's heading, and what announcements call it: "Recipe from Dana". */
16
+ itemLabel: (item: T) => string;
17
+ /** Beside the heading: badges, a time, who sent it. */
18
+ renderMeta?: (item: T) => ReactNode;
19
+ /** The item's body: its text, its previews, links out. */
20
+ renderContent: (item: T) => ReactNode;
21
+ /**
22
+ * What a reviewer can decide. A list, or a function returning one: the
23
+ * function form is handed `edit`, which types an edit action's draft, and
24
+ * is the one to use inline in JSX.
25
+ *
26
+ * actions={(a) => [
27
+ * { id: "approve", label: "Approve", run: (r) => approve(r.id) },
28
+ * a.edit({ id: "edit", label: "Edit", edit: { initial: (r) => ({ … }), … },
29
+ * run: (r, { draft }) => save(r.id, draft) }),
30
+ * ]}
31
+ */
32
+ actions: readonly QueueAction<T>[] | ((kit: QueueActionKit<T>) => readonly QueueAction<T>[]);
33
+ /** `"loading"` before the first answer, `"error"` when the queue itself can't load. */
34
+ status?: "ready" | "loading" | "error";
35
+ /** The whole-queue error, shown with a Retry when `onRetry` is passed. */
36
+ error?: ReactNode;
37
+ onRetry?: () => void;
38
+ empty?: {
39
+ title: string;
40
+ description?: string;
41
+ };
42
+ density?: "comfortable" | "compact";
43
+ /** After the list: "Load more", if the app pages. */
44
+ footer?: ReactNode;
45
+ className?: string;
46
+ }
47
+ /**
48
+ * A queue of things waiting for a decision: submissions to approve, reports to
49
+ * resolve, claims to check before they publish.
50
+ *
51
+ * The app owns the data and every request; this owns the layout, the states,
52
+ * the steps and the keyboard. It never fetches. An action's `run` is the only
53
+ * path from a decision to the network, and the app says whether the item has
54
+ * left by removing it from `items`.
55
+ *
56
+ * What it promises, each pinned in ModerationQueue.checks.stories.tsx:
57
+ * - Only the clicked action is busy, and it keeps focus while it is. That
58
+ * item's other actions wait; every other item stays live.
59
+ * - A decision that lands and removes the item is announced with how many
60
+ * are left, and focus moves to the next item, the previous one, or the
61
+ * empty state. Never to the page.
62
+ * - A decision that fails leaves the item where it was, says why, and leaves
63
+ * focus on the button that tried. A step stays open with its draft.
64
+ * - Confirm, reason and edit steps open in place (an edit may open in a
65
+ * Dialog or Sheet instead), take focus, and give it back on Escape.
66
+ * - An item that disappears for any other reason, with its step open,
67
+ * closes the step without deciding and is announced once as decided
68
+ * elsewhere. Focus moves only if it was inside the item.
69
+ * - Several outcomes in one render are said in one sentence.
70
+ */
71
+ declare function ModerationQueue<T>({ label, hideLabel, headingLevel, itemHeadingLevel, items, getKey, itemLabel, renderMeta, renderContent, actions: actionsProp, status, error, onRetry, empty, density, footer, className, }: ModerationQueueProps<T>): import("react/jsx-runtime").JSX.Element;
72
+ export type { QueueCheckedEditAction };
73
+ export { ModerationQueue };