@blakesteve/roster 5.7.0 → 5.9.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 (106) hide show
  1. package/README.md +169 -5
  2. package/dist/components/atoms/Avatar/Avatar.cjs +1 -1
  3. package/dist/components/atoms/Avatar/Avatar.d.ts +4 -0
  4. package/dist/components/atoms/Avatar/Avatar.js +1 -1
  5. package/dist/components/atoms/AvatarStrip/AvatarStrip.cjs +1 -1
  6. package/dist/components/atoms/AvatarStrip/AvatarStrip.d.ts +10 -1
  7. package/dist/components/atoms/AvatarStrip/AvatarStrip.js +34 -30
  8. package/dist/components/atoms/Button/button-variants.cjs +1 -1
  9. package/dist/components/atoms/Button/button-variants.js +5 -3
  10. package/dist/components/atoms/Eyebrow/eyebrow-variants.cjs +1 -1
  11. package/dist/components/atoms/Eyebrow/eyebrow-variants.js +8 -4
  12. package/dist/components/atoms/MultiSelect/MultiSelect.cjs +1 -1
  13. package/dist/components/atoms/MultiSelect/MultiSelect.d.ts +3 -1
  14. package/dist/components/atoms/MultiSelect/MultiSelect.js +87 -89
  15. package/dist/components/atoms/Progress/Progress.cjs +1 -1
  16. package/dist/components/atoms/Progress/Progress.d.ts +1 -0
  17. package/dist/components/atoms/Progress/Progress.js +28 -27
  18. package/dist/components/atoms/Stat/Stat.cjs +1 -1
  19. package/dist/components/atoms/Stat/Stat.js +5 -5
  20. package/dist/components/atoms/Stat/stat-variants.cjs +1 -1
  21. package/dist/components/atoms/Stat/stat-variants.js +10 -8
  22. package/dist/components/molecules/Breadcrumbs/Breadcrumbs.cjs +1 -1
  23. package/dist/components/molecules/Breadcrumbs/Breadcrumbs.d.ts +10 -1
  24. package/dist/components/molecules/Breadcrumbs/Breadcrumbs.js +31 -29
  25. package/dist/components/molecules/CallToAction/CallToAction.cjs +1 -1
  26. package/dist/components/molecules/CallToAction/CallToAction.d.ts +8 -1
  27. package/dist/components/molecules/CallToAction/CallToAction.js +34 -29
  28. package/dist/components/molecules/Carousel/Carousel.cjs +1 -1
  29. package/dist/components/molecules/Carousel/Carousel.d.ts +7 -0
  30. package/dist/components/molecules/Carousel/Carousel.js +155 -155
  31. package/dist/components/molecules/ErrorState/ErrorState.cjs +1 -1
  32. package/dist/components/molecules/ErrorState/ErrorState.d.ts +8 -1
  33. package/dist/components/molecules/ErrorState/ErrorState.js +44 -39
  34. package/dist/components/molecules/FileUpload/FileUpload.cjs +1 -1
  35. package/dist/components/molecules/FileUpload/FileUpload.js +23 -22
  36. package/dist/components/molecules/MediaPreview/MediaPreview.cjs +1 -1
  37. package/dist/components/molecules/MediaPreview/MediaPreview.d.ts +3 -1
  38. package/dist/components/molecules/MediaPreview/MediaPreview.js +13 -12
  39. package/dist/components/molecules/Menu/Menu.cjs +1 -0
  40. package/dist/components/molecules/Menu/Menu.d.ts +169 -0
  41. package/dist/components/molecules/Menu/Menu.js +577 -0
  42. package/dist/components/molecules/Menu/menu-typeahead.cjs +1 -0
  43. package/dist/components/molecules/Menu/menu-typeahead.d.ts +7 -0
  44. package/dist/components/molecules/Menu/menu-typeahead.js +13 -0
  45. package/dist/components/molecules/Pagination/Pagination.cjs +1 -1
  46. package/dist/components/molecules/Pagination/Pagination.d.ts +1 -0
  47. package/dist/components/molecules/Pagination/Pagination.js +47 -46
  48. package/dist/components/molecules/ProgressField/ProgressField.d.ts +1 -0
  49. package/dist/components/molecules/SkeletonPresets/SkeletonPresets.cjs +1 -1
  50. package/dist/components/molecules/SkeletonPresets/SkeletonPresets.d.ts +2 -2
  51. package/dist/components/molecules/SkeletonPresets/SkeletonPresets.js +17 -17
  52. package/dist/components/molecules/StepProgress/StepProgress.cjs +1 -1
  53. package/dist/components/molecules/StepProgress/StepProgress.d.ts +1 -0
  54. package/dist/components/molecules/StepProgress/StepProgress.js +9 -8
  55. package/dist/components/organisms/Countdown/Countdown.cjs +1 -1
  56. package/dist/components/organisms/Countdown/Countdown.d.ts +13 -0
  57. package/dist/components/organisms/Countdown/Countdown.js +54 -47
  58. package/dist/components/organisms/DataTable/DataTable.cjs +1 -1
  59. package/dist/components/organisms/DataTable/DataTable.d.ts +5 -3
  60. package/dist/components/organisms/DataTable/DataTable.js +27 -26
  61. package/dist/components/organisms/Dialog/Dialog.cjs +1 -1
  62. package/dist/components/organisms/Dialog/Dialog.d.ts +8 -1
  63. package/dist/components/organisms/Dialog/Dialog.js +25 -23
  64. package/dist/components/organisms/Footer/Footer.cjs +1 -1
  65. package/dist/components/organisms/Footer/Footer.d.ts +9 -0
  66. package/dist/components/organisms/Footer/Footer.js +21 -23
  67. package/dist/components/organisms/ModerationQueue/ModerationQueue.cjs +1 -1
  68. package/dist/components/organisms/ModerationQueue/ModerationQueue.d.ts +40 -1
  69. package/dist/components/organisms/ModerationQueue/ModerationQueue.js +262 -237
  70. package/dist/components/organisms/ModerationQueue/QueueEditDialog.cjs +1 -1
  71. package/dist/components/organisms/ModerationQueue/QueueEditDialog.d.ts +1 -1
  72. package/dist/components/organisms/ModerationQueue/QueueEditDialog.js +23 -21
  73. package/dist/components/organisms/ModerationQueue/QueueEditSheet.cjs +1 -1
  74. package/dist/components/organisms/ModerationQueue/QueueEditSheet.d.ts +1 -1
  75. package/dist/components/organisms/ModerationQueue/QueueEditSheet.js +22 -20
  76. package/dist/components/organisms/ModerationQueue/queue-actions.d.ts +29 -10
  77. package/dist/components/organisms/Navbar/Navbar.cjs +1 -1
  78. package/dist/components/organisms/Navbar/Navbar.d.ts +39 -4
  79. package/dist/components/organisms/Navbar/Navbar.js +297 -301
  80. package/dist/components/organisms/Navbar/navbar-variants.cjs +1 -1
  81. package/dist/components/organisms/Navbar/navbar-variants.js +4 -2
  82. package/dist/components/organisms/Sheet/Sheet.cjs +1 -1
  83. package/dist/components/organisms/Sheet/Sheet.d.ts +8 -1
  84. package/dist/components/organisms/Sheet/Sheet.js +65 -63
  85. package/dist/index.d.ts +1 -0
  86. package/dist/lib/labels.cjs +1 -0
  87. package/dist/lib/labels.d.ts +7 -0
  88. package/dist/lib/labels.js +12 -0
  89. package/dist/meta.json +3 -3
  90. package/dist/node_modules/@floating-ui/core/dist/floating-ui.core.js +7 -7
  91. package/dist/node_modules/@floating-ui/dom/dist/floating-ui.dom.js +2 -2
  92. package/dist/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.js +5 -5
  93. package/dist/node_modules/@headlessui/react/dist/components/portal/portal.js +6 -6
  94. package/dist/node_modules/@headlessui/react/dist/utils/focus-management.cjs +1 -1
  95. package/dist/node_modules/@headlessui/react/dist/utils/focus-management.js +52 -61
  96. package/dist/node_modules/@radix-ui/react-popper/dist/index.js +6 -6
  97. package/dist/roster.cjs +1 -1
  98. package/dist/roster.css +1 -1
  99. package/dist/roster.js +127 -116
  100. package/package.json +2 -1
  101. package/dist/node_modules/@headlessui/react/dist/components/menu/menu-machine-glue.cjs +0 -1
  102. package/dist/node_modules/@headlessui/react/dist/components/menu/menu-machine-glue.js +0 -21
  103. package/dist/node_modules/@headlessui/react/dist/components/menu/menu-machine.cjs +0 -1
  104. package/dist/node_modules/@headlessui/react/dist/components/menu/menu-machine.js +0 -120
  105. package/dist/node_modules/@headlessui/react/dist/components/menu/menu.cjs +0 -1
  106. package/dist/node_modules/@headlessui/react/dist/components/menu/menu.js +0 -197
@@ -1 +1 @@
1
- "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),o=require("react"),p=require("../../../lib/utils.cjs"),H=require("../../atoms/Button/Button.cjs"),pt=require("../../atoms/Progress/Progress.cjs"),R=require("./file-rules.cjs"),gt={choose:"Choose photos",dropHint:"or drag them here",dropHere:"Drop to add them",queued:"Waiting",uploading:n=>n===null?"Uploading":`Uploading, ${n}%`,processing:"Finishing up",done:"Uploaded",failed:"Didn't upload.",rejected:"Not added.",remove:n=>`Remove ${n}`,retry:n=>`Try ${n} again`,wrongType:()=>"That type of file isn't accepted.",tooLarge:(n,d)=>`It's over ${R.formatBytes(d)}.`,tooMany:n=>`Only ${n} can be added.`,duplicate:()=>"It's already added.",uploadError:n=>n instanceof Error&&n.message?n.message:"Something went wrong.",size:R.formatBytes,added:n=>`${n} ${n===1?"photo":"photos"} added.`,progress:(n,d)=>`${n} of ${d} uploaded.`,failedNotice:(n,d)=>`${n} didn't upload. ${d}`,rejectedNotice:(n,d)=>`${n} wasn't added. ${d}`,removed:n=>`${n} removed.`};function ht({file:n,status:d}){const[q,M]=o.useState(!1),B=!q&&(n.type.startsWith("image/")||/\.(jpe?g|png|gif|webp|avif|heic|heif)$/i.test(n.name)),N=o.useCallback(L=>{if(!L)return;const w=URL.createObjectURL(n);return L.src=w,()=>URL.revokeObjectURL(w)},[n]),x="rst:h-14 rst:w-14 rst:shrink-0 rst:rounded-md rst:border rst:border-[var(--roster-card-border)]";return B?r.jsx("img",{ref:N,alt:"",onError:()=>M(!0),className:p.cn(x,"rst:object-cover",d==="rejected"&&"rst:opacity-50"),"data-file-thumb":"image"}):r.jsx("span",{"aria-hidden":"true",className:p.cn(x,"rst:flex rst:items-center rst:justify-center rst:text-gray-500 rst:dark:text-gray-400"),"data-file-thumb":"placeholder",children:r.jsxs("svg",{viewBox:"0 0 24 24",width:"24",height:"24",fill:"none",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round",strokeLinejoin:"round",children:[r.jsx("rect",{x:"3",y:"5",width:"18",height:"14",rx:"2"}),r.jsx("circle",{cx:"9",cy:"10",r:"1.6"}),r.jsx("path",{d:"m21 15-4.2-4.2a1.6 1.6 0 0 0-2.3 0L7 18"})]})})}const W="rst:cursor-not-allowed rst:opacity-50",S={width:20,height:20,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};function xt({label:n,upload:d,onChange:q,accept:M="image/*",types:B,maxSize:N,maxFiles:x,validate:L,concurrency:w=3,helperText:E,errorMessage:T,disabled:i=!1,strings:Q,className:X}){const c={...gt,...Q},D=o.useId(),I=`${D}-label`,G=`${D}-help`,V=`${D}-error`,[U,Y]=o.useState([]),l=o.useRef(U),Z=o.useRef(0),m=o.useRef(new Map),F=o.useRef(null),_=o.useRef(null),g=o.useRef({upload:d,onChange:q,concurrency:w,t:c,pump:()=>{}}),[z,tt]=o.useState({text:"",n:0}),j=o.useRef([]),v=o.useRef(null),$=o.useCallback((t,s=!1)=>{s&&(j.current=j.current.filter(e=>!e.count)),j.current.push({text:t,count:s}),!v.current&&(v.current=setTimeout(()=>{v.current=null;const e=j.current.map(u=>u.text).join(" ");j.current=[],tt(u=>({text:e,n:u.n+1}))},0))},[]),O=o.useRef(null),[et,rt]=o.useState(0),J=t=>{O.current=t,rt(s=>s+1)};o.useLayoutEffect(()=>{const t=O.current;if(!t)return;O.current=null,(F.current?.querySelector(t)??F.current?.querySelector("[data-file-choose]"))?.focus()},[et]);const y=o.useCallback(t=>{l.current=t,Y(t),g.current.onChange?.(t)},[]),b=o.useCallback((t,s)=>{l.current.some(e=>e.id===t)&&y(l.current.map(e=>e.id===t?{...e,...s}:e))},[y]);function k(){const{concurrency:t}=g.current,s=l.current.filter(u=>u.status==="uploading"||u.status==="processing").length,e=l.current.filter(u=>u.status==="queued").slice(0,Math.max(0,Math.max(1,t)-s));for(const u of e)st(u)}function st(t){const s=new AbortController;m.current.set(t.id,s),b(t.id,{status:"uploading",progress:null,reason:void 0});const e=()=>!s.signal.aborted&&m.current.get(t.id)===s,u={onProgress:a=>{if(!e())return;const f=Math.round(Math.min(1,Math.max(0,Number.isFinite(a)?a:0))*100)/100,h=l.current.find(ft=>ft.id===t.id);h?.status==="uploading"&&h.progress!==f&&b(t.id,{progress:f})},onProcessing:()=>{e()&&b(t.id,{status:"processing"})},signal:s.signal};new Promise(a=>a(g.current.upload(t.file,u))).then(a=>{if(!e())return;m.current.delete(t.id),b(t.id,{status:"done",progress:1,result:a});const f=l.current.filter(h=>h.status!=="rejected");$(g.current.t.progress(f.filter(h=>h.status==="done").length,f.length),!0),k()},a=>{if(!e())return;m.current.delete(t.id);const f=g.current.t.uploadError(a);b(t.id,{status:"failed",reason:f}),$(g.current.t.failedNotice(t.file.name,f)),k()})}o.useLayoutEffect(()=>{g.current={upload:d,onChange:q,concurrency:w,t:c,pump:k}}),o.useEffect(()=>{const t=m.current;return l.current.some(e=>(e.status==="uploading"||e.status==="processing")&&!t.has(e.id))&&(y(l.current.map(e=>(e.status==="uploading"||e.status==="processing")&&!t.has(e.id)?{...e,status:"queued",progress:null}:e)),g.current.pump()),()=>{for(const e of t.values())e.abort();t.clear(),v.current&&clearTimeout(v.current),v.current=null,j.current=[]}},[y]);const nt=B??R.acceptList(M),at=(t,s)=>{if(s.some(u=>R.sameFile(u.file,t)))return c.duplicate(t);const e=L?.(t);if(e)return e;if(!R.matchesType(t,nt))return c.wrongType(t);if(N!==void 0&&t.size>N)return c.tooLarge(t,N);if(x!==void 0&&s.length>=x)return c.tooMany(x)},K=t=>{if(i||t.length===0)return;const s=l.current.filter(a=>a.status!=="rejected"),e=[];for(const a of t){const f=at(a,[...s,...e.filter(h=>h.status!=="rejected")]);e.push({id:`${D}-file-${Z.current++}`,file:a,status:f?"rejected":"queued",progress:null,reason:f})}y([...l.current,...e]);const u=e.filter(a=>a.status==="queued").length;u&&$(c.added(u));for(const a of e)a.reason&&$(c.rejectedNotice(a.file.name,a.reason));k()},ot=t=>{if(i)return;const s=l.current,e=s.findIndex(a=>a.id===t);if(e<0)return;m.current.get(t)?.abort(),m.current.delete(t);const u=s[e+1]??s[e-1];y(s.filter(a=>a.id!==t)),$(c.removed(s[e].file.name)),J(u?`[data-file-remove="${u.id}"]`:"[data-file-choose]"),k()},ct=t=>{i||(b(t,{status:"queued",progress:null,reason:void 0}),J(`[data-file-remove="${t}"]`),k())},[ut,P]=o.useState(0),C=t=>Array.from(t.dataTransfer?.types??[]).includes("Files"),it={onDragEnter:t=>{C(t)&&(t.preventDefault(),P(s=>s+1))},onDragOver:t=>{C(t)&&(t.preventDefault(),t.dataTransfer.dropEffect=i?"none":"copy")},onDragLeave:t=>{C(t)&&P(s=>Math.max(0,s-1))},onDrop:t=>{C(t)&&(t.preventDefault(),P(0),K(Array.from(t.dataTransfer.files)))}},A=ut>0&&!i,dt=t=>{switch(t.status){case"queued":return c.queued;case"uploading":return c.uploading(t.progress===null?null:Math.round(t.progress*100));case"processing":return c.processing;case"done":return c.done;case"failed":return`${c.failed} ${t.reason??""}`.trim();case"rejected":return`${c.rejected} ${t.reason??""}`.trim()}},lt=[E?G:null,T?V:null].filter(Boolean).join(" ")||void 0;return r.jsxs("div",{ref:F,role:"group","aria-labelledby":I,className:p.cn("rst:font-ui rst:w-full",X),"data-file-upload":"",children:[r.jsx("p",{id:I,className:p.cn("rst:mb-1.5 rst:text-left rst:text-sm rst:font-medium rst:leading-none rst:text-[var(--roster-control-text)]",i&&"rst:opacity-70"),children:n}),r.jsxs("div",{...it,"data-file-drop":"","data-dragging":A?"":void 0,className:p.cn("rst:flex rst:flex-col rst:items-center rst:justify-center rst:gap-2 rst:rounded-lg rst:border-2 rst:border-dashed rst:px-4 rst:py-6 rst:text-center rst:transition-colors rst:motion-reduce:transition-none",A?"rst:border-primary-500 rst:bg-primary-500/10":T?"rst:border-error-500 rst:dark:border-error-400":"rst:border-gray-300 rst:dark:border-gray-600"),children:[r.jsx(H.Button,{type:"button",variant:"outline",colorScheme:"neutral",size:"lg",className:p.cn("rst:px-5",i&&W),"aria-disabled":i||void 0,"aria-describedby":lt,onClick:()=>_.current?.click(),"data-file-choose":"",startIcon:r.jsx("svg",{...S,"aria-hidden":"true",children:r.jsx("path",{d:"M12 16V4M7 9l5-5 5 5M5 20h14"})}),children:c.choose}),r.jsx("p",{className:"rst:hidden rst:text-xs rst:text-gray-600 rst:pointer-fine:block rst:dark:text-gray-400","data-file-drop-hint":"",children:A?c.dropHere:c.dropHint}),r.jsx("input",{ref:_,type:"file",hidden:!0,tabIndex:-1,accept:M,multiple:x!==1,disabled:i,onChange:t=>{K(Array.from(t.currentTarget.files??[])),t.currentTarget.value=""},"data-file-input":""})]}),E&&r.jsx("p",{id:G,className:"rst:mt-1.5 rst:text-left rst:text-xs rst:text-gray-500 rst:dark:text-gray-400",children:E}),T&&r.jsx("p",{id:V,className:"rst:mt-1.5 rst:text-left rst:text-xs rst:font-medium rst:text-error-600 rst:dark:text-error-400",children:T}),U.length>0&&r.jsx("ul",{className:"rst:mt-3 rst:flex rst:flex-col rst:gap-2","aria-labelledby":I,children:U.map(t=>{const s=t.status==="failed"||t.status==="rejected",e=t.status==="uploading"||t.status==="processing"||t.status==="queued";return r.jsxs("li",{"data-file-item":t.id,"data-status":t.status,className:"rst:flex rst:items-center rst:gap-3 rst:rounded-md rst:border rst:border-[var(--roster-card-border)] rst:p-2",children:[r.jsx(ht,{file:t.file,status:t.status}),r.jsxs("div",{className:"rst:min-w-0 rst:flex-1 rst:text-left",children:[r.jsx("p",{className:"rst:truncate rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)]",title:t.file.name,children:t.file.name}),r.jsxs("p",{className:p.cn("rst:mt-0.5 rst:flex rst:items-start rst:gap-1 rst:text-xs",s?"rst:text-error-600 rst:dark:text-error-400":"rst:text-gray-600 rst:dark:text-gray-400"),"data-file-status":"",children:[t.status==="done"&&r.jsx("svg",{...S,width:14,height:14,"aria-hidden":"true",className:"rst:mt-px rst:shrink-0 rst:text-success-600 rst:dark:text-success-400",children:r.jsx("path",{d:"M20 6 9 17l-5-5"})}),r.jsxs("span",{children:[r.jsx("span",{className:"rst:tabular-nums",children:c.size(t.file.size)}),r.jsx("span",{"aria-hidden":"true",children:" · "}),dt(t)]})]}),e&&r.jsx("div",{className:"rst:mt-1.5","data-file-progress":"",children:r.jsx(pt.Progress,{size:"sm",value:t.status==="processing"?100:t.status==="uploading"?(t.progress??0)*100:0,busy:t.status==="processing"||t.status==="uploading"&&t.progress===null,announce:!1})})]}),t.status==="failed"&&r.jsx(H.Button,{type:"button",variant:"ghost",colorScheme:"neutral",size:"icon",className:p.cn("rst:h-11 rst:w-11",i&&W),"aria-disabled":i||void 0,"aria-label":c.retry(t.file.name),onClick:()=>ct(t.id),"data-file-retry":t.id,children:r.jsxs("svg",{...S,"aria-hidden":"true",children:[r.jsx("path",{d:"M3 12a9 9 0 1 0 3-6.7L3 8"}),r.jsx("path",{d:"M3 3v5h5"})]})}),r.jsx(H.Button,{type:"button",variant:"ghost",colorScheme:"neutral",size:"icon",className:p.cn("rst:h-11 rst:w-11",i&&W),"aria-disabled":i||void 0,"aria-label":c.remove(t.file.name),onClick:()=>ot(t.id),"data-file-remove":t.id,children:r.jsx("svg",{...S,"aria-hidden":"true",children:r.jsx("path",{d:"M18 6 6 18M6 6l12 12"})})})]},t.id)})}),r.jsxs("div",{role:"status","aria-live":"polite","aria-atomic":"true",className:"rst:sr-only","data-file-live":"","data-file-live-n":z.n,children:[z.text,z.n%2?" ":""]})]})}exports.FileUpload=xt;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),o=require("react"),p=require("../../../lib/utils.cjs"),pt=require("../../../lib/labels.cjs"),H=require("../../atoms/Button/Button.cjs"),gt=require("../../atoms/Progress/Progress.cjs"),R=require("./file-rules.cjs"),ht={choose:"Choose photos",dropHint:"or drag them here",dropHere:"Drop to add them",queued:"Waiting",uploading:n=>n===null?"Uploading":`Uploading, ${n}%`,processing:"Finishing up",done:"Uploaded",failed:"Didn't upload.",rejected:"Not added.",remove:n=>`Remove ${n}`,retry:n=>`Try ${n} again`,wrongType:()=>"That type of file isn't accepted.",tooLarge:(n,l)=>`It's over ${R.formatBytes(l)}.`,tooMany:n=>`Only ${n} can be added.`,duplicate:()=>"It's already added.",uploadError:n=>n instanceof Error&&n.message?n.message:"Something went wrong.",size:R.formatBytes,added:n=>`${n} ${n===1?"photo":"photos"} added.`,progress:(n,l)=>`${n} of ${l} uploaded.`,failedNotice:(n,l)=>`${n} didn't upload. ${l}`,rejectedNotice:(n,l)=>`${n} wasn't added. ${l}`,removed:n=>`${n} removed.`};function xt({file:n,status:l}){const[q,L]=o.useState(!1),B=!q&&(n.type.startsWith("image/")||/\.(jpe?g|png|gif|webp|avif|heic|heif)$/i.test(n.name)),N=o.useCallback(M=>{if(!M)return;const w=URL.createObjectURL(n);return M.src=w,()=>URL.revokeObjectURL(w)},[n]),x="rst:h-14 rst:w-14 rst:shrink-0 rst:rounded-md rst:border rst:border-[var(--roster-card-border)]";return B?r.jsx("img",{ref:N,alt:"",onError:()=>L(!0),className:p.cn(x,"rst:object-cover",l==="rejected"&&"rst:opacity-50"),"data-file-thumb":"image"}):r.jsx("span",{"aria-hidden":"true",className:p.cn(x,"rst:flex rst:items-center rst:justify-center rst:text-gray-500 rst:dark:text-gray-400"),"data-file-thumb":"placeholder",children:r.jsxs("svg",{viewBox:"0 0 24 24",width:"24",height:"24",fill:"none",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round",strokeLinejoin:"round",children:[r.jsx("rect",{x:"3",y:"5",width:"18",height:"14",rx:"2"}),r.jsx("circle",{cx:"9",cy:"10",r:"1.6"}),r.jsx("path",{d:"m21 15-4.2-4.2a1.6 1.6 0 0 0-2.3 0L7 18"})]})})}const W="rst:cursor-not-allowed rst:opacity-50",S={width:20,height:20,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};function mt({label:n,upload:l,onChange:q,accept:L="image/*",types:B,maxSize:N,maxFiles:x,validate:M,concurrency:w=3,helperText:E,errorMessage:T,disabled:i=!1,strings:Q,className:X}){const c=pt.withLabels(ht,Q),D=o.useId(),I=`${D}-label`,G=`${D}-help`,V=`${D}-error`,[U,Y]=o.useState([]),d=o.useRef(U),Z=o.useRef(0),m=o.useRef(new Map),F=o.useRef(null),_=o.useRef(null),g=o.useRef({upload:l,onChange:q,concurrency:w,t:c,pump:()=>{}}),[z,tt]=o.useState({text:"",n:0}),j=o.useRef([]),v=o.useRef(null),$=o.useCallback((t,s=!1)=>{s&&(j.current=j.current.filter(e=>!e.count)),j.current.push({text:t,count:s}),!v.current&&(v.current=setTimeout(()=>{v.current=null;const e=j.current.map(u=>u.text).join(" ");j.current=[],tt(u=>({text:e,n:u.n+1}))},0))},[]),O=o.useRef(null),[et,rt]=o.useState(0),J=t=>{O.current=t,rt(s=>s+1)};o.useLayoutEffect(()=>{const t=O.current;if(!t)return;O.current=null,(F.current?.querySelector(t)??F.current?.querySelector("[data-file-choose]"))?.focus()},[et]);const y=o.useCallback(t=>{d.current=t,Y(t),g.current.onChange?.(t)},[]),b=o.useCallback((t,s)=>{d.current.some(e=>e.id===t)&&y(d.current.map(e=>e.id===t?{...e,...s}:e))},[y]);function k(){const{concurrency:t}=g.current,s=d.current.filter(u=>u.status==="uploading"||u.status==="processing").length,e=d.current.filter(u=>u.status==="queued").slice(0,Math.max(0,Math.max(1,t)-s));for(const u of e)st(u)}function st(t){const s=new AbortController;m.current.set(t.id,s),b(t.id,{status:"uploading",progress:null,reason:void 0});const e=()=>!s.signal.aborted&&m.current.get(t.id)===s,u={onProgress:a=>{if(!e())return;const f=Math.round(Math.min(1,Math.max(0,Number.isFinite(a)?a:0))*100)/100,h=d.current.find(ft=>ft.id===t.id);h?.status==="uploading"&&h.progress!==f&&b(t.id,{progress:f})},onProcessing:()=>{e()&&b(t.id,{status:"processing"})},signal:s.signal};new Promise(a=>a(g.current.upload(t.file,u))).then(a=>{if(!e())return;m.current.delete(t.id),b(t.id,{status:"done",progress:1,result:a});const f=d.current.filter(h=>h.status!=="rejected");$(g.current.t.progress(f.filter(h=>h.status==="done").length,f.length),!0),k()},a=>{if(!e())return;m.current.delete(t.id);const f=g.current.t.uploadError(a);b(t.id,{status:"failed",reason:f}),$(g.current.t.failedNotice(t.file.name,f)),k()})}o.useLayoutEffect(()=>{g.current={upload:l,onChange:q,concurrency:w,t:c,pump:k}}),o.useEffect(()=>{const t=m.current;return d.current.some(e=>(e.status==="uploading"||e.status==="processing")&&!t.has(e.id))&&(y(d.current.map(e=>(e.status==="uploading"||e.status==="processing")&&!t.has(e.id)?{...e,status:"queued",progress:null}:e)),g.current.pump()),()=>{for(const e of t.values())e.abort();t.clear(),v.current&&clearTimeout(v.current),v.current=null,j.current=[]}},[y]);const nt=B??R.acceptList(L),at=(t,s)=>{if(s.some(u=>R.sameFile(u.file,t)))return c.duplicate(t);const e=M?.(t);if(e)return e;if(!R.matchesType(t,nt))return c.wrongType(t);if(N!==void 0&&t.size>N)return c.tooLarge(t,N);if(x!==void 0&&s.length>=x)return c.tooMany(x)},K=t=>{if(i||t.length===0)return;const s=d.current.filter(a=>a.status!=="rejected"),e=[];for(const a of t){const f=at(a,[...s,...e.filter(h=>h.status!=="rejected")]);e.push({id:`${D}-file-${Z.current++}`,file:a,status:f?"rejected":"queued",progress:null,reason:f})}y([...d.current,...e]);const u=e.filter(a=>a.status==="queued").length;u&&$(c.added(u));for(const a of e)a.reason&&$(c.rejectedNotice(a.file.name,a.reason));k()},ot=t=>{if(i)return;const s=d.current,e=s.findIndex(a=>a.id===t);if(e<0)return;m.current.get(t)?.abort(),m.current.delete(t);const u=s[e+1]??s[e-1];y(s.filter(a=>a.id!==t)),$(c.removed(s[e].file.name)),J(u?`[data-file-remove="${u.id}"]`:"[data-file-choose]"),k()},ct=t=>{i||(b(t,{status:"queued",progress:null,reason:void 0}),J(`[data-file-remove="${t}"]`),k())},[ut,P]=o.useState(0),C=t=>Array.from(t.dataTransfer?.types??[]).includes("Files"),it={onDragEnter:t=>{C(t)&&(t.preventDefault(),P(s=>s+1))},onDragOver:t=>{C(t)&&(t.preventDefault(),t.dataTransfer.dropEffect=i?"none":"copy")},onDragLeave:t=>{C(t)&&P(s=>Math.max(0,s-1))},onDrop:t=>{C(t)&&(t.preventDefault(),P(0),K(Array.from(t.dataTransfer.files)))}},A=ut>0&&!i,lt=t=>{switch(t.status){case"queued":return c.queued;case"uploading":return c.uploading(t.progress===null?null:Math.round(t.progress*100));case"processing":return c.processing;case"done":return c.done;case"failed":return`${c.failed} ${t.reason??""}`.trim();case"rejected":return`${c.rejected} ${t.reason??""}`.trim()}},dt=[E?G:null,T?V:null].filter(Boolean).join(" ")||void 0;return r.jsxs("div",{ref:F,role:"group","aria-labelledby":I,className:p.cn("rst:font-ui rst:w-full",X),"data-file-upload":"",children:[r.jsx("p",{id:I,className:p.cn("rst:mb-1.5 rst:text-left rst:text-sm rst:font-medium rst:leading-none rst:text-[var(--roster-control-text)]",i&&"rst:opacity-70"),children:n}),r.jsxs("div",{...it,"data-file-drop":"","data-dragging":A?"":void 0,className:p.cn("rst:flex rst:flex-col rst:items-center rst:justify-center rst:gap-2 rst:rounded-lg rst:border-2 rst:border-dashed rst:px-4 rst:py-6 rst:text-center rst:transition-colors rst:motion-reduce:transition-none",A?"rst:border-primary-500 rst:bg-primary-500/10":T?"rst:border-error-500 rst:dark:border-error-400":"rst:border-gray-300 rst:dark:border-gray-600"),children:[r.jsx(H.Button,{type:"button",variant:"outline",colorScheme:"neutral",size:"lg",className:p.cn("rst:px-5",i&&W),"aria-disabled":i||void 0,"aria-describedby":dt,onClick:()=>_.current?.click(),"data-file-choose":"",startIcon:r.jsx("svg",{...S,"aria-hidden":"true",children:r.jsx("path",{d:"M12 16V4M7 9l5-5 5 5M5 20h14"})}),children:c.choose}),r.jsx("p",{className:"rst:hidden rst:text-xs rst:text-gray-600 rst:pointer-fine:block rst:dark:text-gray-400","data-file-drop-hint":"",children:A?c.dropHere:c.dropHint}),r.jsx("input",{ref:_,type:"file",hidden:!0,tabIndex:-1,accept:L,multiple:x!==1,disabled:i,onChange:t=>{K(Array.from(t.currentTarget.files??[])),t.currentTarget.value=""},"data-file-input":""})]}),E&&r.jsx("p",{id:G,className:"rst:mt-1.5 rst:text-left rst:text-xs rst:text-gray-500 rst:dark:text-gray-400",children:E}),T&&r.jsx("p",{id:V,className:"rst:mt-1.5 rst:text-left rst:text-xs rst:font-medium rst:text-error-600 rst:dark:text-error-400",children:T}),U.length>0&&r.jsx("ul",{className:"rst:mt-3 rst:flex rst:flex-col rst:gap-2","aria-labelledby":I,children:U.map(t=>{const s=t.status==="failed"||t.status==="rejected",e=t.status==="uploading"||t.status==="processing"||t.status==="queued";return r.jsxs("li",{"data-file-item":t.id,"data-status":t.status,className:"rst:flex rst:items-center rst:gap-3 rst:rounded-md rst:border rst:border-[var(--roster-card-border)] rst:p-2",children:[r.jsx(xt,{file:t.file,status:t.status}),r.jsxs("div",{className:"rst:min-w-0 rst:flex-1 rst:text-left",children:[r.jsx("p",{className:"rst:truncate rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)]",title:t.file.name,children:t.file.name}),r.jsxs("p",{className:p.cn("rst:mt-0.5 rst:flex rst:items-start rst:gap-1 rst:text-xs",s?"rst:text-error-600 rst:dark:text-error-400":"rst:text-gray-600 rst:dark:text-gray-400"),"data-file-status":"",children:[t.status==="done"&&r.jsx("svg",{...S,width:14,height:14,"aria-hidden":"true",className:"rst:mt-px rst:shrink-0 rst:text-success-600 rst:dark:text-success-400",children:r.jsx("path",{d:"M20 6 9 17l-5-5"})}),r.jsxs("span",{children:[r.jsx("span",{className:"rst:tabular-nums",children:c.size(t.file.size)}),r.jsx("span",{"aria-hidden":"true",children:" · "}),lt(t)]})]}),e&&r.jsx("div",{className:"rst:mt-1.5","data-file-progress":"",children:r.jsx(gt.Progress,{size:"sm",value:t.status==="processing"?100:t.status==="uploading"?(t.progress??0)*100:0,busy:t.status==="processing"||t.status==="uploading"&&t.progress===null,announce:!1})})]}),t.status==="failed"&&r.jsx(H.Button,{type:"button",variant:"ghost",colorScheme:"neutral",size:"icon",className:p.cn("rst:h-11 rst:w-11",i&&W),"aria-disabled":i||void 0,"aria-label":c.retry(t.file.name),onClick:()=>ct(t.id),"data-file-retry":t.id,children:r.jsxs("svg",{...S,"aria-hidden":"true",children:[r.jsx("path",{d:"M3 12a9 9 0 1 0 3-6.7L3 8"}),r.jsx("path",{d:"M3 3v5h5"})]})}),r.jsx(H.Button,{type:"button",variant:"ghost",colorScheme:"neutral",size:"icon",className:p.cn("rst:h-11 rst:w-11",i&&W),"aria-disabled":i||void 0,"aria-label":c.remove(t.file.name),onClick:()=>ot(t.id),"data-file-remove":t.id,children:r.jsx("svg",{...S,"aria-hidden":"true",children:r.jsx("path",{d:"M18 6 6 18M6 6l12 12"})})})]},t.id)})}),r.jsxs("div",{role:"status","aria-live":"polite","aria-atomic":"true",className:"rst:sr-only","data-file-live":"","data-file-live-n":z.n,children:[z.text,z.n%2?" ":""]})]})}exports.FileUpload=mt;
@@ -1,11 +1,12 @@
1
1
  "use client";
2
2
  import { jsxs as p, jsx as n } from "react/jsx-runtime";
3
- import { useId as vr, useState as L, useRef as f, useCallback as U, useLayoutEffect as Y, useEffect as xr } from "react";
3
+ import { useId as vr, useState as M, useRef as f, useCallback as U, useLayoutEffect as Y, useEffect as xr } from "react";
4
4
  import { cn as g } from "../../../lib/utils.js";
5
+ import { withLabels as yr } from "../../../lib/labels.js";
5
6
  import { Button as G } from "../../atoms/Button/Button.js";
6
- import { Progress as yr } from "../../atoms/Progress/Progress.js";
7
- import { formatBytes as Z, acceptList as br, sameFile as kr, matchesType as Nr } from "./file-rules.js";
8
- const wr = {
7
+ import { Progress as br } from "../../atoms/Progress/Progress.js";
8
+ import { acceptList as kr, formatBytes as Z, sameFile as Nr, matchesType as wr } from "./file-rules.js";
9
+ const $r = {
9
10
  choose: "Choose photos",
10
11
  dropHint: "or drag them here",
11
12
  dropHere: "Drop to add them",
@@ -29,8 +30,8 @@ const wr = {
29
30
  rejectedNotice: (s, d) => `${s} wasn't added. ${d}`,
30
31
  removed: (s) => `${s} removed.`
31
32
  };
32
- function $r({ file: s, status: d }) {
33
- const [T, D] = L(!1), B = !T && (s.type.startsWith("image/") || /\.(jpe?g|png|gif|webp|avif|heic|heif)$/i.test(s.name)), $ = U(
33
+ function jr({ file: s, status: d }) {
34
+ const [T, D] = M(!1), B = !T && (s.type.startsWith("image/") || /\.(jpe?g|png|gif|webp|avif|heic|heif)$/i.test(s.name)), $ = U(
34
35
  (q) => {
35
36
  if (!q) return;
36
37
  const j = URL.createObjectURL(s);
@@ -62,7 +63,7 @@ function $r({ file: s, status: d }) {
62
63
  );
63
64
  }
64
65
  const V = "rst:cursor-not-allowed rst:opacity-50", I = { width: 20, height: 20, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" };
65
- function Rr({
66
+ function Er({
66
67
  label: s,
67
68
  upload: d,
68
69
  onChange: T,
@@ -78,14 +79,14 @@ function Rr({
78
79
  strings: rr,
79
80
  className: tr
80
81
  }) {
81
- const a = { ...wr, ...rr }, C = vr(), z = `${C}-label`, _ = `${C}-help`, J = `${C}-error`, [F, er] = L([]), u = f(F), sr = f(0), x = f(/* @__PURE__ */ new Map()), O = f(null), K = f(null), h = f({ upload: d, onChange: T, concurrency: j, t: a, pump: () => {
82
- } }), [A, nr] = L({ text: "", n: 0 }), y = f([]), b = f(null), M = U((r, e = !1) => {
82
+ const a = yr($r, rr), C = vr(), z = `${C}-label`, _ = `${C}-help`, J = `${C}-error`, [F, er] = M([]), u = f(F), sr = f(0), x = f(/* @__PURE__ */ new Map()), O = f(null), K = f(null), h = f({ upload: d, onChange: T, concurrency: j, t: a, pump: () => {
83
+ } }), [A, nr] = M({ text: "", n: 0 }), y = f([]), b = f(null), L = U((r, e = !1) => {
83
84
  e && (y.current = y.current.filter((t) => !t.count)), y.current.push({ text: r, count: e }), !b.current && (b.current = setTimeout(() => {
84
85
  b.current = null;
85
86
  const t = y.current.map((c) => c.text).join(" ");
86
87
  y.current = [], nr((c) => ({ text: t, n: c.n + 1 }));
87
88
  }, 0));
88
- }, []), H = f(null), [or, ar] = L(0), Q = (r) => {
89
+ }, []), H = f(null), [or, ar] = M(0), Q = (r) => {
89
90
  H.current = r, ar((e) => e + 1);
90
91
  };
91
92
  Y(() => {
@@ -124,13 +125,13 @@ function Rr({
124
125
  if (!t()) return;
125
126
  x.current.delete(r.id), N(r.id, { status: "done", progress: 1, result: o });
126
127
  const l = u.current.filter((m) => m.status !== "rejected");
127
- M(h.current.t.progress(l.filter((m) => m.status === "done").length, l.length), !0), w();
128
+ L(h.current.t.progress(l.filter((m) => m.status === "done").length, l.length), !0), w();
128
129
  },
129
130
  (o) => {
130
131
  if (!t()) return;
131
132
  x.current.delete(r.id);
132
133
  const l = h.current.t.uploadError(o);
133
- N(r.id, { status: "failed", reason: l }), M(h.current.t.failedNotice(r.file.name, l)), w();
134
+ N(r.id, { status: "failed", reason: l }), L(h.current.t.failedNotice(r.file.name, l)), w();
134
135
  }
135
136
  );
136
137
  }
@@ -147,11 +148,11 @@ function Rr({
147
148
  r.clear(), b.current && clearTimeout(b.current), b.current = null, y.current = [];
148
149
  };
149
150
  }, [k]);
150
- const ir = B ?? br(D), dr = (r, e) => {
151
- if (e.some((c) => kr(c.file, r))) return a.duplicate(r);
151
+ const ir = B ?? kr(D), dr = (r, e) => {
152
+ if (e.some((c) => Nr(c.file, r))) return a.duplicate(r);
152
153
  const t = q?.(r);
153
154
  if (t) return t;
154
- if (!Nr(r, ir)) return a.wrongType(r);
155
+ if (!wr(r, ir)) return a.wrongType(r);
155
156
  if ($ !== void 0 && r.size > $) return a.tooLarge(r, $);
156
157
  if (v !== void 0 && e.length >= v) return a.tooMany(v);
157
158
  }, X = (r) => {
@@ -163,8 +164,8 @@ function Rr({
163
164
  }
164
165
  k([...u.current, ...t]);
165
166
  const c = t.filter((o) => o.status === "queued").length;
166
- c && M(a.added(c));
167
- for (const o of t) o.reason && M(a.rejectedNotice(o.file.name, o.reason));
167
+ c && L(a.added(c));
168
+ for (const o of t) o.reason && L(a.rejectedNotice(o.file.name, o.reason));
168
169
  w();
169
170
  }, ur = (r) => {
170
171
  if (i) return;
@@ -172,10 +173,10 @@ function Rr({
172
173
  if (t < 0) return;
173
174
  x.current.get(r)?.abort(), x.current.delete(r);
174
175
  const c = e[t + 1] ?? e[t - 1];
175
- k(e.filter((o) => o.id !== r)), M(a.removed(e[t].file.name)), Q(c ? `[data-file-remove="${c.id}"]` : "[data-file-choose]"), w();
176
+ k(e.filter((o) => o.id !== r)), L(a.removed(e[t].file.name)), Q(c ? `[data-file-remove="${c.id}"]` : "[data-file-choose]"), w();
176
177
  }, lr = (r) => {
177
178
  i || (N(r, { status: "queued", progress: null, reason: void 0 }), Q(`[data-file-remove="${r}"]`), w());
178
- }, [fr, P] = L(0), E = (r) => Array.from(r.dataTransfer?.types ?? []).includes("Files"), pr = {
179
+ }, [fr, P] = M(0), E = (r) => Array.from(r.dataTransfer?.types ?? []).includes("Files"), pr = {
179
180
  onDragEnter: (r) => {
180
181
  E(r) && (r.preventDefault(), P((e) => e + 1));
181
182
  },
@@ -289,7 +290,7 @@ function Rr({
289
290
  "data-status": r.status,
290
291
  className: "rst:flex rst:items-center rst:gap-3 rst:rounded-md rst:border rst:border-[var(--roster-card-border)] rst:p-2",
291
292
  children: [
292
- /* @__PURE__ */ n($r, { file: r.file, status: r.status }),
293
+ /* @__PURE__ */ n(jr, { file: r.file, status: r.status }),
293
294
  /* @__PURE__ */ p("div", { className: "rst:min-w-0 rst:flex-1 rst:text-left", children: [
294
295
  /* @__PURE__ */ n("p", { className: "rst:truncate rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)]", title: r.file.name, children: r.file.name }),
295
296
  /* @__PURE__ */ p(
@@ -311,7 +312,7 @@ function Rr({
311
312
  }
312
313
  ),
313
314
  t && /* @__PURE__ */ n("div", { className: "rst:mt-1.5", "data-file-progress": "", children: /* @__PURE__ */ n(
314
- yr,
315
+ br,
315
316
  {
316
317
  size: "sm",
317
318
  value: r.status === "processing" ? 100 : r.status === "uploading" ? (r.progress ?? 0) * 100 : 0,
@@ -378,5 +379,5 @@ function Rr({
378
379
  );
379
380
  }
380
381
  export {
381
- Rr as FileUpload
382
+ Er as FileUpload
382
383
  };
@@ -1 +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;
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),h=require("react"),i=require("../../../lib/utils.cjs");function j({src:e,href:t,alt:s,unavailableLabel:n="Preview unavailable",openLabel:a="Open original",newTabLabel:u="in a new tab",onUnavailable:g,className:o,...x}){const[b,f]=h.useState(null),m=!e||b===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(m){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}, ${u}: ${s}`,children:d}):r.jsx("span",{role:"img","aria-label":`${n}: ${s}`,className:l,children:d})}return r.jsx("img",{...x,src:e,alt:s,className:i.cn(c,"rst:object-cover",o),onError:()=>{f(e),g?.()}})}exports.MediaPreview=j;
@@ -10,6 +10,8 @@ export interface MediaPreviewProps extends Omit<ImgHTMLAttributes<HTMLImageEleme
10
10
  unavailableLabel?: string;
11
11
  /** The link's own words. */
12
12
  openLabel?: string;
13
+ /** Said with the link's name, since its arrow shows it only to the eye: "in a new tab". */
14
+ newTabLabel?: string;
13
15
  /** Called once when the thumbnail fails, for an app that keeps a count. */
14
16
  onUnavailable?: () => void;
15
17
  }
@@ -23,5 +25,5 @@ export interface MediaPreviewProps extends Omit<ImgHTMLAttributes<HTMLImageEleme
23
25
  * for a card that says the preview is unavailable and links to the original,
24
26
  * in the same footprint, so a row of previews doesn't jump.
25
27
  */
26
- declare function MediaPreview({ src, href, alt, unavailableLabel, openLabel, onUnavailable, className, ...props }: MediaPreviewProps): import("react/jsx-runtime").JSX.Element;
28
+ declare function MediaPreview({ src, href, alt, unavailableLabel, openLabel, newTabLabel, onUnavailable, className, ...props }: MediaPreviewProps): import("react/jsx-runtime").JSX.Element;
27
29
  export { MediaPreview };
@@ -1,20 +1,21 @@
1
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";
2
+ import { jsx as r, jsxs as m, Fragment as p } from "react/jsx-runtime";
3
+ import { useState as v } from "react";
4
4
  import { cn as i } from "../../../lib/utils.js";
5
- function $({
5
+ function j({
6
6
  src: e,
7
7
  href: t,
8
8
  alt: s,
9
9
  unavailableLabel: n = "Preview unavailable",
10
10
  openLabel: o = "Open original",
11
- onUnavailable: g,
11
+ newTabLabel: g = "in a new tab",
12
+ onUnavailable: u,
12
13
  className: a,
13
- ...u
14
+ ...f
14
15
  }) {
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: [
16
+ const [b, h] = v(null), x = !e || b === 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)]";
17
+ if (x) {
18
+ const l = /* @__PURE__ */ m(p, { children: [
18
19
  /* @__PURE__ */ r("span", { children: n }),
19
20
  t ? /* @__PURE__ */ m("span", { className: "rst:font-semibold rst:underline", children: [
20
21
  o,
@@ -32,7 +33,7 @@ function $({
32
33
  target: "_blank",
33
34
  rel: "noreferrer",
34
35
  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
+ "aria-label": `${n}. ${o}, ${g}: ${s}`,
36
37
  children: l
37
38
  }
38
39
  ) : /* @__PURE__ */ r("span", { role: "img", "aria-label": `${n}: ${s}`, className: c, children: l });
@@ -40,16 +41,16 @@ function $({
40
41
  return /* @__PURE__ */ r(
41
42
  "img",
42
43
  {
43
- ...u,
44
+ ...f,
44
45
  src: e,
45
46
  alt: s,
46
47
  className: i(d, "rst:object-cover", a),
47
48
  onError: () => {
48
- b(e), g?.();
49
+ h(e), u?.();
49
50
  }
50
51
  }
51
52
  );
52
53
  }
53
54
  export {
54
- $ as MediaPreview
55
+ j as MediaPreview
55
56
  };
@@ -0,0 +1 @@
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react/jsx-runtime"),ge=require("react"),W=require("../../../node_modules/@headlessui/react/dist/components/portal/portal.cjs"),A=require("../../../node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.cjs"),E=require("../../../lib/utils.cjs"),he=require("../../../internal/popup.cjs"),be=require("../../atoms/Button/Button.cjs"),xe=require("./menu-typeahead.cjs"),ye=require("../../../node_modules/@floating-ui/dom/dist/floating-ui.dom.cjs");function ve(e){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const n in e)if(n!=="default"){const o=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(r,n,o.get?o:{enumerable:!0,get:()=>e[n]})}}return r.default=e,Object.freeze(r)}const i=ve(ge);function we({href:e,to:r,children:n,...o}){return c.jsx("a",{href:e,...o,children:n})}const G=i.createContext(null),_=i.createContext(null),V=i.createContext(null);function R(e){const r=i.useContext(G);if(!r)throw new Error(`<${e}> must be inside a <Menu>.`);return r}function K(e){const r=i.useContext(_);if(!r)throw new Error(`<${e}> must be inside <MenuItems> or a <MenuSubmenu>.`);return r}const ke="[data-menu-item]",Y=100,Ie=75,Ee='a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), summary, [tabindex]:not([tabindex="-1"]), [contenteditable]:not([contenteditable="false"])';function L(e){return e?[...e.querySelectorAll(ke)].filter(r=>r.closest("[data-menu-panel]")===e):[]}function S(e){e&&(e.focus({preventScroll:!0}),e.scrollIntoView?.({block:"nearest"}))}function $(e){return!!e&&getComputedStyle(e).direction==="rtl"}function Se(e,r){const n=[...document.querySelectorAll(Ee)].filter(t=>t===e||t.tabIndex>=0&&!t.matches(":disabled")&&!t.closest("[data-menu-panel], [inert]")&&t.getClientRects().length>0&&getComputedStyle(t).visibility!=="hidden"&&!Me(t,r)),o=n.indexOf(e);((r?n[o-1]:n[o+1])??e).focus()}function Me(e,r){if(!(e instanceof HTMLInputElement)||e.type!=="radio"||!e.name)return!1;const n=[...e.ownerDocument.querySelectorAll(`input[type="radio"][name="${CSS.escape(e.name)}"]`)].filter(a=>a.form===e.form&&!a.disabled);return(n.find(a=>a.checked)??(r?n[n.length-1]:n[0]))!==e}const D={x:Number.NaN,y:Number.NaN};let H=!1;function je(){H||typeof window>"u"||(H=!0,window.addEventListener("pointermove",e=>{D.x=e.clientX,D.y=e.clientY},{passive:!0}))}function X(e){return!Number.isNaN(D.x)&&(e.clientX!==D.x||e.clientY!==D.y)}const U=e=>`radial-gradient(farthest-side at 50% ${e==="top"?"0":"100%"}, var(--menu-edge), transparent)`,J={backgroundImage:"var(--menu-edge-top, none), var(--menu-edge-bottom, none)",backgroundPosition:"top, bottom",backgroundSize:"100% 0.5rem",backgroundRepeat:"no-repeat"};function Pe(e){i.useLayoutEffect(()=>{if(!e)return;const r=()=>{const o=e.scrollTop>8,a=e.scrollTop+e.clientHeight<e.scrollHeight-8;e.toggleAttribute("data-more-above",o),e.toggleAttribute("data-more-below",a),e.style.setProperty("--menu-edge-top",o?U("top"):"none"),e.style.setProperty("--menu-edge-bottom",a?U("bottom"):"none")};r(),e.addEventListener("scroll",r,{passive:!0});const n=typeof ResizeObserver>"u"?null:new ResizeObserver(r);return n?.observe(e),()=>{e.removeEventListener("scroll",r),n?.disconnect()}},[e])}function Q(e,r){const[n,o]=e.split("-"),a=r?"right":"left",t=r?"left":"right";return n==="top"||n==="bottom"?`${n==="bottom"?"top":"bottom"} ${o==="end"?t:o==="start"?a:"center"}`:`${o==="end"?"bottom":"top"} ${n==="right"?"left":"right"}`}const Z=E.cn("rst:font-ui",he.POPUP_PANEL,"rst:w-max rst:min-w-48 rst:max-w-[min(20rem,calc(100vw-1rem))] rst:overflow-y-auto rst:overscroll-contain rst:custom-scrollbar","rst:[--menu-edge:rgb(0_0_0/0.18)] rst:dark:[--menu-edge:rgb(0_0_0/0.6)]","rst:transition-[opacity,scale] rst:duration-100 rst:ease-out rst:data-closed:opacity-0 rst:data-closed:scale-95 rst:data-leaving:duration-75 rst:data-leaving:ease-in rst:data-closed:pointer-events-none rst:motion-reduce:transition-none");function ee(e){const[r,n]=i.useState(e),[o,a]=i.useState(!0);return i.useLayoutEffect(()=>{if(e){n(!0);const s=requestAnimationFrame(()=>a(!1));return()=>cancelAnimationFrame(s)}a(!0);const t=window.matchMedia?.("(prefers-reduced-motion: reduce)").matches,d=window.setTimeout(()=>n(!1),t?0:Ie);return()=>window.clearTimeout(d)},[e]),{mounted:r,closed:o,leaving:r&&!e}}function te(e,r,n,o,a,t=!1){const[d,s]=i.useState(null),u=A.useFloating({open:r,strategy:"fixed",transform:!1,placement:n,elements:{reference:e},whileElementsMounted:ye.autoUpdate,middleware:[A.offset(o),A.flip({padding:8}),A.shift({padding:8,crossAxis:t}),A.size({padding:8,apply({availableHeight:f,elements:l}){l.floating.style.maxHeight=`min(var(--anchor-max-height, 100vh), ${Math.max(f,96)}px)`}})]}),{setFloating:p}=u.refs,m=i.useCallback(f=>{a.current=f,s(f),p(f)},[a,p]);return Pe(d),{...u,setPanel:m,panelEl:d}}const re=500;function ne(){const e=i.useRef({text:"",at:0}),r=i.useCallback(()=>e.current.text!==""&&performance.now()-e.current.at<=re,[]);return{typedRef:e,typingAhead:r}}function oe({panelRef:e,typedRef:r,onEscape:n,onBack:o}){const a=R("MenuItems");return t=>{const d=e.current;if(!d||!d.contains(t.target)||(!t.ctrlKey&&!t.metaKey&&!t.altKey&&t.stopPropagation(),t.defaultPrevented))return;const s=L(d),u=s.indexOf(document.activeElement),p=$(d);switch(t.key){case"ArrowDown":t.preventDefault(),t.stopPropagation(),S(s[(u+1)%s.length]);return;case"ArrowUp":t.preventDefault(),t.stopPropagation(),S(s[u<=0?s.length-1:u-1]);return;case"Home":case"PageUp":t.preventDefault(),t.stopPropagation(),S(s[0]);return;case"End":case"PageDown":t.preventDefault(),t.stopPropagation(),S(s[s.length-1]);return;case"Escape":t.preventDefault(),t.stopPropagation(),n();return;case"Tab":{t.preventDefault(),t.stopPropagation();const m=a.triggerRef.current;a.close(!1),m&&Se(m,t.shiftKey);return}case"ArrowLeft":case"ArrowRight":o&&t.key===(p?"ArrowRight":"ArrowLeft")&&(t.preventDefault(),t.stopPropagation(),o());return}if(t.key.length===1&&!t.ctrlKey&&!t.metaKey&&!t.altKey){const m=performance.now(),f=r.current.text!==""&&m-r.current.at<=re;if(t.key===" "&&!f)return;t.preventDefault(),r.current={text:f?r.current.text+t.key:t.key,at:m};const l=s.map(w=>w.dataset.menuText??w.textContent??""),b=xe.nextByTypeahead(l,u,r.current.text);b!==-1&&S(s[b])}}}function Te({children:e,open:r,onOpenChange:n,linkComponent:o=we}){const[a,t]=i.useState(!1),d=r??a,s=i.useId(),u=i.useRef(null),[p,m]=i.useState(null),f=i.useCallback(g=>{u.current=g,m(g)},[]),l=i.useRef("panel"),b=i.useCallback(g=>{r===void 0&&t(g),n?.(g)},[r,n]),w=i.useMemo(()=>({treeId:s,open:d,openWith:g=>{l.current=g,b(!0)},close:g=>{b(!1),g&&u.current?.focus()},triggerRef:u,triggerEl:p,registerTrigger:f,triggerId:`${s}-button`,panelId:`${s}-menu`,focusOnOpen:l,linkComponent:o}),[s,d,b,o,p,f]);return i.useEffect(()=>{if(!d)return;je();const g=I=>{I.target?.closest?.(`[data-menu-tree="${s}"]`)||(b(!1),requestAnimationFrame(()=>{(document.activeElement===document.body||!document.activeElement)&&u.current?.focus({preventScroll:!0})}))};return document.addEventListener("pointerdown",g,!0),()=>document.removeEventListener("pointerdown",g,!0)},[d,s,b]),c.jsx(G.Provider,{value:w,children:e})}const Re=i.forwardRef(function({plain:r=!1,className:n,onClick:o,onKeyDown:a,children:t,...d},s){const{variant:u,colorScheme:p,size:m,isLoading:f,loadingLabel:l,startIcon:b,endIcon:w,surface:g,...I}=d,h=R("MenuButton"),{registerTrigger:M}=h,j=i.useCallback(x=>{M(x),typeof s=="function"?s(x):s&&(s.current=x)},[M,s]),P={id:h.triggerId,"aria-haspopup":"menu","aria-expanded":h.open,"aria-controls":h.open?h.panelId:void 0,"data-menu-tree":h.treeId,onClick:x=>{o?.(x),!x.defaultPrevented&&(h.open?h.close(!1):h.openWith("panel"))},onKeyDown:x=>{if(a?.(x),x.defaultPrevented)return;const y=x.key==="Enter"||x.key===" "||x.key==="ArrowDown"?"first":x.key==="ArrowUp"?"last":null;if(!y)return;x.preventDefault();const k=h.open?document.getElementById(h.panelId):null;if(k){const C=L(k);S(y==="last"?C[C.length-1]:C[0]);return}h.openWith(y)}};return r?c.jsx("button",{ref:j,type:"button",className:n,...I,...P,children:t}):c.jsx(be.Button,{ref:j,className:E.cn("rst:min-h-11 rst:min-w-11",n),variant:u,colorScheme:p,size:m,isLoading:f,loadingLabel:l,startIcon:b,endIcon:w,surface:g,...I,...P,children:t})});function Ce({children:e,align:r="start",offset:n=4,className:o,...a}){const t=R("MenuItems"),{mounted:d,closed:s,leaving:u}=ee(t.open),p=i.useRef(null),m=$(t.triggerEl),{setPanel:f,panelEl:l,floatingStyles:b,placement:w,isPositioned:g}=te(t.triggerEl,d,`bottom-${r}`,n,p),I=se(),{typedRef:h,typingAhead:M}=ne(),j=oe({panelRef:p,typedRef:h,onEscape:()=>t.close(!0)});i.useLayoutEffect(()=>{if(!t.open||!l)return;const y=L(l),k=t.focusOnOpen.current;k==="first"&&y[0]?S(y[0]):k==="last"&&y.length?S(y[y.length-1]):l.focus({preventScroll:!0})},[t.open,l,t.focusOnOpen]),i.useLayoutEffect(()=>{if(!g||!l)return;const y=document.activeElement;y&&y!==l&&l.contains(y)&&y.scrollIntoView?.({block:"nearest"})},[g,l]),i.useLayoutEffect(()=>{!t.open&&l?.contains(document.activeElement)&&t.triggerRef.current?.focus({preventScroll:!0})},[t.open,l,t.triggerRef]);const P=y=>{const k=y.relatedTarget;k&&!k.closest(`[data-menu-tree="${t.treeId}"]`)&&t.close(!1)};if(!d)return null;const x=!!t.triggerEl?.closest(".dark");return c.jsx(W.Portal,{children:c.jsx(_.Provider,{value:{...I,panelRef:p,typingAhead:M},children:c.jsx("div",{ref:f,id:t.panelId,dir:m?"rtl":"ltr",role:"menu","aria-labelledby":a["aria-label"]?void 0:t.triggerId,"aria-label":a["aria-label"],tabIndex:-1,"data-menu-panel":"","data-menu-tree":t.treeId,"data-closed":s?"":void 0,"data-leaving":u?"":void 0,onKeyDown:j,onBlur:P,style:{...b,...J,transformOrigin:Q(w,m)},className:E.cn(x&&"dark",Z,o),children:e})})})}function se(){const[e,r]=i.useState(null),n=i.useRef(!1),o=i.useRef(void 0);return i.useEffect(()=>()=>window.clearTimeout(o.current),[]),{openSubmenu:e,focusFirstInSubmenu:n,setOpenSubmenu:(a,t=!1)=>{window.clearTimeout(o.current),n.current=t,r(a)},hoverItem:a=>{window.clearTimeout(o.current),a===null&&(o.current=window.setTimeout(()=>r(null),Y))}}}const O=E.cn("rst:relative rst:flex rst:w-full rst:min-h-11 rst:items-center rst:gap-2.5 rst:border-0 rst:bg-transparent rst:px-3 rst:py-2 rst:text-start rst:text-sm rst:text-inherit rst:no-underline rst:[font-family:inherit] rst:cursor-pointer rst:select-none rst:outline-none rst:transition-colors","rst:focus:bg-primary-100 rst:focus:text-primary-900 rst:dark:focus:bg-primary-900/30 rst:dark:focus:text-primary-100 rst:forced-colors:focus:outline-solid rst:forced-colors:focus:outline-2 rst:forced-colors:focus:-outline-offset-2","rst:aria-disabled:opacity-50 rst:aria-disabled:cursor-not-allowed"),q="rst:text-error-600 rst:dark:text-error-400 rst:focus:bg-error-50 rst:focus:text-error-700 rst:dark:focus:bg-error-900/30 rst:dark:focus:text-error-300",Ae=()=>c.jsx("svg",{viewBox:"0 0 16 16",width:"16",height:"16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:c.jsx("path",{d:"M3.5 8.5 6.5 11.5 12.5 4.5"})}),De=()=>c.jsx("svg",{viewBox:"0 0 16 16",width:"16",height:"16","aria-hidden":"true",children:c.jsx("circle",{cx:"8",cy:"8",r:"3.5",fill:"currentColor"})}),Le=()=>c.jsx("svg",{viewBox:"0 0 16 16",width:"16",height:"16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",className:"rst:rtl:rotate-180",children:c.jsx("path",{d:"M6 3.5 10.5 8 6 12.5"})});function T({icon:e,shortcut:r,description:n,badge:o,children:a},t,d,s){const u=t??e;return c.jsxs(c.Fragment,{children:[u!=null&&c.jsx("span",{"aria-hidden":"true",className:E.cn("rst:flex rst:size-4 rst:shrink-0 rst:items-center rst:justify-center",n!=null&&"rst:self-start rst:mt-0.5"),"data-menu-lead":"",children:u}),c.jsxs("span",{className:"rst:min-w-0 rst:flex-1 rst:break-words","data-menu-label":"",children:[a,n!=null&&c.jsx("span",{id:s,"aria-hidden":"true",className:"rst:block rst:text-xs rst:opacity-75","data-menu-description":"",children:n})]}),o!=null&&c.jsx("span",{className:"rst:flex rst:shrink-0 rst:items-center","data-menu-badge":"",children:o}),r&&c.jsx("span",{"aria-hidden":"true",className:"rst:ms-auto rst:shrink-0 rst:ps-4 rst:text-xs rst:tracking-wide rst:opacity-70","data-menu-shortcut":"",children:r}),d]})}function z({disabled:e,closeOnSelect:r,onChoose:n,spaceKeepsOpen:o}){const a=R("MenuItem"),t=K("MenuItem"),d=(s,u)=>{if(e){s.preventDefault();return}n(s),u&&a.close(!0)};return{onClick:s=>d(s,r),onKeyDown:s=>{if(s.key===" "){if(t.typingAhead())return;s.preventDefault(),d(s,r&&!o)}},onPointerMove:s=>{X(s)&&(t.hoverItem(null),document.activeElement!==s.currentTarget&&s.currentTarget.focus({preventScroll:!0}))}}}function Oe({onSelect:e,href:r,closeOnSelect:n=!0,disabled:o,destructive:a,keyshortcuts:t,textValue:d,className:s,...u}){const p=R("MenuItem"),m=K("MenuItem"),f=i.useId(),l=z({disabled:o,closeOnSelect:n,onChoose:g=>e?.(g)}),b=E.cn(O,a&&q,s),w={role:"menuitem",tabIndex:-1,"aria-disabled":o?!0:void 0,"aria-keyshortcuts":t,"aria-describedby":u.description!=null?f:void 0,"data-menu-item":"","data-menu-text":d,"data-destructive":a?"":void 0};if(r!==void 0){const g=p.linkComponent;return c.jsx(g,{href:r,to:r,className:b,...w,onClick:l.onClick,onPointerMove:l.onPointerMove,onKeyDown:I=>{if(I.key===" "){if(m.typingAhead())return;I.preventDefault(),o||I.currentTarget.click()}},children:T(u,void 0,void 0,f)})}return c.jsx("button",{type:"button",className:b,...w,...l,children:T(u,void 0,void 0,f)})}function Ne({checked:e,onCheckedChange:r,indicator:n,closeOnSelect:o=!0,disabled:a,destructive:t,keyshortcuts:d,textValue:s,className:u,...p}){const m=z({disabled:a,closeOnSelect:o,spaceKeepsOpen:!0,onChoose:()=>r(!e)}),f=i.useId();return c.jsx("button",{type:"button",role:"menuitemcheckbox","aria-checked":e,"aria-describedby":p.description!=null?f:void 0,tabIndex:-1,"aria-disabled":a||void 0,"aria-keyshortcuts":d,"data-menu-item":"","data-menu-text":s,className:E.cn(O,t&&q,u),...m,children:n===void 0?T(p,c.jsx("span",{className:e?void 0:"rst:invisible","data-menu-check":"",children:c.jsx(Ae,{})}),void 0,f):T(p,void 0,c.jsx("span",{"aria-hidden":"true",className:"rst:ms-auto rst:flex rst:shrink-0 rst:items-center",children:n}),f)})}function Be({value:e,onValueChange:r,label:n,children:o,className:a}){return c.jsx(V.Provider,{value:{value:e,onValueChange:r},children:c.jsx(ae,{label:n,className:a,children:o})})}function _e({value:e,closeOnSelect:r=!0,disabled:n,destructive:o,keyshortcuts:a,textValue:t,className:d,...s}){const u=i.useContext(V);if(!u)throw new Error("<MenuRadioItem> must be inside a <MenuRadioGroup>.");const p=u.value===e,m=z({disabled:n,closeOnSelect:r,spaceKeepsOpen:!0,onChoose:()=>u.onValueChange?.(e)}),f=i.useId();return c.jsx("button",{type:"button",role:"menuitemradio","aria-checked":p,"aria-describedby":s.description!=null?f:void 0,tabIndex:-1,"aria-disabled":n||void 0,"aria-keyshortcuts":a,"data-menu-item":"","data-menu-text":t,className:E.cn(O,o&&q,d),...m,children:T(s,c.jsx("span",{className:p?void 0:"rst:invisible","data-menu-check":"",children:c.jsx(De,{})}),void 0,f)})}function ae({label:e,children:r,className:n}){const o=i.useId();return c.jsxs("div",{role:"group","aria-labelledby":e?o:void 0,className:n,children:[e&&c.jsx("div",{id:o,className:"rst:px-3 rst:pt-2 rst:pb-1 rst:text-xs rst:font-semibold rst:text-gray-600 rst:dark:text-gray-400","data-menu-heading":"",children:e}),r]})}function Ke({className:e}){return c.jsx("div",{role:"separator",className:E.cn("rst:my-1 rst:h-[var(--roster-border-width,1px)] rst:bg-[var(--roster-popover-border)]",e)})}function $e({label:e,children:r,icon:n,disabled:o,textValue:a,className:t,panelClassName:d}){const s=R("MenuSubmenu"),u=K("MenuSubmenu"),p=i.useId(),m=`${p}-item`,f=`${p}-menu`,l=u.openSubmenu===m,b=i.useRef(null),[w,g]=i.useState(null),I=i.useCallback(v=>{b.current=v,g(v)},[]),h=i.useRef(null),M=i.useRef(void 0),j=i.useRef("mouse"),{mounted:P,closed:x,leaving:y}=ee(l),k=$(w),{setPanel:C,panelEl:N,floatingStyles:ie,placement:ue}=te(w,P,k?"left-start":"right-start",{mainAxis:0,alignmentAxis:-4},h,!0),ce=se();i.useEffect(()=>()=>window.clearTimeout(M.current),[]);const F=()=>{u.setOpenSubmenu(null),b.current?.focus({preventScroll:!0})},{typedRef:le,typingAhead:de}=ne(),fe=oe({panelRef:h,typedRef:le,onEscape:F,onBack:F});i.useLayoutEffect(()=>{!l||!N||u.focusFirstInSubmenu.current&&S(L(N)[0])},[l,N,u.focusFirstInSubmenu]);const B=v=>{if(!o){if(l&&v&&h.current){S(L(h.current)[0]);return}u.setOpenSubmenu(m,v)}},me=!!s.triggerEl?.closest(".dark");return c.jsxs(c.Fragment,{children:[c.jsx("button",{ref:I,id:m,type:"button",role:"menuitem",tabIndex:-1,"aria-haspopup":"menu","aria-expanded":l,"aria-controls":l?f:void 0,"aria-disabled":o||void 0,"data-menu-item":"","data-menu-text":a,"data-menu-tree":s.treeId,className:E.cn(O,l&&"rst:bg-gray-100 rst:dark:bg-gray-700/50",t),onPointerDown:v=>{j.current=v.pointerType},onClick:()=>l&&j.current!=="mouse"?u.setOpenSubmenu(null):B(!1),onKeyDown:v=>{const pe=k?"ArrowLeft":"ArrowRight";v.key===" "&&u.typingAhead()||(v.key===pe||v.key==="Enter"||v.key===" ")&&(v.preventDefault(),B(!0))},onPointerMove:v=>{X(v)&&(u.hoverItem(m),document.activeElement!==v.currentTarget&&v.currentTarget.focus({preventScroll:!0}),!l&&!o&&(window.clearTimeout(M.current),M.current=window.setTimeout(()=>B(!1),Y)))},onPointerLeave:()=>window.clearTimeout(M.current),children:T({icon:n,children:e},void 0,c.jsx("span",{"aria-hidden":"true",className:"rst:ms-auto rst:flex rst:shrink-0 rst:items-center rst:opacity-70","data-menu-chevron":"",children:c.jsx(Le,{})}))}),P&&c.jsx(W.Portal,{children:c.jsx(_.Provider,{value:{...ce,panelRef:h,typingAhead:de},children:c.jsx("div",{ref:C,id:f,dir:k?"rtl":"ltr",role:"menu","aria-labelledby":m,tabIndex:-1,"data-menu-panel":"","data-menu-tree":s.treeId,"data-closed":x?"":void 0,"data-leaving":y?"":void 0,onKeyDown:fe,onPointerEnter:()=>u.hoverItem(m),style:{...ie,...J,transformOrigin:Q(ue,k)},className:E.cn(me&&"dark",Z,d),children:r})})})]})}exports.Menu=Te;exports.MenuButton=Re;exports.MenuCheckboxItem=Ne;exports.MenuGroup=ae;exports.MenuItem=Oe;exports.MenuItems=Ce;exports.MenuRadioGroup=Be;exports.MenuRadioItem=_e;exports.MenuSeparator=Ke;exports.MenuSubmenu=$e;
@@ -0,0 +1,169 @@
1
+ import { ButtonProps } from '../../atoms/Button/Button';
2
+ import * as React from "react";
3
+ /**
4
+ * The props every link item is rendered with. `href` and `to` carry the same
5
+ * value, so `next/link`, React Router's `Link` and a plain `<a>` all work
6
+ * without a wrapper. The rest must reach the DOM: the role, the tab index and
7
+ * the handlers are what make the link an item of the menu.
8
+ */
9
+ export interface MenuLinkProps {
10
+ href: string;
11
+ to: string;
12
+ className: string;
13
+ children: React.ReactNode;
14
+ role: "menuitem";
15
+ tabIndex: -1;
16
+ "aria-disabled"?: true;
17
+ "aria-keyshortcuts"?: string;
18
+ "aria-describedby"?: string;
19
+ "data-menu-item": "";
20
+ onClick: (event: React.MouseEvent<HTMLAnchorElement>) => void;
21
+ onKeyDown: (event: React.KeyboardEvent<HTMLAnchorElement>) => void;
22
+ onPointerMove: (event: React.PointerEvent<HTMLAnchorElement>) => void;
23
+ }
24
+ export interface MenuProps {
25
+ /** The trigger (`MenuButton`) and the panel (`MenuItems`). */
26
+ children: React.ReactNode;
27
+ /**
28
+ * Controlled open state. Leave both off to let the menu keep its own. Pass
29
+ * `onOpenChange` with `open`: every way the menu closes itself (Escape,
30
+ * Tab, a press outside, a choice) is a call to it.
31
+ */
32
+ open?: boolean;
33
+ onOpenChange?: (open: boolean) => void;
34
+ /**
35
+ * Renders every link item (a `MenuItem` with an `href`). Defaults to a plain
36
+ * `<a>`, which inside a router turns each choice into a full page load: pass
37
+ * `next/link` or your router's link, from a client component.
38
+ */
39
+ linkComponent?: React.ComponentType<MenuLinkProps>;
40
+ }
41
+ /**
42
+ * A button that opens a panel of actions: the menu button pattern. Compose it:
43
+ *
44
+ * ```tsx
45
+ * <Menu>
46
+ * <MenuButton>Actions</MenuButton>
47
+ * <MenuItems>
48
+ * <MenuItem icon={<EditIcon />} shortcut="⌘E" onSelect={edit}>Edit</MenuItem>
49
+ * <MenuSeparator />
50
+ * <MenuItem destructive onSelect={remove}>Delete</MenuItem>
51
+ * </MenuItems>
52
+ * </Menu>
53
+ * ```
54
+ *
55
+ * The keyboard follows the pattern: Enter, Space or Down open it on the first
56
+ * item and Up on the last; arrows move, Home and End jump, a typed letter
57
+ * jumps to the next item starting with it; Escape closes it and puts focus
58
+ * back on the button; Tab closes it and moves on. A submenu opens with the
59
+ * arrow away from the parent and closes with the arrow back.
60
+ */
61
+ declare function Menu({ children, open: openProp, onOpenChange, linkComponent }: MenuProps): import("react/jsx-runtime").JSX.Element;
62
+ export interface MenuButtonProps extends ButtonProps {
63
+ /**
64
+ * A plain `<button>` with only your `className`, for a trigger drawn its own
65
+ * way: an avatar, an icon. Keep its target at least 44 by 44, with
66
+ * padding or a hit area, if you draw it smaller.
67
+ */
68
+ plain?: boolean;
69
+ }
70
+ declare const MenuButton: React.ForwardRefExoticComponent<MenuButtonProps & React.RefAttributes<HTMLButtonElement>>;
71
+ export interface MenuItemsProps {
72
+ children: React.ReactNode;
73
+ /** Which edge of the button the panel lines up with. */
74
+ align?: "start" | "end";
75
+ /** The gap between the button and the panel, in px. */
76
+ offset?: number;
77
+ /** Names the menu when the button's own name shouldn't. By default the button names it. */
78
+ "aria-label"?: string;
79
+ /** Applied to the panel. Its surface reads `--roster-popover-*`; set those to repaint it. */
80
+ className?: string;
81
+ }
82
+ declare function MenuItems({ children, align, offset, className, ...aria }: MenuItemsProps): import("react/jsx-runtime").JSX.Element | null;
83
+ interface ItemContent {
84
+ /** A leading icon. Decorative: the item's words name it. */
85
+ icon?: React.ReactNode;
86
+ /** A second, quieter line under the label: what the item does, or to what. Read as the item's description. */
87
+ description?: React.ReactNode;
88
+ /** A count or a status at the end of the row, read with the item's name. */
89
+ badge?: React.ReactNode;
90
+ /** A keyboard shortcut to show, right-aligned: display only. The app handles the keys. */
91
+ shortcut?: string;
92
+ /** The same shortcut in `aria-keyshortcuts` form ("Control+E"), for assistive technology. */
93
+ keyshortcuts?: string;
94
+ /** Reads as a consequence: red. The words still have to say what it does. */
95
+ destructive?: boolean;
96
+ /** Can be reached by the arrows but not chosen. */
97
+ disabled?: boolean;
98
+ /** What typeahead matches, when the item's text isn't the right thing to match. */
99
+ textValue?: string;
100
+ className?: string;
101
+ children: React.ReactNode;
102
+ }
103
+ export interface MenuItemProps extends ItemContent {
104
+ /** Called when the item is chosen: a click, Enter or Space. */
105
+ onSelect?: (event: React.SyntheticEvent) => void;
106
+ /** Makes it a link item. It navigates through the menu's `linkComponent`. */
107
+ href?: string;
108
+ /** Close the menu once chosen. On by default. */
109
+ closeOnSelect?: boolean;
110
+ }
111
+ /** One action. With `href`, a link. */
112
+ declare function MenuItem({ onSelect, href, closeOnSelect, disabled, destructive, keyshortcuts, textValue, className, ...content }: MenuItemProps): import("react/jsx-runtime").JSX.Element;
113
+ export interface MenuCheckboxItemProps extends ItemContent {
114
+ checked: boolean;
115
+ onCheckedChange: (checked: boolean) => void;
116
+ /**
117
+ * Replaces the leading check mark with an indicator of your own at the end
118
+ * of the row: a switch's track, say. Its state still reaches assistive
119
+ * technology through `aria-checked`.
120
+ */
121
+ indicator?: React.ReactNode;
122
+ /** Close the menu once chosen by click or Enter. Space always keeps it open. */
123
+ closeOnSelect?: boolean;
124
+ }
125
+ /** An on/off choice: `menuitemcheckbox`. */
126
+ declare function MenuCheckboxItem({ checked, onCheckedChange, indicator, closeOnSelect, disabled, destructive, keyshortcuts, textValue, className, ...content }: MenuCheckboxItemProps): import("react/jsx-runtime").JSX.Element;
127
+ export interface MenuRadioGroupProps {
128
+ value: string | undefined;
129
+ onValueChange: (value: string) => void;
130
+ /** The choice's name, shown above its items and read with them. */
131
+ label?: React.ReactNode;
132
+ children: React.ReactNode;
133
+ className?: string;
134
+ }
135
+ /** One choice among several: its items are `menuitemradio`. */
136
+ declare function MenuRadioGroup({ value, onValueChange, label, children, className }: MenuRadioGroupProps): import("react/jsx-runtime").JSX.Element;
137
+ export interface MenuRadioItemProps extends ItemContent {
138
+ value: string;
139
+ /** Close the menu once chosen by click or Enter. Space always keeps it open. */
140
+ closeOnSelect?: boolean;
141
+ }
142
+ declare function MenuRadioItem({ value, closeOnSelect, disabled, destructive, keyshortcuts, textValue, className, ...content }: MenuRadioItemProps): import("react/jsx-runtime").JSX.Element;
143
+ export interface MenuGroupProps {
144
+ /** Shown above the group's items, and names the group. */
145
+ label?: React.ReactNode;
146
+ children: React.ReactNode;
147
+ className?: string;
148
+ }
149
+ /** Items that belong together, under an optional label. */
150
+ declare function MenuGroup({ label, children, className }: MenuGroupProps): import("react/jsx-runtime").JSX.Element;
151
+ /** A rule between groups of items. */
152
+ declare function MenuSeparator({ className }: {
153
+ className?: string;
154
+ }): import("react/jsx-runtime").JSX.Element;
155
+ export interface MenuSubmenuProps extends Omit<ItemContent, "shortcut" | "keyshortcuts" | "children" | "destructive" | "description" | "badge"> {
156
+ /** The item that opens it. */
157
+ label: React.ReactNode;
158
+ /** Its items. */
159
+ children: React.ReactNode;
160
+ /** Applied to the submenu's panel. */
161
+ panelClassName?: string;
162
+ }
163
+ /**
164
+ * An item that opens a menu of its own beside it. It opens with the arrow away
165
+ * from its parent, Enter, Space, a click, or the pointer resting on it; the
166
+ * arrow back, or Escape, closes it and returns to its item.
167
+ */
168
+ declare function MenuSubmenu({ label, children, icon, disabled, textValue, className, panelClassName }: MenuSubmenuProps): import("react/jsx-runtime").JSX.Element;
169
+ export { Menu, MenuButton, MenuItems, MenuItem, MenuCheckboxItem, MenuRadioGroup, MenuRadioItem, MenuGroup, MenuSeparator, MenuSubmenu, };