@magicfeedback/native 2.2.0-alpha.4 → 2.2.0-alpha.6

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 CHANGED
@@ -1,560 +1,400 @@
1
- # MagicFeedbackAI SDK
1
+ # MagicFeedback SDK
2
2
 
3
- This JavaScript library empowers you to effortlessly integrate the power
4
- of [MagicFeedback.io](https://magicfeedback.io/) into your web applications. With minimal code, you can capture valuable
5
- user feedback and insights, driving continuous improvement and enhancing user experience.
3
+ Browser SDK for rendering MagicFeedback surveys/forms, resuming sessions, previewing question definitions, and sending feedback directly from your app.
6
4
 
7
- ## Table of Contents
5
+ ## What this SDK covers
8
6
 
9
- * [Install](#install)
10
- * [Init](#init)
11
- * [How to use](#how-to-use)
12
- * [Answer format](#answer-format)
13
- * [Style](#style)
7
+ - Render a hosted MagicFeedback form with `appId` + `publicKey`
8
+ - Resume an existing survey flow with `sessionId`
9
+ - Submit feedback directly when you already own the UI
10
+ - Preview one or more question objects locally
11
+ - Use the bundled default theme or override CSS variables
12
+
13
+ ## Important before you start
14
+
15
+ - This is a browser-oriented SDK. It relies on `window`, `document`, `navigator`, and `localStorage`.
16
+ - Use it on the client side only. Server-side rendering and Node-only execution are not supported.
17
+ - Call `magicfeedback.init()` before `form()`, `session()`, or `send()`. `init()` sets the API base URL.
18
+ - `form.generate()` expects a DOM element id such as `"survey-root"`, not a CSS selector such as `"#survey-root"`.
14
19
 
15
20
  ## Install
16
21
 
17
- This library is available as a [package on NPM](https://www.npmjs.com/package/@magicfeedback/native). To install into a
18
- project using NPM with a front-end packager such as [Browserify](http://browserify.org/)
19
- or [Webpack](https://webpack.github.io/):
22
+ Install from [npm](https://www.npmjs.com/package/@magicfeedback/native):
20
23
 
21
24
  ```sh
22
- npm i @magicfeedback/native
25
+ npm install @magicfeedback/native
23
26
  ```
24
27
 
25
- You can then require the lib like a standard Node.js module:
26
-
27
- ```js
28
- var magicfeedback = require("@magicfeedback/native");
29
-
30
- // or
28
+ ## Quick start
31
29
 
32
- import magicfeedback from "@magicfeedback/native";
30
+ ### Plain HTML
33
31
 
32
+ ```html
33
+ <link
34
+ rel="stylesheet"
35
+ href="./node_modules/@magicfeedback/native/dist/styles/magicfeedback-default.css"
36
+ />
37
+
38
+ <div id="survey-root"></div>
39
+
40
+ <script src="./node_modules/@magicfeedback/native/dist/magicfeedback-sdk.browser.js"></script>
41
+ <script>
42
+ window.magicfeedback.init({
43
+ env: "prod",
44
+ debug: false
45
+ });
46
+
47
+ const form = window.magicfeedback.form("APP_ID", "PUBLIC_KEY");
48
+
49
+ form.generate("survey-root", {
50
+ addButton: true,
51
+ addSuccessScreen: true
52
+ });
53
+ </script>
34
54
  ```
35
55
 
36
- ## Init
56
+ ### Vite / Webpack / SPA
37
57
 
38
- This method is optional. You can start actived the debug mode to see on console the messages
58
+ ```ts
59
+ import magicfeedback from "@magicfeedback/native";
60
+ import "@magicfeedback/native/dist/styles/magicfeedback-default.css";
39
61
 
40
- ```js
41
62
  magicfeedback.init({
42
- debug: true | false, // Default false
43
- env: "prod", // Default
44
- dryRun: true | false // Default false. If true, survey answers are not sent to API.
45
- })
46
-
47
- ```
48
-
49
- `dryRun` is useful to preview surveys and test conditional logic without creating real feedback in MagicFeedback.
50
-
51
- ## How to use
52
-
53
- This guide provides instructions for utilizing various features and functionalities of the application. Each section
54
- below highlights a specific use case and provides a code snippet to demonstrate its implementation.
55
-
56
- ## Answer format
57
-
58
- See `docs/answer-format.md` for the per-type payload format produced by `Form.answer()`.
59
-
60
- ### A. Generate feedback forms
63
+ env: "prod"
64
+ });
61
65
 
62
- The feedback form generation functionality allows you to easily create and display feedback forms on your website. This
63
- section provides an overview of how to use this feature and the necessary code snippets.
66
+ const form = magicfeedback.form("APP_ID", "PUBLIC_KEY");
64
67
 
65
- To generate a feedback form, you need to include the following HTML code snippet in your web page:
68
+ await form.generate("survey-root", {
69
+ addButton: true,
70
+ addSuccessScreen: true
71
+ });
72
+ ```
66
73
 
67
74
  ```html
68
-
69
- <div id="demo_form_div"></div>
75
+ <div id="survey-root"></div>
70
76
  ```
71
77
 
72
- This code snippet creates a placeholder element with the ID "demo_form_div" where the feedback form will be inserted.
78
+ ## Initialization
73
79
 
74
- Next, you need to include the following JavaScript code snippet in your application:
75
-
76
- ```js
77
- let form = window.magicfeedback.form(
78
- "$_APP_ID",
79
- "$_PUBLIC_KEY"
80
- );
81
- // or
82
- let form = window.magicfeedback.session(
83
- "$_SESSION_ID",
84
- );
80
+ `init()` should be called once before any networked usage.
85
81
 
86
- form.generate(
87
- "demo_form_div",
88
- {
89
- addButton: true | false, // Default false, option to add a button to send the form
90
- sendButtonText: string, // Default "Send", option to change the text of the send button
91
- backButtonText: string, // Default "Back", option to change the text of the back button
92
- nextButtonText: string, // Default "Next", option to change the text of the next button
93
- addSuccessScreen: boolean, // Default flase, option to add a success screen after send the form
94
- successMessage: string, // Default "Thank you for your feedback!", option to change the success message
95
- questionFormat: "standard" | "slim", // Default "standard", option to change the format of the questions.
96
- getMetaData: boolean, // Default true, option to get the metadata of the form
97
- beforeSubmitEvent: ({
98
- loading: boolean,
99
- progress: number,
100
- total: number
101
- }) => {
102
- }, //Function to execute before send the form
103
- afterSubmitEvent: ({
104
- loading: boolean,
105
- progress: number,
106
- total: number,
107
- response: string, // Response of the server if everything is ok
108
- error: string, // Error of the server if something is wrong
109
- }) => {
110
- }, //Function to execute after send the form with the response
111
- onLoadedEvent: ({
112
- loading: boolean,
113
- progress: number,
114
- total: number,
115
- formData: FormData
116
- }) => {
117
- }, //Function to execute after load the form
118
- onBackEvent: ({
119
- loading: boolean,
120
- progress: number,
121
- followup: boolean,
122
- error: string, // Error of the server if something is wrong
123
- }) => {
124
- } //Function to execute after back the form
125
- /*
126
- class FormData {
127
- id: string;
128
- name: string;
129
- description: string;
130
- type: string;
131
- identity: string;
132
- status: string;
133
- createdAt: Date;
134
- updatedAt: Date;
135
- externalId?: string | null;
136
- companyId: string;
137
- productId: string;
138
- userId: string;
139
- setting: Record<string, any>;
140
- conf: Record<string, any>;
141
- */
142
- }
143
- )
82
+ ```ts
83
+ magicfeedback.init({
84
+ env: "prod",
85
+ debug: false,
86
+ dryRun: false
87
+ });
144
88
  ```
145
89
 
146
- In this code snippet, you need to replace $_APP_ID with the actual ID of your feedback application. This ID is provided
147
- by the magicfeedback service.
90
+ | Option | Type | Default | Description |
91
+ | --- | --- | --- | --- |
92
+ | `env` | `"prod" \| "dev"` | `"prod"` | Selects the production or development API host. |
93
+ | `debug` | `boolean` | `false` | Enables console logging. |
94
+ | `dryRun` | `boolean` | `false` | Loads and navigates forms without sending feedback or requesting follow-up questions. |
148
95
 
149
- The **form.generate()** function generates the feedback form inside the specified container element ("demo_form_div" in
150
- this example). You can customize the form generation by including the optional parameters:
96
+ `dryRun` is the safest way to QA a survey before giving it to a client.
151
97
 
152
- * **addButton**: This setting determines whether to include a "Submit" button that enables users to submit the form
153
- themselves. By default, this value is set to false, indicating that the button will not be displayed.
154
- * **beforeSubmitEvent**: An optional function that you can define to execute some actions or validations before the form
155
- is submitted.
156
- * **afterSubmitEvent**: An optional function that you can define to execute actions after the form is submitted. This
157
- function receives the server response as a parameter.
158
- * **onLoadedEvent**: An optional function that you can define to execute actions after the form is loaded.
98
+ ## Render a form
159
99
 
160
- In teh case that you don't want to use the buttons of the sdk to manage the send and back actions, you can use the
161
- following functions to manage the form.
100
+ Create a form instance with an app id and public key:
162
101
 
163
- ```js
164
- form.send() // Get the answers in the form to send and go to the next question or finish.
165
-
166
- form.back() // Go to the previous question.
102
+ ```ts
103
+ const form = magicfeedback.form("APP_ID", "PUBLIC_KEY");
167
104
  ```
168
105
 
169
- If you would like to include additional information with your feedback, you can do so by adding it to the `metadata`
170
- , `metrics` o `profile` variables. These variables are optional and should be formatted as follows:
171
-
172
- ```js
173
- [
174
- {
175
- "key": "key_1",
176
- "value": "value_1"
106
+ Then render it into a container:
107
+
108
+ ```ts
109
+ await form.generate("survey-root", {
110
+ addButton: true,
111
+ sendButtonText: "Send",
112
+ backButtonText: "Back",
113
+ nextButtonText: "Next",
114
+ startButtonText: "Start",
115
+ addSuccessScreen: true,
116
+ successMessage: "Thank you for your feedback!",
117
+ questionFormat: "standard",
118
+ getMetaData: true,
119
+ customMetaData: [
120
+ { key: "customer-id", value: ["acme-42"] },
121
+ { key: "plan", value: ["enterprise"] }
122
+ ],
123
+ onLoadedEvent: ({ formData, progress, total, error }) => {
124
+ console.log("loaded", { formData, progress, total, error });
177
125
  },
178
- {
179
- "key": "key_2",
180
- "value": "value_2"
126
+ beforeSubmitEvent: ({ progress, total }) => {
127
+ console.log("before submit", { progress, total });
181
128
  },
182
- /* ... */
183
- ]
129
+ afterSubmitEvent: ({ response, progress, total, completed, followup, error }) => {
130
+ console.log("after submit", {
131
+ response,
132
+ progress,
133
+ total,
134
+ completed,
135
+ followup,
136
+ error
137
+ });
138
+ },
139
+ onBackEvent: ({ progress, followup, error }) => {
140
+ console.log("back", { progress, followup, error });
141
+ }
142
+ });
184
143
  ```
185
144
 
186
- Here is an example of how to submit feedback with additional information:
187
-
188
- ```js
189
- form.send(
190
- metadata, //{key:string, value:string[]}[] OPTIONAL
191
- metrics, //{key:string, value:string[]}[] OPTIONAL
192
- profile, //{key:string, value:string[]}[] OPTIONAL
193
- )
145
+ ### `generate()` options used by the current runtime
146
+
147
+ | Option | Default | Description |
148
+ | --- | --- | --- |
149
+ | `addButton` | `true` | Renders the built-in action buttons. |
150
+ | `sendButtonText` | `"Send"` | Label for the final submit button. |
151
+ | `backButtonText` | `"Back"` | Label for the back button. |
152
+ | `nextButtonText` | `"Next"` | Label for the next button in multi-step flows. |
153
+ | `startButtonText` | `"Go!"` | Label for the start button when the form has a backend start message. |
154
+ | `addSuccessScreen` | `true` | Shows the built-in success view when the flow finishes. |
155
+ | `successMessage` | `"Thank you for your feedback!"` | Custom success text. |
156
+ | `questionFormat` | `"standard"` | `"standard"` or `"slim"`. |
157
+ | `getMetaData` | `true` | Appends browser and page metadata automatically. |
158
+ | `customMetaData` | `[]` | Extra metadata merged into `feedback.metadata` when `getMetaData` is enabled. |
159
+ | `onLoadedEvent` | `undefined` | Called after the form or start screen is ready. |
160
+ | `beforeSubmitEvent` | `undefined` | Called before a page is submitted. |
161
+ | `afterSubmitEvent` | `undefined` | Called after a page submit, follow-up render, or final completion. |
162
+ | `onBackEvent` | `undefined` | Called after navigating back. |
163
+
164
+ When `getMetaData` is enabled, the SDK includes the current URL, origin, pathname, query string, user agent, browser language, platform, app metadata, screen size, and the session id when rendering from `session()`.
165
+
166
+ ## Resume an existing session
167
+
168
+ If you already have a MagicFeedback session id, render it directly:
169
+
170
+ ```ts
171
+ magicfeedback.init({ env: "prod" });
172
+
173
+ const form = magicfeedback.session("SESSION_ID");
174
+ await form.generate("survey-root", {
175
+ addButton: true
176
+ });
194
177
  ```
195
178
 
196
- This function triggers the submission of the generated feedback form.
179
+ ## Manual navigation
197
180
 
198
- ![](./public/A_form.png)
181
+ If you want to control your own buttons, disable the built-in actions and call `send()` / `back()` yourself.
199
182
 
200
- By following these steps and including the appropriate HTML and JavaScript code snippets, you can easily generate and
201
- display feedback forms on your website using the magicfeedback service.
183
+ ```ts
184
+ const form = magicfeedback.form("APP_ID", "PUBLIC_KEY");
202
185
 
203
- ### B. Send feedback directly
186
+ await form.generate("survey-root", {
187
+ addButton: false
188
+ });
204
189
 
205
- With this option you can send feedback directly without generate a form. This section provides an overview of how to use
206
- this feature and the necessary code snippets.
190
+ document.getElementById("next-btn")?.addEventListener("click", () => {
191
+ form.send(
192
+ [{ key: "source", value: ["pricing-page"] }],
193
+ [{ key: "account-score", value: ["92"] }],
194
+ [{ key: "customer-email", value: ["user@example.com"] }]
195
+ );
196
+ });
207
197
 
208
- To send feedback directly, you need to include the following JavaScript code snippet in your application:
209
-
210
- ```js
211
- window.magicfeedback.send(
212
- "$_APP_ID",
213
- "$_PUBLIC_KEY",
214
- feedbackData,
215
- completed, // Default true
216
- "$_ID", // Optional
217
- "$_PRIVATE_KEY", // Optional
218
- )
198
+ document.getElementById("back-btn")?.addEventListener("click", () => {
199
+ form.back();
200
+ });
219
201
  ```
220
202
 
221
- In this code snippet, you need to replace $_APP_ID with the actual ID of your feedback application and the $_PUBLIC_KEY
222
- with the public key of your feedback application. This ID and key is provided by the magicfeedback service.
203
+ `form.send()` accepts arguments in this order:
204
+
205
+ 1. `metadata`
206
+ 2. `metrics`
207
+ 3. `profile`
208
+
209
+ Each item should follow the same shape:
223
210
 
224
- ###### FeedbackData
211
+ ```ts
212
+ { key: "some-key", value: ["some-value"] }
213
+ ```
214
+
215
+ ## Send feedback directly
225
216
 
226
- Then, you can include the feedback data in an object with the following structure:
217
+ Use `magicfeedback.send()` when you do not want the SDK to render any UI.
227
218
 
228
- ```js
229
- {
230
- text: "string", /* Optional */
219
+ ```ts
220
+ await magicfeedback.send(
221
+ "APP_ID",
222
+ "PUBLIC_KEY",
223
+ {
224
+ text: "",
231
225
  answers: [
232
- {
233
- key: 'string',
234
- value: ["string"]
235
- },
226
+ { key: "nps", value: ["9"] },
227
+ { key: "favorite-feature", value: ["Conditional logic"] }
236
228
  ],
237
229
  metadata: [
238
- {
239
- key: 'string',
240
- value: "string"
241
- },
230
+ { key: "source", value: ["pricing-page"] }
242
231
  ],
243
232
  metrics: [
244
- {
245
- key: 'string',
246
- value: "string"
247
- },
233
+ { key: "plan", value: ["pro"] }
248
234
  ],
249
235
  profile: [
250
- {
251
- key: 'string',
252
- value: "string"
253
- },
236
+ { key: "email", value: ["user@example.com"] }
254
237
  ]
255
- }
238
+ },
239
+ true
240
+ );
256
241
  ```
257
242
 
258
- * **key**: This setting determines the key of the feedback data.
259
- * **value**: This setting determines the value of the feedback data.
260
-
261
- Not all the fields are required. You can send only the fields that you need. But you need to send one of that minimal.
262
-
263
- Finally, to send the feedback, you can use the magicfeedback.send() function.
243
+ Signature:
264
244
 
265
- ## Style
266
-
267
- To use the default modern theme included in the bundle, import the CSS after loading the bundle:
268
-
269
- ```html
270
- <link rel="stylesheet" href="./node_modules/@magicfeedback/native/dist/styles/magicfeedback-default.css" />
245
+ ```ts
246
+ magicfeedback.send(
247
+ appId,
248
+ publicKey,
249
+ feedback,
250
+ completed = true,
251
+ id?,
252
+ privateKey?
253
+ );
271
254
  ```
272
255
 
273
- If you bundle with Webpack/Vite, you can also import directly into your entry:
256
+ ## Preview a question locally
257
+
258
+ `previewQuestion()` renders one question or an array of questions without changing the internal flow state.
259
+
260
+ ```ts
261
+ const previewForm = magicfeedback.form("demo", "demo");
262
+
263
+ previewForm.previewQuestion("preview-root", {
264
+ id: "q_text",
265
+ title: "What is your name?",
266
+ type: "TEXT",
267
+ questionType: { conf: [] },
268
+ ref: "name",
269
+ require: true,
270
+ external_id: "",
271
+ value: [],
272
+ defaultValue: "",
273
+ followup: false,
274
+ position: 1,
275
+ assets: {
276
+ placeholder: "Type your name",
277
+ subtitle: "Used only for preview"
278
+ },
279
+ refMetric: "",
280
+ integrationId: "demo",
281
+ integrationPageId: "demo"
282
+ }, {
283
+ format: "standard",
284
+ language: "en",
285
+ product: { customIcons: false },
286
+ clearContainer: true,
287
+ wrap: true
288
+ });
289
+ ```
274
290
 
275
- ```js
276
- import '@magicfeedback/native/dist/styles/magicfeedback-default.css';
291
+ This is useful for QA, local demos, and visual regression checks.
292
+
293
+ ## Supported rendered question types
294
+
295
+ The renderer currently supports these question types:
296
+
297
+ - `TEXT`
298
+ - `LONGTEXT`
299
+ - `NUMBER`
300
+ - `RADIO`
301
+ - `MULTIPLECHOICE`
302
+ - `SELECT`
303
+ - `DATE`
304
+ - `EMAIL`
305
+ - `PASSWORD`
306
+ - `BOOLEAN`
307
+ - `CONSENT`
308
+ - `RATING_STAR`
309
+ - `RATING_EMOJI`
310
+ - `RATING_NUMBER`
311
+ - `MULTIPLECHOISE_IMAGE`
312
+ - `MULTI_QUESTION_MATRIX`
313
+ - `POINT_SYSTEM`
314
+ - `PRIORITY_LIST`
315
+ - `INFO_PAGE`
316
+ - `UPLOAD_FILE`
317
+ - `UPLOAD_IMAGE`
318
+
319
+ For the output payload generated by `Form.answer()`, see [docs/answer-format.md](docs/answer-format.md). That document describes payload serialization, while the list above reflects the question types currently rendered by the browser UI.
320
+
321
+ Important payload notes:
322
+
323
+ - `EMAIL` answers are also copied into `feedback.profile` as `email`.
324
+ - `POINT_SYSTEM` answers are serialized as values such as `"Quality:60%"`.
325
+ - `MULTI_QUESTION_MATRIX` answers are grouped into a single JSON string entry.
326
+ - Required `MULTI_QUESTION_MATRIX` questions must have an answer in every row before the SDK allows submission.
327
+ - `INFO_PAGE`, `UPLOAD_FILE`, and `UPLOAD_IMAGE` render in the UI but do not currently create answer entries.
328
+
329
+ ## Styling
330
+
331
+ Import the bundled stylesheet:
332
+
333
+ ```ts
334
+ import "@magicfeedback/native/dist/styles/magicfeedback-default.css";
277
335
  ```
278
336
 
279
- You can override CSS variables defined in `:root` to customize colors without modifying the original file:
337
+ Or with plain HTML:
280
338
 
281
- ```css
282
- :root {
283
- /* Colors - Neutral Palette */
284
- --mf-primary: #2563eb;
285
- --mf-primary-hover: #1d4ed8;
286
- --mf-primary-light: #dbeafe;
287
-
288
- --mf-text-primary: #0f172a;
289
- --mf-text-secondary: #64748b;
290
- --mf-text-muted: #94a3b8;
291
-
292
- --mf-bg-primary: #ffffff;
293
- --mf-bg-secondary: #f8fafc;
294
- --mf-bg-hover: #f1f5f9;
295
-
296
- --mf-border: #e2e8f0;
297
- --mf-border-focus: #2563eb;
298
-
299
- --mf-success: #10b981;
300
- --mf-error: #ef4444;
301
- --mf-warning: #f59e0b;
302
-
303
- /* Spacing */
304
- --mf-space-xs: 0.25rem;
305
- --mf-space-sm: 0.5rem;
306
- --mf-space-md: 0.75rem;
307
- --mf-space-lg: 1rem;
308
- --mf-space-xl: 1.5rem;
309
-
310
- /* Border Radius */
311
- --mf-radius-sm: 0.375rem;
312
- --mf-radius-md: 0.5rem;
313
- --mf-radius-lg: 0.75rem;
314
- --mf-radius-full: 9999px;
315
-
316
- /* Shadows */
317
- --mf-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
318
- --mf-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
319
- --mf-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
320
- --mf-shadow-focus: 0 0 0 3px rgba(37, 99, 235, 0.1);
321
-
322
- /* Typography */
323
- --mf-font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Helvetica", "Arial", sans-serif;
324
- --mf-font-size-sm: 0.875rem;
325
- --mf-font-size-base: 1rem;
326
- --mf-font-size-lg: 1.125rem;
327
- --mf-font-size-xl: 1.25rem;
328
- --mf-line-height: 1.6;
329
-
330
- /* Transitions */
331
- --mf-transition: all 0.2s ease;
332
- --mf-transition-fast: all 0.15s ease;
333
- }
339
+ ```html
340
+ <link
341
+ rel="stylesheet"
342
+ href="./node_modules/@magicfeedback/native/dist/styles/magicfeedback-default.css"
343
+ />
334
344
  ```
335
345
 
336
- The file includes subtle animations and variations for focus, selection, and loading states (skeleton). Adjust or extend the classes as needed.
346
+ You can override the main CSS variables without modifying the distributed file:
337
347
 
338
348
  ```css
339
- /* Overall container for the feedback form */
340
- .magicfeedback-container {
341
- /* ... add your container styles here ... */
342
- }
343
-
344
- /* Main form element */
345
- .magicfeedback-form {
346
- /* ... add your form styles here ... */
347
- }
348
-
349
- /* Section for questions */
350
- .magicfeedback-questions {
351
- /* ... add your questions section styles here ... */
352
- }
353
-
354
- /* Section for div */
355
- .magicfeedback-div {
356
- /* ... add your generic div styles here ... */
357
- }
358
-
359
- /* Generic styles for various input elements */
360
- .magicfeedback-label,
361
- .magicfeedback-input,
362
- .magicfeedback-contact,
363
- .magicfeedback-password,
364
- .magicfeedback-email,
365
- .magicfeedback-boolean,
366
- .magicfeedback-consent,
367
- .magicfeedback-date,
368
- .magicfeedback-select,
369
- .magicfeedback-radio,
370
- .magicfeedback-checkbox,
371
- .magicfeedback-rating,
372
- .magicfeedback-rating-container,
373
- .magicfeedback-rating-option,
374
- .magicfeedback-rating-option-label-container,
375
- .magicfeedback-number,
376
- .magicfeedback-longtext,
377
- .magicfeedback-text,
378
- .magicfeedback-priority-list{
379
- /* ... add your generic input styles here ... */
380
- }
381
-
382
- .magicfeedback-skip-container {
383
- /* ... add your skip container styles here ... */
384
- }
385
-
386
- .magicfeedback-skip{
387
- /* ... add your skip button styles here ... */
388
- }
389
-
390
- .magicfeedback-image {
391
- /* ... add your image styles here ... */
392
- }
393
-
394
- /* Specific styles for individual input types */
395
- .magicfeedback-radio-container,
396
- .magicfeedback-boolean-container,
397
- .magicfeedback-consent-container,
398
- .magicfeedback-checkbox-container,
399
- .magicfeedback-longtext-container,
400
- .magicfeedback-priority-list-container{
401
- /* ... add styles for radio/checkbox containers ... */
402
- }
403
-
404
- .magicfeedback-rating-placeholder {
405
- /* ... add your rating placeholder styles here ... */
406
- }
407
-
408
- .magicfeedback-rating-placeholder-min {
409
- /* ... add your rating placeholder min styles here ... */
410
- }
411
-
412
- .magicfeedback-rating-placeholder-max {
413
- /* ... add your rating placeholder max styles here ... */
414
- }
415
-
416
- .magicfeedback-rating-image1,
417
- .magicfeedback-rating-image2,
418
- .magicfeedback-rating-image3,
419
- .magicfeedback-rating-image4,
420
- .magicfeedback-rating-image5,
421
- .magicfeedback-rating-image6,
422
- .magicfeedback-rating-image7,
423
- .magicfeedback-rating-image8,
424
- .magicfeedback-rating-image9,
425
- .magicfeedback-rating-image10,
426
- .magicfeedback-rating-image-extra {
427
- /* ... add styles for rating images ... */
428
- }
429
-
430
- /* Section for number rating */
431
- .magicfeedback-rating-number-container {
432
- /* ... add your number rating container styles here ... */
433
- }
434
-
435
- .magicfeedback-rating-number-placeholder {
436
- /* ... add your number rating placeholder styles here ... */
437
- }
438
-
439
- .magicfeedback-rating-number-placeholder-min {
440
- /* ... add your number rating placeholder min styles here ... */
441
- }
442
-
443
- .magicfeedback-rating-number-placeholder-max {
444
- /* ... add your number rating placeholder max styles here ... */
445
- }
446
-
447
- .magicfeedback-rating-number-option {
448
- /* ... add your number rating option styles here ... */
449
- }
450
-
451
- .magicfeedback-rating-number-option-label-container {
452
- /* ... add your number rating option label container styles here ... */
453
- }
454
-
455
-
456
- /* Section for star rating */
457
- .magicfeedback-rating-star {
458
- /* ... add your star rating container styles here ... */
459
- }
460
-
461
- .magicfeedback-rating-star-container {
462
- /* ... add your star rating styles here ... */
463
- }
464
-
465
- .magicfeedback-rating-star-option {
466
- /* ... add your star rating option styles here ... */
467
- }
468
-
469
- .magicfeedback-rating-star-selected {
470
- /* ... add your star rating selected styles here ... */
471
- }
472
-
473
- /* Section for multiple choice image */
474
- .magicfeedback-multiple-choice-image {
475
- /* ... add your multiple choice image container styles here ... */
476
- }
477
-
478
- .magicfeedback-multiple-choice-image-container {
479
- /* ... add your multiple choice image styles here ... */
480
- }
349
+ :root {
350
+ --mf-primary: #0f766e;
351
+ --mf-primary-hover: #115e59;
352
+ --mf-primary-light: #ccfbf1;
481
353
 
482
- .magicfeedback-multiple-choice-image-option {
483
- /* ... add your multiple choice image option styles here ... */
484
- }
354
+ --mf-text-primary: #0f172a;
355
+ --mf-text-secondary: #475569;
485
356
 
486
- .magicfeedback-image-option-label-container {
487
- /* ... add your multiple choice image option label container styles here ... */
488
- }
357
+ --mf-bg-primary: #ffffff;
358
+ --mf-bg-secondary: #f8fafc;
489
359
 
490
- .magicfeedback-multiple-choice-image-label {
491
- /* ... add your multiple choice image label styles here ... */
492
- }
360
+ --mf-border: #cbd5e1;
361
+ --mf-border-focus: #0f766e;
493
362
 
494
- .magicfeedback-multiple-choice-image-input {
495
- /* ... add your multiple choice image input styles here ... */
363
+ --mf-radius-md: 0.5rem;
364
+ --mf-shadow-md: 0 10px 20px rgba(15, 23, 42, 0.08);
496
365
  }
366
+ ```
497
367
 
498
- .magicfeedback-multiple-choice-image-image {
499
- /* ... add your multiple choice image image styles here ... */
500
- }
368
+ For deeper customization, inspect `dist/styles/magicfeedback-default.css` and override the generated classes from your own stylesheet.
501
369
 
502
- /* Section for priority-list */
503
- .magicfeedback-priority-list-container {
504
- /* ... add your priority list container styles here ... */
505
- }
506
- .magicfeedback-priority-list-list {
507
- /* ... add your priority list list styles here ... */
508
- }
509
- .magicfeedback-priority-list-item{
510
- /* ... add your priority list item styles here ... */
511
- }
512
- .magicfeedback-priority-list-item-label{
513
- /* ... add your priority list item label styles here ... */
514
- }
515
- .magicfeedback-priority-list-arrow-up,
516
- .magicfeedback-priority-list-arrow-down{
517
- /* ... add your priority list arrow up styles here ... */
518
-
519
- }
520
- /* Action buttons container */
521
- .magicfeedback-action-container {
522
- /* ... add your action button container styles here ... */
523
- }
370
+ ## QA and staging
524
371
 
525
- /* Submit button */
526
- .magicfeedback-submit {
527
- /* ... add your submit button styles here ... */
528
- }
372
+ Recommended setup for client review:
529
373
 
530
- /* Back button */
531
- .magicfeedback-back {
532
- /* ... add your back button styles here ... */
533
- }
374
+ ```ts
375
+ magicfeedback.init({
376
+ env: "dev",
377
+ debug: true,
378
+ dryRun: true
379
+ });
380
+ ```
534
381
 
535
- /* Start message */
536
- .magicfeedback-start-message-container {
537
- /* ... add your start message container styles here ... */
538
- }
382
+ This combination lets you load the survey, navigate questions, and inspect callbacks without creating real feedback records.
539
383
 
540
- .magicfeedback-start-message {
541
- /* ... add your start message styles here ... */
542
- }
384
+ ## Examples in this repository
543
385
 
544
- .magicfeedback-start-message-button {
545
- /* ... add your start message button styles here ... */
546
- }
386
+ - `examples/frontend/browser.html` - minimal browser integration
387
+ - `examples/frontend/browser_static.html` - live form plus local previews for all supported question types
388
+ - `examples/frontend/form.html` - embed the SDK inside an existing page layout
389
+ - `examples/frontend/embedded_in_form.html` - combine static inputs with SDK-managed questions
390
+ - `docs/answer-format.md` - exact payload format produced by `Form.answer()`
547
391
 
548
- .magicfeedback-info-page {
549
- /* ... add your info page styles here ... */
550
- }
392
+ ## Troubleshooting
551
393
 
552
- .magicfeedback-info-message{
553
- /* ... add your info message styles here ... */
554
- }
394
+ If the form does not load:
555
395
 
556
- /* Success message (if applicable) */
557
- .magicfeedback-success {
558
- /* ... add your success message styles here ... */
559
- }
560
- ````
396
+ - Confirm that `magicfeedback.init()` has been called.
397
+ - Confirm that the container id passed to `generate()` exists in the DOM.
398
+ - Check that you are using the correct `APP_ID`, `PUBLIC_KEY`, or `SESSION_ID`.
399
+ - Turn on `debug: true` to inspect SDK logs.
400
+ - Use `dryRun: true` when validating the flow before production rollout.