@explorer02/cfm-survey-sdk 0.3.4 → 0.3.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/dist/cli/index.js +38 -38
- package/dist/cli/index.mjs +46 -46
- package/package.json +1 -1
- package/templates/docs/00-integration/component-checklist.md +0 -1
- package/templates/docs/templates/CsatMatrixScale.tsx +67 -92
- package/templates/docs/templates/CustomSliderTrack.tsx +4 -6
- package/templates/docs/templates/Footer.tsx +42 -72
- package/templates/docs/templates/Header.tsx +59 -110
- package/templates/docs/templates/LikertMatrixScale.tsx +3 -3
- package/templates/docs/templates/SliderMatrixScale.tsx +6 -4
- package/templates/docs/templates/labelStyles.ts +40 -50
- package/templates/docs/templates/surveyUiScaleUtils.ts +17 -0
- package/templates/preview-harness/preview-bridge.inline.js +58 -5
- package/templates/preview-harness/vite-app/src/PreviewConfigContext.tsx +8 -2
- package/templates/preview-harness/vite-app/src/fixtures/questions.ts +9 -18
- package/templates/survey-theme.css +18 -37
- package/templates/wizard-dist/assets/{PreviewMock-CC1UlWe-.js → PreviewMock-AeUxzA3b.js} +1 -1
- package/templates/wizard-dist/assets/TypePanel-B4UpxOhr.js +1 -0
- package/templates/wizard-dist/assets/index-CsragJbi.css +1 -0
- package/templates/wizard-dist/assets/index-Z7mePXvc.js +34 -0
- package/templates/wizard-dist/index.html +2 -2
- package/templates/wizard-dist/assets/TypePanel-DISCXm0z.js +0 -1
- package/templates/wizard-dist/assets/index-Blpq4QjK.js +0 -34
- package/templates/wizard-dist/assets/index-CVBd54V0.css +0 -1
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Wizard-ready Header — copy to src/components/Header.tsx
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Brand row: [logo image] [company name] — company sits after logo when both exist.
|
|
5
|
+
* When no logo file: text fallback via data-cfm-logo-text (company name or empty).
|
|
6
|
+
*
|
|
7
|
+
* After wizard save, logo src MUST come from survey-ui-config.json global.logo.fileName
|
|
8
|
+
* via uiConfig.ts — never hardcode telekom-logo.svg or change fileName manually.
|
|
6
9
|
*/
|
|
7
10
|
'use client';
|
|
8
11
|
|
|
@@ -16,131 +19,77 @@ const seedCompany = getCompanyName();
|
|
|
16
19
|
const seedLogoSrc = getLogoSrc({ staticExport: true });
|
|
17
20
|
const seedShowCompany = shouldShowCompanyName();
|
|
18
21
|
|
|
19
|
-
function
|
|
20
|
-
const hasLogoFile = Boolean(seedLogoSrc);
|
|
21
|
-
return (
|
|
22
|
-
<div
|
|
23
|
-
className="cfm-header-logo-slot shrink-0"
|
|
24
|
-
style={{
|
|
25
|
-
width: 'var(--cfm-header-logo-width, 80px)',
|
|
26
|
-
height: 'var(--cfm-header-logo-height, 80px)',
|
|
27
|
-
padding: 'var(--cfm-header-logo-padding, 8px)',
|
|
28
|
-
boxSizing: 'border-box',
|
|
29
|
-
display: 'flex',
|
|
30
|
-
alignItems: 'center',
|
|
31
|
-
justifyContent: 'center',
|
|
32
|
-
}}
|
|
33
|
-
>
|
|
34
|
-
{hasLogoFile ? (
|
|
35
|
-
<img
|
|
36
|
-
data-cfm-logo
|
|
37
|
-
src={seedLogoSrc!}
|
|
38
|
-
alt={seedCompany || 'Logo'}
|
|
39
|
-
className="h-full w-full object-contain"
|
|
40
|
-
style={{ background: 'transparent' }}
|
|
41
|
-
/>
|
|
42
|
-
) : (
|
|
43
|
-
<img data-cfm-logo src="" alt="Logo" className="h-full w-full object-contain" style={{ display: 'none' }} />
|
|
44
|
-
)}
|
|
45
|
-
</div>
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function CompanyName({ inBrandRow = false }: { inBrandRow?: boolean }) {
|
|
22
|
+
export default function Header({ embedded = false }: HeaderProps) {
|
|
50
23
|
const hasLogoFile = Boolean(seedLogoSrc);
|
|
51
|
-
const show =
|
|
52
|
-
seedShowCompany && (hasLogoFile || seedCompany) && (hasLogoFile || !inBrandRow);
|
|
53
24
|
|
|
54
|
-
return (
|
|
55
|
-
<>
|
|
56
|
-
<span
|
|
57
|
-
data-cfm-logo-text
|
|
58
|
-
className="font-semibold"
|
|
59
|
-
style={{
|
|
60
|
-
display: hasLogoFile ? 'none' : seedCompany ? '' : 'none',
|
|
61
|
-
color: 'var(--cfm-header-company-color, var(--cfm-text))',
|
|
62
|
-
fontSize: 'var(--cfm-header-company-size, 18px)',
|
|
63
|
-
fontWeight: 'var(--cfm-header-company-weight, 600)',
|
|
64
|
-
}}
|
|
65
|
-
>
|
|
66
|
-
{seedCompany}
|
|
67
|
-
</span>
|
|
68
|
-
<span
|
|
69
|
-
data-cfm-company
|
|
70
|
-
className="font-semibold"
|
|
71
|
-
style={{
|
|
72
|
-
display: show ? (hasLogoFile ? '' : 'none') : 'none',
|
|
73
|
-
marginTop: 'var(--cfm-header-company-margin-top, 0)',
|
|
74
|
-
marginLeft: inBrandRow ? 0 : 'var(--cfm-header-company-margin-left, 0)',
|
|
75
|
-
marginRight: inBrandRow ? 0 : 'var(--cfm-header-company-margin-right, 0)',
|
|
76
|
-
color: 'var(--cfm-header-company-color, var(--cfm-text))',
|
|
77
|
-
fontSize: 'var(--cfm-header-company-size, 18px)',
|
|
78
|
-
fontWeight: 'var(--cfm-header-company-weight, 600)',
|
|
79
|
-
lineHeight: 1.2,
|
|
80
|
-
}}
|
|
81
|
-
>
|
|
82
|
-
{seedCompany}
|
|
83
|
-
</span>
|
|
84
|
-
</>
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export default function Header({ embedded = false }: HeaderProps) {
|
|
89
25
|
return (
|
|
90
26
|
<header
|
|
91
27
|
className={`cfm-header relative w-full ${embedded ? '' : 'z-10 shadow-[0_2px_8px_rgba(0,0,0,0.06)]'}`}
|
|
92
28
|
style={{
|
|
93
|
-
height: 'var(--cfm-header-height, 140px)',
|
|
94
29
|
background: 'var(--cfm-header-bg, #fff)',
|
|
95
30
|
borderBottom: '1px solid var(--cfm-header-border, #e5e7eb)',
|
|
96
31
|
boxShadow: embedded ? undefined : 'var(--cfm-header-shadow, 0 2px 8px rgba(0,0,0,0.06))',
|
|
97
32
|
}}
|
|
98
33
|
>
|
|
99
34
|
<div
|
|
100
|
-
className="cfm-header-inner mx-auto
|
|
101
|
-
style={{
|
|
102
|
-
maxWidth: 'var(--cfm-max-width, 48rem)',
|
|
103
|
-
gridTemplateColumns: '1fr 1fr 1fr',
|
|
104
|
-
padding:
|
|
105
|
-
'var(--cfm-header-padding-y, 12px) var(--cfm-header-padding-x, 40px)',
|
|
106
|
-
boxSizing: 'border-box',
|
|
107
|
-
}}
|
|
35
|
+
className="cfm-header-inner mx-auto w-full"
|
|
36
|
+
style={{ maxWidth: 'var(--cfm-max-width, 48rem)' }}
|
|
108
37
|
>
|
|
109
|
-
{/* Brand row: logo + company adjacent (left+left or right+right) */}
|
|
110
38
|
<div
|
|
111
|
-
className="cfm-header-brand
|
|
112
|
-
style={{
|
|
113
|
-
gridColumn: 'var(--cfm-header-logo-col, 1)',
|
|
114
|
-
justifySelf: 'var(--cfm-header-logo-justify, start)',
|
|
115
|
-
gap: 'var(--cfm-header-brand-gap, 16px)',
|
|
116
|
-
display: 'var(--cfm-header-brand-row-display, none)',
|
|
117
|
-
}}
|
|
39
|
+
className="cfm-header-brand flex items-center"
|
|
40
|
+
style={{ gap: 'var(--cfm-header-brand-gap, 16px)' }}
|
|
118
41
|
>
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
42
|
+
{hasLogoFile ? (
|
|
43
|
+
<img
|
|
44
|
+
data-cfm-logo
|
|
45
|
+
src={seedLogoSrc!}
|
|
46
|
+
alt={seedCompany || 'Logo'}
|
|
47
|
+
className="shrink-0 object-contain"
|
|
48
|
+
style={{
|
|
49
|
+
width: 'var(--cfm-header-logo-width, 120px)',
|
|
50
|
+
height: 'var(--cfm-header-logo-height, 120px)',
|
|
51
|
+
padding: 'var(--cfm-header-logo-padding, 10px)',
|
|
52
|
+
background: 'transparent',
|
|
53
|
+
boxSizing: 'border-box',
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
) : (
|
|
57
|
+
<img
|
|
58
|
+
data-cfm-logo
|
|
59
|
+
src=""
|
|
60
|
+
alt="Logo"
|
|
61
|
+
className="shrink-0 object-contain"
|
|
62
|
+
style={{ display: 'none' }}
|
|
63
|
+
/>
|
|
64
|
+
)}
|
|
122
65
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
66
|
+
<span
|
|
67
|
+
data-cfm-logo-text
|
|
68
|
+
className="font-semibold"
|
|
69
|
+
style={{
|
|
70
|
+
display: hasLogoFile ? 'none' : seedCompany ? '' : 'none',
|
|
71
|
+
color: 'var(--cfm-header-company-color, var(--cfm-text))',
|
|
72
|
+
fontSize: 'var(--cfm-header-company-size, 18px)',
|
|
73
|
+
fontWeight: 'var(--cfm-header-company-weight, 600)',
|
|
74
|
+
}}
|
|
75
|
+
>
|
|
76
|
+
{seedCompany}
|
|
77
|
+
</span>
|
|
134
78
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
79
|
+
{seedCompany ? (
|
|
80
|
+
<span
|
|
81
|
+
data-cfm-company
|
|
82
|
+
className="font-semibold"
|
|
83
|
+
style={{
|
|
84
|
+
display: seedShowCompany && hasLogoFile ? undefined : 'none',
|
|
85
|
+
color: 'var(--cfm-header-company-color, var(--cfm-text))',
|
|
86
|
+
fontSize: 'var(--cfm-header-company-size, 18px)',
|
|
87
|
+
fontWeight: 'var(--cfm-header-company-weight, 600)',
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
{seedCompany}
|
|
91
|
+
</span>
|
|
92
|
+
) : null}
|
|
144
93
|
</div>
|
|
145
94
|
</div>
|
|
146
95
|
</header>
|
|
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import type { CfmMatrixQuestion, MatrixRowAnswers } from '@explorer02/cfm-survey-sdk';
|
|
3
3
|
import { columnSubmitValue } from './surveyUiScaleUtils';
|
|
4
4
|
import MatrixDropdown from './MatrixDropdown';
|
|
5
|
-
import {
|
|
5
|
+
import { matrixColumnLabelStyle } from '@/lib/surveyUi/labelStyles';
|
|
6
6
|
import { focusRingVar, matrixCarouselDotVar, matrixRadioDotStyle, matrixRadioRingStyle, matrixRowBackgroundStyle } from '@/lib/surveyUi/selectionStyles';
|
|
7
7
|
|
|
8
8
|
const MATRIX_ROW_LABEL_WIDTH = 'var(--cfm-matrix-row-width, 180px)';
|
|
@@ -219,7 +219,7 @@ function LikertMatrixGridLayout({
|
|
|
219
219
|
position: 'absolute', left: leftPos, transform: 'translateX(-50%)',
|
|
220
220
|
bottom: 0, display: 'flex', justifyContent: 'center', whiteSpace: 'nowrap'
|
|
221
221
|
}}>
|
|
222
|
-
<span style={{ fontSize: '13px', fontWeight: 600, ...
|
|
222
|
+
<span style={{ fontSize: '13px', fontWeight: 600, ...matrixColumnLabelStyle() }}>{lbl}</span>
|
|
223
223
|
</div>
|
|
224
224
|
);
|
|
225
225
|
})}
|
|
@@ -234,7 +234,7 @@ function LikertMatrixGridLayout({
|
|
|
234
234
|
<div style={{ flex: 1, display: 'grid', gridTemplateColumns: `repeat(${gridCols.length}, 1fr)` }}>
|
|
235
235
|
{gridCols.map((col) => (
|
|
236
236
|
<div key={col.id} style={{ display: 'flex', justifyContent: 'center', padding: '0 4px' }}>
|
|
237
|
-
<span style={{ fontSize: '13px', fontWeight: 500, ...
|
|
237
|
+
<span style={{ fontSize: '13px', fontWeight: 500, textAlign: 'center', lineHeight: 1.2, ...matrixColumnLabelStyle() }}
|
|
238
238
|
dangerouslySetInnerHTML={{ __html: transposeTable ? ('statementText' in col ? col.statementText : col.label) : ('label' in col ? col.label : (col as { statementText: string }).statementText) }} />
|
|
239
239
|
</div>
|
|
240
240
|
))}
|
|
@@ -9,7 +9,7 @@ import React from 'react';
|
|
|
9
9
|
import type { SliderMatrixQuestion, MatrixRowAnswers } from '@explorer02/cfm-survey-sdk';
|
|
10
10
|
import { tickColorFromIndex } from './surveyUiScaleUtils';
|
|
11
11
|
import { CustomSliderTrack } from './CustomSliderTrack';
|
|
12
|
-
import {
|
|
12
|
+
import { hintLabelStyle, sliderTickLabelStyle } from '@/lib/surveyUi/labelStyles';
|
|
13
13
|
|
|
14
14
|
const MATRIX_ROW_LABEL_WIDTH = 'var(--cfm-matrix-row-width, 180px)';
|
|
15
15
|
const SLIDER_ROW_BAND = 'var(--cfm-slider-row-band, var(--cfm-row-band, #f3f4f6))';
|
|
@@ -81,14 +81,15 @@ export function SliderMatrixScale({ question, selectedValue = {}, onSelect }: Sl
|
|
|
81
81
|
display: 'flex',
|
|
82
82
|
justifyContent: 'space-between',
|
|
83
83
|
margin: '0 16px',
|
|
84
|
-
marginBottom: '
|
|
84
|
+
marginBottom: tickValues.length > 0 ? '24px' : '8px',
|
|
85
|
+
minHeight: '20px',
|
|
85
86
|
fontSize: '14px',
|
|
86
87
|
fontWeight: 500,
|
|
87
88
|
}}
|
|
88
89
|
>
|
|
89
90
|
{labels.map((lbl, idx) => (
|
|
90
91
|
<div key={idx} style={{ width: 0, display: 'flex', justifyContent: 'center' }}>
|
|
91
|
-
<span style={
|
|
92
|
+
<span style={hintLabelStyle()}>
|
|
92
93
|
{lbl}
|
|
93
94
|
</span>
|
|
94
95
|
</div>
|
|
@@ -100,10 +101,11 @@ export function SliderMatrixScale({ question, selectedValue = {}, onSelect }: Sl
|
|
|
100
101
|
style={{
|
|
101
102
|
position: 'relative',
|
|
102
103
|
margin: '0 16px',
|
|
104
|
+
marginTop: labels && labels.length > 0 ? '4px' : '0',
|
|
103
105
|
marginBottom: '8px',
|
|
104
106
|
fontSize: '14px',
|
|
105
107
|
fontWeight: 400,
|
|
106
|
-
height: '
|
|
108
|
+
height: '32px',
|
|
107
109
|
...sliderTickLabelStyle(),
|
|
108
110
|
}}
|
|
109
111
|
>
|
|
@@ -4,55 +4,45 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { CSSProperties } from 'react';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
type LabelPillScope = 'matrix' | 'csat' | 'rating' | 'hint' | 'sliderTick';
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
const PILL_SCOPE_VARS: Record<LabelPillScope, { color: string; bg: string }> = {
|
|
10
|
+
matrix: {
|
|
11
|
+
color: '--cfm-matrix-column-label-color',
|
|
12
|
+
bg: '--cfm-matrix-column-label-bg',
|
|
13
|
+
},
|
|
14
|
+
csat: {
|
|
15
|
+
color: '--cfm-csat-column-label-color',
|
|
16
|
+
bg: '--cfm-csat-column-label-bg',
|
|
17
|
+
},
|
|
18
|
+
rating: {
|
|
19
|
+
color: '--cfm-rating-column-label-color',
|
|
20
|
+
bg: '--cfm-rating-column-label-bg',
|
|
21
|
+
},
|
|
22
|
+
hint: {
|
|
23
|
+
color: '--cfm-hint-label-color',
|
|
24
|
+
bg: '--cfm-hint-label-bg',
|
|
25
|
+
},
|
|
26
|
+
sliderTick: {
|
|
27
|
+
color: '--cfm-slider-tick-label-color',
|
|
28
|
+
bg: '--cfm-slider-tick-label-bg',
|
|
29
|
+
},
|
|
19
30
|
};
|
|
20
31
|
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
color: 'var(--cfm-rating-column-label-color, var(--cfm-matrix-column-label-color, #4b5563))',
|
|
36
|
-
backgroundColor: 'var(--cfm-rating-column-label-bg, var(--cfm-matrix-column-label-bg, transparent))',
|
|
37
|
-
};
|
|
38
|
-
case 'hint':
|
|
39
|
-
return {
|
|
40
|
-
color: 'var(--cfm-hint-label-color, #6b7280)',
|
|
41
|
-
backgroundColor: 'var(--cfm-hint-label-bg, transparent)',
|
|
42
|
-
};
|
|
43
|
-
case 'sliderTick':
|
|
44
|
-
return {
|
|
45
|
-
color: 'var(--cfm-slider-tick-label-color, #4b5563)',
|
|
46
|
-
backgroundColor: 'var(--cfm-slider-tick-label-bg, transparent)',
|
|
47
|
-
};
|
|
48
|
-
default:
|
|
49
|
-
return { color: '#4b5563', backgroundColor: 'transparent' };
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** Centered pill for column / anchor / tick labels — wizard Label Items customization. */
|
|
54
|
-
export function columnLabelPillStyle(scope: ColumnLabelScope): CSSProperties {
|
|
55
|
-
return { ...PILL_BASE, ...scopeColorVars(scope) };
|
|
32
|
+
export function columnLabelPillStyle(scope: LabelPillScope): CSSProperties {
|
|
33
|
+
const vars = PILL_SCOPE_VARS[scope];
|
|
34
|
+
return {
|
|
35
|
+
display: 'inline-flex',
|
|
36
|
+
alignItems: 'center',
|
|
37
|
+
justifyContent: 'center',
|
|
38
|
+
padding: '4px 10px',
|
|
39
|
+
borderRadius: 'var(--cfm-border-radius, 6px)',
|
|
40
|
+
textAlign: 'center',
|
|
41
|
+
lineHeight: 1.2,
|
|
42
|
+
whiteSpace: 'nowrap',
|
|
43
|
+
color: `var(${vars.color}, #4b5563)`,
|
|
44
|
+
backgroundColor: `var(${vars.bg}, transparent)`,
|
|
45
|
+
};
|
|
56
46
|
}
|
|
57
47
|
|
|
58
48
|
export function hintLabelStyle(): CSSProperties {
|
|
@@ -60,17 +50,17 @@ export function hintLabelStyle(): CSSProperties {
|
|
|
60
50
|
}
|
|
61
51
|
|
|
62
52
|
export function matrixColumnLabelStyle(): CSSProperties {
|
|
63
|
-
return
|
|
53
|
+
return columnLabelPillStyle('matrix');
|
|
64
54
|
}
|
|
65
55
|
|
|
66
56
|
export function csatColumnLabelStyle(): CSSProperties {
|
|
67
|
-
return
|
|
57
|
+
return columnLabelPillStyle('csat');
|
|
68
58
|
}
|
|
69
59
|
|
|
70
60
|
export function ratingColumnLabelStyle(): CSSProperties {
|
|
71
|
-
return
|
|
61
|
+
return columnLabelPillStyle('rating');
|
|
72
62
|
}
|
|
73
63
|
|
|
74
64
|
export function sliderTickLabelStyle(): CSSProperties {
|
|
75
|
-
return
|
|
65
|
+
return columnLabelPillStyle('sliderTick');
|
|
76
66
|
}
|
|
@@ -96,3 +96,20 @@ export function columnAccentColor(column: { id: string; label: string }): string
|
|
|
96
96
|
}
|
|
97
97
|
return undefined;
|
|
98
98
|
}
|
|
99
|
+
|
|
100
|
+
/** Column-center anchor label positioning (m = option columns, n = anchor labels). */
|
|
101
|
+
export function anchorLabelPercent(
|
|
102
|
+
index: number,
|
|
103
|
+
labelCount: number,
|
|
104
|
+
columnCount: number,
|
|
105
|
+
isGraphics = false,
|
|
106
|
+
): number {
|
|
107
|
+
const m = columnCount;
|
|
108
|
+
const n = labelCount;
|
|
109
|
+
if (isGraphics) {
|
|
110
|
+
return n === 1 ? 0 : (index / (n - 1)) * 100;
|
|
111
|
+
}
|
|
112
|
+
const startPercent = 0.5 / m;
|
|
113
|
+
const rangePercent = (m - 1) / m;
|
|
114
|
+
return n === 1 ? 50 : (startPercent + (index / (n - 1)) * rangePercent) * 100;
|
|
115
|
+
}
|
|
@@ -76,6 +76,35 @@
|
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
function ensureCompanySpan() {
|
|
80
|
+
var brand = document.querySelector('.cfm-header-brand');
|
|
81
|
+
if (!brand) return null;
|
|
82
|
+
var el = brand.querySelector('[data-cfm-company]');
|
|
83
|
+
if (el) return el;
|
|
84
|
+
el = document.createElement('span');
|
|
85
|
+
el.setAttribute('data-cfm-company', '');
|
|
86
|
+
el.className = 'font-semibold';
|
|
87
|
+
el.style.color = 'var(--cfm-header-company-color, var(--cfm-text))';
|
|
88
|
+
el.style.fontSize = 'var(--cfm-header-company-size, 18px)';
|
|
89
|
+
el.style.fontWeight = 'var(--cfm-header-company-weight, 600)';
|
|
90
|
+
var logo = brand.querySelector('[data-cfm-logo]');
|
|
91
|
+
if (logo && logo.parentNode === brand) {
|
|
92
|
+
if (logo.nextSibling) brand.insertBefore(el, logo.nextSibling);
|
|
93
|
+
else brand.appendChild(el);
|
|
94
|
+
} else {
|
|
95
|
+
brand.appendChild(el);
|
|
96
|
+
}
|
|
97
|
+
return el;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function companyNameVisible() {
|
|
101
|
+
var root = document.documentElement;
|
|
102
|
+
var attr = root.getAttribute('data-cfm-show-company-name');
|
|
103
|
+
if (attr === '0') return false;
|
|
104
|
+
if (attr === '1') return true;
|
|
105
|
+
return readVar('--cfm-header-show-company', '1') !== '0';
|
|
106
|
+
}
|
|
107
|
+
|
|
79
108
|
function applyThemeSideEffects() {
|
|
80
109
|
applyNumberBadgeColors();
|
|
81
110
|
applyDropzoneStyle();
|
|
@@ -105,15 +134,23 @@
|
|
|
105
134
|
});
|
|
106
135
|
document.querySelectorAll('[data-cfm-company]').forEach(function (el) {
|
|
107
136
|
if (patch.logoUrl) {
|
|
108
|
-
|
|
137
|
+
var show = companyNameVisible() && el.textContent;
|
|
138
|
+
el.style.display = show ? '' : 'none';
|
|
109
139
|
}
|
|
110
140
|
});
|
|
111
141
|
}
|
|
112
142
|
if (patch.companyName !== undefined) {
|
|
113
143
|
var name = patch.companyName || '';
|
|
144
|
+
if (name && document.querySelectorAll('[data-cfm-company]').length === 0) {
|
|
145
|
+
ensureCompanySpan();
|
|
146
|
+
}
|
|
114
147
|
document.querySelectorAll('[data-cfm-company]').forEach(function (el) {
|
|
115
148
|
el.textContent = name;
|
|
116
|
-
|
|
149
|
+
var logoImg = document.querySelector('[data-cfm-logo]');
|
|
150
|
+
var logoVisible =
|
|
151
|
+
logoImg && logoImg.style.display !== 'none' && logoImg.getAttribute('src');
|
|
152
|
+
var show = name && logoVisible && companyNameVisible();
|
|
153
|
+
el.style.display = show ? '' : 'none';
|
|
117
154
|
});
|
|
118
155
|
document.querySelectorAll('[data-cfm-logo-text]').forEach(function (el) {
|
|
119
156
|
var logoImg = document.querySelector('[data-cfm-logo]');
|
|
@@ -174,7 +211,17 @@
|
|
|
174
211
|
if (patch.layoutFlags) {
|
|
175
212
|
var flags = patch.layoutFlags;
|
|
176
213
|
if (flags.showCompanyName !== undefined) {
|
|
177
|
-
|
|
214
|
+
document.documentElement.setAttribute(
|
|
215
|
+
'data-cfm-show-company-name',
|
|
216
|
+
flags.showCompanyName ? '1' : '0',
|
|
217
|
+
);
|
|
218
|
+
document.querySelectorAll('[data-cfm-company]').forEach(function (el) {
|
|
219
|
+
var logoImg = document.querySelector('[data-cfm-logo]');
|
|
220
|
+
var logoVisible =
|
|
221
|
+
logoImg && logoImg.style.display !== 'none' && logoImg.getAttribute('src');
|
|
222
|
+
var show = flags.showCompanyName && el.textContent && logoVisible;
|
|
223
|
+
el.style.display = show ? '' : 'none';
|
|
224
|
+
});
|
|
178
225
|
}
|
|
179
226
|
if (flags.showHeader !== undefined) {
|
|
180
227
|
setDisplay('.cfm-header, header.cfm-header', flags.showHeader);
|
|
@@ -195,10 +242,16 @@
|
|
|
195
242
|
setDisplay('[data-cfm-btn-back]', flags.showBackButton);
|
|
196
243
|
}
|
|
197
244
|
if (flags.showQuestionNumbers !== undefined) {
|
|
198
|
-
|
|
245
|
+
document.documentElement.setAttribute(
|
|
246
|
+
'data-cfm-show-question-numbers',
|
|
247
|
+
flags.showQuestionNumbers ? '1' : '0',
|
|
248
|
+
);
|
|
199
249
|
}
|
|
200
250
|
if (flags.showRequiredAsterisk !== undefined) {
|
|
201
|
-
|
|
251
|
+
document.documentElement.setAttribute(
|
|
252
|
+
'data-cfm-show-required',
|
|
253
|
+
flags.showRequiredAsterisk ? '1' : '0',
|
|
254
|
+
);
|
|
202
255
|
}
|
|
203
256
|
if (flags.showFooterLogo !== undefined) {
|
|
204
257
|
setDisplay('[data-cfm-footer-logo]', flags.showFooterLogo);
|
|
@@ -71,7 +71,14 @@ export function PreviewConfigProvider({ children }: { children: ReactNode }) {
|
|
|
71
71
|
if (!data?.type) return;
|
|
72
72
|
if (data.type !== PREVIEW_BRIDGE_SNAPSHOT && data.type !== PREVIEW_BRIDGE_DELTA) return;
|
|
73
73
|
if (data.contentPatch?.previewState) {
|
|
74
|
-
setPreviewState((prev) =>
|
|
74
|
+
setPreviewState((prev) => {
|
|
75
|
+
const next = { ...prev, ...data.contentPatch.previewState };
|
|
76
|
+
const changed = (Object.keys(data.contentPatch.previewState) as (keyof PreviewStatePatch)[]).some(
|
|
77
|
+
(key) => prev[key] !== next[key],
|
|
78
|
+
);
|
|
79
|
+
if (changed) setConfigRevision((r) => r + 1);
|
|
80
|
+
return next;
|
|
81
|
+
});
|
|
75
82
|
}
|
|
76
83
|
if (data.contentPatch?.domAttributes) {
|
|
77
84
|
const root = document.documentElement;
|
|
@@ -85,7 +92,6 @@ export function PreviewConfigProvider({ children }: { children: ReactNode }) {
|
|
|
85
92
|
root.style.setProperty(key, value as string);
|
|
86
93
|
}
|
|
87
94
|
}
|
|
88
|
-
setConfigRevision((r) => r + 1);
|
|
89
95
|
applyThemeSideEffects();
|
|
90
96
|
};
|
|
91
97
|
|
|
@@ -209,7 +209,8 @@ export const FIXTURE_CSAT_EMOJI = base({
|
|
|
209
209
|
displayStyle: 'emoji',
|
|
210
210
|
gridLayout: 'standard',
|
|
211
211
|
statementRows: MATRIX_ROW_SINGLE,
|
|
212
|
-
scaleColumns:
|
|
212
|
+
scaleColumns: Array.from({ length: 10 }, (_, i) => ({ id: `c${i}`, label: String(i + 1) })),
|
|
213
|
+
scaleAnchorLabels: ['Very unhappy', '', '', '', 'Very happy'],
|
|
213
214
|
});
|
|
214
215
|
|
|
215
216
|
export const FIXTURE_CSAT_STAR = base({
|
|
@@ -217,7 +218,7 @@ export const FIXTURE_CSAT_STAR = base({
|
|
|
217
218
|
displayStyle: 'star',
|
|
218
219
|
gridLayout: 'standard',
|
|
219
220
|
statementRows: MATRIX_ROW_SINGLE,
|
|
220
|
-
scaleColumns:
|
|
221
|
+
scaleColumns: Array.from({ length: 10 }, (_, i) => ({ id: `c${i}`, label: String(i + 1) })),
|
|
221
222
|
});
|
|
222
223
|
|
|
223
224
|
export const FIXTURE_CSAT_NUMBERED = base({
|
|
@@ -225,7 +226,7 @@ export const FIXTURE_CSAT_NUMBERED = base({
|
|
|
225
226
|
displayStyle: 'numbered',
|
|
226
227
|
gridLayout: 'standard',
|
|
227
228
|
statementRows: MATRIX_ROWS_MULTI,
|
|
228
|
-
scaleColumns:
|
|
229
|
+
scaleColumns: Array.from({ length: 10 }, (_, i) => ({ id: `c${i}`, label: String(i + 1) })),
|
|
229
230
|
});
|
|
230
231
|
|
|
231
232
|
export const FIXTURE_CSAT_GRAPHICS = base({
|
|
@@ -233,7 +234,8 @@ export const FIXTURE_CSAT_GRAPHICS = base({
|
|
|
233
234
|
displayStyle: 'graphics',
|
|
234
235
|
gridLayout: 'standard',
|
|
235
236
|
statementRows: MATRIX_ROW_SINGLE,
|
|
236
|
-
scaleColumns:
|
|
237
|
+
scaleColumns: Array.from({ length: 10 }, (_, i) => ({ id: `c${i}`, label: String(i + 1) })),
|
|
238
|
+
scaleAnchorLabels: ['Label 1', 'Label 2'],
|
|
237
239
|
});
|
|
238
240
|
|
|
239
241
|
export const FIXTURE_CSAT_CAROUSEL = base({
|
|
@@ -241,7 +243,7 @@ export const FIXTURE_CSAT_CAROUSEL = base({
|
|
|
241
243
|
displayStyle: 'star',
|
|
242
244
|
gridLayout: 'carousel',
|
|
243
245
|
statementRows: [{ id: 'r1', statementText: 'Overall experience' }],
|
|
244
|
-
scaleColumns:
|
|
246
|
+
scaleColumns: Array.from({ length: 5 }, (_, i) => ({ id: `c${i}`, label: String(i + 1) })),
|
|
245
247
|
});
|
|
246
248
|
|
|
247
249
|
export const FIXTURE_CSAT_DROPDOWN = base({
|
|
@@ -257,22 +259,13 @@ export const FIXTURE_CSAT_DROPDOWN = base({
|
|
|
257
259
|
],
|
|
258
260
|
});
|
|
259
261
|
|
|
260
|
-
const RATING_ANCHOR_LABELS = [
|
|
261
|
-
'Strongly Disagree',
|
|
262
|
-
'Disagree',
|
|
263
|
-
'Neutral',
|
|
264
|
-
'Agree',
|
|
265
|
-
'Strongly Agree',
|
|
266
|
-
];
|
|
267
|
-
|
|
268
262
|
export const FIXTURE_RATING_STAR = base({
|
|
269
263
|
type: 'RATING_MATRIX',
|
|
270
264
|
displayStyle: 'star',
|
|
271
265
|
gridLayout: 'standard',
|
|
272
266
|
showColumnHeaders: true,
|
|
273
267
|
statementRows: MATRIX_ROWS_MULTI,
|
|
274
|
-
scaleColumns:
|
|
275
|
-
scaleAnchorLabels: RATING_ANCHOR_LABELS,
|
|
268
|
+
scaleColumns: LIKERT_COLUMNS,
|
|
276
269
|
});
|
|
277
270
|
|
|
278
271
|
export const FIXTURE_RATING_NUMBERED = base({
|
|
@@ -281,7 +274,6 @@ export const FIXTURE_RATING_NUMBERED = base({
|
|
|
281
274
|
gridLayout: 'standard',
|
|
282
275
|
statementRows: MATRIX_ROWS_MULTI,
|
|
283
276
|
scaleColumns: Array.from({ length: 10 }, (_, i) => ({ id: `c${i}`, label: String(i + 1) })),
|
|
284
|
-
scaleAnchorLabels: RATING_ANCHOR_LABELS,
|
|
285
277
|
});
|
|
286
278
|
|
|
287
279
|
export const FIXTURE_RATING_RADIO = base({
|
|
@@ -298,7 +290,6 @@ export const FIXTURE_RATING_EMOJI = base({
|
|
|
298
290
|
gridLayout: 'standard',
|
|
299
291
|
statementRows: MATRIX_ROW_SINGLE,
|
|
300
292
|
scaleColumns: Array.from({ length: 10 }, (_, i) => ({ id: `c${i}`, label: String(i + 1) })),
|
|
301
|
-
scaleAnchorLabels: RATING_ANCHOR_LABELS,
|
|
302
293
|
});
|
|
303
294
|
|
|
304
295
|
export const FIXTURE_RATING_GRAPHICS = base({
|
|
@@ -307,7 +298,7 @@ export const FIXTURE_RATING_GRAPHICS = base({
|
|
|
307
298
|
gridLayout: 'standard',
|
|
308
299
|
statementRows: MATRIX_ROW_SINGLE,
|
|
309
300
|
scaleColumns: Array.from({ length: 10 }, (_, i) => ({ id: `c${i}`, label: String(i + 1) })),
|
|
310
|
-
scaleAnchorLabels:
|
|
301
|
+
scaleAnchorLabels: ['Label 1', 'Label 2', 'Label 3', 'Label 4', 'Label 5'],
|
|
311
302
|
});
|
|
312
303
|
|
|
313
304
|
export const FIXTURE_RATING_SLIDER = base({
|