@scalemule/nextjs 0.1.20 → 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.
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
@@ -1945,7 +1945,7 @@ var require_server = __commonJS({
1945
1945
  var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
1946
1946
  var server_exports = {};
1947
1947
  __export(server_exports, {
1948
- FlagClient: () => FlagClient2,
1948
+ FlagClient: () => FlagClient,
1949
1949
  allConditionsMatch: () => allConditionsMatch,
1950
1950
  evaluateFlag: () => evaluateFlag,
1951
1951
  hashToBucket: () => hashToBucket
@@ -2197,7 +2197,7 @@ var require_server = __commonJS({
2197
2197
  bucket: null
2198
2198
  };
2199
2199
  }
2200
- var FlagClient2 = class {
2200
+ var FlagClient = class {
2201
2201
  constructor(options) {
2202
2202
  this.config = null;
2203
2203
  this.flagIndex = /* @__PURE__ */ new Map();
@@ -5197,9 +5197,6 @@ function createWebhookHandler(config = {}) {
5197
5197
  }
5198
5198
  };
5199
5199
  }
5200
-
5201
- // src/server/bootstrap-flags.ts
5202
- var import_server2 = __toESM(require_server());
5203
5200
  var _clients = /* @__PURE__ */ new Map();
5204
5201
  var _initPromises = /* @__PURE__ */ new Map();
5205
5202
  var _serverClient = null;
@@ -5227,7 +5224,8 @@ async function getFlagClient(environment) {
5227
5224
  const pending = _initPromises.get(key);
5228
5225
  if (pending) return pending;
5229
5226
  const promise = (async () => {
5230
- const client = new import_server2.FlagClient({ apiKey, environment, gatewayUrl });
5227
+ const { FlagClient } = await Promise.resolve().then(() => __toESM(require_server()));
5228
+ const client = new FlagClient({ apiKey, environment, gatewayUrl });
5231
5229
  await Promise.race([
5232
5230
  client.init(),
5233
5231
  new Promise(
@@ -1943,7 +1943,7 @@ var require_server = __commonJS({
1943
1943
  var __toCommonJS = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
1944
1944
  var server_exports = {};
1945
1945
  __export(server_exports, {
1946
- FlagClient: () => FlagClient2,
1946
+ FlagClient: () => FlagClient,
1947
1947
  allConditionsMatch: () => allConditionsMatch,
1948
1948
  evaluateFlag: () => evaluateFlag,
1949
1949
  hashToBucket: () => hashToBucket
@@ -2195,7 +2195,7 @@ var require_server = __commonJS({
2195
2195
  bucket: null
2196
2196
  };
2197
2197
  }
2198
- var FlagClient2 = class {
2198
+ var FlagClient = class {
2199
2199
  constructor(options) {
2200
2200
  this.config = null;
2201
2201
  this.flagIndex = /* @__PURE__ */ new Map();
@@ -5195,9 +5195,6 @@ function createWebhookHandler(config = {}) {
5195
5195
  }
5196
5196
  };
5197
5197
  }
5198
-
5199
- // src/server/bootstrap-flags.ts
5200
- var import_server2 = __toESM(require_server());
5201
5198
  var _clients = /* @__PURE__ */ new Map();
5202
5199
  var _initPromises = /* @__PURE__ */ new Map();
5203
5200
  var _serverClient = null;
@@ -5225,7 +5222,8 @@ async function getFlagClient(environment) {
5225
5222
  const pending = _initPromises.get(key);
5226
5223
  if (pending) return pending;
5227
5224
  const promise = (async () => {
5228
- const client = new import_server2.FlagClient({ apiKey, environment, gatewayUrl });
5225
+ const { FlagClient } = await Promise.resolve().then(() => __toESM(require_server()));
5226
+ const client = new FlagClient({ apiKey, environment, gatewayUrl });
5229
5227
  await Promise.race([
5230
5228
  client.init(),
5231
5229
  new Promise(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scalemule/nextjs",
3
- "version": "0.1.20",
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",