@feedvalue/vue 0.1.8 → 0.1.10
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.cjs +69 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -1
- package/dist/index.d.ts +48 -1
- package/dist/index.js +69 -24
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -165,7 +165,8 @@ function useReaction(widgetId) {
|
|
|
165
165
|
});
|
|
166
166
|
const reactionConfig = vue.computed(() => {
|
|
167
167
|
if (!instance.value || !isReady.value) return null;
|
|
168
|
-
|
|
168
|
+
const widgetConfig = instance.value.getWidgetConfig();
|
|
169
|
+
return widgetConfig?.config ?? null;
|
|
169
170
|
});
|
|
170
171
|
const showLabels = vue.computed(() => {
|
|
171
172
|
return reactionConfig.value?.showLabels ?? true;
|
|
@@ -192,7 +193,7 @@ function useReaction(widgetId) {
|
|
|
192
193
|
if (!instance.value || !isReady.value) {
|
|
193
194
|
return defaultStyling;
|
|
194
195
|
}
|
|
195
|
-
const widgetConfig = instance.value.
|
|
196
|
+
const widgetConfig = instance.value.getWidgetConfig();
|
|
196
197
|
if (!widgetConfig?.styling) {
|
|
197
198
|
return defaultStyling;
|
|
198
199
|
}
|
|
@@ -271,7 +272,10 @@ var borderWidthMap = {
|
|
|
271
272
|
"1": "1px",
|
|
272
273
|
"2": "2px",
|
|
273
274
|
"3": "3px",
|
|
274
|
-
"4": "4px"
|
|
275
|
+
"4": "4px",
|
|
276
|
+
thin: "1px",
|
|
277
|
+
medium: "2px",
|
|
278
|
+
thick: "3px"
|
|
275
279
|
};
|
|
276
280
|
var sizeStyles = {
|
|
277
281
|
sm: {
|
|
@@ -334,7 +338,8 @@ var styles = {
|
|
|
334
338
|
border: "1px solid #d1d5db",
|
|
335
339
|
borderRadius: "0.375rem",
|
|
336
340
|
backgroundColor: "#ffffff",
|
|
337
|
-
boxSizing: "border-box"
|
|
341
|
+
boxSizing: "border-box",
|
|
342
|
+
resize: "none"
|
|
338
343
|
},
|
|
339
344
|
actions: {
|
|
340
345
|
display: "flex",
|
|
@@ -409,11 +414,33 @@ var ReactionButtons = vue.defineComponent({
|
|
|
409
414
|
buttonClass: {
|
|
410
415
|
type: String,
|
|
411
416
|
default: ""
|
|
417
|
+
},
|
|
418
|
+
/** Custom class for the follow-up form */
|
|
419
|
+
formClass: {
|
|
420
|
+
type: String,
|
|
421
|
+
default: ""
|
|
422
|
+
},
|
|
423
|
+
/** Custom class for the thank you message */
|
|
424
|
+
thankYouClass: {
|
|
425
|
+
type: String,
|
|
426
|
+
default: ""
|
|
427
|
+
},
|
|
428
|
+
/** Hide after submission (default: false) */
|
|
429
|
+
hideAfterSubmit: {
|
|
430
|
+
type: Boolean,
|
|
431
|
+
default: false
|
|
432
|
+
},
|
|
433
|
+
/** Whether to show follow-up inline or not at all */
|
|
434
|
+
followUpMode: {
|
|
435
|
+
type: String,
|
|
436
|
+
default: "inline"
|
|
412
437
|
}
|
|
413
438
|
},
|
|
414
439
|
emits: {
|
|
415
440
|
/** Emitted when a reaction is submitted */
|
|
416
|
-
react: (value, _followUp) => typeof value === "string"
|
|
441
|
+
react: (value, _followUp) => typeof value === "string",
|
|
442
|
+
/** Emitted when an error occurs */
|
|
443
|
+
error: (_error) => true
|
|
417
444
|
},
|
|
418
445
|
setup(props, { emit }) {
|
|
419
446
|
const {
|
|
@@ -429,25 +456,30 @@ var ReactionButtons = vue.defineComponent({
|
|
|
429
456
|
showLabels,
|
|
430
457
|
buttonSize,
|
|
431
458
|
shouldShowFollowUp,
|
|
432
|
-
styling
|
|
459
|
+
styling,
|
|
460
|
+
isReactionWidget
|
|
433
461
|
} = useReaction(props.widgetId);
|
|
434
462
|
const followUpText = vue.ref("");
|
|
463
|
+
const hoveredButton = vue.ref(null);
|
|
435
464
|
const getFollowUpOption = vue.computed(() => {
|
|
436
465
|
if (!showFollowUp.value || !options.value) return null;
|
|
437
466
|
return options.value.find((opt) => opt.value === showFollowUp.value) ?? null;
|
|
438
467
|
});
|
|
439
468
|
const handleOptionClick = (option) => {
|
|
440
|
-
if (shouldShowFollowUp(option.value)) {
|
|
469
|
+
if (props.followUpMode === "inline" && shouldShowFollowUp(option.value)) {
|
|
441
470
|
setShowFollowUp(option.value);
|
|
442
471
|
} else {
|
|
443
472
|
submitReaction(option.value);
|
|
444
473
|
}
|
|
445
474
|
};
|
|
446
475
|
const submitReaction = async (value, followUp) => {
|
|
476
|
+
const trimmedFollowUp = followUp?.trim() || void 0;
|
|
447
477
|
try {
|
|
448
|
-
await react(value,
|
|
449
|
-
emit("react", value,
|
|
450
|
-
} catch {
|
|
478
|
+
await react(value, trimmedFollowUp);
|
|
479
|
+
emit("react", value, trimmedFollowUp);
|
|
480
|
+
} catch (err) {
|
|
481
|
+
const reactionError = err instanceof Error ? err : new Error(String(err));
|
|
482
|
+
emit("error", reactionError);
|
|
451
483
|
}
|
|
452
484
|
};
|
|
453
485
|
const handleFollowUpSubmit = (e) => {
|
|
@@ -462,7 +494,10 @@ var ReactionButtons = vue.defineComponent({
|
|
|
462
494
|
followUpText.value = "";
|
|
463
495
|
};
|
|
464
496
|
return () => {
|
|
465
|
-
if (!isReady.value || !options.value) {
|
|
497
|
+
if (!isReady.value || !isReactionWidget.value || !options.value) {
|
|
498
|
+
return null;
|
|
499
|
+
}
|
|
500
|
+
if (submitted.value && props.hideAfterSubmit) {
|
|
466
501
|
return null;
|
|
467
502
|
}
|
|
468
503
|
if (submitted.value) {
|
|
@@ -470,8 +505,8 @@ var ReactionButtons = vue.defineComponent({
|
|
|
470
505
|
return vue.h(
|
|
471
506
|
"div",
|
|
472
507
|
{
|
|
473
|
-
class: props.containerClass,
|
|
474
|
-
style: {
|
|
508
|
+
class: props.thankYouClass || props.containerClass,
|
|
509
|
+
style: props.thankYouClass ? void 0 : {
|
|
475
510
|
...styles.thankYou,
|
|
476
511
|
color: currentStyling2.primaryColor ?? "#059669"
|
|
477
512
|
}
|
|
@@ -495,8 +530,9 @@ var ReactionButtons = vue.defineComponent({
|
|
|
495
530
|
const currentStyling = styling.value;
|
|
496
531
|
const borderRadius = borderRadiusMap[currentStyling.borderRadius ?? "full"] ?? "9999px";
|
|
497
532
|
const borderWidth = borderWidthMap[currentStyling.borderWidth ?? "1"] ?? "1px";
|
|
498
|
-
const buttonElements = options.value.map((option) => {
|
|
533
|
+
const buttonElements = !showFollowUp.value ? options.value.map((option) => {
|
|
499
534
|
const isActive = showFollowUp.value === option.value;
|
|
535
|
+
const isHovered = hoveredButton.value === option.value;
|
|
500
536
|
const children = [
|
|
501
537
|
vue.h("span", { style: { ...styles.icon, ...currentSizeStyles.icon }, "aria-hidden": "true" }, option.icon)
|
|
502
538
|
];
|
|
@@ -513,11 +549,12 @@ var ReactionButtons = vue.defineComponent({
|
|
|
513
549
|
...styles.button,
|
|
514
550
|
...currentSizeStyles.button,
|
|
515
551
|
backgroundColor: currentStyling.backgroundColor ?? "#ffffff",
|
|
516
|
-
borderColor: isActive ? currentStyling.primaryColor ?? "#6366f1" : currentStyling.borderColor ?? "#e5e7eb",
|
|
552
|
+
borderColor: isActive || isHovered ? currentStyling.primaryColor ?? "#6366f1" : currentStyling.borderColor ?? "#e5e7eb",
|
|
517
553
|
borderWidth,
|
|
518
554
|
borderRadius,
|
|
555
|
+
borderStyle: "solid",
|
|
519
556
|
color: currentStyling.buttonTextColor ?? "#4b5563",
|
|
520
|
-
...isActive ? {
|
|
557
|
+
...isActive || isHovered ? {
|
|
521
558
|
backgroundColor: `${currentStyling.primaryColor ?? "#6366f1"}10`
|
|
522
559
|
} : {},
|
|
523
560
|
...isSubmitting.value ? styles.buttonDisabled : {}
|
|
@@ -525,28 +562,35 @@ var ReactionButtons = vue.defineComponent({
|
|
|
525
562
|
disabled: isSubmitting.value,
|
|
526
563
|
"aria-pressed": isActive,
|
|
527
564
|
"aria-label": option.label,
|
|
528
|
-
onClick: () => handleOptionClick(option)
|
|
565
|
+
onClick: () => handleOptionClick(option),
|
|
566
|
+
onMouseenter: () => {
|
|
567
|
+
hoveredButton.value = option.value;
|
|
568
|
+
},
|
|
569
|
+
onMouseleave: () => {
|
|
570
|
+
hoveredButton.value = null;
|
|
571
|
+
}
|
|
529
572
|
},
|
|
530
573
|
children
|
|
531
574
|
);
|
|
532
|
-
});
|
|
575
|
+
}) : [];
|
|
533
576
|
let followUpForm = null;
|
|
534
577
|
const followUpOption = getFollowUpOption.value;
|
|
535
578
|
if (showFollowUp.value && followUpOption) {
|
|
536
579
|
followUpForm = vue.h(
|
|
537
580
|
"form",
|
|
538
581
|
{
|
|
539
|
-
|
|
582
|
+
class: props.formClass,
|
|
583
|
+
style: props.formClass ? void 0 : styles.followUp,
|
|
540
584
|
onSubmit: handleFollowUpSubmit
|
|
541
585
|
},
|
|
542
586
|
[
|
|
543
|
-
vue.h("
|
|
544
|
-
type: "text",
|
|
587
|
+
vue.h("textarea", {
|
|
545
588
|
style: styles.input,
|
|
546
589
|
value: followUpText.value,
|
|
547
|
-
placeholder: followUpOption.followUpPlaceholder || "Tell us more
|
|
590
|
+
placeholder: followUpOption.followUpPlaceholder || "Tell us more (optional)",
|
|
548
591
|
disabled: isSubmitting.value,
|
|
549
592
|
maxlength: 500,
|
|
593
|
+
rows: 3,
|
|
550
594
|
onInput: (e) => {
|
|
551
595
|
followUpText.value = e.target.value;
|
|
552
596
|
}
|
|
@@ -603,10 +647,11 @@ var ReactionButtons = vue.defineComponent({
|
|
|
603
647
|
"aria-label": "Reaction buttons"
|
|
604
648
|
},
|
|
605
649
|
[
|
|
606
|
-
|
|
650
|
+
// Only render button group if there are buttons to show
|
|
651
|
+
buttonElements.length > 0 ? vue.h("div", { style: styles.buttonGroup, role: "radiogroup" }, buttonElements) : null,
|
|
607
652
|
followUpForm,
|
|
608
653
|
errorElement
|
|
609
|
-
]
|
|
654
|
+
].filter(Boolean)
|
|
610
655
|
);
|
|
611
656
|
};
|
|
612
657
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugin.ts","../src/composables.ts","../src/use-reaction.ts","../src/ReactionButtons.ts"],"names":["FeedValue","inject","shallowRef","ref","onMounted","onUnmounted","readonly","computed","NEGATIVE_OPTIONS_MAP","defineComponent","currentStyling","h"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @feedvalue/vue - Plugin\n *\n * Vue plugin for FeedValue. Provides app-level configuration\n * and automatic initialization.\n */\n\nimport type { App, InjectionKey } from 'vue';\nimport { FeedValue, type FeedValueConfig, type FeedValueInstance } from '@feedvalue/core';\n\n/**\n * Plugin options\n */\nexport interface FeedValuePluginOptions {\n /** Widget ID from FeedValue dashboard */\n widgetId: string;\n /** API base URL (for self-hosted) */\n apiBaseUrl?: string;\n /** Configuration overrides */\n config?: Partial<FeedValueConfig>;\n /**\n * Headless mode - disables all DOM rendering.\n * Use this when you want full control over the UI.\n * The SDK will still fetch config and provide all API methods\n * but won't render any trigger button or modal.\n *\n * @default false\n */\n headless?: boolean;\n}\n\n/**\n * Injection key for FeedValue instance\n */\nexport const FEEDVALUE_KEY: InjectionKey<FeedValueInstance> = Symbol('feedvalue');\n\n/**\n * Injection key for widget ID (used by useFeedValue when no instance is injected)\n */\nexport const FEEDVALUE_OPTIONS_KEY: InjectionKey<FeedValuePluginOptions> = Symbol('feedvalue-options');\n\n/**\n * Create FeedValue Vue plugin\n *\n * @example\n * ```ts\n * // main.ts\n * import { createApp } from 'vue';\n * import { createFeedValue } from '@feedvalue/vue';\n * import App from './App.vue';\n *\n * const app = createApp(App);\n *\n * app.use(createFeedValue({\n * widgetId: 'your-widget-id',\n * config: { theme: 'dark' }\n * }));\n *\n * app.mount('#app');\n * ```\n */\nexport function createFeedValue(options: FeedValuePluginOptions) {\n let instance: FeedValueInstance | null = null;\n\n return {\n install(app: App) {\n // Only initialize on client side\n if (typeof window !== 'undefined') {\n instance = FeedValue.init({\n widgetId: options.widgetId,\n apiBaseUrl: options.apiBaseUrl,\n config: options.config,\n headless: options.headless,\n });\n\n // Provide instance to all components\n app.provide(FEEDVALUE_KEY, instance);\n\n // Also provide to global properties for Options API access\n app.config.globalProperties.$feedvalue = instance;\n }\n\n // Always provide options (for SSR where we don't initialize)\n app.provide(FEEDVALUE_OPTIONS_KEY, options);\n },\n };\n}\n\n/**\n * Type augmentation for global properties\n */\ndeclare module 'vue' {\n interface ComponentCustomProperties {\n $feedvalue: FeedValueInstance | undefined;\n }\n}\n","/**\n * @feedvalue/vue - Composables\n *\n * Vue composables for FeedValue. Provides reactive state and methods.\n */\n\nimport {\n ref,\n shallowRef,\n readonly,\n onMounted,\n onUnmounted,\n inject,\n type Ref,\n type ShallowRef,\n} from 'vue';\nimport {\n FeedValue,\n type FeedValueConfig,\n type FeedValueInstance,\n type FeedbackData,\n type UserTraits,\n} from '@feedvalue/core';\nimport { FEEDVALUE_KEY, FEEDVALUE_OPTIONS_KEY } from './plugin';\n\n/**\n * Return type for useFeedValue composable\n */\nexport interface UseFeedValueReturn {\n /** FeedValue instance (for advanced usage) */\n instance: Readonly<ShallowRef<FeedValueInstance | null>>;\n /** Widget is ready */\n isReady: Readonly<Ref<boolean>>;\n /** Modal is open */\n isOpen: Readonly<Ref<boolean>>;\n /** Widget is visible */\n isVisible: Readonly<Ref<boolean>>;\n /** Current error */\n error: Readonly<Ref<Error | null>>;\n /** Submission in progress */\n isSubmitting: Readonly<Ref<boolean>>;\n /** Running in headless mode (no default UI rendered) */\n isHeadless: Readonly<Ref<boolean>>;\n /** Open the feedback modal */\n open: () => void;\n /** Close the feedback modal */\n close: () => void;\n /** Toggle the feedback modal */\n toggle: () => void;\n /** Show the trigger button */\n show: () => void;\n /** Hide the trigger button */\n hide: () => void;\n /** Submit feedback programmatically */\n submit: (feedback: Partial<FeedbackData>) => Promise<void>;\n /** Identify user */\n identify: (userId: string, traits?: UserTraits) => void;\n /** Set user data */\n setData: (data: Record<string, string>) => void;\n /** Reset user data */\n reset: () => void;\n}\n\n/**\n * FeedValue composable\n *\n * Can be used with or without plugin. If plugin is installed, uses the\n * provided instance. Otherwise, creates a new instance.\n *\n * @example\n * ```vue\n * <script setup>\n * import { useFeedValue } from '@feedvalue/vue';\n *\n * // With plugin installed\n * const { open, isReady } = useFeedValue();\n *\n * // Or standalone with widgetId\n * const { open, isReady } = useFeedValue('your-widget-id');\n * </script>\n *\n * <template>\n * <button @click=\"open\" :disabled=\"!isReady\">\n * Give Feedback\n * </button>\n * </template>\n * ```\n */\nexport function useFeedValue(\n widgetId?: string,\n config?: Partial<FeedValueConfig>\n): UseFeedValueReturn {\n // Try to inject instance from plugin\n const injectedInstance = inject(FEEDVALUE_KEY, null);\n const injectedOptions = inject(FEEDVALUE_OPTIONS_KEY, null);\n\n // Refs for reactive state\n const instance = shallowRef<FeedValueInstance | null>(null);\n const isReady = ref(false);\n const isOpen = ref(false);\n const isVisible = ref(false);\n const error = ref<Error | null>(null);\n const isSubmitting = ref(false);\n const isHeadless = ref(false);\n\n // Track if we own the instance (need to destroy on unmount)\n let ownsInstance = false;\n let unsubscribe: (() => void) | null = null;\n\n /**\n * Sync reactive state from instance\n */\n const syncState = () => {\n const state = instance.value?.getSnapshot();\n if (state) {\n isReady.value = state.isReady;\n isOpen.value = state.isOpen;\n isVisible.value = state.isVisible;\n error.value = state.error;\n isSubmitting.value = state.isSubmitting;\n }\n };\n\n onMounted(() => {\n // Use injected instance if available and no widgetId override\n if (injectedInstance && !widgetId) {\n instance.value = injectedInstance;\n isHeadless.value = injectedInstance.isHeadless();\n } else {\n // Create new instance\n const effectiveWidgetId = widgetId ?? injectedOptions?.widgetId;\n\n if (!effectiveWidgetId) {\n console.error(\n '[FeedValue] No widgetId provided. Either install the plugin with createFeedValue() ' +\n 'or pass widgetId to useFeedValue().'\n );\n return;\n }\n\n instance.value = FeedValue.init({\n widgetId: effectiveWidgetId,\n apiBaseUrl: injectedOptions?.apiBaseUrl,\n config: config ?? injectedOptions?.config,\n headless: injectedOptions?.headless,\n });\n ownsInstance = true;\n }\n\n // Subscribe to state changes\n if (instance.value) {\n unsubscribe = instance.value.subscribe(syncState);\n isHeadless.value = instance.value.isHeadless();\n syncState(); // Initial sync\n }\n });\n\n onUnmounted(() => {\n unsubscribe?.();\n if (ownsInstance && instance.value) {\n instance.value.destroy();\n }\n instance.value = null;\n });\n\n // Methods that delegate to instance\n const open = () => instance.value?.open();\n const close = () => instance.value?.close();\n const toggle = () => instance.value?.toggle();\n const show = () => instance.value?.show();\n const hide = () => instance.value?.hide();\n const submit = (feedback: Partial<FeedbackData>) =>\n instance.value?.submit(feedback) ?? Promise.reject(new Error('Not initialized'));\n const identify = (userId: string, traits?: UserTraits) =>\n instance.value?.identify(userId, traits);\n const setData = (data: Record<string, string>) => instance.value?.setData(data);\n const reset = () => instance.value?.reset();\n\n return {\n instance: readonly(instance),\n isReady: readonly(isReady),\n isOpen: readonly(isOpen),\n isVisible: readonly(isVisible),\n error: readonly(error),\n isSubmitting: readonly(isSubmitting),\n isHeadless: readonly(isHeadless),\n open,\n close,\n toggle,\n show,\n hide,\n submit,\n identify,\n setData,\n reset,\n };\n}\n","/**\n * @feedvalue/vue - useReaction Composable\n *\n * Composable for reaction widgets in Vue applications.\n * Provides a simple API for submitting reactions.\n */\n\nimport {\n ref,\n computed,\n readonly,\n onMounted,\n onUnmounted,\n inject,\n type Ref,\n type ComputedRef,\n} from 'vue';\nimport {\n FeedValue,\n NEGATIVE_OPTIONS_MAP,\n type ReactionOption,\n type FeedValueInstance,\n type ButtonSize,\n type FollowUpTrigger,\n type ReactionTemplate,\n type ReactionStyling,\n} from '@feedvalue/core';\nimport { FEEDVALUE_KEY, FEEDVALUE_OPTIONS_KEY } from './plugin';\n\n/**\n * Return type for useReaction composable\n */\nexport interface UseReactionReturn {\n /** Available reaction options */\n options: ComputedRef<ReactionOption[] | null>;\n /** Currently submitting */\n isSubmitting: Readonly<Ref<boolean>>;\n /** Successfully submitted value (null if not yet submitted) */\n submitted: Readonly<Ref<string | null>>;\n /** Error if submission failed */\n error: Readonly<Ref<Error | null>>;\n /** Option value requiring follow-up input (null if none) */\n showFollowUp: Readonly<Ref<string | null>>;\n /** Submit a reaction */\n react: (value: string, followUp?: string) => Promise<void>;\n /** Set which option is showing follow-up input */\n setShowFollowUp: (value: string | null) => void;\n /** Clear the submitted state to allow re-submission */\n clearSubmitted: () => void;\n /** Check if widget is a reaction type */\n isReactionWidget: ComputedRef<boolean>;\n /** Widget configuration is ready */\n isReady: Readonly<Ref<boolean>>;\n /** Whether to show text labels next to icons */\n showLabels: ComputedRef<boolean>;\n /** Button size */\n buttonSize: ComputedRef<ButtonSize>;\n /** When to show follow-up input */\n followUpTrigger: ComputedRef<FollowUpTrigger>;\n /** Check if an option should show follow-up based on followUpTrigger */\n shouldShowFollowUp: (optionValue: string) => boolean;\n /** Widget styling configuration */\n styling: ComputedRef<ReactionStyling>;\n}\n\n/**\n * Composable for reaction widgets\n *\n * Provides reaction options, submission handling, and follow-up state management.\n * Can be used with or without the FeedValue plugin.\n *\n * @param widgetId - Optional widget ID override (uses plugin widget if not provided)\n *\n * @example\n * ```vue\n * <script setup>\n * import { useReaction } from '@feedvalue/vue';\n *\n * const {\n * options,\n * react,\n * isSubmitting,\n * submitted,\n * error,\n * showFollowUp,\n * setShowFollowUp,\n * isReady,\n * } = useReaction();\n *\n * const handleClick = (option) => {\n * if (option.showFollowUp) {\n * setShowFollowUp(option.value);\n * } else {\n * react(option.value);\n * }\n * };\n * </script>\n *\n * <template>\n * <div v-if=\"isReady && options\">\n * <div v-if=\"submitted\">Thanks for your feedback!</div>\n *\n * <template v-else>\n * <button\n * v-for=\"option in options\"\n * :key=\"option.value\"\n * @click=\"handleClick(option)\"\n * :disabled=\"isSubmitting\"\n * >\n * {{ option.icon }} {{ option.label }}\n * </button>\n *\n * <form v-if=\"showFollowUp\" @submit.prevent=\"react(showFollowUp, followUpText)\">\n * <input v-model=\"followUpText\" placeholder=\"Tell us more...\" />\n * <button type=\"submit\">Send</button>\n * </form>\n *\n * <div v-if=\"error\">Error: {{ error.message }}</div>\n * </template>\n * </div>\n * </template>\n * ```\n */\nexport function useReaction(widgetId?: string): UseReactionReturn {\n // Try to inject instance from plugin\n const injectedInstance = inject(FEEDVALUE_KEY, null);\n const injectedOptions = inject(FEEDVALUE_OPTIONS_KEY, null);\n\n // Local instance ref (may be created if no plugin or widgetId override)\n const instance = ref<FeedValueInstance | null>(null);\n const isReady = ref(false);\n\n // Local state for reaction UI\n const showFollowUp = ref<string | null>(null);\n const submitted = ref<string | null>(null);\n const isSubmitting = ref(false);\n const error = ref<Error | null>(null);\n\n // Track if we own the instance (need to destroy on unmount)\n let ownsInstance = false;\n let unsubscribe: (() => void) | null = null;\n\n /**\n * Sync ready state from instance\n */\n const syncState = () => {\n const state = instance.value?.getSnapshot();\n if (state) {\n isReady.value = state.isReady;\n }\n };\n\n onMounted(() => {\n // Use injected instance if available and no widgetId override\n if (injectedInstance && !widgetId) {\n instance.value = injectedInstance;\n } else {\n // Create new instance\n const effectiveWidgetId = widgetId ?? injectedOptions?.widgetId;\n\n if (!effectiveWidgetId) {\n console.error(\n '[FeedValue] No widgetId provided. Either install the plugin with createFeedValue() ' +\n 'or pass widgetId to useReaction().'\n );\n return;\n }\n\n instance.value = FeedValue.init({\n widgetId: effectiveWidgetId,\n apiBaseUrl: injectedOptions?.apiBaseUrl,\n config: injectedOptions?.config,\n headless: true, // Reaction widgets are always headless\n });\n ownsInstance = true;\n }\n\n // Subscribe to state changes\n if (instance.value) {\n unsubscribe = instance.value.subscribe(syncState);\n syncState(); // Initial sync\n }\n });\n\n onUnmounted(() => {\n unsubscribe?.();\n if (ownsInstance && instance.value) {\n instance.value.destroy();\n }\n instance.value = null;\n });\n\n // Computed: reaction options from instance\n const options = computed<ReactionOption[] | null>(() => {\n if (!instance.value || !isReady.value) return null;\n return instance.value.getReactionOptions();\n });\n\n // Computed: check if this is a reaction widget\n const isReactionWidget = computed(() => {\n return instance.value?.isReaction() ?? false;\n });\n\n // Computed: get config values with defaults\n const reactionConfig = computed(() => {\n if (!instance.value || !isReady.value) return null;\n // Access the widget config which includes reaction config\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (instance.value as any)._widgetConfig?.config ?? null;\n });\n\n const showLabels = computed(() => {\n return reactionConfig.value?.showLabels ?? true;\n });\n\n const buttonSize = computed<ButtonSize>(() => {\n return reactionConfig.value?.buttonSize ?? 'md';\n });\n\n const followUpTrigger = computed<FollowUpTrigger>(() => {\n return reactionConfig.value?.followUpTrigger ?? 'negative';\n });\n\n const template = computed<ReactionTemplate | undefined>(() => {\n return reactionConfig.value?.template;\n });\n\n // Computed: widget styling configuration\n const styling = computed<ReactionStyling>(() => {\n const defaultStyling: ReactionStyling = {\n primaryColor: '#6366f1',\n backgroundColor: '#ffffff',\n textColor: '#111827',\n buttonTextColor: '#4b5563',\n borderColor: '#e5e7eb',\n borderWidth: '1',\n borderRadius: 'full',\n };\n\n if (!instance.value || !isReady.value) {\n return defaultStyling;\n }\n\n // Access the widget config styling\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const widgetConfig = (instance.value as any)._widgetConfig;\n if (!widgetConfig?.styling) {\n return defaultStyling;\n }\n\n // Cast styling to access extended properties that may be present from API\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const widgetStyling = widgetConfig.styling as any;\n return {\n primaryColor: widgetStyling.primaryColor ?? defaultStyling.primaryColor,\n backgroundColor: widgetStyling.backgroundColor ?? defaultStyling.backgroundColor,\n textColor: widgetStyling.textColor ?? defaultStyling.textColor,\n buttonTextColor: widgetStyling.buttonTextColor ?? defaultStyling.buttonTextColor,\n borderColor: widgetStyling.borderColor ?? defaultStyling.borderColor,\n borderWidth: widgetStyling.borderWidth ?? defaultStyling.borderWidth,\n borderRadius: widgetStyling.borderRadius ?? defaultStyling.borderRadius,\n };\n });\n\n /**\n * Check if an option should show follow-up based on followUpTrigger\n */\n const shouldShowFollowUp = (optionValue: string): boolean => {\n if (followUpTrigger.value === 'none') return false;\n if (followUpTrigger.value === 'all') return true;\n // followUpTrigger === 'negative'\n if (template.value && NEGATIVE_OPTIONS_MAP[template.value]) {\n return NEGATIVE_OPTIONS_MAP[template.value].includes(optionValue);\n }\n // For custom options, use the option's own showFollowUp setting\n const option = options.value?.find((o) => o.value === optionValue);\n return option?.showFollowUp ?? false;\n };\n\n /**\n * Submit a reaction\n */\n const react = async (value: string, followUp?: string): Promise<void> => {\n if (!instance.value) {\n throw new Error('FeedValue not initialized');\n }\n\n isSubmitting.value = true;\n error.value = null;\n\n try {\n await instance.value.react(value, followUp ? { followUp } : undefined);\n submitted.value = value;\n showFollowUp.value = null;\n } catch (err) {\n const reactionError = err instanceof Error ? err : new Error(String(err));\n error.value = reactionError;\n throw reactionError;\n } finally {\n isSubmitting.value = false;\n }\n };\n\n /**\n * Set which option is showing follow-up input\n */\n const setShowFollowUp = (value: string | null): void => {\n showFollowUp.value = value;\n };\n\n /**\n * Clear submitted state to allow re-submission\n */\n const clearSubmitted = (): void => {\n submitted.value = null;\n error.value = null;\n };\n\n return {\n options,\n isSubmitting: readonly(isSubmitting),\n submitted: readonly(submitted),\n error: readonly(error),\n showFollowUp: readonly(showFollowUp),\n react,\n setShowFollowUp,\n clearSubmitted,\n isReactionWidget,\n isReady: readonly(isReady),\n showLabels,\n buttonSize,\n followUpTrigger,\n shouldShowFollowUp,\n styling,\n };\n}\n","/**\n * @feedvalue/vue - ReactionButtons Component\n *\n * Pre-built reaction buttons component for Vue applications.\n * Renders reaction options with optional follow-up input.\n */\n\nimport { defineComponent, ref, computed, h, type PropType } from 'vue';\nimport { useReaction } from './use-reaction';\nimport type { ReactionOption } from '@feedvalue/core';\n\nimport type { ButtonSize, ReactionBorderRadius, ReactionBorderWidth } from '@feedvalue/core';\n\n/**\n * Border radius mapping from preset to CSS value\n */\nconst borderRadiusMap: Record<ReactionBorderRadius, string> = {\n full: '9999px',\n lg: '12px',\n md: '8px',\n sm: '4px',\n none: '0px',\n};\n\n/**\n * Border width mapping from preset to CSS value\n */\nconst borderWidthMap: Record<ReactionBorderWidth, string> = {\n '0': '0px',\n '1': '1px',\n '2': '2px',\n '3': '3px',\n '4': '4px',\n};\n\n/**\n * Button size style variants\n */\nconst sizeStyles: Record<ButtonSize, { button: Record<string, string>; icon: Record<string, string>; label: Record<string, string> }> = {\n sm: {\n button: { padding: '0.375rem 0.75rem', fontSize: '0.75rem', gap: '0.375rem' },\n icon: { fontSize: '1rem' },\n label: { fontSize: '0.75rem' },\n },\n md: {\n button: { padding: '0.5rem 1rem', fontSize: '0.875rem', gap: '0.5rem' },\n icon: { fontSize: '1.125rem' },\n label: { fontSize: '0.875rem' },\n },\n lg: {\n button: { padding: '0.75rem 1.25rem', fontSize: '1rem', gap: '0.625rem' },\n icon: { fontSize: '1.5rem' },\n label: { fontSize: '1rem' },\n },\n};\n\n/**\n * Default CSS styles for the component\n */\nconst styles = {\n container: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '0.75rem',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n },\n buttonGroup: {\n display: 'flex',\n flexWrap: 'wrap' as const,\n gap: '0.5rem',\n },\n button: {\n display: 'inline-flex',\n alignItems: 'center',\n fontWeight: '500',\n color: '#374151',\n backgroundColor: '#ffffff',\n border: '1px solid #d1d5db',\n borderRadius: '9999px',\n cursor: 'pointer',\n transition: 'background-color 0.15s, border-color 0.15s, transform 0.1s',\n },\n buttonActive: {\n backgroundColor: '#eef2ff',\n borderColor: '#6366f1',\n color: '#4f46e5',\n },\n buttonDisabled: {\n opacity: 0.7,\n cursor: 'not-allowed',\n },\n icon: {},\n followUp: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '0.5rem',\n padding: '0.75rem',\n backgroundColor: '#f9fafb',\n border: '1px solid #e5e7eb',\n borderRadius: '0.5rem',\n },\n input: {\n width: '100%',\n padding: '0.5rem 0.75rem',\n fontSize: '0.875rem',\n border: '1px solid #d1d5db',\n borderRadius: '0.375rem',\n backgroundColor: '#ffffff',\n boxSizing: 'border-box' as const,\n },\n actions: {\n display: 'flex',\n gap: '0.5rem',\n justifyContent: 'flex-end',\n },\n submitButton: {\n padding: '0.375rem 0.75rem',\n fontSize: '0.875rem',\n fontWeight: '500',\n color: '#ffffff',\n backgroundColor: '#6366f1',\n border: 'none',\n borderRadius: '0.375rem',\n cursor: 'pointer',\n },\n cancelButton: {\n padding: '0.375rem 0.75rem',\n fontSize: '0.875rem',\n color: '#6b7280',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n },\n thankYou: {\n display: 'flex',\n alignItems: 'center',\n gap: '0.5rem',\n padding: '0.75rem 1rem',\n fontSize: '0.875rem',\n color: '#059669',\n backgroundColor: '#ecfdf5',\n border: '1px solid #a7f3d0',\n borderRadius: '0.5rem',\n },\n resetButton: {\n padding: '0.25rem 0.5rem',\n fontSize: '0.875rem',\n color: '#6b7280',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n },\n error: {\n padding: '0.5rem 0.75rem',\n fontSize: '0.875rem',\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n border: '1px solid #fecaca',\n borderRadius: '0.375rem',\n },\n};\n\n/**\n * ReactionButtons Component\n *\n * Pre-built reaction buttons with follow-up input support.\n *\n * @example\n * ```vue\n * <template>\n * <ReactionButtons widget-id=\"xxx\" @react=\"onReact\" />\n * </template>\n *\n * <script setup>\n * import { ReactionButtons } from '@feedvalue/vue';\n *\n * const onReact = (value, followUp) => {\n * console.log('Reacted:', value, followUp);\n * };\n * </script>\n * ```\n */\nexport const ReactionButtons = defineComponent({\n name: 'ReactionButtons',\n\n props: {\n /** Widget ID (optional if using FeedValue plugin) */\n widgetId: {\n type: String as PropType<string | undefined>,\n default: undefined,\n },\n /** Custom thank you message (overrides widget config) */\n thankYouMessage: {\n type: String as PropType<string | undefined>,\n default: undefined,\n },\n /** Custom class for the container */\n containerClass: {\n type: String,\n default: '',\n },\n /** Custom class for buttons */\n buttonClass: {\n type: String,\n default: '',\n },\n },\n\n emits: {\n /** Emitted when a reaction is submitted */\n react: (value: string, _followUp?: string) => typeof value === 'string',\n },\n\n setup(props, { emit }) {\n const {\n options,\n react,\n isSubmitting,\n submitted,\n error,\n showFollowUp,\n setShowFollowUp,\n clearSubmitted,\n isReady,\n showLabels,\n buttonSize,\n shouldShowFollowUp,\n styling,\n } = useReaction(props.widgetId);\n\n // Local state for follow-up input\n const followUpText = ref('');\n\n // Get follow-up option\n const getFollowUpOption = computed<ReactionOption | null>(() => {\n if (!showFollowUp.value || !options.value) return null;\n return options.value.find((opt) => opt.value === showFollowUp.value) ?? null;\n });\n\n /**\n * Handle option click\n */\n const handleOptionClick = (option: ReactionOption) => {\n if (shouldShowFollowUp(option.value)) {\n setShowFollowUp(option.value);\n } else {\n submitReaction(option.value);\n }\n };\n\n /**\n * Submit reaction\n */\n const submitReaction = async (value: string, followUp?: string) => {\n try {\n await react(value, followUp);\n emit('react', value, followUp);\n } catch {\n // Error is already set in state\n }\n };\n\n /**\n * Handle follow-up form submit\n */\n const handleFollowUpSubmit = (e: Event) => {\n e.preventDefault();\n if (showFollowUp.value) {\n submitReaction(showFollowUp.value, followUpText.value || undefined);\n followUpText.value = '';\n }\n };\n\n /**\n * Cancel follow-up\n */\n const cancelFollowUp = () => {\n setShowFollowUp(null);\n followUpText.value = '';\n };\n\n return () => {\n // Don't render if not ready or no options\n if (!isReady.value || !options.value) {\n return null;\n }\n\n // Render thank you message after submission\n if (submitted.value) {\n const currentStyling = styling.value;\n return h(\n 'div',\n {\n class: props.containerClass,\n style: {\n ...styles.thankYou,\n color: currentStyling.primaryColor ?? '#059669',\n },\n },\n [\n h('span', props.thankYouMessage || 'Thanks for your feedback!'),\n h(\n 'button',\n {\n type: 'button',\n style: styles.resetButton,\n onClick: clearSubmitted,\n 'aria-label': 'Submit another reaction',\n },\n '↺'\n ),\n ]\n );\n }\n\n // Build reaction buttons using styling from widget config\n const currentSizeStyles = sizeStyles[buttonSize.value] || sizeStyles.md;\n const currentStyling = styling.value;\n const borderRadius = borderRadiusMap[currentStyling.borderRadius ?? 'full'] ?? '9999px';\n const borderWidth = borderWidthMap[currentStyling.borderWidth ?? '1'] ?? '1px';\n\n const buttonElements = options.value.map((option) => {\n const isActive = showFollowUp.value === option.value;\n const children = [\n h('span', { style: { ...styles.icon, ...currentSizeStyles.icon }, 'aria-hidden': 'true' }, option.icon),\n ];\n if (showLabels.value) {\n children.push(h('span', { style: { ...currentSizeStyles.label, color: currentStyling.buttonTextColor ?? '#4b5563' } }, option.label));\n }\n\n return h(\n 'button',\n {\n key: option.value,\n type: 'button',\n class: props.buttonClass,\n style: {\n ...styles.button,\n ...currentSizeStyles.button,\n backgroundColor: currentStyling.backgroundColor ?? '#ffffff',\n borderColor: isActive ? (currentStyling.primaryColor ?? '#6366f1') : (currentStyling.borderColor ?? '#e5e7eb'),\n borderWidth: borderWidth,\n borderRadius: borderRadius,\n color: currentStyling.buttonTextColor ?? '#4b5563',\n ...(isActive ? {\n backgroundColor: `${currentStyling.primaryColor ?? '#6366f1'}10`,\n } : {}),\n ...(isSubmitting.value ? styles.buttonDisabled : {}),\n },\n disabled: isSubmitting.value,\n 'aria-pressed': isActive,\n 'aria-label': option.label,\n onClick: () => handleOptionClick(option),\n },\n children\n );\n });\n\n // Build follow-up form if needed\n let followUpForm = null;\n const followUpOption = getFollowUpOption.value;\n if (showFollowUp.value && followUpOption) {\n followUpForm = h(\n 'form',\n {\n style: styles.followUp,\n onSubmit: handleFollowUpSubmit,\n },\n [\n h('input', {\n type: 'text',\n style: styles.input,\n value: followUpText.value,\n placeholder: followUpOption.followUpPlaceholder || 'Tell us more...',\n disabled: isSubmitting.value,\n maxlength: 500,\n onInput: (e: Event) => {\n followUpText.value = (e.target as HTMLInputElement).value;\n },\n }),\n h('div', { style: { ...styles.actions, justifyContent: 'center' } }, [\n h(\n 'button',\n {\n type: 'submit',\n style: {\n ...styles.submitButton,\n backgroundColor: currentStyling.primaryColor ?? '#6366f1',\n borderRadius: borderRadius,\n ...(isSubmitting.value ? styles.buttonDisabled : {}),\n },\n disabled: isSubmitting.value,\n },\n isSubmitting.value ? 'Sending...' : 'Send'\n ),\n h(\n 'button',\n {\n type: 'button',\n style: {\n ...styles.cancelButton,\n backgroundColor: currentStyling.backgroundColor ?? '#ffffff',\n color: currentStyling.buttonTextColor ?? '#6b7280',\n borderRadius: borderRadius,\n border: `${borderWidth} solid ${currentStyling.borderColor ?? '#e5e7eb'}`,\n },\n disabled: isSubmitting.value,\n onClick: cancelFollowUp,\n },\n 'Cancel'\n ),\n ]),\n ]\n );\n }\n\n // Build error message\n let errorElement = null;\n if (error.value) {\n errorElement = h(\n 'div',\n { style: styles.error, role: 'alert' },\n error.value.message\n );\n }\n\n // Return full component\n return h(\n 'div',\n {\n class: props.containerClass,\n style: styles.container,\n role: 'group',\n 'aria-label': 'Reaction buttons',\n },\n [\n h('div', { style: styles.buttonGroup, role: 'radiogroup' }, buttonElements),\n followUpForm,\n errorElement,\n ]\n );\n };\n },\n});\n\nexport default ReactionButtons;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/plugin.ts","../src/composables.ts","../src/use-reaction.ts","../src/ReactionButtons.ts"],"names":["FeedValue","inject","shallowRef","ref","onMounted","onUnmounted","readonly","computed","NEGATIVE_OPTIONS_MAP","defineComponent","currentStyling","h"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @feedvalue/vue - Plugin\n *\n * Vue plugin for FeedValue. Provides app-level configuration\n * and automatic initialization.\n */\n\nimport type { App, InjectionKey } from 'vue';\nimport { FeedValue, type FeedValueConfig, type FeedValueInstance } from '@feedvalue/core';\n\n/**\n * Plugin options\n */\nexport interface FeedValuePluginOptions {\n /** Widget ID from FeedValue dashboard */\n widgetId: string;\n /** API base URL (for self-hosted) */\n apiBaseUrl?: string;\n /** Configuration overrides */\n config?: Partial<FeedValueConfig>;\n /**\n * Headless mode - disables all DOM rendering.\n * Use this when you want full control over the UI.\n * The SDK will still fetch config and provide all API methods\n * but won't render any trigger button or modal.\n *\n * @default false\n */\n headless?: boolean;\n}\n\n/**\n * Injection key for FeedValue instance\n */\nexport const FEEDVALUE_KEY: InjectionKey<FeedValueInstance> = Symbol('feedvalue');\n\n/**\n * Injection key for widget ID (used by useFeedValue when no instance is injected)\n */\nexport const FEEDVALUE_OPTIONS_KEY: InjectionKey<FeedValuePluginOptions> = Symbol('feedvalue-options');\n\n/**\n * Create FeedValue Vue plugin\n *\n * @example\n * ```ts\n * // main.ts\n * import { createApp } from 'vue';\n * import { createFeedValue } from '@feedvalue/vue';\n * import App from './App.vue';\n *\n * const app = createApp(App);\n *\n * app.use(createFeedValue({\n * widgetId: 'your-widget-id',\n * config: { theme: 'dark' }\n * }));\n *\n * app.mount('#app');\n * ```\n */\nexport function createFeedValue(options: FeedValuePluginOptions) {\n let instance: FeedValueInstance | null = null;\n\n return {\n install(app: App) {\n // Only initialize on client side\n if (typeof window !== 'undefined') {\n instance = FeedValue.init({\n widgetId: options.widgetId,\n apiBaseUrl: options.apiBaseUrl,\n config: options.config,\n headless: options.headless,\n });\n\n // Provide instance to all components\n app.provide(FEEDVALUE_KEY, instance);\n\n // Also provide to global properties for Options API access\n app.config.globalProperties.$feedvalue = instance;\n }\n\n // Always provide options (for SSR where we don't initialize)\n app.provide(FEEDVALUE_OPTIONS_KEY, options);\n },\n };\n}\n\n/**\n * Type augmentation for global properties\n */\ndeclare module 'vue' {\n interface ComponentCustomProperties {\n $feedvalue: FeedValueInstance | undefined;\n }\n}\n","/**\n * @feedvalue/vue - Composables\n *\n * Vue composables for FeedValue. Provides reactive state and methods.\n */\n\nimport {\n ref,\n shallowRef,\n readonly,\n onMounted,\n onUnmounted,\n inject,\n type Ref,\n type ShallowRef,\n} from 'vue';\nimport {\n FeedValue,\n type FeedValueConfig,\n type FeedValueInstance,\n type FeedbackData,\n type UserTraits,\n} from '@feedvalue/core';\nimport { FEEDVALUE_KEY, FEEDVALUE_OPTIONS_KEY } from './plugin';\n\n/**\n * Return type for useFeedValue composable\n */\nexport interface UseFeedValueReturn {\n /** FeedValue instance (for advanced usage) */\n instance: Readonly<ShallowRef<FeedValueInstance | null>>;\n /** Widget is ready */\n isReady: Readonly<Ref<boolean>>;\n /** Modal is open */\n isOpen: Readonly<Ref<boolean>>;\n /** Widget is visible */\n isVisible: Readonly<Ref<boolean>>;\n /** Current error */\n error: Readonly<Ref<Error | null>>;\n /** Submission in progress */\n isSubmitting: Readonly<Ref<boolean>>;\n /** Running in headless mode (no default UI rendered) */\n isHeadless: Readonly<Ref<boolean>>;\n /** Open the feedback modal */\n open: () => void;\n /** Close the feedback modal */\n close: () => void;\n /** Toggle the feedback modal */\n toggle: () => void;\n /** Show the trigger button */\n show: () => void;\n /** Hide the trigger button */\n hide: () => void;\n /** Submit feedback programmatically */\n submit: (feedback: Partial<FeedbackData>) => Promise<void>;\n /** Identify user */\n identify: (userId: string, traits?: UserTraits) => void;\n /** Set user data */\n setData: (data: Record<string, string>) => void;\n /** Reset user data */\n reset: () => void;\n}\n\n/**\n * FeedValue composable\n *\n * Can be used with or without plugin. If plugin is installed, uses the\n * provided instance. Otherwise, creates a new instance.\n *\n * @example\n * ```vue\n * <script setup>\n * import { useFeedValue } from '@feedvalue/vue';\n *\n * // With plugin installed\n * const { open, isReady } = useFeedValue();\n *\n * // Or standalone with widgetId\n * const { open, isReady } = useFeedValue('your-widget-id');\n * </script>\n *\n * <template>\n * <button @click=\"open\" :disabled=\"!isReady\">\n * Give Feedback\n * </button>\n * </template>\n * ```\n */\nexport function useFeedValue(\n widgetId?: string,\n config?: Partial<FeedValueConfig>\n): UseFeedValueReturn {\n // Try to inject instance from plugin\n const injectedInstance = inject(FEEDVALUE_KEY, null);\n const injectedOptions = inject(FEEDVALUE_OPTIONS_KEY, null);\n\n // Refs for reactive state\n const instance = shallowRef<FeedValueInstance | null>(null);\n const isReady = ref(false);\n const isOpen = ref(false);\n const isVisible = ref(false);\n const error = ref<Error | null>(null);\n const isSubmitting = ref(false);\n const isHeadless = ref(false);\n\n // Track if we own the instance (need to destroy on unmount)\n let ownsInstance = false;\n let unsubscribe: (() => void) | null = null;\n\n /**\n * Sync reactive state from instance\n */\n const syncState = () => {\n const state = instance.value?.getSnapshot();\n if (state) {\n isReady.value = state.isReady;\n isOpen.value = state.isOpen;\n isVisible.value = state.isVisible;\n error.value = state.error;\n isSubmitting.value = state.isSubmitting;\n }\n };\n\n onMounted(() => {\n // Use injected instance if available and no widgetId override\n if (injectedInstance && !widgetId) {\n instance.value = injectedInstance;\n isHeadless.value = injectedInstance.isHeadless();\n } else {\n // Create new instance\n const effectiveWidgetId = widgetId ?? injectedOptions?.widgetId;\n\n if (!effectiveWidgetId) {\n console.error(\n '[FeedValue] No widgetId provided. Either install the plugin with createFeedValue() ' +\n 'or pass widgetId to useFeedValue().'\n );\n return;\n }\n\n instance.value = FeedValue.init({\n widgetId: effectiveWidgetId,\n apiBaseUrl: injectedOptions?.apiBaseUrl,\n config: config ?? injectedOptions?.config,\n headless: injectedOptions?.headless,\n });\n ownsInstance = true;\n }\n\n // Subscribe to state changes\n if (instance.value) {\n unsubscribe = instance.value.subscribe(syncState);\n isHeadless.value = instance.value.isHeadless();\n syncState(); // Initial sync\n }\n });\n\n onUnmounted(() => {\n unsubscribe?.();\n if (ownsInstance && instance.value) {\n instance.value.destroy();\n }\n instance.value = null;\n });\n\n // Methods that delegate to instance\n const open = () => instance.value?.open();\n const close = () => instance.value?.close();\n const toggle = () => instance.value?.toggle();\n const show = () => instance.value?.show();\n const hide = () => instance.value?.hide();\n const submit = (feedback: Partial<FeedbackData>) =>\n instance.value?.submit(feedback) ?? Promise.reject(new Error('Not initialized'));\n const identify = (userId: string, traits?: UserTraits) =>\n instance.value?.identify(userId, traits);\n const setData = (data: Record<string, string>) => instance.value?.setData(data);\n const reset = () => instance.value?.reset();\n\n return {\n instance: readonly(instance),\n isReady: readonly(isReady),\n isOpen: readonly(isOpen),\n isVisible: readonly(isVisible),\n error: readonly(error),\n isSubmitting: readonly(isSubmitting),\n isHeadless: readonly(isHeadless),\n open,\n close,\n toggle,\n show,\n hide,\n submit,\n identify,\n setData,\n reset,\n };\n}\n","/**\n * @feedvalue/vue - useReaction Composable\n *\n * Composable for reaction widgets in Vue applications.\n * Provides a simple API for submitting reactions.\n */\n\nimport {\n ref,\n computed,\n readonly,\n onMounted,\n onUnmounted,\n inject,\n type Ref,\n type ComputedRef,\n} from 'vue';\nimport {\n FeedValue,\n NEGATIVE_OPTIONS_MAP,\n type ReactionOption,\n type FeedValueInstance,\n type ButtonSize,\n type FollowUpTrigger,\n type ReactionTemplate,\n type ReactionStyling,\n} from '@feedvalue/core';\nimport { FEEDVALUE_KEY, FEEDVALUE_OPTIONS_KEY } from './plugin';\n\n/**\n * Return type for useReaction composable\n */\nexport interface UseReactionReturn {\n /** Available reaction options */\n options: ComputedRef<ReactionOption[] | null>;\n /** Currently submitting */\n isSubmitting: Readonly<Ref<boolean>>;\n /** Successfully submitted value (null if not yet submitted) */\n submitted: Readonly<Ref<string | null>>;\n /** Error if submission failed */\n error: Readonly<Ref<Error | null>>;\n /** Option value requiring follow-up input (null if none) */\n showFollowUp: Readonly<Ref<string | null>>;\n /** Submit a reaction */\n react: (value: string, followUp?: string) => Promise<void>;\n /** Set which option is showing follow-up input */\n setShowFollowUp: (value: string | null) => void;\n /** Clear the submitted state to allow re-submission */\n clearSubmitted: () => void;\n /** Check if widget is a reaction type */\n isReactionWidget: ComputedRef<boolean>;\n /** Widget configuration is ready */\n isReady: Readonly<Ref<boolean>>;\n /** Whether to show text labels next to icons */\n showLabels: ComputedRef<boolean>;\n /** Button size */\n buttonSize: ComputedRef<ButtonSize>;\n /** When to show follow-up input */\n followUpTrigger: ComputedRef<FollowUpTrigger>;\n /** Check if an option should show follow-up based on followUpTrigger */\n shouldShowFollowUp: (optionValue: string) => boolean;\n /** Widget styling configuration */\n styling: ComputedRef<ReactionStyling>;\n}\n\n/**\n * Composable for reaction widgets\n *\n * Provides reaction options, submission handling, and follow-up state management.\n * Can be used with or without the FeedValue plugin.\n *\n * @param widgetId - Optional widget ID override (uses plugin widget if not provided)\n *\n * @example\n * ```vue\n * <script setup>\n * import { useReaction } from '@feedvalue/vue';\n *\n * const {\n * options,\n * react,\n * isSubmitting,\n * submitted,\n * error,\n * showFollowUp,\n * setShowFollowUp,\n * isReady,\n * } = useReaction();\n *\n * const handleClick = (option) => {\n * if (option.showFollowUp) {\n * setShowFollowUp(option.value);\n * } else {\n * react(option.value);\n * }\n * };\n * </script>\n *\n * <template>\n * <div v-if=\"isReady && options\">\n * <div v-if=\"submitted\">Thanks for your feedback!</div>\n *\n * <template v-else>\n * <button\n * v-for=\"option in options\"\n * :key=\"option.value\"\n * @click=\"handleClick(option)\"\n * :disabled=\"isSubmitting\"\n * >\n * {{ option.icon }} {{ option.label }}\n * </button>\n *\n * <form v-if=\"showFollowUp\" @submit.prevent=\"react(showFollowUp, followUpText)\">\n * <input v-model=\"followUpText\" placeholder=\"Tell us more...\" />\n * <button type=\"submit\">Send</button>\n * </form>\n *\n * <div v-if=\"error\">Error: {{ error.message }}</div>\n * </template>\n * </div>\n * </template>\n * ```\n */\nexport function useReaction(widgetId?: string): UseReactionReturn {\n // Try to inject instance from plugin\n const injectedInstance = inject(FEEDVALUE_KEY, null);\n const injectedOptions = inject(FEEDVALUE_OPTIONS_KEY, null);\n\n // Local instance ref (may be created if no plugin or widgetId override)\n const instance = ref<FeedValueInstance | null>(null);\n const isReady = ref(false);\n\n // Local state for reaction UI\n const showFollowUp = ref<string | null>(null);\n const submitted = ref<string | null>(null);\n const isSubmitting = ref(false);\n const error = ref<Error | null>(null);\n\n // Track if we own the instance (need to destroy on unmount)\n let ownsInstance = false;\n let unsubscribe: (() => void) | null = null;\n\n /**\n * Sync ready state from instance\n */\n const syncState = () => {\n const state = instance.value?.getSnapshot();\n if (state) {\n isReady.value = state.isReady;\n }\n };\n\n onMounted(() => {\n // Use injected instance if available and no widgetId override\n if (injectedInstance && !widgetId) {\n instance.value = injectedInstance;\n } else {\n // Create new instance\n const effectiveWidgetId = widgetId ?? injectedOptions?.widgetId;\n\n if (!effectiveWidgetId) {\n console.error(\n '[FeedValue] No widgetId provided. Either install the plugin with createFeedValue() ' +\n 'or pass widgetId to useReaction().'\n );\n return;\n }\n\n instance.value = FeedValue.init({\n widgetId: effectiveWidgetId,\n apiBaseUrl: injectedOptions?.apiBaseUrl,\n config: injectedOptions?.config,\n headless: true, // Reaction widgets are always headless\n });\n ownsInstance = true;\n }\n\n // Subscribe to state changes\n if (instance.value) {\n unsubscribe = instance.value.subscribe(syncState);\n syncState(); // Initial sync\n }\n });\n\n onUnmounted(() => {\n unsubscribe?.();\n if (ownsInstance && instance.value) {\n instance.value.destroy();\n }\n instance.value = null;\n });\n\n // Computed: reaction options from instance\n const options = computed<ReactionOption[] | null>(() => {\n if (!instance.value || !isReady.value) return null;\n return instance.value.getReactionOptions();\n });\n\n // Computed: check if this is a reaction widget\n const isReactionWidget = computed(() => {\n return instance.value?.isReaction() ?? false;\n });\n\n // Computed: get config values with defaults\n const reactionConfig = computed(() => {\n if (!instance.value || !isReady.value) return null;\n // Access the widget config which includes reaction config\n const widgetConfig = instance.value.getWidgetConfig();\n return widgetConfig?.config ?? null;\n });\n\n const showLabels = computed(() => {\n return reactionConfig.value?.showLabels ?? true;\n });\n\n const buttonSize = computed<ButtonSize>(() => {\n return reactionConfig.value?.buttonSize ?? 'md';\n });\n\n const followUpTrigger = computed<FollowUpTrigger>(() => {\n return reactionConfig.value?.followUpTrigger ?? 'negative';\n });\n\n const template = computed<ReactionTemplate | undefined>(() => {\n return reactionConfig.value?.template;\n });\n\n // Computed: widget styling configuration\n const styling = computed<ReactionStyling>(() => {\n const defaultStyling: ReactionStyling = {\n primaryColor: '#6366f1',\n backgroundColor: '#ffffff',\n textColor: '#111827',\n buttonTextColor: '#4b5563',\n borderColor: '#e5e7eb',\n borderWidth: '1',\n borderRadius: 'full',\n };\n\n if (!instance.value || !isReady.value) {\n return defaultStyling;\n }\n\n // Access the widget config styling using public method\n const widgetConfig = instance.value.getWidgetConfig();\n if (!widgetConfig?.styling) {\n return defaultStyling;\n }\n\n // Cast styling to access extended properties that may be present from API\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const widgetStyling = widgetConfig.styling as any;\n return {\n primaryColor: widgetStyling.primaryColor ?? defaultStyling.primaryColor,\n backgroundColor: widgetStyling.backgroundColor ?? defaultStyling.backgroundColor,\n textColor: widgetStyling.textColor ?? defaultStyling.textColor,\n buttonTextColor: widgetStyling.buttonTextColor ?? defaultStyling.buttonTextColor,\n borderColor: widgetStyling.borderColor ?? defaultStyling.borderColor,\n borderWidth: widgetStyling.borderWidth ?? defaultStyling.borderWidth,\n borderRadius: widgetStyling.borderRadius ?? defaultStyling.borderRadius,\n };\n });\n\n /**\n * Check if an option should show follow-up based on followUpTrigger\n */\n const shouldShowFollowUp = (optionValue: string): boolean => {\n if (followUpTrigger.value === 'none') return false;\n if (followUpTrigger.value === 'all') return true;\n // followUpTrigger === 'negative'\n if (template.value && NEGATIVE_OPTIONS_MAP[template.value]) {\n return NEGATIVE_OPTIONS_MAP[template.value].includes(optionValue);\n }\n // For custom options, use the option's own showFollowUp setting\n const option = options.value?.find((o) => o.value === optionValue);\n return option?.showFollowUp ?? false;\n };\n\n /**\n * Submit a reaction\n */\n const react = async (value: string, followUp?: string): Promise<void> => {\n if (!instance.value) {\n throw new Error('FeedValue not initialized');\n }\n\n isSubmitting.value = true;\n error.value = null;\n\n try {\n await instance.value.react(value, followUp ? { followUp } : undefined);\n submitted.value = value;\n showFollowUp.value = null;\n } catch (err) {\n const reactionError = err instanceof Error ? err : new Error(String(err));\n error.value = reactionError;\n throw reactionError;\n } finally {\n isSubmitting.value = false;\n }\n };\n\n /**\n * Set which option is showing follow-up input\n */\n const setShowFollowUp = (value: string | null): void => {\n showFollowUp.value = value;\n };\n\n /**\n * Clear submitted state to allow re-submission\n */\n const clearSubmitted = (): void => {\n submitted.value = null;\n error.value = null;\n };\n\n return {\n options,\n isSubmitting: readonly(isSubmitting),\n submitted: readonly(submitted),\n error: readonly(error),\n showFollowUp: readonly(showFollowUp),\n react,\n setShowFollowUp,\n clearSubmitted,\n isReactionWidget,\n isReady: readonly(isReady),\n showLabels,\n buttonSize,\n followUpTrigger,\n shouldShowFollowUp,\n styling,\n };\n}\n","/**\n * @feedvalue/vue - ReactionButtons Component\n *\n * Pre-built reaction buttons component for Vue applications.\n * Renders reaction options with optional follow-up input.\n */\n\nimport { defineComponent, ref, computed, h, type PropType } from 'vue';\nimport { useReaction } from './use-reaction';\nimport type { ReactionOption } from '@feedvalue/core';\n\nimport type { ButtonSize, ReactionBorderRadius } from '@feedvalue/core';\n\n/**\n * Border radius mapping from preset to CSS value\n */\nconst borderRadiusMap: Record<ReactionBorderRadius, string> = {\n full: '9999px',\n lg: '12px',\n md: '8px',\n sm: '4px',\n none: '0px',\n};\n\n/**\n * Border width mapping from preset to CSS value\n */\nconst borderWidthMap: Record<string, string> = {\n '0': '0px',\n '1': '1px',\n '2': '2px',\n '3': '3px',\n '4': '4px',\n thin: '1px',\n medium: '2px',\n thick: '3px',\n};\n\n/**\n * Button size style variants\n */\nconst sizeStyles: Record<ButtonSize, { button: Record<string, string>; icon: Record<string, string>; label: Record<string, string> }> = {\n sm: {\n button: { padding: '0.375rem 0.75rem', fontSize: '0.75rem', gap: '0.375rem' },\n icon: { fontSize: '1rem' },\n label: { fontSize: '0.75rem' },\n },\n md: {\n button: { padding: '0.5rem 1rem', fontSize: '0.875rem', gap: '0.5rem' },\n icon: { fontSize: '1.125rem' },\n label: { fontSize: '0.875rem' },\n },\n lg: {\n button: { padding: '0.75rem 1.25rem', fontSize: '1rem', gap: '0.625rem' },\n icon: { fontSize: '1.5rem' },\n label: { fontSize: '1rem' },\n },\n};\n\n/**\n * Default CSS styles for the component\n */\nconst styles = {\n container: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '0.75rem',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n },\n buttonGroup: {\n display: 'flex',\n flexWrap: 'wrap' as const,\n gap: '0.5rem',\n },\n button: {\n display: 'inline-flex',\n alignItems: 'center',\n fontWeight: '500',\n color: '#374151',\n backgroundColor: '#ffffff',\n border: '1px solid #d1d5db',\n borderRadius: '9999px',\n cursor: 'pointer',\n transition: 'background-color 0.15s, border-color 0.15s, transform 0.1s',\n },\n buttonActive: {\n backgroundColor: '#eef2ff',\n borderColor: '#6366f1',\n color: '#4f46e5',\n },\n buttonDisabled: {\n opacity: 0.7,\n cursor: 'not-allowed',\n },\n icon: {},\n followUp: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '0.5rem',\n padding: '0.75rem',\n backgroundColor: '#f9fafb',\n border: '1px solid #e5e7eb',\n borderRadius: '0.5rem',\n },\n input: {\n width: '100%',\n padding: '0.5rem 0.75rem',\n fontSize: '0.875rem',\n border: '1px solid #d1d5db',\n borderRadius: '0.375rem',\n backgroundColor: '#ffffff',\n boxSizing: 'border-box' as const,\n resize: 'none' as const,\n },\n actions: {\n display: 'flex',\n gap: '0.5rem',\n justifyContent: 'flex-end',\n },\n submitButton: {\n padding: '0.375rem 0.75rem',\n fontSize: '0.875rem',\n fontWeight: '500',\n color: '#ffffff',\n backgroundColor: '#6366f1',\n border: 'none',\n borderRadius: '0.375rem',\n cursor: 'pointer',\n },\n cancelButton: {\n padding: '0.375rem 0.75rem',\n fontSize: '0.875rem',\n color: '#6b7280',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n },\n thankYou: {\n display: 'flex',\n alignItems: 'center',\n gap: '0.5rem',\n padding: '0.75rem 1rem',\n fontSize: '0.875rem',\n color: '#059669',\n backgroundColor: '#ecfdf5',\n border: '1px solid #a7f3d0',\n borderRadius: '0.5rem',\n },\n resetButton: {\n padding: '0.25rem 0.5rem',\n fontSize: '0.875rem',\n color: '#6b7280',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n },\n error: {\n padding: '0.5rem 0.75rem',\n fontSize: '0.875rem',\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n border: '1px solid #fecaca',\n borderRadius: '0.375rem',\n },\n};\n\n/**\n * ReactionButtons Component\n *\n * Pre-built reaction buttons with follow-up input support.\n *\n * @example\n * ```vue\n * <template>\n * <ReactionButtons widget-id=\"xxx\" @react=\"onReact\" />\n * </template>\n *\n * <script setup>\n * import { ReactionButtons } from '@feedvalue/vue';\n *\n * const onReact = (value, followUp) => {\n * console.log('Reacted:', value, followUp);\n * };\n * </script>\n * ```\n */\nexport const ReactionButtons = defineComponent({\n name: 'ReactionButtons',\n\n props: {\n /** Widget ID (optional if using FeedValue plugin) */\n widgetId: {\n type: String as PropType<string | undefined>,\n default: undefined,\n },\n /** Custom thank you message (overrides widget config) */\n thankYouMessage: {\n type: String as PropType<string | undefined>,\n default: undefined,\n },\n /** Custom class for the container */\n containerClass: {\n type: String,\n default: '',\n },\n /** Custom class for buttons */\n buttonClass: {\n type: String,\n default: '',\n },\n /** Custom class for the follow-up form */\n formClass: {\n type: String,\n default: '',\n },\n /** Custom class for the thank you message */\n thankYouClass: {\n type: String,\n default: '',\n },\n /** Hide after submission (default: false) */\n hideAfterSubmit: {\n type: Boolean,\n default: false,\n },\n /** Whether to show follow-up inline or not at all */\n followUpMode: {\n type: String as PropType<'inline' | 'none'>,\n default: 'inline',\n },\n },\n\n emits: {\n /** Emitted when a reaction is submitted */\n react: (value: string, _followUp?: string) => typeof value === 'string',\n /** Emitted when an error occurs */\n error: (_error: Error) => true,\n },\n\n setup(props, { emit }) {\n const {\n options,\n react,\n isSubmitting,\n submitted,\n error,\n showFollowUp,\n setShowFollowUp,\n clearSubmitted,\n isReady,\n showLabels,\n buttonSize,\n shouldShowFollowUp,\n styling,\n isReactionWidget,\n } = useReaction(props.widgetId);\n\n // Local state for follow-up input\n const followUpText = ref('');\n // Hover state for buttons\n const hoveredButton = ref<string | null>(null);\n\n // Get follow-up option\n const getFollowUpOption = computed<ReactionOption | null>(() => {\n if (!showFollowUp.value || !options.value) return null;\n return options.value.find((opt) => opt.value === showFollowUp.value) ?? null;\n });\n\n /**\n * Handle option click\n */\n const handleOptionClick = (option: ReactionOption) => {\n if (props.followUpMode === 'inline' && shouldShowFollowUp(option.value)) {\n setShowFollowUp(option.value);\n } else {\n submitReaction(option.value);\n }\n };\n\n /**\n * Submit reaction\n */\n const submitReaction = async (value: string, followUp?: string) => {\n const trimmedFollowUp = followUp?.trim() || undefined;\n try {\n await react(value, trimmedFollowUp);\n emit('react', value, trimmedFollowUp);\n } catch (err) {\n const reactionError = err instanceof Error ? err : new Error(String(err));\n emit('error', reactionError);\n }\n };\n\n /**\n * Handle follow-up form submit\n */\n const handleFollowUpSubmit = (e: Event) => {\n e.preventDefault();\n if (showFollowUp.value) {\n submitReaction(showFollowUp.value, followUpText.value || undefined);\n followUpText.value = '';\n }\n };\n\n /**\n * Cancel follow-up\n */\n const cancelFollowUp = () => {\n setShowFollowUp(null);\n followUpText.value = '';\n };\n\n return () => {\n // Don't render if not ready, not a reaction widget, or no options\n if (!isReady.value || !isReactionWidget.value || !options.value) {\n return null;\n }\n\n // Hide after submission if prop is set\n if (submitted.value && props.hideAfterSubmit) {\n return null;\n }\n\n // Render thank you message after submission\n if (submitted.value) {\n const currentStyling = styling.value;\n return h(\n 'div',\n {\n class: props.thankYouClass || props.containerClass,\n style: props.thankYouClass ? undefined : {\n ...styles.thankYou,\n color: currentStyling.primaryColor ?? '#059669',\n },\n },\n [\n h('span', props.thankYouMessage || 'Thanks for your feedback!'),\n h(\n 'button',\n {\n type: 'button',\n style: styles.resetButton,\n onClick: clearSubmitted,\n 'aria-label': 'Submit another reaction',\n },\n '↺'\n ),\n ]\n );\n }\n\n // Build reaction buttons using styling from widget config\n const currentSizeStyles = sizeStyles[buttonSize.value] || sizeStyles.md;\n const currentStyling = styling.value;\n const borderRadius = borderRadiusMap[currentStyling.borderRadius ?? 'full'] ?? '9999px';\n const borderWidth = borderWidthMap[currentStyling.borderWidth ?? '1'] ?? '1px';\n\n // Only show buttons when follow-up is not displayed\n const buttonElements = !showFollowUp.value ? options.value.map((option) => {\n const isActive = showFollowUp.value === option.value;\n const isHovered = hoveredButton.value === option.value;\n const children = [\n h('span', { style: { ...styles.icon, ...currentSizeStyles.icon }, 'aria-hidden': 'true' }, option.icon),\n ];\n if (showLabels.value) {\n children.push(h('span', { style: { ...currentSizeStyles.label, color: currentStyling.buttonTextColor ?? '#4b5563' } }, option.label));\n }\n\n return h(\n 'button',\n {\n key: option.value,\n type: 'button',\n class: props.buttonClass,\n style: {\n ...styles.button,\n ...currentSizeStyles.button,\n backgroundColor: currentStyling.backgroundColor ?? '#ffffff',\n borderColor: isActive || isHovered ? (currentStyling.primaryColor ?? '#6366f1') : (currentStyling.borderColor ?? '#e5e7eb'),\n borderWidth: borderWidth,\n borderRadius: borderRadius,\n borderStyle: 'solid',\n color: currentStyling.buttonTextColor ?? '#4b5563',\n ...(isActive || isHovered ? {\n backgroundColor: `${currentStyling.primaryColor ?? '#6366f1'}10`,\n } : {}),\n ...(isSubmitting.value ? styles.buttonDisabled : {}),\n },\n disabled: isSubmitting.value,\n 'aria-pressed': isActive,\n 'aria-label': option.label,\n onClick: () => handleOptionClick(option),\n onMouseenter: () => { hoveredButton.value = option.value; },\n onMouseleave: () => { hoveredButton.value = null; },\n },\n children\n );\n }) : [];\n\n // Build follow-up form if needed\n let followUpForm = null;\n const followUpOption = getFollowUpOption.value;\n if (showFollowUp.value && followUpOption) {\n followUpForm = h(\n 'form',\n {\n class: props.formClass,\n style: props.formClass ? undefined : styles.followUp,\n onSubmit: handleFollowUpSubmit,\n },\n [\n h('textarea', {\n style: styles.input,\n value: followUpText.value,\n placeholder: followUpOption.followUpPlaceholder || 'Tell us more (optional)',\n disabled: isSubmitting.value,\n maxlength: 500,\n rows: 3,\n onInput: (e: Event) => {\n followUpText.value = (e.target as HTMLTextAreaElement).value;\n },\n }),\n h('div', { style: { ...styles.actions, justifyContent: 'center' } }, [\n h(\n 'button',\n {\n type: 'submit',\n style: {\n ...styles.submitButton,\n backgroundColor: currentStyling.primaryColor ?? '#6366f1',\n borderRadius: borderRadius,\n ...(isSubmitting.value ? styles.buttonDisabled : {}),\n },\n disabled: isSubmitting.value,\n },\n isSubmitting.value ? 'Sending...' : 'Send'\n ),\n h(\n 'button',\n {\n type: 'button',\n style: {\n ...styles.cancelButton,\n backgroundColor: currentStyling.backgroundColor ?? '#ffffff',\n color: currentStyling.buttonTextColor ?? '#6b7280',\n borderRadius: borderRadius,\n border: `${borderWidth} solid ${currentStyling.borderColor ?? '#e5e7eb'}`,\n },\n disabled: isSubmitting.value,\n onClick: cancelFollowUp,\n },\n 'Cancel'\n ),\n ]),\n ]\n );\n }\n\n // Build error message\n let errorElement = null;\n if (error.value) {\n errorElement = h(\n 'div',\n { style: styles.error, role: 'alert' },\n error.value.message\n );\n }\n\n // Return full component\n return h(\n 'div',\n {\n class: props.containerClass,\n style: styles.container,\n role: 'group',\n 'aria-label': 'Reaction buttons',\n },\n [\n // Only render button group if there are buttons to show\n buttonElements.length > 0\n ? h('div', { style: styles.buttonGroup, role: 'radiogroup' }, buttonElements)\n : null,\n followUpForm,\n errorElement,\n ].filter(Boolean)\n );\n };\n },\n});\n\nexport default ReactionButtons;\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -283,11 +283,33 @@ declare const ReactionButtons: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
283
283
|
type: StringConstructor;
|
|
284
284
|
default: string;
|
|
285
285
|
};
|
|
286
|
+
/** Custom class for the follow-up form */
|
|
287
|
+
formClass: {
|
|
288
|
+
type: StringConstructor;
|
|
289
|
+
default: string;
|
|
290
|
+
};
|
|
291
|
+
/** Custom class for the thank you message */
|
|
292
|
+
thankYouClass: {
|
|
293
|
+
type: StringConstructor;
|
|
294
|
+
default: string;
|
|
295
|
+
};
|
|
296
|
+
/** Hide after submission (default: false) */
|
|
297
|
+
hideAfterSubmit: {
|
|
298
|
+
type: BooleanConstructor;
|
|
299
|
+
default: boolean;
|
|
300
|
+
};
|
|
301
|
+
/** Whether to show follow-up inline or not at all */
|
|
302
|
+
followUpMode: {
|
|
303
|
+
type: PropType<"inline" | "none">;
|
|
304
|
+
default: string;
|
|
305
|
+
};
|
|
286
306
|
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
287
307
|
[key: string]: any;
|
|
288
308
|
}> | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
|
|
289
309
|
/** Emitted when a reaction is submitted */
|
|
290
310
|
react: (value: string, _followUp?: string) => boolean;
|
|
311
|
+
/** Emitted when an error occurs */
|
|
312
|
+
error: (_error: Error) => true;
|
|
291
313
|
}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
292
314
|
/** Widget ID (optional if using FeedValue plugin) */
|
|
293
315
|
widgetId: {
|
|
@@ -309,13 +331,38 @@ declare const ReactionButtons: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
309
331
|
type: StringConstructor;
|
|
310
332
|
default: string;
|
|
311
333
|
};
|
|
334
|
+
/** Custom class for the follow-up form */
|
|
335
|
+
formClass: {
|
|
336
|
+
type: StringConstructor;
|
|
337
|
+
default: string;
|
|
338
|
+
};
|
|
339
|
+
/** Custom class for the thank you message */
|
|
340
|
+
thankYouClass: {
|
|
341
|
+
type: StringConstructor;
|
|
342
|
+
default: string;
|
|
343
|
+
};
|
|
344
|
+
/** Hide after submission (default: false) */
|
|
345
|
+
hideAfterSubmit: {
|
|
346
|
+
type: BooleanConstructor;
|
|
347
|
+
default: boolean;
|
|
348
|
+
};
|
|
349
|
+
/** Whether to show follow-up inline or not at all */
|
|
350
|
+
followUpMode: {
|
|
351
|
+
type: PropType<"inline" | "none">;
|
|
352
|
+
default: string;
|
|
353
|
+
};
|
|
312
354
|
}>> & Readonly<{
|
|
355
|
+
onError?: (_error: Error) => any;
|
|
313
356
|
onReact?: (value: string, _followUp?: string | undefined) => any;
|
|
314
357
|
}>, {
|
|
315
|
-
widgetId: string | undefined;
|
|
316
358
|
thankYouMessage: string | undefined;
|
|
359
|
+
widgetId: string | undefined;
|
|
317
360
|
containerClass: string;
|
|
318
361
|
buttonClass: string;
|
|
362
|
+
formClass: string;
|
|
363
|
+
thankYouClass: string;
|
|
364
|
+
hideAfterSubmit: boolean;
|
|
365
|
+
followUpMode: "none" | "inline";
|
|
319
366
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
320
367
|
|
|
321
368
|
export { FEEDVALUE_KEY, FEEDVALUE_OPTIONS_KEY, type FeedValuePluginOptions, ReactionButtons, type UseFeedValueReturn, type UseReactionReturn, createFeedValue, useFeedValue, useReaction };
|
package/dist/index.d.ts
CHANGED
|
@@ -283,11 +283,33 @@ declare const ReactionButtons: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
283
283
|
type: StringConstructor;
|
|
284
284
|
default: string;
|
|
285
285
|
};
|
|
286
|
+
/** Custom class for the follow-up form */
|
|
287
|
+
formClass: {
|
|
288
|
+
type: StringConstructor;
|
|
289
|
+
default: string;
|
|
290
|
+
};
|
|
291
|
+
/** Custom class for the thank you message */
|
|
292
|
+
thankYouClass: {
|
|
293
|
+
type: StringConstructor;
|
|
294
|
+
default: string;
|
|
295
|
+
};
|
|
296
|
+
/** Hide after submission (default: false) */
|
|
297
|
+
hideAfterSubmit: {
|
|
298
|
+
type: BooleanConstructor;
|
|
299
|
+
default: boolean;
|
|
300
|
+
};
|
|
301
|
+
/** Whether to show follow-up inline or not at all */
|
|
302
|
+
followUpMode: {
|
|
303
|
+
type: PropType<"inline" | "none">;
|
|
304
|
+
default: string;
|
|
305
|
+
};
|
|
286
306
|
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
287
307
|
[key: string]: any;
|
|
288
308
|
}> | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
|
|
289
309
|
/** Emitted when a reaction is submitted */
|
|
290
310
|
react: (value: string, _followUp?: string) => boolean;
|
|
311
|
+
/** Emitted when an error occurs */
|
|
312
|
+
error: (_error: Error) => true;
|
|
291
313
|
}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
292
314
|
/** Widget ID (optional if using FeedValue plugin) */
|
|
293
315
|
widgetId: {
|
|
@@ -309,13 +331,38 @@ declare const ReactionButtons: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
309
331
|
type: StringConstructor;
|
|
310
332
|
default: string;
|
|
311
333
|
};
|
|
334
|
+
/** Custom class for the follow-up form */
|
|
335
|
+
formClass: {
|
|
336
|
+
type: StringConstructor;
|
|
337
|
+
default: string;
|
|
338
|
+
};
|
|
339
|
+
/** Custom class for the thank you message */
|
|
340
|
+
thankYouClass: {
|
|
341
|
+
type: StringConstructor;
|
|
342
|
+
default: string;
|
|
343
|
+
};
|
|
344
|
+
/** Hide after submission (default: false) */
|
|
345
|
+
hideAfterSubmit: {
|
|
346
|
+
type: BooleanConstructor;
|
|
347
|
+
default: boolean;
|
|
348
|
+
};
|
|
349
|
+
/** Whether to show follow-up inline or not at all */
|
|
350
|
+
followUpMode: {
|
|
351
|
+
type: PropType<"inline" | "none">;
|
|
352
|
+
default: string;
|
|
353
|
+
};
|
|
312
354
|
}>> & Readonly<{
|
|
355
|
+
onError?: (_error: Error) => any;
|
|
313
356
|
onReact?: (value: string, _followUp?: string | undefined) => any;
|
|
314
357
|
}>, {
|
|
315
|
-
widgetId: string | undefined;
|
|
316
358
|
thankYouMessage: string | undefined;
|
|
359
|
+
widgetId: string | undefined;
|
|
317
360
|
containerClass: string;
|
|
318
361
|
buttonClass: string;
|
|
362
|
+
formClass: string;
|
|
363
|
+
thankYouClass: string;
|
|
364
|
+
hideAfterSubmit: boolean;
|
|
365
|
+
followUpMode: "none" | "inline";
|
|
319
366
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
320
367
|
|
|
321
368
|
export { FEEDVALUE_KEY, FEEDVALUE_OPTIONS_KEY, type FeedValuePluginOptions, ReactionButtons, type UseFeedValueReturn, type UseReactionReturn, createFeedValue, useFeedValue, useReaction };
|
package/dist/index.js
CHANGED
|
@@ -163,7 +163,8 @@ function useReaction(widgetId) {
|
|
|
163
163
|
});
|
|
164
164
|
const reactionConfig = computed(() => {
|
|
165
165
|
if (!instance.value || !isReady.value) return null;
|
|
166
|
-
|
|
166
|
+
const widgetConfig = instance.value.getWidgetConfig();
|
|
167
|
+
return widgetConfig?.config ?? null;
|
|
167
168
|
});
|
|
168
169
|
const showLabels = computed(() => {
|
|
169
170
|
return reactionConfig.value?.showLabels ?? true;
|
|
@@ -190,7 +191,7 @@ function useReaction(widgetId) {
|
|
|
190
191
|
if (!instance.value || !isReady.value) {
|
|
191
192
|
return defaultStyling;
|
|
192
193
|
}
|
|
193
|
-
const widgetConfig = instance.value.
|
|
194
|
+
const widgetConfig = instance.value.getWidgetConfig();
|
|
194
195
|
if (!widgetConfig?.styling) {
|
|
195
196
|
return defaultStyling;
|
|
196
197
|
}
|
|
@@ -269,7 +270,10 @@ var borderWidthMap = {
|
|
|
269
270
|
"1": "1px",
|
|
270
271
|
"2": "2px",
|
|
271
272
|
"3": "3px",
|
|
272
|
-
"4": "4px"
|
|
273
|
+
"4": "4px",
|
|
274
|
+
thin: "1px",
|
|
275
|
+
medium: "2px",
|
|
276
|
+
thick: "3px"
|
|
273
277
|
};
|
|
274
278
|
var sizeStyles = {
|
|
275
279
|
sm: {
|
|
@@ -332,7 +336,8 @@ var styles = {
|
|
|
332
336
|
border: "1px solid #d1d5db",
|
|
333
337
|
borderRadius: "0.375rem",
|
|
334
338
|
backgroundColor: "#ffffff",
|
|
335
|
-
boxSizing: "border-box"
|
|
339
|
+
boxSizing: "border-box",
|
|
340
|
+
resize: "none"
|
|
336
341
|
},
|
|
337
342
|
actions: {
|
|
338
343
|
display: "flex",
|
|
@@ -407,11 +412,33 @@ var ReactionButtons = defineComponent({
|
|
|
407
412
|
buttonClass: {
|
|
408
413
|
type: String,
|
|
409
414
|
default: ""
|
|
415
|
+
},
|
|
416
|
+
/** Custom class for the follow-up form */
|
|
417
|
+
formClass: {
|
|
418
|
+
type: String,
|
|
419
|
+
default: ""
|
|
420
|
+
},
|
|
421
|
+
/** Custom class for the thank you message */
|
|
422
|
+
thankYouClass: {
|
|
423
|
+
type: String,
|
|
424
|
+
default: ""
|
|
425
|
+
},
|
|
426
|
+
/** Hide after submission (default: false) */
|
|
427
|
+
hideAfterSubmit: {
|
|
428
|
+
type: Boolean,
|
|
429
|
+
default: false
|
|
430
|
+
},
|
|
431
|
+
/** Whether to show follow-up inline or not at all */
|
|
432
|
+
followUpMode: {
|
|
433
|
+
type: String,
|
|
434
|
+
default: "inline"
|
|
410
435
|
}
|
|
411
436
|
},
|
|
412
437
|
emits: {
|
|
413
438
|
/** Emitted when a reaction is submitted */
|
|
414
|
-
react: (value, _followUp) => typeof value === "string"
|
|
439
|
+
react: (value, _followUp) => typeof value === "string",
|
|
440
|
+
/** Emitted when an error occurs */
|
|
441
|
+
error: (_error) => true
|
|
415
442
|
},
|
|
416
443
|
setup(props, { emit }) {
|
|
417
444
|
const {
|
|
@@ -427,25 +454,30 @@ var ReactionButtons = defineComponent({
|
|
|
427
454
|
showLabels,
|
|
428
455
|
buttonSize,
|
|
429
456
|
shouldShowFollowUp,
|
|
430
|
-
styling
|
|
457
|
+
styling,
|
|
458
|
+
isReactionWidget
|
|
431
459
|
} = useReaction(props.widgetId);
|
|
432
460
|
const followUpText = ref("");
|
|
461
|
+
const hoveredButton = ref(null);
|
|
433
462
|
const getFollowUpOption = computed(() => {
|
|
434
463
|
if (!showFollowUp.value || !options.value) return null;
|
|
435
464
|
return options.value.find((opt) => opt.value === showFollowUp.value) ?? null;
|
|
436
465
|
});
|
|
437
466
|
const handleOptionClick = (option) => {
|
|
438
|
-
if (shouldShowFollowUp(option.value)) {
|
|
467
|
+
if (props.followUpMode === "inline" && shouldShowFollowUp(option.value)) {
|
|
439
468
|
setShowFollowUp(option.value);
|
|
440
469
|
} else {
|
|
441
470
|
submitReaction(option.value);
|
|
442
471
|
}
|
|
443
472
|
};
|
|
444
473
|
const submitReaction = async (value, followUp) => {
|
|
474
|
+
const trimmedFollowUp = followUp?.trim() || void 0;
|
|
445
475
|
try {
|
|
446
|
-
await react(value,
|
|
447
|
-
emit("react", value,
|
|
448
|
-
} catch {
|
|
476
|
+
await react(value, trimmedFollowUp);
|
|
477
|
+
emit("react", value, trimmedFollowUp);
|
|
478
|
+
} catch (err) {
|
|
479
|
+
const reactionError = err instanceof Error ? err : new Error(String(err));
|
|
480
|
+
emit("error", reactionError);
|
|
449
481
|
}
|
|
450
482
|
};
|
|
451
483
|
const handleFollowUpSubmit = (e) => {
|
|
@@ -460,7 +492,10 @@ var ReactionButtons = defineComponent({
|
|
|
460
492
|
followUpText.value = "";
|
|
461
493
|
};
|
|
462
494
|
return () => {
|
|
463
|
-
if (!isReady.value || !options.value) {
|
|
495
|
+
if (!isReady.value || !isReactionWidget.value || !options.value) {
|
|
496
|
+
return null;
|
|
497
|
+
}
|
|
498
|
+
if (submitted.value && props.hideAfterSubmit) {
|
|
464
499
|
return null;
|
|
465
500
|
}
|
|
466
501
|
if (submitted.value) {
|
|
@@ -468,8 +503,8 @@ var ReactionButtons = defineComponent({
|
|
|
468
503
|
return h(
|
|
469
504
|
"div",
|
|
470
505
|
{
|
|
471
|
-
class: props.containerClass,
|
|
472
|
-
style: {
|
|
506
|
+
class: props.thankYouClass || props.containerClass,
|
|
507
|
+
style: props.thankYouClass ? void 0 : {
|
|
473
508
|
...styles.thankYou,
|
|
474
509
|
color: currentStyling2.primaryColor ?? "#059669"
|
|
475
510
|
}
|
|
@@ -493,8 +528,9 @@ var ReactionButtons = defineComponent({
|
|
|
493
528
|
const currentStyling = styling.value;
|
|
494
529
|
const borderRadius = borderRadiusMap[currentStyling.borderRadius ?? "full"] ?? "9999px";
|
|
495
530
|
const borderWidth = borderWidthMap[currentStyling.borderWidth ?? "1"] ?? "1px";
|
|
496
|
-
const buttonElements = options.value.map((option) => {
|
|
531
|
+
const buttonElements = !showFollowUp.value ? options.value.map((option) => {
|
|
497
532
|
const isActive = showFollowUp.value === option.value;
|
|
533
|
+
const isHovered = hoveredButton.value === option.value;
|
|
498
534
|
const children = [
|
|
499
535
|
h("span", { style: { ...styles.icon, ...currentSizeStyles.icon }, "aria-hidden": "true" }, option.icon)
|
|
500
536
|
];
|
|
@@ -511,11 +547,12 @@ var ReactionButtons = defineComponent({
|
|
|
511
547
|
...styles.button,
|
|
512
548
|
...currentSizeStyles.button,
|
|
513
549
|
backgroundColor: currentStyling.backgroundColor ?? "#ffffff",
|
|
514
|
-
borderColor: isActive ? currentStyling.primaryColor ?? "#6366f1" : currentStyling.borderColor ?? "#e5e7eb",
|
|
550
|
+
borderColor: isActive || isHovered ? currentStyling.primaryColor ?? "#6366f1" : currentStyling.borderColor ?? "#e5e7eb",
|
|
515
551
|
borderWidth,
|
|
516
552
|
borderRadius,
|
|
553
|
+
borderStyle: "solid",
|
|
517
554
|
color: currentStyling.buttonTextColor ?? "#4b5563",
|
|
518
|
-
...isActive ? {
|
|
555
|
+
...isActive || isHovered ? {
|
|
519
556
|
backgroundColor: `${currentStyling.primaryColor ?? "#6366f1"}10`
|
|
520
557
|
} : {},
|
|
521
558
|
...isSubmitting.value ? styles.buttonDisabled : {}
|
|
@@ -523,28 +560,35 @@ var ReactionButtons = defineComponent({
|
|
|
523
560
|
disabled: isSubmitting.value,
|
|
524
561
|
"aria-pressed": isActive,
|
|
525
562
|
"aria-label": option.label,
|
|
526
|
-
onClick: () => handleOptionClick(option)
|
|
563
|
+
onClick: () => handleOptionClick(option),
|
|
564
|
+
onMouseenter: () => {
|
|
565
|
+
hoveredButton.value = option.value;
|
|
566
|
+
},
|
|
567
|
+
onMouseleave: () => {
|
|
568
|
+
hoveredButton.value = null;
|
|
569
|
+
}
|
|
527
570
|
},
|
|
528
571
|
children
|
|
529
572
|
);
|
|
530
|
-
});
|
|
573
|
+
}) : [];
|
|
531
574
|
let followUpForm = null;
|
|
532
575
|
const followUpOption = getFollowUpOption.value;
|
|
533
576
|
if (showFollowUp.value && followUpOption) {
|
|
534
577
|
followUpForm = h(
|
|
535
578
|
"form",
|
|
536
579
|
{
|
|
537
|
-
|
|
580
|
+
class: props.formClass,
|
|
581
|
+
style: props.formClass ? void 0 : styles.followUp,
|
|
538
582
|
onSubmit: handleFollowUpSubmit
|
|
539
583
|
},
|
|
540
584
|
[
|
|
541
|
-
h("
|
|
542
|
-
type: "text",
|
|
585
|
+
h("textarea", {
|
|
543
586
|
style: styles.input,
|
|
544
587
|
value: followUpText.value,
|
|
545
|
-
placeholder: followUpOption.followUpPlaceholder || "Tell us more
|
|
588
|
+
placeholder: followUpOption.followUpPlaceholder || "Tell us more (optional)",
|
|
546
589
|
disabled: isSubmitting.value,
|
|
547
590
|
maxlength: 500,
|
|
591
|
+
rows: 3,
|
|
548
592
|
onInput: (e) => {
|
|
549
593
|
followUpText.value = e.target.value;
|
|
550
594
|
}
|
|
@@ -601,10 +645,11 @@ var ReactionButtons = defineComponent({
|
|
|
601
645
|
"aria-label": "Reaction buttons"
|
|
602
646
|
},
|
|
603
647
|
[
|
|
604
|
-
|
|
648
|
+
// Only render button group if there are buttons to show
|
|
649
|
+
buttonElements.length > 0 ? h("div", { style: styles.buttonGroup, role: "radiogroup" }, buttonElements) : null,
|
|
605
650
|
followUpForm,
|
|
606
651
|
errorElement
|
|
607
|
-
]
|
|
652
|
+
].filter(Boolean)
|
|
608
653
|
);
|
|
609
654
|
};
|
|
610
655
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugin.ts","../src/composables.ts","../src/use-reaction.ts","../src/ReactionButtons.ts"],"names":["FeedValue","inject","ref","onMounted","onUnmounted","readonly","computed","currentStyling"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @feedvalue/vue - Plugin\n *\n * Vue plugin for FeedValue. Provides app-level configuration\n * and automatic initialization.\n */\n\nimport type { App, InjectionKey } from 'vue';\nimport { FeedValue, type FeedValueConfig, type FeedValueInstance } from '@feedvalue/core';\n\n/**\n * Plugin options\n */\nexport interface FeedValuePluginOptions {\n /** Widget ID from FeedValue dashboard */\n widgetId: string;\n /** API base URL (for self-hosted) */\n apiBaseUrl?: string;\n /** Configuration overrides */\n config?: Partial<FeedValueConfig>;\n /**\n * Headless mode - disables all DOM rendering.\n * Use this when you want full control over the UI.\n * The SDK will still fetch config and provide all API methods\n * but won't render any trigger button or modal.\n *\n * @default false\n */\n headless?: boolean;\n}\n\n/**\n * Injection key for FeedValue instance\n */\nexport const FEEDVALUE_KEY: InjectionKey<FeedValueInstance> = Symbol('feedvalue');\n\n/**\n * Injection key for widget ID (used by useFeedValue when no instance is injected)\n */\nexport const FEEDVALUE_OPTIONS_KEY: InjectionKey<FeedValuePluginOptions> = Symbol('feedvalue-options');\n\n/**\n * Create FeedValue Vue plugin\n *\n * @example\n * ```ts\n * // main.ts\n * import { createApp } from 'vue';\n * import { createFeedValue } from '@feedvalue/vue';\n * import App from './App.vue';\n *\n * const app = createApp(App);\n *\n * app.use(createFeedValue({\n * widgetId: 'your-widget-id',\n * config: { theme: 'dark' }\n * }));\n *\n * app.mount('#app');\n * ```\n */\nexport function createFeedValue(options: FeedValuePluginOptions) {\n let instance: FeedValueInstance | null = null;\n\n return {\n install(app: App) {\n // Only initialize on client side\n if (typeof window !== 'undefined') {\n instance = FeedValue.init({\n widgetId: options.widgetId,\n apiBaseUrl: options.apiBaseUrl,\n config: options.config,\n headless: options.headless,\n });\n\n // Provide instance to all components\n app.provide(FEEDVALUE_KEY, instance);\n\n // Also provide to global properties for Options API access\n app.config.globalProperties.$feedvalue = instance;\n }\n\n // Always provide options (for SSR where we don't initialize)\n app.provide(FEEDVALUE_OPTIONS_KEY, options);\n },\n };\n}\n\n/**\n * Type augmentation for global properties\n */\ndeclare module 'vue' {\n interface ComponentCustomProperties {\n $feedvalue: FeedValueInstance | undefined;\n }\n}\n","/**\n * @feedvalue/vue - Composables\n *\n * Vue composables for FeedValue. Provides reactive state and methods.\n */\n\nimport {\n ref,\n shallowRef,\n readonly,\n onMounted,\n onUnmounted,\n inject,\n type Ref,\n type ShallowRef,\n} from 'vue';\nimport {\n FeedValue,\n type FeedValueConfig,\n type FeedValueInstance,\n type FeedbackData,\n type UserTraits,\n} from '@feedvalue/core';\nimport { FEEDVALUE_KEY, FEEDVALUE_OPTIONS_KEY } from './plugin';\n\n/**\n * Return type for useFeedValue composable\n */\nexport interface UseFeedValueReturn {\n /** FeedValue instance (for advanced usage) */\n instance: Readonly<ShallowRef<FeedValueInstance | null>>;\n /** Widget is ready */\n isReady: Readonly<Ref<boolean>>;\n /** Modal is open */\n isOpen: Readonly<Ref<boolean>>;\n /** Widget is visible */\n isVisible: Readonly<Ref<boolean>>;\n /** Current error */\n error: Readonly<Ref<Error | null>>;\n /** Submission in progress */\n isSubmitting: Readonly<Ref<boolean>>;\n /** Running in headless mode (no default UI rendered) */\n isHeadless: Readonly<Ref<boolean>>;\n /** Open the feedback modal */\n open: () => void;\n /** Close the feedback modal */\n close: () => void;\n /** Toggle the feedback modal */\n toggle: () => void;\n /** Show the trigger button */\n show: () => void;\n /** Hide the trigger button */\n hide: () => void;\n /** Submit feedback programmatically */\n submit: (feedback: Partial<FeedbackData>) => Promise<void>;\n /** Identify user */\n identify: (userId: string, traits?: UserTraits) => void;\n /** Set user data */\n setData: (data: Record<string, string>) => void;\n /** Reset user data */\n reset: () => void;\n}\n\n/**\n * FeedValue composable\n *\n * Can be used with or without plugin. If plugin is installed, uses the\n * provided instance. Otherwise, creates a new instance.\n *\n * @example\n * ```vue\n * <script setup>\n * import { useFeedValue } from '@feedvalue/vue';\n *\n * // With plugin installed\n * const { open, isReady } = useFeedValue();\n *\n * // Or standalone with widgetId\n * const { open, isReady } = useFeedValue('your-widget-id');\n * </script>\n *\n * <template>\n * <button @click=\"open\" :disabled=\"!isReady\">\n * Give Feedback\n * </button>\n * </template>\n * ```\n */\nexport function useFeedValue(\n widgetId?: string,\n config?: Partial<FeedValueConfig>\n): UseFeedValueReturn {\n // Try to inject instance from plugin\n const injectedInstance = inject(FEEDVALUE_KEY, null);\n const injectedOptions = inject(FEEDVALUE_OPTIONS_KEY, null);\n\n // Refs for reactive state\n const instance = shallowRef<FeedValueInstance | null>(null);\n const isReady = ref(false);\n const isOpen = ref(false);\n const isVisible = ref(false);\n const error = ref<Error | null>(null);\n const isSubmitting = ref(false);\n const isHeadless = ref(false);\n\n // Track if we own the instance (need to destroy on unmount)\n let ownsInstance = false;\n let unsubscribe: (() => void) | null = null;\n\n /**\n * Sync reactive state from instance\n */\n const syncState = () => {\n const state = instance.value?.getSnapshot();\n if (state) {\n isReady.value = state.isReady;\n isOpen.value = state.isOpen;\n isVisible.value = state.isVisible;\n error.value = state.error;\n isSubmitting.value = state.isSubmitting;\n }\n };\n\n onMounted(() => {\n // Use injected instance if available and no widgetId override\n if (injectedInstance && !widgetId) {\n instance.value = injectedInstance;\n isHeadless.value = injectedInstance.isHeadless();\n } else {\n // Create new instance\n const effectiveWidgetId = widgetId ?? injectedOptions?.widgetId;\n\n if (!effectiveWidgetId) {\n console.error(\n '[FeedValue] No widgetId provided. Either install the plugin with createFeedValue() ' +\n 'or pass widgetId to useFeedValue().'\n );\n return;\n }\n\n instance.value = FeedValue.init({\n widgetId: effectiveWidgetId,\n apiBaseUrl: injectedOptions?.apiBaseUrl,\n config: config ?? injectedOptions?.config,\n headless: injectedOptions?.headless,\n });\n ownsInstance = true;\n }\n\n // Subscribe to state changes\n if (instance.value) {\n unsubscribe = instance.value.subscribe(syncState);\n isHeadless.value = instance.value.isHeadless();\n syncState(); // Initial sync\n }\n });\n\n onUnmounted(() => {\n unsubscribe?.();\n if (ownsInstance && instance.value) {\n instance.value.destroy();\n }\n instance.value = null;\n });\n\n // Methods that delegate to instance\n const open = () => instance.value?.open();\n const close = () => instance.value?.close();\n const toggle = () => instance.value?.toggle();\n const show = () => instance.value?.show();\n const hide = () => instance.value?.hide();\n const submit = (feedback: Partial<FeedbackData>) =>\n instance.value?.submit(feedback) ?? Promise.reject(new Error('Not initialized'));\n const identify = (userId: string, traits?: UserTraits) =>\n instance.value?.identify(userId, traits);\n const setData = (data: Record<string, string>) => instance.value?.setData(data);\n const reset = () => instance.value?.reset();\n\n return {\n instance: readonly(instance),\n isReady: readonly(isReady),\n isOpen: readonly(isOpen),\n isVisible: readonly(isVisible),\n error: readonly(error),\n isSubmitting: readonly(isSubmitting),\n isHeadless: readonly(isHeadless),\n open,\n close,\n toggle,\n show,\n hide,\n submit,\n identify,\n setData,\n reset,\n };\n}\n","/**\n * @feedvalue/vue - useReaction Composable\n *\n * Composable for reaction widgets in Vue applications.\n * Provides a simple API for submitting reactions.\n */\n\nimport {\n ref,\n computed,\n readonly,\n onMounted,\n onUnmounted,\n inject,\n type Ref,\n type ComputedRef,\n} from 'vue';\nimport {\n FeedValue,\n NEGATIVE_OPTIONS_MAP,\n type ReactionOption,\n type FeedValueInstance,\n type ButtonSize,\n type FollowUpTrigger,\n type ReactionTemplate,\n type ReactionStyling,\n} from '@feedvalue/core';\nimport { FEEDVALUE_KEY, FEEDVALUE_OPTIONS_KEY } from './plugin';\n\n/**\n * Return type for useReaction composable\n */\nexport interface UseReactionReturn {\n /** Available reaction options */\n options: ComputedRef<ReactionOption[] | null>;\n /** Currently submitting */\n isSubmitting: Readonly<Ref<boolean>>;\n /** Successfully submitted value (null if not yet submitted) */\n submitted: Readonly<Ref<string | null>>;\n /** Error if submission failed */\n error: Readonly<Ref<Error | null>>;\n /** Option value requiring follow-up input (null if none) */\n showFollowUp: Readonly<Ref<string | null>>;\n /** Submit a reaction */\n react: (value: string, followUp?: string) => Promise<void>;\n /** Set which option is showing follow-up input */\n setShowFollowUp: (value: string | null) => void;\n /** Clear the submitted state to allow re-submission */\n clearSubmitted: () => void;\n /** Check if widget is a reaction type */\n isReactionWidget: ComputedRef<boolean>;\n /** Widget configuration is ready */\n isReady: Readonly<Ref<boolean>>;\n /** Whether to show text labels next to icons */\n showLabels: ComputedRef<boolean>;\n /** Button size */\n buttonSize: ComputedRef<ButtonSize>;\n /** When to show follow-up input */\n followUpTrigger: ComputedRef<FollowUpTrigger>;\n /** Check if an option should show follow-up based on followUpTrigger */\n shouldShowFollowUp: (optionValue: string) => boolean;\n /** Widget styling configuration */\n styling: ComputedRef<ReactionStyling>;\n}\n\n/**\n * Composable for reaction widgets\n *\n * Provides reaction options, submission handling, and follow-up state management.\n * Can be used with or without the FeedValue plugin.\n *\n * @param widgetId - Optional widget ID override (uses plugin widget if not provided)\n *\n * @example\n * ```vue\n * <script setup>\n * import { useReaction } from '@feedvalue/vue';\n *\n * const {\n * options,\n * react,\n * isSubmitting,\n * submitted,\n * error,\n * showFollowUp,\n * setShowFollowUp,\n * isReady,\n * } = useReaction();\n *\n * const handleClick = (option) => {\n * if (option.showFollowUp) {\n * setShowFollowUp(option.value);\n * } else {\n * react(option.value);\n * }\n * };\n * </script>\n *\n * <template>\n * <div v-if=\"isReady && options\">\n * <div v-if=\"submitted\">Thanks for your feedback!</div>\n *\n * <template v-else>\n * <button\n * v-for=\"option in options\"\n * :key=\"option.value\"\n * @click=\"handleClick(option)\"\n * :disabled=\"isSubmitting\"\n * >\n * {{ option.icon }} {{ option.label }}\n * </button>\n *\n * <form v-if=\"showFollowUp\" @submit.prevent=\"react(showFollowUp, followUpText)\">\n * <input v-model=\"followUpText\" placeholder=\"Tell us more...\" />\n * <button type=\"submit\">Send</button>\n * </form>\n *\n * <div v-if=\"error\">Error: {{ error.message }}</div>\n * </template>\n * </div>\n * </template>\n * ```\n */\nexport function useReaction(widgetId?: string): UseReactionReturn {\n // Try to inject instance from plugin\n const injectedInstance = inject(FEEDVALUE_KEY, null);\n const injectedOptions = inject(FEEDVALUE_OPTIONS_KEY, null);\n\n // Local instance ref (may be created if no plugin or widgetId override)\n const instance = ref<FeedValueInstance | null>(null);\n const isReady = ref(false);\n\n // Local state for reaction UI\n const showFollowUp = ref<string | null>(null);\n const submitted = ref<string | null>(null);\n const isSubmitting = ref(false);\n const error = ref<Error | null>(null);\n\n // Track if we own the instance (need to destroy on unmount)\n let ownsInstance = false;\n let unsubscribe: (() => void) | null = null;\n\n /**\n * Sync ready state from instance\n */\n const syncState = () => {\n const state = instance.value?.getSnapshot();\n if (state) {\n isReady.value = state.isReady;\n }\n };\n\n onMounted(() => {\n // Use injected instance if available and no widgetId override\n if (injectedInstance && !widgetId) {\n instance.value = injectedInstance;\n } else {\n // Create new instance\n const effectiveWidgetId = widgetId ?? injectedOptions?.widgetId;\n\n if (!effectiveWidgetId) {\n console.error(\n '[FeedValue] No widgetId provided. Either install the plugin with createFeedValue() ' +\n 'or pass widgetId to useReaction().'\n );\n return;\n }\n\n instance.value = FeedValue.init({\n widgetId: effectiveWidgetId,\n apiBaseUrl: injectedOptions?.apiBaseUrl,\n config: injectedOptions?.config,\n headless: true, // Reaction widgets are always headless\n });\n ownsInstance = true;\n }\n\n // Subscribe to state changes\n if (instance.value) {\n unsubscribe = instance.value.subscribe(syncState);\n syncState(); // Initial sync\n }\n });\n\n onUnmounted(() => {\n unsubscribe?.();\n if (ownsInstance && instance.value) {\n instance.value.destroy();\n }\n instance.value = null;\n });\n\n // Computed: reaction options from instance\n const options = computed<ReactionOption[] | null>(() => {\n if (!instance.value || !isReady.value) return null;\n return instance.value.getReactionOptions();\n });\n\n // Computed: check if this is a reaction widget\n const isReactionWidget = computed(() => {\n return instance.value?.isReaction() ?? false;\n });\n\n // Computed: get config values with defaults\n const reactionConfig = computed(() => {\n if (!instance.value || !isReady.value) return null;\n // Access the widget config which includes reaction config\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (instance.value as any)._widgetConfig?.config ?? null;\n });\n\n const showLabels = computed(() => {\n return reactionConfig.value?.showLabels ?? true;\n });\n\n const buttonSize = computed<ButtonSize>(() => {\n return reactionConfig.value?.buttonSize ?? 'md';\n });\n\n const followUpTrigger = computed<FollowUpTrigger>(() => {\n return reactionConfig.value?.followUpTrigger ?? 'negative';\n });\n\n const template = computed<ReactionTemplate | undefined>(() => {\n return reactionConfig.value?.template;\n });\n\n // Computed: widget styling configuration\n const styling = computed<ReactionStyling>(() => {\n const defaultStyling: ReactionStyling = {\n primaryColor: '#6366f1',\n backgroundColor: '#ffffff',\n textColor: '#111827',\n buttonTextColor: '#4b5563',\n borderColor: '#e5e7eb',\n borderWidth: '1',\n borderRadius: 'full',\n };\n\n if (!instance.value || !isReady.value) {\n return defaultStyling;\n }\n\n // Access the widget config styling\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const widgetConfig = (instance.value as any)._widgetConfig;\n if (!widgetConfig?.styling) {\n return defaultStyling;\n }\n\n // Cast styling to access extended properties that may be present from API\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const widgetStyling = widgetConfig.styling as any;\n return {\n primaryColor: widgetStyling.primaryColor ?? defaultStyling.primaryColor,\n backgroundColor: widgetStyling.backgroundColor ?? defaultStyling.backgroundColor,\n textColor: widgetStyling.textColor ?? defaultStyling.textColor,\n buttonTextColor: widgetStyling.buttonTextColor ?? defaultStyling.buttonTextColor,\n borderColor: widgetStyling.borderColor ?? defaultStyling.borderColor,\n borderWidth: widgetStyling.borderWidth ?? defaultStyling.borderWidth,\n borderRadius: widgetStyling.borderRadius ?? defaultStyling.borderRadius,\n };\n });\n\n /**\n * Check if an option should show follow-up based on followUpTrigger\n */\n const shouldShowFollowUp = (optionValue: string): boolean => {\n if (followUpTrigger.value === 'none') return false;\n if (followUpTrigger.value === 'all') return true;\n // followUpTrigger === 'negative'\n if (template.value && NEGATIVE_OPTIONS_MAP[template.value]) {\n return NEGATIVE_OPTIONS_MAP[template.value].includes(optionValue);\n }\n // For custom options, use the option's own showFollowUp setting\n const option = options.value?.find((o) => o.value === optionValue);\n return option?.showFollowUp ?? false;\n };\n\n /**\n * Submit a reaction\n */\n const react = async (value: string, followUp?: string): Promise<void> => {\n if (!instance.value) {\n throw new Error('FeedValue not initialized');\n }\n\n isSubmitting.value = true;\n error.value = null;\n\n try {\n await instance.value.react(value, followUp ? { followUp } : undefined);\n submitted.value = value;\n showFollowUp.value = null;\n } catch (err) {\n const reactionError = err instanceof Error ? err : new Error(String(err));\n error.value = reactionError;\n throw reactionError;\n } finally {\n isSubmitting.value = false;\n }\n };\n\n /**\n * Set which option is showing follow-up input\n */\n const setShowFollowUp = (value: string | null): void => {\n showFollowUp.value = value;\n };\n\n /**\n * Clear submitted state to allow re-submission\n */\n const clearSubmitted = (): void => {\n submitted.value = null;\n error.value = null;\n };\n\n return {\n options,\n isSubmitting: readonly(isSubmitting),\n submitted: readonly(submitted),\n error: readonly(error),\n showFollowUp: readonly(showFollowUp),\n react,\n setShowFollowUp,\n clearSubmitted,\n isReactionWidget,\n isReady: readonly(isReady),\n showLabels,\n buttonSize,\n followUpTrigger,\n shouldShowFollowUp,\n styling,\n };\n}\n","/**\n * @feedvalue/vue - ReactionButtons Component\n *\n * Pre-built reaction buttons component for Vue applications.\n * Renders reaction options with optional follow-up input.\n */\n\nimport { defineComponent, ref, computed, h, type PropType } from 'vue';\nimport { useReaction } from './use-reaction';\nimport type { ReactionOption } from '@feedvalue/core';\n\nimport type { ButtonSize, ReactionBorderRadius, ReactionBorderWidth } from '@feedvalue/core';\n\n/**\n * Border radius mapping from preset to CSS value\n */\nconst borderRadiusMap: Record<ReactionBorderRadius, string> = {\n full: '9999px',\n lg: '12px',\n md: '8px',\n sm: '4px',\n none: '0px',\n};\n\n/**\n * Border width mapping from preset to CSS value\n */\nconst borderWidthMap: Record<ReactionBorderWidth, string> = {\n '0': '0px',\n '1': '1px',\n '2': '2px',\n '3': '3px',\n '4': '4px',\n};\n\n/**\n * Button size style variants\n */\nconst sizeStyles: Record<ButtonSize, { button: Record<string, string>; icon: Record<string, string>; label: Record<string, string> }> = {\n sm: {\n button: { padding: '0.375rem 0.75rem', fontSize: '0.75rem', gap: '0.375rem' },\n icon: { fontSize: '1rem' },\n label: { fontSize: '0.75rem' },\n },\n md: {\n button: { padding: '0.5rem 1rem', fontSize: '0.875rem', gap: '0.5rem' },\n icon: { fontSize: '1.125rem' },\n label: { fontSize: '0.875rem' },\n },\n lg: {\n button: { padding: '0.75rem 1.25rem', fontSize: '1rem', gap: '0.625rem' },\n icon: { fontSize: '1.5rem' },\n label: { fontSize: '1rem' },\n },\n};\n\n/**\n * Default CSS styles for the component\n */\nconst styles = {\n container: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '0.75rem',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n },\n buttonGroup: {\n display: 'flex',\n flexWrap: 'wrap' as const,\n gap: '0.5rem',\n },\n button: {\n display: 'inline-flex',\n alignItems: 'center',\n fontWeight: '500',\n color: '#374151',\n backgroundColor: '#ffffff',\n border: '1px solid #d1d5db',\n borderRadius: '9999px',\n cursor: 'pointer',\n transition: 'background-color 0.15s, border-color 0.15s, transform 0.1s',\n },\n buttonActive: {\n backgroundColor: '#eef2ff',\n borderColor: '#6366f1',\n color: '#4f46e5',\n },\n buttonDisabled: {\n opacity: 0.7,\n cursor: 'not-allowed',\n },\n icon: {},\n followUp: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '0.5rem',\n padding: '0.75rem',\n backgroundColor: '#f9fafb',\n border: '1px solid #e5e7eb',\n borderRadius: '0.5rem',\n },\n input: {\n width: '100%',\n padding: '0.5rem 0.75rem',\n fontSize: '0.875rem',\n border: '1px solid #d1d5db',\n borderRadius: '0.375rem',\n backgroundColor: '#ffffff',\n boxSizing: 'border-box' as const,\n },\n actions: {\n display: 'flex',\n gap: '0.5rem',\n justifyContent: 'flex-end',\n },\n submitButton: {\n padding: '0.375rem 0.75rem',\n fontSize: '0.875rem',\n fontWeight: '500',\n color: '#ffffff',\n backgroundColor: '#6366f1',\n border: 'none',\n borderRadius: '0.375rem',\n cursor: 'pointer',\n },\n cancelButton: {\n padding: '0.375rem 0.75rem',\n fontSize: '0.875rem',\n color: '#6b7280',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n },\n thankYou: {\n display: 'flex',\n alignItems: 'center',\n gap: '0.5rem',\n padding: '0.75rem 1rem',\n fontSize: '0.875rem',\n color: '#059669',\n backgroundColor: '#ecfdf5',\n border: '1px solid #a7f3d0',\n borderRadius: '0.5rem',\n },\n resetButton: {\n padding: '0.25rem 0.5rem',\n fontSize: '0.875rem',\n color: '#6b7280',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n },\n error: {\n padding: '0.5rem 0.75rem',\n fontSize: '0.875rem',\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n border: '1px solid #fecaca',\n borderRadius: '0.375rem',\n },\n};\n\n/**\n * ReactionButtons Component\n *\n * Pre-built reaction buttons with follow-up input support.\n *\n * @example\n * ```vue\n * <template>\n * <ReactionButtons widget-id=\"xxx\" @react=\"onReact\" />\n * </template>\n *\n * <script setup>\n * import { ReactionButtons } from '@feedvalue/vue';\n *\n * const onReact = (value, followUp) => {\n * console.log('Reacted:', value, followUp);\n * };\n * </script>\n * ```\n */\nexport const ReactionButtons = defineComponent({\n name: 'ReactionButtons',\n\n props: {\n /** Widget ID (optional if using FeedValue plugin) */\n widgetId: {\n type: String as PropType<string | undefined>,\n default: undefined,\n },\n /** Custom thank you message (overrides widget config) */\n thankYouMessage: {\n type: String as PropType<string | undefined>,\n default: undefined,\n },\n /** Custom class for the container */\n containerClass: {\n type: String,\n default: '',\n },\n /** Custom class for buttons */\n buttonClass: {\n type: String,\n default: '',\n },\n },\n\n emits: {\n /** Emitted when a reaction is submitted */\n react: (value: string, _followUp?: string) => typeof value === 'string',\n },\n\n setup(props, { emit }) {\n const {\n options,\n react,\n isSubmitting,\n submitted,\n error,\n showFollowUp,\n setShowFollowUp,\n clearSubmitted,\n isReady,\n showLabels,\n buttonSize,\n shouldShowFollowUp,\n styling,\n } = useReaction(props.widgetId);\n\n // Local state for follow-up input\n const followUpText = ref('');\n\n // Get follow-up option\n const getFollowUpOption = computed<ReactionOption | null>(() => {\n if (!showFollowUp.value || !options.value) return null;\n return options.value.find((opt) => opt.value === showFollowUp.value) ?? null;\n });\n\n /**\n * Handle option click\n */\n const handleOptionClick = (option: ReactionOption) => {\n if (shouldShowFollowUp(option.value)) {\n setShowFollowUp(option.value);\n } else {\n submitReaction(option.value);\n }\n };\n\n /**\n * Submit reaction\n */\n const submitReaction = async (value: string, followUp?: string) => {\n try {\n await react(value, followUp);\n emit('react', value, followUp);\n } catch {\n // Error is already set in state\n }\n };\n\n /**\n * Handle follow-up form submit\n */\n const handleFollowUpSubmit = (e: Event) => {\n e.preventDefault();\n if (showFollowUp.value) {\n submitReaction(showFollowUp.value, followUpText.value || undefined);\n followUpText.value = '';\n }\n };\n\n /**\n * Cancel follow-up\n */\n const cancelFollowUp = () => {\n setShowFollowUp(null);\n followUpText.value = '';\n };\n\n return () => {\n // Don't render if not ready or no options\n if (!isReady.value || !options.value) {\n return null;\n }\n\n // Render thank you message after submission\n if (submitted.value) {\n const currentStyling = styling.value;\n return h(\n 'div',\n {\n class: props.containerClass,\n style: {\n ...styles.thankYou,\n color: currentStyling.primaryColor ?? '#059669',\n },\n },\n [\n h('span', props.thankYouMessage || 'Thanks for your feedback!'),\n h(\n 'button',\n {\n type: 'button',\n style: styles.resetButton,\n onClick: clearSubmitted,\n 'aria-label': 'Submit another reaction',\n },\n '↺'\n ),\n ]\n );\n }\n\n // Build reaction buttons using styling from widget config\n const currentSizeStyles = sizeStyles[buttonSize.value] || sizeStyles.md;\n const currentStyling = styling.value;\n const borderRadius = borderRadiusMap[currentStyling.borderRadius ?? 'full'] ?? '9999px';\n const borderWidth = borderWidthMap[currentStyling.borderWidth ?? '1'] ?? '1px';\n\n const buttonElements = options.value.map((option) => {\n const isActive = showFollowUp.value === option.value;\n const children = [\n h('span', { style: { ...styles.icon, ...currentSizeStyles.icon }, 'aria-hidden': 'true' }, option.icon),\n ];\n if (showLabels.value) {\n children.push(h('span', { style: { ...currentSizeStyles.label, color: currentStyling.buttonTextColor ?? '#4b5563' } }, option.label));\n }\n\n return h(\n 'button',\n {\n key: option.value,\n type: 'button',\n class: props.buttonClass,\n style: {\n ...styles.button,\n ...currentSizeStyles.button,\n backgroundColor: currentStyling.backgroundColor ?? '#ffffff',\n borderColor: isActive ? (currentStyling.primaryColor ?? '#6366f1') : (currentStyling.borderColor ?? '#e5e7eb'),\n borderWidth: borderWidth,\n borderRadius: borderRadius,\n color: currentStyling.buttonTextColor ?? '#4b5563',\n ...(isActive ? {\n backgroundColor: `${currentStyling.primaryColor ?? '#6366f1'}10`,\n } : {}),\n ...(isSubmitting.value ? styles.buttonDisabled : {}),\n },\n disabled: isSubmitting.value,\n 'aria-pressed': isActive,\n 'aria-label': option.label,\n onClick: () => handleOptionClick(option),\n },\n children\n );\n });\n\n // Build follow-up form if needed\n let followUpForm = null;\n const followUpOption = getFollowUpOption.value;\n if (showFollowUp.value && followUpOption) {\n followUpForm = h(\n 'form',\n {\n style: styles.followUp,\n onSubmit: handleFollowUpSubmit,\n },\n [\n h('input', {\n type: 'text',\n style: styles.input,\n value: followUpText.value,\n placeholder: followUpOption.followUpPlaceholder || 'Tell us more...',\n disabled: isSubmitting.value,\n maxlength: 500,\n onInput: (e: Event) => {\n followUpText.value = (e.target as HTMLInputElement).value;\n },\n }),\n h('div', { style: { ...styles.actions, justifyContent: 'center' } }, [\n h(\n 'button',\n {\n type: 'submit',\n style: {\n ...styles.submitButton,\n backgroundColor: currentStyling.primaryColor ?? '#6366f1',\n borderRadius: borderRadius,\n ...(isSubmitting.value ? styles.buttonDisabled : {}),\n },\n disabled: isSubmitting.value,\n },\n isSubmitting.value ? 'Sending...' : 'Send'\n ),\n h(\n 'button',\n {\n type: 'button',\n style: {\n ...styles.cancelButton,\n backgroundColor: currentStyling.backgroundColor ?? '#ffffff',\n color: currentStyling.buttonTextColor ?? '#6b7280',\n borderRadius: borderRadius,\n border: `${borderWidth} solid ${currentStyling.borderColor ?? '#e5e7eb'}`,\n },\n disabled: isSubmitting.value,\n onClick: cancelFollowUp,\n },\n 'Cancel'\n ),\n ]),\n ]\n );\n }\n\n // Build error message\n let errorElement = null;\n if (error.value) {\n errorElement = h(\n 'div',\n { style: styles.error, role: 'alert' },\n error.value.message\n );\n }\n\n // Return full component\n return h(\n 'div',\n {\n class: props.containerClass,\n style: styles.container,\n role: 'group',\n 'aria-label': 'Reaction buttons',\n },\n [\n h('div', { style: styles.buttonGroup, role: 'radiogroup' }, buttonElements),\n followUpForm,\n errorElement,\n ]\n );\n };\n },\n});\n\nexport default ReactionButtons;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/plugin.ts","../src/composables.ts","../src/use-reaction.ts","../src/ReactionButtons.ts"],"names":["FeedValue","inject","ref","onMounted","onUnmounted","readonly","computed","currentStyling"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @feedvalue/vue - Plugin\n *\n * Vue plugin for FeedValue. Provides app-level configuration\n * and automatic initialization.\n */\n\nimport type { App, InjectionKey } from 'vue';\nimport { FeedValue, type FeedValueConfig, type FeedValueInstance } from '@feedvalue/core';\n\n/**\n * Plugin options\n */\nexport interface FeedValuePluginOptions {\n /** Widget ID from FeedValue dashboard */\n widgetId: string;\n /** API base URL (for self-hosted) */\n apiBaseUrl?: string;\n /** Configuration overrides */\n config?: Partial<FeedValueConfig>;\n /**\n * Headless mode - disables all DOM rendering.\n * Use this when you want full control over the UI.\n * The SDK will still fetch config and provide all API methods\n * but won't render any trigger button or modal.\n *\n * @default false\n */\n headless?: boolean;\n}\n\n/**\n * Injection key for FeedValue instance\n */\nexport const FEEDVALUE_KEY: InjectionKey<FeedValueInstance> = Symbol('feedvalue');\n\n/**\n * Injection key for widget ID (used by useFeedValue when no instance is injected)\n */\nexport const FEEDVALUE_OPTIONS_KEY: InjectionKey<FeedValuePluginOptions> = Symbol('feedvalue-options');\n\n/**\n * Create FeedValue Vue plugin\n *\n * @example\n * ```ts\n * // main.ts\n * import { createApp } from 'vue';\n * import { createFeedValue } from '@feedvalue/vue';\n * import App from './App.vue';\n *\n * const app = createApp(App);\n *\n * app.use(createFeedValue({\n * widgetId: 'your-widget-id',\n * config: { theme: 'dark' }\n * }));\n *\n * app.mount('#app');\n * ```\n */\nexport function createFeedValue(options: FeedValuePluginOptions) {\n let instance: FeedValueInstance | null = null;\n\n return {\n install(app: App) {\n // Only initialize on client side\n if (typeof window !== 'undefined') {\n instance = FeedValue.init({\n widgetId: options.widgetId,\n apiBaseUrl: options.apiBaseUrl,\n config: options.config,\n headless: options.headless,\n });\n\n // Provide instance to all components\n app.provide(FEEDVALUE_KEY, instance);\n\n // Also provide to global properties for Options API access\n app.config.globalProperties.$feedvalue = instance;\n }\n\n // Always provide options (for SSR where we don't initialize)\n app.provide(FEEDVALUE_OPTIONS_KEY, options);\n },\n };\n}\n\n/**\n * Type augmentation for global properties\n */\ndeclare module 'vue' {\n interface ComponentCustomProperties {\n $feedvalue: FeedValueInstance | undefined;\n }\n}\n","/**\n * @feedvalue/vue - Composables\n *\n * Vue composables for FeedValue. Provides reactive state and methods.\n */\n\nimport {\n ref,\n shallowRef,\n readonly,\n onMounted,\n onUnmounted,\n inject,\n type Ref,\n type ShallowRef,\n} from 'vue';\nimport {\n FeedValue,\n type FeedValueConfig,\n type FeedValueInstance,\n type FeedbackData,\n type UserTraits,\n} from '@feedvalue/core';\nimport { FEEDVALUE_KEY, FEEDVALUE_OPTIONS_KEY } from './plugin';\n\n/**\n * Return type for useFeedValue composable\n */\nexport interface UseFeedValueReturn {\n /** FeedValue instance (for advanced usage) */\n instance: Readonly<ShallowRef<FeedValueInstance | null>>;\n /** Widget is ready */\n isReady: Readonly<Ref<boolean>>;\n /** Modal is open */\n isOpen: Readonly<Ref<boolean>>;\n /** Widget is visible */\n isVisible: Readonly<Ref<boolean>>;\n /** Current error */\n error: Readonly<Ref<Error | null>>;\n /** Submission in progress */\n isSubmitting: Readonly<Ref<boolean>>;\n /** Running in headless mode (no default UI rendered) */\n isHeadless: Readonly<Ref<boolean>>;\n /** Open the feedback modal */\n open: () => void;\n /** Close the feedback modal */\n close: () => void;\n /** Toggle the feedback modal */\n toggle: () => void;\n /** Show the trigger button */\n show: () => void;\n /** Hide the trigger button */\n hide: () => void;\n /** Submit feedback programmatically */\n submit: (feedback: Partial<FeedbackData>) => Promise<void>;\n /** Identify user */\n identify: (userId: string, traits?: UserTraits) => void;\n /** Set user data */\n setData: (data: Record<string, string>) => void;\n /** Reset user data */\n reset: () => void;\n}\n\n/**\n * FeedValue composable\n *\n * Can be used with or without plugin. If plugin is installed, uses the\n * provided instance. Otherwise, creates a new instance.\n *\n * @example\n * ```vue\n * <script setup>\n * import { useFeedValue } from '@feedvalue/vue';\n *\n * // With plugin installed\n * const { open, isReady } = useFeedValue();\n *\n * // Or standalone with widgetId\n * const { open, isReady } = useFeedValue('your-widget-id');\n * </script>\n *\n * <template>\n * <button @click=\"open\" :disabled=\"!isReady\">\n * Give Feedback\n * </button>\n * </template>\n * ```\n */\nexport function useFeedValue(\n widgetId?: string,\n config?: Partial<FeedValueConfig>\n): UseFeedValueReturn {\n // Try to inject instance from plugin\n const injectedInstance = inject(FEEDVALUE_KEY, null);\n const injectedOptions = inject(FEEDVALUE_OPTIONS_KEY, null);\n\n // Refs for reactive state\n const instance = shallowRef<FeedValueInstance | null>(null);\n const isReady = ref(false);\n const isOpen = ref(false);\n const isVisible = ref(false);\n const error = ref<Error | null>(null);\n const isSubmitting = ref(false);\n const isHeadless = ref(false);\n\n // Track if we own the instance (need to destroy on unmount)\n let ownsInstance = false;\n let unsubscribe: (() => void) | null = null;\n\n /**\n * Sync reactive state from instance\n */\n const syncState = () => {\n const state = instance.value?.getSnapshot();\n if (state) {\n isReady.value = state.isReady;\n isOpen.value = state.isOpen;\n isVisible.value = state.isVisible;\n error.value = state.error;\n isSubmitting.value = state.isSubmitting;\n }\n };\n\n onMounted(() => {\n // Use injected instance if available and no widgetId override\n if (injectedInstance && !widgetId) {\n instance.value = injectedInstance;\n isHeadless.value = injectedInstance.isHeadless();\n } else {\n // Create new instance\n const effectiveWidgetId = widgetId ?? injectedOptions?.widgetId;\n\n if (!effectiveWidgetId) {\n console.error(\n '[FeedValue] No widgetId provided. Either install the plugin with createFeedValue() ' +\n 'or pass widgetId to useFeedValue().'\n );\n return;\n }\n\n instance.value = FeedValue.init({\n widgetId: effectiveWidgetId,\n apiBaseUrl: injectedOptions?.apiBaseUrl,\n config: config ?? injectedOptions?.config,\n headless: injectedOptions?.headless,\n });\n ownsInstance = true;\n }\n\n // Subscribe to state changes\n if (instance.value) {\n unsubscribe = instance.value.subscribe(syncState);\n isHeadless.value = instance.value.isHeadless();\n syncState(); // Initial sync\n }\n });\n\n onUnmounted(() => {\n unsubscribe?.();\n if (ownsInstance && instance.value) {\n instance.value.destroy();\n }\n instance.value = null;\n });\n\n // Methods that delegate to instance\n const open = () => instance.value?.open();\n const close = () => instance.value?.close();\n const toggle = () => instance.value?.toggle();\n const show = () => instance.value?.show();\n const hide = () => instance.value?.hide();\n const submit = (feedback: Partial<FeedbackData>) =>\n instance.value?.submit(feedback) ?? Promise.reject(new Error('Not initialized'));\n const identify = (userId: string, traits?: UserTraits) =>\n instance.value?.identify(userId, traits);\n const setData = (data: Record<string, string>) => instance.value?.setData(data);\n const reset = () => instance.value?.reset();\n\n return {\n instance: readonly(instance),\n isReady: readonly(isReady),\n isOpen: readonly(isOpen),\n isVisible: readonly(isVisible),\n error: readonly(error),\n isSubmitting: readonly(isSubmitting),\n isHeadless: readonly(isHeadless),\n open,\n close,\n toggle,\n show,\n hide,\n submit,\n identify,\n setData,\n reset,\n };\n}\n","/**\n * @feedvalue/vue - useReaction Composable\n *\n * Composable for reaction widgets in Vue applications.\n * Provides a simple API for submitting reactions.\n */\n\nimport {\n ref,\n computed,\n readonly,\n onMounted,\n onUnmounted,\n inject,\n type Ref,\n type ComputedRef,\n} from 'vue';\nimport {\n FeedValue,\n NEGATIVE_OPTIONS_MAP,\n type ReactionOption,\n type FeedValueInstance,\n type ButtonSize,\n type FollowUpTrigger,\n type ReactionTemplate,\n type ReactionStyling,\n} from '@feedvalue/core';\nimport { FEEDVALUE_KEY, FEEDVALUE_OPTIONS_KEY } from './plugin';\n\n/**\n * Return type for useReaction composable\n */\nexport interface UseReactionReturn {\n /** Available reaction options */\n options: ComputedRef<ReactionOption[] | null>;\n /** Currently submitting */\n isSubmitting: Readonly<Ref<boolean>>;\n /** Successfully submitted value (null if not yet submitted) */\n submitted: Readonly<Ref<string | null>>;\n /** Error if submission failed */\n error: Readonly<Ref<Error | null>>;\n /** Option value requiring follow-up input (null if none) */\n showFollowUp: Readonly<Ref<string | null>>;\n /** Submit a reaction */\n react: (value: string, followUp?: string) => Promise<void>;\n /** Set which option is showing follow-up input */\n setShowFollowUp: (value: string | null) => void;\n /** Clear the submitted state to allow re-submission */\n clearSubmitted: () => void;\n /** Check if widget is a reaction type */\n isReactionWidget: ComputedRef<boolean>;\n /** Widget configuration is ready */\n isReady: Readonly<Ref<boolean>>;\n /** Whether to show text labels next to icons */\n showLabels: ComputedRef<boolean>;\n /** Button size */\n buttonSize: ComputedRef<ButtonSize>;\n /** When to show follow-up input */\n followUpTrigger: ComputedRef<FollowUpTrigger>;\n /** Check if an option should show follow-up based on followUpTrigger */\n shouldShowFollowUp: (optionValue: string) => boolean;\n /** Widget styling configuration */\n styling: ComputedRef<ReactionStyling>;\n}\n\n/**\n * Composable for reaction widgets\n *\n * Provides reaction options, submission handling, and follow-up state management.\n * Can be used with or without the FeedValue plugin.\n *\n * @param widgetId - Optional widget ID override (uses plugin widget if not provided)\n *\n * @example\n * ```vue\n * <script setup>\n * import { useReaction } from '@feedvalue/vue';\n *\n * const {\n * options,\n * react,\n * isSubmitting,\n * submitted,\n * error,\n * showFollowUp,\n * setShowFollowUp,\n * isReady,\n * } = useReaction();\n *\n * const handleClick = (option) => {\n * if (option.showFollowUp) {\n * setShowFollowUp(option.value);\n * } else {\n * react(option.value);\n * }\n * };\n * </script>\n *\n * <template>\n * <div v-if=\"isReady && options\">\n * <div v-if=\"submitted\">Thanks for your feedback!</div>\n *\n * <template v-else>\n * <button\n * v-for=\"option in options\"\n * :key=\"option.value\"\n * @click=\"handleClick(option)\"\n * :disabled=\"isSubmitting\"\n * >\n * {{ option.icon }} {{ option.label }}\n * </button>\n *\n * <form v-if=\"showFollowUp\" @submit.prevent=\"react(showFollowUp, followUpText)\">\n * <input v-model=\"followUpText\" placeholder=\"Tell us more...\" />\n * <button type=\"submit\">Send</button>\n * </form>\n *\n * <div v-if=\"error\">Error: {{ error.message }}</div>\n * </template>\n * </div>\n * </template>\n * ```\n */\nexport function useReaction(widgetId?: string): UseReactionReturn {\n // Try to inject instance from plugin\n const injectedInstance = inject(FEEDVALUE_KEY, null);\n const injectedOptions = inject(FEEDVALUE_OPTIONS_KEY, null);\n\n // Local instance ref (may be created if no plugin or widgetId override)\n const instance = ref<FeedValueInstance | null>(null);\n const isReady = ref(false);\n\n // Local state for reaction UI\n const showFollowUp = ref<string | null>(null);\n const submitted = ref<string | null>(null);\n const isSubmitting = ref(false);\n const error = ref<Error | null>(null);\n\n // Track if we own the instance (need to destroy on unmount)\n let ownsInstance = false;\n let unsubscribe: (() => void) | null = null;\n\n /**\n * Sync ready state from instance\n */\n const syncState = () => {\n const state = instance.value?.getSnapshot();\n if (state) {\n isReady.value = state.isReady;\n }\n };\n\n onMounted(() => {\n // Use injected instance if available and no widgetId override\n if (injectedInstance && !widgetId) {\n instance.value = injectedInstance;\n } else {\n // Create new instance\n const effectiveWidgetId = widgetId ?? injectedOptions?.widgetId;\n\n if (!effectiveWidgetId) {\n console.error(\n '[FeedValue] No widgetId provided. Either install the plugin with createFeedValue() ' +\n 'or pass widgetId to useReaction().'\n );\n return;\n }\n\n instance.value = FeedValue.init({\n widgetId: effectiveWidgetId,\n apiBaseUrl: injectedOptions?.apiBaseUrl,\n config: injectedOptions?.config,\n headless: true, // Reaction widgets are always headless\n });\n ownsInstance = true;\n }\n\n // Subscribe to state changes\n if (instance.value) {\n unsubscribe = instance.value.subscribe(syncState);\n syncState(); // Initial sync\n }\n });\n\n onUnmounted(() => {\n unsubscribe?.();\n if (ownsInstance && instance.value) {\n instance.value.destroy();\n }\n instance.value = null;\n });\n\n // Computed: reaction options from instance\n const options = computed<ReactionOption[] | null>(() => {\n if (!instance.value || !isReady.value) return null;\n return instance.value.getReactionOptions();\n });\n\n // Computed: check if this is a reaction widget\n const isReactionWidget = computed(() => {\n return instance.value?.isReaction() ?? false;\n });\n\n // Computed: get config values with defaults\n const reactionConfig = computed(() => {\n if (!instance.value || !isReady.value) return null;\n // Access the widget config which includes reaction config\n const widgetConfig = instance.value.getWidgetConfig();\n return widgetConfig?.config ?? null;\n });\n\n const showLabels = computed(() => {\n return reactionConfig.value?.showLabels ?? true;\n });\n\n const buttonSize = computed<ButtonSize>(() => {\n return reactionConfig.value?.buttonSize ?? 'md';\n });\n\n const followUpTrigger = computed<FollowUpTrigger>(() => {\n return reactionConfig.value?.followUpTrigger ?? 'negative';\n });\n\n const template = computed<ReactionTemplate | undefined>(() => {\n return reactionConfig.value?.template;\n });\n\n // Computed: widget styling configuration\n const styling = computed<ReactionStyling>(() => {\n const defaultStyling: ReactionStyling = {\n primaryColor: '#6366f1',\n backgroundColor: '#ffffff',\n textColor: '#111827',\n buttonTextColor: '#4b5563',\n borderColor: '#e5e7eb',\n borderWidth: '1',\n borderRadius: 'full',\n };\n\n if (!instance.value || !isReady.value) {\n return defaultStyling;\n }\n\n // Access the widget config styling using public method\n const widgetConfig = instance.value.getWidgetConfig();\n if (!widgetConfig?.styling) {\n return defaultStyling;\n }\n\n // Cast styling to access extended properties that may be present from API\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const widgetStyling = widgetConfig.styling as any;\n return {\n primaryColor: widgetStyling.primaryColor ?? defaultStyling.primaryColor,\n backgroundColor: widgetStyling.backgroundColor ?? defaultStyling.backgroundColor,\n textColor: widgetStyling.textColor ?? defaultStyling.textColor,\n buttonTextColor: widgetStyling.buttonTextColor ?? defaultStyling.buttonTextColor,\n borderColor: widgetStyling.borderColor ?? defaultStyling.borderColor,\n borderWidth: widgetStyling.borderWidth ?? defaultStyling.borderWidth,\n borderRadius: widgetStyling.borderRadius ?? defaultStyling.borderRadius,\n };\n });\n\n /**\n * Check if an option should show follow-up based on followUpTrigger\n */\n const shouldShowFollowUp = (optionValue: string): boolean => {\n if (followUpTrigger.value === 'none') return false;\n if (followUpTrigger.value === 'all') return true;\n // followUpTrigger === 'negative'\n if (template.value && NEGATIVE_OPTIONS_MAP[template.value]) {\n return NEGATIVE_OPTIONS_MAP[template.value].includes(optionValue);\n }\n // For custom options, use the option's own showFollowUp setting\n const option = options.value?.find((o) => o.value === optionValue);\n return option?.showFollowUp ?? false;\n };\n\n /**\n * Submit a reaction\n */\n const react = async (value: string, followUp?: string): Promise<void> => {\n if (!instance.value) {\n throw new Error('FeedValue not initialized');\n }\n\n isSubmitting.value = true;\n error.value = null;\n\n try {\n await instance.value.react(value, followUp ? { followUp } : undefined);\n submitted.value = value;\n showFollowUp.value = null;\n } catch (err) {\n const reactionError = err instanceof Error ? err : new Error(String(err));\n error.value = reactionError;\n throw reactionError;\n } finally {\n isSubmitting.value = false;\n }\n };\n\n /**\n * Set which option is showing follow-up input\n */\n const setShowFollowUp = (value: string | null): void => {\n showFollowUp.value = value;\n };\n\n /**\n * Clear submitted state to allow re-submission\n */\n const clearSubmitted = (): void => {\n submitted.value = null;\n error.value = null;\n };\n\n return {\n options,\n isSubmitting: readonly(isSubmitting),\n submitted: readonly(submitted),\n error: readonly(error),\n showFollowUp: readonly(showFollowUp),\n react,\n setShowFollowUp,\n clearSubmitted,\n isReactionWidget,\n isReady: readonly(isReady),\n showLabels,\n buttonSize,\n followUpTrigger,\n shouldShowFollowUp,\n styling,\n };\n}\n","/**\n * @feedvalue/vue - ReactionButtons Component\n *\n * Pre-built reaction buttons component for Vue applications.\n * Renders reaction options with optional follow-up input.\n */\n\nimport { defineComponent, ref, computed, h, type PropType } from 'vue';\nimport { useReaction } from './use-reaction';\nimport type { ReactionOption } from '@feedvalue/core';\n\nimport type { ButtonSize, ReactionBorderRadius } from '@feedvalue/core';\n\n/**\n * Border radius mapping from preset to CSS value\n */\nconst borderRadiusMap: Record<ReactionBorderRadius, string> = {\n full: '9999px',\n lg: '12px',\n md: '8px',\n sm: '4px',\n none: '0px',\n};\n\n/**\n * Border width mapping from preset to CSS value\n */\nconst borderWidthMap: Record<string, string> = {\n '0': '0px',\n '1': '1px',\n '2': '2px',\n '3': '3px',\n '4': '4px',\n thin: '1px',\n medium: '2px',\n thick: '3px',\n};\n\n/**\n * Button size style variants\n */\nconst sizeStyles: Record<ButtonSize, { button: Record<string, string>; icon: Record<string, string>; label: Record<string, string> }> = {\n sm: {\n button: { padding: '0.375rem 0.75rem', fontSize: '0.75rem', gap: '0.375rem' },\n icon: { fontSize: '1rem' },\n label: { fontSize: '0.75rem' },\n },\n md: {\n button: { padding: '0.5rem 1rem', fontSize: '0.875rem', gap: '0.5rem' },\n icon: { fontSize: '1.125rem' },\n label: { fontSize: '0.875rem' },\n },\n lg: {\n button: { padding: '0.75rem 1.25rem', fontSize: '1rem', gap: '0.625rem' },\n icon: { fontSize: '1.5rem' },\n label: { fontSize: '1rem' },\n },\n};\n\n/**\n * Default CSS styles for the component\n */\nconst styles = {\n container: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '0.75rem',\n fontFamily: 'system-ui, -apple-system, sans-serif',\n },\n buttonGroup: {\n display: 'flex',\n flexWrap: 'wrap' as const,\n gap: '0.5rem',\n },\n button: {\n display: 'inline-flex',\n alignItems: 'center',\n fontWeight: '500',\n color: '#374151',\n backgroundColor: '#ffffff',\n border: '1px solid #d1d5db',\n borderRadius: '9999px',\n cursor: 'pointer',\n transition: 'background-color 0.15s, border-color 0.15s, transform 0.1s',\n },\n buttonActive: {\n backgroundColor: '#eef2ff',\n borderColor: '#6366f1',\n color: '#4f46e5',\n },\n buttonDisabled: {\n opacity: 0.7,\n cursor: 'not-allowed',\n },\n icon: {},\n followUp: {\n display: 'flex',\n flexDirection: 'column' as const,\n gap: '0.5rem',\n padding: '0.75rem',\n backgroundColor: '#f9fafb',\n border: '1px solid #e5e7eb',\n borderRadius: '0.5rem',\n },\n input: {\n width: '100%',\n padding: '0.5rem 0.75rem',\n fontSize: '0.875rem',\n border: '1px solid #d1d5db',\n borderRadius: '0.375rem',\n backgroundColor: '#ffffff',\n boxSizing: 'border-box' as const,\n resize: 'none' as const,\n },\n actions: {\n display: 'flex',\n gap: '0.5rem',\n justifyContent: 'flex-end',\n },\n submitButton: {\n padding: '0.375rem 0.75rem',\n fontSize: '0.875rem',\n fontWeight: '500',\n color: '#ffffff',\n backgroundColor: '#6366f1',\n border: 'none',\n borderRadius: '0.375rem',\n cursor: 'pointer',\n },\n cancelButton: {\n padding: '0.375rem 0.75rem',\n fontSize: '0.875rem',\n color: '#6b7280',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n },\n thankYou: {\n display: 'flex',\n alignItems: 'center',\n gap: '0.5rem',\n padding: '0.75rem 1rem',\n fontSize: '0.875rem',\n color: '#059669',\n backgroundColor: '#ecfdf5',\n border: '1px solid #a7f3d0',\n borderRadius: '0.5rem',\n },\n resetButton: {\n padding: '0.25rem 0.5rem',\n fontSize: '0.875rem',\n color: '#6b7280',\n background: 'none',\n border: 'none',\n cursor: 'pointer',\n },\n error: {\n padding: '0.5rem 0.75rem',\n fontSize: '0.875rem',\n color: '#dc2626',\n backgroundColor: '#fef2f2',\n border: '1px solid #fecaca',\n borderRadius: '0.375rem',\n },\n};\n\n/**\n * ReactionButtons Component\n *\n * Pre-built reaction buttons with follow-up input support.\n *\n * @example\n * ```vue\n * <template>\n * <ReactionButtons widget-id=\"xxx\" @react=\"onReact\" />\n * </template>\n *\n * <script setup>\n * import { ReactionButtons } from '@feedvalue/vue';\n *\n * const onReact = (value, followUp) => {\n * console.log('Reacted:', value, followUp);\n * };\n * </script>\n * ```\n */\nexport const ReactionButtons = defineComponent({\n name: 'ReactionButtons',\n\n props: {\n /** Widget ID (optional if using FeedValue plugin) */\n widgetId: {\n type: String as PropType<string | undefined>,\n default: undefined,\n },\n /** Custom thank you message (overrides widget config) */\n thankYouMessage: {\n type: String as PropType<string | undefined>,\n default: undefined,\n },\n /** Custom class for the container */\n containerClass: {\n type: String,\n default: '',\n },\n /** Custom class for buttons */\n buttonClass: {\n type: String,\n default: '',\n },\n /** Custom class for the follow-up form */\n formClass: {\n type: String,\n default: '',\n },\n /** Custom class for the thank you message */\n thankYouClass: {\n type: String,\n default: '',\n },\n /** Hide after submission (default: false) */\n hideAfterSubmit: {\n type: Boolean,\n default: false,\n },\n /** Whether to show follow-up inline or not at all */\n followUpMode: {\n type: String as PropType<'inline' | 'none'>,\n default: 'inline',\n },\n },\n\n emits: {\n /** Emitted when a reaction is submitted */\n react: (value: string, _followUp?: string) => typeof value === 'string',\n /** Emitted when an error occurs */\n error: (_error: Error) => true,\n },\n\n setup(props, { emit }) {\n const {\n options,\n react,\n isSubmitting,\n submitted,\n error,\n showFollowUp,\n setShowFollowUp,\n clearSubmitted,\n isReady,\n showLabels,\n buttonSize,\n shouldShowFollowUp,\n styling,\n isReactionWidget,\n } = useReaction(props.widgetId);\n\n // Local state for follow-up input\n const followUpText = ref('');\n // Hover state for buttons\n const hoveredButton = ref<string | null>(null);\n\n // Get follow-up option\n const getFollowUpOption = computed<ReactionOption | null>(() => {\n if (!showFollowUp.value || !options.value) return null;\n return options.value.find((opt) => opt.value === showFollowUp.value) ?? null;\n });\n\n /**\n * Handle option click\n */\n const handleOptionClick = (option: ReactionOption) => {\n if (props.followUpMode === 'inline' && shouldShowFollowUp(option.value)) {\n setShowFollowUp(option.value);\n } else {\n submitReaction(option.value);\n }\n };\n\n /**\n * Submit reaction\n */\n const submitReaction = async (value: string, followUp?: string) => {\n const trimmedFollowUp = followUp?.trim() || undefined;\n try {\n await react(value, trimmedFollowUp);\n emit('react', value, trimmedFollowUp);\n } catch (err) {\n const reactionError = err instanceof Error ? err : new Error(String(err));\n emit('error', reactionError);\n }\n };\n\n /**\n * Handle follow-up form submit\n */\n const handleFollowUpSubmit = (e: Event) => {\n e.preventDefault();\n if (showFollowUp.value) {\n submitReaction(showFollowUp.value, followUpText.value || undefined);\n followUpText.value = '';\n }\n };\n\n /**\n * Cancel follow-up\n */\n const cancelFollowUp = () => {\n setShowFollowUp(null);\n followUpText.value = '';\n };\n\n return () => {\n // Don't render if not ready, not a reaction widget, or no options\n if (!isReady.value || !isReactionWidget.value || !options.value) {\n return null;\n }\n\n // Hide after submission if prop is set\n if (submitted.value && props.hideAfterSubmit) {\n return null;\n }\n\n // Render thank you message after submission\n if (submitted.value) {\n const currentStyling = styling.value;\n return h(\n 'div',\n {\n class: props.thankYouClass || props.containerClass,\n style: props.thankYouClass ? undefined : {\n ...styles.thankYou,\n color: currentStyling.primaryColor ?? '#059669',\n },\n },\n [\n h('span', props.thankYouMessage || 'Thanks for your feedback!'),\n h(\n 'button',\n {\n type: 'button',\n style: styles.resetButton,\n onClick: clearSubmitted,\n 'aria-label': 'Submit another reaction',\n },\n '↺'\n ),\n ]\n );\n }\n\n // Build reaction buttons using styling from widget config\n const currentSizeStyles = sizeStyles[buttonSize.value] || sizeStyles.md;\n const currentStyling = styling.value;\n const borderRadius = borderRadiusMap[currentStyling.borderRadius ?? 'full'] ?? '9999px';\n const borderWidth = borderWidthMap[currentStyling.borderWidth ?? '1'] ?? '1px';\n\n // Only show buttons when follow-up is not displayed\n const buttonElements = !showFollowUp.value ? options.value.map((option) => {\n const isActive = showFollowUp.value === option.value;\n const isHovered = hoveredButton.value === option.value;\n const children = [\n h('span', { style: { ...styles.icon, ...currentSizeStyles.icon }, 'aria-hidden': 'true' }, option.icon),\n ];\n if (showLabels.value) {\n children.push(h('span', { style: { ...currentSizeStyles.label, color: currentStyling.buttonTextColor ?? '#4b5563' } }, option.label));\n }\n\n return h(\n 'button',\n {\n key: option.value,\n type: 'button',\n class: props.buttonClass,\n style: {\n ...styles.button,\n ...currentSizeStyles.button,\n backgroundColor: currentStyling.backgroundColor ?? '#ffffff',\n borderColor: isActive || isHovered ? (currentStyling.primaryColor ?? '#6366f1') : (currentStyling.borderColor ?? '#e5e7eb'),\n borderWidth: borderWidth,\n borderRadius: borderRadius,\n borderStyle: 'solid',\n color: currentStyling.buttonTextColor ?? '#4b5563',\n ...(isActive || isHovered ? {\n backgroundColor: `${currentStyling.primaryColor ?? '#6366f1'}10`,\n } : {}),\n ...(isSubmitting.value ? styles.buttonDisabled : {}),\n },\n disabled: isSubmitting.value,\n 'aria-pressed': isActive,\n 'aria-label': option.label,\n onClick: () => handleOptionClick(option),\n onMouseenter: () => { hoveredButton.value = option.value; },\n onMouseleave: () => { hoveredButton.value = null; },\n },\n children\n );\n }) : [];\n\n // Build follow-up form if needed\n let followUpForm = null;\n const followUpOption = getFollowUpOption.value;\n if (showFollowUp.value && followUpOption) {\n followUpForm = h(\n 'form',\n {\n class: props.formClass,\n style: props.formClass ? undefined : styles.followUp,\n onSubmit: handleFollowUpSubmit,\n },\n [\n h('textarea', {\n style: styles.input,\n value: followUpText.value,\n placeholder: followUpOption.followUpPlaceholder || 'Tell us more (optional)',\n disabled: isSubmitting.value,\n maxlength: 500,\n rows: 3,\n onInput: (e: Event) => {\n followUpText.value = (e.target as HTMLTextAreaElement).value;\n },\n }),\n h('div', { style: { ...styles.actions, justifyContent: 'center' } }, [\n h(\n 'button',\n {\n type: 'submit',\n style: {\n ...styles.submitButton,\n backgroundColor: currentStyling.primaryColor ?? '#6366f1',\n borderRadius: borderRadius,\n ...(isSubmitting.value ? styles.buttonDisabled : {}),\n },\n disabled: isSubmitting.value,\n },\n isSubmitting.value ? 'Sending...' : 'Send'\n ),\n h(\n 'button',\n {\n type: 'button',\n style: {\n ...styles.cancelButton,\n backgroundColor: currentStyling.backgroundColor ?? '#ffffff',\n color: currentStyling.buttonTextColor ?? '#6b7280',\n borderRadius: borderRadius,\n border: `${borderWidth} solid ${currentStyling.borderColor ?? '#e5e7eb'}`,\n },\n disabled: isSubmitting.value,\n onClick: cancelFollowUp,\n },\n 'Cancel'\n ),\n ]),\n ]\n );\n }\n\n // Build error message\n let errorElement = null;\n if (error.value) {\n errorElement = h(\n 'div',\n { style: styles.error, role: 'alert' },\n error.value.message\n );\n }\n\n // Return full component\n return h(\n 'div',\n {\n class: props.containerClass,\n style: styles.container,\n role: 'group',\n 'aria-label': 'Reaction buttons',\n },\n [\n // Only render button group if there are buttons to show\n buttonElements.length > 0\n ? h('div', { style: styles.buttonGroup, role: 'radiogroup' }, buttonElements)\n : null,\n followUpForm,\n errorElement,\n ].filter(Boolean)\n );\n };\n },\n});\n\nexport default ReactionButtons;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@feedvalue/vue",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "FeedValue Vue 3 SDK - Plugin and Composables for Vue 3+",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"vue": ">=3.3.0"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@feedvalue/core": "^0.1.
|
|
30
|
+
"@feedvalue/core": "^0.1.14"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@vitejs/plugin-vue": "^6.0.3",
|