@geekapps/silo-elements-nextjs 0.1.3 → 0.1.4

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.
package/dist/index.js CHANGED
@@ -169,6 +169,72 @@ function ProgressBar({ progress, className = "", style }) {
169
169
  }
170
170
  );
171
171
  }
172
+ var FORMATS = [
173
+ { value: "webp", label: "WebP", hint: "Melhor custo-benef\xEDcio" },
174
+ { value: "avif", label: "AVIF", hint: "M\xE1xima compress\xE3o" },
175
+ { value: "jpeg", label: "JPEG", hint: "Compatibilidade universal" },
176
+ { value: "png", label: "PNG", hint: "Sem perda" }
177
+ ];
178
+ function ImageOptions({ value, onChange, style }) {
179
+ const fmt = value.format ?? "webp";
180
+ const optimize = value.optimize ?? true;
181
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 10, ...style }, children: [
182
+ /* @__PURE__ */ jsxs("div", { children: [
183
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 11, fontWeight: 700, color: "var(--silo-text-muted, #64748b)", letterSpacing: "0.05em", textTransform: "uppercase", marginBottom: 6 }, children: "Formato de sa\xEDda" }),
184
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: FORMATS.map((f) => /* @__PURE__ */ jsx(
185
+ "button",
186
+ {
187
+ type: "button",
188
+ onClick: () => onChange({ ...value, format: f.value }),
189
+ title: f.hint,
190
+ style: {
191
+ padding: "4px 12px",
192
+ borderRadius: 6,
193
+ border: `1px solid ${fmt === f.value ? "var(--silo-accent, #6366f1)" : "var(--silo-border, #e2e8f0)"}`,
194
+ background: fmt === f.value ? "var(--silo-accent, #6366f1)" : "transparent",
195
+ color: fmt === f.value ? "#fff" : "var(--silo-text, #0f172a)",
196
+ fontSize: 12,
197
+ fontWeight: 600,
198
+ cursor: "pointer"
199
+ },
200
+ children: f.label
201
+ },
202
+ f.value
203
+ )) })
204
+ ] }),
205
+ /* @__PURE__ */ jsxs("label", { style: { display: "flex", alignItems: "center", gap: 8, cursor: "pointer", userSelect: "none" }, children: [
206
+ /* @__PURE__ */ jsx(
207
+ "span",
208
+ {
209
+ onClick: () => onChange({ ...value, optimize: !optimize }),
210
+ style: {
211
+ width: 36,
212
+ height: 20,
213
+ borderRadius: 10,
214
+ background: optimize ? "var(--silo-accent, #6366f1)" : "var(--silo-border, #e2e8f0)",
215
+ position: "relative",
216
+ flexShrink: 0,
217
+ transition: "background 0.15s",
218
+ cursor: "pointer"
219
+ },
220
+ children: /* @__PURE__ */ jsx("span", { style: {
221
+ position: "absolute",
222
+ top: 2,
223
+ left: optimize ? 18 : 2,
224
+ width: 16,
225
+ height: 16,
226
+ borderRadius: "50%",
227
+ background: "#fff",
228
+ transition: "left 0.15s",
229
+ boxShadow: "0 1px 3px rgba(0,0,0,0.2)"
230
+ } })
231
+ }
232
+ ),
233
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 12, color: "var(--silo-text, #0f172a)", fontWeight: 500 }, children: "Otimizar tamanho" }),
234
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 11, color: "var(--silo-text-muted, #94a3b8)" }, children: optimize ? "Qualidade 85 \u2014 menor tamanho" : "Qualidade m\xE1xima" })
235
+ ] })
236
+ ] });
237
+ }
172
238
 
173
239
  // src/utils/format.ts
174
240
  function formatBytes(bytes) {
@@ -200,6 +266,7 @@ function ImageUploader({
200
266
  maxSize,
201
267
  accept = "image/*",
202
268
  showPreview = true,
269
+ showImageOptions = false,
203
270
  image,
204
271
  theme,
205
272
  renderIcon,
@@ -210,6 +277,7 @@ function ImageUploader({
210
277
  }) {
211
278
  const { state, upload, pause, resume, abort, reset } = useMultipartUpload(bucket);
212
279
  const [preview, setPreview] = useState(null);
280
+ const [imageOpts, setImageOpts] = useState(image ?? { format: "webp", optimize: true });
213
281
  const t = resolveTheme(theme);
214
282
  const vars = themeToVars(t);
215
283
  const handleFiles = useCallback(async (files) => {
@@ -217,16 +285,17 @@ function ImageUploader({
217
285
  if (!file) return;
218
286
  if (showPreview) setPreview(URL.createObjectURL(file));
219
287
  try {
288
+ const opts = showImageOptions ? imageOpts : image ?? imageOpts;
220
289
  const result = await upload(file, {
221
290
  ...bucket !== void 0 && { bucket },
222
291
  visibility,
223
- ...image && { image }
292
+ image: opts
224
293
  });
225
294
  if (result) onUpload?.(result);
226
295
  } catch (err) {
227
296
  onError?.(err instanceof Error ? err : new Error(String(err)));
228
297
  }
229
- }, [upload, bucket, visibility, image, onUpload, onError, showPreview]);
298
+ }, [upload, bucket, visibility, image, imageOpts, showImageOptions, onUpload, onError, showPreview]);
230
299
  const containerStyle = {
231
300
  ...vars,
232
301
  display: "flex",
@@ -242,6 +311,14 @@ function ImageUploader({
242
311
  if (state.status === "error" && renderError) return /* @__PURE__ */ jsx("div", { style: containerStyle, children: renderError(state.error, reset) });
243
312
  if (state.status === "done" && renderSuccess) return /* @__PURE__ */ jsx("div", { style: containerStyle, children: renderSuccess(state.result) });
244
313
  return /* @__PURE__ */ jsxs("div", { className: `silo-image-uploader${className ? ` ${className}` : ""}`, style: containerStyle, children: [
314
+ showImageOptions && !isUploading && state.status !== "done" && /* @__PURE__ */ jsx(
315
+ ImageOptions,
316
+ {
317
+ value: imageOpts,
318
+ onChange: setImageOpts,
319
+ style: { padding: "12px 14px", borderRadius: 8, border: "1px solid var(--silo-border, #e2e8f0)", background: "var(--silo-bg-hover, #f8fafc)" }
320
+ }
321
+ ),
245
322
  /* @__PURE__ */ jsx(
246
323
  DropZone,
247
324
  {
@@ -308,6 +385,132 @@ function ImageUploader({
308
385
  ] })
309
386
  ] });
310
387
  }
388
+ var CODECS = [
389
+ { value: "h264", label: "H.264", hint: "Compatibilidade m\xE1xima" },
390
+ { value: "h265", label: "H.265", hint: "Melhor compress\xE3o" },
391
+ { value: "av1", label: "AV1", hint: "Futuro \u2014 menor tamanho" },
392
+ { value: "vp9", label: "VP9", hint: "Open source" }
393
+ ];
394
+ var RESOLUTIONS = ["360", "480", "720", "1080", "1440", "2160"];
395
+ var RESOLUTION_LABELS = {
396
+ "360": "360p",
397
+ "480": "480p",
398
+ "720": "720p",
399
+ "1080": "1080p",
400
+ "1440": "1440p",
401
+ "2160": "4K"
402
+ };
403
+ function VideoOptions({ value, onChange, style }) {
404
+ const codec = value.codec ?? "h264";
405
+ const transcoding = value.transcoding ?? "auto";
406
+ const isAuto = transcoding === "auto";
407
+ const selectedRes = isAuto ? [] : transcoding;
408
+ function toggleRes(r) {
409
+ if (isAuto) {
410
+ onChange({ ...value, transcoding: [r] });
411
+ return;
412
+ }
413
+ const next = selectedRes.includes(r) ? selectedRes.filter((x) => x !== r) : [...selectedRes, r];
414
+ onChange({ ...value, transcoding: next.length === 0 ? "auto" : next });
415
+ }
416
+ function toggleFeature(key) {
417
+ onChange({ ...value, [key]: !value[key] });
418
+ }
419
+ const btn = (active) => ({
420
+ padding: "4px 10px",
421
+ borderRadius: 6,
422
+ border: `1px solid ${active ? "var(--silo-accent, #6366f1)" : "var(--silo-border, #e2e8f0)"}`,
423
+ background: active ? "var(--silo-accent, #6366f1)" : "transparent",
424
+ color: active ? "#fff" : "var(--silo-text, #0f172a)",
425
+ fontSize: 12,
426
+ fontWeight: 600,
427
+ cursor: "pointer"
428
+ });
429
+ const toggle = (on) => ({
430
+ display: "inline-flex",
431
+ alignItems: "center",
432
+ gap: 6,
433
+ cursor: "pointer",
434
+ userSelect: "none",
435
+ fontSize: 12,
436
+ color: "var(--silo-text, #0f172a)",
437
+ fontWeight: 500
438
+ });
439
+ function Toggle({ checked, onToggle, label }) {
440
+ return /* @__PURE__ */ jsxs("label", { style: toggle(), onClick: onToggle, children: [
441
+ /* @__PURE__ */ jsx("span", { style: {
442
+ width: 32,
443
+ height: 18,
444
+ borderRadius: 9,
445
+ flexShrink: 0,
446
+ background: checked ? "var(--silo-accent, #6366f1)" : "var(--silo-border, #e2e8f0)",
447
+ position: "relative",
448
+ transition: "background 0.15s",
449
+ cursor: "pointer"
450
+ }, children: /* @__PURE__ */ jsx("span", { style: {
451
+ position: "absolute",
452
+ top: 2,
453
+ left: checked ? 16 : 2,
454
+ width: 14,
455
+ height: 14,
456
+ borderRadius: "50%",
457
+ background: "#fff",
458
+ transition: "left 0.15s",
459
+ boxShadow: "0 1px 3px rgba(0,0,0,0.2)"
460
+ } }) }),
461
+ label
462
+ ] });
463
+ }
464
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 12, ...style }, children: [
465
+ /* @__PURE__ */ jsxs("div", { children: [
466
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 11, fontWeight: 700, color: "var(--silo-text-muted, #64748b)", letterSpacing: "0.05em", textTransform: "uppercase", marginBottom: 6 }, children: "Codec" }),
467
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: CODECS.map((c) => /* @__PURE__ */ jsx(
468
+ "button",
469
+ {
470
+ type: "button",
471
+ title: c.hint,
472
+ onClick: () => onChange({ ...value, codec: c.value }),
473
+ style: btn(codec === c.value),
474
+ children: c.label
475
+ },
476
+ c.value
477
+ )) })
478
+ ] }),
479
+ /* @__PURE__ */ jsxs("div", { children: [
480
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 11, fontWeight: 700, color: "var(--silo-text-muted, #64748b)", letterSpacing: "0.05em", textTransform: "uppercase", marginBottom: 6 }, children: "Resolu\xE7\xF5es" }),
481
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
482
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => onChange({ ...value, transcoding: "auto" }), style: btn(isAuto), children: "Auto" }),
483
+ RESOLUTIONS.map((r) => /* @__PURE__ */ jsx(
484
+ "button",
485
+ {
486
+ type: "button",
487
+ onClick: () => toggleRes(r),
488
+ style: btn(!isAuto && selectedRes.includes(r)),
489
+ children: RESOLUTION_LABELS[r]
490
+ },
491
+ r
492
+ ))
493
+ ] })
494
+ ] }),
495
+ /* @__PURE__ */ jsxs("div", { children: [
496
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 11, fontWeight: 700, color: "var(--silo-text-muted, #64748b)", letterSpacing: "0.05em", textTransform: "uppercase", marginBottom: 8 }, children: "Recursos" }),
497
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
498
+ /* @__PURE__ */ jsx(Toggle, { checked: value.thumbnails ?? true, onToggle: () => toggleFeature("thumbnails"), label: "Gerar thumbnails" }),
499
+ /* @__PURE__ */ jsx(Toggle, { checked: value.storyboard ?? false, onToggle: () => toggleFeature("storyboard"), label: "Gerar storyboard" }),
500
+ /* @__PURE__ */ jsx(Toggle, { checked: value.autoCaptions ?? false, onToggle: () => toggleFeature("autoCaptions"), label: "Legendas autom\xE1ticas (IA)" }),
501
+ /* @__PURE__ */ jsx(Toggle, { checked: value.separateAudio ?? false, onToggle: () => toggleFeature("separateAudio"), label: "Separar faixa de \xE1udio" })
502
+ ] })
503
+ ] })
504
+ ] });
505
+ }
506
+ var DEFAULT_VIDEO_OPTS = {
507
+ thumbnails: true,
508
+ storyboard: false,
509
+ autoCaptions: false,
510
+ separateAudio: false,
511
+ codec: "h264",
512
+ transcoding: "auto"
513
+ };
311
514
  function VideoUploader({
312
515
  bucket,
313
516
  expiresIn,
@@ -320,6 +523,7 @@ function VideoUploader({
320
523
  maxSize,
321
524
  accept = "video/*",
322
525
  showPreview = true,
526
+ showVideoOptions = false,
323
527
  video,
324
528
  theme,
325
529
  renderIcon,
@@ -330,6 +534,7 @@ function VideoUploader({
330
534
  }) {
331
535
  const { state, upload, pause, resume, abort, reset } = useMultipartUpload(bucket);
332
536
  const [preview, setPreview] = useState(null);
537
+ const [videoOpts, setVideoOpts] = useState(video ?? DEFAULT_VIDEO_OPTS);
333
538
  const t = resolveTheme(theme);
334
539
  const vars = themeToVars(t);
335
540
  const handleFiles = useCallback(async (files) => {
@@ -337,16 +542,17 @@ function VideoUploader({
337
542
  if (!file) return;
338
543
  if (showPreview) setPreview(URL.createObjectURL(file));
339
544
  try {
545
+ const opts = showVideoOptions ? videoOpts : video ?? videoOpts;
340
546
  const result = await upload(file, {
341
547
  ...bucket !== void 0 && { bucket },
342
548
  visibility,
343
- ...video && { video }
549
+ video: opts
344
550
  });
345
551
  if (result) onUpload?.(result);
346
552
  } catch (err) {
347
553
  onError?.(err instanceof Error ? err : new Error(String(err)));
348
554
  }
349
- }, [upload, bucket, visibility, video, onUpload, onError, showPreview]);
555
+ }, [upload, bucket, visibility, video, videoOpts, showVideoOptions, onUpload, onError, showPreview]);
350
556
  const containerStyle = {
351
557
  ...vars,
352
558
  display: "flex",
@@ -362,6 +568,14 @@ function VideoUploader({
362
568
  if (state.status === "error" && renderError) return /* @__PURE__ */ jsx("div", { style: containerStyle, children: renderError(state.error, reset) });
363
569
  if (state.status === "done" && renderSuccess) return /* @__PURE__ */ jsx("div", { style: containerStyle, children: renderSuccess(state.result) });
364
570
  return /* @__PURE__ */ jsxs("div", { className: `silo-video-uploader${className ? ` ${className}` : ""}`, style: containerStyle, children: [
571
+ showVideoOptions && !isUploading && state.status !== "done" && /* @__PURE__ */ jsx(
572
+ VideoOptions,
573
+ {
574
+ value: videoOpts,
575
+ onChange: setVideoOpts,
576
+ style: { padding: "12px 14px", borderRadius: 8, border: "1px solid var(--silo-border, #e2e8f0)", background: "var(--silo-bg-hover, #f8fafc)" }
577
+ }
578
+ ),
365
579
  /* @__PURE__ */ jsx(
366
580
  DropZone,
367
581
  {
@@ -403,7 +617,14 @@ function VideoUploader({
403
617
  /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: "var(--silo-text-muted)" }, children: "O processamento inicia ap\xF3s o upload" })
404
618
  ] }) }),
405
619
  isPaused && /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px" }, children: [
406
- /* @__PURE__ */ jsx("button", { onClick: () => resume({ ...bucket !== void 0 && { bucket }, visibility, ...video && { video } }), style: { flex: 1, padding: "8px", borderRadius: "6px", border: "none", backgroundColor: "#10b981", color: "#fff", fontSize: "13px", fontWeight: 600, cursor: "pointer" }, children: "Retomar upload" }),
620
+ /* @__PURE__ */ jsx(
621
+ "button",
622
+ {
623
+ onClick: () => resume({ ...bucket !== void 0 && { bucket }, visibility, video: showVideoOptions ? videoOpts : video ?? videoOpts }),
624
+ style: { flex: 1, padding: "8px", borderRadius: "6px", border: "none", backgroundColor: "#10b981", color: "#fff", fontSize: "13px", fontWeight: 600, cursor: "pointer" },
625
+ children: "Retomar upload"
626
+ }
627
+ ),
407
628
  /* @__PURE__ */ jsx("button", { onClick: () => {
408
629
  abort();
409
630
  setPreview(null);
@@ -426,6 +647,14 @@ function VideoUploader({
426
647
  ] })
427
648
  ] });
428
649
  }
650
+ var DEFAULT_VIDEO_OPTS2 = {
651
+ thumbnails: true,
652
+ storyboard: false,
653
+ autoCaptions: false,
654
+ separateAudio: false,
655
+ codec: "h264",
656
+ transcoding: "auto"
657
+ };
429
658
  function FileUploader({
430
659
  bucket,
431
660
  visibility = "private",
@@ -439,6 +668,8 @@ function FileUploader({
439
668
  accept,
440
669
  multiple = false,
441
670
  allowRename = false,
671
+ showImageOptions = false,
672
+ showVideoOptions = false,
442
673
  image,
443
674
  video,
444
675
  theme,
@@ -461,6 +692,8 @@ function FileUploader({
461
692
  };
462
693
  const single = useMultipartUpload(bucket);
463
694
  const batch = useBatchUpload();
695
+ const [imageOpts, setImageOpts] = useState(image ?? { format: "webp", optimize: true });
696
+ const [videoOpts, setVideoOpts] = useState(video ?? DEFAULT_VIDEO_OPTS2);
464
697
  const [staged, setStaged] = useState(null);
465
698
  const [renames, setRenames] = useState(/* @__PURE__ */ new Map());
466
699
  const [editingIndex, setEditingIndex] = useState(null);
@@ -484,9 +717,11 @@ function FileUploader({
484
717
  setEditingIndex(null);
485
718
  }
486
719
  const doUpload = useCallback(async (files) => {
720
+ const effectiveImage = showImageOptions ? imageOpts : image ?? imageOpts;
721
+ const effectiveVideo = showVideoOptions ? videoOpts : video ?? videoOpts;
487
722
  if (multiple && files.length > 1) {
488
723
  try {
489
- const opts = { ...bucket !== void 0 && { bucket }, visibility, ...image && { image }, ...video && { video } };
724
+ const opts = { ...bucket !== void 0 && { bucket }, visibility, image: effectiveImage, video: effectiveVideo };
490
725
  const results = await batch.upload(files, opts);
491
726
  onBatchUpload?.(results);
492
727
  results.forEach((r) => onUpload?.(r));
@@ -497,7 +732,7 @@ function FileUploader({
497
732
  const file = files[0];
498
733
  if (!file) return;
499
734
  try {
500
- const opts = { ...bucket !== void 0 && { bucket }, visibility, ...image && { image }, ...video && { video } };
735
+ const opts = { ...bucket !== void 0 && { bucket }, visibility, image: effectiveImage, video: effectiveVideo };
501
736
  const result = await single.upload(file, opts);
502
737
  if (result) onUpload?.(result);
503
738
  } catch (err) {
@@ -616,6 +851,22 @@ function FileUploader({
616
851
  }
617
852
  )
618
853
  ] }, i)),
854
+ showImageOptions && staged.some((f) => f.type.startsWith("image/")) && /* @__PURE__ */ jsx(
855
+ ImageOptions,
856
+ {
857
+ value: imageOpts,
858
+ onChange: setImageOpts,
859
+ style: { padding: "12px 14px", borderRadius: 8, border: "1px solid var(--silo-border)", background: "var(--silo-bg-hover, #f8fafc)", marginTop: 4 }
860
+ }
861
+ ),
862
+ showVideoOptions && staged.some((f) => f.type.startsWith("video/")) && /* @__PURE__ */ jsx(
863
+ VideoOptions,
864
+ {
865
+ value: videoOpts,
866
+ onChange: setVideoOpts,
867
+ style: { padding: "12px 14px", borderRadius: 8, border: "1px solid var(--silo-border)", background: "var(--silo-bg-hover, #f8fafc)", marginTop: 4 }
868
+ }
869
+ ),
619
870
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "8px", marginTop: "4px" }, children: [
620
871
  /* @__PURE__ */ jsx(
621
872
  "button",
@@ -2354,6 +2605,6 @@ var metaGrid = {
2354
2605
  alignItems: "baseline"
2355
2606
  };
2356
2607
 
2357
- export { Avatar, Background, DropZone, FileCard, FileIcon, FilePreview, FileUploader, ImageUploader, MediaUploader, ProgressBar, Source, Sources, Storyboard, StoryboardFrame, Subtitle, Subtitles, Thumbnail, Video, VideoPlayer, VideoUploader, defaultTheme, resolveTheme };
2608
+ export { Avatar, Background, DropZone, FileCard, FileIcon, FilePreview, FileUploader, ImageOptions, ImageUploader, MediaUploader, ProgressBar, Source, Sources, Storyboard, StoryboardFrame, Subtitle, Subtitles, Thumbnail, Video, VideoOptions, VideoPlayer, VideoUploader, defaultTheme, resolveTheme };
2358
2609
  //# sourceMappingURL=index.js.map
2359
2610
  //# sourceMappingURL=index.js.map