@intentai/react 2.0.0 → 2.0.2

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 +253 -204
  2. package/dist/index.mjs +253 -204
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -190,9 +190,9 @@ var containerVariants = {
190
190
  transition: springPresets.smooth
191
191
  },
192
192
  expanded: {
193
- width: 400,
194
- height: 520,
195
- borderRadius: 24,
193
+ width: 360,
194
+ height: "auto",
195
+ borderRadius: 20,
196
196
  transition: {
197
197
  ...springPresets.smooth,
198
198
  staggerChildren: 0.05,
@@ -219,30 +219,6 @@ var contentVariants = {
219
219
  transition: { duration: 0.2 }
220
220
  }
221
221
  };
222
- var categoryVariants = {
223
- hidden: { opacity: 0, y: 20, scale: 0.9 },
224
- visible: (i) => ({
225
- opacity: 1,
226
- y: 0,
227
- scale: 1,
228
- transition: {
229
- delay: i * 0.05,
230
- ...springPresets.smooth
231
- }
232
- }),
233
- hover: {
234
- scale: 1.05,
235
- y: -2,
236
- transition: springPresets.bouncy
237
- },
238
- tap: {
239
- scale: 0.95
240
- },
241
- selected: {
242
- scale: 1,
243
- borderColor: "var(--widget-primary)"
244
- }
245
- };
246
222
  var BreathingRing = ({ isActive }) => {
247
223
  const { reducedMotion } = useWidget();
248
224
  if (reducedMotion) return null;
@@ -277,11 +253,11 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
277
253
  const particleCount = Math.floor(audioLevel * 4);
278
254
  const newParticles = Array.from({ length: particleCount }, () => ({
279
255
  id: Math.random().toString(36).slice(2, 11),
280
- x: 120,
281
- y: 120,
256
+ x: 70,
257
+ y: 70,
282
258
  angle: Math.random() * Math.PI * 2,
283
259
  speed: 1 + Math.random() * 3,
284
- size: 2 + Math.random() * 4,
260
+ size: 2 + Math.random() * 3,
285
261
  color: Math.random() > 0.5 ? "var(--widget-primary-light)" : "var(--widget-accent)"
286
262
  }));
287
263
  setParticles((prev) => [...prev, ...newParticles].slice(-40));
@@ -294,7 +270,7 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
294
270
  return () => clearTimeout(timeout);
295
271
  }, [particles]);
296
272
  const orbScale = 1 + audioLevel * 0.2;
297
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "fiq-ambient-orb", style: { position: "relative", width: 240, height: 240 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: 240, height: 240, viewBox: "0 0 240 240", children: [
273
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "fiq-ambient-orb", style: { position: "relative", width: 140, height: 140, margin: "0 auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: 140, height: 140, viewBox: "0 0 140 140", children: [
298
274
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("defs", { children: [
299
275
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("radialGradient", { id: "orbGradient", cx: "30%", cy: "30%", children: [
300
276
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("stop", { offset: "0%", stopColor: "var(--widget-accent-light)" }),
@@ -309,14 +285,14 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
309
285
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
310
286
  import_framer_motion.motion.circle,
311
287
  {
312
- cx: 120,
313
- cy: 120,
314
- r: 80,
288
+ cx: 70,
289
+ cy: 70,
290
+ r: 50,
315
291
  fill: "none",
316
292
  stroke: "var(--widget-primary-glow)",
317
293
  strokeWidth: 2,
318
294
  animate: {
319
- r: isRecording ? [80, 90, 80] : 80,
295
+ r: isRecording ? [50, 58, 50] : 50,
320
296
  opacity: isRecording ? [0.3, 0.6, 0.3] : 0.3
321
297
  },
322
298
  transition: {
@@ -329,9 +305,9 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
329
305
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
330
306
  import_framer_motion.motion.circle,
331
307
  {
332
- cx: 120,
333
- cy: 120,
334
- r: 60,
308
+ cx: 70,
309
+ cy: 70,
310
+ r: 40,
335
311
  fill: "url(#orbGradient)",
336
312
  filter: "url(#orbGlow)",
337
313
  animate: { scale: reducedMotion ? 1 : orbScale },
@@ -339,7 +315,7 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
339
315
  style: { transformOrigin: "center" }
340
316
  }
341
317
  ),
342
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { transform: "translate(100, 95)", children: [
318
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { transform: "translate(58, 55)", children: [
343
319
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
344
320
  import_framer_motion.motion.path,
345
321
  {
@@ -371,14 +347,14 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
371
347
  particles.map((particle) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
372
348
  import_framer_motion.motion.circle,
373
349
  {
374
- cx: particle.x,
375
- cy: particle.y,
350
+ cx: 70,
351
+ cy: 70,
376
352
  r: particle.size,
377
353
  fill: particle.color,
378
354
  initial: { opacity: 0.8, scale: 1 },
379
355
  animate: {
380
- cx: particle.x + Math.cos(particle.angle) * 80,
381
- cy: particle.y + Math.sin(particle.angle) * 80,
356
+ cx: 70 + Math.cos(particle.angle) * 50,
357
+ cy: 70 + Math.sin(particle.angle) * 50,
382
358
  opacity: 0,
383
359
  scale: 0.5
384
360
  },
@@ -546,68 +522,47 @@ var CategorySelector = ({ categories, selected, onSelect }) => {
546
522
  {
547
523
  style: {
548
524
  display: "block",
549
- fontSize: 13,
550
- fontWeight: 600,
551
- color: "var(--widget-text-secondary)",
552
- marginBottom: 10,
553
- textTransform: "uppercase",
554
- letterSpacing: "0.05em"
525
+ fontSize: 12,
526
+ fontWeight: 500,
527
+ color: "var(--widget-text-muted)",
528
+ marginBottom: 10
555
529
  },
556
- children: "Category"
530
+ children: "What's this about?"
557
531
  }
558
532
  ),
559
533
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
560
534
  "div",
561
535
  {
562
536
  style: {
563
- display: "grid",
564
- gridTemplateColumns: "repeat(auto-fit, minmax(100px, 1fr))",
565
- gap: 10
537
+ display: "flex",
538
+ flexWrap: "wrap",
539
+ gap: 8
566
540
  },
567
- children: categories.map((category, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
541
+ children: categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
568
542
  import_framer_motion.motion.button,
569
543
  {
570
- custom: index,
571
- variants: categoryVariants,
572
- initial: "hidden",
573
- animate: selected === category.id ? "selected" : "visible",
574
- whileHover: "hover",
575
- whileTap: "tap",
544
+ whileHover: { scale: 1.03 },
545
+ whileTap: { scale: 0.97 },
576
546
  onClick: () => onSelect(category.id),
577
547
  style: {
578
- display: "flex",
579
- flexDirection: "column",
580
- alignItems: "center",
581
- gap: 6,
582
- padding: "12px 8px",
583
- background: selected === category.id ? "var(--widget-primary)" : "var(--widget-glass-bg)",
584
- border: `2px solid ${selected === category.id ? "var(--widget-primary)" : "var(--widget-glass-border)"}`,
585
- borderRadius: 12,
548
+ padding: "8px 16px",
549
+ background: selected === category.id ? "var(--widget-primary)" : "transparent",
550
+ border: `1.5px solid ${selected === category.id ? "var(--widget-primary)" : "var(--widget-glass-border)"}`,
551
+ borderRadius: 20,
586
552
  cursor: "pointer",
587
- transition: "background 0.2s, border-color 0.2s"
553
+ transition: "all 0.2s ease"
588
554
  },
589
- children: [
590
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
591
- import_framer_motion.motion.span,
592
- {
593
- style: { fontSize: 20 },
594
- animate: selected === category.id ? { scale: [1, 1.3, 1], rotate: [0, 10, -10, 0] } : {},
595
- transition: { duration: 0.4 },
596
- children: category.icon
597
- }
598
- ),
599
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
600
- "span",
601
- {
602
- style: {
603
- fontSize: 12,
604
- fontWeight: 500,
605
- color: selected === category.id ? "white" : "var(--widget-text-primary)"
606
- },
607
- children: category.label
608
- }
609
- )
610
- ]
555
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
556
+ "span",
557
+ {
558
+ style: {
559
+ fontSize: 13,
560
+ fontWeight: 500,
561
+ color: selected === category.id ? "white" : "var(--widget-text-primary)"
562
+ },
563
+ children: category.label
564
+ }
565
+ )
611
566
  },
612
567
  category.id
613
568
  ))
@@ -762,7 +717,7 @@ var SuccessCelebration = ({ onComplete }) => {
762
717
  }
763
718
  );
764
719
  };
765
- var MagneticButton = ({ children, onClick, variant = "primary", disabled, loading }) => {
720
+ var MagneticButton = ({ children, onClick, onPressStart, onPressEnd, variant = "primary", disabled, loading }) => {
766
721
  const buttonRef = (0, import_react.useRef)(null);
767
722
  const [magnetOffset, setMagnetOffset] = (0, import_react.useState)({ x: 0, y: 0 });
768
723
  const handleMouseMove = (e) => {
@@ -805,8 +760,20 @@ var MagneticButton = ({ children, onClick, variant = "primary", disabled, loadin
805
760
  ghost: {
806
761
  background: "transparent",
807
762
  color: "var(--widget-text-secondary)"
763
+ },
764
+ recording: {
765
+ background: "var(--widget-recording)",
766
+ color: "white"
808
767
  }
809
768
  };
769
+ const handlePressStart = () => {
770
+ if (disabled || loading) return;
771
+ onPressStart?.();
772
+ };
773
+ const handlePressEnd = () => {
774
+ if (disabled || loading) return;
775
+ onPressEnd?.();
776
+ };
810
777
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
811
778
  import_framer_motion.motion.button,
812
779
  {
@@ -814,7 +781,14 @@ var MagneticButton = ({ children, onClick, variant = "primary", disabled, loadin
814
781
  onClick,
815
782
  disabled: disabled || loading,
816
783
  onMouseMove: handleMouseMove,
817
- onMouseLeave: handleMouseLeave,
784
+ onMouseLeave: () => {
785
+ handleMouseLeave();
786
+ if (onPressEnd) handlePressEnd();
787
+ },
788
+ onMouseDown: onPressStart ? handlePressStart : void 0,
789
+ onMouseUp: onPressEnd ? handlePressEnd : void 0,
790
+ onTouchStart: onPressStart ? handlePressStart : void 0,
791
+ onTouchEnd: onPressEnd ? handlePressEnd : void 0,
818
792
  animate: {
819
793
  x: magnetOffset.x,
820
794
  y: magnetOffset.y,
@@ -842,11 +816,11 @@ var MagneticButton = ({ children, onClick, variant = "primary", disabled, loadin
842
816
  );
843
817
  };
844
818
  var DEFAULT_CATEGORIES = [
845
- { id: "bug", label: "Bug", icon: "\u{1F41B}" },
846
- { id: "feature", label: "Feature", icon: "\u2728" },
847
- { id: "improvement", label: "Improve", icon: "\u{1F4A1}" },
848
- { id: "praise", label: "Praise", icon: "\u2764\uFE0F" },
849
- { id: "other", label: "Other", icon: "\u{1F4AC}" }
819
+ { id: "bug", label: "Bug", icon: "" },
820
+ { id: "feature", label: "Feature", icon: "" },
821
+ { id: "improvement", label: "Improve", icon: "" },
822
+ { id: "praise", label: "Praise", icon: "" },
823
+ { id: "other", label: "Other", icon: "" }
850
824
  ];
851
825
  var PremiumVoiceWidget = ({
852
826
  position = "bottom-right",
@@ -989,6 +963,24 @@ var PremiumVoiceWidget = ({
989
963
  return "idle";
990
964
  }, [isExpanded, scrollState, state]);
991
965
  const shouldShowAttentionPulse = timeOnPage === 60 && !isExpanded && frustrationLevel < 3;
966
+ const [showPrompt, setShowPrompt] = (0, import_react.useState)(false);
967
+ const promptMessages = [
968
+ "Help us improve!",
969
+ "Got feedback?",
970
+ "Share your thoughts",
971
+ "We'd love to hear from you"
972
+ ];
973
+ const [promptMessage, setPromptMessage] = (0, import_react.useState)(promptMessages[0]);
974
+ (0, import_react.useEffect)(() => {
975
+ if (isExpanded) return;
976
+ const showTimes = [30, 90, 180];
977
+ if (showTimes.includes(timeOnPage)) {
978
+ setPromptMessage(promptMessages[Math.floor(Math.random() * promptMessages.length)]);
979
+ setShowPrompt(true);
980
+ const timer = setTimeout(() => setShowPrompt(false), 4e3);
981
+ return () => clearTimeout(timer);
982
+ }
983
+ }, [timeOnPage, isExpanded]);
992
984
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WidgetContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
993
985
  "div",
994
986
  {
@@ -1001,111 +993,167 @@ var PremiumVoiceWidget = ({
1001
993
  fontFamily: "system-ui, -apple-system, sans-serif"
1002
994
  },
1003
995
  children: [
1004
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_framer_motion.AnimatePresence, { mode: "wait", children: !isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1005
- import_framer_motion.motion.button,
1006
- {
1007
- ref: triggerRef,
1008
- variants: triggerVariants,
1009
- initial: "idle",
1010
- animate: triggerState,
1011
- exit: "hidden",
1012
- whileHover: "hover",
1013
- whileTap: "tap",
1014
- onClick: handleOpen,
1015
- onMouseEnter: () => setState("hover"),
1016
- onMouseLeave: () => setState("idle"),
1017
- "aria-label": "Open feedback widget",
1018
- "aria-expanded": isExpanded,
1019
- style: {
1020
- width: 56,
1021
- height: 56,
1022
- borderRadius: "50%",
1023
- border: "none",
1024
- cursor: "pointer",
1025
- position: "relative",
1026
- background: "var(--widget-glass-bg)",
1027
- backdropFilter: "blur(20px) saturate(180%)",
1028
- WebkitBackdropFilter: "blur(20px) saturate(180%)",
1029
- boxShadow: `
996
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_framer_motion.AnimatePresence, { mode: "wait", children: [
997
+ !isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
998
+ import_framer_motion.motion.button,
999
+ {
1000
+ ref: triggerRef,
1001
+ variants: triggerVariants,
1002
+ initial: "idle",
1003
+ animate: triggerState,
1004
+ exit: "hidden",
1005
+ whileHover: "hover",
1006
+ whileTap: "tap",
1007
+ onClick: handleOpen,
1008
+ onMouseEnter: () => setState("hover"),
1009
+ onMouseLeave: () => setState("idle"),
1010
+ "aria-label": "Open feedback widget",
1011
+ "aria-expanded": isExpanded,
1012
+ style: {
1013
+ width: 56,
1014
+ height: 56,
1015
+ borderRadius: "50%",
1016
+ border: "none",
1017
+ cursor: "pointer",
1018
+ position: "relative",
1019
+ background: "var(--widget-glass-bg)",
1020
+ backdropFilter: "blur(20px) saturate(180%)",
1021
+ WebkitBackdropFilter: "blur(20px) saturate(180%)",
1022
+ boxShadow: `
1030
1023
  inset 0 0 0 1px var(--widget-glass-highlight),
1031
1024
  0 4px 24px -4px rgba(0, 0, 0, 0.5),
1032
1025
  0 0 40px -10px var(--widget-primary-glow)
1033
1026
  `
1034
- },
1035
- children: [
1036
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BreathingRing, { isActive: !reducedMotion && triggerState === "idle" }),
1037
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1038
- "div",
1039
- {
1040
- style: {
1041
- position: "absolute",
1042
- inset: 3,
1043
- borderRadius: "50%",
1044
- background: `linear-gradient(135deg, var(--widget-primary) 0%, var(--widget-accent) 100%)`,
1045
- opacity: 0.9
1027
+ },
1028
+ children: [
1029
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BreathingRing, { isActive: !reducedMotion && triggerState === "idle" }),
1030
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1031
+ "div",
1032
+ {
1033
+ style: {
1034
+ position: "absolute",
1035
+ inset: 3,
1036
+ borderRadius: "50%",
1037
+ background: `linear-gradient(135deg, var(--widget-primary) 0%, var(--widget-accent) 100%)`,
1038
+ opacity: 0.9
1039
+ }
1046
1040
  }
1047
- }
1048
- ),
1049
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1050
- "svg",
1051
- {
1052
- width: 24,
1053
- height: 24,
1054
- viewBox: "0 0 24 24",
1055
- fill: "none",
1056
- stroke: "white",
1057
- strokeWidth: 2,
1058
- strokeLinecap: "round",
1059
- style: { position: "relative", zIndex: 1 },
1060
- children: [
1061
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
1062
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
1063
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
1064
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
1065
- ]
1066
- }
1067
- ),
1068
- shouldShowAttentionPulse && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1069
- import_framer_motion.motion.div,
1070
- {
1071
- initial: { scale: 1, opacity: 1 },
1072
- animate: { scale: 1.5, opacity: 0 },
1073
- transition: { duration: 1, repeat: 3 },
1074
- style: {
1075
- position: "absolute",
1076
- inset: 0,
1077
- borderRadius: "50%",
1078
- border: "2px solid var(--widget-primary)",
1079
- pointerEvents: "none"
1041
+ ),
1042
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1043
+ "svg",
1044
+ {
1045
+ width: 24,
1046
+ height: 24,
1047
+ viewBox: "0 0 24 24",
1048
+ fill: "none",
1049
+ stroke: "white",
1050
+ strokeWidth: 2,
1051
+ strokeLinecap: "round",
1052
+ style: {
1053
+ position: "absolute",
1054
+ top: "50%",
1055
+ left: "50%",
1056
+ transform: "translate(-50%, -50%)",
1057
+ zIndex: 1
1058
+ },
1059
+ children: [
1060
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
1061
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
1062
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
1063
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
1064
+ ]
1080
1065
  }
1081
- }
1082
- ),
1083
- frustrationLevel >= 5 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1084
- import_framer_motion.motion.div,
1085
- {
1086
- initial: { scale: 0 },
1087
- animate: { scale: 1 },
1088
- style: {
1089
- position: "absolute",
1090
- top: -4,
1091
- right: -4,
1092
- width: 16,
1093
- height: 16,
1094
- borderRadius: "50%",
1095
- background: "var(--widget-frustrated)",
1096
- border: "2px solid var(--widget-glass-bg)",
1097
- display: "flex",
1098
- alignItems: "center",
1099
- justifyContent: "center",
1100
- fontSize: 10
1101
- },
1102
- children: "?"
1103
- }
1104
- )
1105
- ]
1106
- },
1107
- "trigger"
1108
- ) }),
1066
+ ),
1067
+ shouldShowAttentionPulse && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1068
+ import_framer_motion.motion.div,
1069
+ {
1070
+ initial: { scale: 1, opacity: 1 },
1071
+ animate: { scale: 1.5, opacity: 0 },
1072
+ transition: { duration: 1, repeat: 3 },
1073
+ style: {
1074
+ position: "absolute",
1075
+ inset: 0,
1076
+ borderRadius: "50%",
1077
+ border: "2px solid var(--widget-primary)",
1078
+ pointerEvents: "none"
1079
+ }
1080
+ }
1081
+ ),
1082
+ frustrationLevel >= 5 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1083
+ import_framer_motion.motion.div,
1084
+ {
1085
+ initial: { scale: 0 },
1086
+ animate: { scale: 1 },
1087
+ style: {
1088
+ position: "absolute",
1089
+ top: -4,
1090
+ right: -4,
1091
+ width: 16,
1092
+ height: 16,
1093
+ borderRadius: "50%",
1094
+ background: "var(--widget-frustrated)",
1095
+ border: "2px solid var(--widget-glass-bg)",
1096
+ display: "flex",
1097
+ alignItems: "center",
1098
+ justifyContent: "center",
1099
+ fontSize: 10
1100
+ },
1101
+ children: "?"
1102
+ }
1103
+ )
1104
+ ]
1105
+ },
1106
+ "trigger"
1107
+ ),
1108
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_framer_motion.AnimatePresence, { children: showPrompt && !isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1109
+ import_framer_motion.motion.div,
1110
+ {
1111
+ initial: { opacity: 0, x: 10, scale: 0.9 },
1112
+ animate: { opacity: 1, x: 0, scale: 1 },
1113
+ exit: { opacity: 0, x: 10, scale: 0.9 },
1114
+ transition: springPresets.smooth,
1115
+ onClick: handleOpen,
1116
+ style: {
1117
+ position: "absolute",
1118
+ right: 70,
1119
+ top: "50%",
1120
+ transform: "translateY(-50%)",
1121
+ background: "var(--widget-glass-bg)",
1122
+ backdropFilter: "blur(12px)",
1123
+ WebkitBackdropFilter: "blur(12px)",
1124
+ border: "1px solid var(--widget-glass-border)",
1125
+ borderRadius: 12,
1126
+ padding: "10px 16px",
1127
+ boxShadow: "0 4px 20px rgba(0,0,0,0.3)",
1128
+ cursor: "pointer",
1129
+ whiteSpace: "nowrap"
1130
+ },
1131
+ children: [
1132
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: {
1133
+ fontSize: 13,
1134
+ fontWeight: 500,
1135
+ color: "var(--widget-text-primary)"
1136
+ }, children: promptMessage }),
1137
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1138
+ "div",
1139
+ {
1140
+ style: {
1141
+ position: "absolute",
1142
+ right: -6,
1143
+ top: "50%",
1144
+ transform: "translateY(-50%) rotate(45deg)",
1145
+ width: 12,
1146
+ height: 12,
1147
+ background: "var(--widget-glass-bg)",
1148
+ borderRight: "1px solid var(--widget-glass-border)",
1149
+ borderTop: "1px solid var(--widget-glass-border)"
1150
+ }
1151
+ }
1152
+ )
1153
+ ]
1154
+ }
1155
+ ) })
1156
+ ] }),
1109
1157
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_framer_motion.AnimatePresence, { mode: "wait", children: isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1110
1158
  import_framer_motion.motion.div,
1111
1159
  {
@@ -1241,7 +1289,7 @@ var PremiumVoiceWidget = ({
1241
1289
  ))
1242
1290
  }
1243
1291
  ),
1244
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { flex: 1, overflow: "auto", padding: 24 }, children: [
1292
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "20px 24px" }, children: [
1245
1293
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginBottom: 24 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1246
1294
  CategorySelector,
1247
1295
  {
@@ -1267,7 +1315,7 @@ var PremiumVoiceWidget = ({
1267
1315
  fontSize: 14,
1268
1316
  marginTop: 16
1269
1317
  },
1270
- children: "Tap the orb to start recording"
1318
+ children: "Hold to record"
1271
1319
  }
1272
1320
  ),
1273
1321
  (isRecording || transcription) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginTop: 20 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -1280,8 +1328,9 @@ var PremiumVoiceWidget = ({
1280
1328
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginTop: 20 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1281
1329
  MagneticButton,
1282
1330
  {
1283
- onClick: isRecording ? handleStopRecording : handleStartRecording,
1284
- variant: isRecording ? "secondary" : "primary",
1331
+ onPressStart: handleStartRecording,
1332
+ onPressEnd: handleStopRecording,
1333
+ variant: isRecording ? "recording" : "primary",
1285
1334
  children: isRecording ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1286
1335
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1287
1336
  "svg",
@@ -1290,11 +1339,11 @@ var PremiumVoiceWidget = ({
1290
1339
  height: 16,
1291
1340
  viewBox: "0 0 24 24",
1292
1341
  fill: "currentColor",
1293
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: 6, y: 6, width: 12, height: 12, rx: 2 })
1342
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: 12, cy: 12, r: 6 })
1294
1343
  }
1295
1344
  ),
1296
- "Stop Recording"
1297
- ] }) : recordingSeconds > 0 ? "Record Again" : "Start Recording"
1345
+ "Recording..."
1346
+ ] }) : transcription ? "Hold to record more" : "Hold to record"
1298
1347
  }
1299
1348
  ) })
1300
1349
  ] }),
package/dist/index.mjs CHANGED
@@ -172,9 +172,9 @@ var containerVariants = {
172
172
  transition: springPresets.smooth
173
173
  },
174
174
  expanded: {
175
- width: 400,
176
- height: 520,
177
- borderRadius: 24,
175
+ width: 360,
176
+ height: "auto",
177
+ borderRadius: 20,
178
178
  transition: {
179
179
  ...springPresets.smooth,
180
180
  staggerChildren: 0.05,
@@ -201,30 +201,6 @@ var contentVariants = {
201
201
  transition: { duration: 0.2 }
202
202
  }
203
203
  };
204
- var categoryVariants = {
205
- hidden: { opacity: 0, y: 20, scale: 0.9 },
206
- visible: (i) => ({
207
- opacity: 1,
208
- y: 0,
209
- scale: 1,
210
- transition: {
211
- delay: i * 0.05,
212
- ...springPresets.smooth
213
- }
214
- }),
215
- hover: {
216
- scale: 1.05,
217
- y: -2,
218
- transition: springPresets.bouncy
219
- },
220
- tap: {
221
- scale: 0.95
222
- },
223
- selected: {
224
- scale: 1,
225
- borderColor: "var(--widget-primary)"
226
- }
227
- };
228
204
  var BreathingRing = ({ isActive }) => {
229
205
  const { reducedMotion } = useWidget();
230
206
  if (reducedMotion) return null;
@@ -259,11 +235,11 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
259
235
  const particleCount = Math.floor(audioLevel * 4);
260
236
  const newParticles = Array.from({ length: particleCount }, () => ({
261
237
  id: Math.random().toString(36).slice(2, 11),
262
- x: 120,
263
- y: 120,
238
+ x: 70,
239
+ y: 70,
264
240
  angle: Math.random() * Math.PI * 2,
265
241
  speed: 1 + Math.random() * 3,
266
- size: 2 + Math.random() * 4,
242
+ size: 2 + Math.random() * 3,
267
243
  color: Math.random() > 0.5 ? "var(--widget-primary-light)" : "var(--widget-accent)"
268
244
  }));
269
245
  setParticles((prev) => [...prev, ...newParticles].slice(-40));
@@ -276,7 +252,7 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
276
252
  return () => clearTimeout(timeout);
277
253
  }, [particles]);
278
254
  const orbScale = 1 + audioLevel * 0.2;
279
- return /* @__PURE__ */ jsx("div", { className: "fiq-ambient-orb", style: { position: "relative", width: 240, height: 240 }, children: /* @__PURE__ */ jsxs("svg", { width: 240, height: 240, viewBox: "0 0 240 240", children: [
255
+ return /* @__PURE__ */ jsx("div", { className: "fiq-ambient-orb", style: { position: "relative", width: 140, height: 140, margin: "0 auto" }, children: /* @__PURE__ */ jsxs("svg", { width: 140, height: 140, viewBox: "0 0 140 140", children: [
280
256
  /* @__PURE__ */ jsxs("defs", { children: [
281
257
  /* @__PURE__ */ jsxs("radialGradient", { id: "orbGradient", cx: "30%", cy: "30%", children: [
282
258
  /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "var(--widget-accent-light)" }),
@@ -291,14 +267,14 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
291
267
  /* @__PURE__ */ jsx(
292
268
  motion.circle,
293
269
  {
294
- cx: 120,
295
- cy: 120,
296
- r: 80,
270
+ cx: 70,
271
+ cy: 70,
272
+ r: 50,
297
273
  fill: "none",
298
274
  stroke: "var(--widget-primary-glow)",
299
275
  strokeWidth: 2,
300
276
  animate: {
301
- r: isRecording ? [80, 90, 80] : 80,
277
+ r: isRecording ? [50, 58, 50] : 50,
302
278
  opacity: isRecording ? [0.3, 0.6, 0.3] : 0.3
303
279
  },
304
280
  transition: {
@@ -311,9 +287,9 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
311
287
  /* @__PURE__ */ jsx(
312
288
  motion.circle,
313
289
  {
314
- cx: 120,
315
- cy: 120,
316
- r: 60,
290
+ cx: 70,
291
+ cy: 70,
292
+ r: 40,
317
293
  fill: "url(#orbGradient)",
318
294
  filter: "url(#orbGlow)",
319
295
  animate: { scale: reducedMotion ? 1 : orbScale },
@@ -321,7 +297,7 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
321
297
  style: { transformOrigin: "center" }
322
298
  }
323
299
  ),
324
- /* @__PURE__ */ jsxs("g", { transform: "translate(100, 95)", children: [
300
+ /* @__PURE__ */ jsxs("g", { transform: "translate(58, 55)", children: [
325
301
  /* @__PURE__ */ jsx(
326
302
  motion.path,
327
303
  {
@@ -353,14 +329,14 @@ var AmbientOrb = ({ audioLevel, isRecording }) => {
353
329
  particles.map((particle) => /* @__PURE__ */ jsx(
354
330
  motion.circle,
355
331
  {
356
- cx: particle.x,
357
- cy: particle.y,
332
+ cx: 70,
333
+ cy: 70,
358
334
  r: particle.size,
359
335
  fill: particle.color,
360
336
  initial: { opacity: 0.8, scale: 1 },
361
337
  animate: {
362
- cx: particle.x + Math.cos(particle.angle) * 80,
363
- cy: particle.y + Math.sin(particle.angle) * 80,
338
+ cx: 70 + Math.cos(particle.angle) * 50,
339
+ cy: 70 + Math.sin(particle.angle) * 50,
364
340
  opacity: 0,
365
341
  scale: 0.5
366
342
  },
@@ -528,68 +504,47 @@ var CategorySelector = ({ categories, selected, onSelect }) => {
528
504
  {
529
505
  style: {
530
506
  display: "block",
531
- fontSize: 13,
532
- fontWeight: 600,
533
- color: "var(--widget-text-secondary)",
534
- marginBottom: 10,
535
- textTransform: "uppercase",
536
- letterSpacing: "0.05em"
507
+ fontSize: 12,
508
+ fontWeight: 500,
509
+ color: "var(--widget-text-muted)",
510
+ marginBottom: 10
537
511
  },
538
- children: "Category"
512
+ children: "What's this about?"
539
513
  }
540
514
  ),
541
515
  /* @__PURE__ */ jsx(
542
516
  "div",
543
517
  {
544
518
  style: {
545
- display: "grid",
546
- gridTemplateColumns: "repeat(auto-fit, minmax(100px, 1fr))",
547
- gap: 10
519
+ display: "flex",
520
+ flexWrap: "wrap",
521
+ gap: 8
548
522
  },
549
- children: categories.map((category, index) => /* @__PURE__ */ jsxs(
523
+ children: categories.map((category) => /* @__PURE__ */ jsx(
550
524
  motion.button,
551
525
  {
552
- custom: index,
553
- variants: categoryVariants,
554
- initial: "hidden",
555
- animate: selected === category.id ? "selected" : "visible",
556
- whileHover: "hover",
557
- whileTap: "tap",
526
+ whileHover: { scale: 1.03 },
527
+ whileTap: { scale: 0.97 },
558
528
  onClick: () => onSelect(category.id),
559
529
  style: {
560
- display: "flex",
561
- flexDirection: "column",
562
- alignItems: "center",
563
- gap: 6,
564
- padding: "12px 8px",
565
- background: selected === category.id ? "var(--widget-primary)" : "var(--widget-glass-bg)",
566
- border: `2px solid ${selected === category.id ? "var(--widget-primary)" : "var(--widget-glass-border)"}`,
567
- borderRadius: 12,
530
+ padding: "8px 16px",
531
+ background: selected === category.id ? "var(--widget-primary)" : "transparent",
532
+ border: `1.5px solid ${selected === category.id ? "var(--widget-primary)" : "var(--widget-glass-border)"}`,
533
+ borderRadius: 20,
568
534
  cursor: "pointer",
569
- transition: "background 0.2s, border-color 0.2s"
535
+ transition: "all 0.2s ease"
570
536
  },
571
- children: [
572
- /* @__PURE__ */ jsx(
573
- motion.span,
574
- {
575
- style: { fontSize: 20 },
576
- animate: selected === category.id ? { scale: [1, 1.3, 1], rotate: [0, 10, -10, 0] } : {},
577
- transition: { duration: 0.4 },
578
- children: category.icon
579
- }
580
- ),
581
- /* @__PURE__ */ jsx(
582
- "span",
583
- {
584
- style: {
585
- fontSize: 12,
586
- fontWeight: 500,
587
- color: selected === category.id ? "white" : "var(--widget-text-primary)"
588
- },
589
- children: category.label
590
- }
591
- )
592
- ]
537
+ children: /* @__PURE__ */ jsx(
538
+ "span",
539
+ {
540
+ style: {
541
+ fontSize: 13,
542
+ fontWeight: 500,
543
+ color: selected === category.id ? "white" : "var(--widget-text-primary)"
544
+ },
545
+ children: category.label
546
+ }
547
+ )
593
548
  },
594
549
  category.id
595
550
  ))
@@ -744,7 +699,7 @@ var SuccessCelebration = ({ onComplete }) => {
744
699
  }
745
700
  );
746
701
  };
747
- var MagneticButton = ({ children, onClick, variant = "primary", disabled, loading }) => {
702
+ var MagneticButton = ({ children, onClick, onPressStart, onPressEnd, variant = "primary", disabled, loading }) => {
748
703
  const buttonRef = useRef(null);
749
704
  const [magnetOffset, setMagnetOffset] = useState({ x: 0, y: 0 });
750
705
  const handleMouseMove = (e) => {
@@ -787,8 +742,20 @@ var MagneticButton = ({ children, onClick, variant = "primary", disabled, loadin
787
742
  ghost: {
788
743
  background: "transparent",
789
744
  color: "var(--widget-text-secondary)"
745
+ },
746
+ recording: {
747
+ background: "var(--widget-recording)",
748
+ color: "white"
790
749
  }
791
750
  };
751
+ const handlePressStart = () => {
752
+ if (disabled || loading) return;
753
+ onPressStart?.();
754
+ };
755
+ const handlePressEnd = () => {
756
+ if (disabled || loading) return;
757
+ onPressEnd?.();
758
+ };
792
759
  return /* @__PURE__ */ jsx(
793
760
  motion.button,
794
761
  {
@@ -796,7 +763,14 @@ var MagneticButton = ({ children, onClick, variant = "primary", disabled, loadin
796
763
  onClick,
797
764
  disabled: disabled || loading,
798
765
  onMouseMove: handleMouseMove,
799
- onMouseLeave: handleMouseLeave,
766
+ onMouseLeave: () => {
767
+ handleMouseLeave();
768
+ if (onPressEnd) handlePressEnd();
769
+ },
770
+ onMouseDown: onPressStart ? handlePressStart : void 0,
771
+ onMouseUp: onPressEnd ? handlePressEnd : void 0,
772
+ onTouchStart: onPressStart ? handlePressStart : void 0,
773
+ onTouchEnd: onPressEnd ? handlePressEnd : void 0,
800
774
  animate: {
801
775
  x: magnetOffset.x,
802
776
  y: magnetOffset.y,
@@ -824,11 +798,11 @@ var MagneticButton = ({ children, onClick, variant = "primary", disabled, loadin
824
798
  );
825
799
  };
826
800
  var DEFAULT_CATEGORIES = [
827
- { id: "bug", label: "Bug", icon: "\u{1F41B}" },
828
- { id: "feature", label: "Feature", icon: "\u2728" },
829
- { id: "improvement", label: "Improve", icon: "\u{1F4A1}" },
830
- { id: "praise", label: "Praise", icon: "\u2764\uFE0F" },
831
- { id: "other", label: "Other", icon: "\u{1F4AC}" }
801
+ { id: "bug", label: "Bug", icon: "" },
802
+ { id: "feature", label: "Feature", icon: "" },
803
+ { id: "improvement", label: "Improve", icon: "" },
804
+ { id: "praise", label: "Praise", icon: "" },
805
+ { id: "other", label: "Other", icon: "" }
832
806
  ];
833
807
  var PremiumVoiceWidget = ({
834
808
  position = "bottom-right",
@@ -971,6 +945,24 @@ var PremiumVoiceWidget = ({
971
945
  return "idle";
972
946
  }, [isExpanded, scrollState, state]);
973
947
  const shouldShowAttentionPulse = timeOnPage === 60 && !isExpanded && frustrationLevel < 3;
948
+ const [showPrompt, setShowPrompt] = useState(false);
949
+ const promptMessages = [
950
+ "Help us improve!",
951
+ "Got feedback?",
952
+ "Share your thoughts",
953
+ "We'd love to hear from you"
954
+ ];
955
+ const [promptMessage, setPromptMessage] = useState(promptMessages[0]);
956
+ useEffect(() => {
957
+ if (isExpanded) return;
958
+ const showTimes = [30, 90, 180];
959
+ if (showTimes.includes(timeOnPage)) {
960
+ setPromptMessage(promptMessages[Math.floor(Math.random() * promptMessages.length)]);
961
+ setShowPrompt(true);
962
+ const timer = setTimeout(() => setShowPrompt(false), 4e3);
963
+ return () => clearTimeout(timer);
964
+ }
965
+ }, [timeOnPage, isExpanded]);
974
966
  return /* @__PURE__ */ jsx(WidgetContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
975
967
  "div",
976
968
  {
@@ -983,111 +975,167 @@ var PremiumVoiceWidget = ({
983
975
  fontFamily: "system-ui, -apple-system, sans-serif"
984
976
  },
985
977
  children: [
986
- /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: !isExpanded && /* @__PURE__ */ jsxs(
987
- motion.button,
988
- {
989
- ref: triggerRef,
990
- variants: triggerVariants,
991
- initial: "idle",
992
- animate: triggerState,
993
- exit: "hidden",
994
- whileHover: "hover",
995
- whileTap: "tap",
996
- onClick: handleOpen,
997
- onMouseEnter: () => setState("hover"),
998
- onMouseLeave: () => setState("idle"),
999
- "aria-label": "Open feedback widget",
1000
- "aria-expanded": isExpanded,
1001
- style: {
1002
- width: 56,
1003
- height: 56,
1004
- borderRadius: "50%",
1005
- border: "none",
1006
- cursor: "pointer",
1007
- position: "relative",
1008
- background: "var(--widget-glass-bg)",
1009
- backdropFilter: "blur(20px) saturate(180%)",
1010
- WebkitBackdropFilter: "blur(20px) saturate(180%)",
1011
- boxShadow: `
978
+ /* @__PURE__ */ jsxs(AnimatePresence, { mode: "wait", children: [
979
+ !isExpanded && /* @__PURE__ */ jsxs(
980
+ motion.button,
981
+ {
982
+ ref: triggerRef,
983
+ variants: triggerVariants,
984
+ initial: "idle",
985
+ animate: triggerState,
986
+ exit: "hidden",
987
+ whileHover: "hover",
988
+ whileTap: "tap",
989
+ onClick: handleOpen,
990
+ onMouseEnter: () => setState("hover"),
991
+ onMouseLeave: () => setState("idle"),
992
+ "aria-label": "Open feedback widget",
993
+ "aria-expanded": isExpanded,
994
+ style: {
995
+ width: 56,
996
+ height: 56,
997
+ borderRadius: "50%",
998
+ border: "none",
999
+ cursor: "pointer",
1000
+ position: "relative",
1001
+ background: "var(--widget-glass-bg)",
1002
+ backdropFilter: "blur(20px) saturate(180%)",
1003
+ WebkitBackdropFilter: "blur(20px) saturate(180%)",
1004
+ boxShadow: `
1012
1005
  inset 0 0 0 1px var(--widget-glass-highlight),
1013
1006
  0 4px 24px -4px rgba(0, 0, 0, 0.5),
1014
1007
  0 0 40px -10px var(--widget-primary-glow)
1015
1008
  `
1016
- },
1017
- children: [
1018
- /* @__PURE__ */ jsx(BreathingRing, { isActive: !reducedMotion && triggerState === "idle" }),
1019
- /* @__PURE__ */ jsx(
1020
- "div",
1021
- {
1022
- style: {
1023
- position: "absolute",
1024
- inset: 3,
1025
- borderRadius: "50%",
1026
- background: `linear-gradient(135deg, var(--widget-primary) 0%, var(--widget-accent) 100%)`,
1027
- opacity: 0.9
1009
+ },
1010
+ children: [
1011
+ /* @__PURE__ */ jsx(BreathingRing, { isActive: !reducedMotion && triggerState === "idle" }),
1012
+ /* @__PURE__ */ jsx(
1013
+ "div",
1014
+ {
1015
+ style: {
1016
+ position: "absolute",
1017
+ inset: 3,
1018
+ borderRadius: "50%",
1019
+ background: `linear-gradient(135deg, var(--widget-primary) 0%, var(--widget-accent) 100%)`,
1020
+ opacity: 0.9
1021
+ }
1028
1022
  }
1029
- }
1030
- ),
1031
- /* @__PURE__ */ jsxs(
1032
- "svg",
1033
- {
1034
- width: 24,
1035
- height: 24,
1036
- viewBox: "0 0 24 24",
1037
- fill: "none",
1038
- stroke: "white",
1039
- strokeWidth: 2,
1040
- strokeLinecap: "round",
1041
- style: { position: "relative", zIndex: 1 },
1042
- children: [
1043
- /* @__PURE__ */ jsx("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
1044
- /* @__PURE__ */ jsx("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
1045
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
1046
- /* @__PURE__ */ jsx("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
1047
- ]
1048
- }
1049
- ),
1050
- shouldShowAttentionPulse && /* @__PURE__ */ jsx(
1051
- motion.div,
1052
- {
1053
- initial: { scale: 1, opacity: 1 },
1054
- animate: { scale: 1.5, opacity: 0 },
1055
- transition: { duration: 1, repeat: 3 },
1056
- style: {
1057
- position: "absolute",
1058
- inset: 0,
1059
- borderRadius: "50%",
1060
- border: "2px solid var(--widget-primary)",
1061
- pointerEvents: "none"
1023
+ ),
1024
+ /* @__PURE__ */ jsxs(
1025
+ "svg",
1026
+ {
1027
+ width: 24,
1028
+ height: 24,
1029
+ viewBox: "0 0 24 24",
1030
+ fill: "none",
1031
+ stroke: "white",
1032
+ strokeWidth: 2,
1033
+ strokeLinecap: "round",
1034
+ style: {
1035
+ position: "absolute",
1036
+ top: "50%",
1037
+ left: "50%",
1038
+ transform: "translate(-50%, -50%)",
1039
+ zIndex: 1
1040
+ },
1041
+ children: [
1042
+ /* @__PURE__ */ jsx("path", { d: "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" }),
1043
+ /* @__PURE__ */ jsx("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
1044
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "19", x2: "12", y2: "23" }),
1045
+ /* @__PURE__ */ jsx("line", { x1: "8", y1: "23", x2: "16", y2: "23" })
1046
+ ]
1062
1047
  }
1063
- }
1064
- ),
1065
- frustrationLevel >= 5 && /* @__PURE__ */ jsx(
1066
- motion.div,
1067
- {
1068
- initial: { scale: 0 },
1069
- animate: { scale: 1 },
1070
- style: {
1071
- position: "absolute",
1072
- top: -4,
1073
- right: -4,
1074
- width: 16,
1075
- height: 16,
1076
- borderRadius: "50%",
1077
- background: "var(--widget-frustrated)",
1078
- border: "2px solid var(--widget-glass-bg)",
1079
- display: "flex",
1080
- alignItems: "center",
1081
- justifyContent: "center",
1082
- fontSize: 10
1083
- },
1084
- children: "?"
1085
- }
1086
- )
1087
- ]
1088
- },
1089
- "trigger"
1090
- ) }),
1048
+ ),
1049
+ shouldShowAttentionPulse && /* @__PURE__ */ jsx(
1050
+ motion.div,
1051
+ {
1052
+ initial: { scale: 1, opacity: 1 },
1053
+ animate: { scale: 1.5, opacity: 0 },
1054
+ transition: { duration: 1, repeat: 3 },
1055
+ style: {
1056
+ position: "absolute",
1057
+ inset: 0,
1058
+ borderRadius: "50%",
1059
+ border: "2px solid var(--widget-primary)",
1060
+ pointerEvents: "none"
1061
+ }
1062
+ }
1063
+ ),
1064
+ frustrationLevel >= 5 && /* @__PURE__ */ jsx(
1065
+ motion.div,
1066
+ {
1067
+ initial: { scale: 0 },
1068
+ animate: { scale: 1 },
1069
+ style: {
1070
+ position: "absolute",
1071
+ top: -4,
1072
+ right: -4,
1073
+ width: 16,
1074
+ height: 16,
1075
+ borderRadius: "50%",
1076
+ background: "var(--widget-frustrated)",
1077
+ border: "2px solid var(--widget-glass-bg)",
1078
+ display: "flex",
1079
+ alignItems: "center",
1080
+ justifyContent: "center",
1081
+ fontSize: 10
1082
+ },
1083
+ children: "?"
1084
+ }
1085
+ )
1086
+ ]
1087
+ },
1088
+ "trigger"
1089
+ ),
1090
+ /* @__PURE__ */ jsx(AnimatePresence, { children: showPrompt && !isExpanded && /* @__PURE__ */ jsxs(
1091
+ motion.div,
1092
+ {
1093
+ initial: { opacity: 0, x: 10, scale: 0.9 },
1094
+ animate: { opacity: 1, x: 0, scale: 1 },
1095
+ exit: { opacity: 0, x: 10, scale: 0.9 },
1096
+ transition: springPresets.smooth,
1097
+ onClick: handleOpen,
1098
+ style: {
1099
+ position: "absolute",
1100
+ right: 70,
1101
+ top: "50%",
1102
+ transform: "translateY(-50%)",
1103
+ background: "var(--widget-glass-bg)",
1104
+ backdropFilter: "blur(12px)",
1105
+ WebkitBackdropFilter: "blur(12px)",
1106
+ border: "1px solid var(--widget-glass-border)",
1107
+ borderRadius: 12,
1108
+ padding: "10px 16px",
1109
+ boxShadow: "0 4px 20px rgba(0,0,0,0.3)",
1110
+ cursor: "pointer",
1111
+ whiteSpace: "nowrap"
1112
+ },
1113
+ children: [
1114
+ /* @__PURE__ */ jsx("span", { style: {
1115
+ fontSize: 13,
1116
+ fontWeight: 500,
1117
+ color: "var(--widget-text-primary)"
1118
+ }, children: promptMessage }),
1119
+ /* @__PURE__ */ jsx(
1120
+ "div",
1121
+ {
1122
+ style: {
1123
+ position: "absolute",
1124
+ right: -6,
1125
+ top: "50%",
1126
+ transform: "translateY(-50%) rotate(45deg)",
1127
+ width: 12,
1128
+ height: 12,
1129
+ background: "var(--widget-glass-bg)",
1130
+ borderRight: "1px solid var(--widget-glass-border)",
1131
+ borderTop: "1px solid var(--widget-glass-border)"
1132
+ }
1133
+ }
1134
+ )
1135
+ ]
1136
+ }
1137
+ ) })
1138
+ ] }),
1091
1139
  /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: isExpanded && /* @__PURE__ */ jsx(
1092
1140
  motion.div,
1093
1141
  {
@@ -1223,7 +1271,7 @@ var PremiumVoiceWidget = ({
1223
1271
  ))
1224
1272
  }
1225
1273
  ),
1226
- /* @__PURE__ */ jsxs("div", { style: { flex: 1, overflow: "auto", padding: 24 }, children: [
1274
+ /* @__PURE__ */ jsxs("div", { style: { padding: "20px 24px" }, children: [
1227
1275
  /* @__PURE__ */ jsx("div", { style: { marginBottom: 24 }, children: /* @__PURE__ */ jsx(
1228
1276
  CategorySelector,
1229
1277
  {
@@ -1249,7 +1297,7 @@ var PremiumVoiceWidget = ({
1249
1297
  fontSize: 14,
1250
1298
  marginTop: 16
1251
1299
  },
1252
- children: "Tap the orb to start recording"
1300
+ children: "Hold to record"
1253
1301
  }
1254
1302
  ),
1255
1303
  (isRecording || transcription) && /* @__PURE__ */ jsx("div", { style: { marginTop: 20 }, children: /* @__PURE__ */ jsx(
@@ -1262,8 +1310,9 @@ var PremiumVoiceWidget = ({
1262
1310
  /* @__PURE__ */ jsx("div", { style: { marginTop: 20 }, children: /* @__PURE__ */ jsx(
1263
1311
  MagneticButton,
1264
1312
  {
1265
- onClick: isRecording ? handleStopRecording : handleStartRecording,
1266
- variant: isRecording ? "secondary" : "primary",
1313
+ onPressStart: handleStartRecording,
1314
+ onPressEnd: handleStopRecording,
1315
+ variant: isRecording ? "recording" : "primary",
1267
1316
  children: isRecording ? /* @__PURE__ */ jsxs(Fragment, { children: [
1268
1317
  /* @__PURE__ */ jsx(
1269
1318
  "svg",
@@ -1272,11 +1321,11 @@ var PremiumVoiceWidget = ({
1272
1321
  height: 16,
1273
1322
  viewBox: "0 0 24 24",
1274
1323
  fill: "currentColor",
1275
- children: /* @__PURE__ */ jsx("rect", { x: 6, y: 6, width: 12, height: 12, rx: 2 })
1324
+ children: /* @__PURE__ */ jsx("circle", { cx: 12, cy: 12, r: 6 })
1276
1325
  }
1277
1326
  ),
1278
- "Stop Recording"
1279
- ] }) : recordingSeconds > 0 ? "Record Again" : "Start Recording"
1327
+ "Recording..."
1328
+ ] }) : transcription ? "Hold to record more" : "Hold to record"
1280
1329
  }
1281
1330
  ) })
1282
1331
  ] }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentai/react",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "React component for Intent AI feedback widget - easily collect user feedback with AI-powered analysis",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org",