@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.
@@ -1,8 +1,11 @@
1
1
  /**
2
2
  * Wizard-ready Header — copy to src/components/Header.tsx
3
3
  *
4
- * Logo + company placement driven entirely by --cfm-header-* CSS vars from survey-ui-config.
5
- * Logo src from getLogoSrc() never hardcode asset paths.
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 LogoSlot() {
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 grid h-full w-full items-center"
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-row flex items-center"
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
- <LogoSlot />
120
- <CompanyName inBrandRow />
121
- </div>
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
- {/* Separate slots when company is not adjacent to logo */}
124
- <div
125
- className="cfm-header-logo-slot-only"
126
- style={{
127
- gridColumn: 'var(--cfm-header-logo-col, 1)',
128
- justifySelf: 'var(--cfm-header-logo-justify, start)',
129
- display: 'var(--cfm-header-logo-slot-display, flex)',
130
- }}
131
- >
132
- <LogoSlot />
133
- </div>
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
- <div
136
- className="cfm-header-company-slot flex items-center"
137
- style={{
138
- gridColumn: 'var(--cfm-header-company-col, 2)',
139
- justifySelf: 'var(--cfm-header-company-justify, center)',
140
- display: 'var(--cfm-header-company-slot-display, flex)',
141
- }}
142
- >
143
- <CompanyName />
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 { columnLabelPillStyle, matrixColumnLabelStyle } from '@/lib/surveyUi/labelStyles';
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, ...columnLabelPillStyle('matrix') }}>{lbl}</span>
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, ...columnLabelPillStyle('matrix') }}
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 { columnLabelPillStyle, sliderTickLabelStyle } from '@/lib/surveyUi/labelStyles';
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: '16px',
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={columnLabelPillStyle('hint')}>
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: '28px',
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
- export type ColumnLabelScope = 'matrix' | 'csat' | 'rating' | 'hint' | 'sliderTick';
7
+ type LabelPillScope = 'matrix' | 'csat' | 'rating' | 'hint' | 'sliderTick';
8
8
 
9
- const PILL_BASE: CSSProperties = {
10
- display: 'inline-flex',
11
- alignItems: 'center',
12
- justifyContent: 'center',
13
- padding: '4px 10px',
14
- borderRadius: 'var(--cfm-border-radius, 6px)',
15
- textAlign: 'center',
16
- lineHeight: 1.2,
17
- whiteSpace: 'nowrap',
18
- boxSizing: 'border-box',
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 scopeColorVars(scope: ColumnLabelScope): { color: string; backgroundColor: string } {
22
- switch (scope) {
23
- case 'matrix':
24
- return {
25
- color: 'var(--cfm-matrix-column-label-color, #4b5563)',
26
- backgroundColor: 'var(--cfm-matrix-column-label-bg, transparent)',
27
- };
28
- case 'csat':
29
- return {
30
- color: 'var(--cfm-csat-column-label-color, #4b5563)',
31
- backgroundColor: 'var(--cfm-csat-column-label-bg, transparent)',
32
- };
33
- case 'rating':
34
- return {
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 scopeColorVars('matrix');
53
+ return columnLabelPillStyle('matrix');
64
54
  }
65
55
 
66
56
  export function csatColumnLabelStyle(): CSSProperties {
67
- return scopeColorVars('csat');
57
+ return columnLabelPillStyle('csat');
68
58
  }
69
59
 
70
60
  export function ratingColumnLabelStyle(): CSSProperties {
71
- return scopeColorVars('rating');
61
+ return columnLabelPillStyle('rating');
72
62
  }
73
63
 
74
64
  export function sliderTickLabelStyle(): CSSProperties {
75
- return scopeColorVars('sliderTick');
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
- el.style.display = el.textContent ? '' : 'none';
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
- el.style.display = name ? '' : 'none';
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
- setDisplay('[data-cfm-company]', flags.showCompanyName);
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
- setDisplay('[data-cfm-question-number]', flags.showQuestionNumbers);
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
- setDisplay('[data-cfm-required]', flags.showRequiredAsterisk);
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) => ({ ...prev, ...data.contentPatch.previewState }));
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: LIKERT_COLUMNS,
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: LIKERT_COLUMNS,
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: LIKERT_COLUMNS,
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: LIKERT_COLUMNS,
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: LIKERT_COLUMNS,
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: Array.from({ length: 10 }, (_, i) => ({ id: `c${i}`, label: String(i + 1) })),
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: RATING_ANCHOR_LABELS,
301
+ scaleAnchorLabels: ['Label 1', 'Label 2', 'Label 3', 'Label 4', 'Label 5'],
311
302
  });
312
303
 
313
304
  export const FIXTURE_RATING_SLIDER = base({