hocmai-feedback-widget 0.2.1 → 0.2.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/README.md +78 -113
- package/dist/capture/device-detection.d.ts +13 -0
- package/dist/capture/fonts.d.ts +4 -0
- package/dist/capture/index.d.ts +14 -0
- package/dist/capture/mathjax-fonts.d.ts +5 -0
- package/dist/capture/types.d.ts +25 -0
- package/dist/ckeditor.mjs +113 -0
- package/dist/ckeditor.mjs.map +1 -0
- package/dist/components/CkEditor.d.ts +14 -0
- package/dist/components/FeedbackWidget.d.ts +13 -1
- package/dist/context/FeedbackContext.d.ts +14 -2
- package/dist/hocmai-feedback-widget.mjs +7550 -0
- package/dist/hocmai-feedback-widget.mjs.map +1 -0
- package/dist/index.d.ts +4 -2
- package/package.json +39 -29
- package/src/App.tsx +147 -58
- package/src/capture/device-detection.ts +52 -0
- package/src/capture/fonts.ts +34 -0
- package/src/capture/index.ts +361 -0
- package/src/capture/mathjax-fonts.ts +143 -0
- package/src/capture/types.ts +34 -0
- package/src/ckeditor.d.ts +14 -0
- package/src/components/CkEditor.tsx +130 -0
- package/src/components/CropOverlay.tsx +29 -47
- package/src/components/FeedbackWidget.tsx +105 -93
- package/src/context/FeedbackContext.tsx +49 -9
- package/src/index.ts +9 -3
- package/src/main.tsx +7 -9
- package/src/utils/device.ts +14 -14
- package/dist/support-feedback-lib.es.js +0 -3946
- package/dist/support-feedback-lib.umd.js +0 -84
- package/dist/test-mobile-screenshot.html +0 -211
- package/dist/test-simple-capture.html +0 -107
- package/dist/utils/screenshot/background-renderer.d.ts +0 -3
- package/dist/utils/screenshot/canvas-renderer.d.ts +0 -9
- package/dist/utils/screenshot/cleanup.d.ts +0 -3
- package/dist/utils/screenshot/device-detection.d.ts +0 -16
- package/dist/utils/screenshot/element-collector.d.ts +0 -10
- package/dist/utils/screenshot/image-renderer.d.ts +0 -21
- package/dist/utils/screenshot/performance.d.ts +0 -3
- package/dist/utils/screenshot/svg-renderer.d.ts +0 -24
- package/dist/utils/screenshot/text-renderer.d.ts +0 -23
- package/dist/utils/screenshot/types.d.ts +0 -35
- package/dist/utils/screenshot.d.ts +0 -9
- package/dist/vite.svg +0 -1
- package/src/App.css +0 -42
- package/src/assets/react.svg +0 -1
- package/src/index.css +0 -68
- package/src/utils/screenshot/background-renderer.ts +0 -54
- package/src/utils/screenshot/canvas-renderer.ts +0 -343
- package/src/utils/screenshot/cleanup.ts +0 -32
- package/src/utils/screenshot/device-detection.ts +0 -90
- package/src/utils/screenshot/element-collector.ts +0 -134
- package/src/utils/screenshot/image-renderer.ts +0 -148
- package/src/utils/screenshot/performance.ts +0 -57
- package/src/utils/screenshot/svg-renderer.ts +0 -149
- package/src/utils/screenshot/text-renderer.ts +0 -212
- package/src/utils/screenshot/types.ts +0 -40
- package/src/utils/screenshot.ts +0 -83
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import React, { createContext, useContext, useState, type ReactNode } from 'react';
|
|
2
2
|
import FeedbackWidget, { type FeedbackData } from '../components/FeedbackWidget';
|
|
3
|
+
import type { CkEditorProps } from '../components/CkEditor';
|
|
4
|
+
|
|
5
|
+
export type FeedbackSubmitHandler = (data: FeedbackData) => Promise<void> | void;
|
|
3
6
|
|
|
4
7
|
interface FeedbackContextType {
|
|
5
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Open the report form.
|
|
10
|
+
* @param onSubmit optional per-call handler; overrides the Provider's onSubmit
|
|
11
|
+
* for this submission. Lets you handle submit from anywhere.
|
|
12
|
+
*/
|
|
13
|
+
openFeedback: (
|
|
14
|
+
questionId: string | number,
|
|
15
|
+
contextData?: any,
|
|
16
|
+
onSubmit?: FeedbackSubmitHandler
|
|
17
|
+
) => void;
|
|
6
18
|
closeFeedback: () => void;
|
|
7
19
|
isOpen: boolean;
|
|
8
20
|
activeQuestionId: string | number | null;
|
|
@@ -20,47 +32,75 @@ export const useFeedback = () => {
|
|
|
20
32
|
|
|
21
33
|
interface FeedbackProviderProps {
|
|
22
34
|
children: ReactNode;
|
|
23
|
-
|
|
35
|
+
/** Default submit handler. Optional — you can instead pass one per call via openFeedback. */
|
|
36
|
+
onSubmit?: FeedbackSubmitHandler;
|
|
24
37
|
themeColor?: string;
|
|
38
|
+
/** Use the rich-text editor for the description instead of a plain textarea. */
|
|
39
|
+
isCkEditor?: boolean;
|
|
40
|
+
/** Editor component for the description (from `hocmai-feedback-widget/ckeditor` or your own). */
|
|
41
|
+
descriptionEditor?: React.ComponentType<CkEditorProps>;
|
|
25
42
|
}
|
|
26
43
|
|
|
27
44
|
export const FeedbackProvider: React.FC<FeedbackProviderProps> = ({
|
|
28
45
|
children,
|
|
29
46
|
onSubmit,
|
|
30
|
-
themeColor
|
|
47
|
+
themeColor,
|
|
48
|
+
isCkEditor,
|
|
49
|
+
descriptionEditor,
|
|
31
50
|
}) => {
|
|
32
51
|
const [isOpen, setIsOpen] = useState(false);
|
|
33
52
|
const [activeQuestionId, setActiveQuestionId] = useState<string | number | null>(null);
|
|
34
53
|
const [activeContextData, setActiveContextData] = useState<any>(undefined);
|
|
54
|
+
// Per-call submit handler set by openFeedback (stored via updater so React
|
|
55
|
+
// doesn't treat the function as a state initializer).
|
|
56
|
+
const [activeOnSubmit, setActiveOnSubmit] = useState<FeedbackSubmitHandler | undefined>(undefined);
|
|
35
57
|
|
|
36
|
-
const openFeedback = (
|
|
58
|
+
const openFeedback = (
|
|
59
|
+
questionId: string | number,
|
|
60
|
+
contextData?: any,
|
|
61
|
+
perCallOnSubmit?: FeedbackSubmitHandler
|
|
62
|
+
) => {
|
|
37
63
|
setActiveQuestionId(questionId);
|
|
38
64
|
setActiveContextData(contextData);
|
|
65
|
+
setActiveOnSubmit(() => perCallOnSubmit);
|
|
39
66
|
setIsOpen(true);
|
|
40
67
|
};
|
|
41
68
|
|
|
42
69
|
const closeFeedback = () => {
|
|
43
70
|
setIsOpen(false);
|
|
44
|
-
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// Resolve handler: per-call → Provider → warn (never crash).
|
|
74
|
+
const effectiveOnSubmit: FeedbackSubmitHandler = async (data) => {
|
|
75
|
+
const handler = activeOnSubmit ?? onSubmit;
|
|
76
|
+
if (!handler) {
|
|
77
|
+
console.warn(
|
|
78
|
+
'[feedback-widget] Bỏ qua gửi báo lỗi: chưa cung cấp onSubmit (ở FeedbackProvider hoặc openFeedback). Dữ liệu:',
|
|
79
|
+
data
|
|
80
|
+
);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
await handler(data);
|
|
45
84
|
};
|
|
46
85
|
|
|
47
86
|
return (
|
|
48
87
|
<FeedbackContext.Provider value={{ openFeedback, closeFeedback, isOpen, activeQuestionId }}>
|
|
49
88
|
{children}
|
|
50
89
|
|
|
51
|
-
{/* The
|
|
90
|
+
{/* The single global widget */}
|
|
52
91
|
{activeQuestionId && (
|
|
53
92
|
<FeedbackWidget
|
|
54
93
|
questionId={activeQuestionId}
|
|
55
94
|
contextData={activeContextData}
|
|
56
|
-
onSubmit={
|
|
95
|
+
onSubmit={effectiveOnSubmit}
|
|
57
96
|
themeColor={themeColor}
|
|
97
|
+
isCkEditor={isCkEditor}
|
|
98
|
+
descriptionEditor={descriptionEditor}
|
|
58
99
|
isOpen={isOpen}
|
|
59
100
|
onClose={closeFeedback}
|
|
60
|
-
// We don't need triggerComponent here because triggers are distributed
|
|
61
101
|
triggerComponent={<></>}
|
|
62
102
|
/>
|
|
63
103
|
)}
|
|
64
104
|
</FeedbackContext.Provider>
|
|
65
105
|
);
|
|
66
|
-
};
|
|
106
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
export { default as FeedbackWidget } from './components/FeedbackWidget';
|
|
2
2
|
export type { FeedbackData, FeedbackProps } from './components/FeedbackWidget';
|
|
3
|
+
export type { CkEditorProps } from './components/CkEditor';
|
|
3
4
|
export { FeedbackProvider, useFeedback } from './context/FeedbackContext';
|
|
5
|
+
export type { FeedbackSubmitHandler } from './context/FeedbackContext';
|
|
4
6
|
|
|
5
|
-
//
|
|
6
|
-
export {
|
|
7
|
-
|
|
7
|
+
// Screenshot utilities (MathJax-CHTML aware, snapdom-based)
|
|
8
|
+
export {
|
|
9
|
+
captureScreenshot,
|
|
10
|
+
captureScreenshotWithOptions,
|
|
11
|
+
prewarmCapture,
|
|
12
|
+
} from './capture';
|
|
13
|
+
export type { Rect, CaptureProgress, CaptureOptions } from './capture/types';
|
package/src/main.tsx
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import './index.css'
|
|
4
|
-
import App from './App.tsx'
|
|
1
|
+
import ReactDOM from 'react-dom/client';
|
|
2
|
+
import App from './App';
|
|
5
3
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
)
|
|
4
|
+
// NOTE: No <React.StrictMode> on purpose. In dev, StrictMode double-mounts
|
|
5
|
+
// components, and @ckeditor/ckeditor5-react creates a second editor instance
|
|
6
|
+
// during the remount (its async destroy hasn't finished) — showing TWO editors.
|
|
7
|
+
// The host app runs without StrictMode, so this matches production behaviour.
|
|
8
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(<App />);
|
package/src/utils/device.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { UAParser } from 'ua-parser-js';
|
|
2
2
|
|
|
3
3
|
export interface DeviceInfo {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
os: string;
|
|
5
|
+
osVersion: string;
|
|
6
|
+
browser: string;
|
|
7
|
+
browserVersion: string;
|
|
8
|
+
deviceType: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export const getDeviceInfo = (): DeviceInfo => {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const parser = new UAParser();
|
|
13
|
+
const result = parser.getResult();
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
return {
|
|
16
|
+
os: result.os.name || 'unknown',
|
|
17
|
+
osVersion: result.os.version || 'unknown',
|
|
18
|
+
browser: result.browser.name || 'unknown',
|
|
19
|
+
browserVersion: result.browser.version || 'unknown',
|
|
20
|
+
deviceType: result.device.type || 'desktop',
|
|
21
|
+
};
|
|
22
22
|
};
|