@patch-adams/plugin-feedback 1.0.0 → 1.0.3
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 +21 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +21 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -77,7 +77,7 @@ var FeedbackConfigSchema = zod.z.object({
|
|
|
77
77
|
/** Text displayed on the feedback tab */
|
|
78
78
|
tabText: zod.z.string().default("Feedback"),
|
|
79
79
|
/** Background color of the feedback tab */
|
|
80
|
-
tabColor: zod.z.string().default("#
|
|
80
|
+
tabColor: zod.z.string().default("#da291c"),
|
|
81
81
|
/** Text color of the feedback tab */
|
|
82
82
|
tabTextColor: zod.z.string().default("#ffffff"),
|
|
83
83
|
/** Z-index for the feedback widget (default: 9999) */
|
|
@@ -635,6 +635,15 @@ function generateFeedbackStyles(config) {
|
|
|
635
635
|
const tabColor = config.tabColor;
|
|
636
636
|
const tabTextColor = config.tabTextColor;
|
|
637
637
|
const zIndex = config.zIndex;
|
|
638
|
+
const isRight = position === "right";
|
|
639
|
+
const tabTransform = isRight ? "-90deg" : "90deg";
|
|
640
|
+
const tabTransformOrigin = isRight ? "right center" : "left center";
|
|
641
|
+
const tabOffset = isRight ? "right: 20px; left: auto;" : "left: 20px; right: auto;";
|
|
642
|
+
const tabBorderRadius = isRight ? "8px 8px 0 0" : "0 0 8px 8px";
|
|
643
|
+
const modalPosition = isRight ? "right: 0; left: auto;" : "left: 0; right: auto;";
|
|
644
|
+
const modalJustify = isRight ? "flex-end" : "flex-start";
|
|
645
|
+
const contentShadow = isRight ? "-4px 0 20px rgba(0, 0, 0, 0.15)" : "4px 0 20px rgba(0, 0, 0, 0.15)";
|
|
646
|
+
const slideFrom = isRight ? "100%" : "-100%";
|
|
638
647
|
return `
|
|
639
648
|
/* ============================================================================
|
|
640
649
|
FEEDBACK WIDGET STYLES - Patch-Adams Plugin v1.0.0
|
|
@@ -665,11 +674,10 @@ function generateFeedbackStyles(config) {
|
|
|
665
674
|
|
|
666
675
|
#pa-feedback-tab {
|
|
667
676
|
position: fixed;
|
|
668
|
-
${position}: 0;
|
|
669
677
|
top: 50%;
|
|
670
|
-
|
|
671
|
-
transform
|
|
672
|
-
|
|
678
|
+
${tabOffset}
|
|
679
|
+
transform: translateY(-50%) rotate(${tabTransform});
|
|
680
|
+
transform-origin: ${tabTransformOrigin};
|
|
673
681
|
z-index: ${zIndex};
|
|
674
682
|
background: ${tabColor};
|
|
675
683
|
color: ${tabTextColor};
|
|
@@ -678,7 +686,7 @@ function generateFeedbackStyles(config) {
|
|
|
678
686
|
font-size: 14px;
|
|
679
687
|
font-weight: 600;
|
|
680
688
|
cursor: pointer;
|
|
681
|
-
border-radius: ${
|
|
689
|
+
border-radius: ${tabBorderRadius};
|
|
682
690
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
683
691
|
transition: all 0.2s ease;
|
|
684
692
|
white-space: nowrap;
|
|
@@ -704,14 +712,14 @@ function generateFeedbackStyles(config) {
|
|
|
704
712
|
|
|
705
713
|
#pa-feedback-modal {
|
|
706
714
|
position: fixed;
|
|
707
|
-
${position}: 0;
|
|
708
715
|
top: 0;
|
|
716
|
+
${modalPosition}
|
|
709
717
|
width: 360px;
|
|
710
718
|
height: 100%;
|
|
711
719
|
z-index: ${zIndex + 1};
|
|
712
720
|
background: rgba(0, 0, 0, 0.3);
|
|
713
721
|
display: flex;
|
|
714
|
-
justify-content:
|
|
722
|
+
justify-content: ${modalJustify};
|
|
715
723
|
animation: pa-feedback-fade-in 0.2s ease;
|
|
716
724
|
}
|
|
717
725
|
|
|
@@ -725,7 +733,7 @@ function generateFeedbackStyles(config) {
|
|
|
725
733
|
max-width: 360px;
|
|
726
734
|
height: 100%;
|
|
727
735
|
background: #fff;
|
|
728
|
-
box-shadow: ${
|
|
736
|
+
box-shadow: ${contentShadow};
|
|
729
737
|
display: flex;
|
|
730
738
|
flex-direction: column;
|
|
731
739
|
animation: pa-feedback-slide-in 0.2s ease;
|
|
@@ -733,7 +741,7 @@ function generateFeedbackStyles(config) {
|
|
|
733
741
|
|
|
734
742
|
@keyframes pa-feedback-slide-in {
|
|
735
743
|
from {
|
|
736
|
-
transform: translateX(${
|
|
744
|
+
transform: translateX(${slideFrom});
|
|
737
745
|
}
|
|
738
746
|
to {
|
|
739
747
|
transform: translateX(0);
|
|
@@ -913,10 +921,13 @@ function generateFeedbackStyles(config) {
|
|
|
913
921
|
cursor: pointer;
|
|
914
922
|
transition: all 0.15s ease;
|
|
915
923
|
margin-top: auto;
|
|
924
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
916
925
|
}
|
|
917
926
|
|
|
918
927
|
#pa-feedback-container .pa-feedback-submit:hover:not(:disabled) {
|
|
919
928
|
background: ${adjustColor(tabColor, -15)};
|
|
929
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
930
|
+
transform: translateY(-1px);
|
|
920
931
|
}
|
|
921
932
|
|
|
922
933
|
#pa-feedback-container .pa-feedback-submit:focus {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/i18n/en.json","../src/i18n/fr.json","../src/i18n/index.ts","../src/widget.ts","../src/styles.ts","../src/index.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["import { z } from 'zod';\n\n/**\n * Issue subtype definition\n */\nexport const IssueSubtypeSchema = z.object({\n /** Unique identifier for the subtype */\n id: z.string().min(1),\n /** Display label for the subtype */\n label: z.string().min(1),\n});\n\n/**\n * Issue type definition with optional subtypes\n */\nexport const IssueTypeSchema = z.object({\n /** Unique identifier for the issue type */\n id: z.string().min(1),\n /** Display label for the issue type */\n label: z.string().min(1),\n /** Optional subtypes that appear when this type is selected */\n subtypes: z.array(IssueSubtypeSchema).optional(),\n});\n\n/**\n * Metadata options - what to include with feedback submissions\n */\nexport const MetadataOptionsSchema = z.object({\n /** Include the course ID from LRS bridge (if available) */\n courseId: z.boolean().default(true),\n /** Include the current lesson/page ID (URL hash or pathname) */\n lessonId: z.boolean().default(true),\n /** Include the browser user agent */\n userAgent: z.boolean().default(true),\n /** Include timestamp of submission */\n timestamp: z.boolean().default(true),\n /** Include the full current URL */\n url: z.boolean().default(true),\n});\n\n/**\n * Default issue types if none are provided\n */\nexport const DEFAULT_ISSUE_TYPES: z.infer<typeof IssueTypeSchema>[] = [\n {\n id: 'content',\n label: 'Content Issue',\n subtypes: [\n { id: 'typo', label: 'Typo / Grammar' },\n { id: 'incorrect', label: 'Incorrect Information' },\n { id: 'unclear', label: 'Unclear / Confusing' },\n { id: 'outdated', label: 'Outdated Content' },\n ],\n },\n {\n id: 'technical',\n label: 'Technical Issue',\n subtypes: [\n { id: 'audio', label: 'Audio Problem' },\n { id: 'video', label: 'Video Problem' },\n { id: 'navigation', label: 'Navigation Issue' },\n { id: 'display', label: 'Display / Layout Issue' },\n ],\n },\n {\n id: 'suggestion',\n label: 'Suggestion',\n },\n {\n id: 'other',\n label: 'Other',\n },\n];\n\n/**\n * Full feedback plugin configuration schema\n */\nexport const FeedbackConfigSchema = z.object({\n /** Whether the feedback plugin is enabled */\n enabled: z.boolean().default(true),\n\n // === Endpoint Configuration ===\n\n /** API endpoint URL for submitting feedback (optional - if not set, logs to console) */\n endpoint: z.string().url().optional(),\n\n /** HTTP method for the endpoint (default: POST) */\n method: z.enum(['POST', 'PUT']).default('POST'),\n\n /** Additional headers to send with the request */\n headers: z.record(z.string()).optional(),\n\n // === Appearance ===\n\n /** Position of the feedback tab (left or right side of screen) */\n position: z.enum(['left', 'right']).default('right'),\n\n /** Text displayed on the feedback tab */\n tabText: z.string().default('Feedback'),\n\n /** Background color of the feedback tab */\n tabColor: z.string().default('#007bff'),\n\n /** Text color of the feedback tab */\n tabTextColor: z.string().default('#ffffff'),\n\n /** Z-index for the feedback widget (default: 9999) */\n zIndex: z.number().default(9999),\n\n // === Form Fields ===\n\n /** Show star rating field */\n showRating: z.boolean().default(true),\n\n /** Whether rating is required to submit */\n ratingRequired: z.boolean().default(false),\n\n /** Number of stars in the rating (default: 5) */\n ratingStars: z.number().min(3).max(10).default(5),\n\n /** Show issue type dropdown */\n showIssueType: z.boolean().default(true),\n\n /** Whether issue type is required to submit */\n issueTypeRequired: z.boolean().default(false),\n\n /** Available issue types (uses defaults if not provided) */\n issueTypes: z.array(IssueTypeSchema).optional(),\n\n /** Show comment textarea */\n showComment: z.boolean().default(true),\n\n /** Whether comment is required to submit */\n commentRequired: z.boolean().default(false),\n\n /** Maximum length for comments (default: 500) */\n commentMaxLength: z.number().min(50).max(5000).default(500),\n\n /** Placeholder text for comment field (uses translation if not set) */\n commentPlaceholder: z.string().optional(),\n\n // === Language / i18n ===\n\n /** Locale for UI text (en or fr) */\n locale: z.enum(['en', 'fr']).default('en'),\n\n /** Custom translations (overrides built-in translations) */\n translations: z.record(z.string()).optional(),\n\n // === Metadata ===\n\n /** What metadata to include with feedback submissions */\n includeMetadata: MetadataOptionsSchema.default({}),\n\n // === Behavior ===\n\n /** Auto-close modal after successful submission (default: true) */\n autoClose: z.boolean().default(true),\n\n /** Delay in ms before auto-closing after success (default: 2000) */\n autoCloseDelay: z.number().min(500).max(10000).default(2000),\n\n /** Enable debug logging (default: false) */\n debug: z.boolean().default(false),\n});\n\nexport type FeedbackConfig = z.infer<typeof FeedbackConfigSchema>;\nexport type IssueType = z.infer<typeof IssueTypeSchema>;\nexport type IssueSubtype = z.infer<typeof IssueSubtypeSchema>;\nexport type MetadataOptions = z.infer<typeof MetadataOptionsSchema>;\n","{\n \"title\": \"Send Feedback\",\n \"ratingLabel\": \"How would you rate this content?\",\n \"issueTypeLabel\": \"What type of feedback?\",\n \"selectIssueType\": \"Select type...\",\n \"subtypeLabel\": \"More specifically:\",\n \"selectSubtype\": \"Select...\",\n \"commentLabel\": \"Your feedback\",\n \"commentPlaceholder\": \"Please describe your feedback in detail...\",\n \"submit\": \"Send Feedback\",\n \"submitting\": \"Sending...\",\n \"thankYou\": \"Thank you for your feedback!\",\n \"errorSubmitting\": \"Failed to send feedback. Please try again.\",\n \"errorRequired\": \"Please fill in the required fields.\",\n \"characterCount\": \"{current}/{max}\"\n}\n","{\n \"title\": \"Envoyer un commentaire\",\n \"ratingLabel\": \"Comment évaluez-vous ce contenu?\",\n \"issueTypeLabel\": \"Type de commentaire\",\n \"selectIssueType\": \"Sélectionner...\",\n \"subtypeLabel\": \"Plus précisément:\",\n \"selectSubtype\": \"Sélectionner...\",\n \"commentLabel\": \"Votre commentaire\",\n \"commentPlaceholder\": \"Veuillez décrire votre commentaire en détail...\",\n \"submit\": \"Envoyer\",\n \"submitting\": \"Envoi en cours...\",\n \"thankYou\": \"Merci pour votre commentaire!\",\n \"errorSubmitting\": \"Échec de l'envoi. Veuillez réessayer.\",\n \"errorRequired\": \"Veuillez remplir les champs obligatoires.\",\n \"characterCount\": \"{current}/{max}\"\n}\n","import en from './en.json';\nimport fr from './fr.json';\n\nexport interface Translations {\n title: string;\n ratingLabel: string;\n issueTypeLabel: string;\n selectIssueType: string;\n subtypeLabel: string;\n selectSubtype: string;\n commentLabel: string;\n commentPlaceholder: string;\n submit: string;\n submitting: string;\n thankYou: string;\n errorSubmitting: string;\n errorRequired: string;\n characterCount: string;\n}\n\nexport const translations: Record<string, Translations> = {\n en: en as Translations,\n fr: fr as Translations,\n};\n\nexport function getTranslations(locale: string, overrides?: Record<string, string>): Translations {\n const base = translations[locale] || translations.en;\n if (overrides) {\n return { ...base, ...overrides } as Translations;\n }\n return base;\n}\n\nexport { en, fr };\n","import type { FeedbackConfig, IssueType } from './config.js';\nimport { DEFAULT_ISSUE_TYPES } from './config.js';\nimport { getTranslations } from './i18n/index.js';\n\n/**\n * Generate the feedback widget JavaScript code.\n * This produces a self-contained IIFE that creates and manages the feedback widget.\n */\nexport function generateFeedbackWidget(config: FeedbackConfig): string {\n const t = getTranslations(config.locale, config.translations);\n const issueTypes = config.issueTypes || DEFAULT_ISSUE_TYPES;\n\n return `\n(function() {\n 'use strict';\n\n // ============================================================================\n // FEEDBACK WIDGET - Patch-Adams Plugin v1.0.0\n // ============================================================================\n\n var FEEDBACK = window.pa_patcher = window.pa_patcher || {};\n FEEDBACK.feedback = {\n version: '1.0.0',\n isOpen: false,\n rating: 0,\n config: ${JSON.stringify({\n endpoint: config.endpoint,\n method: config.method,\n headers: config.headers,\n position: config.position,\n showRating: config.showRating,\n ratingRequired: config.ratingRequired,\n ratingStars: config.ratingStars,\n showIssueType: config.showIssueType,\n issueTypeRequired: config.issueTypeRequired,\n showComment: config.showComment,\n commentRequired: config.commentRequired,\n commentMaxLength: config.commentMaxLength,\n autoClose: config.autoClose,\n autoCloseDelay: config.autoCloseDelay,\n debug: config.debug,\n includeMetadata: config.includeMetadata,\n })},\n translations: ${JSON.stringify(t)},\n issueTypes: ${JSON.stringify(issueTypes)},\n };\n\n var FB = FEEDBACK.feedback;\n\n function log() {\n if (FB.config.debug) {\n console.log.apply(console, ['[PA-Feedback]'].concat(Array.prototype.slice.call(arguments)));\n }\n }\n\n // ============================================================================\n // DOM CREATION\n // ============================================================================\n\n function createWidget() {\n var container = document.createElement('div');\n container.id = 'pa-feedback-container';\n container.className = 'pa-feedback-${config.position}';\n container.innerHTML = buildWidgetHtml();\n document.body.appendChild(container);\n setupEventListeners();\n log('Widget created');\n }\n\n function buildWidgetHtml() {\n var html = '';\n\n // Tab button\n html += '<button id=\"pa-feedback-tab\" class=\"pa-feedback-tab\" aria-label=\"' + FB.translations.title + '\">';\n html += '<span class=\"pa-feedback-tab-text\">${config.tabText}</span>';\n html += '</button>';\n\n // Modal\n html += '<div id=\"pa-feedback-modal\" class=\"pa-feedback-modal pa-feedback-hidden\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"pa-feedback-title\">';\n html += '<div class=\"pa-feedback-content\">';\n\n // Header\n html += '<div class=\"pa-feedback-header\">';\n html += '<h3 id=\"pa-feedback-title\">' + FB.translations.title + '</h3>';\n html += '<button id=\"pa-feedback-close\" class=\"pa-feedback-close\" aria-label=\"Close\">×</button>';\n html += '</div>';\n\n // Form\n html += '<form id=\"pa-feedback-form\">';\n\n // Rating (if enabled)\n ${config.showRating ? `\n html += '<div class=\"pa-feedback-field\">';\n html += '<label class=\"pa-feedback-label\">' + FB.translations.ratingLabel + '${config.ratingRequired ? ' <span class=\"pa-feedback-required\">*</span>' : ''}</label>';\n html += '<div class=\"pa-feedback-stars\" role=\"radiogroup\" aria-label=\"Rating\">';\n for (var i = 1; i <= ${config.ratingStars}; i++) {\n html += '<button type=\"button\" class=\"pa-feedback-star\" data-value=\"' + i + '\" role=\"radio\" aria-checked=\"false\" aria-label=\"' + i + ' star\">☆</button>';\n }\n html += '</div>';\n html += '</div>';\n ` : ''}\n\n // Issue Type (if enabled)\n ${config.showIssueType ? `\n html += '<div class=\"pa-feedback-field\">';\n html += '<label class=\"pa-feedback-label\" for=\"pa-feedback-issue-type\">' + FB.translations.issueTypeLabel + '${config.issueTypeRequired ? ' <span class=\"pa-feedback-required\">*</span>' : ''}</label>';\n html += '<select id=\"pa-feedback-issue-type\" class=\"pa-feedback-select\">';\n html += '<option value=\"\">' + FB.translations.selectIssueType + '</option>';\n FB.issueTypes.forEach(function(type) {\n html += '<option value=\"' + type.id + '\">' + type.label + '</option>';\n });\n html += '</select>';\n html += '</div>';\n\n // Subtype container (hidden by default)\n html += '<div id=\"pa-feedback-subtype-field\" class=\"pa-feedback-field pa-feedback-hidden\">';\n html += '<label class=\"pa-feedback-label\" for=\"pa-feedback-subtype\">' + FB.translations.subtypeLabel + '</label>';\n html += '<select id=\"pa-feedback-subtype\" class=\"pa-feedback-select\">';\n html += '<option value=\"\">' + FB.translations.selectSubtype + '</option>';\n html += '</select>';\n html += '</div>';\n ` : ''}\n\n // Comment (if enabled)\n ${config.showComment ? `\n html += '<div class=\"pa-feedback-field\">';\n html += '<label class=\"pa-feedback-label\" for=\"pa-feedback-comment\">' + FB.translations.commentLabel + '${config.commentRequired ? ' <span class=\"pa-feedback-required\">*</span>' : ''}</label>';\n html += '<textarea id=\"pa-feedback-comment\" class=\"pa-feedback-textarea\" maxlength=\"${config.commentMaxLength}\" placeholder=\"${config.commentPlaceholder || ''}\" rows=\"4\"></textarea>';\n html += '<div class=\"pa-feedback-counter\"><span id=\"pa-feedback-char-count\">0</span>/${config.commentMaxLength}</div>';\n html += '</div>';\n ` : ''}\n\n // Error message area\n html += '<div id=\"pa-feedback-error\" class=\"pa-feedback-error pa-feedback-hidden\"></div>';\n\n // Submit button\n html += '<button type=\"submit\" id=\"pa-feedback-submit\" class=\"pa-feedback-submit\">';\n html += '<span class=\"pa-feedback-submit-text\">' + FB.translations.submit + '</span>';\n html += '<span class=\"pa-feedback-submit-loading pa-feedback-hidden\">' + FB.translations.submitting + '</span>';\n html += '</button>';\n\n html += '</form>';\n\n // Success message\n html += '<div id=\"pa-feedback-success\" class=\"pa-feedback-success pa-feedback-hidden\">';\n html += '<div class=\"pa-feedback-checkmark\">✓</div>';\n html += '<p>' + FB.translations.thankYou + '</p>';\n html += '</div>';\n\n html += '</div>'; // content\n html += '</div>'; // modal\n\n return html;\n }\n\n // ============================================================================\n // EVENT HANDLERS\n // ============================================================================\n\n function setupEventListeners() {\n // Tab click\n document.getElementById('pa-feedback-tab').addEventListener('click', toggleModal);\n\n // Close button\n document.getElementById('pa-feedback-close').addEventListener('click', closeModal);\n\n // Form submit\n document.getElementById('pa-feedback-form').addEventListener('submit', handleSubmit);\n\n // Click outside to close\n document.getElementById('pa-feedback-modal').addEventListener('click', function(e) {\n if (e.target === this) closeModal();\n });\n\n // Escape key to close\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape' && FB.isOpen) closeModal();\n });\n\n ${config.showRating ? `\n // Star rating\n var stars = document.querySelectorAll('.pa-feedback-star');\n stars.forEach(function(star, index) {\n star.addEventListener('click', function() {\n FB.rating = index + 1;\n updateStars();\n });\n star.addEventListener('mouseenter', function() {\n highlightStars(index + 1);\n });\n });\n document.querySelector('.pa-feedback-stars').addEventListener('mouseleave', function() {\n highlightStars(FB.rating);\n });\n ` : ''}\n\n ${config.showIssueType ? `\n // Issue type change\n document.getElementById('pa-feedback-issue-type').addEventListener('change', updateSubtypes);\n ` : ''}\n\n ${config.showComment ? `\n // Character counter\n document.getElementById('pa-feedback-comment').addEventListener('input', updateCharCount);\n ` : ''}\n }\n\n function toggleModal() {\n if (FB.isOpen) {\n closeModal();\n } else {\n openModal();\n }\n }\n\n function openModal() {\n FB.isOpen = true;\n document.getElementById('pa-feedback-modal').classList.remove('pa-feedback-hidden');\n document.getElementById('pa-feedback-tab').classList.add('pa-feedback-tab-active');\n log('Modal opened');\n }\n\n function closeModal() {\n FB.isOpen = false;\n document.getElementById('pa-feedback-modal').classList.add('pa-feedback-hidden');\n document.getElementById('pa-feedback-tab').classList.remove('pa-feedback-tab-active');\n log('Modal closed');\n }\n\n ${config.showRating ? `\n function updateStars() {\n var stars = document.querySelectorAll('.pa-feedback-star');\n stars.forEach(function(star, index) {\n var isFilled = index < FB.rating;\n star.innerHTML = isFilled ? '★' : '☆';\n star.classList.toggle('pa-feedback-star-filled', isFilled);\n star.setAttribute('aria-checked', isFilled ? 'true' : 'false');\n });\n }\n\n function highlightStars(count) {\n var stars = document.querySelectorAll('.pa-feedback-star');\n stars.forEach(function(star, index) {\n var isFilled = index < count;\n star.innerHTML = isFilled ? '★' : '☆';\n star.classList.toggle('pa-feedback-star-hover', isFilled && count > FB.rating);\n });\n }\n ` : ''}\n\n ${config.showIssueType ? `\n function updateSubtypes() {\n var typeSelect = document.getElementById('pa-feedback-issue-type');\n var subtypeField = document.getElementById('pa-feedback-subtype-field');\n var subtypeSelect = document.getElementById('pa-feedback-subtype');\n var selectedType = typeSelect.value;\n\n // Find the selected issue type\n var issueType = FB.issueTypes.find(function(t) { return t.id === selectedType; });\n\n if (issueType && issueType.subtypes && issueType.subtypes.length > 0) {\n // Populate subtypes\n subtypeSelect.innerHTML = '<option value=\"\">' + FB.translations.selectSubtype + '</option>';\n issueType.subtypes.forEach(function(subtype) {\n subtypeSelect.innerHTML += '<option value=\"' + subtype.id + '\">' + subtype.label + '</option>';\n });\n subtypeField.classList.remove('pa-feedback-hidden');\n } else {\n subtypeField.classList.add('pa-feedback-hidden');\n subtypeSelect.value = '';\n }\n }\n ` : ''}\n\n ${config.showComment ? `\n function updateCharCount() {\n var textarea = document.getElementById('pa-feedback-comment');\n var counter = document.getElementById('pa-feedback-char-count');\n counter.textContent = textarea.value.length;\n }\n ` : ''}\n\n // ============================================================================\n // FORM SUBMISSION\n // ============================================================================\n\n function validateForm() {\n var errors = [];\n\n ${config.showRating && config.ratingRequired ? `\n if (FB.rating === 0) {\n errors.push('Rating is required');\n }\n ` : ''}\n\n ${config.showIssueType && config.issueTypeRequired ? `\n if (!document.getElementById('pa-feedback-issue-type').value) {\n errors.push('Issue type is required');\n }\n ` : ''}\n\n ${config.showComment && config.commentRequired ? `\n if (!document.getElementById('pa-feedback-comment').value.trim()) {\n errors.push('Comment is required');\n }\n ` : ''}\n\n return errors;\n }\n\n function collectFormData() {\n var data = {};\n\n ${config.showRating ? `data.rating = FB.rating;` : ''}\n ${config.showIssueType ? `\n data.issueType = document.getElementById('pa-feedback-issue-type').value || null;\n data.issueSubtype = document.getElementById('pa-feedback-subtype').value || null;\n ` : ''}\n ${config.showComment ? `data.comment = document.getElementById('pa-feedback-comment').value.trim();` : ''}\n\n // Add metadata\n data.metadata = collectMetadata();\n\n return data;\n }\n\n function collectMetadata() {\n var meta = {};\n var cfg = FB.config.includeMetadata;\n\n if (cfg.courseId && window.pa_patcher && window.pa_patcher.lrs && window.pa_patcher.lrs.courseInfo) {\n meta.courseId = window.pa_patcher.lrs.courseInfo.id;\n meta.courseTitle = window.pa_patcher.lrs.courseInfo.title;\n }\n\n if (cfg.lessonId) {\n meta.lessonId = window.location.hash || window.location.pathname;\n }\n\n if (cfg.userAgent) {\n meta.userAgent = navigator.userAgent;\n }\n\n if (cfg.timestamp) {\n meta.timestamp = new Date().toISOString();\n }\n\n if (cfg.url) {\n meta.url = window.location.href;\n }\n\n return meta;\n }\n\n function showError(message) {\n var errorEl = document.getElementById('pa-feedback-error');\n errorEl.textContent = message;\n errorEl.classList.remove('pa-feedback-hidden');\n }\n\n function hideError() {\n document.getElementById('pa-feedback-error').classList.add('pa-feedback-hidden');\n }\n\n function setSubmitting(isSubmitting) {\n var submitBtn = document.getElementById('pa-feedback-submit');\n var textEl = submitBtn.querySelector('.pa-feedback-submit-text');\n var loadingEl = submitBtn.querySelector('.pa-feedback-submit-loading');\n\n submitBtn.disabled = isSubmitting;\n textEl.classList.toggle('pa-feedback-hidden', isSubmitting);\n loadingEl.classList.toggle('pa-feedback-hidden', !isSubmitting);\n }\n\n function showSuccess() {\n document.getElementById('pa-feedback-form').classList.add('pa-feedback-hidden');\n document.getElementById('pa-feedback-success').classList.remove('pa-feedback-hidden');\n\n if (FB.config.autoClose) {\n setTimeout(function() {\n closeModal();\n resetForm();\n }, FB.config.autoCloseDelay);\n }\n }\n\n function resetForm() {\n var form = document.getElementById('pa-feedback-form');\n form.reset();\n form.classList.remove('pa-feedback-hidden');\n document.getElementById('pa-feedback-success').classList.add('pa-feedback-hidden');\n hideError();\n\n FB.rating = 0;\n ${config.showRating ? 'updateStars();' : ''}\n ${config.showComment ? 'updateCharCount();' : ''}\n ${config.showIssueType ? `\n document.getElementById('pa-feedback-subtype-field').classList.add('pa-feedback-hidden');\n ` : ''}\n }\n\n async function handleSubmit(e) {\n e.preventDefault();\n hideError();\n\n // Validate\n var errors = validateForm();\n if (errors.length > 0) {\n showError(FB.translations.errorRequired);\n return;\n }\n\n // Collect data\n var data = collectFormData();\n log('Submitting:', data);\n\n // Submit\n setSubmitting(true);\n\n try {\n ${config.endpoint ? `\n var response = await fetch('${config.endpoint}', {\n method: '${config.method}',\n headers: Object.assign({\n 'Content-Type': 'application/json',\n }, FB.config.headers || {}),\n body: JSON.stringify(data),\n });\n\n if (!response.ok) {\n throw new Error('HTTP ' + response.status);\n }\n\n log('Submitted successfully');\n ` : `\n // No endpoint configured - just log\n console.log('[PA-Feedback] Feedback submitted:', data);\n log('No endpoint configured, feedback logged to console');\n `}\n\n showSuccess();\n } catch (err) {\n log('Submit error:', err);\n showError(FB.translations.errorSubmitting);\n } finally {\n setSubmitting(false);\n }\n }\n\n // ============================================================================\n // INITIALIZATION\n // ============================================================================\n\n function init() {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', createWidget);\n } else {\n createWidget();\n }\n log('Initialized');\n }\n\n init();\n\n})();\n`;\n}\n","import type { FeedbackConfig } from './config.js';\n\n/**\n * Generate the CSS styles for the feedback widget.\n * Styles are scoped with #pa-feedback-container to avoid conflicts.\n */\nexport function generateFeedbackStyles(config: FeedbackConfig): string {\n const position = config.position;\n const tabColor = config.tabColor;\n const tabTextColor = config.tabTextColor;\n const zIndex = config.zIndex;\n\n return `\n/* ============================================================================\n FEEDBACK WIDGET STYLES - Patch-Adams Plugin v1.0.0\n ============================================================================ */\n\n#pa-feedback-container {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: #333;\n box-sizing: border-box;\n}\n\n#pa-feedback-container *,\n#pa-feedback-container *::before,\n#pa-feedback-container *::after {\n box-sizing: inherit;\n}\n\n/* Hidden utility class */\n#pa-feedback-container .pa-feedback-hidden {\n display: none !important;\n}\n\n/* ============================================================================\n TAB BUTTON\n ============================================================================ */\n\n#pa-feedback-tab {\n position: fixed;\n ${position}: 0;\n top: 50%;\n transform: translateY(-50%) rotate(${position === 'right' ? '-90deg' : '90deg'});\n transform-origin: ${position === 'right' ? 'right center' : 'left center'};\n ${position === 'right' ? 'right: -32px;' : 'left: -32px;'}\n z-index: ${zIndex};\n background: ${tabColor};\n color: ${tabTextColor};\n border: none;\n padding: 10px 20px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n border-radius: ${position === 'right' ? '0 0 8px 8px' : '8px 8px 0 0'};\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n#pa-feedback-tab:hover {\n background: ${adjustColor(tabColor, -15)};\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n}\n\n#pa-feedback-tab:focus {\n outline: 2px solid ${tabColor};\n outline-offset: 2px;\n}\n\n#pa-feedback-tab.pa-feedback-tab-active {\n background: ${adjustColor(tabColor, -20)};\n}\n\n/* ============================================================================\n MODAL\n ============================================================================ */\n\n#pa-feedback-modal {\n position: fixed;\n ${position}: 0;\n top: 0;\n width: 360px;\n height: 100%;\n z-index: ${zIndex + 1};\n background: rgba(0, 0, 0, 0.3);\n display: flex;\n justify-content: flex-${position === 'right' ? 'end' : 'start'};\n animation: pa-feedback-fade-in 0.2s ease;\n}\n\n@keyframes pa-feedback-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n#pa-feedback-container .pa-feedback-content {\n width: 100%;\n max-width: 360px;\n height: 100%;\n background: #fff;\n box-shadow: ${position === 'right' ? '-4px' : '4px'} 0 20px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n animation: pa-feedback-slide-in 0.2s ease;\n}\n\n@keyframes pa-feedback-slide-in {\n from {\n transform: translateX(${position === 'right' ? '100%' : '-100%'});\n }\n to {\n transform: translateX(0);\n }\n}\n\n/* ============================================================================\n HEADER\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid #e5e5e5;\n background: #fafafa;\n}\n\n#pa-feedback-container .pa-feedback-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #222;\n}\n\n#pa-feedback-container .pa-feedback-close {\n background: none;\n border: none;\n font-size: 24px;\n color: #666;\n cursor: pointer;\n padding: 4px 8px;\n line-height: 1;\n border-radius: 4px;\n transition: all 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-close:hover {\n background: #e5e5e5;\n color: #333;\n}\n\n/* ============================================================================\n FORM\n ============================================================================ */\n\n#pa-feedback-form {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n#pa-feedback-container .pa-feedback-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n#pa-feedback-container .pa-feedback-label {\n font-weight: 500;\n color: #444;\n font-size: 14px;\n}\n\n#pa-feedback-container .pa-feedback-required {\n color: #dc3545;\n}\n\n/* ============================================================================\n STAR RATING\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-stars {\n display: flex;\n gap: 4px;\n}\n\n#pa-feedback-container .pa-feedback-star {\n background: none;\n border: none;\n font-size: 28px;\n color: #ccc;\n cursor: pointer;\n padding: 4px;\n line-height: 1;\n transition: all 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-star:hover {\n transform: scale(1.1);\n}\n\n#pa-feedback-container .pa-feedback-star-filled,\n#pa-feedback-container .pa-feedback-star-hover {\n color: #ffc107;\n}\n\n/* ============================================================================\n SELECT & TEXTAREA\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-select {\n width: 100%;\n padding: 10px 12px;\n font-size: 14px;\n border: 1px solid #ddd;\n border-radius: 6px;\n background: #fff;\n color: #333;\n cursor: pointer;\n transition: border-color 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-select:focus {\n outline: none;\n border-color: ${tabColor};\n box-shadow: 0 0 0 3px ${hexToRgba(tabColor, 0.1)};\n}\n\n#pa-feedback-container .pa-feedback-textarea {\n width: 100%;\n padding: 12px;\n font-size: 14px;\n font-family: inherit;\n border: 1px solid #ddd;\n border-radius: 6px;\n resize: vertical;\n min-height: 100px;\n transition: border-color 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-textarea:focus {\n outline: none;\n border-color: ${tabColor};\n box-shadow: 0 0 0 3px ${hexToRgba(tabColor, 0.1)};\n}\n\n#pa-feedback-container .pa-feedback-textarea::placeholder {\n color: #999;\n}\n\n#pa-feedback-container .pa-feedback-counter {\n text-align: right;\n font-size: 12px;\n color: #888;\n}\n\n/* ============================================================================\n ERROR MESSAGE\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-error {\n background: #fee2e2;\n color: #dc2626;\n padding: 10px 14px;\n border-radius: 6px;\n font-size: 13px;\n}\n\n/* ============================================================================\n SUBMIT BUTTON\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-submit {\n width: 100%;\n padding: 12px 20px;\n font-size: 16px;\n font-weight: 600;\n color: #fff;\n background: ${tabColor};\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n margin-top: auto;\n}\n\n#pa-feedback-container .pa-feedback-submit:hover:not(:disabled) {\n background: ${adjustColor(tabColor, -15)};\n}\n\n#pa-feedback-container .pa-feedback-submit:focus {\n outline: 2px solid ${tabColor};\n outline-offset: 2px;\n}\n\n#pa-feedback-container .pa-feedback-submit:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n}\n\n/* ============================================================================\n SUCCESS MESSAGE\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-success {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n\n#pa-feedback-container .pa-feedback-checkmark {\n width: 64px;\n height: 64px;\n background: #10b981;\n color: #fff;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 32px;\n margin-bottom: 20px;\n animation: pa-feedback-pop 0.3s ease;\n}\n\n@keyframes pa-feedback-pop {\n 0% { transform: scale(0); }\n 50% { transform: scale(1.2); }\n 100% { transform: scale(1); }\n}\n\n#pa-feedback-container .pa-feedback-success p {\n margin: 0;\n font-size: 18px;\n font-weight: 500;\n color: #333;\n}\n`;\n}\n\n/**\n * Adjust a hex color by a percentage (positive = lighter, negative = darker)\n */\nfunction adjustColor(hex: string, percent: number): string {\n // Remove # if present\n hex = hex.replace(/^#/, '');\n\n // Parse the color\n let r = parseInt(hex.substring(0, 2), 16);\n let g = parseInt(hex.substring(2, 4), 16);\n let b = parseInt(hex.substring(4, 6), 16);\n\n // Adjust\n r = Math.min(255, Math.max(0, r + (r * percent) / 100));\n g = Math.min(255, Math.max(0, g + (g * percent) / 100));\n b = Math.min(255, Math.max(0, b + (b * percent) / 100));\n\n // Convert back to hex\n return (\n '#' +\n Math.round(r).toString(16).padStart(2, '0') +\n Math.round(g).toString(16).padStart(2, '0') +\n Math.round(b).toString(16).padStart(2, '0')\n );\n}\n\n/**\n * Convert hex color to rgba\n */\nfunction hexToRgba(hex: string, alpha: number): string {\n hex = hex.replace(/^#/, '');\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n","/**\n * @patch-adams/plugin-feedback\n *\n * Feedback widget plugin for Patch-Adams.\n * Injects a customizable feedback form into patched Rise courses.\n *\n * Features:\n * - Star rating\n * - Issue type/subtype selection\n * - Comment text area\n * - Multi-language support (en/fr)\n * - Customizable appearance\n * - Automatic metadata collection\n * - Configurable API endpoint\n */\n\nimport type { PatchAdamsPlugin } from '@patch-adams/core';\nimport { FeedbackConfigSchema, type FeedbackConfig } from './config.js';\nimport { generateFeedbackWidget } from './widget.js';\nimport { generateFeedbackStyles } from './styles.js';\n\n/**\n * Feedback plugin for Patch-Adams\n */\nexport const feedbackPlugin: PatchAdamsPlugin<FeedbackConfig> = {\n name: 'feedback',\n version: '1.0.0',\n description: 'Inject a feedback form widget into Rise courses for collecting user feedback',\n configSchema: FeedbackConfigSchema,\n\n generateCss(config: FeedbackConfig) {\n return {\n after: generateFeedbackStyles(config),\n };\n },\n\n generateJs(config: FeedbackConfig) {\n return {\n after: generateFeedbackWidget(config),\n };\n },\n};\n\n// Default export for convenience\nexport default feedbackPlugin;\n\n// Re-export types and utilities\nexport {\n FeedbackConfigSchema,\n type FeedbackConfig,\n type IssueType,\n type IssueSubtype,\n type MetadataOptions,\n DEFAULT_ISSUE_TYPES,\n} from './config.js';\n\nexport { generateFeedbackWidget } from './widget.js';\nexport { generateFeedbackStyles } from './styles.js';\nexport { getTranslations, translations, type Translations } from './i18n/index.js';\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/i18n/en.json","../src/i18n/fr.json","../src/i18n/index.ts","../src/widget.ts","../src/styles.ts","../src/index.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["import { z } from 'zod';\n\n/**\n * Issue subtype definition\n */\nexport const IssueSubtypeSchema = z.object({\n /** Unique identifier for the subtype */\n id: z.string().min(1),\n /** Display label for the subtype */\n label: z.string().min(1),\n});\n\n/**\n * Issue type definition with optional subtypes\n */\nexport const IssueTypeSchema = z.object({\n /** Unique identifier for the issue type */\n id: z.string().min(1),\n /** Display label for the issue type */\n label: z.string().min(1),\n /** Optional subtypes that appear when this type is selected */\n subtypes: z.array(IssueSubtypeSchema).optional(),\n});\n\n/**\n * Metadata options - what to include with feedback submissions\n */\nexport const MetadataOptionsSchema = z.object({\n /** Include the course ID from LRS bridge (if available) */\n courseId: z.boolean().default(true),\n /** Include the current lesson/page ID (URL hash or pathname) */\n lessonId: z.boolean().default(true),\n /** Include the browser user agent */\n userAgent: z.boolean().default(true),\n /** Include timestamp of submission */\n timestamp: z.boolean().default(true),\n /** Include the full current URL */\n url: z.boolean().default(true),\n});\n\n/**\n * Default issue types if none are provided\n */\nexport const DEFAULT_ISSUE_TYPES: z.infer<typeof IssueTypeSchema>[] = [\n {\n id: 'content',\n label: 'Content Issue',\n subtypes: [\n { id: 'typo', label: 'Typo / Grammar' },\n { id: 'incorrect', label: 'Incorrect Information' },\n { id: 'unclear', label: 'Unclear / Confusing' },\n { id: 'outdated', label: 'Outdated Content' },\n ],\n },\n {\n id: 'technical',\n label: 'Technical Issue',\n subtypes: [\n { id: 'audio', label: 'Audio Problem' },\n { id: 'video', label: 'Video Problem' },\n { id: 'navigation', label: 'Navigation Issue' },\n { id: 'display', label: 'Display / Layout Issue' },\n ],\n },\n {\n id: 'suggestion',\n label: 'Suggestion',\n },\n {\n id: 'other',\n label: 'Other',\n },\n];\n\n/**\n * Full feedback plugin configuration schema\n */\nexport const FeedbackConfigSchema = z.object({\n /** Whether the feedback plugin is enabled */\n enabled: z.boolean().default(true),\n\n // === Endpoint Configuration ===\n\n /** API endpoint URL for submitting feedback (optional - if not set, logs to console) */\n endpoint: z.string().url().optional(),\n\n /** HTTP method for the endpoint (default: POST) */\n method: z.enum(['POST', 'PUT']).default('POST'),\n\n /** Additional headers to send with the request */\n headers: z.record(z.string()).optional(),\n\n // === Appearance ===\n\n /** Position of the feedback tab (left or right side of screen) */\n position: z.enum(['left', 'right']).default('right'),\n\n /** Text displayed on the feedback tab */\n tabText: z.string().default('Feedback'),\n\n /** Background color of the feedback tab */\n tabColor: z.string().default('#da291c'),\n\n /** Text color of the feedback tab */\n tabTextColor: z.string().default('#ffffff'),\n\n /** Z-index for the feedback widget (default: 9999) */\n zIndex: z.number().default(9999),\n\n // === Form Fields ===\n\n /** Show star rating field */\n showRating: z.boolean().default(true),\n\n /** Whether rating is required to submit */\n ratingRequired: z.boolean().default(false),\n\n /** Number of stars in the rating (default: 5) */\n ratingStars: z.number().min(3).max(10).default(5),\n\n /** Show issue type dropdown */\n showIssueType: z.boolean().default(true),\n\n /** Whether issue type is required to submit */\n issueTypeRequired: z.boolean().default(false),\n\n /** Available issue types (uses defaults if not provided) */\n issueTypes: z.array(IssueTypeSchema).optional(),\n\n /** Show comment textarea */\n showComment: z.boolean().default(true),\n\n /** Whether comment is required to submit */\n commentRequired: z.boolean().default(false),\n\n /** Maximum length for comments (default: 500) */\n commentMaxLength: z.number().min(50).max(5000).default(500),\n\n /** Placeholder text for comment field (uses translation if not set) */\n commentPlaceholder: z.string().optional(),\n\n // === Language / i18n ===\n\n /** Locale for UI text (en or fr) */\n locale: z.enum(['en', 'fr']).default('en'),\n\n /** Custom translations (overrides built-in translations) */\n translations: z.record(z.string()).optional(),\n\n // === Metadata ===\n\n /** What metadata to include with feedback submissions */\n includeMetadata: MetadataOptionsSchema.default({}),\n\n // === Behavior ===\n\n /** Auto-close modal after successful submission (default: true) */\n autoClose: z.boolean().default(true),\n\n /** Delay in ms before auto-closing after success (default: 2000) */\n autoCloseDelay: z.number().min(500).max(10000).default(2000),\n\n /** Enable debug logging (default: false) */\n debug: z.boolean().default(false),\n});\n\nexport type FeedbackConfig = z.infer<typeof FeedbackConfigSchema>;\nexport type IssueType = z.infer<typeof IssueTypeSchema>;\nexport type IssueSubtype = z.infer<typeof IssueSubtypeSchema>;\nexport type MetadataOptions = z.infer<typeof MetadataOptionsSchema>;\n","{\n \"title\": \"Send Feedback\",\n \"ratingLabel\": \"How would you rate this content?\",\n \"issueTypeLabel\": \"What type of feedback?\",\n \"selectIssueType\": \"Select type...\",\n \"subtypeLabel\": \"More specifically:\",\n \"selectSubtype\": \"Select...\",\n \"commentLabel\": \"Your feedback\",\n \"commentPlaceholder\": \"Please describe your feedback in detail...\",\n \"submit\": \"Send Feedback\",\n \"submitting\": \"Sending...\",\n \"thankYou\": \"Thank you for your feedback!\",\n \"errorSubmitting\": \"Failed to send feedback. Please try again.\",\n \"errorRequired\": \"Please fill in the required fields.\",\n \"characterCount\": \"{current}/{max}\"\n}\n","{\n \"title\": \"Envoyer un commentaire\",\n \"ratingLabel\": \"Comment évaluez-vous ce contenu?\",\n \"issueTypeLabel\": \"Type de commentaire\",\n \"selectIssueType\": \"Sélectionner...\",\n \"subtypeLabel\": \"Plus précisément:\",\n \"selectSubtype\": \"Sélectionner...\",\n \"commentLabel\": \"Votre commentaire\",\n \"commentPlaceholder\": \"Veuillez décrire votre commentaire en détail...\",\n \"submit\": \"Envoyer\",\n \"submitting\": \"Envoi en cours...\",\n \"thankYou\": \"Merci pour votre commentaire!\",\n \"errorSubmitting\": \"Échec de l'envoi. Veuillez réessayer.\",\n \"errorRequired\": \"Veuillez remplir les champs obligatoires.\",\n \"characterCount\": \"{current}/{max}\"\n}\n","import en from './en.json';\nimport fr from './fr.json';\n\nexport interface Translations {\n title: string;\n ratingLabel: string;\n issueTypeLabel: string;\n selectIssueType: string;\n subtypeLabel: string;\n selectSubtype: string;\n commentLabel: string;\n commentPlaceholder: string;\n submit: string;\n submitting: string;\n thankYou: string;\n errorSubmitting: string;\n errorRequired: string;\n characterCount: string;\n}\n\nexport const translations: Record<string, Translations> = {\n en: en as Translations,\n fr: fr as Translations,\n};\n\nexport function getTranslations(locale: string, overrides?: Record<string, string>): Translations {\n const base = translations[locale] || translations.en;\n if (overrides) {\n return { ...base, ...overrides } as Translations;\n }\n return base;\n}\n\nexport { en, fr };\n","import type { FeedbackConfig, IssueType } from './config.js';\nimport { DEFAULT_ISSUE_TYPES } from './config.js';\nimport { getTranslations } from './i18n/index.js';\n\n/**\n * Generate the feedback widget JavaScript code.\n * This produces a self-contained IIFE that creates and manages the feedback widget.\n */\nexport function generateFeedbackWidget(config: FeedbackConfig): string {\n const t = getTranslations(config.locale, config.translations);\n const issueTypes = config.issueTypes || DEFAULT_ISSUE_TYPES;\n\n return `\n(function() {\n 'use strict';\n\n // ============================================================================\n // FEEDBACK WIDGET - Patch-Adams Plugin v1.0.0\n // ============================================================================\n\n var FEEDBACK = window.pa_patcher = window.pa_patcher || {};\n FEEDBACK.feedback = {\n version: '1.0.0',\n isOpen: false,\n rating: 0,\n config: ${JSON.stringify({\n endpoint: config.endpoint,\n method: config.method,\n headers: config.headers,\n position: config.position,\n showRating: config.showRating,\n ratingRequired: config.ratingRequired,\n ratingStars: config.ratingStars,\n showIssueType: config.showIssueType,\n issueTypeRequired: config.issueTypeRequired,\n showComment: config.showComment,\n commentRequired: config.commentRequired,\n commentMaxLength: config.commentMaxLength,\n autoClose: config.autoClose,\n autoCloseDelay: config.autoCloseDelay,\n debug: config.debug,\n includeMetadata: config.includeMetadata,\n })},\n translations: ${JSON.stringify(t)},\n issueTypes: ${JSON.stringify(issueTypes)},\n };\n\n var FB = FEEDBACK.feedback;\n\n function log() {\n if (FB.config.debug) {\n console.log.apply(console, ['[PA-Feedback]'].concat(Array.prototype.slice.call(arguments)));\n }\n }\n\n // ============================================================================\n // DOM CREATION\n // ============================================================================\n\n function createWidget() {\n var container = document.createElement('div');\n container.id = 'pa-feedback-container';\n container.className = 'pa-feedback-${config.position}';\n container.innerHTML = buildWidgetHtml();\n document.body.appendChild(container);\n setupEventListeners();\n log('Widget created');\n }\n\n function buildWidgetHtml() {\n var html = '';\n\n // Tab button\n html += '<button id=\"pa-feedback-tab\" class=\"pa-feedback-tab\" aria-label=\"' + FB.translations.title + '\">';\n html += '<span class=\"pa-feedback-tab-text\">${config.tabText}</span>';\n html += '</button>';\n\n // Modal\n html += '<div id=\"pa-feedback-modal\" class=\"pa-feedback-modal pa-feedback-hidden\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"pa-feedback-title\">';\n html += '<div class=\"pa-feedback-content\">';\n\n // Header\n html += '<div class=\"pa-feedback-header\">';\n html += '<h3 id=\"pa-feedback-title\">' + FB.translations.title + '</h3>';\n html += '<button id=\"pa-feedback-close\" class=\"pa-feedback-close\" aria-label=\"Close\">×</button>';\n html += '</div>';\n\n // Form\n html += '<form id=\"pa-feedback-form\">';\n\n // Rating (if enabled)\n ${config.showRating ? `\n html += '<div class=\"pa-feedback-field\">';\n html += '<label class=\"pa-feedback-label\">' + FB.translations.ratingLabel + '${config.ratingRequired ? ' <span class=\"pa-feedback-required\">*</span>' : ''}</label>';\n html += '<div class=\"pa-feedback-stars\" role=\"radiogroup\" aria-label=\"Rating\">';\n for (var i = 1; i <= ${config.ratingStars}; i++) {\n html += '<button type=\"button\" class=\"pa-feedback-star\" data-value=\"' + i + '\" role=\"radio\" aria-checked=\"false\" aria-label=\"' + i + ' star\">☆</button>';\n }\n html += '</div>';\n html += '</div>';\n ` : ''}\n\n // Issue Type (if enabled)\n ${config.showIssueType ? `\n html += '<div class=\"pa-feedback-field\">';\n html += '<label class=\"pa-feedback-label\" for=\"pa-feedback-issue-type\">' + FB.translations.issueTypeLabel + '${config.issueTypeRequired ? ' <span class=\"pa-feedback-required\">*</span>' : ''}</label>';\n html += '<select id=\"pa-feedback-issue-type\" class=\"pa-feedback-select\">';\n html += '<option value=\"\">' + FB.translations.selectIssueType + '</option>';\n FB.issueTypes.forEach(function(type) {\n html += '<option value=\"' + type.id + '\">' + type.label + '</option>';\n });\n html += '</select>';\n html += '</div>';\n\n // Subtype container (hidden by default)\n html += '<div id=\"pa-feedback-subtype-field\" class=\"pa-feedback-field pa-feedback-hidden\">';\n html += '<label class=\"pa-feedback-label\" for=\"pa-feedback-subtype\">' + FB.translations.subtypeLabel + '</label>';\n html += '<select id=\"pa-feedback-subtype\" class=\"pa-feedback-select\">';\n html += '<option value=\"\">' + FB.translations.selectSubtype + '</option>';\n html += '</select>';\n html += '</div>';\n ` : ''}\n\n // Comment (if enabled)\n ${config.showComment ? `\n html += '<div class=\"pa-feedback-field\">';\n html += '<label class=\"pa-feedback-label\" for=\"pa-feedback-comment\">' + FB.translations.commentLabel + '${config.commentRequired ? ' <span class=\"pa-feedback-required\">*</span>' : ''}</label>';\n html += '<textarea id=\"pa-feedback-comment\" class=\"pa-feedback-textarea\" maxlength=\"${config.commentMaxLength}\" placeholder=\"${config.commentPlaceholder || ''}\" rows=\"4\"></textarea>';\n html += '<div class=\"pa-feedback-counter\"><span id=\"pa-feedback-char-count\">0</span>/${config.commentMaxLength}</div>';\n html += '</div>';\n ` : ''}\n\n // Error message area\n html += '<div id=\"pa-feedback-error\" class=\"pa-feedback-error pa-feedback-hidden\"></div>';\n\n // Submit button\n html += '<button type=\"submit\" id=\"pa-feedback-submit\" class=\"pa-feedback-submit\">';\n html += '<span class=\"pa-feedback-submit-text\">' + FB.translations.submit + '</span>';\n html += '<span class=\"pa-feedback-submit-loading pa-feedback-hidden\">' + FB.translations.submitting + '</span>';\n html += '</button>';\n\n html += '</form>';\n\n // Success message\n html += '<div id=\"pa-feedback-success\" class=\"pa-feedback-success pa-feedback-hidden\">';\n html += '<div class=\"pa-feedback-checkmark\">✓</div>';\n html += '<p>' + FB.translations.thankYou + '</p>';\n html += '</div>';\n\n html += '</div>'; // content\n html += '</div>'; // modal\n\n return html;\n }\n\n // ============================================================================\n // EVENT HANDLERS\n // ============================================================================\n\n function setupEventListeners() {\n // Tab click\n document.getElementById('pa-feedback-tab').addEventListener('click', toggleModal);\n\n // Close button\n document.getElementById('pa-feedback-close').addEventListener('click', closeModal);\n\n // Form submit\n document.getElementById('pa-feedback-form').addEventListener('submit', handleSubmit);\n\n // Click outside to close\n document.getElementById('pa-feedback-modal').addEventListener('click', function(e) {\n if (e.target === this) closeModal();\n });\n\n // Escape key to close\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape' && FB.isOpen) closeModal();\n });\n\n ${config.showRating ? `\n // Star rating\n var stars = document.querySelectorAll('.pa-feedback-star');\n stars.forEach(function(star, index) {\n star.addEventListener('click', function() {\n FB.rating = index + 1;\n updateStars();\n });\n star.addEventListener('mouseenter', function() {\n highlightStars(index + 1);\n });\n });\n document.querySelector('.pa-feedback-stars').addEventListener('mouseleave', function() {\n highlightStars(FB.rating);\n });\n ` : ''}\n\n ${config.showIssueType ? `\n // Issue type change\n document.getElementById('pa-feedback-issue-type').addEventListener('change', updateSubtypes);\n ` : ''}\n\n ${config.showComment ? `\n // Character counter\n document.getElementById('pa-feedback-comment').addEventListener('input', updateCharCount);\n ` : ''}\n }\n\n function toggleModal() {\n if (FB.isOpen) {\n closeModal();\n } else {\n openModal();\n }\n }\n\n function openModal() {\n FB.isOpen = true;\n document.getElementById('pa-feedback-modal').classList.remove('pa-feedback-hidden');\n document.getElementById('pa-feedback-tab').classList.add('pa-feedback-tab-active');\n log('Modal opened');\n }\n\n function closeModal() {\n FB.isOpen = false;\n document.getElementById('pa-feedback-modal').classList.add('pa-feedback-hidden');\n document.getElementById('pa-feedback-tab').classList.remove('pa-feedback-tab-active');\n log('Modal closed');\n }\n\n ${config.showRating ? `\n function updateStars() {\n var stars = document.querySelectorAll('.pa-feedback-star');\n stars.forEach(function(star, index) {\n var isFilled = index < FB.rating;\n star.innerHTML = isFilled ? '★' : '☆';\n star.classList.toggle('pa-feedback-star-filled', isFilled);\n star.setAttribute('aria-checked', isFilled ? 'true' : 'false');\n });\n }\n\n function highlightStars(count) {\n var stars = document.querySelectorAll('.pa-feedback-star');\n stars.forEach(function(star, index) {\n var isFilled = index < count;\n star.innerHTML = isFilled ? '★' : '☆';\n star.classList.toggle('pa-feedback-star-hover', isFilled && count > FB.rating);\n });\n }\n ` : ''}\n\n ${config.showIssueType ? `\n function updateSubtypes() {\n var typeSelect = document.getElementById('pa-feedback-issue-type');\n var subtypeField = document.getElementById('pa-feedback-subtype-field');\n var subtypeSelect = document.getElementById('pa-feedback-subtype');\n var selectedType = typeSelect.value;\n\n // Find the selected issue type\n var issueType = FB.issueTypes.find(function(t) { return t.id === selectedType; });\n\n if (issueType && issueType.subtypes && issueType.subtypes.length > 0) {\n // Populate subtypes\n subtypeSelect.innerHTML = '<option value=\"\">' + FB.translations.selectSubtype + '</option>';\n issueType.subtypes.forEach(function(subtype) {\n subtypeSelect.innerHTML += '<option value=\"' + subtype.id + '\">' + subtype.label + '</option>';\n });\n subtypeField.classList.remove('pa-feedback-hidden');\n } else {\n subtypeField.classList.add('pa-feedback-hidden');\n subtypeSelect.value = '';\n }\n }\n ` : ''}\n\n ${config.showComment ? `\n function updateCharCount() {\n var textarea = document.getElementById('pa-feedback-comment');\n var counter = document.getElementById('pa-feedback-char-count');\n counter.textContent = textarea.value.length;\n }\n ` : ''}\n\n // ============================================================================\n // FORM SUBMISSION\n // ============================================================================\n\n function validateForm() {\n var errors = [];\n\n ${config.showRating && config.ratingRequired ? `\n if (FB.rating === 0) {\n errors.push('Rating is required');\n }\n ` : ''}\n\n ${config.showIssueType && config.issueTypeRequired ? `\n if (!document.getElementById('pa-feedback-issue-type').value) {\n errors.push('Issue type is required');\n }\n ` : ''}\n\n ${config.showComment && config.commentRequired ? `\n if (!document.getElementById('pa-feedback-comment').value.trim()) {\n errors.push('Comment is required');\n }\n ` : ''}\n\n return errors;\n }\n\n function collectFormData() {\n var data = {};\n\n ${config.showRating ? `data.rating = FB.rating;` : ''}\n ${config.showIssueType ? `\n data.issueType = document.getElementById('pa-feedback-issue-type').value || null;\n data.issueSubtype = document.getElementById('pa-feedback-subtype').value || null;\n ` : ''}\n ${config.showComment ? `data.comment = document.getElementById('pa-feedback-comment').value.trim();` : ''}\n\n // Add metadata\n data.metadata = collectMetadata();\n\n return data;\n }\n\n function collectMetadata() {\n var meta = {};\n var cfg = FB.config.includeMetadata;\n\n if (cfg.courseId && window.pa_patcher && window.pa_patcher.lrs && window.pa_patcher.lrs.courseInfo) {\n meta.courseId = window.pa_patcher.lrs.courseInfo.id;\n meta.courseTitle = window.pa_patcher.lrs.courseInfo.title;\n }\n\n if (cfg.lessonId) {\n meta.lessonId = window.location.hash || window.location.pathname;\n }\n\n if (cfg.userAgent) {\n meta.userAgent = navigator.userAgent;\n }\n\n if (cfg.timestamp) {\n meta.timestamp = new Date().toISOString();\n }\n\n if (cfg.url) {\n meta.url = window.location.href;\n }\n\n return meta;\n }\n\n function showError(message) {\n var errorEl = document.getElementById('pa-feedback-error');\n errorEl.textContent = message;\n errorEl.classList.remove('pa-feedback-hidden');\n }\n\n function hideError() {\n document.getElementById('pa-feedback-error').classList.add('pa-feedback-hidden');\n }\n\n function setSubmitting(isSubmitting) {\n var submitBtn = document.getElementById('pa-feedback-submit');\n var textEl = submitBtn.querySelector('.pa-feedback-submit-text');\n var loadingEl = submitBtn.querySelector('.pa-feedback-submit-loading');\n\n submitBtn.disabled = isSubmitting;\n textEl.classList.toggle('pa-feedback-hidden', isSubmitting);\n loadingEl.classList.toggle('pa-feedback-hidden', !isSubmitting);\n }\n\n function showSuccess() {\n document.getElementById('pa-feedback-form').classList.add('pa-feedback-hidden');\n document.getElementById('pa-feedback-success').classList.remove('pa-feedback-hidden');\n\n if (FB.config.autoClose) {\n setTimeout(function() {\n closeModal();\n resetForm();\n }, FB.config.autoCloseDelay);\n }\n }\n\n function resetForm() {\n var form = document.getElementById('pa-feedback-form');\n form.reset();\n form.classList.remove('pa-feedback-hidden');\n document.getElementById('pa-feedback-success').classList.add('pa-feedback-hidden');\n hideError();\n\n FB.rating = 0;\n ${config.showRating ? 'updateStars();' : ''}\n ${config.showComment ? 'updateCharCount();' : ''}\n ${config.showIssueType ? `\n document.getElementById('pa-feedback-subtype-field').classList.add('pa-feedback-hidden');\n ` : ''}\n }\n\n async function handleSubmit(e) {\n e.preventDefault();\n hideError();\n\n // Validate\n var errors = validateForm();\n if (errors.length > 0) {\n showError(FB.translations.errorRequired);\n return;\n }\n\n // Collect data\n var data = collectFormData();\n log('Submitting:', data);\n\n // Submit\n setSubmitting(true);\n\n try {\n ${config.endpoint ? `\n var response = await fetch('${config.endpoint}', {\n method: '${config.method}',\n headers: Object.assign({\n 'Content-Type': 'application/json',\n }, FB.config.headers || {}),\n body: JSON.stringify(data),\n });\n\n if (!response.ok) {\n throw new Error('HTTP ' + response.status);\n }\n\n log('Submitted successfully');\n ` : `\n // No endpoint configured - just log\n console.log('[PA-Feedback] Feedback submitted:', data);\n log('No endpoint configured, feedback logged to console');\n `}\n\n showSuccess();\n } catch (err) {\n log('Submit error:', err);\n showError(FB.translations.errorSubmitting);\n } finally {\n setSubmitting(false);\n }\n }\n\n // ============================================================================\n // INITIALIZATION\n // ============================================================================\n\n function init() {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', createWidget);\n } else {\n createWidget();\n }\n log('Initialized');\n }\n\n init();\n\n})();\n`;\n}\n","import type { FeedbackConfig } from './config.js';\n\n/**\n * Generate the CSS styles for the feedback widget.\n * Styles are scoped with #pa-feedback-container to avoid conflicts.\n */\nexport function generateFeedbackStyles(config: FeedbackConfig): string {\n const position = config.position;\n const tabColor = config.tabColor;\n const tabTextColor = config.tabTextColor;\n const zIndex = config.zIndex;\n\n // Pre-compute position-dependent values\n const isRight = position === 'right';\n const tabTransform = isRight ? '-90deg' : '90deg';\n const tabTransformOrigin = isRight ? 'right center' : 'left center';\n const tabOffset = isRight ? 'right: 20px; left: auto;' : 'left: 20px; right: auto;';\n const tabBorderRadius = isRight ? '8px 8px 0 0' : '0 0 8px 8px';\n const modalPosition = isRight ? 'right: 0; left: auto;' : 'left: 0; right: auto;';\n const modalJustify = isRight ? 'flex-end' : 'flex-start';\n const contentShadow = isRight ? '-4px 0 20px rgba(0, 0, 0, 0.15)' : '4px 0 20px rgba(0, 0, 0, 0.15)';\n const slideFrom = isRight ? '100%' : '-100%';\n\n return `\n/* ============================================================================\n FEEDBACK WIDGET STYLES - Patch-Adams Plugin v1.0.0\n ============================================================================ */\n\n#pa-feedback-container {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: #333;\n box-sizing: border-box;\n}\n\n#pa-feedback-container *,\n#pa-feedback-container *::before,\n#pa-feedback-container *::after {\n box-sizing: inherit;\n}\n\n/* Hidden utility class */\n#pa-feedback-container .pa-feedback-hidden {\n display: none !important;\n}\n\n/* ============================================================================\n TAB BUTTON\n ============================================================================ */\n\n#pa-feedback-tab {\n position: fixed;\n top: 50%;\n ${tabOffset}\n transform: translateY(-50%) rotate(${tabTransform});\n transform-origin: ${tabTransformOrigin};\n z-index: ${zIndex};\n background: ${tabColor};\n color: ${tabTextColor};\n border: none;\n padding: 10px 20px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n border-radius: ${tabBorderRadius};\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n#pa-feedback-tab:hover {\n background: ${adjustColor(tabColor, -15)};\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n}\n\n#pa-feedback-tab:focus {\n outline: 2px solid ${tabColor};\n outline-offset: 2px;\n}\n\n#pa-feedback-tab.pa-feedback-tab-active {\n background: ${adjustColor(tabColor, -20)};\n}\n\n/* ============================================================================\n MODAL\n ============================================================================ */\n\n#pa-feedback-modal {\n position: fixed;\n top: 0;\n ${modalPosition}\n width: 360px;\n height: 100%;\n z-index: ${zIndex + 1};\n background: rgba(0, 0, 0, 0.3);\n display: flex;\n justify-content: ${modalJustify};\n animation: pa-feedback-fade-in 0.2s ease;\n}\n\n@keyframes pa-feedback-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n#pa-feedback-container .pa-feedback-content {\n width: 100%;\n max-width: 360px;\n height: 100%;\n background: #fff;\n box-shadow: ${contentShadow};\n display: flex;\n flex-direction: column;\n animation: pa-feedback-slide-in 0.2s ease;\n}\n\n@keyframes pa-feedback-slide-in {\n from {\n transform: translateX(${slideFrom});\n }\n to {\n transform: translateX(0);\n }\n}\n\n/* ============================================================================\n HEADER\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid #e5e5e5;\n background: #fafafa;\n}\n\n#pa-feedback-container .pa-feedback-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #222;\n}\n\n#pa-feedback-container .pa-feedback-close {\n background: none;\n border: none;\n font-size: 24px;\n color: #666;\n cursor: pointer;\n padding: 4px 8px;\n line-height: 1;\n border-radius: 4px;\n transition: all 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-close:hover {\n background: #e5e5e5;\n color: #333;\n}\n\n/* ============================================================================\n FORM\n ============================================================================ */\n\n#pa-feedback-form {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n#pa-feedback-container .pa-feedback-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n#pa-feedback-container .pa-feedback-label {\n font-weight: 500;\n color: #444;\n font-size: 14px;\n}\n\n#pa-feedback-container .pa-feedback-required {\n color: #dc3545;\n}\n\n/* ============================================================================\n STAR RATING\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-stars {\n display: flex;\n gap: 4px;\n}\n\n#pa-feedback-container .pa-feedback-star {\n background: none;\n border: none;\n font-size: 28px;\n color: #ccc;\n cursor: pointer;\n padding: 4px;\n line-height: 1;\n transition: all 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-star:hover {\n transform: scale(1.1);\n}\n\n#pa-feedback-container .pa-feedback-star-filled,\n#pa-feedback-container .pa-feedback-star-hover {\n color: #ffc107;\n}\n\n/* ============================================================================\n SELECT & TEXTAREA\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-select {\n width: 100%;\n padding: 10px 12px;\n font-size: 14px;\n border: 1px solid #ddd;\n border-radius: 6px;\n background: #fff;\n color: #333;\n cursor: pointer;\n transition: border-color 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-select:focus {\n outline: none;\n border-color: ${tabColor};\n box-shadow: 0 0 0 3px ${hexToRgba(tabColor, 0.1)};\n}\n\n#pa-feedback-container .pa-feedback-textarea {\n width: 100%;\n padding: 12px;\n font-size: 14px;\n font-family: inherit;\n border: 1px solid #ddd;\n border-radius: 6px;\n resize: vertical;\n min-height: 100px;\n transition: border-color 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-textarea:focus {\n outline: none;\n border-color: ${tabColor};\n box-shadow: 0 0 0 3px ${hexToRgba(tabColor, 0.1)};\n}\n\n#pa-feedback-container .pa-feedback-textarea::placeholder {\n color: #999;\n}\n\n#pa-feedback-container .pa-feedback-counter {\n text-align: right;\n font-size: 12px;\n color: #888;\n}\n\n/* ============================================================================\n ERROR MESSAGE\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-error {\n background: #fee2e2;\n color: #dc2626;\n padding: 10px 14px;\n border-radius: 6px;\n font-size: 13px;\n}\n\n/* ============================================================================\n SUBMIT BUTTON\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-submit {\n width: 100%;\n padding: 12px 20px;\n font-size: 16px;\n font-weight: 600;\n color: #fff;\n background: ${tabColor};\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n margin-top: auto;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n}\n\n#pa-feedback-container .pa-feedback-submit:hover:not(:disabled) {\n background: ${adjustColor(tabColor, -15)};\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n transform: translateY(-1px);\n}\n\n#pa-feedback-container .pa-feedback-submit:focus {\n outline: 2px solid ${tabColor};\n outline-offset: 2px;\n}\n\n#pa-feedback-container .pa-feedback-submit:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n}\n\n/* ============================================================================\n SUCCESS MESSAGE\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-success {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n\n#pa-feedback-container .pa-feedback-checkmark {\n width: 64px;\n height: 64px;\n background: #10b981;\n color: #fff;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 32px;\n margin-bottom: 20px;\n animation: pa-feedback-pop 0.3s ease;\n}\n\n@keyframes pa-feedback-pop {\n 0% { transform: scale(0); }\n 50% { transform: scale(1.2); }\n 100% { transform: scale(1); }\n}\n\n#pa-feedback-container .pa-feedback-success p {\n margin: 0;\n font-size: 18px;\n font-weight: 500;\n color: #333;\n}\n`;\n}\n\n/**\n * Adjust a hex color by a percentage (positive = lighter, negative = darker)\n */\nfunction adjustColor(hex: string, percent: number): string {\n // Remove # if present\n hex = hex.replace(/^#/, '');\n\n // Parse the color\n let r = parseInt(hex.substring(0, 2), 16);\n let g = parseInt(hex.substring(2, 4), 16);\n let b = parseInt(hex.substring(4, 6), 16);\n\n // Adjust\n r = Math.min(255, Math.max(0, r + (r * percent) / 100));\n g = Math.min(255, Math.max(0, g + (g * percent) / 100));\n b = Math.min(255, Math.max(0, b + (b * percent) / 100));\n\n // Convert back to hex\n return (\n '#' +\n Math.round(r).toString(16).padStart(2, '0') +\n Math.round(g).toString(16).padStart(2, '0') +\n Math.round(b).toString(16).padStart(2, '0')\n );\n}\n\n/**\n * Convert hex color to rgba\n */\nfunction hexToRgba(hex: string, alpha: number): string {\n hex = hex.replace(/^#/, '');\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n","/**\n * @patch-adams/plugin-feedback\n *\n * Feedback widget plugin for Patch-Adams.\n * Injects a customizable feedback form into patched Rise courses.\n *\n * Features:\n * - Star rating\n * - Issue type/subtype selection\n * - Comment text area\n * - Multi-language support (en/fr)\n * - Customizable appearance\n * - Automatic metadata collection\n * - Configurable API endpoint\n */\n\nimport type { PatchAdamsPlugin } from '@patch-adams/core';\nimport { FeedbackConfigSchema, type FeedbackConfig } from './config.js';\nimport { generateFeedbackWidget } from './widget.js';\nimport { generateFeedbackStyles } from './styles.js';\n\n/**\n * Feedback plugin for Patch-Adams\n */\nexport const feedbackPlugin: PatchAdamsPlugin<FeedbackConfig> = {\n name: 'feedback',\n version: '1.0.0',\n description: 'Inject a feedback form widget into Rise courses for collecting user feedback',\n configSchema: FeedbackConfigSchema,\n\n generateCss(config: FeedbackConfig) {\n return {\n after: generateFeedbackStyles(config),\n };\n },\n\n generateJs(config: FeedbackConfig) {\n return {\n after: generateFeedbackWidget(config),\n };\n },\n};\n\n// Default export for convenience\nexport default feedbackPlugin;\n\n// Re-export types and utilities\nexport {\n FeedbackConfigSchema,\n type FeedbackConfig,\n type IssueType,\n type IssueSubtype,\n type MetadataOptions,\n DEFAULT_ISSUE_TYPES,\n} from './config.js';\n\nexport { generateFeedbackWidget } from './widget.js';\nexport { generateFeedbackStyles } from './styles.js';\nexport { getTranslations, translations, type Translations } from './i18n/index.js';\n"]}
|
package/dist/index.js
CHANGED
|
@@ -73,7 +73,7 @@ var FeedbackConfigSchema = z.object({
|
|
|
73
73
|
/** Text displayed on the feedback tab */
|
|
74
74
|
tabText: z.string().default("Feedback"),
|
|
75
75
|
/** Background color of the feedback tab */
|
|
76
|
-
tabColor: z.string().default("#
|
|
76
|
+
tabColor: z.string().default("#da291c"),
|
|
77
77
|
/** Text color of the feedback tab */
|
|
78
78
|
tabTextColor: z.string().default("#ffffff"),
|
|
79
79
|
/** Z-index for the feedback widget (default: 9999) */
|
|
@@ -631,6 +631,15 @@ function generateFeedbackStyles(config) {
|
|
|
631
631
|
const tabColor = config.tabColor;
|
|
632
632
|
const tabTextColor = config.tabTextColor;
|
|
633
633
|
const zIndex = config.zIndex;
|
|
634
|
+
const isRight = position === "right";
|
|
635
|
+
const tabTransform = isRight ? "-90deg" : "90deg";
|
|
636
|
+
const tabTransformOrigin = isRight ? "right center" : "left center";
|
|
637
|
+
const tabOffset = isRight ? "right: 20px; left: auto;" : "left: 20px; right: auto;";
|
|
638
|
+
const tabBorderRadius = isRight ? "8px 8px 0 0" : "0 0 8px 8px";
|
|
639
|
+
const modalPosition = isRight ? "right: 0; left: auto;" : "left: 0; right: auto;";
|
|
640
|
+
const modalJustify = isRight ? "flex-end" : "flex-start";
|
|
641
|
+
const contentShadow = isRight ? "-4px 0 20px rgba(0, 0, 0, 0.15)" : "4px 0 20px rgba(0, 0, 0, 0.15)";
|
|
642
|
+
const slideFrom = isRight ? "100%" : "-100%";
|
|
634
643
|
return `
|
|
635
644
|
/* ============================================================================
|
|
636
645
|
FEEDBACK WIDGET STYLES - Patch-Adams Plugin v1.0.0
|
|
@@ -661,11 +670,10 @@ function generateFeedbackStyles(config) {
|
|
|
661
670
|
|
|
662
671
|
#pa-feedback-tab {
|
|
663
672
|
position: fixed;
|
|
664
|
-
${position}: 0;
|
|
665
673
|
top: 50%;
|
|
666
|
-
|
|
667
|
-
transform
|
|
668
|
-
|
|
674
|
+
${tabOffset}
|
|
675
|
+
transform: translateY(-50%) rotate(${tabTransform});
|
|
676
|
+
transform-origin: ${tabTransformOrigin};
|
|
669
677
|
z-index: ${zIndex};
|
|
670
678
|
background: ${tabColor};
|
|
671
679
|
color: ${tabTextColor};
|
|
@@ -674,7 +682,7 @@ function generateFeedbackStyles(config) {
|
|
|
674
682
|
font-size: 14px;
|
|
675
683
|
font-weight: 600;
|
|
676
684
|
cursor: pointer;
|
|
677
|
-
border-radius: ${
|
|
685
|
+
border-radius: ${tabBorderRadius};
|
|
678
686
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
679
687
|
transition: all 0.2s ease;
|
|
680
688
|
white-space: nowrap;
|
|
@@ -700,14 +708,14 @@ function generateFeedbackStyles(config) {
|
|
|
700
708
|
|
|
701
709
|
#pa-feedback-modal {
|
|
702
710
|
position: fixed;
|
|
703
|
-
${position}: 0;
|
|
704
711
|
top: 0;
|
|
712
|
+
${modalPosition}
|
|
705
713
|
width: 360px;
|
|
706
714
|
height: 100%;
|
|
707
715
|
z-index: ${zIndex + 1};
|
|
708
716
|
background: rgba(0, 0, 0, 0.3);
|
|
709
717
|
display: flex;
|
|
710
|
-
justify-content:
|
|
718
|
+
justify-content: ${modalJustify};
|
|
711
719
|
animation: pa-feedback-fade-in 0.2s ease;
|
|
712
720
|
}
|
|
713
721
|
|
|
@@ -721,7 +729,7 @@ function generateFeedbackStyles(config) {
|
|
|
721
729
|
max-width: 360px;
|
|
722
730
|
height: 100%;
|
|
723
731
|
background: #fff;
|
|
724
|
-
box-shadow: ${
|
|
732
|
+
box-shadow: ${contentShadow};
|
|
725
733
|
display: flex;
|
|
726
734
|
flex-direction: column;
|
|
727
735
|
animation: pa-feedback-slide-in 0.2s ease;
|
|
@@ -729,7 +737,7 @@ function generateFeedbackStyles(config) {
|
|
|
729
737
|
|
|
730
738
|
@keyframes pa-feedback-slide-in {
|
|
731
739
|
from {
|
|
732
|
-
transform: translateX(${
|
|
740
|
+
transform: translateX(${slideFrom});
|
|
733
741
|
}
|
|
734
742
|
to {
|
|
735
743
|
transform: translateX(0);
|
|
@@ -909,10 +917,13 @@ function generateFeedbackStyles(config) {
|
|
|
909
917
|
cursor: pointer;
|
|
910
918
|
transition: all 0.15s ease;
|
|
911
919
|
margin-top: auto;
|
|
920
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
912
921
|
}
|
|
913
922
|
|
|
914
923
|
#pa-feedback-container .pa-feedback-submit:hover:not(:disabled) {
|
|
915
924
|
background: ${adjustColor(tabColor, -15)};
|
|
925
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
926
|
+
transform: translateY(-1px);
|
|
916
927
|
}
|
|
917
928
|
|
|
918
929
|
#pa-feedback-container .pa-feedback-submit:focus {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/i18n/en.json","../src/i18n/fr.json","../src/i18n/index.ts","../src/widget.ts","../src/styles.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { z } from 'zod';\n\n/**\n * Issue subtype definition\n */\nexport const IssueSubtypeSchema = z.object({\n /** Unique identifier for the subtype */\n id: z.string().min(1),\n /** Display label for the subtype */\n label: z.string().min(1),\n});\n\n/**\n * Issue type definition with optional subtypes\n */\nexport const IssueTypeSchema = z.object({\n /** Unique identifier for the issue type */\n id: z.string().min(1),\n /** Display label for the issue type */\n label: z.string().min(1),\n /** Optional subtypes that appear when this type is selected */\n subtypes: z.array(IssueSubtypeSchema).optional(),\n});\n\n/**\n * Metadata options - what to include with feedback submissions\n */\nexport const MetadataOptionsSchema = z.object({\n /** Include the course ID from LRS bridge (if available) */\n courseId: z.boolean().default(true),\n /** Include the current lesson/page ID (URL hash or pathname) */\n lessonId: z.boolean().default(true),\n /** Include the browser user agent */\n userAgent: z.boolean().default(true),\n /** Include timestamp of submission */\n timestamp: z.boolean().default(true),\n /** Include the full current URL */\n url: z.boolean().default(true),\n});\n\n/**\n * Default issue types if none are provided\n */\nexport const DEFAULT_ISSUE_TYPES: z.infer<typeof IssueTypeSchema>[] = [\n {\n id: 'content',\n label: 'Content Issue',\n subtypes: [\n { id: 'typo', label: 'Typo / Grammar' },\n { id: 'incorrect', label: 'Incorrect Information' },\n { id: 'unclear', label: 'Unclear / Confusing' },\n { id: 'outdated', label: 'Outdated Content' },\n ],\n },\n {\n id: 'technical',\n label: 'Technical Issue',\n subtypes: [\n { id: 'audio', label: 'Audio Problem' },\n { id: 'video', label: 'Video Problem' },\n { id: 'navigation', label: 'Navigation Issue' },\n { id: 'display', label: 'Display / Layout Issue' },\n ],\n },\n {\n id: 'suggestion',\n label: 'Suggestion',\n },\n {\n id: 'other',\n label: 'Other',\n },\n];\n\n/**\n * Full feedback plugin configuration schema\n */\nexport const FeedbackConfigSchema = z.object({\n /** Whether the feedback plugin is enabled */\n enabled: z.boolean().default(true),\n\n // === Endpoint Configuration ===\n\n /** API endpoint URL for submitting feedback (optional - if not set, logs to console) */\n endpoint: z.string().url().optional(),\n\n /** HTTP method for the endpoint (default: POST) */\n method: z.enum(['POST', 'PUT']).default('POST'),\n\n /** Additional headers to send with the request */\n headers: z.record(z.string()).optional(),\n\n // === Appearance ===\n\n /** Position of the feedback tab (left or right side of screen) */\n position: z.enum(['left', 'right']).default('right'),\n\n /** Text displayed on the feedback tab */\n tabText: z.string().default('Feedback'),\n\n /** Background color of the feedback tab */\n tabColor: z.string().default('#007bff'),\n\n /** Text color of the feedback tab */\n tabTextColor: z.string().default('#ffffff'),\n\n /** Z-index for the feedback widget (default: 9999) */\n zIndex: z.number().default(9999),\n\n // === Form Fields ===\n\n /** Show star rating field */\n showRating: z.boolean().default(true),\n\n /** Whether rating is required to submit */\n ratingRequired: z.boolean().default(false),\n\n /** Number of stars in the rating (default: 5) */\n ratingStars: z.number().min(3).max(10).default(5),\n\n /** Show issue type dropdown */\n showIssueType: z.boolean().default(true),\n\n /** Whether issue type is required to submit */\n issueTypeRequired: z.boolean().default(false),\n\n /** Available issue types (uses defaults if not provided) */\n issueTypes: z.array(IssueTypeSchema).optional(),\n\n /** Show comment textarea */\n showComment: z.boolean().default(true),\n\n /** Whether comment is required to submit */\n commentRequired: z.boolean().default(false),\n\n /** Maximum length for comments (default: 500) */\n commentMaxLength: z.number().min(50).max(5000).default(500),\n\n /** Placeholder text for comment field (uses translation if not set) */\n commentPlaceholder: z.string().optional(),\n\n // === Language / i18n ===\n\n /** Locale for UI text (en or fr) */\n locale: z.enum(['en', 'fr']).default('en'),\n\n /** Custom translations (overrides built-in translations) */\n translations: z.record(z.string()).optional(),\n\n // === Metadata ===\n\n /** What metadata to include with feedback submissions */\n includeMetadata: MetadataOptionsSchema.default({}),\n\n // === Behavior ===\n\n /** Auto-close modal after successful submission (default: true) */\n autoClose: z.boolean().default(true),\n\n /** Delay in ms before auto-closing after success (default: 2000) */\n autoCloseDelay: z.number().min(500).max(10000).default(2000),\n\n /** Enable debug logging (default: false) */\n debug: z.boolean().default(false),\n});\n\nexport type FeedbackConfig = z.infer<typeof FeedbackConfigSchema>;\nexport type IssueType = z.infer<typeof IssueTypeSchema>;\nexport type IssueSubtype = z.infer<typeof IssueSubtypeSchema>;\nexport type MetadataOptions = z.infer<typeof MetadataOptionsSchema>;\n","{\n \"title\": \"Send Feedback\",\n \"ratingLabel\": \"How would you rate this content?\",\n \"issueTypeLabel\": \"What type of feedback?\",\n \"selectIssueType\": \"Select type...\",\n \"subtypeLabel\": \"More specifically:\",\n \"selectSubtype\": \"Select...\",\n \"commentLabel\": \"Your feedback\",\n \"commentPlaceholder\": \"Please describe your feedback in detail...\",\n \"submit\": \"Send Feedback\",\n \"submitting\": \"Sending...\",\n \"thankYou\": \"Thank you for your feedback!\",\n \"errorSubmitting\": \"Failed to send feedback. Please try again.\",\n \"errorRequired\": \"Please fill in the required fields.\",\n \"characterCount\": \"{current}/{max}\"\n}\n","{\n \"title\": \"Envoyer un commentaire\",\n \"ratingLabel\": \"Comment évaluez-vous ce contenu?\",\n \"issueTypeLabel\": \"Type de commentaire\",\n \"selectIssueType\": \"Sélectionner...\",\n \"subtypeLabel\": \"Plus précisément:\",\n \"selectSubtype\": \"Sélectionner...\",\n \"commentLabel\": \"Votre commentaire\",\n \"commentPlaceholder\": \"Veuillez décrire votre commentaire en détail...\",\n \"submit\": \"Envoyer\",\n \"submitting\": \"Envoi en cours...\",\n \"thankYou\": \"Merci pour votre commentaire!\",\n \"errorSubmitting\": \"Échec de l'envoi. Veuillez réessayer.\",\n \"errorRequired\": \"Veuillez remplir les champs obligatoires.\",\n \"characterCount\": \"{current}/{max}\"\n}\n","import en from './en.json';\nimport fr from './fr.json';\n\nexport interface Translations {\n title: string;\n ratingLabel: string;\n issueTypeLabel: string;\n selectIssueType: string;\n subtypeLabel: string;\n selectSubtype: string;\n commentLabel: string;\n commentPlaceholder: string;\n submit: string;\n submitting: string;\n thankYou: string;\n errorSubmitting: string;\n errorRequired: string;\n characterCount: string;\n}\n\nexport const translations: Record<string, Translations> = {\n en: en as Translations,\n fr: fr as Translations,\n};\n\nexport function getTranslations(locale: string, overrides?: Record<string, string>): Translations {\n const base = translations[locale] || translations.en;\n if (overrides) {\n return { ...base, ...overrides } as Translations;\n }\n return base;\n}\n\nexport { en, fr };\n","import type { FeedbackConfig, IssueType } from './config.js';\nimport { DEFAULT_ISSUE_TYPES } from './config.js';\nimport { getTranslations } from './i18n/index.js';\n\n/**\n * Generate the feedback widget JavaScript code.\n * This produces a self-contained IIFE that creates and manages the feedback widget.\n */\nexport function generateFeedbackWidget(config: FeedbackConfig): string {\n const t = getTranslations(config.locale, config.translations);\n const issueTypes = config.issueTypes || DEFAULT_ISSUE_TYPES;\n\n return `\n(function() {\n 'use strict';\n\n // ============================================================================\n // FEEDBACK WIDGET - Patch-Adams Plugin v1.0.0\n // ============================================================================\n\n var FEEDBACK = window.pa_patcher = window.pa_patcher || {};\n FEEDBACK.feedback = {\n version: '1.0.0',\n isOpen: false,\n rating: 0,\n config: ${JSON.stringify({\n endpoint: config.endpoint,\n method: config.method,\n headers: config.headers,\n position: config.position,\n showRating: config.showRating,\n ratingRequired: config.ratingRequired,\n ratingStars: config.ratingStars,\n showIssueType: config.showIssueType,\n issueTypeRequired: config.issueTypeRequired,\n showComment: config.showComment,\n commentRequired: config.commentRequired,\n commentMaxLength: config.commentMaxLength,\n autoClose: config.autoClose,\n autoCloseDelay: config.autoCloseDelay,\n debug: config.debug,\n includeMetadata: config.includeMetadata,\n })},\n translations: ${JSON.stringify(t)},\n issueTypes: ${JSON.stringify(issueTypes)},\n };\n\n var FB = FEEDBACK.feedback;\n\n function log() {\n if (FB.config.debug) {\n console.log.apply(console, ['[PA-Feedback]'].concat(Array.prototype.slice.call(arguments)));\n }\n }\n\n // ============================================================================\n // DOM CREATION\n // ============================================================================\n\n function createWidget() {\n var container = document.createElement('div');\n container.id = 'pa-feedback-container';\n container.className = 'pa-feedback-${config.position}';\n container.innerHTML = buildWidgetHtml();\n document.body.appendChild(container);\n setupEventListeners();\n log('Widget created');\n }\n\n function buildWidgetHtml() {\n var html = '';\n\n // Tab button\n html += '<button id=\"pa-feedback-tab\" class=\"pa-feedback-tab\" aria-label=\"' + FB.translations.title + '\">';\n html += '<span class=\"pa-feedback-tab-text\">${config.tabText}</span>';\n html += '</button>';\n\n // Modal\n html += '<div id=\"pa-feedback-modal\" class=\"pa-feedback-modal pa-feedback-hidden\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"pa-feedback-title\">';\n html += '<div class=\"pa-feedback-content\">';\n\n // Header\n html += '<div class=\"pa-feedback-header\">';\n html += '<h3 id=\"pa-feedback-title\">' + FB.translations.title + '</h3>';\n html += '<button id=\"pa-feedback-close\" class=\"pa-feedback-close\" aria-label=\"Close\">×</button>';\n html += '</div>';\n\n // Form\n html += '<form id=\"pa-feedback-form\">';\n\n // Rating (if enabled)\n ${config.showRating ? `\n html += '<div class=\"pa-feedback-field\">';\n html += '<label class=\"pa-feedback-label\">' + FB.translations.ratingLabel + '${config.ratingRequired ? ' <span class=\"pa-feedback-required\">*</span>' : ''}</label>';\n html += '<div class=\"pa-feedback-stars\" role=\"radiogroup\" aria-label=\"Rating\">';\n for (var i = 1; i <= ${config.ratingStars}; i++) {\n html += '<button type=\"button\" class=\"pa-feedback-star\" data-value=\"' + i + '\" role=\"radio\" aria-checked=\"false\" aria-label=\"' + i + ' star\">☆</button>';\n }\n html += '</div>';\n html += '</div>';\n ` : ''}\n\n // Issue Type (if enabled)\n ${config.showIssueType ? `\n html += '<div class=\"pa-feedback-field\">';\n html += '<label class=\"pa-feedback-label\" for=\"pa-feedback-issue-type\">' + FB.translations.issueTypeLabel + '${config.issueTypeRequired ? ' <span class=\"pa-feedback-required\">*</span>' : ''}</label>';\n html += '<select id=\"pa-feedback-issue-type\" class=\"pa-feedback-select\">';\n html += '<option value=\"\">' + FB.translations.selectIssueType + '</option>';\n FB.issueTypes.forEach(function(type) {\n html += '<option value=\"' + type.id + '\">' + type.label + '</option>';\n });\n html += '</select>';\n html += '</div>';\n\n // Subtype container (hidden by default)\n html += '<div id=\"pa-feedback-subtype-field\" class=\"pa-feedback-field pa-feedback-hidden\">';\n html += '<label class=\"pa-feedback-label\" for=\"pa-feedback-subtype\">' + FB.translations.subtypeLabel + '</label>';\n html += '<select id=\"pa-feedback-subtype\" class=\"pa-feedback-select\">';\n html += '<option value=\"\">' + FB.translations.selectSubtype + '</option>';\n html += '</select>';\n html += '</div>';\n ` : ''}\n\n // Comment (if enabled)\n ${config.showComment ? `\n html += '<div class=\"pa-feedback-field\">';\n html += '<label class=\"pa-feedback-label\" for=\"pa-feedback-comment\">' + FB.translations.commentLabel + '${config.commentRequired ? ' <span class=\"pa-feedback-required\">*</span>' : ''}</label>';\n html += '<textarea id=\"pa-feedback-comment\" class=\"pa-feedback-textarea\" maxlength=\"${config.commentMaxLength}\" placeholder=\"${config.commentPlaceholder || ''}\" rows=\"4\"></textarea>';\n html += '<div class=\"pa-feedback-counter\"><span id=\"pa-feedback-char-count\">0</span>/${config.commentMaxLength}</div>';\n html += '</div>';\n ` : ''}\n\n // Error message area\n html += '<div id=\"pa-feedback-error\" class=\"pa-feedback-error pa-feedback-hidden\"></div>';\n\n // Submit button\n html += '<button type=\"submit\" id=\"pa-feedback-submit\" class=\"pa-feedback-submit\">';\n html += '<span class=\"pa-feedback-submit-text\">' + FB.translations.submit + '</span>';\n html += '<span class=\"pa-feedback-submit-loading pa-feedback-hidden\">' + FB.translations.submitting + '</span>';\n html += '</button>';\n\n html += '</form>';\n\n // Success message\n html += '<div id=\"pa-feedback-success\" class=\"pa-feedback-success pa-feedback-hidden\">';\n html += '<div class=\"pa-feedback-checkmark\">✓</div>';\n html += '<p>' + FB.translations.thankYou + '</p>';\n html += '</div>';\n\n html += '</div>'; // content\n html += '</div>'; // modal\n\n return html;\n }\n\n // ============================================================================\n // EVENT HANDLERS\n // ============================================================================\n\n function setupEventListeners() {\n // Tab click\n document.getElementById('pa-feedback-tab').addEventListener('click', toggleModal);\n\n // Close button\n document.getElementById('pa-feedback-close').addEventListener('click', closeModal);\n\n // Form submit\n document.getElementById('pa-feedback-form').addEventListener('submit', handleSubmit);\n\n // Click outside to close\n document.getElementById('pa-feedback-modal').addEventListener('click', function(e) {\n if (e.target === this) closeModal();\n });\n\n // Escape key to close\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape' && FB.isOpen) closeModal();\n });\n\n ${config.showRating ? `\n // Star rating\n var stars = document.querySelectorAll('.pa-feedback-star');\n stars.forEach(function(star, index) {\n star.addEventListener('click', function() {\n FB.rating = index + 1;\n updateStars();\n });\n star.addEventListener('mouseenter', function() {\n highlightStars(index + 1);\n });\n });\n document.querySelector('.pa-feedback-stars').addEventListener('mouseleave', function() {\n highlightStars(FB.rating);\n });\n ` : ''}\n\n ${config.showIssueType ? `\n // Issue type change\n document.getElementById('pa-feedback-issue-type').addEventListener('change', updateSubtypes);\n ` : ''}\n\n ${config.showComment ? `\n // Character counter\n document.getElementById('pa-feedback-comment').addEventListener('input', updateCharCount);\n ` : ''}\n }\n\n function toggleModal() {\n if (FB.isOpen) {\n closeModal();\n } else {\n openModal();\n }\n }\n\n function openModal() {\n FB.isOpen = true;\n document.getElementById('pa-feedback-modal').classList.remove('pa-feedback-hidden');\n document.getElementById('pa-feedback-tab').classList.add('pa-feedback-tab-active');\n log('Modal opened');\n }\n\n function closeModal() {\n FB.isOpen = false;\n document.getElementById('pa-feedback-modal').classList.add('pa-feedback-hidden');\n document.getElementById('pa-feedback-tab').classList.remove('pa-feedback-tab-active');\n log('Modal closed');\n }\n\n ${config.showRating ? `\n function updateStars() {\n var stars = document.querySelectorAll('.pa-feedback-star');\n stars.forEach(function(star, index) {\n var isFilled = index < FB.rating;\n star.innerHTML = isFilled ? '★' : '☆';\n star.classList.toggle('pa-feedback-star-filled', isFilled);\n star.setAttribute('aria-checked', isFilled ? 'true' : 'false');\n });\n }\n\n function highlightStars(count) {\n var stars = document.querySelectorAll('.pa-feedback-star');\n stars.forEach(function(star, index) {\n var isFilled = index < count;\n star.innerHTML = isFilled ? '★' : '☆';\n star.classList.toggle('pa-feedback-star-hover', isFilled && count > FB.rating);\n });\n }\n ` : ''}\n\n ${config.showIssueType ? `\n function updateSubtypes() {\n var typeSelect = document.getElementById('pa-feedback-issue-type');\n var subtypeField = document.getElementById('pa-feedback-subtype-field');\n var subtypeSelect = document.getElementById('pa-feedback-subtype');\n var selectedType = typeSelect.value;\n\n // Find the selected issue type\n var issueType = FB.issueTypes.find(function(t) { return t.id === selectedType; });\n\n if (issueType && issueType.subtypes && issueType.subtypes.length > 0) {\n // Populate subtypes\n subtypeSelect.innerHTML = '<option value=\"\">' + FB.translations.selectSubtype + '</option>';\n issueType.subtypes.forEach(function(subtype) {\n subtypeSelect.innerHTML += '<option value=\"' + subtype.id + '\">' + subtype.label + '</option>';\n });\n subtypeField.classList.remove('pa-feedback-hidden');\n } else {\n subtypeField.classList.add('pa-feedback-hidden');\n subtypeSelect.value = '';\n }\n }\n ` : ''}\n\n ${config.showComment ? `\n function updateCharCount() {\n var textarea = document.getElementById('pa-feedback-comment');\n var counter = document.getElementById('pa-feedback-char-count');\n counter.textContent = textarea.value.length;\n }\n ` : ''}\n\n // ============================================================================\n // FORM SUBMISSION\n // ============================================================================\n\n function validateForm() {\n var errors = [];\n\n ${config.showRating && config.ratingRequired ? `\n if (FB.rating === 0) {\n errors.push('Rating is required');\n }\n ` : ''}\n\n ${config.showIssueType && config.issueTypeRequired ? `\n if (!document.getElementById('pa-feedback-issue-type').value) {\n errors.push('Issue type is required');\n }\n ` : ''}\n\n ${config.showComment && config.commentRequired ? `\n if (!document.getElementById('pa-feedback-comment').value.trim()) {\n errors.push('Comment is required');\n }\n ` : ''}\n\n return errors;\n }\n\n function collectFormData() {\n var data = {};\n\n ${config.showRating ? `data.rating = FB.rating;` : ''}\n ${config.showIssueType ? `\n data.issueType = document.getElementById('pa-feedback-issue-type').value || null;\n data.issueSubtype = document.getElementById('pa-feedback-subtype').value || null;\n ` : ''}\n ${config.showComment ? `data.comment = document.getElementById('pa-feedback-comment').value.trim();` : ''}\n\n // Add metadata\n data.metadata = collectMetadata();\n\n return data;\n }\n\n function collectMetadata() {\n var meta = {};\n var cfg = FB.config.includeMetadata;\n\n if (cfg.courseId && window.pa_patcher && window.pa_patcher.lrs && window.pa_patcher.lrs.courseInfo) {\n meta.courseId = window.pa_patcher.lrs.courseInfo.id;\n meta.courseTitle = window.pa_patcher.lrs.courseInfo.title;\n }\n\n if (cfg.lessonId) {\n meta.lessonId = window.location.hash || window.location.pathname;\n }\n\n if (cfg.userAgent) {\n meta.userAgent = navigator.userAgent;\n }\n\n if (cfg.timestamp) {\n meta.timestamp = new Date().toISOString();\n }\n\n if (cfg.url) {\n meta.url = window.location.href;\n }\n\n return meta;\n }\n\n function showError(message) {\n var errorEl = document.getElementById('pa-feedback-error');\n errorEl.textContent = message;\n errorEl.classList.remove('pa-feedback-hidden');\n }\n\n function hideError() {\n document.getElementById('pa-feedback-error').classList.add('pa-feedback-hidden');\n }\n\n function setSubmitting(isSubmitting) {\n var submitBtn = document.getElementById('pa-feedback-submit');\n var textEl = submitBtn.querySelector('.pa-feedback-submit-text');\n var loadingEl = submitBtn.querySelector('.pa-feedback-submit-loading');\n\n submitBtn.disabled = isSubmitting;\n textEl.classList.toggle('pa-feedback-hidden', isSubmitting);\n loadingEl.classList.toggle('pa-feedback-hidden', !isSubmitting);\n }\n\n function showSuccess() {\n document.getElementById('pa-feedback-form').classList.add('pa-feedback-hidden');\n document.getElementById('pa-feedback-success').classList.remove('pa-feedback-hidden');\n\n if (FB.config.autoClose) {\n setTimeout(function() {\n closeModal();\n resetForm();\n }, FB.config.autoCloseDelay);\n }\n }\n\n function resetForm() {\n var form = document.getElementById('pa-feedback-form');\n form.reset();\n form.classList.remove('pa-feedback-hidden');\n document.getElementById('pa-feedback-success').classList.add('pa-feedback-hidden');\n hideError();\n\n FB.rating = 0;\n ${config.showRating ? 'updateStars();' : ''}\n ${config.showComment ? 'updateCharCount();' : ''}\n ${config.showIssueType ? `\n document.getElementById('pa-feedback-subtype-field').classList.add('pa-feedback-hidden');\n ` : ''}\n }\n\n async function handleSubmit(e) {\n e.preventDefault();\n hideError();\n\n // Validate\n var errors = validateForm();\n if (errors.length > 0) {\n showError(FB.translations.errorRequired);\n return;\n }\n\n // Collect data\n var data = collectFormData();\n log('Submitting:', data);\n\n // Submit\n setSubmitting(true);\n\n try {\n ${config.endpoint ? `\n var response = await fetch('${config.endpoint}', {\n method: '${config.method}',\n headers: Object.assign({\n 'Content-Type': 'application/json',\n }, FB.config.headers || {}),\n body: JSON.stringify(data),\n });\n\n if (!response.ok) {\n throw new Error('HTTP ' + response.status);\n }\n\n log('Submitted successfully');\n ` : `\n // No endpoint configured - just log\n console.log('[PA-Feedback] Feedback submitted:', data);\n log('No endpoint configured, feedback logged to console');\n `}\n\n showSuccess();\n } catch (err) {\n log('Submit error:', err);\n showError(FB.translations.errorSubmitting);\n } finally {\n setSubmitting(false);\n }\n }\n\n // ============================================================================\n // INITIALIZATION\n // ============================================================================\n\n function init() {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', createWidget);\n } else {\n createWidget();\n }\n log('Initialized');\n }\n\n init();\n\n})();\n`;\n}\n","import type { FeedbackConfig } from './config.js';\n\n/**\n * Generate the CSS styles for the feedback widget.\n * Styles are scoped with #pa-feedback-container to avoid conflicts.\n */\nexport function generateFeedbackStyles(config: FeedbackConfig): string {\n const position = config.position;\n const tabColor = config.tabColor;\n const tabTextColor = config.tabTextColor;\n const zIndex = config.zIndex;\n\n return `\n/* ============================================================================\n FEEDBACK WIDGET STYLES - Patch-Adams Plugin v1.0.0\n ============================================================================ */\n\n#pa-feedback-container {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: #333;\n box-sizing: border-box;\n}\n\n#pa-feedback-container *,\n#pa-feedback-container *::before,\n#pa-feedback-container *::after {\n box-sizing: inherit;\n}\n\n/* Hidden utility class */\n#pa-feedback-container .pa-feedback-hidden {\n display: none !important;\n}\n\n/* ============================================================================\n TAB BUTTON\n ============================================================================ */\n\n#pa-feedback-tab {\n position: fixed;\n ${position}: 0;\n top: 50%;\n transform: translateY(-50%) rotate(${position === 'right' ? '-90deg' : '90deg'});\n transform-origin: ${position === 'right' ? 'right center' : 'left center'};\n ${position === 'right' ? 'right: -32px;' : 'left: -32px;'}\n z-index: ${zIndex};\n background: ${tabColor};\n color: ${tabTextColor};\n border: none;\n padding: 10px 20px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n border-radius: ${position === 'right' ? '0 0 8px 8px' : '8px 8px 0 0'};\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n#pa-feedback-tab:hover {\n background: ${adjustColor(tabColor, -15)};\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n}\n\n#pa-feedback-tab:focus {\n outline: 2px solid ${tabColor};\n outline-offset: 2px;\n}\n\n#pa-feedback-tab.pa-feedback-tab-active {\n background: ${adjustColor(tabColor, -20)};\n}\n\n/* ============================================================================\n MODAL\n ============================================================================ */\n\n#pa-feedback-modal {\n position: fixed;\n ${position}: 0;\n top: 0;\n width: 360px;\n height: 100%;\n z-index: ${zIndex + 1};\n background: rgba(0, 0, 0, 0.3);\n display: flex;\n justify-content: flex-${position === 'right' ? 'end' : 'start'};\n animation: pa-feedback-fade-in 0.2s ease;\n}\n\n@keyframes pa-feedback-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n#pa-feedback-container .pa-feedback-content {\n width: 100%;\n max-width: 360px;\n height: 100%;\n background: #fff;\n box-shadow: ${position === 'right' ? '-4px' : '4px'} 0 20px rgba(0, 0, 0, 0.15);\n display: flex;\n flex-direction: column;\n animation: pa-feedback-slide-in 0.2s ease;\n}\n\n@keyframes pa-feedback-slide-in {\n from {\n transform: translateX(${position === 'right' ? '100%' : '-100%'});\n }\n to {\n transform: translateX(0);\n }\n}\n\n/* ============================================================================\n HEADER\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid #e5e5e5;\n background: #fafafa;\n}\n\n#pa-feedback-container .pa-feedback-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #222;\n}\n\n#pa-feedback-container .pa-feedback-close {\n background: none;\n border: none;\n font-size: 24px;\n color: #666;\n cursor: pointer;\n padding: 4px 8px;\n line-height: 1;\n border-radius: 4px;\n transition: all 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-close:hover {\n background: #e5e5e5;\n color: #333;\n}\n\n/* ============================================================================\n FORM\n ============================================================================ */\n\n#pa-feedback-form {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n#pa-feedback-container .pa-feedback-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n#pa-feedback-container .pa-feedback-label {\n font-weight: 500;\n color: #444;\n font-size: 14px;\n}\n\n#pa-feedback-container .pa-feedback-required {\n color: #dc3545;\n}\n\n/* ============================================================================\n STAR RATING\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-stars {\n display: flex;\n gap: 4px;\n}\n\n#pa-feedback-container .pa-feedback-star {\n background: none;\n border: none;\n font-size: 28px;\n color: #ccc;\n cursor: pointer;\n padding: 4px;\n line-height: 1;\n transition: all 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-star:hover {\n transform: scale(1.1);\n}\n\n#pa-feedback-container .pa-feedback-star-filled,\n#pa-feedback-container .pa-feedback-star-hover {\n color: #ffc107;\n}\n\n/* ============================================================================\n SELECT & TEXTAREA\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-select {\n width: 100%;\n padding: 10px 12px;\n font-size: 14px;\n border: 1px solid #ddd;\n border-radius: 6px;\n background: #fff;\n color: #333;\n cursor: pointer;\n transition: border-color 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-select:focus {\n outline: none;\n border-color: ${tabColor};\n box-shadow: 0 0 0 3px ${hexToRgba(tabColor, 0.1)};\n}\n\n#pa-feedback-container .pa-feedback-textarea {\n width: 100%;\n padding: 12px;\n font-size: 14px;\n font-family: inherit;\n border: 1px solid #ddd;\n border-radius: 6px;\n resize: vertical;\n min-height: 100px;\n transition: border-color 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-textarea:focus {\n outline: none;\n border-color: ${tabColor};\n box-shadow: 0 0 0 3px ${hexToRgba(tabColor, 0.1)};\n}\n\n#pa-feedback-container .pa-feedback-textarea::placeholder {\n color: #999;\n}\n\n#pa-feedback-container .pa-feedback-counter {\n text-align: right;\n font-size: 12px;\n color: #888;\n}\n\n/* ============================================================================\n ERROR MESSAGE\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-error {\n background: #fee2e2;\n color: #dc2626;\n padding: 10px 14px;\n border-radius: 6px;\n font-size: 13px;\n}\n\n/* ============================================================================\n SUBMIT BUTTON\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-submit {\n width: 100%;\n padding: 12px 20px;\n font-size: 16px;\n font-weight: 600;\n color: #fff;\n background: ${tabColor};\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n margin-top: auto;\n}\n\n#pa-feedback-container .pa-feedback-submit:hover:not(:disabled) {\n background: ${adjustColor(tabColor, -15)};\n}\n\n#pa-feedback-container .pa-feedback-submit:focus {\n outline: 2px solid ${tabColor};\n outline-offset: 2px;\n}\n\n#pa-feedback-container .pa-feedback-submit:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n}\n\n/* ============================================================================\n SUCCESS MESSAGE\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-success {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n\n#pa-feedback-container .pa-feedback-checkmark {\n width: 64px;\n height: 64px;\n background: #10b981;\n color: #fff;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 32px;\n margin-bottom: 20px;\n animation: pa-feedback-pop 0.3s ease;\n}\n\n@keyframes pa-feedback-pop {\n 0% { transform: scale(0); }\n 50% { transform: scale(1.2); }\n 100% { transform: scale(1); }\n}\n\n#pa-feedback-container .pa-feedback-success p {\n margin: 0;\n font-size: 18px;\n font-weight: 500;\n color: #333;\n}\n`;\n}\n\n/**\n * Adjust a hex color by a percentage (positive = lighter, negative = darker)\n */\nfunction adjustColor(hex: string, percent: number): string {\n // Remove # if present\n hex = hex.replace(/^#/, '');\n\n // Parse the color\n let r = parseInt(hex.substring(0, 2), 16);\n let g = parseInt(hex.substring(2, 4), 16);\n let b = parseInt(hex.substring(4, 6), 16);\n\n // Adjust\n r = Math.min(255, Math.max(0, r + (r * percent) / 100));\n g = Math.min(255, Math.max(0, g + (g * percent) / 100));\n b = Math.min(255, Math.max(0, b + (b * percent) / 100));\n\n // Convert back to hex\n return (\n '#' +\n Math.round(r).toString(16).padStart(2, '0') +\n Math.round(g).toString(16).padStart(2, '0') +\n Math.round(b).toString(16).padStart(2, '0')\n );\n}\n\n/**\n * Convert hex color to rgba\n */\nfunction hexToRgba(hex: string, alpha: number): string {\n hex = hex.replace(/^#/, '');\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n","/**\n * @patch-adams/plugin-feedback\n *\n * Feedback widget plugin for Patch-Adams.\n * Injects a customizable feedback form into patched Rise courses.\n *\n * Features:\n * - Star rating\n * - Issue type/subtype selection\n * - Comment text area\n * - Multi-language support (en/fr)\n * - Customizable appearance\n * - Automatic metadata collection\n * - Configurable API endpoint\n */\n\nimport type { PatchAdamsPlugin } from '@patch-adams/core';\nimport { FeedbackConfigSchema, type FeedbackConfig } from './config.js';\nimport { generateFeedbackWidget } from './widget.js';\nimport { generateFeedbackStyles } from './styles.js';\n\n/**\n * Feedback plugin for Patch-Adams\n */\nexport const feedbackPlugin: PatchAdamsPlugin<FeedbackConfig> = {\n name: 'feedback',\n version: '1.0.0',\n description: 'Inject a feedback form widget into Rise courses for collecting user feedback',\n configSchema: FeedbackConfigSchema,\n\n generateCss(config: FeedbackConfig) {\n return {\n after: generateFeedbackStyles(config),\n };\n },\n\n generateJs(config: FeedbackConfig) {\n return {\n after: generateFeedbackWidget(config),\n };\n },\n};\n\n// Default export for convenience\nexport default feedbackPlugin;\n\n// Re-export types and utilities\nexport {\n FeedbackConfigSchema,\n type FeedbackConfig,\n type IssueType,\n type IssueSubtype,\n type MetadataOptions,\n DEFAULT_ISSUE_TYPES,\n} from './config.js';\n\nexport { generateFeedbackWidget } from './widget.js';\nexport { generateFeedbackStyles } from './styles.js';\nexport { getTranslations, translations, type Translations } from './i18n/index.js';\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/i18n/en.json","../src/i18n/fr.json","../src/i18n/index.ts","../src/widget.ts","../src/styles.ts","../src/index.ts"],"names":[],"mappings":";;;AAKO,IAAM,kBAAA,GAAqB,EAAE,MAAA,CAAO;AAAA;AAAA,EAEzC,EAAA,EAAI,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEpB,KAAA,EAAO,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC;AACzB,CAAC,CAAA;AAKM,IAAM,eAAA,GAAkB,EAAE,MAAA,CAAO;AAAA;AAAA,EAEtC,EAAA,EAAI,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEpB,KAAA,EAAO,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA,EAEvB,QAAA,EAAU,CAAA,CAAE,KAAA,CAAM,kBAAkB,EAAE,QAAA;AACxC,CAAC,CAAA;AAKM,IAAM,qBAAA,GAAwB,EAAE,MAAA,CAAO;AAAA;AAAA,EAE5C,QAAA,EAAU,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA,EAElC,QAAA,EAAU,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA,EAElC,SAAA,EAAW,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA,EAEnC,SAAA,EAAW,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA,EAEnC,GAAA,EAAK,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI;AAC/B,CAAC,CAAA;AAKM,IAAM,mBAAA,GAAyD;AAAA,EACpE;AAAA,IACE,EAAA,EAAI,SAAA;AAAA,IACJ,KAAA,EAAO,eAAA;AAAA,IACP,QAAA,EAAU;AAAA,MACR,EAAE,EAAA,EAAI,MAAA,EAAQ,KAAA,EAAO,gBAAA,EAAiB;AAAA,MACtC,EAAE,EAAA,EAAI,WAAA,EAAa,KAAA,EAAO,uBAAA,EAAwB;AAAA,MAClD,EAAE,EAAA,EAAI,SAAA,EAAW,KAAA,EAAO,qBAAA,EAAsB;AAAA,MAC9C,EAAE,EAAA,EAAI,UAAA,EAAY,KAAA,EAAO,kBAAA;AAAmB;AAC9C,GACF;AAAA,EACA;AAAA,IACE,EAAA,EAAI,WAAA;AAAA,IACJ,KAAA,EAAO,iBAAA;AAAA,IACP,QAAA,EAAU;AAAA,MACR,EAAE,EAAA,EAAI,OAAA,EAAS,KAAA,EAAO,eAAA,EAAgB;AAAA,MACtC,EAAE,EAAA,EAAI,OAAA,EAAS,KAAA,EAAO,eAAA,EAAgB;AAAA,MACtC,EAAE,EAAA,EAAI,YAAA,EAAc,KAAA,EAAO,kBAAA,EAAmB;AAAA,MAC9C,EAAE,EAAA,EAAI,SAAA,EAAW,KAAA,EAAO,wBAAA;AAAyB;AACnD,GACF;AAAA,EACA;AAAA,IACE,EAAA,EAAI,YAAA;AAAA,IACJ,KAAA,EAAO;AAAA,GACT;AAAA,EACA;AAAA,IACE,EAAA,EAAI,OAAA;AAAA,IACJ,KAAA,EAAO;AAAA;AAEX;AAKO,IAAM,oBAAA,GAAuB,EAAE,MAAA,CAAO;AAAA;AAAA,EAE3C,OAAA,EAAS,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA;AAAA,EAKjC,UAAU,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,GAAM,QAAA,EAAS;AAAA;AAAA,EAGpC,MAAA,EAAQ,EAAE,IAAA,CAAK,CAAC,QAAQ,KAAK,CAAC,CAAA,CAAE,OAAA,CAAQ,MAAM,CAAA;AAAA;AAAA,EAG9C,SAAS,CAAA,CAAE,MAAA,CAAO,EAAE,MAAA,EAAQ,EAAE,QAAA,EAAS;AAAA;AAAA;AAAA,EAKvC,QAAA,EAAU,EAAE,IAAA,CAAK,CAAC,QAAQ,OAAO,CAAC,CAAA,CAAE,OAAA,CAAQ,OAAO,CAAA;AAAA;AAAA,EAGnD,OAAA,EAAS,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,UAAU,CAAA;AAAA;AAAA,EAGtC,QAAA,EAAU,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,SAAS,CAAA;AAAA;AAAA,EAGtC,YAAA,EAAc,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,SAAS,CAAA;AAAA;AAAA,EAG1C,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAO,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA;AAAA,EAK/B,UAAA,EAAY,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA,EAGpC,cAAA,EAAgB,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,KAAK,CAAA;AAAA;AAAA,EAGzC,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,EAAE,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA;AAAA,EAGhD,aAAA,EAAe,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA,EAGvC,iBAAA,EAAmB,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,KAAK,CAAA;AAAA;AAAA,EAG5C,UAAA,EAAY,CAAA,CAAE,KAAA,CAAM,eAAe,EAAE,QAAA,EAAS;AAAA;AAAA,EAG9C,WAAA,EAAa,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA,EAGrC,eAAA,EAAiB,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,KAAK,CAAA;AAAA;AAAA,EAG1C,gBAAA,EAAkB,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,EAAE,CAAA,CAAE,GAAA,CAAI,GAAI,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA;AAAA;AAAA,EAG1D,kBAAA,EAAoB,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA;AAAA;AAAA,EAKxC,MAAA,EAAQ,EAAE,IAAA,CAAK,CAAC,MAAM,IAAI,CAAC,CAAA,CAAE,OAAA,CAAQ,IAAI,CAAA;AAAA;AAAA,EAGzC,cAAc,CAAA,CAAE,MAAA,CAAO,EAAE,MAAA,EAAQ,EAAE,QAAA,EAAS;AAAA;AAAA;AAAA,EAK5C,eAAA,EAAiB,qBAAA,CAAsB,OAAA,CAAQ,EAAE,CAAA;AAAA;AAAA;AAAA,EAKjD,SAAA,EAAW,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,IAAI,CAAA;AAAA;AAAA,EAGnC,cAAA,EAAgB,CAAA,CAAE,MAAA,EAAO,CAAE,GAAA,CAAI,GAAG,CAAA,CAAE,GAAA,CAAI,GAAK,CAAA,CAAE,OAAA,CAAQ,GAAI,CAAA;AAAA;AAAA,EAG3D,KAAA,EAAO,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,KAAK;AAClC,CAAC;;;ACpKD,IAAA,UAAA,GAAA;AAAA,EACE,KAAA,EAAS,eAAA;AAAA,EACT,WAAA,EAAe,kCAAA;AAAA,EACf,cAAA,EAAkB,wBAAA;AAAA,EAClB,eAAA,EAAmB,gBAAA;AAAA,EACnB,YAAA,EAAgB,oBAAA;AAAA,EAChB,aAAA,EAAiB,WAAA;AAAA,EACjB,YAAA,EAAgB,eAAA;AAAA,EAChB,kBAAA,EAAsB,4CAAA;AAAA,EACtB,MAAA,EAAU,eAAA;AAAA,EACV,UAAA,EAAc,YAAA;AAAA,EACd,QAAA,EAAY,8BAAA;AAAA,EACZ,eAAA,EAAmB,4CAAA;AAAA,EACnB,aAAA,EAAiB,qCAAA;AAAA,EACjB,cAAA,EAAkB;AACpB,CAAA;;;ACfA,IAAA,UAAA,GAAA;AAAA,EACE,KAAA,EAAS,wBAAA;AAAA,EACT,WAAA,EAAe,qCAAA;AAAA,EACf,cAAA,EAAkB,qBAAA;AAAA,EAClB,eAAA,EAAmB,oBAAA;AAAA,EACnB,YAAA,EAAgB,yBAAA;AAAA,EAChB,aAAA,EAAiB,oBAAA;AAAA,EACjB,YAAA,EAAgB,mBAAA;AAAA,EAChB,kBAAA,EAAsB,uDAAA;AAAA,EACtB,MAAA,EAAU,SAAA;AAAA,EACV,UAAA,EAAc,mBAAA;AAAA,EACd,QAAA,EAAY,+BAAA;AAAA,EACZ,eAAA,EAAmB,6CAAA;AAAA,EACnB,aAAA,EAAiB,2CAAA;AAAA,EACjB,cAAA,EAAkB;AACpB,CAAA;;;ACKO,IAAM,YAAA,GAA6C;AAAA,EACxD,EAAA,EAAI,UAAA;AAAA,EACJ,EAAA,EAAI;AACN;AAEO,SAAS,eAAA,CAAgB,QAAgB,SAAA,EAAkD;AAChG,EAAA,MAAM,IAAA,GAAO,YAAA,CAAa,MAAM,CAAA,IAAK,YAAA,CAAa,EAAA;AAClD,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,OAAO,EAAE,GAAG,IAAA,EAAM,GAAG,SAAA,EAAU;AAAA,EACjC;AACA,EAAA,OAAO,IAAA;AACT;;;ACvBO,SAAS,uBAAuB,MAAA,EAAgC;AACrE,EAAA,MAAM,CAAA,GAAI,eAAA,CAAgB,MAAA,CAAO,MAAA,EAAQ,OAAO,YAAY,CAAA;AAC5D,EAAA,MAAM,UAAA,GAAa,OAAO,UAAA,IAAc,mBAAA;AAExC,EAAA,OAAO;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAA,EAaK,KAAK,SAAA,CAAU;AAAA,IACvB,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,gBAAgB,MAAA,CAAO,cAAA;AAAA,IACvB,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,eAAe,MAAA,CAAO,aAAA;AAAA,IACtB,mBAAmB,MAAA,CAAO,iBAAA;AAAA,IAC1B,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,iBAAiB,MAAA,CAAO,eAAA;AAAA,IACxB,kBAAkB,MAAA,CAAO,gBAAA;AAAA,IACzB,WAAW,MAAA,CAAO,SAAA;AAAA,IAClB,gBAAgB,MAAA,CAAO,cAAA;AAAA,IACvB,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,iBAAiB,MAAA,CAAO;AAAA,GACzB,CAAC,CAAA;AAAA,kBAAA,EACc,IAAA,CAAK,SAAA,CAAU,CAAC,CAAC,CAAA;AAAA,gBAAA,EACnB,IAAA,CAAK,SAAA,CAAU,UAAU,CAAC,CAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,uCAAA,EAkBH,OAAO,QAAQ,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA,gDAAA,EAYN,OAAO,OAAO,CAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA,IAAA,EAiB1D,OAAO,UAAA,GAAa;AAAA;AAAA,iFAAA,EAEyD,MAAA,CAAO,cAAA,GAAiB,8CAAA,GAAiD,EAAE,CAAA;AAAA;AAAA,yBAAA,EAEnI,OAAO,WAAW,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAAA,GAKrC,EAAE;;AAAA;AAAA,IAAA,EAGJ,OAAO,aAAA,GAAgB;AAAA;AAAA,iHAAA,EAEsF,MAAA,CAAO,iBAAA,GAAoB,8CAAA,GAAiD,EAAE,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAAA,GAgBzL,EAAE;;AAAA;AAAA,IAAA,EAGJ,OAAO,WAAA,GAAc;AAAA;AAAA,4GAAA,EAEmF,MAAA,CAAO,eAAA,GAAkB,8CAAA,GAAiD,EAAE,CAAA;AAAA,wFAAA,EAChG,MAAA,CAAO,gBAAgB,CAAA,eAAA,EAAkB,MAAA,CAAO,sBAAsB,EAAE,CAAA;AAAA,yFAAA,EACvE,OAAO,gBAAgB,CAAA;AAAA;AAAA,IAAA,CAAA,GAE1G,EAAE;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA,IAAA,EAiDJ,OAAO,UAAA,GAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAAA,GAelB,EAAE;;AAAA,IAAA,EAEJ,OAAO,aAAA,GAAgB;AAAA;AAAA;AAAA,IAAA,CAAA,GAGrB,EAAE;;AAAA,IAAA,EAEJ,OAAO,WAAA,GAAc;AAAA;AAAA;AAAA,IAAA,CAAA,GAGnB,EAAE;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,EAAA,EAyBN,OAAO,UAAA,GAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAAA,CAAA,GAmBlB,EAAE;;AAAA,EAAA,EAEJ,OAAO,aAAA,GAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAAA,CAAA,GAsBrB,EAAE;;AAAA,EAAA,EAEJ,OAAO,WAAA,GAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAAA,CAAA,GAMnB,EAAE;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA,IAAA,EASF,MAAA,CAAO,UAAA,IAAc,MAAA,CAAO,cAAA,GAAiB;AAAA;AAAA;AAAA;AAAA,IAAA,CAAA,GAI3C,EAAE;;AAAA,IAAA,EAEJ,MAAA,CAAO,aAAA,IAAiB,MAAA,CAAO,iBAAA,GAAoB;AAAA;AAAA;AAAA;AAAA,IAAA,CAAA,GAIjD,EAAE;;AAAA,IAAA,EAEJ,MAAA,CAAO,WAAA,IAAe,MAAA,CAAO,eAAA,GAAkB;AAAA;AAAA;AAAA;AAAA,IAAA,CAAA,GAI7C,EAAE;;AAAA;AAAA;;AAAA;AAAA;;AAAA,IAAA,EAQJ,MAAA,CAAO,UAAA,GAAa,CAAA,wBAAA,CAAA,GAA6B,EAAE;AAAA,IAAA,EACnD,OAAO,aAAA,GAAgB;AAAA;AAAA;AAAA,IAAA,CAAA,GAGrB,EAAE;AAAA,IAAA,EACJ,MAAA,CAAO,WAAA,GAAc,CAAA,2EAAA,CAAA,GAAgF,EAAE;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,IAAA,EA4EvG,MAAA,CAAO,UAAA,GAAa,gBAAA,GAAmB,EAAE;AAAA,IAAA,EACzC,MAAA,CAAO,WAAA,GAAc,oBAAA,GAAuB,EAAE;AAAA,IAAA,EAC9C,OAAO,aAAA,GAAgB;AAAA;AAAA,IAAA,CAAA,GAErB,EAAE;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA,MAAA,EAsBF,OAAO,QAAA,GAAW;AAAA,kCAAA,EACU,OAAO,QAAQ,CAAA;AAAA,iBAAA,EAChC,OAAO,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA,MAAA,CAAA,GAYtB;AAAA;AAAA;AAAA;AAAA,MAAA,CAIH;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA,CAAA;AA4BP;;;AC5cO,SAAS,uBAAuB,MAAA,EAAgC;AACrE,EAAA,MAAM,WAAW,MAAA,CAAO,QAAA;AACxB,EAAA,MAAM,WAAW,MAAA,CAAO,QAAA;AACxB,EAAA,MAAM,eAAe,MAAA,CAAO,YAAA;AAC5B,EAAA,MAAM,SAAS,MAAA,CAAO,MAAA;AAGtB,EAAA,MAAM,UAAU,QAAA,KAAa,OAAA;AAC7B,EAAA,MAAM,YAAA,GAAe,UAAU,QAAA,GAAW,OAAA;AAC1C,EAAA,MAAM,kBAAA,GAAqB,UAAU,cAAA,GAAiB,aAAA;AACtD,EAAA,MAAM,SAAA,GAAY,UAAU,0BAAA,GAA6B,0BAAA;AACzD,EAAA,MAAM,eAAA,GAAkB,UAAU,aAAA,GAAgB,aAAA;AAClD,EAAA,MAAM,aAAA,GAAgB,UAAU,uBAAA,GAA0B,uBAAA;AAC1D,EAAA,MAAM,YAAA,GAAe,UAAU,UAAA,GAAa,YAAA;AAC5C,EAAA,MAAM,aAAA,GAAgB,UAAU,iCAAA,GAAoC,gCAAA;AACpE,EAAA,MAAM,SAAA,GAAY,UAAU,MAAA,GAAS,OAAA;AAErC,EAAA,OAAO;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,EAAA,EA+BL,SAAS;AAAA,qCAAA,EAC0B,YAAY,CAAA;AAAA,oBAAA,EAC7B,kBAAkB,CAAA;AAAA,WAAA,EAC3B,MAAM,CAAA;AAAA,cAAA,EACH,QAAQ,CAAA;AAAA,SAAA,EACb,YAAY,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAA,EAMJ,eAAe,CAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,cAAA,EAOlB,WAAA,CAAY,QAAA,EAAU,GAAG,CAAC,CAAA;AAAA;AAAA;;AAAA;AAAA,qBAAA,EAKnB,QAAQ,CAAA;AAAA;AAAA;;AAAA;AAAA,cAAA,EAKf,WAAA,CAAY,QAAA,EAAU,GAAG,CAAC,CAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,EAAA,EAUtC,aAAa;AAAA;AAAA;AAAA,WAAA,EAGJ,SAAS,CAAC,CAAA;AAAA;AAAA;AAAA,mBAAA,EAGF,YAAY,CAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAAA,EAcjB,aAAa,CAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,0BAAA,EAQD,SAAS,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,gBAAA,EAwHnB,QAAQ,CAAA;AAAA,wBAAA,EACA,SAAA,CAAU,QAAA,EAAU,GAAG,CAAC,CAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,gBAAA,EAiBhC,QAAQ,CAAA;AAAA,wBAAA,EACA,SAAA,CAAU,QAAA,EAAU,GAAG,CAAC,CAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAAA,EAmClC,QAAQ,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,cAAA,EAUR,WAAA,CAAY,QAAA,EAAU,GAAG,CAAC,CAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,qBAAA,EAMnB,QAAQ,CAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAkD/B;AAKA,SAAS,WAAA,CAAY,KAAa,OAAA,EAAyB;AAEzD,EAAA,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,IAAA,EAAM,EAAE,CAAA;AAG1B,EAAA,IAAI,IAAI,QAAA,CAAS,GAAA,CAAI,UAAU,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AACxC,EAAA,IAAI,IAAI,QAAA,CAAS,GAAA,CAAI,UAAU,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AACxC,EAAA,IAAI,IAAI,QAAA,CAAS,GAAA,CAAI,UAAU,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AAGxC,EAAA,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,GAAK,CAAA,GAAI,OAAA,GAAW,GAAG,CAAC,CAAA;AACtD,EAAA,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,GAAK,CAAA,GAAI,OAAA,GAAW,GAAG,CAAC,CAAA;AACtD,EAAA,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,GAAK,CAAA,GAAI,OAAA,GAAW,GAAG,CAAC,CAAA;AAGtD,EAAA,OACE,GAAA,GACA,IAAA,CAAK,KAAA,CAAM,CAAC,EAAE,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA,GAC1C,IAAA,CAAK,MAAM,CAAC,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,IAC1C,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AAE9C;AAKA,SAAS,SAAA,CAAU,KAAa,KAAA,EAAuB;AACrD,EAAA,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,IAAA,EAAM,EAAE,CAAA;AAC1B,EAAA,MAAM,IAAI,QAAA,CAAS,GAAA,CAAI,UAAU,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AAC1C,EAAA,MAAM,IAAI,QAAA,CAAS,GAAA,CAAI,UAAU,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AAC1C,EAAA,MAAM,IAAI,QAAA,CAAS,GAAA,CAAI,UAAU,CAAA,EAAG,CAAC,GAAG,EAAE,CAAA;AAC1C,EAAA,OAAO,QAAQ,CAAC,CAAA,EAAA,EAAK,CAAC,CAAA,EAAA,EAAK,CAAC,KAAK,KAAK,CAAA,CAAA,CAAA;AACxC;;;ACrXO,IAAM,cAAA,GAAmD;AAAA,EAC9D,IAAA,EAAM,UAAA;AAAA,EACN,OAAA,EAAS,OAAA;AAAA,EACT,WAAA,EAAa,8EAAA;AAAA,EACb,YAAA,EAAc,oBAAA;AAAA,EAEd,YAAY,MAAA,EAAwB;AAClC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,uBAAuB,MAAM;AAAA,KACtC;AAAA,EACF,CAAA;AAAA,EAEA,WAAW,MAAA,EAAwB;AACjC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,uBAAuB,MAAM;AAAA,KACtC;AAAA,EACF;AACF;AAGA,IAAO,aAAA,GAAQ","file":"index.js","sourcesContent":["import { z } from 'zod';\n\n/**\n * Issue subtype definition\n */\nexport const IssueSubtypeSchema = z.object({\n /** Unique identifier for the subtype */\n id: z.string().min(1),\n /** Display label for the subtype */\n label: z.string().min(1),\n});\n\n/**\n * Issue type definition with optional subtypes\n */\nexport const IssueTypeSchema = z.object({\n /** Unique identifier for the issue type */\n id: z.string().min(1),\n /** Display label for the issue type */\n label: z.string().min(1),\n /** Optional subtypes that appear when this type is selected */\n subtypes: z.array(IssueSubtypeSchema).optional(),\n});\n\n/**\n * Metadata options - what to include with feedback submissions\n */\nexport const MetadataOptionsSchema = z.object({\n /** Include the course ID from LRS bridge (if available) */\n courseId: z.boolean().default(true),\n /** Include the current lesson/page ID (URL hash or pathname) */\n lessonId: z.boolean().default(true),\n /** Include the browser user agent */\n userAgent: z.boolean().default(true),\n /** Include timestamp of submission */\n timestamp: z.boolean().default(true),\n /** Include the full current URL */\n url: z.boolean().default(true),\n});\n\n/**\n * Default issue types if none are provided\n */\nexport const DEFAULT_ISSUE_TYPES: z.infer<typeof IssueTypeSchema>[] = [\n {\n id: 'content',\n label: 'Content Issue',\n subtypes: [\n { id: 'typo', label: 'Typo / Grammar' },\n { id: 'incorrect', label: 'Incorrect Information' },\n { id: 'unclear', label: 'Unclear / Confusing' },\n { id: 'outdated', label: 'Outdated Content' },\n ],\n },\n {\n id: 'technical',\n label: 'Technical Issue',\n subtypes: [\n { id: 'audio', label: 'Audio Problem' },\n { id: 'video', label: 'Video Problem' },\n { id: 'navigation', label: 'Navigation Issue' },\n { id: 'display', label: 'Display / Layout Issue' },\n ],\n },\n {\n id: 'suggestion',\n label: 'Suggestion',\n },\n {\n id: 'other',\n label: 'Other',\n },\n];\n\n/**\n * Full feedback plugin configuration schema\n */\nexport const FeedbackConfigSchema = z.object({\n /** Whether the feedback plugin is enabled */\n enabled: z.boolean().default(true),\n\n // === Endpoint Configuration ===\n\n /** API endpoint URL for submitting feedback (optional - if not set, logs to console) */\n endpoint: z.string().url().optional(),\n\n /** HTTP method for the endpoint (default: POST) */\n method: z.enum(['POST', 'PUT']).default('POST'),\n\n /** Additional headers to send with the request */\n headers: z.record(z.string()).optional(),\n\n // === Appearance ===\n\n /** Position of the feedback tab (left or right side of screen) */\n position: z.enum(['left', 'right']).default('right'),\n\n /** Text displayed on the feedback tab */\n tabText: z.string().default('Feedback'),\n\n /** Background color of the feedback tab */\n tabColor: z.string().default('#da291c'),\n\n /** Text color of the feedback tab */\n tabTextColor: z.string().default('#ffffff'),\n\n /** Z-index for the feedback widget (default: 9999) */\n zIndex: z.number().default(9999),\n\n // === Form Fields ===\n\n /** Show star rating field */\n showRating: z.boolean().default(true),\n\n /** Whether rating is required to submit */\n ratingRequired: z.boolean().default(false),\n\n /** Number of stars in the rating (default: 5) */\n ratingStars: z.number().min(3).max(10).default(5),\n\n /** Show issue type dropdown */\n showIssueType: z.boolean().default(true),\n\n /** Whether issue type is required to submit */\n issueTypeRequired: z.boolean().default(false),\n\n /** Available issue types (uses defaults if not provided) */\n issueTypes: z.array(IssueTypeSchema).optional(),\n\n /** Show comment textarea */\n showComment: z.boolean().default(true),\n\n /** Whether comment is required to submit */\n commentRequired: z.boolean().default(false),\n\n /** Maximum length for comments (default: 500) */\n commentMaxLength: z.number().min(50).max(5000).default(500),\n\n /** Placeholder text for comment field (uses translation if not set) */\n commentPlaceholder: z.string().optional(),\n\n // === Language / i18n ===\n\n /** Locale for UI text (en or fr) */\n locale: z.enum(['en', 'fr']).default('en'),\n\n /** Custom translations (overrides built-in translations) */\n translations: z.record(z.string()).optional(),\n\n // === Metadata ===\n\n /** What metadata to include with feedback submissions */\n includeMetadata: MetadataOptionsSchema.default({}),\n\n // === Behavior ===\n\n /** Auto-close modal after successful submission (default: true) */\n autoClose: z.boolean().default(true),\n\n /** Delay in ms before auto-closing after success (default: 2000) */\n autoCloseDelay: z.number().min(500).max(10000).default(2000),\n\n /** Enable debug logging (default: false) */\n debug: z.boolean().default(false),\n});\n\nexport type FeedbackConfig = z.infer<typeof FeedbackConfigSchema>;\nexport type IssueType = z.infer<typeof IssueTypeSchema>;\nexport type IssueSubtype = z.infer<typeof IssueSubtypeSchema>;\nexport type MetadataOptions = z.infer<typeof MetadataOptionsSchema>;\n","{\n \"title\": \"Send Feedback\",\n \"ratingLabel\": \"How would you rate this content?\",\n \"issueTypeLabel\": \"What type of feedback?\",\n \"selectIssueType\": \"Select type...\",\n \"subtypeLabel\": \"More specifically:\",\n \"selectSubtype\": \"Select...\",\n \"commentLabel\": \"Your feedback\",\n \"commentPlaceholder\": \"Please describe your feedback in detail...\",\n \"submit\": \"Send Feedback\",\n \"submitting\": \"Sending...\",\n \"thankYou\": \"Thank you for your feedback!\",\n \"errorSubmitting\": \"Failed to send feedback. Please try again.\",\n \"errorRequired\": \"Please fill in the required fields.\",\n \"characterCount\": \"{current}/{max}\"\n}\n","{\n \"title\": \"Envoyer un commentaire\",\n \"ratingLabel\": \"Comment évaluez-vous ce contenu?\",\n \"issueTypeLabel\": \"Type de commentaire\",\n \"selectIssueType\": \"Sélectionner...\",\n \"subtypeLabel\": \"Plus précisément:\",\n \"selectSubtype\": \"Sélectionner...\",\n \"commentLabel\": \"Votre commentaire\",\n \"commentPlaceholder\": \"Veuillez décrire votre commentaire en détail...\",\n \"submit\": \"Envoyer\",\n \"submitting\": \"Envoi en cours...\",\n \"thankYou\": \"Merci pour votre commentaire!\",\n \"errorSubmitting\": \"Échec de l'envoi. Veuillez réessayer.\",\n \"errorRequired\": \"Veuillez remplir les champs obligatoires.\",\n \"characterCount\": \"{current}/{max}\"\n}\n","import en from './en.json';\nimport fr from './fr.json';\n\nexport interface Translations {\n title: string;\n ratingLabel: string;\n issueTypeLabel: string;\n selectIssueType: string;\n subtypeLabel: string;\n selectSubtype: string;\n commentLabel: string;\n commentPlaceholder: string;\n submit: string;\n submitting: string;\n thankYou: string;\n errorSubmitting: string;\n errorRequired: string;\n characterCount: string;\n}\n\nexport const translations: Record<string, Translations> = {\n en: en as Translations,\n fr: fr as Translations,\n};\n\nexport function getTranslations(locale: string, overrides?: Record<string, string>): Translations {\n const base = translations[locale] || translations.en;\n if (overrides) {\n return { ...base, ...overrides } as Translations;\n }\n return base;\n}\n\nexport { en, fr };\n","import type { FeedbackConfig, IssueType } from './config.js';\nimport { DEFAULT_ISSUE_TYPES } from './config.js';\nimport { getTranslations } from './i18n/index.js';\n\n/**\n * Generate the feedback widget JavaScript code.\n * This produces a self-contained IIFE that creates and manages the feedback widget.\n */\nexport function generateFeedbackWidget(config: FeedbackConfig): string {\n const t = getTranslations(config.locale, config.translations);\n const issueTypes = config.issueTypes || DEFAULT_ISSUE_TYPES;\n\n return `\n(function() {\n 'use strict';\n\n // ============================================================================\n // FEEDBACK WIDGET - Patch-Adams Plugin v1.0.0\n // ============================================================================\n\n var FEEDBACK = window.pa_patcher = window.pa_patcher || {};\n FEEDBACK.feedback = {\n version: '1.0.0',\n isOpen: false,\n rating: 0,\n config: ${JSON.stringify({\n endpoint: config.endpoint,\n method: config.method,\n headers: config.headers,\n position: config.position,\n showRating: config.showRating,\n ratingRequired: config.ratingRequired,\n ratingStars: config.ratingStars,\n showIssueType: config.showIssueType,\n issueTypeRequired: config.issueTypeRequired,\n showComment: config.showComment,\n commentRequired: config.commentRequired,\n commentMaxLength: config.commentMaxLength,\n autoClose: config.autoClose,\n autoCloseDelay: config.autoCloseDelay,\n debug: config.debug,\n includeMetadata: config.includeMetadata,\n })},\n translations: ${JSON.stringify(t)},\n issueTypes: ${JSON.stringify(issueTypes)},\n };\n\n var FB = FEEDBACK.feedback;\n\n function log() {\n if (FB.config.debug) {\n console.log.apply(console, ['[PA-Feedback]'].concat(Array.prototype.slice.call(arguments)));\n }\n }\n\n // ============================================================================\n // DOM CREATION\n // ============================================================================\n\n function createWidget() {\n var container = document.createElement('div');\n container.id = 'pa-feedback-container';\n container.className = 'pa-feedback-${config.position}';\n container.innerHTML = buildWidgetHtml();\n document.body.appendChild(container);\n setupEventListeners();\n log('Widget created');\n }\n\n function buildWidgetHtml() {\n var html = '';\n\n // Tab button\n html += '<button id=\"pa-feedback-tab\" class=\"pa-feedback-tab\" aria-label=\"' + FB.translations.title + '\">';\n html += '<span class=\"pa-feedback-tab-text\">${config.tabText}</span>';\n html += '</button>';\n\n // Modal\n html += '<div id=\"pa-feedback-modal\" class=\"pa-feedback-modal pa-feedback-hidden\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"pa-feedback-title\">';\n html += '<div class=\"pa-feedback-content\">';\n\n // Header\n html += '<div class=\"pa-feedback-header\">';\n html += '<h3 id=\"pa-feedback-title\">' + FB.translations.title + '</h3>';\n html += '<button id=\"pa-feedback-close\" class=\"pa-feedback-close\" aria-label=\"Close\">×</button>';\n html += '</div>';\n\n // Form\n html += '<form id=\"pa-feedback-form\">';\n\n // Rating (if enabled)\n ${config.showRating ? `\n html += '<div class=\"pa-feedback-field\">';\n html += '<label class=\"pa-feedback-label\">' + FB.translations.ratingLabel + '${config.ratingRequired ? ' <span class=\"pa-feedback-required\">*</span>' : ''}</label>';\n html += '<div class=\"pa-feedback-stars\" role=\"radiogroup\" aria-label=\"Rating\">';\n for (var i = 1; i <= ${config.ratingStars}; i++) {\n html += '<button type=\"button\" class=\"pa-feedback-star\" data-value=\"' + i + '\" role=\"radio\" aria-checked=\"false\" aria-label=\"' + i + ' star\">☆</button>';\n }\n html += '</div>';\n html += '</div>';\n ` : ''}\n\n // Issue Type (if enabled)\n ${config.showIssueType ? `\n html += '<div class=\"pa-feedback-field\">';\n html += '<label class=\"pa-feedback-label\" for=\"pa-feedback-issue-type\">' + FB.translations.issueTypeLabel + '${config.issueTypeRequired ? ' <span class=\"pa-feedback-required\">*</span>' : ''}</label>';\n html += '<select id=\"pa-feedback-issue-type\" class=\"pa-feedback-select\">';\n html += '<option value=\"\">' + FB.translations.selectIssueType + '</option>';\n FB.issueTypes.forEach(function(type) {\n html += '<option value=\"' + type.id + '\">' + type.label + '</option>';\n });\n html += '</select>';\n html += '</div>';\n\n // Subtype container (hidden by default)\n html += '<div id=\"pa-feedback-subtype-field\" class=\"pa-feedback-field pa-feedback-hidden\">';\n html += '<label class=\"pa-feedback-label\" for=\"pa-feedback-subtype\">' + FB.translations.subtypeLabel + '</label>';\n html += '<select id=\"pa-feedback-subtype\" class=\"pa-feedback-select\">';\n html += '<option value=\"\">' + FB.translations.selectSubtype + '</option>';\n html += '</select>';\n html += '</div>';\n ` : ''}\n\n // Comment (if enabled)\n ${config.showComment ? `\n html += '<div class=\"pa-feedback-field\">';\n html += '<label class=\"pa-feedback-label\" for=\"pa-feedback-comment\">' + FB.translations.commentLabel + '${config.commentRequired ? ' <span class=\"pa-feedback-required\">*</span>' : ''}</label>';\n html += '<textarea id=\"pa-feedback-comment\" class=\"pa-feedback-textarea\" maxlength=\"${config.commentMaxLength}\" placeholder=\"${config.commentPlaceholder || ''}\" rows=\"4\"></textarea>';\n html += '<div class=\"pa-feedback-counter\"><span id=\"pa-feedback-char-count\">0</span>/${config.commentMaxLength}</div>';\n html += '</div>';\n ` : ''}\n\n // Error message area\n html += '<div id=\"pa-feedback-error\" class=\"pa-feedback-error pa-feedback-hidden\"></div>';\n\n // Submit button\n html += '<button type=\"submit\" id=\"pa-feedback-submit\" class=\"pa-feedback-submit\">';\n html += '<span class=\"pa-feedback-submit-text\">' + FB.translations.submit + '</span>';\n html += '<span class=\"pa-feedback-submit-loading pa-feedback-hidden\">' + FB.translations.submitting + '</span>';\n html += '</button>';\n\n html += '</form>';\n\n // Success message\n html += '<div id=\"pa-feedback-success\" class=\"pa-feedback-success pa-feedback-hidden\">';\n html += '<div class=\"pa-feedback-checkmark\">✓</div>';\n html += '<p>' + FB.translations.thankYou + '</p>';\n html += '</div>';\n\n html += '</div>'; // content\n html += '</div>'; // modal\n\n return html;\n }\n\n // ============================================================================\n // EVENT HANDLERS\n // ============================================================================\n\n function setupEventListeners() {\n // Tab click\n document.getElementById('pa-feedback-tab').addEventListener('click', toggleModal);\n\n // Close button\n document.getElementById('pa-feedback-close').addEventListener('click', closeModal);\n\n // Form submit\n document.getElementById('pa-feedback-form').addEventListener('submit', handleSubmit);\n\n // Click outside to close\n document.getElementById('pa-feedback-modal').addEventListener('click', function(e) {\n if (e.target === this) closeModal();\n });\n\n // Escape key to close\n document.addEventListener('keydown', function(e) {\n if (e.key === 'Escape' && FB.isOpen) closeModal();\n });\n\n ${config.showRating ? `\n // Star rating\n var stars = document.querySelectorAll('.pa-feedback-star');\n stars.forEach(function(star, index) {\n star.addEventListener('click', function() {\n FB.rating = index + 1;\n updateStars();\n });\n star.addEventListener('mouseenter', function() {\n highlightStars(index + 1);\n });\n });\n document.querySelector('.pa-feedback-stars').addEventListener('mouseleave', function() {\n highlightStars(FB.rating);\n });\n ` : ''}\n\n ${config.showIssueType ? `\n // Issue type change\n document.getElementById('pa-feedback-issue-type').addEventListener('change', updateSubtypes);\n ` : ''}\n\n ${config.showComment ? `\n // Character counter\n document.getElementById('pa-feedback-comment').addEventListener('input', updateCharCount);\n ` : ''}\n }\n\n function toggleModal() {\n if (FB.isOpen) {\n closeModal();\n } else {\n openModal();\n }\n }\n\n function openModal() {\n FB.isOpen = true;\n document.getElementById('pa-feedback-modal').classList.remove('pa-feedback-hidden');\n document.getElementById('pa-feedback-tab').classList.add('pa-feedback-tab-active');\n log('Modal opened');\n }\n\n function closeModal() {\n FB.isOpen = false;\n document.getElementById('pa-feedback-modal').classList.add('pa-feedback-hidden');\n document.getElementById('pa-feedback-tab').classList.remove('pa-feedback-tab-active');\n log('Modal closed');\n }\n\n ${config.showRating ? `\n function updateStars() {\n var stars = document.querySelectorAll('.pa-feedback-star');\n stars.forEach(function(star, index) {\n var isFilled = index < FB.rating;\n star.innerHTML = isFilled ? '★' : '☆';\n star.classList.toggle('pa-feedback-star-filled', isFilled);\n star.setAttribute('aria-checked', isFilled ? 'true' : 'false');\n });\n }\n\n function highlightStars(count) {\n var stars = document.querySelectorAll('.pa-feedback-star');\n stars.forEach(function(star, index) {\n var isFilled = index < count;\n star.innerHTML = isFilled ? '★' : '☆';\n star.classList.toggle('pa-feedback-star-hover', isFilled && count > FB.rating);\n });\n }\n ` : ''}\n\n ${config.showIssueType ? `\n function updateSubtypes() {\n var typeSelect = document.getElementById('pa-feedback-issue-type');\n var subtypeField = document.getElementById('pa-feedback-subtype-field');\n var subtypeSelect = document.getElementById('pa-feedback-subtype');\n var selectedType = typeSelect.value;\n\n // Find the selected issue type\n var issueType = FB.issueTypes.find(function(t) { return t.id === selectedType; });\n\n if (issueType && issueType.subtypes && issueType.subtypes.length > 0) {\n // Populate subtypes\n subtypeSelect.innerHTML = '<option value=\"\">' + FB.translations.selectSubtype + '</option>';\n issueType.subtypes.forEach(function(subtype) {\n subtypeSelect.innerHTML += '<option value=\"' + subtype.id + '\">' + subtype.label + '</option>';\n });\n subtypeField.classList.remove('pa-feedback-hidden');\n } else {\n subtypeField.classList.add('pa-feedback-hidden');\n subtypeSelect.value = '';\n }\n }\n ` : ''}\n\n ${config.showComment ? `\n function updateCharCount() {\n var textarea = document.getElementById('pa-feedback-comment');\n var counter = document.getElementById('pa-feedback-char-count');\n counter.textContent = textarea.value.length;\n }\n ` : ''}\n\n // ============================================================================\n // FORM SUBMISSION\n // ============================================================================\n\n function validateForm() {\n var errors = [];\n\n ${config.showRating && config.ratingRequired ? `\n if (FB.rating === 0) {\n errors.push('Rating is required');\n }\n ` : ''}\n\n ${config.showIssueType && config.issueTypeRequired ? `\n if (!document.getElementById('pa-feedback-issue-type').value) {\n errors.push('Issue type is required');\n }\n ` : ''}\n\n ${config.showComment && config.commentRequired ? `\n if (!document.getElementById('pa-feedback-comment').value.trim()) {\n errors.push('Comment is required');\n }\n ` : ''}\n\n return errors;\n }\n\n function collectFormData() {\n var data = {};\n\n ${config.showRating ? `data.rating = FB.rating;` : ''}\n ${config.showIssueType ? `\n data.issueType = document.getElementById('pa-feedback-issue-type').value || null;\n data.issueSubtype = document.getElementById('pa-feedback-subtype').value || null;\n ` : ''}\n ${config.showComment ? `data.comment = document.getElementById('pa-feedback-comment').value.trim();` : ''}\n\n // Add metadata\n data.metadata = collectMetadata();\n\n return data;\n }\n\n function collectMetadata() {\n var meta = {};\n var cfg = FB.config.includeMetadata;\n\n if (cfg.courseId && window.pa_patcher && window.pa_patcher.lrs && window.pa_patcher.lrs.courseInfo) {\n meta.courseId = window.pa_patcher.lrs.courseInfo.id;\n meta.courseTitle = window.pa_patcher.lrs.courseInfo.title;\n }\n\n if (cfg.lessonId) {\n meta.lessonId = window.location.hash || window.location.pathname;\n }\n\n if (cfg.userAgent) {\n meta.userAgent = navigator.userAgent;\n }\n\n if (cfg.timestamp) {\n meta.timestamp = new Date().toISOString();\n }\n\n if (cfg.url) {\n meta.url = window.location.href;\n }\n\n return meta;\n }\n\n function showError(message) {\n var errorEl = document.getElementById('pa-feedback-error');\n errorEl.textContent = message;\n errorEl.classList.remove('pa-feedback-hidden');\n }\n\n function hideError() {\n document.getElementById('pa-feedback-error').classList.add('pa-feedback-hidden');\n }\n\n function setSubmitting(isSubmitting) {\n var submitBtn = document.getElementById('pa-feedback-submit');\n var textEl = submitBtn.querySelector('.pa-feedback-submit-text');\n var loadingEl = submitBtn.querySelector('.pa-feedback-submit-loading');\n\n submitBtn.disabled = isSubmitting;\n textEl.classList.toggle('pa-feedback-hidden', isSubmitting);\n loadingEl.classList.toggle('pa-feedback-hidden', !isSubmitting);\n }\n\n function showSuccess() {\n document.getElementById('pa-feedback-form').classList.add('pa-feedback-hidden');\n document.getElementById('pa-feedback-success').classList.remove('pa-feedback-hidden');\n\n if (FB.config.autoClose) {\n setTimeout(function() {\n closeModal();\n resetForm();\n }, FB.config.autoCloseDelay);\n }\n }\n\n function resetForm() {\n var form = document.getElementById('pa-feedback-form');\n form.reset();\n form.classList.remove('pa-feedback-hidden');\n document.getElementById('pa-feedback-success').classList.add('pa-feedback-hidden');\n hideError();\n\n FB.rating = 0;\n ${config.showRating ? 'updateStars();' : ''}\n ${config.showComment ? 'updateCharCount();' : ''}\n ${config.showIssueType ? `\n document.getElementById('pa-feedback-subtype-field').classList.add('pa-feedback-hidden');\n ` : ''}\n }\n\n async function handleSubmit(e) {\n e.preventDefault();\n hideError();\n\n // Validate\n var errors = validateForm();\n if (errors.length > 0) {\n showError(FB.translations.errorRequired);\n return;\n }\n\n // Collect data\n var data = collectFormData();\n log('Submitting:', data);\n\n // Submit\n setSubmitting(true);\n\n try {\n ${config.endpoint ? `\n var response = await fetch('${config.endpoint}', {\n method: '${config.method}',\n headers: Object.assign({\n 'Content-Type': 'application/json',\n }, FB.config.headers || {}),\n body: JSON.stringify(data),\n });\n\n if (!response.ok) {\n throw new Error('HTTP ' + response.status);\n }\n\n log('Submitted successfully');\n ` : `\n // No endpoint configured - just log\n console.log('[PA-Feedback] Feedback submitted:', data);\n log('No endpoint configured, feedback logged to console');\n `}\n\n showSuccess();\n } catch (err) {\n log('Submit error:', err);\n showError(FB.translations.errorSubmitting);\n } finally {\n setSubmitting(false);\n }\n }\n\n // ============================================================================\n // INITIALIZATION\n // ============================================================================\n\n function init() {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', createWidget);\n } else {\n createWidget();\n }\n log('Initialized');\n }\n\n init();\n\n})();\n`;\n}\n","import type { FeedbackConfig } from './config.js';\n\n/**\n * Generate the CSS styles for the feedback widget.\n * Styles are scoped with #pa-feedback-container to avoid conflicts.\n */\nexport function generateFeedbackStyles(config: FeedbackConfig): string {\n const position = config.position;\n const tabColor = config.tabColor;\n const tabTextColor = config.tabTextColor;\n const zIndex = config.zIndex;\n\n // Pre-compute position-dependent values\n const isRight = position === 'right';\n const tabTransform = isRight ? '-90deg' : '90deg';\n const tabTransformOrigin = isRight ? 'right center' : 'left center';\n const tabOffset = isRight ? 'right: 20px; left: auto;' : 'left: 20px; right: auto;';\n const tabBorderRadius = isRight ? '8px 8px 0 0' : '0 0 8px 8px';\n const modalPosition = isRight ? 'right: 0; left: auto;' : 'left: 0; right: auto;';\n const modalJustify = isRight ? 'flex-end' : 'flex-start';\n const contentShadow = isRight ? '-4px 0 20px rgba(0, 0, 0, 0.15)' : '4px 0 20px rgba(0, 0, 0, 0.15)';\n const slideFrom = isRight ? '100%' : '-100%';\n\n return `\n/* ============================================================================\n FEEDBACK WIDGET STYLES - Patch-Adams Plugin v1.0.0\n ============================================================================ */\n\n#pa-feedback-container {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: #333;\n box-sizing: border-box;\n}\n\n#pa-feedback-container *,\n#pa-feedback-container *::before,\n#pa-feedback-container *::after {\n box-sizing: inherit;\n}\n\n/* Hidden utility class */\n#pa-feedback-container .pa-feedback-hidden {\n display: none !important;\n}\n\n/* ============================================================================\n TAB BUTTON\n ============================================================================ */\n\n#pa-feedback-tab {\n position: fixed;\n top: 50%;\n ${tabOffset}\n transform: translateY(-50%) rotate(${tabTransform});\n transform-origin: ${tabTransformOrigin};\n z-index: ${zIndex};\n background: ${tabColor};\n color: ${tabTextColor};\n border: none;\n padding: 10px 20px;\n font-size: 14px;\n font-weight: 600;\n cursor: pointer;\n border-radius: ${tabBorderRadius};\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n transition: all 0.2s ease;\n white-space: nowrap;\n}\n\n#pa-feedback-tab:hover {\n background: ${adjustColor(tabColor, -15)};\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n}\n\n#pa-feedback-tab:focus {\n outline: 2px solid ${tabColor};\n outline-offset: 2px;\n}\n\n#pa-feedback-tab.pa-feedback-tab-active {\n background: ${adjustColor(tabColor, -20)};\n}\n\n/* ============================================================================\n MODAL\n ============================================================================ */\n\n#pa-feedback-modal {\n position: fixed;\n top: 0;\n ${modalPosition}\n width: 360px;\n height: 100%;\n z-index: ${zIndex + 1};\n background: rgba(0, 0, 0, 0.3);\n display: flex;\n justify-content: ${modalJustify};\n animation: pa-feedback-fade-in 0.2s ease;\n}\n\n@keyframes pa-feedback-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n#pa-feedback-container .pa-feedback-content {\n width: 100%;\n max-width: 360px;\n height: 100%;\n background: #fff;\n box-shadow: ${contentShadow};\n display: flex;\n flex-direction: column;\n animation: pa-feedback-slide-in 0.2s ease;\n}\n\n@keyframes pa-feedback-slide-in {\n from {\n transform: translateX(${slideFrom});\n }\n to {\n transform: translateX(0);\n }\n}\n\n/* ============================================================================\n HEADER\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid #e5e5e5;\n background: #fafafa;\n}\n\n#pa-feedback-container .pa-feedback-header h3 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n color: #222;\n}\n\n#pa-feedback-container .pa-feedback-close {\n background: none;\n border: none;\n font-size: 24px;\n color: #666;\n cursor: pointer;\n padding: 4px 8px;\n line-height: 1;\n border-radius: 4px;\n transition: all 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-close:hover {\n background: #e5e5e5;\n color: #333;\n}\n\n/* ============================================================================\n FORM\n ============================================================================ */\n\n#pa-feedback-form {\n flex: 1;\n overflow-y: auto;\n padding: 20px;\n display: flex;\n flex-direction: column;\n gap: 20px;\n}\n\n#pa-feedback-container .pa-feedback-field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n#pa-feedback-container .pa-feedback-label {\n font-weight: 500;\n color: #444;\n font-size: 14px;\n}\n\n#pa-feedback-container .pa-feedback-required {\n color: #dc3545;\n}\n\n/* ============================================================================\n STAR RATING\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-stars {\n display: flex;\n gap: 4px;\n}\n\n#pa-feedback-container .pa-feedback-star {\n background: none;\n border: none;\n font-size: 28px;\n color: #ccc;\n cursor: pointer;\n padding: 4px;\n line-height: 1;\n transition: all 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-star:hover {\n transform: scale(1.1);\n}\n\n#pa-feedback-container .pa-feedback-star-filled,\n#pa-feedback-container .pa-feedback-star-hover {\n color: #ffc107;\n}\n\n/* ============================================================================\n SELECT & TEXTAREA\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-select {\n width: 100%;\n padding: 10px 12px;\n font-size: 14px;\n border: 1px solid #ddd;\n border-radius: 6px;\n background: #fff;\n color: #333;\n cursor: pointer;\n transition: border-color 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-select:focus {\n outline: none;\n border-color: ${tabColor};\n box-shadow: 0 0 0 3px ${hexToRgba(tabColor, 0.1)};\n}\n\n#pa-feedback-container .pa-feedback-textarea {\n width: 100%;\n padding: 12px;\n font-size: 14px;\n font-family: inherit;\n border: 1px solid #ddd;\n border-radius: 6px;\n resize: vertical;\n min-height: 100px;\n transition: border-color 0.15s ease;\n}\n\n#pa-feedback-container .pa-feedback-textarea:focus {\n outline: none;\n border-color: ${tabColor};\n box-shadow: 0 0 0 3px ${hexToRgba(tabColor, 0.1)};\n}\n\n#pa-feedback-container .pa-feedback-textarea::placeholder {\n color: #999;\n}\n\n#pa-feedback-container .pa-feedback-counter {\n text-align: right;\n font-size: 12px;\n color: #888;\n}\n\n/* ============================================================================\n ERROR MESSAGE\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-error {\n background: #fee2e2;\n color: #dc2626;\n padding: 10px 14px;\n border-radius: 6px;\n font-size: 13px;\n}\n\n/* ============================================================================\n SUBMIT BUTTON\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-submit {\n width: 100%;\n padding: 12px 20px;\n font-size: 16px;\n font-weight: 600;\n color: #fff;\n background: ${tabColor};\n border: none;\n border-radius: 6px;\n cursor: pointer;\n transition: all 0.15s ease;\n margin-top: auto;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n}\n\n#pa-feedback-container .pa-feedback-submit:hover:not(:disabled) {\n background: ${adjustColor(tabColor, -15)};\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);\n transform: translateY(-1px);\n}\n\n#pa-feedback-container .pa-feedback-submit:focus {\n outline: 2px solid ${tabColor};\n outline-offset: 2px;\n}\n\n#pa-feedback-container .pa-feedback-submit:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n}\n\n/* ============================================================================\n SUCCESS MESSAGE\n ============================================================================ */\n\n#pa-feedback-container .pa-feedback-success {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px 20px;\n text-align: center;\n}\n\n#pa-feedback-container .pa-feedback-checkmark {\n width: 64px;\n height: 64px;\n background: #10b981;\n color: #fff;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 32px;\n margin-bottom: 20px;\n animation: pa-feedback-pop 0.3s ease;\n}\n\n@keyframes pa-feedback-pop {\n 0% { transform: scale(0); }\n 50% { transform: scale(1.2); }\n 100% { transform: scale(1); }\n}\n\n#pa-feedback-container .pa-feedback-success p {\n margin: 0;\n font-size: 18px;\n font-weight: 500;\n color: #333;\n}\n`;\n}\n\n/**\n * Adjust a hex color by a percentage (positive = lighter, negative = darker)\n */\nfunction adjustColor(hex: string, percent: number): string {\n // Remove # if present\n hex = hex.replace(/^#/, '');\n\n // Parse the color\n let r = parseInt(hex.substring(0, 2), 16);\n let g = parseInt(hex.substring(2, 4), 16);\n let b = parseInt(hex.substring(4, 6), 16);\n\n // Adjust\n r = Math.min(255, Math.max(0, r + (r * percent) / 100));\n g = Math.min(255, Math.max(0, g + (g * percent) / 100));\n b = Math.min(255, Math.max(0, b + (b * percent) / 100));\n\n // Convert back to hex\n return (\n '#' +\n Math.round(r).toString(16).padStart(2, '0') +\n Math.round(g).toString(16).padStart(2, '0') +\n Math.round(b).toString(16).padStart(2, '0')\n );\n}\n\n/**\n * Convert hex color to rgba\n */\nfunction hexToRgba(hex: string, alpha: number): string {\n hex = hex.replace(/^#/, '');\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n","/**\n * @patch-adams/plugin-feedback\n *\n * Feedback widget plugin for Patch-Adams.\n * Injects a customizable feedback form into patched Rise courses.\n *\n * Features:\n * - Star rating\n * - Issue type/subtype selection\n * - Comment text area\n * - Multi-language support (en/fr)\n * - Customizable appearance\n * - Automatic metadata collection\n * - Configurable API endpoint\n */\n\nimport type { PatchAdamsPlugin } from '@patch-adams/core';\nimport { FeedbackConfigSchema, type FeedbackConfig } from './config.js';\nimport { generateFeedbackWidget } from './widget.js';\nimport { generateFeedbackStyles } from './styles.js';\n\n/**\n * Feedback plugin for Patch-Adams\n */\nexport const feedbackPlugin: PatchAdamsPlugin<FeedbackConfig> = {\n name: 'feedback',\n version: '1.0.0',\n description: 'Inject a feedback form widget into Rise courses for collecting user feedback',\n configSchema: FeedbackConfigSchema,\n\n generateCss(config: FeedbackConfig) {\n return {\n after: generateFeedbackStyles(config),\n };\n },\n\n generateJs(config: FeedbackConfig) {\n return {\n after: generateFeedbackWidget(config),\n };\n },\n};\n\n// Default export for convenience\nexport default feedbackPlugin;\n\n// Re-export types and utilities\nexport {\n FeedbackConfigSchema,\n type FeedbackConfig,\n type IssueType,\n type IssueSubtype,\n type MetadataOptions,\n DEFAULT_ISSUE_TYPES,\n} from './config.js';\n\nexport { generateFeedbackWidget } from './widget.js';\nexport { generateFeedbackStyles } from './styles.js';\nexport { getTranslations, translations, type Translations } from './i18n/index.js';\n"]}
|
package/package.json
CHANGED