@appgram/react 0.1.0
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/LICENSE +21 -0
- package/dist/chunk-3UBJGXCO.js +6368 -0
- package/dist/chunk-3UBJGXCO.js.map +1 -0
- package/dist/chunk-75P634IK.js +758 -0
- package/dist/chunk-75P634IK.js.map +1 -0
- package/dist/chunk-AIDLOCVJ.mjs +6341 -0
- package/dist/chunk-AIDLOCVJ.mjs.map +1 -0
- package/dist/chunk-KPIKYXAN.mjs +47 -0
- package/dist/chunk-KPIKYXAN.mjs.map +1 -0
- package/dist/chunk-N6PJDQCU.mjs +741 -0
- package/dist/chunk-N6PJDQCU.mjs.map +1 -0
- package/dist/chunk-ZJZ3A2S3.js +49 -0
- package/dist/chunk-ZJZ3A2S3.js.map +1 -0
- package/dist/components/index.d.mts +1283 -0
- package/dist/components/index.d.ts +1283 -0
- package/dist/components/index.js +85 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +4 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/hooks/index.d.mts +572 -0
- package/dist/hooks/index.d.ts +572 -0
- package/dist/hooks/index.js +53 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/index.mjs +4 -0
- package/dist/hooks/index.mjs.map +1 -0
- package/dist/index.d.mts +399 -0
- package/dist/index.d.ts +399 -0
- package/dist/index.js +783 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +645 -0
- package/dist/index.mjs.map +1 -0
- package/dist/useVote-CLhkwtLT.d.mts +420 -0
- package/dist/useVote-CLhkwtLT.d.ts +420 -0
- package/package.json +82 -0
- package/tailwind-preset.js +48 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client/AppgramClient.ts","../src/provider/AppgramProvider.tsx"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * AppgramClient\n *\n * API client for Appgram portal/public endpoints.\n * Adapted from the main app's api.ts for use in the SDK.\n */\n\nimport type {\n ApiResponse,\n Wish,\n WishFilters,\n WishesResponse,\n VoteCheckResponse,\n Comment,\n CommentsResponse,\n RoadmapData,\n Release,\n ReleaseFeature,\n HelpCollection,\n HelpFlow,\n HelpArticle,\n SupportRequest,\n SupportRequestInput,\n} from '../types'\n\nexport interface AppgramClientConfig {\n baseUrl: string\n projectId: string\n orgSlug?: string\n projectSlug?: string\n}\n\nexport class AppgramClient {\n private baseUrl: string\n private projectId: string\n private orgSlug?: string\n private projectSlug?: string\n\n constructor(config: AppgramClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/$/, '') // Remove trailing slash\n this.projectId = config.projectId\n this.orgSlug = config.orgSlug\n this.projectSlug = config.projectSlug\n }\n\n // ============================================================================\n // HTTP Methods\n // ============================================================================\n\n private async request<T>(\n method: string,\n endpoint: string,\n options?: {\n params?: Record<string, string>\n body?: unknown\n }\n ): Promise<ApiResponse<T>> {\n let url = `${this.baseUrl}${endpoint}`\n\n if (options?.params) {\n const searchParams = new URLSearchParams()\n Object.entries(options.params).forEach(([key, value]) => {\n if (value !== undefined && value !== null && value !== '') {\n searchParams.append(key, value)\n }\n })\n const queryString = searchParams.toString()\n if (queryString) {\n url += `?${queryString}`\n }\n }\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n },\n body: options?.body ? JSON.stringify(options.body) : undefined,\n })\n\n const data = await response.json()\n\n if (!response.ok) {\n return {\n success: false,\n error: {\n code: String(response.status),\n message: data.message || data.error || 'An error occurred',\n },\n }\n }\n\n // Handle both wrapped response format { success, data } and direct data format\n if (data && typeof data === 'object' && 'success' in data) {\n return data\n }\n\n return {\n success: true,\n data: data as T,\n }\n } catch (error) {\n return {\n success: false,\n error: {\n code: 'NETWORK_ERROR',\n message: error instanceof Error ? error.message : 'Network error',\n },\n }\n }\n }\n\n private get<T>(endpoint: string, params?: Record<string, string>): Promise<ApiResponse<T>> {\n return this.request<T>('GET', endpoint, { params })\n }\n\n /**\n * Raw request that returns the API response as-is without transformation\n */\n private async requestRaw<T>(\n endpoint: string,\n params?: Record<string, string>\n ): Promise<T & { success: boolean; error?: { code: string; message: string } }> {\n let url = `${this.baseUrl}${endpoint}`\n\n if (params) {\n const searchParams = new URLSearchParams()\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null && value !== '') {\n searchParams.append(key, value)\n }\n })\n const queryString = searchParams.toString()\n if (queryString) {\n url += `?${queryString}`\n }\n }\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n })\n\n const data = await response.json()\n\n if (!response.ok) {\n return {\n success: false,\n error: {\n code: String(response.status),\n message: data.message || data.error || 'An error occurred',\n },\n } as T & { success: boolean; error?: { code: string; message: string } }\n }\n\n return data\n } catch (error) {\n return {\n success: false,\n error: {\n code: 'NETWORK_ERROR',\n message: error instanceof Error ? error.message : 'Network error',\n },\n } as T & { success: boolean; error?: { code: string; message: string } }\n }\n }\n\n private post<T>(endpoint: string, body?: unknown): Promise<ApiResponse<T>> {\n return this.request<T>('POST', endpoint, { body })\n }\n\n private delete<T>(endpoint: string): Promise<ApiResponse<T>> {\n return this.request<T>('DELETE', endpoint)\n }\n\n // ============================================================================\n // Wishes\n // ============================================================================\n\n /**\n * Get public wishes for the project\n */\n async getPublicWishes(filters?: WishFilters): Promise<ApiResponse<WishesResponse>> {\n const params: Record<string, string> = {\n project_id: this.projectId,\n }\n\n if (filters?.status) {\n params.status = Array.isArray(filters.status) ? filters.status.join(',') : filters.status\n }\n if (filters?.category_id) params.category_id = filters.category_id\n if (filters?.search) params.search = filters.search\n if (filters?.sort_by) params.sort_by = filters.sort_by\n if (filters?.sort_order) params.sort_order = filters.sort_order\n if (filters?.page) params.page = String(filters.page)\n if (filters?.per_page) params.per_page = String(filters.per_page)\n if (filters?.fingerprint) params.fingerprint = filters.fingerprint\n\n // The API returns { success, data: [...wishes], total, page, per_page, total_pages }\n // We need to transform this to { success, data: { data: [...wishes], total, ... } }\n const rawResponse = await this.requestRaw<{\n success: boolean\n data: Wish[]\n total: number\n page: number\n per_page: number\n total_pages: number\n error?: { code: string; message: string }\n }>('/portal/wishes', params)\n\n if (!rawResponse.success) {\n return {\n success: false,\n error: rawResponse.error,\n }\n }\n\n return {\n success: true,\n data: {\n data: rawResponse.data || [],\n total: rawResponse.total || 0,\n page: rawResponse.page || 1,\n per_page: rawResponse.per_page || 20,\n total_pages: rawResponse.total_pages || 0,\n },\n }\n }\n\n /**\n * Get a single wish by ID\n */\n async getWish(wishId: string): Promise<ApiResponse<Wish>> {\n return this.get<Wish>(`/portal/wishes/${wishId}`, {\n project_id: this.projectId,\n })\n }\n\n /**\n * Create a new wish (feature request)\n */\n async createWish(data: {\n title: string\n description: string\n author_email?: string\n author_name?: string\n category_id?: string\n }): Promise<ApiResponse<Wish>> {\n return this.post<Wish>('/portal/wishes', {\n project_id: this.projectId,\n ...data,\n })\n }\n\n // ============================================================================\n // Votes\n // ============================================================================\n\n /**\n * Check if a fingerprint has voted on a wish\n */\n async checkVote(wishId: string, fingerprint: string): Promise<ApiResponse<VoteCheckResponse>> {\n return this.get<VoteCheckResponse>(`/api/v1/votes/check/${wishId}`, {\n fingerprint,\n })\n }\n\n /**\n * Create a vote\n */\n async createVote(wishId: string, fingerprint: string, voterEmail?: string): Promise<ApiResponse<{ id: string; wish_id: string }>> {\n return this.post<{ id: string; wish_id: string }>('/api/v1/votes', {\n wish_id: wishId,\n fingerprint,\n voter_email: voterEmail,\n })\n }\n\n /**\n * Delete a vote\n */\n async deleteVote(voteId: string): Promise<ApiResponse<{ success: boolean }>> {\n return this.delete<{ success: boolean }>(`/api/v1/votes/${voteId}`)\n }\n\n // ============================================================================\n // Comments\n // ============================================================================\n\n /**\n * Get comments for a wish\n */\n async getComments(\n wishId: string,\n options?: { page?: number; per_page?: number }\n ): Promise<ApiResponse<CommentsResponse>> {\n const params: Record<string, string> = {\n wish_id: wishId,\n }\n if (options?.page) params.page = String(options.page)\n if (options?.per_page) params.per_page = String(options.per_page)\n\n // The API returns Comment[] directly, not a paginated response\n // We need to transform it to match the expected CommentsResponse format\n const response = await this.get<Comment[]>('/api/v1/comments', params)\n\n if (!response.success) {\n return {\n success: false,\n error: response.error,\n }\n }\n\n const comments = response.data || []\n return {\n success: true,\n data: {\n data: comments,\n total: comments.length,\n page: options?.page || 1,\n per_page: options?.per_page || 20,\n total_pages: 1,\n },\n }\n }\n\n /**\n * Create a comment\n */\n async createComment(data: {\n wish_id: string\n content: string\n author_name?: string\n author_email?: string\n parent_id?: string\n }): Promise<ApiResponse<Comment>> {\n // Include required fields for anonymous public comments\n return this.post<Comment>('/api/v1/comments', {\n ...data,\n author_type: 'anonymous',\n is_official: false,\n })\n }\n\n // ============================================================================\n // Roadmap\n // ============================================================================\n\n /**\n * Get roadmap data for the project\n */\n async getRoadmapData(): Promise<ApiResponse<RoadmapData>> {\n const params: Record<string, string> = {\n project_id: this.projectId,\n }\n\n if (this.orgSlug && this.projectSlug) {\n params.org_slug = this.orgSlug\n params.project_slug = this.projectSlug\n }\n\n return this.get<RoadmapData>('/portal/roadmap-data', params)\n }\n\n // ============================================================================\n // Releases\n // ============================================================================\n\n /**\n * Get public releases for the project\n */\n async getReleases(options?: { limit?: number }): Promise<ApiResponse<Release[]>> {\n if (!this.orgSlug || !this.projectSlug) {\n return {\n success: false,\n error: {\n code: 'MISSING_SLUGS',\n message: 'orgSlug and projectSlug are required for releases endpoint',\n },\n }\n }\n\n const params: Record<string, string> = {}\n if (options?.limit) params.limit = String(options.limit)\n\n return this.get<Release[]>(\n `/api/v1/releases/public/${this.orgSlug}/${this.projectSlug}`,\n params\n )\n }\n\n /**\n * Get a single release by slug\n */\n async getRelease(releaseSlug: string): Promise<ApiResponse<Release>> {\n if (!this.orgSlug || !this.projectSlug) {\n return {\n success: false,\n error: {\n code: 'MISSING_SLUGS',\n message: 'orgSlug and projectSlug are required for releases endpoint',\n },\n }\n }\n\n return this.get<Release>(\n `/api/v1/releases/public/${this.orgSlug}/${this.projectSlug}/${releaseSlug}`\n )\n }\n\n /**\n * Get features for a release (public endpoint)\n */\n async getReleaseFeatures(releaseSlug: string): Promise<ApiResponse<ReleaseFeature[]>> {\n if (!this.orgSlug || !this.projectSlug) {\n return {\n success: false,\n error: {\n code: 'MISSING_SLUGS',\n message: 'orgSlug and projectSlug are required for release features endpoint',\n },\n }\n }\n\n return this.get<ReleaseFeature[]>(\n `/api/v1/releases/public/${this.orgSlug}/${this.projectSlug}/${releaseSlug}/features`\n )\n }\n\n // ============================================================================\n // Help Center\n // ============================================================================\n\n /**\n * Get help center collection for the project\n */\n async getHelpCollection(): Promise<ApiResponse<{ collection: HelpCollection | null; flows: HelpFlow[] }>> {\n return this.get<{ collection: HelpCollection | null; flows: HelpFlow[] }>('/portal/help', {\n project_id: this.projectId,\n })\n }\n\n /**\n * Get a help flow by slug\n */\n async getHelpFlow(slug: string): Promise<ApiResponse<HelpFlow>> {\n return this.get<HelpFlow>(`/portal/help/flows/${slug}`, {\n project_id: this.projectId,\n })\n }\n\n /**\n * Get a help article by slug\n */\n async getHelpArticle(slug: string, flowId: string): Promise<ApiResponse<HelpArticle>> {\n return this.get<HelpArticle>(`/portal/help/articles/${slug}`, {\n flow_id: flowId,\n })\n }\n\n // ============================================================================\n // Support\n // ============================================================================\n\n /**\n * Upload a file via public portal (no auth required)\n */\n async uploadFile(file: File): Promise<ApiResponse<{\n url: string\n name: string\n size: number\n mime_type?: string\n }>> {\n const url = `${this.baseUrl}/portal/files/upload`\n const formData = new FormData()\n formData.append('file', file)\n formData.append('project_id', this.projectId)\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n body: formData,\n })\n\n const data = await response.json()\n\n if (!response.ok) {\n return {\n success: false,\n error: {\n code: data.error?.code || 'UPLOAD_ERROR',\n message: data.error?.message || data.message || 'File upload failed',\n },\n }\n }\n\n return {\n success: true,\n data: data.data || data,\n }\n } catch (error) {\n return {\n success: false,\n error: {\n code: 'UPLOAD_ERROR',\n message: error instanceof Error ? error.message : 'File upload failed',\n },\n }\n }\n }\n\n /**\n * Submit a support request\n */\n async submitSupportRequest(\n data: SupportRequestInput\n ): Promise<ApiResponse<SupportRequest>> {\n // Upload attachments first if any\n const uploadedAttachments: Array<{ url: string; name: string; size: number; mime_type?: string }> = []\n if (data.attachments && data.attachments.length > 0) {\n for (const file of data.attachments) {\n if (file.size > 10 * 1024 * 1024) {\n return {\n success: false,\n error: {\n code: 'FILE_TOO_LARGE',\n message: `File \"${file.name}\" is too large. Maximum size is 10MB.`,\n },\n }\n }\n const uploadResponse = await this.uploadFile(file)\n if (uploadResponse.success && uploadResponse.data) {\n uploadedAttachments.push({\n url: uploadResponse.data.url,\n name: uploadResponse.data.name,\n size: uploadResponse.data.size,\n mime_type: uploadResponse.data.mime_type,\n })\n } else {\n return {\n success: false,\n error: uploadResponse.error || {\n code: 'UPLOAD_ERROR',\n message: 'Failed to upload attachment',\n },\n }\n }\n }\n }\n\n const payload: Record<string, unknown> = {\n project_id: this.projectId,\n subject: data.subject,\n description: data.description,\n user_email: data.user_email,\n }\n\n if (data.user_name) payload.user_name = data.user_name\n if (data.category) payload.category = data.category\n if (uploadedAttachments.length > 0) payload.attachments = uploadedAttachments\n\n return this.post<SupportRequest>('/portal/support-requests', payload)\n }\n\n /**\n * Request a magic link to access support tickets\n */\n async sendSupportMagicLink(userEmail: string): Promise<ApiResponse<{ success: boolean; message: string }>> {\n return this.post<{ success: boolean; message: string }>('/portal/support-requests/send-magic-link', {\n project_id: this.projectId,\n user_email: userEmail,\n })\n }\n\n /**\n * Verify magic link token and get user's support tickets\n */\n async verifySupportToken(token: string): Promise<ApiResponse<{\n tickets: SupportRequest[]\n user_email: string\n }>> {\n return this.get<{ tickets: SupportRequest[]; user_email: string }>(\n '/portal/support-requests/verify-token',\n {\n token,\n project_id: this.projectId,\n }\n )\n }\n\n /**\n * Get a specific support ticket using magic link token\n */\n async getSupportTicket(\n ticketId: string,\n token: string\n ): Promise<ApiResponse<SupportRequest>> {\n return this.get<SupportRequest>(`/portal/support-requests/${ticketId}`, {\n token,\n })\n }\n\n /**\n * Add a message to a support ticket\n */\n async addSupportMessage(\n ticketId: string,\n token: string,\n content: string\n ): Promise<ApiResponse<{ id: string; content: string; created_at: string }>> {\n const url = `/portal/support-requests/${ticketId}/messages`\n const fullUrl = `${this.baseUrl}${url}`\n\n try {\n const response = await fetch(fullUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`,\n },\n body: JSON.stringify({ content }),\n })\n\n const data = await response.json()\n\n if (!response.ok) {\n return {\n success: false,\n error: {\n code: String(response.status),\n message: data.message || data.error || 'An error occurred',\n },\n }\n }\n\n if (data && typeof data === 'object' && 'success' in data) {\n return data\n }\n\n return {\n success: true,\n data: data as { id: string; content: string; created_at: string },\n }\n } catch (error) {\n return {\n success: false,\n error: {\n code: 'NETWORK_ERROR',\n message: error instanceof Error ? error.message : 'Network error',\n },\n }\n }\n }\n\n // ============================================================================\n // Page Data (Combined)\n // ============================================================================\n\n /**\n * Get all public page data in one request\n */\n async getPageData(): Promise<ApiResponse<{\n project?: unknown\n customization_data?: unknown\n wishes?: Wish[]\n total_wishes?: number\n categories?: unknown[]\n }>> {\n const params: Record<string, string> = {\n project_id: this.projectId,\n }\n\n if (this.orgSlug) params.org_slug = this.orgSlug\n if (this.projectSlug) params.project_slug = this.projectSlug\n\n return this.get('/portal/page-data', params)\n }\n}\n","/**\n * AppgramProvider\n *\n * Root provider component that manages configuration, API client, and theming.\n */\n\nimport React, { useMemo, useEffect, useState } from 'react'\nimport { AppgramContext, type AppgramConfig } from './context'\nimport { AppgramClient } from '../client/AppgramClient'\nimport { getFingerprint } from '../utils/fingerprint'\nimport type { AppgramTheme, CustomColors, ThemeMode } from '../types'\n\nexport interface AppgramProviderProps {\n /**\n * Appgram configuration\n */\n config: AppgramConfig\n\n /**\n * Child components\n */\n children: React.ReactNode\n}\n\nconst DEFAULT_API_URL = 'https://api.appgram.dev'\n\n// Arctic Blue light theme colors\nconst DEFAULT_LIGHT_COLORS: CustomColors = {\n primary: '#0EA5E9', // Arctic blue\n secondary: '#6B7280', // Gray\n accent: '#0EA5E9', // Arctic blue\n background: '#FFFFFF', // White\n text: '#242424', // Near-black\n cardBackground: '#F7F7F7',\n cardText: '#242424',\n}\n\n// Arctic Blue dark theme colors\nconst DEFAULT_DARK_COLORS: CustomColors = {\n primary: '#38BDF8', // Lighter arctic blue\n secondary: '#3A3A3A', // Dark gray (subtle for borders)\n accent: '#38BDF8', // Lighter arctic blue\n background: '#0A0A0A', // Near-black\n text: '#E5E5E5', // Light gray\n cardBackground: '#1A1A1A',\n cardText: '#E5E5E5',\n}\n\nconst DEFAULT_THEME: AppgramTheme = {\n mode: 'system',\n colors: DEFAULT_LIGHT_COLORS,\n darkColors: DEFAULT_DARK_COLORS,\n typography: {\n fontFamily: 'inherit',\n },\n borderRadius: 8,\n}\n\n/**\n * Detect system dark mode preference\n */\nfunction getSystemIsDark(): boolean {\n if (typeof window === 'undefined') return false\n return window.matchMedia('(prefers-color-scheme: dark)').matches\n}\n\n/**\n * Resolve the effective dark mode state based on theme mode setting\n */\nfunction resolveIsDark(mode: ThemeMode): boolean {\n if (mode === 'dark') return true\n if (mode === 'light') return false\n return getSystemIsDark()\n}\n\n/**\n * AppgramProvider - Root provider for Appgram React SDK\n *\n * Supports automatic dark/light theme based on system preference.\n *\n * @example\n * ```tsx\n * <AppgramProvider\n * config={{\n * projectId: 'proj_xxx',\n * orgSlug: 'acme',\n * projectSlug: 'feedback',\n * theme: {\n * mode: 'system', // 'light' | 'dark' | 'system' (default: 'system')\n * colors: { primary: '#0EA5E9' }, // Light mode colors\n * darkColors: { primary: '#38BDF8' }, // Dark mode colors (optional)\n * }\n * }}\n * >\n * <App />\n * </AppgramProvider>\n * ```\n */\nexport function AppgramProvider({\n config,\n children,\n}: AppgramProviderProps): React.ReactElement {\n const [fingerprint, setFingerprint] = useState<string | null>(null)\n const themeMode = config.theme?.mode ?? 'system'\n const [isDark, setIsDark] = useState(() => resolveIsDark(themeMode))\n\n // Initialize fingerprint on mount (client-side only)\n useEffect(() => {\n if (config.enableFingerprinting !== false) {\n setFingerprint(getFingerprint())\n }\n }, [config.enableFingerprinting])\n\n // Listen for system theme changes when mode is 'system'\n useEffect(() => {\n if (themeMode !== 'system' || typeof window === 'undefined') {\n setIsDark(resolveIsDark(themeMode))\n return\n }\n\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')\n setIsDark(mediaQuery.matches)\n\n const handler = (e: MediaQueryListEvent) => setIsDark(e.matches)\n mediaQuery.addEventListener('change', handler)\n return () => mediaQuery.removeEventListener('change', handler)\n }, [themeMode])\n\n // Create API client instance\n const client = useMemo(() => {\n return new AppgramClient({\n baseUrl: config.apiUrl || DEFAULT_API_URL,\n projectId: config.projectId,\n orgSlug: config.orgSlug,\n projectSlug: config.projectSlug,\n })\n }, [config.apiUrl, config.projectId, config.orgSlug, config.projectSlug])\n\n // Get light and dark colors with user overrides\n const lightColors = useMemo(() => ({\n ...DEFAULT_LIGHT_COLORS,\n ...config.theme?.colors,\n }), [config.theme?.colors])\n\n const darkColors = useMemo(() => ({\n ...DEFAULT_DARK_COLORS,\n ...config.theme?.darkColors,\n }), [config.theme?.darkColors])\n\n // Resolve current colors based on dark mode state\n const currentColors = isDark ? darkColors : lightColors\n\n // Merge theme with defaults\n const theme = useMemo<AppgramTheme & { isDark: boolean; currentColors: CustomColors }>(() => {\n return {\n mode: themeMode,\n colors: lightColors,\n darkColors: darkColors,\n typography: {\n ...DEFAULT_THEME.typography,\n ...config.theme?.typography,\n },\n borderRadius: config.theme?.borderRadius ?? DEFAULT_THEME.borderRadius,\n // Include resolved state for components\n isDark,\n currentColors,\n }\n }, [themeMode, lightColors, darkColors, config.theme?.typography, config.theme?.borderRadius, isDark, currentColors])\n\n // Context value\n const contextValue = useMemo(() => ({\n config: {\n ...config,\n apiUrl: config.apiUrl || DEFAULT_API_URL,\n },\n client,\n fingerprint,\n theme,\n }), [config, client, fingerprint, theme])\n\n // Inject CSS custom properties for theming\n useEffect(() => {\n if (typeof document === 'undefined') return\n\n const root = document.documentElement\n const colors = currentColors\n\n // Set dark mode attribute for CSS targeting\n root.setAttribute('data-appgram-theme', isDark ? 'dark' : 'light')\n\n if (colors.primary) root.style.setProperty('--appgram-primary', colors.primary)\n if (colors.secondary) root.style.setProperty('--appgram-secondary', colors.secondary)\n if (colors.accent) root.style.setProperty('--appgram-accent', colors.accent)\n if (colors.background) root.style.setProperty('--appgram-background', colors.background)\n if (colors.text) root.style.setProperty('--appgram-foreground', colors.text)\n if (colors.cardBackground) root.style.setProperty('--appgram-card', colors.cardBackground)\n if (colors.cardText) root.style.setProperty('--appgram-card-foreground', colors.cardText)\n if (theme.borderRadius) root.style.setProperty('--appgram-radius', `${theme.borderRadius}px`)\n if (theme.typography?.fontFamily) root.style.setProperty('--appgram-font-family', theme.typography.fontFamily)\n }, [currentColors, isDark, theme.borderRadius, theme.typography?.fontFamily])\n\n return (\n <AppgramContext.Provider value={contextValue}>\n {children}\n </AppgramContext.Provider>\n )\n}\n"]}
|
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wish (Feature Request) Types
|
|
3
|
+
*/
|
|
4
|
+
type WishStatus = 'pending' | 'under_review' | 'planned' | 'in_progress' | 'completed' | 'declined';
|
|
5
|
+
type WishPriority = 'low' | 'medium' | 'high' | 'critical';
|
|
6
|
+
interface Category {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
slug: string;
|
|
10
|
+
color: string;
|
|
11
|
+
icon?: string | null;
|
|
12
|
+
description?: string | null;
|
|
13
|
+
wish_count?: number;
|
|
14
|
+
}
|
|
15
|
+
interface WishAuthor {
|
|
16
|
+
name: string;
|
|
17
|
+
email?: string | null;
|
|
18
|
+
avatar_url?: string | null;
|
|
19
|
+
}
|
|
20
|
+
interface Wish {
|
|
21
|
+
id: string;
|
|
22
|
+
project_id: string;
|
|
23
|
+
category_id?: string | null;
|
|
24
|
+
title: string;
|
|
25
|
+
description: string;
|
|
26
|
+
status: WishStatus;
|
|
27
|
+
priority?: WishPriority | null;
|
|
28
|
+
author_type: 'user' | 'anonymous' | 'team_member';
|
|
29
|
+
author_email?: string | null;
|
|
30
|
+
author_name?: string | null;
|
|
31
|
+
vote_count: number;
|
|
32
|
+
comment_count: number;
|
|
33
|
+
slug: string;
|
|
34
|
+
is_pinned?: boolean;
|
|
35
|
+
created_at: string;
|
|
36
|
+
updated_at: string;
|
|
37
|
+
completed_at?: string | null;
|
|
38
|
+
category?: Category | null;
|
|
39
|
+
author?: WishAuthor;
|
|
40
|
+
has_voted?: boolean;
|
|
41
|
+
}
|
|
42
|
+
interface WishFilters {
|
|
43
|
+
status?: WishStatus | WishStatus[];
|
|
44
|
+
category_id?: string;
|
|
45
|
+
priority?: WishPriority | WishPriority[];
|
|
46
|
+
search?: string;
|
|
47
|
+
sort_by?: 'votes' | 'created_at' | 'updated_at';
|
|
48
|
+
sort_order?: 'asc' | 'desc';
|
|
49
|
+
page?: number;
|
|
50
|
+
per_page?: number;
|
|
51
|
+
fingerprint?: string;
|
|
52
|
+
}
|
|
53
|
+
interface WishesResponse {
|
|
54
|
+
data: Wish[];
|
|
55
|
+
total: number;
|
|
56
|
+
page: number;
|
|
57
|
+
per_page: number;
|
|
58
|
+
total_pages: number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Comment Types
|
|
63
|
+
*/
|
|
64
|
+
interface CommentAuthor {
|
|
65
|
+
name: string;
|
|
66
|
+
avatar_url?: string | null;
|
|
67
|
+
}
|
|
68
|
+
interface Comment {
|
|
69
|
+
id: string;
|
|
70
|
+
wish_id: string;
|
|
71
|
+
parent_id?: string | null;
|
|
72
|
+
author_type: 'user' | 'team_member' | 'anonymous';
|
|
73
|
+
author_user_id?: string | null;
|
|
74
|
+
author_name: string;
|
|
75
|
+
author_avatar_url?: string | null;
|
|
76
|
+
content: string;
|
|
77
|
+
is_official: boolean;
|
|
78
|
+
is_deleted: boolean;
|
|
79
|
+
reply_count: number;
|
|
80
|
+
created_at: string;
|
|
81
|
+
updated_at: string;
|
|
82
|
+
replies?: Comment[];
|
|
83
|
+
}
|
|
84
|
+
interface CommentCreateInput {
|
|
85
|
+
wish_id: string;
|
|
86
|
+
content: string;
|
|
87
|
+
author_name?: string;
|
|
88
|
+
author_email?: string;
|
|
89
|
+
parent_id?: string;
|
|
90
|
+
}
|
|
91
|
+
interface CommentsResponse {
|
|
92
|
+
data: Comment[];
|
|
93
|
+
total: number;
|
|
94
|
+
page: number;
|
|
95
|
+
per_page: number;
|
|
96
|
+
total_pages: number;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Roadmap Types
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
type RoadmapVisibility = 'public' | 'private' | 'voters_only';
|
|
104
|
+
interface Roadmap {
|
|
105
|
+
id: string;
|
|
106
|
+
project_id: string;
|
|
107
|
+
name: string;
|
|
108
|
+
description?: string | null;
|
|
109
|
+
visibility: RoadmapVisibility;
|
|
110
|
+
show_vote_counts: boolean;
|
|
111
|
+
show_comments: boolean;
|
|
112
|
+
is_default: boolean;
|
|
113
|
+
created_at: string;
|
|
114
|
+
updated_at: string;
|
|
115
|
+
columns?: RoadmapColumn[];
|
|
116
|
+
}
|
|
117
|
+
interface RoadmapColumn {
|
|
118
|
+
id: string;
|
|
119
|
+
roadmap_id: string;
|
|
120
|
+
name: string;
|
|
121
|
+
color: string;
|
|
122
|
+
sort_order: number;
|
|
123
|
+
wip_limit?: number | null;
|
|
124
|
+
created_at: string;
|
|
125
|
+
updated_at: string;
|
|
126
|
+
items?: RoadmapItem[];
|
|
127
|
+
}
|
|
128
|
+
interface RoadmapItem {
|
|
129
|
+
id: string;
|
|
130
|
+
roadmap_id: string;
|
|
131
|
+
column_id: string;
|
|
132
|
+
wish_id?: string | null;
|
|
133
|
+
title: string;
|
|
134
|
+
description?: string | null;
|
|
135
|
+
sort_order: number;
|
|
136
|
+
color?: string | null;
|
|
137
|
+
target_date?: string | null;
|
|
138
|
+
created_at: string;
|
|
139
|
+
updated_at: string;
|
|
140
|
+
wish?: Wish | null;
|
|
141
|
+
}
|
|
142
|
+
interface RoadmapData {
|
|
143
|
+
roadmap: Roadmap | null;
|
|
144
|
+
columns: RoadmapColumn[];
|
|
145
|
+
total_items: number;
|
|
146
|
+
customization?: {
|
|
147
|
+
use_custom: boolean;
|
|
148
|
+
customization_data: any;
|
|
149
|
+
} | null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Release / Changelog Types
|
|
154
|
+
*/
|
|
155
|
+
type ReleaseItemType = 'feature' | 'improvement' | 'bugfix' | 'other';
|
|
156
|
+
interface ReleaseItem {
|
|
157
|
+
id: string;
|
|
158
|
+
release_id: string;
|
|
159
|
+
title: string;
|
|
160
|
+
description?: string | null;
|
|
161
|
+
type: ReleaseItemType;
|
|
162
|
+
image_url?: string | null;
|
|
163
|
+
sort_order: number;
|
|
164
|
+
}
|
|
165
|
+
interface ReleaseFeature {
|
|
166
|
+
id: string;
|
|
167
|
+
release_id: string;
|
|
168
|
+
title: string;
|
|
169
|
+
description: string;
|
|
170
|
+
image_url?: string | null;
|
|
171
|
+
sort_order: number;
|
|
172
|
+
}
|
|
173
|
+
interface Release {
|
|
174
|
+
id: string;
|
|
175
|
+
project_id: string;
|
|
176
|
+
title: string;
|
|
177
|
+
content: string;
|
|
178
|
+
excerpt?: string | null;
|
|
179
|
+
cover_image_url?: string | null;
|
|
180
|
+
slug: string;
|
|
181
|
+
is_published: boolean;
|
|
182
|
+
published_at?: string | null;
|
|
183
|
+
version?: string | null;
|
|
184
|
+
labels: string[];
|
|
185
|
+
wish_ids: string[];
|
|
186
|
+
author_user_id: string;
|
|
187
|
+
created_at: string;
|
|
188
|
+
updated_at: string;
|
|
189
|
+
features?: ReleaseFeature[];
|
|
190
|
+
items?: ReleaseItem[];
|
|
191
|
+
}
|
|
192
|
+
interface ReleasesResponse {
|
|
193
|
+
data: Release[];
|
|
194
|
+
total: number;
|
|
195
|
+
page: number;
|
|
196
|
+
per_page: number;
|
|
197
|
+
total_pages: number;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Help Center Types
|
|
202
|
+
*/
|
|
203
|
+
type ArticleType = 'guide' | 'faq' | 'tutorial';
|
|
204
|
+
type FlowDisplayType = 'list' | 'accordion' | 'decision_tree' | 'wizard';
|
|
205
|
+
interface HelpArticle {
|
|
206
|
+
id: string;
|
|
207
|
+
flow_id: string;
|
|
208
|
+
title: string;
|
|
209
|
+
slug: string;
|
|
210
|
+
content: string;
|
|
211
|
+
excerpt?: string | null;
|
|
212
|
+
article_type: ArticleType;
|
|
213
|
+
is_published: boolean;
|
|
214
|
+
sort_order: number;
|
|
215
|
+
published_at?: string | null;
|
|
216
|
+
created_at: string;
|
|
217
|
+
updated_at: string;
|
|
218
|
+
}
|
|
219
|
+
interface HelpFlow {
|
|
220
|
+
id: string;
|
|
221
|
+
collection_id: string;
|
|
222
|
+
name: string;
|
|
223
|
+
slug: string;
|
|
224
|
+
description?: string | null;
|
|
225
|
+
icon?: string | null;
|
|
226
|
+
color?: string | null;
|
|
227
|
+
display_type: FlowDisplayType;
|
|
228
|
+
sort_order: number;
|
|
229
|
+
created_at: string;
|
|
230
|
+
updated_at: string;
|
|
231
|
+
articles?: HelpArticle[];
|
|
232
|
+
}
|
|
233
|
+
interface HelpCollection {
|
|
234
|
+
id: string;
|
|
235
|
+
project_id: string;
|
|
236
|
+
name: string;
|
|
237
|
+
version: string;
|
|
238
|
+
description?: string | null;
|
|
239
|
+
is_live: boolean;
|
|
240
|
+
created_at: string;
|
|
241
|
+
updated_at: string;
|
|
242
|
+
flows?: HelpFlow[];
|
|
243
|
+
}
|
|
244
|
+
interface HelpCenterData {
|
|
245
|
+
collection: HelpCollection | null;
|
|
246
|
+
flows: HelpFlow[];
|
|
247
|
+
}
|
|
248
|
+
interface HelpArticlesResponse {
|
|
249
|
+
data: HelpArticle[];
|
|
250
|
+
total: number;
|
|
251
|
+
page: number;
|
|
252
|
+
per_page: number;
|
|
253
|
+
total_pages: number;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Support Types
|
|
258
|
+
*/
|
|
259
|
+
type SupportRequestStatus = 'new' | 'open' | 'in_progress' | 'resolved' | 'closed';
|
|
260
|
+
type SupportRequestPriority = 'low' | 'medium' | 'high' | 'critical';
|
|
261
|
+
type SupportRequestCategory = 'bug_report' | 'feature_request' | 'general_inquiry' | 'billing' | 'account';
|
|
262
|
+
interface SupportAttachment {
|
|
263
|
+
url: string;
|
|
264
|
+
name: string;
|
|
265
|
+
size: number;
|
|
266
|
+
mime_type?: string;
|
|
267
|
+
}
|
|
268
|
+
interface SupportMessage {
|
|
269
|
+
id: string;
|
|
270
|
+
support_request_id: string;
|
|
271
|
+
author_type: 'user' | 'team_member';
|
|
272
|
+
author_user_id?: string | null;
|
|
273
|
+
author_email?: string | null;
|
|
274
|
+
author_name?: string | null;
|
|
275
|
+
content: string;
|
|
276
|
+
is_internal: boolean;
|
|
277
|
+
attachments?: SupportAttachment[];
|
|
278
|
+
created_at: string;
|
|
279
|
+
}
|
|
280
|
+
interface SupportRequest {
|
|
281
|
+
id: string;
|
|
282
|
+
project_id: string;
|
|
283
|
+
subject: string;
|
|
284
|
+
description: string;
|
|
285
|
+
status: SupportRequestStatus;
|
|
286
|
+
priority?: SupportRequestPriority | null;
|
|
287
|
+
category?: SupportRequestCategory | null;
|
|
288
|
+
user_email: string;
|
|
289
|
+
user_name?: string | null;
|
|
290
|
+
assignee_id?: string | null;
|
|
291
|
+
message_count: number;
|
|
292
|
+
created_at: string;
|
|
293
|
+
updated_at: string;
|
|
294
|
+
resolved_at?: string | null;
|
|
295
|
+
messages?: SupportMessage[];
|
|
296
|
+
attachments?: SupportAttachment[];
|
|
297
|
+
}
|
|
298
|
+
interface SupportRequestInput {
|
|
299
|
+
subject: string;
|
|
300
|
+
description: string;
|
|
301
|
+
user_email: string;
|
|
302
|
+
user_name?: string;
|
|
303
|
+
category?: SupportRequestCategory;
|
|
304
|
+
attachments?: File[];
|
|
305
|
+
}
|
|
306
|
+
interface SupportRequestsResponse {
|
|
307
|
+
data: SupportRequest[];
|
|
308
|
+
total: number;
|
|
309
|
+
page: number;
|
|
310
|
+
per_page: number;
|
|
311
|
+
total_pages: number;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* useVote Hook
|
|
316
|
+
*
|
|
317
|
+
* Manages voting state and actions for a wish.
|
|
318
|
+
* Provides optimistic updates for instant UI feedback.
|
|
319
|
+
*
|
|
320
|
+
* @example
|
|
321
|
+
* ```tsx
|
|
322
|
+
* import { useVote } from '@appgram/react'
|
|
323
|
+
*
|
|
324
|
+
* function VoteButton({ wishId, initialCount, initialHasVoted }) {
|
|
325
|
+
* const { hasVoted, voteCount, toggle, isLoading } = useVote({
|
|
326
|
+
* wishId,
|
|
327
|
+
* initialVoteCount: initialCount,
|
|
328
|
+
* initialHasVoted,
|
|
329
|
+
* onVoteChange: (voted, count) => {
|
|
330
|
+
* analytics.track('vote', { wishId, voted })
|
|
331
|
+
* }
|
|
332
|
+
* })
|
|
333
|
+
*
|
|
334
|
+
* return (
|
|
335
|
+
* <button
|
|
336
|
+
* onClick={toggle}
|
|
337
|
+
* disabled={isLoading}
|
|
338
|
+
* className={hasVoted ? 'voted' : ''}
|
|
339
|
+
* >
|
|
340
|
+
* {hasVoted ? '✓' : '▲'} {voteCount}
|
|
341
|
+
* </button>
|
|
342
|
+
* )
|
|
343
|
+
* }
|
|
344
|
+
* ```
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* ```tsx
|
|
348
|
+
* // Lazy vote check to avoid rate limiting
|
|
349
|
+
* const { hasVoted, voteCount, toggle } = useVote({
|
|
350
|
+
* wishId: wish.id,
|
|
351
|
+
* initialVoteCount: wish.vote_count,
|
|
352
|
+
* skipAutoCheck: true, // Check on first click instead
|
|
353
|
+
* })
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
356
|
+
interface UseVoteOptions {
|
|
357
|
+
/**
|
|
358
|
+
* The wish ID to vote on
|
|
359
|
+
*/
|
|
360
|
+
wishId: string;
|
|
361
|
+
/**
|
|
362
|
+
* Initial vote count (optional, useful when you already have the wish data)
|
|
363
|
+
*/
|
|
364
|
+
initialVoteCount?: number;
|
|
365
|
+
/**
|
|
366
|
+
* Initial hasVoted state (optional)
|
|
367
|
+
*/
|
|
368
|
+
initialHasVoted?: boolean;
|
|
369
|
+
/**
|
|
370
|
+
* Voter email (optional, for identified voting)
|
|
371
|
+
*/
|
|
372
|
+
voterEmail?: string;
|
|
373
|
+
/**
|
|
374
|
+
* Callback when vote state changes
|
|
375
|
+
*/
|
|
376
|
+
onVoteChange?: (hasVoted: boolean, voteCount: number) => void;
|
|
377
|
+
/**
|
|
378
|
+
* Skip automatic vote check on mount to avoid rate limiting
|
|
379
|
+
* When true, vote status will be checked lazily on first interaction
|
|
380
|
+
* @default true
|
|
381
|
+
*/
|
|
382
|
+
skipAutoCheck?: boolean;
|
|
383
|
+
}
|
|
384
|
+
interface UseVoteResult {
|
|
385
|
+
/**
|
|
386
|
+
* Whether the current user has voted
|
|
387
|
+
*/
|
|
388
|
+
hasVoted: boolean;
|
|
389
|
+
/**
|
|
390
|
+
* Current vote count
|
|
391
|
+
*/
|
|
392
|
+
voteCount: number;
|
|
393
|
+
/**
|
|
394
|
+
* Loading state for vote operations
|
|
395
|
+
*/
|
|
396
|
+
isLoading: boolean;
|
|
397
|
+
/**
|
|
398
|
+
* Loading state for initial vote check
|
|
399
|
+
*/
|
|
400
|
+
isChecking: boolean;
|
|
401
|
+
/**
|
|
402
|
+
* Error message if any
|
|
403
|
+
*/
|
|
404
|
+
error: string | null;
|
|
405
|
+
/**
|
|
406
|
+
* Toggle vote (vote if not voted, unvote if voted)
|
|
407
|
+
*/
|
|
408
|
+
toggle: () => Promise<void>;
|
|
409
|
+
/**
|
|
410
|
+
* Cast a vote
|
|
411
|
+
*/
|
|
412
|
+
vote: () => Promise<void>;
|
|
413
|
+
/**
|
|
414
|
+
* Remove a vote
|
|
415
|
+
*/
|
|
416
|
+
unvote: () => Promise<void>;
|
|
417
|
+
}
|
|
418
|
+
declare function useVote(options: UseVoteOptions): UseVoteResult;
|
|
419
|
+
|
|
420
|
+
export { type ArticleType as A, type WishPriority as B, type CommentsResponse as C, type WishStatus as D, useVote as E, type FlowDisplayType as F, type HelpCollection as H, type RoadmapData as R, type SupportRequestInput as S, type UseVoteOptions as U, type WishFilters as W, type WishesResponse as a, type Wish as b, type Comment as c, type Release as d, type ReleaseFeature as e, type HelpFlow as f, type HelpArticle as g, type SupportRequest as h, type Category as i, type CommentAuthor as j, type CommentCreateInput as k, type HelpArticlesResponse as l, type HelpCenterData as m, type ReleasesResponse as n, type Roadmap as o, type RoadmapColumn as p, type RoadmapItem as q, type RoadmapVisibility as r, type SupportAttachment as s, type SupportMessage as t, type SupportRequestCategory as u, type SupportRequestPriority as v, type SupportRequestStatus as w, type SupportRequestsResponse as x, type UseVoteResult as y, type WishAuthor as z };
|