@scalemule/nextjs 0.1.21 → 0.1.22

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 (3) hide show
  1. package/dist/index.js +281 -130
  2. package/dist/index.mjs +281 -130
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11289,6 +11289,156 @@ function FeedbackWidget(props) {
11289
11289
  ] });
11290
11290
  }
11291
11291
  var SPEEDS = [1, 1.25, 1.5, 2];
11292
+ var styles = {
11293
+ root: {
11294
+ borderRadius: "1.75rem",
11295
+ border: "1px solid rgba(226, 232, 240, 0.8)",
11296
+ background: "linear-gradient(180deg, #f8fbff 0%, #edf4ff 100%)",
11297
+ padding: "1rem",
11298
+ color: "#0f172b",
11299
+ boxShadow: "0 22px 70px rgba(4, 12, 24, 0.28)"
11300
+ },
11301
+ layout: {
11302
+ display: "flex",
11303
+ flexWrap: "wrap",
11304
+ alignItems: "center",
11305
+ gap: "1rem"
11306
+ },
11307
+ playButton: {
11308
+ display: "flex",
11309
+ height: "4.5rem",
11310
+ width: "4.5rem",
11311
+ flexShrink: 0,
11312
+ alignItems: "center",
11313
+ justifyContent: "center",
11314
+ borderRadius: "9999px",
11315
+ border: "none",
11316
+ backgroundColor: "#020618",
11317
+ color: "#ffffff",
11318
+ boxShadow: "0 10px 28px rgba(15, 23, 42, 0.25)",
11319
+ cursor: "pointer"
11320
+ },
11321
+ playIcon: {
11322
+ display: "block",
11323
+ width: "1.75rem",
11324
+ height: "1.75rem",
11325
+ fill: "currentColor"
11326
+ },
11327
+ playIconOffset: {
11328
+ marginLeft: "0.25rem"
11329
+ },
11330
+ content: {
11331
+ minWidth: "16rem",
11332
+ flex: "1 1 18rem"
11333
+ },
11334
+ metaRow: {
11335
+ display: "flex",
11336
+ alignItems: "center",
11337
+ justifyContent: "space-between",
11338
+ gap: "0.75rem",
11339
+ fontSize: "0.8rem",
11340
+ fontWeight: 500,
11341
+ color: "#62748e"
11342
+ },
11343
+ metaRight: {
11344
+ display: "flex",
11345
+ alignItems: "center",
11346
+ gap: "0.75rem"
11347
+ },
11348
+ badge: {
11349
+ borderRadius: "9999px",
11350
+ backgroundColor: "#dbeafe",
11351
+ padding: "0.25rem 0.75rem",
11352
+ fontSize: "0.65rem",
11353
+ fontWeight: 600,
11354
+ letterSpacing: "0.24em",
11355
+ textTransform: "uppercase",
11356
+ color: "#1447e6"
11357
+ },
11358
+ scrubber: {
11359
+ position: "relative",
11360
+ marginTop: "1rem",
11361
+ height: "3rem",
11362
+ cursor: "pointer",
11363
+ overflow: "hidden",
11364
+ borderRadius: "1rem",
11365
+ backgroundColor: "rgba(226, 232, 240, 0.9)",
11366
+ paddingInline: "0.25rem"
11367
+ },
11368
+ waveform: {
11369
+ pointerEvents: "none",
11370
+ position: "absolute",
11371
+ inset: 0,
11372
+ height: "100%",
11373
+ width: "100%"
11374
+ },
11375
+ fallbackTrack: {
11376
+ position: "absolute",
11377
+ inset: 0,
11378
+ backgroundColor: "rgba(226, 232, 240, 0.9)"
11379
+ },
11380
+ fallbackProgress: {
11381
+ position: "absolute",
11382
+ insetBlock: 0,
11383
+ left: 0,
11384
+ backgroundColor: "#155dfc"
11385
+ },
11386
+ chipsRow: {
11387
+ marginTop: "1rem",
11388
+ display: "flex",
11389
+ flexWrap: "wrap",
11390
+ alignItems: "center",
11391
+ gap: "0.5rem",
11392
+ fontSize: "0.72rem",
11393
+ fontWeight: 500,
11394
+ color: "#62748e"
11395
+ },
11396
+ chipStrong: {
11397
+ borderRadius: "9999px",
11398
+ border: "1px solid #e2e8f0",
11399
+ backgroundColor: "rgba(255, 255, 255, 0.85)",
11400
+ padding: "0.25rem 0.75rem",
11401
+ color: "#334155"
11402
+ },
11403
+ chipMuted: {
11404
+ borderRadius: "9999px",
11405
+ border: "1px solid #e2e8f0",
11406
+ backgroundColor: "rgba(255, 255, 255, 0.65)",
11407
+ padding: "0.25rem 0.75rem"
11408
+ },
11409
+ controls: {
11410
+ display: "flex",
11411
+ flexShrink: 0,
11412
+ alignItems: "center",
11413
+ gap: "0.5rem",
11414
+ alignSelf: "flex-start"
11415
+ },
11416
+ secondaryButton: {
11417
+ borderRadius: "9999px",
11418
+ border: "1px solid #cad5e2",
11419
+ backgroundColor: "rgba(255, 255, 255, 0.9)",
11420
+ padding: "0.5rem 1rem",
11421
+ fontSize: "1rem",
11422
+ fontWeight: 600,
11423
+ color: "#334155",
11424
+ boxShadow: "0 1px 3px rgba(15, 23, 42, 0.08)",
11425
+ cursor: "pointer"
11426
+ },
11427
+ refreshButton: {
11428
+ borderRadius: "9999px",
11429
+ border: "1px solid #cad5e2",
11430
+ backgroundColor: "rgba(255, 255, 255, 0.75)",
11431
+ padding: "0.5rem 1rem",
11432
+ fontSize: "0.875rem",
11433
+ fontWeight: 600,
11434
+ color: "#334155",
11435
+ cursor: "pointer"
11436
+ },
11437
+ disabled: {
11438
+ cursor: "not-allowed",
11439
+ opacity: 0.6
11440
+ }
11441
+ };
11292
11442
  function formatTime(seconds) {
11293
11443
  if (!Number.isFinite(seconds) || seconds <= 0) {
11294
11444
  return "0:00";
@@ -11371,146 +11521,147 @@ function NarrationPlayer({
11371
11521
  if (!audio.url) {
11372
11522
  return null;
11373
11523
  }
11374
- return /* @__PURE__ */ jsxRuntime.jsxs(
11375
- "div",
11376
- {
11377
- className: "rounded-[1.75rem] border border-slate-200/80 bg-[linear-gradient(180deg,#f8fbff_0%,#edf4ff_100%)] p-4 text-slate-900 shadow-[0_22px_70px_rgba(4,12,24,0.28)] " + (className ?? ""),
11378
- children: [
11524
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: styles.root, children: [
11525
+ /* @__PURE__ */ jsxRuntime.jsx(
11526
+ "audio",
11527
+ {
11528
+ ref: audioRef,
11529
+ src: audio.url ?? void 0,
11530
+ preload: "metadata",
11531
+ onLoadedMetadata: (event) => {
11532
+ setDuration(event.currentTarget.duration || 0);
11533
+ },
11534
+ onTimeUpdate: (event) => {
11535
+ setCurrentTime(event.currentTarget.currentTime);
11536
+ },
11537
+ onPlay: () => setPlaying(true),
11538
+ onPause: () => setPlaying(false),
11539
+ onEnded: () => setPlaying(false),
11540
+ onError: () => onPlaybackError?.()
11541
+ }
11542
+ ),
11543
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.layout, children: [
11544
+ /* @__PURE__ */ jsxRuntime.jsx(
11545
+ "button",
11546
+ {
11547
+ type: "button",
11548
+ onClick: togglePlayback,
11549
+ "aria-label": playing ? "Pause narration" : "Play narration",
11550
+ style: styles.playButton,
11551
+ children: playing ? /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", style: styles.playIcon, "aria-hidden": "true", children: [
11552
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "6", y: "5", width: "4", height: "14", rx: "1.2" }),
11553
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "5", width: "4", height: "14", rx: "1.2" })
11554
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
11555
+ "svg",
11556
+ {
11557
+ viewBox: "0 0 24 24",
11558
+ style: { ...styles.playIcon, ...styles.playIconOffset },
11559
+ "aria-hidden": "true",
11560
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 5.2c0-1.02 1.12-1.65 2-.98l10.2 7.78a1.24 1.24 0 0 1 0 1.98L9 21.76c-.88.67-2-.04-2-1.08V5.2Z" })
11561
+ }
11562
+ )
11563
+ }
11564
+ ),
11565
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.content, children: [
11566
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.metaRow, children: [
11567
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatTime(currentTime / speed) }),
11568
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.metaRight, children: [
11569
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles.badge, children: narrationLabel }),
11570
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatTime(duration / speed) })
11571
+ ] })
11572
+ ] }),
11379
11573
  /* @__PURE__ */ jsxRuntime.jsx(
11380
- "audio",
11574
+ "div",
11381
11575
  {
11382
- ref: audioRef,
11383
- src: audio.url ?? void 0,
11384
- preload: "metadata",
11385
- onLoadedMetadata: (event) => {
11386
- setDuration(event.currentTarget.duration || 0);
11387
- },
11388
- onTimeUpdate: (event) => {
11389
- setCurrentTime(event.currentTarget.currentTime);
11576
+ ref: scrubRef,
11577
+ role: "slider",
11578
+ "aria-label": "Narration progress",
11579
+ "aria-valuemin": 0,
11580
+ "aria-valuemax": Math.max(1, Math.floor(duration)),
11581
+ "aria-valuenow": Math.floor(currentTime),
11582
+ tabIndex: 0,
11583
+ onClick: (event) => {
11584
+ seekTo(event.clientX);
11390
11585
  },
11391
- onPlay: () => setPlaying(true),
11392
- onPause: () => setPlaying(false),
11393
- onEnded: () => setPlaying(false),
11394
- onError: () => onPlaybackError?.()
11395
- }
11396
- ),
11397
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 md:flex-row md:items-center", children: [
11398
- /* @__PURE__ */ jsxRuntime.jsx(
11399
- "button",
11400
- {
11401
- type: "button",
11402
- onClick: togglePlayback,
11403
- "aria-label": playing ? "Pause narration" : "Play narration",
11404
- className: "flex h-[4.5rem] w-[4.5rem] shrink-0 items-center justify-center rounded-full bg-slate-950 text-white shadow-[0_10px_28px_rgba(15,23,42,0.25)] transition hover:bg-slate-800",
11405
- children: playing ? /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", className: "h-7 w-7 fill-current", "aria-hidden": "true", children: [
11406
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "6", y: "5", width: "4", height: "14", rx: "1.2" }),
11407
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "14", y: "5", width: "4", height: "14", rx: "1.2" })
11408
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", className: "ml-1 h-7 w-7 fill-current", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 5.2c0-1.02 1.12-1.65 2-.98l10.2 7.78a1.24 1.24 0 0 1 0 1.98L9 21.76c-.88.67-2-.04-2-1.08V5.2Z" }) })
11409
- }
11410
- ),
11411
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
11412
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 text-[0.8rem] font-medium text-slate-500", children: [
11413
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatTime(currentTime / speed) }),
11414
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
11415
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-blue-100 px-3 py-1 text-[0.65rem] font-semibold uppercase tracking-[0.24em] text-blue-700", children: narrationLabel }),
11416
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatTime(duration / speed) })
11417
- ] })
11418
- ] }),
11419
- /* @__PURE__ */ jsxRuntime.jsx(
11420
- "div",
11586
+ style: styles.scrubber,
11587
+ children: peaks.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
11588
+ "svg",
11421
11589
  {
11422
- ref: scrubRef,
11423
- role: "slider",
11424
- "aria-label": "Narration progress",
11425
- "aria-valuemin": 0,
11426
- "aria-valuemax": Math.max(1, Math.floor(duration)),
11427
- "aria-valuenow": Math.floor(currentTime),
11428
- tabIndex: 0,
11429
- onClick: (event) => {
11430
- seekTo(event.clientX);
11431
- },
11432
- className: "relative mt-4 h-12 cursor-pointer overflow-hidden rounded-[1rem] bg-slate-200/90 px-1",
11433
- children: peaks.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
11434
- "svg",
11435
- {
11436
- viewBox: `0 0 ${peaks.length} 40`,
11437
- preserveAspectRatio: "none",
11438
- className: "pointer-events-none absolute inset-0 h-full w-full",
11439
- children: peaks.map((peak, index) => {
11440
- const height = Math.max(2, Math.round(Math.abs(peak) * 34));
11441
- const y = (40 - height) / 2;
11442
- const filled = index / peaks.length < progress;
11443
- return /* @__PURE__ */ jsxRuntime.jsx(
11444
- "rect",
11445
- {
11446
- x: index,
11447
- y,
11448
- width: 0.82,
11449
- height,
11450
- rx: 0.4,
11451
- className: filled ? "fill-blue-600" : "fill-blue-300"
11452
- },
11453
- `${audio.id}-${index}`
11454
- );
11455
- })
11456
- }
11457
- ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
11458
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-slate-200/90" }),
11459
- /* @__PURE__ */ jsxRuntime.jsx(
11460
- "div",
11590
+ viewBox: `0 0 ${peaks.length} 40`,
11591
+ preserveAspectRatio: "none",
11592
+ style: styles.waveform,
11593
+ children: peaks.map((peak, index) => {
11594
+ const height = Math.max(2, Math.round(Math.abs(peak) * 34));
11595
+ const y = (40 - height) / 2;
11596
+ const filled = index / peaks.length < progress;
11597
+ return /* @__PURE__ */ jsxRuntime.jsx(
11598
+ "rect",
11461
11599
  {
11462
- className: "absolute inset-y-0 left-0 bg-blue-600",
11463
- style: { width: `${progress * 100}%` }
11464
- }
11465
- )
11466
- ] })
11600
+ x: index,
11601
+ y,
11602
+ width: 0.82,
11603
+ height,
11604
+ rx: 0.4,
11605
+ fill: filled ? "#155dfc" : "#90c5ff"
11606
+ },
11607
+ `${audio.id}-${index}`
11608
+ );
11609
+ })
11467
11610
  }
11468
- ),
11469
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex flex-wrap items-center gap-2 text-[0.72rem] font-medium text-slate-500", children: [
11470
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "rounded-full border border-slate-200 bg-white/85 px-3 py-1 text-slate-700", children: [
11471
- "Provider: ",
11472
- providerLabel
11473
- ] }),
11474
- duration > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "rounded-full border border-slate-200 bg-white/65 px-3 py-1", children: [
11475
- "Length ",
11476
- formatTime(duration / speed)
11477
- ] }),
11478
- expiresLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "rounded-full border border-slate-200 bg-white/65 px-3 py-1", children: [
11479
- "Expires ",
11480
- expiresLabel
11481
- ] })
11611
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
11612
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: styles.fallbackTrack }),
11613
+ /* @__PURE__ */ jsxRuntime.jsx(
11614
+ "div",
11615
+ {
11616
+ style: { ...styles.fallbackProgress, width: `${progress * 100}%` }
11617
+ }
11618
+ )
11482
11619
  ] })
11620
+ }
11621
+ ),
11622
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.chipsRow, children: [
11623
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles.chipStrong, children: [
11624
+ "Provider: ",
11625
+ providerLabel
11483
11626
  ] }),
11484
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-2 self-start md:self-center", children: [
11485
- /* @__PURE__ */ jsxRuntime.jsxs(
11486
- "button",
11487
- {
11488
- type: "button",
11489
- onClick: () => {
11490
- setSpeed((currentSpeed) => getNextSpeed(currentSpeed));
11491
- },
11492
- className: "rounded-full border border-slate-300 bg-white/90 px-4 py-2 text-base font-semibold text-slate-700 shadow-sm hover:bg-white",
11493
- children: [
11494
- speed,
11495
- "\xD7"
11496
- ]
11497
- }
11498
- ),
11499
- onRefresh && /* @__PURE__ */ jsxRuntime.jsx(
11500
- "button",
11501
- {
11502
- type: "button",
11503
- onClick: onRefresh,
11504
- disabled: refreshing,
11505
- className: "rounded-full border border-slate-300 bg-white/75 px-4 py-2 text-sm font-semibold text-slate-700 hover:bg-white disabled:cursor-not-allowed disabled:opacity-60",
11506
- children: refreshing ? "Refreshing\u2026" : "Refresh"
11507
- }
11508
- )
11627
+ duration > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles.chipMuted, children: [
11628
+ "Length ",
11629
+ formatTime(duration / speed)
11630
+ ] }),
11631
+ expiresLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: styles.chipMuted, children: [
11632
+ "Expires ",
11633
+ expiresLabel
11509
11634
  ] })
11510
11635
  ] })
11511
- ]
11512
- }
11513
- );
11636
+ ] }),
11637
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.controls, children: [
11638
+ /* @__PURE__ */ jsxRuntime.jsxs(
11639
+ "button",
11640
+ {
11641
+ type: "button",
11642
+ onClick: () => {
11643
+ setSpeed((currentSpeed) => getNextSpeed(currentSpeed));
11644
+ },
11645
+ style: styles.secondaryButton,
11646
+ children: [
11647
+ speed,
11648
+ "\xD7"
11649
+ ]
11650
+ }
11651
+ ),
11652
+ onRefresh && /* @__PURE__ */ jsxRuntime.jsx(
11653
+ "button",
11654
+ {
11655
+ type: "button",
11656
+ onClick: onRefresh,
11657
+ disabled: refreshing,
11658
+ style: refreshing ? { ...styles.refreshButton, ...styles.disabled } : styles.refreshButton,
11659
+ children: refreshing ? "Refreshing\u2026" : "Refresh"
11660
+ }
11661
+ )
11662
+ ] })
11663
+ ] })
11664
+ ] });
11514
11665
  }
11515
11666
 
11516
11667
  // src/validation.ts
package/dist/index.mjs CHANGED
@@ -11269,6 +11269,156 @@ function FeedbackWidget(props) {
11269
11269
  ] });
11270
11270
  }
11271
11271
  var SPEEDS = [1, 1.25, 1.5, 2];
11272
+ var styles = {
11273
+ root: {
11274
+ borderRadius: "1.75rem",
11275
+ border: "1px solid rgba(226, 232, 240, 0.8)",
11276
+ background: "linear-gradient(180deg, #f8fbff 0%, #edf4ff 100%)",
11277
+ padding: "1rem",
11278
+ color: "#0f172b",
11279
+ boxShadow: "0 22px 70px rgba(4, 12, 24, 0.28)"
11280
+ },
11281
+ layout: {
11282
+ display: "flex",
11283
+ flexWrap: "wrap",
11284
+ alignItems: "center",
11285
+ gap: "1rem"
11286
+ },
11287
+ playButton: {
11288
+ display: "flex",
11289
+ height: "4.5rem",
11290
+ width: "4.5rem",
11291
+ flexShrink: 0,
11292
+ alignItems: "center",
11293
+ justifyContent: "center",
11294
+ borderRadius: "9999px",
11295
+ border: "none",
11296
+ backgroundColor: "#020618",
11297
+ color: "#ffffff",
11298
+ boxShadow: "0 10px 28px rgba(15, 23, 42, 0.25)",
11299
+ cursor: "pointer"
11300
+ },
11301
+ playIcon: {
11302
+ display: "block",
11303
+ width: "1.75rem",
11304
+ height: "1.75rem",
11305
+ fill: "currentColor"
11306
+ },
11307
+ playIconOffset: {
11308
+ marginLeft: "0.25rem"
11309
+ },
11310
+ content: {
11311
+ minWidth: "16rem",
11312
+ flex: "1 1 18rem"
11313
+ },
11314
+ metaRow: {
11315
+ display: "flex",
11316
+ alignItems: "center",
11317
+ justifyContent: "space-between",
11318
+ gap: "0.75rem",
11319
+ fontSize: "0.8rem",
11320
+ fontWeight: 500,
11321
+ color: "#62748e"
11322
+ },
11323
+ metaRight: {
11324
+ display: "flex",
11325
+ alignItems: "center",
11326
+ gap: "0.75rem"
11327
+ },
11328
+ badge: {
11329
+ borderRadius: "9999px",
11330
+ backgroundColor: "#dbeafe",
11331
+ padding: "0.25rem 0.75rem",
11332
+ fontSize: "0.65rem",
11333
+ fontWeight: 600,
11334
+ letterSpacing: "0.24em",
11335
+ textTransform: "uppercase",
11336
+ color: "#1447e6"
11337
+ },
11338
+ scrubber: {
11339
+ position: "relative",
11340
+ marginTop: "1rem",
11341
+ height: "3rem",
11342
+ cursor: "pointer",
11343
+ overflow: "hidden",
11344
+ borderRadius: "1rem",
11345
+ backgroundColor: "rgba(226, 232, 240, 0.9)",
11346
+ paddingInline: "0.25rem"
11347
+ },
11348
+ waveform: {
11349
+ pointerEvents: "none",
11350
+ position: "absolute",
11351
+ inset: 0,
11352
+ height: "100%",
11353
+ width: "100%"
11354
+ },
11355
+ fallbackTrack: {
11356
+ position: "absolute",
11357
+ inset: 0,
11358
+ backgroundColor: "rgba(226, 232, 240, 0.9)"
11359
+ },
11360
+ fallbackProgress: {
11361
+ position: "absolute",
11362
+ insetBlock: 0,
11363
+ left: 0,
11364
+ backgroundColor: "#155dfc"
11365
+ },
11366
+ chipsRow: {
11367
+ marginTop: "1rem",
11368
+ display: "flex",
11369
+ flexWrap: "wrap",
11370
+ alignItems: "center",
11371
+ gap: "0.5rem",
11372
+ fontSize: "0.72rem",
11373
+ fontWeight: 500,
11374
+ color: "#62748e"
11375
+ },
11376
+ chipStrong: {
11377
+ borderRadius: "9999px",
11378
+ border: "1px solid #e2e8f0",
11379
+ backgroundColor: "rgba(255, 255, 255, 0.85)",
11380
+ padding: "0.25rem 0.75rem",
11381
+ color: "#334155"
11382
+ },
11383
+ chipMuted: {
11384
+ borderRadius: "9999px",
11385
+ border: "1px solid #e2e8f0",
11386
+ backgroundColor: "rgba(255, 255, 255, 0.65)",
11387
+ padding: "0.25rem 0.75rem"
11388
+ },
11389
+ controls: {
11390
+ display: "flex",
11391
+ flexShrink: 0,
11392
+ alignItems: "center",
11393
+ gap: "0.5rem",
11394
+ alignSelf: "flex-start"
11395
+ },
11396
+ secondaryButton: {
11397
+ borderRadius: "9999px",
11398
+ border: "1px solid #cad5e2",
11399
+ backgroundColor: "rgba(255, 255, 255, 0.9)",
11400
+ padding: "0.5rem 1rem",
11401
+ fontSize: "1rem",
11402
+ fontWeight: 600,
11403
+ color: "#334155",
11404
+ boxShadow: "0 1px 3px rgba(15, 23, 42, 0.08)",
11405
+ cursor: "pointer"
11406
+ },
11407
+ refreshButton: {
11408
+ borderRadius: "9999px",
11409
+ border: "1px solid #cad5e2",
11410
+ backgroundColor: "rgba(255, 255, 255, 0.75)",
11411
+ padding: "0.5rem 1rem",
11412
+ fontSize: "0.875rem",
11413
+ fontWeight: 600,
11414
+ color: "#334155",
11415
+ cursor: "pointer"
11416
+ },
11417
+ disabled: {
11418
+ cursor: "not-allowed",
11419
+ opacity: 0.6
11420
+ }
11421
+ };
11272
11422
  function formatTime(seconds) {
11273
11423
  if (!Number.isFinite(seconds) || seconds <= 0) {
11274
11424
  return "0:00";
@@ -11351,146 +11501,147 @@ function NarrationPlayer({
11351
11501
  if (!audio.url) {
11352
11502
  return null;
11353
11503
  }
11354
- return /* @__PURE__ */ jsxs(
11355
- "div",
11356
- {
11357
- className: "rounded-[1.75rem] border border-slate-200/80 bg-[linear-gradient(180deg,#f8fbff_0%,#edf4ff_100%)] p-4 text-slate-900 shadow-[0_22px_70px_rgba(4,12,24,0.28)] " + (className ?? ""),
11358
- children: [
11504
+ return /* @__PURE__ */ jsxs("div", { className, style: styles.root, children: [
11505
+ /* @__PURE__ */ jsx(
11506
+ "audio",
11507
+ {
11508
+ ref: audioRef,
11509
+ src: audio.url ?? void 0,
11510
+ preload: "metadata",
11511
+ onLoadedMetadata: (event) => {
11512
+ setDuration(event.currentTarget.duration || 0);
11513
+ },
11514
+ onTimeUpdate: (event) => {
11515
+ setCurrentTime(event.currentTarget.currentTime);
11516
+ },
11517
+ onPlay: () => setPlaying(true),
11518
+ onPause: () => setPlaying(false),
11519
+ onEnded: () => setPlaying(false),
11520
+ onError: () => onPlaybackError?.()
11521
+ }
11522
+ ),
11523
+ /* @__PURE__ */ jsxs("div", { style: styles.layout, children: [
11524
+ /* @__PURE__ */ jsx(
11525
+ "button",
11526
+ {
11527
+ type: "button",
11528
+ onClick: togglePlayback,
11529
+ "aria-label": playing ? "Pause narration" : "Play narration",
11530
+ style: styles.playButton,
11531
+ children: playing ? /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", style: styles.playIcon, "aria-hidden": "true", children: [
11532
+ /* @__PURE__ */ jsx("rect", { x: "6", y: "5", width: "4", height: "14", rx: "1.2" }),
11533
+ /* @__PURE__ */ jsx("rect", { x: "14", y: "5", width: "4", height: "14", rx: "1.2" })
11534
+ ] }) : /* @__PURE__ */ jsx(
11535
+ "svg",
11536
+ {
11537
+ viewBox: "0 0 24 24",
11538
+ style: { ...styles.playIcon, ...styles.playIconOffset },
11539
+ "aria-hidden": "true",
11540
+ children: /* @__PURE__ */ jsx("path", { d: "M7 5.2c0-1.02 1.12-1.65 2-.98l10.2 7.78a1.24 1.24 0 0 1 0 1.98L9 21.76c-.88.67-2-.04-2-1.08V5.2Z" })
11541
+ }
11542
+ )
11543
+ }
11544
+ ),
11545
+ /* @__PURE__ */ jsxs("div", { style: styles.content, children: [
11546
+ /* @__PURE__ */ jsxs("div", { style: styles.metaRow, children: [
11547
+ /* @__PURE__ */ jsx("span", { children: formatTime(currentTime / speed) }),
11548
+ /* @__PURE__ */ jsxs("div", { style: styles.metaRight, children: [
11549
+ /* @__PURE__ */ jsx("span", { style: styles.badge, children: narrationLabel }),
11550
+ /* @__PURE__ */ jsx("span", { children: formatTime(duration / speed) })
11551
+ ] })
11552
+ ] }),
11359
11553
  /* @__PURE__ */ jsx(
11360
- "audio",
11554
+ "div",
11361
11555
  {
11362
- ref: audioRef,
11363
- src: audio.url ?? void 0,
11364
- preload: "metadata",
11365
- onLoadedMetadata: (event) => {
11366
- setDuration(event.currentTarget.duration || 0);
11367
- },
11368
- onTimeUpdate: (event) => {
11369
- setCurrentTime(event.currentTarget.currentTime);
11556
+ ref: scrubRef,
11557
+ role: "slider",
11558
+ "aria-label": "Narration progress",
11559
+ "aria-valuemin": 0,
11560
+ "aria-valuemax": Math.max(1, Math.floor(duration)),
11561
+ "aria-valuenow": Math.floor(currentTime),
11562
+ tabIndex: 0,
11563
+ onClick: (event) => {
11564
+ seekTo(event.clientX);
11370
11565
  },
11371
- onPlay: () => setPlaying(true),
11372
- onPause: () => setPlaying(false),
11373
- onEnded: () => setPlaying(false),
11374
- onError: () => onPlaybackError?.()
11375
- }
11376
- ),
11377
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 md:flex-row md:items-center", children: [
11378
- /* @__PURE__ */ jsx(
11379
- "button",
11380
- {
11381
- type: "button",
11382
- onClick: togglePlayback,
11383
- "aria-label": playing ? "Pause narration" : "Play narration",
11384
- className: "flex h-[4.5rem] w-[4.5rem] shrink-0 items-center justify-center rounded-full bg-slate-950 text-white shadow-[0_10px_28px_rgba(15,23,42,0.25)] transition hover:bg-slate-800",
11385
- children: playing ? /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", className: "h-7 w-7 fill-current", "aria-hidden": "true", children: [
11386
- /* @__PURE__ */ jsx("rect", { x: "6", y: "5", width: "4", height: "14", rx: "1.2" }),
11387
- /* @__PURE__ */ jsx("rect", { x: "14", y: "5", width: "4", height: "14", rx: "1.2" })
11388
- ] }) : /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "ml-1 h-7 w-7 fill-current", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M7 5.2c0-1.02 1.12-1.65 2-.98l10.2 7.78a1.24 1.24 0 0 1 0 1.98L9 21.76c-.88.67-2-.04-2-1.08V5.2Z" }) })
11389
- }
11390
- ),
11391
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
11392
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 text-[0.8rem] font-medium text-slate-500", children: [
11393
- /* @__PURE__ */ jsx("span", { children: formatTime(currentTime / speed) }),
11394
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
11395
- /* @__PURE__ */ jsx("span", { className: "rounded-full bg-blue-100 px-3 py-1 text-[0.65rem] font-semibold uppercase tracking-[0.24em] text-blue-700", children: narrationLabel }),
11396
- /* @__PURE__ */ jsx("span", { children: formatTime(duration / speed) })
11397
- ] })
11398
- ] }),
11399
- /* @__PURE__ */ jsx(
11400
- "div",
11566
+ style: styles.scrubber,
11567
+ children: peaks.length > 0 ? /* @__PURE__ */ jsx(
11568
+ "svg",
11401
11569
  {
11402
- ref: scrubRef,
11403
- role: "slider",
11404
- "aria-label": "Narration progress",
11405
- "aria-valuemin": 0,
11406
- "aria-valuemax": Math.max(1, Math.floor(duration)),
11407
- "aria-valuenow": Math.floor(currentTime),
11408
- tabIndex: 0,
11409
- onClick: (event) => {
11410
- seekTo(event.clientX);
11411
- },
11412
- className: "relative mt-4 h-12 cursor-pointer overflow-hidden rounded-[1rem] bg-slate-200/90 px-1",
11413
- children: peaks.length > 0 ? /* @__PURE__ */ jsx(
11414
- "svg",
11415
- {
11416
- viewBox: `0 0 ${peaks.length} 40`,
11417
- preserveAspectRatio: "none",
11418
- className: "pointer-events-none absolute inset-0 h-full w-full",
11419
- children: peaks.map((peak, index) => {
11420
- const height = Math.max(2, Math.round(Math.abs(peak) * 34));
11421
- const y = (40 - height) / 2;
11422
- const filled = index / peaks.length < progress;
11423
- return /* @__PURE__ */ jsx(
11424
- "rect",
11425
- {
11426
- x: index,
11427
- y,
11428
- width: 0.82,
11429
- height,
11430
- rx: 0.4,
11431
- className: filled ? "fill-blue-600" : "fill-blue-300"
11432
- },
11433
- `${audio.id}-${index}`
11434
- );
11435
- })
11436
- }
11437
- ) : /* @__PURE__ */ jsxs(Fragment, { children: [
11438
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-slate-200/90" }),
11439
- /* @__PURE__ */ jsx(
11440
- "div",
11570
+ viewBox: `0 0 ${peaks.length} 40`,
11571
+ preserveAspectRatio: "none",
11572
+ style: styles.waveform,
11573
+ children: peaks.map((peak, index) => {
11574
+ const height = Math.max(2, Math.round(Math.abs(peak) * 34));
11575
+ const y = (40 - height) / 2;
11576
+ const filled = index / peaks.length < progress;
11577
+ return /* @__PURE__ */ jsx(
11578
+ "rect",
11441
11579
  {
11442
- className: "absolute inset-y-0 left-0 bg-blue-600",
11443
- style: { width: `${progress * 100}%` }
11444
- }
11445
- )
11446
- ] })
11580
+ x: index,
11581
+ y,
11582
+ width: 0.82,
11583
+ height,
11584
+ rx: 0.4,
11585
+ fill: filled ? "#155dfc" : "#90c5ff"
11586
+ },
11587
+ `${audio.id}-${index}`
11588
+ );
11589
+ })
11447
11590
  }
11448
- ),
11449
- /* @__PURE__ */ jsxs("div", { className: "mt-4 flex flex-wrap items-center gap-2 text-[0.72rem] font-medium text-slate-500", children: [
11450
- /* @__PURE__ */ jsxs("span", { className: "rounded-full border border-slate-200 bg-white/85 px-3 py-1 text-slate-700", children: [
11451
- "Provider: ",
11452
- providerLabel
11453
- ] }),
11454
- duration > 0 && /* @__PURE__ */ jsxs("span", { className: "rounded-full border border-slate-200 bg-white/65 px-3 py-1", children: [
11455
- "Length ",
11456
- formatTime(duration / speed)
11457
- ] }),
11458
- expiresLabel && /* @__PURE__ */ jsxs("span", { className: "rounded-full border border-slate-200 bg-white/65 px-3 py-1", children: [
11459
- "Expires ",
11460
- expiresLabel
11461
- ] })
11591
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
11592
+ /* @__PURE__ */ jsx("div", { style: styles.fallbackTrack }),
11593
+ /* @__PURE__ */ jsx(
11594
+ "div",
11595
+ {
11596
+ style: { ...styles.fallbackProgress, width: `${progress * 100}%` }
11597
+ }
11598
+ )
11462
11599
  ] })
11600
+ }
11601
+ ),
11602
+ /* @__PURE__ */ jsxs("div", { style: styles.chipsRow, children: [
11603
+ /* @__PURE__ */ jsxs("span", { style: styles.chipStrong, children: [
11604
+ "Provider: ",
11605
+ providerLabel
11463
11606
  ] }),
11464
- /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-2 self-start md:self-center", children: [
11465
- /* @__PURE__ */ jsxs(
11466
- "button",
11467
- {
11468
- type: "button",
11469
- onClick: () => {
11470
- setSpeed((currentSpeed) => getNextSpeed(currentSpeed));
11471
- },
11472
- className: "rounded-full border border-slate-300 bg-white/90 px-4 py-2 text-base font-semibold text-slate-700 shadow-sm hover:bg-white",
11473
- children: [
11474
- speed,
11475
- "\xD7"
11476
- ]
11477
- }
11478
- ),
11479
- onRefresh && /* @__PURE__ */ jsx(
11480
- "button",
11481
- {
11482
- type: "button",
11483
- onClick: onRefresh,
11484
- disabled: refreshing,
11485
- className: "rounded-full border border-slate-300 bg-white/75 px-4 py-2 text-sm font-semibold text-slate-700 hover:bg-white disabled:cursor-not-allowed disabled:opacity-60",
11486
- children: refreshing ? "Refreshing\u2026" : "Refresh"
11487
- }
11488
- )
11607
+ duration > 0 && /* @__PURE__ */ jsxs("span", { style: styles.chipMuted, children: [
11608
+ "Length ",
11609
+ formatTime(duration / speed)
11610
+ ] }),
11611
+ expiresLabel && /* @__PURE__ */ jsxs("span", { style: styles.chipMuted, children: [
11612
+ "Expires ",
11613
+ expiresLabel
11489
11614
  ] })
11490
11615
  ] })
11491
- ]
11492
- }
11493
- );
11616
+ ] }),
11617
+ /* @__PURE__ */ jsxs("div", { style: styles.controls, children: [
11618
+ /* @__PURE__ */ jsxs(
11619
+ "button",
11620
+ {
11621
+ type: "button",
11622
+ onClick: () => {
11623
+ setSpeed((currentSpeed) => getNextSpeed(currentSpeed));
11624
+ },
11625
+ style: styles.secondaryButton,
11626
+ children: [
11627
+ speed,
11628
+ "\xD7"
11629
+ ]
11630
+ }
11631
+ ),
11632
+ onRefresh && /* @__PURE__ */ jsx(
11633
+ "button",
11634
+ {
11635
+ type: "button",
11636
+ onClick: onRefresh,
11637
+ disabled: refreshing,
11638
+ style: refreshing ? { ...styles.refreshButton, ...styles.disabled } : styles.refreshButton,
11639
+ children: refreshing ? "Refreshing\u2026" : "Refresh"
11640
+ }
11641
+ )
11642
+ ] })
11643
+ ] })
11644
+ ] });
11494
11645
  }
11495
11646
 
11496
11647
  // src/validation.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scalemule/nextjs",
3
- "version": "0.1.21",
3
+ "version": "0.1.22",
4
4
  "description": "ScaleMule SDK for Next.js applications - authentication, storage, and user management",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",