@medialane/ui 0.126.10 → 0.126.11

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.
@@ -54,6 +54,7 @@ const MODE_OPTIONS = [
54
54
  ];
55
55
  function LaunchpadPublishHero({
56
56
  imagePreview,
57
+ imageUri,
57
58
  imageUploading = false,
58
59
  onFileSelect,
59
60
  onClearImage,
@@ -65,7 +66,8 @@ function LaunchpadPublishHero({
65
66
  className
66
67
  }) {
67
68
  const fileInputRef = (0, import_react.useRef)(null);
68
- const ready = !!imagePreview && name.trim().length > 0 && !imageUploading;
69
+ const uploadFailed = !!imagePreview && !imageUploading && !imageUri;
70
+ const ready = !!imageUri && name.trim().length > 0 && !imageUploading;
69
71
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", { className: (0, import_cn.cn)("rounded-3xl bg-brand-blue/5 p-6 sm:p-10", className), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "max-w-xl mx-auto space-y-6", children: [
70
72
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5 text-center", children: [
71
73
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-2xl sm:text-3xl font-bold tracking-tight", children: "Publish your work" }),
@@ -132,6 +134,7 @@ function LaunchpadPublishHero({
132
134
  ]
133
135
  }
134
136
  ),
137
+ uploadFailed && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-destructive text-center -mt-2", children: "Upload failed \u2014 remove the file and try again." }),
135
138
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
136
139
  "input",
137
140
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/launchpad-publish-hero.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRef } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { ImagePlus, Layers, Loader2, ArrowRight, X } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\n\nexport type LaunchpadPublishMode = \"single\" | \"editions\";\n\nexport interface LaunchpadPublishHeroProps {\n\n imagePreview: string | null;\n\n imageUploading?: boolean;\n\n onFileSelect: (file: File) => void;\n\n onClearImage: () => void;\n\n name: string;\n\n onNameChange: (value: string) => void;\n\n mode: LaunchpadPublishMode;\n\n onModeChange: (mode: LaunchpadPublishMode) => void;\n\n continueHref: string;\n\n className?: string;\n}\n\nconst MODE_OPTIONS: { value: LaunchpadPublishMode; icon: typeof ImagePlus; label: string; blurb: string }[] = [\n {\n value: \"single\",\n icon: ImagePlus,\n label: \"One copy\",\n blurb: \"Minted once. For a single photo, song, or document.\",\n },\n {\n value: \"editions\",\n icon: Layers,\n label: \"Numbered copies\",\n blurb: \"Release the same work as several numbered pieces.\",\n },\n];\n\nexport function LaunchpadPublishHero({\n imagePreview,\n imageUploading = false,\n onFileSelect,\n onClearImage,\n name,\n onNameChange,\n mode,\n onModeChange,\n continueHref,\n className,\n}: LaunchpadPublishHeroProps) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n const ready = !!imagePreview && name.trim().length > 0 && !imageUploading;\n\n return (\n <section className={cn(\"rounded-3xl bg-brand-blue/5 p-6 sm:p-10\", className)}>\n <div className=\"max-w-xl mx-auto space-y-6\">\n <div className=\"space-y-1.5 text-center\">\n <h2 className=\"text-2xl sm:text-3xl font-bold tracking-tight\">Publish your work</h2>\n <p className=\"text-sm text-muted-foreground\">\n Upload a file, give it a name, and choose how many copies exist. Everything else can wait.\n </p>\n </div>\n\n <div\n role=\"button\"\n tabIndex={0}\n aria-label=\"Upload a file\"\n onClick={() => !imageUploading && fileInputRef.current?.click()}\n onKeyDown={(e) => {\n if ((e.key === \"Enter\" || e.key === \" \") && !imageUploading) {\n e.preventDefault();\n fileInputRef.current?.click();\n }\n }}\n onDragOver={(e) => e.preventDefault()}\n onDrop={(e) => {\n e.preventDefault();\n const file = e.dataTransfer.files?.[0];\n if (file) onFileSelect(file);\n }}\n className={cn(\n \"relative flex flex-col items-center justify-center gap-2 rounded-2xl bg-card\",\n \"h-48 sm:h-56 cursor-pointer overflow-hidden transition-colors\",\n imagePreview ? \"\" : \"hover:bg-card/70\",\n )}\n >\n {imagePreview ? (\n <>\n <Image src={imagePreview} alt=\"\" fill className=\"object-cover\" unoptimized />\n {!imageUploading && (\n <button\n type=\"button\"\n aria-label=\"Remove file\"\n onClick={(e) => { e.stopPropagation(); onClearImage(); }}\n className=\"absolute top-3 right-3 flex h-8 w-8 items-center justify-center rounded-full bg-background/80 backdrop-blur-sm text-foreground hover:bg-background transition-colors\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n {imageUploading && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-background/60\">\n <Loader2 className=\"h-6 w-6 animate-spin\" />\n </div>\n )}\n </>\n ) : (\n <>\n <ImagePlus className=\"h-8 w-8 text-muted-foreground\" />\n <p className=\"text-sm font-medium\">Drop a file, or click to upload</p>\n <p className=\"text-xs text-muted-foreground\">Image, audio, video, or document · max 10 MB</p>\n </>\n )}\n <input\n ref={fileInputRef}\n type=\"file\"\n className=\"hidden\"\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (file) onFileSelect(file);\n }}\n />\n </div>\n\n <input\n value={name}\n onChange={(e) => onNameChange(e.target.value)}\n placeholder=\"Name your work\"\n className=\"w-full h-12 rounded-xl bg-card px-4 text-base font-medium placeholder:text-muted-foreground placeholder:font-normal focus:outline-none focus:ring-2 focus:ring-brand-blue/40\"\n />\n\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n {MODE_OPTIONS.map(({ value, icon: Icon, label, blurb }) => {\n const selected = mode === value;\n return (\n <button\n key={value}\n type=\"button\"\n onClick={() => onModeChange(value)}\n aria-pressed={selected}\n className={cn(\n \"flex items-start gap-3 rounded-2xl p-4 text-left transition-all\",\n selected ? \"bg-brand-blue text-white\" : \"bg-card hover:bg-card/70\",\n )}\n >\n <Icon className={cn(\"h-5 w-5 shrink-0 mt-0.5\", selected ? \"text-white\" : \"text-muted-foreground\")} />\n <span>\n <span className=\"block text-sm font-semibold\">{label}</span>\n <span className={cn(\"block text-xs mt-0.5\", selected ? \"text-white/80\" : \"text-muted-foreground\")}>\n {blurb}\n </span>\n </span>\n </button>\n );\n })}\n </div>\n\n <Link\n href={ready ? continueHref : \"#\"}\n aria-disabled={!ready}\n onClick={(e) => { if (!ready) e.preventDefault(); }}\n className={cn(\n \"flex items-center justify-center gap-1.5 w-full h-12 rounded-xl text-base font-semibold text-white transition-all\",\n ready ? \"bg-brand-blue hover:brightness-110 active:scale-[0.98]\" : \"bg-brand-blue/40 cursor-not-allowed\",\n )}\n >\n Continue\n <ArrowRight className=\"h-4 w-4\" />\n </Link>\n </div>\n </section>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkEQ;AAhER,mBAAuB;AACvB,kBAAiB;AACjB,mBAAkB;AAClB,0BAA0D;AAC1D,gBAAmB;AA2BnB,MAAM,eAAwG;AAAA,EAC5G;AAAA,IACE,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AACF;AAEO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA8B;AAC5B,QAAM,mBAAe,qBAAyB,IAAI;AAClD,QAAM,QAAQ,CAAC,CAAC,gBAAgB,KAAK,KAAK,EAAE,SAAS,KAAK,CAAC;AAE3D,SACE,4CAAC,aAAQ,eAAW,cAAG,2CAA2C,SAAS,GACzE,uDAAC,SAAI,WAAU,8BACb;AAAA,iDAAC,SAAI,WAAU,2BACb;AAAA,kDAAC,QAAG,WAAU,iDAAgD,+BAAiB;AAAA,MAC/E,4CAAC,OAAE,WAAU,iCAAgC,wGAE7C;AAAA,OACF;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,UAAU;AAAA,QACV,cAAW;AAAA,QACX,SAAS,MAAM,CAAC,kBAAkB,aAAa,SAAS,MAAM;AAAA,QAC9D,WAAW,CAAC,MAAM;AAChB,eAAK,EAAE,QAAQ,WAAW,EAAE,QAAQ,QAAQ,CAAC,gBAAgB;AAC3D,cAAE,eAAe;AACjB,yBAAa,SAAS,MAAM;AAAA,UAC9B;AAAA,QACF;AAAA,QACA,YAAY,CAAC,MAAM,EAAE,eAAe;AAAA,QACpC,QAAQ,CAAC,MAAM;AACb,YAAE,eAAe;AACjB,gBAAM,OAAO,EAAE,aAAa,QAAQ,CAAC;AACrC,cAAI,KAAM,cAAa,IAAI;AAAA,QAC7B;AAAA,QACA,eAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA,eAAe,KAAK;AAAA,QACtB;AAAA,QAEC;AAAA,yBACC,4EACE;AAAA,wDAAC,aAAAA,SAAA,EAAM,KAAK,cAAc,KAAI,IAAG,MAAI,MAAC,WAAU,gBAAe,aAAW,MAAC;AAAA,YAC1E,CAAC,kBACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,cAAW;AAAA,gBACX,SAAS,CAAC,MAAM;AAAE,oBAAE,gBAAgB;AAAG,+BAAa;AAAA,gBAAG;AAAA,gBACvD,WAAU;AAAA,gBAEV,sDAAC,yBAAE,WAAU,WAAU;AAAA;AAAA,YACzB;AAAA,YAED,kBACC,4CAAC,SAAI,WAAU,sEACb,sDAAC,+BAAQ,WAAU,wBAAuB,GAC5C;AAAA,aAEJ,IAEA,4EACE;AAAA,wDAAC,iCAAU,WAAU,iCAAgC;AAAA,YACrD,4CAAC,OAAE,WAAU,uBAAsB,6CAA+B;AAAA,YAClE,4CAAC,OAAE,WAAU,iCAAgC,6DAA4C;AAAA,aAC3F;AAAA,UAEF;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,MAAK;AAAA,cACL,WAAU;AAAA,cACV,UAAU,CAAC,MAAM;AACf,sBAAM,OAAO,EAAE,OAAO,QAAQ,CAAC;AAC/B,oBAAI,KAAM,cAAa,IAAI;AAAA,cAC7B;AAAA;AAAA,UACF;AAAA;AAAA;AAAA,IACF;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,QACP,UAAU,CAAC,MAAM,aAAa,EAAE,OAAO,KAAK;AAAA,QAC5C,aAAY;AAAA,QACZ,WAAU;AAAA;AAAA,IACZ;AAAA,IAEA,4CAAC,SAAI,WAAU,yCACZ,uBAAa,IAAI,CAAC,EAAE,OAAO,MAAM,MAAM,OAAO,MAAM,MAAM;AACzD,YAAM,WAAW,SAAS;AAC1B,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,SAAS,MAAM,aAAa,KAAK;AAAA,UACjC,gBAAc;AAAA,UACd,eAAW;AAAA,YACT;AAAA,YACA,WAAW,6BAA6B;AAAA,UAC1C;AAAA,UAEA;AAAA,wDAAC,QAAK,eAAW,cAAG,2BAA2B,WAAW,eAAe,uBAAuB,GAAG;AAAA,YACnG,6CAAC,UACC;AAAA,0DAAC,UAAK,WAAU,+BAA+B,iBAAM;AAAA,cACrD,4CAAC,UAAK,eAAW,cAAG,wBAAwB,WAAW,kBAAkB,uBAAuB,GAC7F,iBACH;AAAA,eACF;AAAA;AAAA;AAAA,QAfK;AAAA,MAgBP;AAAA,IAEJ,CAAC,GACH;AAAA,IAEA;AAAA,MAAC,YAAAC;AAAA,MAAA;AAAA,QACC,MAAM,QAAQ,eAAe;AAAA,QAC7B,iBAAe,CAAC;AAAA,QAChB,SAAS,CAAC,MAAM;AAAE,cAAI,CAAC,MAAO,GAAE,eAAe;AAAA,QAAG;AAAA,QAClD,eAAW;AAAA,UACT;AAAA,UACA,QAAQ,2DAA2D;AAAA,QACrE;AAAA,QACD;AAAA;AAAA,UAEC,4CAAC,kCAAW,WAAU,WAAU;AAAA;AAAA;AAAA,IAClC;AAAA,KACF,GACF;AAEJ;","names":["Image","Link"]}
1
+ {"version":3,"sources":["../../src/components/launchpad-publish-hero.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRef } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { ImagePlus, Layers, Loader2, ArrowRight, X } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\n\nexport type LaunchpadPublishMode = \"single\" | \"editions\";\n\nexport interface LaunchpadPublishHeroProps {\n\n imagePreview: string | null;\n\n imageUri: string | null;\n\n imageUploading?: boolean;\n\n onFileSelect: (file: File) => void;\n\n onClearImage: () => void;\n\n name: string;\n\n onNameChange: (value: string) => void;\n\n mode: LaunchpadPublishMode;\n\n onModeChange: (mode: LaunchpadPublishMode) => void;\n\n continueHref: string;\n\n className?: string;\n}\n\nconst MODE_OPTIONS: { value: LaunchpadPublishMode; icon: typeof ImagePlus; label: string; blurb: string }[] = [\n {\n value: \"single\",\n icon: ImagePlus,\n label: \"One copy\",\n blurb: \"Minted once. For a single photo, song, or document.\",\n },\n {\n value: \"editions\",\n icon: Layers,\n label: \"Numbered copies\",\n blurb: \"Release the same work as several numbered pieces.\",\n },\n];\n\nexport function LaunchpadPublishHero({\n imagePreview,\n imageUri,\n imageUploading = false,\n onFileSelect,\n onClearImage,\n name,\n onNameChange,\n mode,\n onModeChange,\n continueHref,\n className,\n}: LaunchpadPublishHeroProps) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n const uploadFailed = !!imagePreview && !imageUploading && !imageUri;\n const ready = !!imageUri && name.trim().length > 0 && !imageUploading;\n\n return (\n <section className={cn(\"rounded-3xl bg-brand-blue/5 p-6 sm:p-10\", className)}>\n <div className=\"max-w-xl mx-auto space-y-6\">\n <div className=\"space-y-1.5 text-center\">\n <h2 className=\"text-2xl sm:text-3xl font-bold tracking-tight\">Publish your work</h2>\n <p className=\"text-sm text-muted-foreground\">\n Upload a file, give it a name, and choose how many copies exist. Everything else can wait.\n </p>\n </div>\n\n <div\n role=\"button\"\n tabIndex={0}\n aria-label=\"Upload a file\"\n onClick={() => !imageUploading && fileInputRef.current?.click()}\n onKeyDown={(e) => {\n if ((e.key === \"Enter\" || e.key === \" \") && !imageUploading) {\n e.preventDefault();\n fileInputRef.current?.click();\n }\n }}\n onDragOver={(e) => e.preventDefault()}\n onDrop={(e) => {\n e.preventDefault();\n const file = e.dataTransfer.files?.[0];\n if (file) onFileSelect(file);\n }}\n className={cn(\n \"relative flex flex-col items-center justify-center gap-2 rounded-2xl bg-card\",\n \"h-48 sm:h-56 cursor-pointer overflow-hidden transition-colors\",\n imagePreview ? \"\" : \"hover:bg-card/70\",\n )}\n >\n {imagePreview ? (\n <>\n <Image src={imagePreview} alt=\"\" fill className=\"object-cover\" unoptimized />\n {!imageUploading && (\n <button\n type=\"button\"\n aria-label=\"Remove file\"\n onClick={(e) => { e.stopPropagation(); onClearImage(); }}\n className=\"absolute top-3 right-3 flex h-8 w-8 items-center justify-center rounded-full bg-background/80 backdrop-blur-sm text-foreground hover:bg-background transition-colors\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n {imageUploading && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-background/60\">\n <Loader2 className=\"h-6 w-6 animate-spin\" />\n </div>\n )}\n </>\n ) : (\n <>\n <ImagePlus className=\"h-8 w-8 text-muted-foreground\" />\n <p className=\"text-sm font-medium\">Drop a file, or click to upload</p>\n <p className=\"text-xs text-muted-foreground\">Image, audio, video, or document · max 10 MB</p>\n </>\n )}\n <input\n ref={fileInputRef}\n type=\"file\"\n className=\"hidden\"\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (file) onFileSelect(file);\n }}\n />\n </div>\n {uploadFailed && (\n <p className=\"text-xs text-destructive text-center -mt-2\">\n Upload failed — remove the file and try again.\n </p>\n )}\n\n <input\n value={name}\n onChange={(e) => onNameChange(e.target.value)}\n placeholder=\"Name your work\"\n className=\"w-full h-12 rounded-xl bg-card px-4 text-base font-medium placeholder:text-muted-foreground placeholder:font-normal focus:outline-none focus:ring-2 focus:ring-brand-blue/40\"\n />\n\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n {MODE_OPTIONS.map(({ value, icon: Icon, label, blurb }) => {\n const selected = mode === value;\n return (\n <button\n key={value}\n type=\"button\"\n onClick={() => onModeChange(value)}\n aria-pressed={selected}\n className={cn(\n \"flex items-start gap-3 rounded-2xl p-4 text-left transition-all\",\n selected ? \"bg-brand-blue text-white\" : \"bg-card hover:bg-card/70\",\n )}\n >\n <Icon className={cn(\"h-5 w-5 shrink-0 mt-0.5\", selected ? \"text-white\" : \"text-muted-foreground\")} />\n <span>\n <span className=\"block text-sm font-semibold\">{label}</span>\n <span className={cn(\"block text-xs mt-0.5\", selected ? \"text-white/80\" : \"text-muted-foreground\")}>\n {blurb}\n </span>\n </span>\n </button>\n );\n })}\n </div>\n\n <Link\n href={ready ? continueHref : \"#\"}\n aria-disabled={!ready}\n onClick={(e) => { if (!ready) e.preventDefault(); }}\n className={cn(\n \"flex items-center justify-center gap-1.5 w-full h-12 rounded-xl text-base font-semibold text-white transition-all\",\n ready ? \"bg-brand-blue hover:brightness-110 active:scale-[0.98]\" : \"bg-brand-blue/40 cursor-not-allowed\",\n )}\n >\n Continue\n <ArrowRight className=\"h-4 w-4\" />\n </Link>\n </div>\n </section>\n );\n}\n"],"mappings":"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","names":["Image","Link"]}
@@ -3,6 +3,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  type LaunchpadPublishMode = "single" | "editions";
4
4
  interface LaunchpadPublishHeroProps {
5
5
  imagePreview: string | null;
6
+ imageUri: string | null;
6
7
  imageUploading?: boolean;
7
8
  onFileSelect: (file: File) => void;
8
9
  onClearImage: () => void;
@@ -13,6 +14,6 @@ interface LaunchpadPublishHeroProps {
13
14
  continueHref: string;
14
15
  className?: string;
15
16
  }
16
- declare function LaunchpadPublishHero({ imagePreview, imageUploading, onFileSelect, onClearImage, name, onNameChange, mode, onModeChange, continueHref, className, }: LaunchpadPublishHeroProps): react_jsx_runtime.JSX.Element;
17
+ declare function LaunchpadPublishHero({ imagePreview, imageUri, imageUploading, onFileSelect, onClearImage, name, onNameChange, mode, onModeChange, continueHref, className, }: LaunchpadPublishHeroProps): react_jsx_runtime.JSX.Element;
17
18
 
18
19
  export { LaunchpadPublishHero, type LaunchpadPublishHeroProps, type LaunchpadPublishMode };
@@ -3,6 +3,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  type LaunchpadPublishMode = "single" | "editions";
4
4
  interface LaunchpadPublishHeroProps {
5
5
  imagePreview: string | null;
6
+ imageUri: string | null;
6
7
  imageUploading?: boolean;
7
8
  onFileSelect: (file: File) => void;
8
9
  onClearImage: () => void;
@@ -13,6 +14,6 @@ interface LaunchpadPublishHeroProps {
13
14
  continueHref: string;
14
15
  className?: string;
15
16
  }
16
- declare function LaunchpadPublishHero({ imagePreview, imageUploading, onFileSelect, onClearImage, name, onNameChange, mode, onModeChange, continueHref, className, }: LaunchpadPublishHeroProps): react_jsx_runtime.JSX.Element;
17
+ declare function LaunchpadPublishHero({ imagePreview, imageUri, imageUploading, onFileSelect, onClearImage, name, onNameChange, mode, onModeChange, continueHref, className, }: LaunchpadPublishHeroProps): react_jsx_runtime.JSX.Element;
17
18
 
18
19
  export { LaunchpadPublishHero, type LaunchpadPublishHeroProps, type LaunchpadPublishMode };
@@ -21,6 +21,7 @@ const MODE_OPTIONS = [
21
21
  ];
22
22
  function LaunchpadPublishHero({
23
23
  imagePreview,
24
+ imageUri,
24
25
  imageUploading = false,
25
26
  onFileSelect,
26
27
  onClearImage,
@@ -32,7 +33,8 @@ function LaunchpadPublishHero({
32
33
  className
33
34
  }) {
34
35
  const fileInputRef = useRef(null);
35
- const ready = !!imagePreview && name.trim().length > 0 && !imageUploading;
36
+ const uploadFailed = !!imagePreview && !imageUploading && !imageUri;
37
+ const ready = !!imageUri && name.trim().length > 0 && !imageUploading;
36
38
  return /* @__PURE__ */ jsx("section", { className: cn("rounded-3xl bg-brand-blue/5 p-6 sm:p-10", className), children: /* @__PURE__ */ jsxs("div", { className: "max-w-xl mx-auto space-y-6", children: [
37
39
  /* @__PURE__ */ jsxs("div", { className: "space-y-1.5 text-center", children: [
38
40
  /* @__PURE__ */ jsx("h2", { className: "text-2xl sm:text-3xl font-bold tracking-tight", children: "Publish your work" }),
@@ -99,6 +101,7 @@ function LaunchpadPublishHero({
99
101
  ]
100
102
  }
101
103
  ),
104
+ uploadFailed && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive text-center -mt-2", children: "Upload failed \u2014 remove the file and try again." }),
102
105
  /* @__PURE__ */ jsx(
103
106
  "input",
104
107
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/launchpad-publish-hero.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRef } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { ImagePlus, Layers, Loader2, ArrowRight, X } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\n\nexport type LaunchpadPublishMode = \"single\" | \"editions\";\n\nexport interface LaunchpadPublishHeroProps {\n\n imagePreview: string | null;\n\n imageUploading?: boolean;\n\n onFileSelect: (file: File) => void;\n\n onClearImage: () => void;\n\n name: string;\n\n onNameChange: (value: string) => void;\n\n mode: LaunchpadPublishMode;\n\n onModeChange: (mode: LaunchpadPublishMode) => void;\n\n continueHref: string;\n\n className?: string;\n}\n\nconst MODE_OPTIONS: { value: LaunchpadPublishMode; icon: typeof ImagePlus; label: string; blurb: string }[] = [\n {\n value: \"single\",\n icon: ImagePlus,\n label: \"One copy\",\n blurb: \"Minted once. For a single photo, song, or document.\",\n },\n {\n value: \"editions\",\n icon: Layers,\n label: \"Numbered copies\",\n blurb: \"Release the same work as several numbered pieces.\",\n },\n];\n\nexport function LaunchpadPublishHero({\n imagePreview,\n imageUploading = false,\n onFileSelect,\n onClearImage,\n name,\n onNameChange,\n mode,\n onModeChange,\n continueHref,\n className,\n}: LaunchpadPublishHeroProps) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n const ready = !!imagePreview && name.trim().length > 0 && !imageUploading;\n\n return (\n <section className={cn(\"rounded-3xl bg-brand-blue/5 p-6 sm:p-10\", className)}>\n <div className=\"max-w-xl mx-auto space-y-6\">\n <div className=\"space-y-1.5 text-center\">\n <h2 className=\"text-2xl sm:text-3xl font-bold tracking-tight\">Publish your work</h2>\n <p className=\"text-sm text-muted-foreground\">\n Upload a file, give it a name, and choose how many copies exist. Everything else can wait.\n </p>\n </div>\n\n <div\n role=\"button\"\n tabIndex={0}\n aria-label=\"Upload a file\"\n onClick={() => !imageUploading && fileInputRef.current?.click()}\n onKeyDown={(e) => {\n if ((e.key === \"Enter\" || e.key === \" \") && !imageUploading) {\n e.preventDefault();\n fileInputRef.current?.click();\n }\n }}\n onDragOver={(e) => e.preventDefault()}\n onDrop={(e) => {\n e.preventDefault();\n const file = e.dataTransfer.files?.[0];\n if (file) onFileSelect(file);\n }}\n className={cn(\n \"relative flex flex-col items-center justify-center gap-2 rounded-2xl bg-card\",\n \"h-48 sm:h-56 cursor-pointer overflow-hidden transition-colors\",\n imagePreview ? \"\" : \"hover:bg-card/70\",\n )}\n >\n {imagePreview ? (\n <>\n <Image src={imagePreview} alt=\"\" fill className=\"object-cover\" unoptimized />\n {!imageUploading && (\n <button\n type=\"button\"\n aria-label=\"Remove file\"\n onClick={(e) => { e.stopPropagation(); onClearImage(); }}\n className=\"absolute top-3 right-3 flex h-8 w-8 items-center justify-center rounded-full bg-background/80 backdrop-blur-sm text-foreground hover:bg-background transition-colors\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n {imageUploading && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-background/60\">\n <Loader2 className=\"h-6 w-6 animate-spin\" />\n </div>\n )}\n </>\n ) : (\n <>\n <ImagePlus className=\"h-8 w-8 text-muted-foreground\" />\n <p className=\"text-sm font-medium\">Drop a file, or click to upload</p>\n <p className=\"text-xs text-muted-foreground\">Image, audio, video, or document · max 10 MB</p>\n </>\n )}\n <input\n ref={fileInputRef}\n type=\"file\"\n className=\"hidden\"\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (file) onFileSelect(file);\n }}\n />\n </div>\n\n <input\n value={name}\n onChange={(e) => onNameChange(e.target.value)}\n placeholder=\"Name your work\"\n className=\"w-full h-12 rounded-xl bg-card px-4 text-base font-medium placeholder:text-muted-foreground placeholder:font-normal focus:outline-none focus:ring-2 focus:ring-brand-blue/40\"\n />\n\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n {MODE_OPTIONS.map(({ value, icon: Icon, label, blurb }) => {\n const selected = mode === value;\n return (\n <button\n key={value}\n type=\"button\"\n onClick={() => onModeChange(value)}\n aria-pressed={selected}\n className={cn(\n \"flex items-start gap-3 rounded-2xl p-4 text-left transition-all\",\n selected ? \"bg-brand-blue text-white\" : \"bg-card hover:bg-card/70\",\n )}\n >\n <Icon className={cn(\"h-5 w-5 shrink-0 mt-0.5\", selected ? \"text-white\" : \"text-muted-foreground\")} />\n <span>\n <span className=\"block text-sm font-semibold\">{label}</span>\n <span className={cn(\"block text-xs mt-0.5\", selected ? \"text-white/80\" : \"text-muted-foreground\")}>\n {blurb}\n </span>\n </span>\n </button>\n );\n })}\n </div>\n\n <Link\n href={ready ? continueHref : \"#\"}\n aria-disabled={!ready}\n onClick={(e) => { if (!ready) e.preventDefault(); }}\n className={cn(\n \"flex items-center justify-center gap-1.5 w-full h-12 rounded-xl text-base font-semibold text-white transition-all\",\n ready ? \"bg-brand-blue hover:brightness-110 active:scale-[0.98]\" : \"bg-brand-blue/40 cursor-not-allowed\",\n )}\n >\n Continue\n <ArrowRight className=\"h-4 w-4\" />\n </Link>\n </div>\n </section>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/launchpad-publish-hero.tsx"],"sourcesContent":["\"use client\";\n\nimport { useRef } from \"react\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { ImagePlus, Layers, Loader2, ArrowRight, X } from \"lucide-react\";\nimport { cn } from \"../utils/cn.js\";\n\nexport type LaunchpadPublishMode = \"single\" | \"editions\";\n\nexport interface LaunchpadPublishHeroProps {\n\n imagePreview: string | null;\n\n imageUri: string | null;\n\n imageUploading?: boolean;\n\n onFileSelect: (file: File) => void;\n\n onClearImage: () => void;\n\n name: string;\n\n onNameChange: (value: string) => void;\n\n mode: LaunchpadPublishMode;\n\n onModeChange: (mode: LaunchpadPublishMode) => void;\n\n continueHref: string;\n\n className?: string;\n}\n\nconst MODE_OPTIONS: { value: LaunchpadPublishMode; icon: typeof ImagePlus; label: string; blurb: string }[] = [\n {\n value: \"single\",\n icon: ImagePlus,\n label: \"One copy\",\n blurb: \"Minted once. For a single photo, song, or document.\",\n },\n {\n value: \"editions\",\n icon: Layers,\n label: \"Numbered copies\",\n blurb: \"Release the same work as several numbered pieces.\",\n },\n];\n\nexport function LaunchpadPublishHero({\n imagePreview,\n imageUri,\n imageUploading = false,\n onFileSelect,\n onClearImage,\n name,\n onNameChange,\n mode,\n onModeChange,\n continueHref,\n className,\n}: LaunchpadPublishHeroProps) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n const uploadFailed = !!imagePreview && !imageUploading && !imageUri;\n const ready = !!imageUri && name.trim().length > 0 && !imageUploading;\n\n return (\n <section className={cn(\"rounded-3xl bg-brand-blue/5 p-6 sm:p-10\", className)}>\n <div className=\"max-w-xl mx-auto space-y-6\">\n <div className=\"space-y-1.5 text-center\">\n <h2 className=\"text-2xl sm:text-3xl font-bold tracking-tight\">Publish your work</h2>\n <p className=\"text-sm text-muted-foreground\">\n Upload a file, give it a name, and choose how many copies exist. Everything else can wait.\n </p>\n </div>\n\n <div\n role=\"button\"\n tabIndex={0}\n aria-label=\"Upload a file\"\n onClick={() => !imageUploading && fileInputRef.current?.click()}\n onKeyDown={(e) => {\n if ((e.key === \"Enter\" || e.key === \" \") && !imageUploading) {\n e.preventDefault();\n fileInputRef.current?.click();\n }\n }}\n onDragOver={(e) => e.preventDefault()}\n onDrop={(e) => {\n e.preventDefault();\n const file = e.dataTransfer.files?.[0];\n if (file) onFileSelect(file);\n }}\n className={cn(\n \"relative flex flex-col items-center justify-center gap-2 rounded-2xl bg-card\",\n \"h-48 sm:h-56 cursor-pointer overflow-hidden transition-colors\",\n imagePreview ? \"\" : \"hover:bg-card/70\",\n )}\n >\n {imagePreview ? (\n <>\n <Image src={imagePreview} alt=\"\" fill className=\"object-cover\" unoptimized />\n {!imageUploading && (\n <button\n type=\"button\"\n aria-label=\"Remove file\"\n onClick={(e) => { e.stopPropagation(); onClearImage(); }}\n className=\"absolute top-3 right-3 flex h-8 w-8 items-center justify-center rounded-full bg-background/80 backdrop-blur-sm text-foreground hover:bg-background transition-colors\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n {imageUploading && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-background/60\">\n <Loader2 className=\"h-6 w-6 animate-spin\" />\n </div>\n )}\n </>\n ) : (\n <>\n <ImagePlus className=\"h-8 w-8 text-muted-foreground\" />\n <p className=\"text-sm font-medium\">Drop a file, or click to upload</p>\n <p className=\"text-xs text-muted-foreground\">Image, audio, video, or document · max 10 MB</p>\n </>\n )}\n <input\n ref={fileInputRef}\n type=\"file\"\n className=\"hidden\"\n onChange={(e) => {\n const file = e.target.files?.[0];\n if (file) onFileSelect(file);\n }}\n />\n </div>\n {uploadFailed && (\n <p className=\"text-xs text-destructive text-center -mt-2\">\n Upload failed — remove the file and try again.\n </p>\n )}\n\n <input\n value={name}\n onChange={(e) => onNameChange(e.target.value)}\n placeholder=\"Name your work\"\n className=\"w-full h-12 rounded-xl bg-card px-4 text-base font-medium placeholder:text-muted-foreground placeholder:font-normal focus:outline-none focus:ring-2 focus:ring-brand-blue/40\"\n />\n\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n {MODE_OPTIONS.map(({ value, icon: Icon, label, blurb }) => {\n const selected = mode === value;\n return (\n <button\n key={value}\n type=\"button\"\n onClick={() => onModeChange(value)}\n aria-pressed={selected}\n className={cn(\n \"flex items-start gap-3 rounded-2xl p-4 text-left transition-all\",\n selected ? \"bg-brand-blue text-white\" : \"bg-card hover:bg-card/70\",\n )}\n >\n <Icon className={cn(\"h-5 w-5 shrink-0 mt-0.5\", selected ? \"text-white\" : \"text-muted-foreground\")} />\n <span>\n <span className=\"block text-sm font-semibold\">{label}</span>\n <span className={cn(\"block text-xs mt-0.5\", selected ? \"text-white/80\" : \"text-muted-foreground\")}>\n {blurb}\n </span>\n </span>\n </button>\n );\n })}\n </div>\n\n <Link\n href={ready ? continueHref : \"#\"}\n aria-disabled={!ready}\n onClick={(e) => { if (!ready) e.preventDefault(); }}\n className={cn(\n \"flex items-center justify-center gap-1.5 w-full h-12 rounded-xl text-base font-semibold text-white transition-all\",\n ready ? \"bg-brand-blue hover:brightness-110 active:scale-[0.98]\" : \"bg-brand-blue/40 cursor-not-allowed\",\n )}\n >\n Continue\n <ArrowRight className=\"h-4 w-4\" />\n </Link>\n </div>\n </section>\n );\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@medialane/ui",
3
- "version": "0.126.10",
3
+ "version": "0.126.11",
4
4
  "description": "Shared UI components for Medialane apps",
5
5
  "type": "module",
6
6
  "sideEffects": false,