@feedvalue/vue 0.1.7 → 0.1.8
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 +75 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +75 -13
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -179,6 +179,34 @@ function useReaction(widgetId) {
|
|
|
179
179
|
const template = vue.computed(() => {
|
|
180
180
|
return reactionConfig.value?.template;
|
|
181
181
|
});
|
|
182
|
+
const styling = vue.computed(() => {
|
|
183
|
+
const defaultStyling = {
|
|
184
|
+
primaryColor: "#6366f1",
|
|
185
|
+
backgroundColor: "#ffffff",
|
|
186
|
+
textColor: "#111827",
|
|
187
|
+
buttonTextColor: "#4b5563",
|
|
188
|
+
borderColor: "#e5e7eb",
|
|
189
|
+
borderWidth: "1",
|
|
190
|
+
borderRadius: "full"
|
|
191
|
+
};
|
|
192
|
+
if (!instance.value || !isReady.value) {
|
|
193
|
+
return defaultStyling;
|
|
194
|
+
}
|
|
195
|
+
const widgetConfig = instance.value._widgetConfig;
|
|
196
|
+
if (!widgetConfig?.styling) {
|
|
197
|
+
return defaultStyling;
|
|
198
|
+
}
|
|
199
|
+
const widgetStyling = widgetConfig.styling;
|
|
200
|
+
return {
|
|
201
|
+
primaryColor: widgetStyling.primaryColor ?? defaultStyling.primaryColor,
|
|
202
|
+
backgroundColor: widgetStyling.backgroundColor ?? defaultStyling.backgroundColor,
|
|
203
|
+
textColor: widgetStyling.textColor ?? defaultStyling.textColor,
|
|
204
|
+
buttonTextColor: widgetStyling.buttonTextColor ?? defaultStyling.buttonTextColor,
|
|
205
|
+
borderColor: widgetStyling.borderColor ?? defaultStyling.borderColor,
|
|
206
|
+
borderWidth: widgetStyling.borderWidth ?? defaultStyling.borderWidth,
|
|
207
|
+
borderRadius: widgetStyling.borderRadius ?? defaultStyling.borderRadius
|
|
208
|
+
};
|
|
209
|
+
});
|
|
182
210
|
const shouldShowFollowUp = (optionValue) => {
|
|
183
211
|
if (followUpTrigger.value === "none") return false;
|
|
184
212
|
if (followUpTrigger.value === "all") return true;
|
|
@@ -227,9 +255,24 @@ function useReaction(widgetId) {
|
|
|
227
255
|
showLabels,
|
|
228
256
|
buttonSize,
|
|
229
257
|
followUpTrigger,
|
|
230
|
-
shouldShowFollowUp
|
|
258
|
+
shouldShowFollowUp,
|
|
259
|
+
styling
|
|
231
260
|
};
|
|
232
261
|
}
|
|
262
|
+
var borderRadiusMap = {
|
|
263
|
+
full: "9999px",
|
|
264
|
+
lg: "12px",
|
|
265
|
+
md: "8px",
|
|
266
|
+
sm: "4px",
|
|
267
|
+
none: "0px"
|
|
268
|
+
};
|
|
269
|
+
var borderWidthMap = {
|
|
270
|
+
"0": "0px",
|
|
271
|
+
"1": "1px",
|
|
272
|
+
"2": "2px",
|
|
273
|
+
"3": "3px",
|
|
274
|
+
"4": "4px"
|
|
275
|
+
};
|
|
233
276
|
var sizeStyles = {
|
|
234
277
|
sm: {
|
|
235
278
|
button: { padding: "0.375rem 0.75rem", fontSize: "0.75rem", gap: "0.375rem" },
|
|
@@ -270,11 +313,6 @@ var styles = {
|
|
|
270
313
|
cursor: "pointer",
|
|
271
314
|
transition: "background-color 0.15s, border-color 0.15s, transform 0.1s"
|
|
272
315
|
},
|
|
273
|
-
buttonActive: {
|
|
274
|
-
backgroundColor: "#eef2ff",
|
|
275
|
-
borderColor: "#6366f1",
|
|
276
|
-
color: "#4f46e5"
|
|
277
|
-
},
|
|
278
316
|
buttonDisabled: {
|
|
279
317
|
opacity: 0.7,
|
|
280
318
|
cursor: "not-allowed"
|
|
@@ -390,7 +428,8 @@ var ReactionButtons = vue.defineComponent({
|
|
|
390
428
|
isReady,
|
|
391
429
|
showLabels,
|
|
392
430
|
buttonSize,
|
|
393
|
-
shouldShowFollowUp
|
|
431
|
+
shouldShowFollowUp,
|
|
432
|
+
styling
|
|
394
433
|
} = useReaction(props.widgetId);
|
|
395
434
|
const followUpText = vue.ref("");
|
|
396
435
|
const getFollowUpOption = vue.computed(() => {
|
|
@@ -427,11 +466,15 @@ var ReactionButtons = vue.defineComponent({
|
|
|
427
466
|
return null;
|
|
428
467
|
}
|
|
429
468
|
if (submitted.value) {
|
|
469
|
+
const currentStyling2 = styling.value;
|
|
430
470
|
return vue.h(
|
|
431
471
|
"div",
|
|
432
472
|
{
|
|
433
473
|
class: props.containerClass,
|
|
434
|
-
style:
|
|
474
|
+
style: {
|
|
475
|
+
...styles.thankYou,
|
|
476
|
+
color: currentStyling2.primaryColor ?? "#059669"
|
|
477
|
+
}
|
|
435
478
|
},
|
|
436
479
|
[
|
|
437
480
|
vue.h("span", props.thankYouMessage || "Thanks for your feedback!"),
|
|
@@ -449,12 +492,16 @@ var ReactionButtons = vue.defineComponent({
|
|
|
449
492
|
);
|
|
450
493
|
}
|
|
451
494
|
const currentSizeStyles = sizeStyles[buttonSize.value] || sizeStyles.md;
|
|
495
|
+
const currentStyling = styling.value;
|
|
496
|
+
const borderRadius = borderRadiusMap[currentStyling.borderRadius ?? "full"] ?? "9999px";
|
|
497
|
+
const borderWidth = borderWidthMap[currentStyling.borderWidth ?? "1"] ?? "1px";
|
|
452
498
|
const buttonElements = options.value.map((option) => {
|
|
499
|
+
const isActive = showFollowUp.value === option.value;
|
|
453
500
|
const children = [
|
|
454
501
|
vue.h("span", { style: { ...styles.icon, ...currentSizeStyles.icon }, "aria-hidden": "true" }, option.icon)
|
|
455
502
|
];
|
|
456
503
|
if (showLabels.value) {
|
|
457
|
-
children.push(vue.h("span", { style: currentSizeStyles.label }, option.label));
|
|
504
|
+
children.push(vue.h("span", { style: { ...currentSizeStyles.label, color: currentStyling.buttonTextColor ?? "#4b5563" } }, option.label));
|
|
458
505
|
}
|
|
459
506
|
return vue.h(
|
|
460
507
|
"button",
|
|
@@ -465,11 +512,18 @@ var ReactionButtons = vue.defineComponent({
|
|
|
465
512
|
style: {
|
|
466
513
|
...styles.button,
|
|
467
514
|
...currentSizeStyles.button,
|
|
468
|
-
|
|
515
|
+
backgroundColor: currentStyling.backgroundColor ?? "#ffffff",
|
|
516
|
+
borderColor: isActive ? currentStyling.primaryColor ?? "#6366f1" : currentStyling.borderColor ?? "#e5e7eb",
|
|
517
|
+
borderWidth,
|
|
518
|
+
borderRadius,
|
|
519
|
+
color: currentStyling.buttonTextColor ?? "#4b5563",
|
|
520
|
+
...isActive ? {
|
|
521
|
+
backgroundColor: `${currentStyling.primaryColor ?? "#6366f1"}10`
|
|
522
|
+
} : {},
|
|
469
523
|
...isSubmitting.value ? styles.buttonDisabled : {}
|
|
470
524
|
},
|
|
471
525
|
disabled: isSubmitting.value,
|
|
472
|
-
"aria-pressed":
|
|
526
|
+
"aria-pressed": isActive,
|
|
473
527
|
"aria-label": option.label,
|
|
474
528
|
onClick: () => handleOptionClick(option)
|
|
475
529
|
},
|
|
@@ -497,13 +551,15 @@ var ReactionButtons = vue.defineComponent({
|
|
|
497
551
|
followUpText.value = e.target.value;
|
|
498
552
|
}
|
|
499
553
|
}),
|
|
500
|
-
vue.h("div", { style: styles.actions }, [
|
|
554
|
+
vue.h("div", { style: { ...styles.actions, justifyContent: "center" } }, [
|
|
501
555
|
vue.h(
|
|
502
556
|
"button",
|
|
503
557
|
{
|
|
504
558
|
type: "submit",
|
|
505
559
|
style: {
|
|
506
560
|
...styles.submitButton,
|
|
561
|
+
backgroundColor: currentStyling.primaryColor ?? "#6366f1",
|
|
562
|
+
borderRadius,
|
|
507
563
|
...isSubmitting.value ? styles.buttonDisabled : {}
|
|
508
564
|
},
|
|
509
565
|
disabled: isSubmitting.value
|
|
@@ -514,7 +570,13 @@ var ReactionButtons = vue.defineComponent({
|
|
|
514
570
|
"button",
|
|
515
571
|
{
|
|
516
572
|
type: "button",
|
|
517
|
-
style:
|
|
573
|
+
style: {
|
|
574
|
+
...styles.cancelButton,
|
|
575
|
+
backgroundColor: currentStyling.backgroundColor ?? "#ffffff",
|
|
576
|
+
color: currentStyling.buttonTextColor ?? "#6b7280",
|
|
577
|
+
borderRadius,
|
|
578
|
+
border: `${borderWidth} solid ${currentStyling.borderColor ?? "#e5e7eb"}`
|
|
579
|
+
},
|
|
518
580
|
disabled: isSubmitting.value,
|
|
519
581
|
onClick: cancelFollowUp
|
|
520
582
|
},
|
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","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} 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}\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 /**\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 };\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 } from '@feedvalue/core';\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 } = 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 return h(\n 'div',\n {\n class: props.containerClass,\n style: styles.thankYou,\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\n const currentSizeStyles = sizeStyles[buttonSize.value] || sizeStyles.md;\n const buttonElements = options.value.map((option) => {\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 }, 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 ...(showFollowUp.value === option.value ? styles.buttonActive : {}),\n ...(isSubmitting.value ? styles.buttonDisabled : {}),\n },\n disabled: isSubmitting.value,\n 'aria-pressed': showFollowUp.value === option.value,\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 }, [\n h(\n 'button',\n {\n type: 'submit',\n style: {\n ...styles.submitButton,\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: styles.cancelButton,\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 // 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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
2
|
import { InjectionKey, App, ShallowRef, Ref, ComputedRef, PropType } from 'vue';
|
|
3
|
-
import { FeedValueInstance, FeedValueConfig, FeedbackData, UserTraits, ReactionOption, ButtonSize, FollowUpTrigger } from '@feedvalue/core';
|
|
3
|
+
import { FeedValueInstance, FeedValueConfig, FeedbackData, UserTraits, ReactionOption, ButtonSize, FollowUpTrigger, ReactionStyling } from '@feedvalue/core';
|
|
4
4
|
export { FeedValueConfig, FeedValueEvents, FeedValueState, FeedbackData, FeedbackMetadata, ReactionConfig, ReactionOption, ReactionState, ReactionTemplate, UserData, UserTraits } from '@feedvalue/core';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -179,6 +179,8 @@ interface UseReactionReturn {
|
|
|
179
179
|
followUpTrigger: ComputedRef<FollowUpTrigger>;
|
|
180
180
|
/** Check if an option should show follow-up based on followUpTrigger */
|
|
181
181
|
shouldShowFollowUp: (optionValue: string) => boolean;
|
|
182
|
+
/** Widget styling configuration */
|
|
183
|
+
styling: ComputedRef<ReactionStyling>;
|
|
182
184
|
}
|
|
183
185
|
/**
|
|
184
186
|
* Composable for reaction widgets
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
2
|
import { InjectionKey, App, ShallowRef, Ref, ComputedRef, PropType } from 'vue';
|
|
3
|
-
import { FeedValueInstance, FeedValueConfig, FeedbackData, UserTraits, ReactionOption, ButtonSize, FollowUpTrigger } from '@feedvalue/core';
|
|
3
|
+
import { FeedValueInstance, FeedValueConfig, FeedbackData, UserTraits, ReactionOption, ButtonSize, FollowUpTrigger, ReactionStyling } from '@feedvalue/core';
|
|
4
4
|
export { FeedValueConfig, FeedValueEvents, FeedValueState, FeedbackData, FeedbackMetadata, ReactionConfig, ReactionOption, ReactionState, ReactionTemplate, UserData, UserTraits } from '@feedvalue/core';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -179,6 +179,8 @@ interface UseReactionReturn {
|
|
|
179
179
|
followUpTrigger: ComputedRef<FollowUpTrigger>;
|
|
180
180
|
/** Check if an option should show follow-up based on followUpTrigger */
|
|
181
181
|
shouldShowFollowUp: (optionValue: string) => boolean;
|
|
182
|
+
/** Widget styling configuration */
|
|
183
|
+
styling: ComputedRef<ReactionStyling>;
|
|
182
184
|
}
|
|
183
185
|
/**
|
|
184
186
|
* Composable for reaction widgets
|
package/dist/index.js
CHANGED
|
@@ -177,6 +177,34 @@ function useReaction(widgetId) {
|
|
|
177
177
|
const template = computed(() => {
|
|
178
178
|
return reactionConfig.value?.template;
|
|
179
179
|
});
|
|
180
|
+
const styling = computed(() => {
|
|
181
|
+
const defaultStyling = {
|
|
182
|
+
primaryColor: "#6366f1",
|
|
183
|
+
backgroundColor: "#ffffff",
|
|
184
|
+
textColor: "#111827",
|
|
185
|
+
buttonTextColor: "#4b5563",
|
|
186
|
+
borderColor: "#e5e7eb",
|
|
187
|
+
borderWidth: "1",
|
|
188
|
+
borderRadius: "full"
|
|
189
|
+
};
|
|
190
|
+
if (!instance.value || !isReady.value) {
|
|
191
|
+
return defaultStyling;
|
|
192
|
+
}
|
|
193
|
+
const widgetConfig = instance.value._widgetConfig;
|
|
194
|
+
if (!widgetConfig?.styling) {
|
|
195
|
+
return defaultStyling;
|
|
196
|
+
}
|
|
197
|
+
const widgetStyling = widgetConfig.styling;
|
|
198
|
+
return {
|
|
199
|
+
primaryColor: widgetStyling.primaryColor ?? defaultStyling.primaryColor,
|
|
200
|
+
backgroundColor: widgetStyling.backgroundColor ?? defaultStyling.backgroundColor,
|
|
201
|
+
textColor: widgetStyling.textColor ?? defaultStyling.textColor,
|
|
202
|
+
buttonTextColor: widgetStyling.buttonTextColor ?? defaultStyling.buttonTextColor,
|
|
203
|
+
borderColor: widgetStyling.borderColor ?? defaultStyling.borderColor,
|
|
204
|
+
borderWidth: widgetStyling.borderWidth ?? defaultStyling.borderWidth,
|
|
205
|
+
borderRadius: widgetStyling.borderRadius ?? defaultStyling.borderRadius
|
|
206
|
+
};
|
|
207
|
+
});
|
|
180
208
|
const shouldShowFollowUp = (optionValue) => {
|
|
181
209
|
if (followUpTrigger.value === "none") return false;
|
|
182
210
|
if (followUpTrigger.value === "all") return true;
|
|
@@ -225,9 +253,24 @@ function useReaction(widgetId) {
|
|
|
225
253
|
showLabels,
|
|
226
254
|
buttonSize,
|
|
227
255
|
followUpTrigger,
|
|
228
|
-
shouldShowFollowUp
|
|
256
|
+
shouldShowFollowUp,
|
|
257
|
+
styling
|
|
229
258
|
};
|
|
230
259
|
}
|
|
260
|
+
var borderRadiusMap = {
|
|
261
|
+
full: "9999px",
|
|
262
|
+
lg: "12px",
|
|
263
|
+
md: "8px",
|
|
264
|
+
sm: "4px",
|
|
265
|
+
none: "0px"
|
|
266
|
+
};
|
|
267
|
+
var borderWidthMap = {
|
|
268
|
+
"0": "0px",
|
|
269
|
+
"1": "1px",
|
|
270
|
+
"2": "2px",
|
|
271
|
+
"3": "3px",
|
|
272
|
+
"4": "4px"
|
|
273
|
+
};
|
|
231
274
|
var sizeStyles = {
|
|
232
275
|
sm: {
|
|
233
276
|
button: { padding: "0.375rem 0.75rem", fontSize: "0.75rem", gap: "0.375rem" },
|
|
@@ -268,11 +311,6 @@ var styles = {
|
|
|
268
311
|
cursor: "pointer",
|
|
269
312
|
transition: "background-color 0.15s, border-color 0.15s, transform 0.1s"
|
|
270
313
|
},
|
|
271
|
-
buttonActive: {
|
|
272
|
-
backgroundColor: "#eef2ff",
|
|
273
|
-
borderColor: "#6366f1",
|
|
274
|
-
color: "#4f46e5"
|
|
275
|
-
},
|
|
276
314
|
buttonDisabled: {
|
|
277
315
|
opacity: 0.7,
|
|
278
316
|
cursor: "not-allowed"
|
|
@@ -388,7 +426,8 @@ var ReactionButtons = defineComponent({
|
|
|
388
426
|
isReady,
|
|
389
427
|
showLabels,
|
|
390
428
|
buttonSize,
|
|
391
|
-
shouldShowFollowUp
|
|
429
|
+
shouldShowFollowUp,
|
|
430
|
+
styling
|
|
392
431
|
} = useReaction(props.widgetId);
|
|
393
432
|
const followUpText = ref("");
|
|
394
433
|
const getFollowUpOption = computed(() => {
|
|
@@ -425,11 +464,15 @@ var ReactionButtons = defineComponent({
|
|
|
425
464
|
return null;
|
|
426
465
|
}
|
|
427
466
|
if (submitted.value) {
|
|
467
|
+
const currentStyling2 = styling.value;
|
|
428
468
|
return h(
|
|
429
469
|
"div",
|
|
430
470
|
{
|
|
431
471
|
class: props.containerClass,
|
|
432
|
-
style:
|
|
472
|
+
style: {
|
|
473
|
+
...styles.thankYou,
|
|
474
|
+
color: currentStyling2.primaryColor ?? "#059669"
|
|
475
|
+
}
|
|
433
476
|
},
|
|
434
477
|
[
|
|
435
478
|
h("span", props.thankYouMessage || "Thanks for your feedback!"),
|
|
@@ -447,12 +490,16 @@ var ReactionButtons = defineComponent({
|
|
|
447
490
|
);
|
|
448
491
|
}
|
|
449
492
|
const currentSizeStyles = sizeStyles[buttonSize.value] || sizeStyles.md;
|
|
493
|
+
const currentStyling = styling.value;
|
|
494
|
+
const borderRadius = borderRadiusMap[currentStyling.borderRadius ?? "full"] ?? "9999px";
|
|
495
|
+
const borderWidth = borderWidthMap[currentStyling.borderWidth ?? "1"] ?? "1px";
|
|
450
496
|
const buttonElements = options.value.map((option) => {
|
|
497
|
+
const isActive = showFollowUp.value === option.value;
|
|
451
498
|
const children = [
|
|
452
499
|
h("span", { style: { ...styles.icon, ...currentSizeStyles.icon }, "aria-hidden": "true" }, option.icon)
|
|
453
500
|
];
|
|
454
501
|
if (showLabels.value) {
|
|
455
|
-
children.push(h("span", { style: currentSizeStyles.label }, option.label));
|
|
502
|
+
children.push(h("span", { style: { ...currentSizeStyles.label, color: currentStyling.buttonTextColor ?? "#4b5563" } }, option.label));
|
|
456
503
|
}
|
|
457
504
|
return h(
|
|
458
505
|
"button",
|
|
@@ -463,11 +510,18 @@ var ReactionButtons = defineComponent({
|
|
|
463
510
|
style: {
|
|
464
511
|
...styles.button,
|
|
465
512
|
...currentSizeStyles.button,
|
|
466
|
-
|
|
513
|
+
backgroundColor: currentStyling.backgroundColor ?? "#ffffff",
|
|
514
|
+
borderColor: isActive ? currentStyling.primaryColor ?? "#6366f1" : currentStyling.borderColor ?? "#e5e7eb",
|
|
515
|
+
borderWidth,
|
|
516
|
+
borderRadius,
|
|
517
|
+
color: currentStyling.buttonTextColor ?? "#4b5563",
|
|
518
|
+
...isActive ? {
|
|
519
|
+
backgroundColor: `${currentStyling.primaryColor ?? "#6366f1"}10`
|
|
520
|
+
} : {},
|
|
467
521
|
...isSubmitting.value ? styles.buttonDisabled : {}
|
|
468
522
|
},
|
|
469
523
|
disabled: isSubmitting.value,
|
|
470
|
-
"aria-pressed":
|
|
524
|
+
"aria-pressed": isActive,
|
|
471
525
|
"aria-label": option.label,
|
|
472
526
|
onClick: () => handleOptionClick(option)
|
|
473
527
|
},
|
|
@@ -495,13 +549,15 @@ var ReactionButtons = defineComponent({
|
|
|
495
549
|
followUpText.value = e.target.value;
|
|
496
550
|
}
|
|
497
551
|
}),
|
|
498
|
-
h("div", { style: styles.actions }, [
|
|
552
|
+
h("div", { style: { ...styles.actions, justifyContent: "center" } }, [
|
|
499
553
|
h(
|
|
500
554
|
"button",
|
|
501
555
|
{
|
|
502
556
|
type: "submit",
|
|
503
557
|
style: {
|
|
504
558
|
...styles.submitButton,
|
|
559
|
+
backgroundColor: currentStyling.primaryColor ?? "#6366f1",
|
|
560
|
+
borderRadius,
|
|
505
561
|
...isSubmitting.value ? styles.buttonDisabled : {}
|
|
506
562
|
},
|
|
507
563
|
disabled: isSubmitting.value
|
|
@@ -512,7 +568,13 @@ var ReactionButtons = defineComponent({
|
|
|
512
568
|
"button",
|
|
513
569
|
{
|
|
514
570
|
type: "button",
|
|
515
|
-
style:
|
|
571
|
+
style: {
|
|
572
|
+
...styles.cancelButton,
|
|
573
|
+
backgroundColor: currentStyling.backgroundColor ?? "#ffffff",
|
|
574
|
+
color: currentStyling.buttonTextColor ?? "#6b7280",
|
|
575
|
+
borderRadius,
|
|
576
|
+
border: `${borderWidth} solid ${currentStyling.borderColor ?? "#e5e7eb"}`
|
|
577
|
+
},
|
|
516
578
|
disabled: isSubmitting.value,
|
|
517
579
|
onClick: cancelFollowUp
|
|
518
580
|
},
|
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"],"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} 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}\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 /**\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 };\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 } from '@feedvalue/core';\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 } = 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 return h(\n 'div',\n {\n class: props.containerClass,\n style: styles.thankYou,\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\n const currentSizeStyles = sizeStyles[buttonSize.value] || sizeStyles.md;\n const buttonElements = options.value.map((option) => {\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 }, 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 ...(showFollowUp.value === option.value ? styles.buttonActive : {}),\n ...(isSubmitting.value ? styles.buttonDisabled : {}),\n },\n disabled: isSubmitting.value,\n 'aria-pressed': showFollowUp.value === option.value,\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 }, [\n h(\n 'button',\n {\n type: 'submit',\n style: {\n ...styles.submitButton,\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: styles.cancelButton,\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 // 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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@feedvalue/vue",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
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.11"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@vitejs/plugin-vue": "^6.0.3",
|