@media-quest/builder 0.0.34 → 0.0.36
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/public-api.d.ts +97 -78
- package/dist/public-api.js +85 -22
- package/dist/public-api.js.map +1 -1
- package/package.json +2 -2
- package/src/Builder-question.ts +98 -98
- package/src/Builder-schema-dto.spec.ts +155 -0
- package/src/Builder-schema-dto.ts +77 -0
- package/src/Builder-schema.spec.ts +1 -1
- package/src/Builder-schema.ts +21 -24
- package/src/builder-compiler.ts +20 -14
- package/src/code-book/codebook.ts +1 -1
- package/src/media-files.ts +32 -28
- package/src/public-api.ts +2 -1
- package/src/schema-config.ts +26 -25
- package/src/sum-score/sum-score-variable.ts +1 -0
- package/src/sum-score/sum-score.ts +2 -1
- package/src/theme/Default-theme.ts +18 -7
- package/src/theme/ThemeCompiler.ts +2 -1
- package/src/theme/button-bar/button-text-utils.ts +233 -0
- package/src/theme/button-bar/text-utils.spec.ts +105 -0
- package/src/theme/default-theme-compiler.ts +3 -2
- package/src/theme/theme2.ts +13 -9
package/src/schema-config.ts
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
import { CodebookPredefinedVariable } from "./code-book/codebook-variable";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
readonly
|
|
11
|
-
readonly
|
|
12
|
-
readonly
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
1
|
+
import { CodebookPredefinedVariable } from "./code-book/codebook-variable";
|
|
2
|
+
|
|
3
|
+
import { BuilderSchemaDto } from "./Builder-schema-dto";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* This interface is ment to define all information that a schema-admin app
|
|
7
|
+
* needs to generate a dynamic form for setting values for predefined variables.
|
|
8
|
+
*/
|
|
9
|
+
export interface SchemaConfig {
|
|
10
|
+
readonly schemaName: string;
|
|
11
|
+
readonly schemaId: string;
|
|
12
|
+
readonly schemaPrefix: string;
|
|
13
|
+
readonly variables: ReadonlyArray<CodebookPredefinedVariable>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const SchemaConfig = {
|
|
17
|
+
fromSchema: (schema: BuilderSchemaDto): SchemaConfig => {
|
|
18
|
+
const variables = schema.predefinedVariables ?? [];
|
|
19
|
+
return {
|
|
20
|
+
schemaId: schema.id,
|
|
21
|
+
schemaName: schema.name,
|
|
22
|
+
schemaPrefix: schema.prefix,
|
|
23
|
+
variables,
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
} as const;
|
|
@@ -2,7 +2,8 @@ import { SumScoreVariableDto } from "./sum-score-variable";
|
|
|
2
2
|
import { SumScoreVariableID } from "../primitives/ID";
|
|
3
3
|
import { SumScoreAnswer } from "./sum-score-answer";
|
|
4
4
|
import { CodeBook } from "../code-book/codebook";
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
import { BuilderSchemaDto } from "../Builder-schema-dto";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
*
|
|
@@ -13,15 +13,22 @@ namespace BuilderOptionTheme {
|
|
|
13
13
|
const BLUE = "#2F5597";
|
|
14
14
|
const BTN_BORDER_WIDTH = 3;
|
|
15
15
|
const BTN_BORDER_RADIUS = 10;
|
|
16
|
+
const BTN_HEIGHT = 130;
|
|
17
|
+
const BTN_WIDTH_LONG: DCss.Percent = { _unit: "percent", value: 19 };
|
|
18
|
+
const BTN_WIDTH_SHORT: DCss.Percent = { _unit: "percent", value: 15 };
|
|
16
19
|
const BTN_BORDER_STYLE: DStyle["borderStyle"] = "solid";
|
|
17
|
-
const FONT_WEIGHT: DStyle["fontWeight"] =
|
|
18
|
-
const FONT_SIZE: DCss.Px["value"] =
|
|
19
|
-
const
|
|
20
|
-
const
|
|
20
|
+
const FONT_WEIGHT: DStyle["fontWeight"] = 500;
|
|
21
|
+
const FONT_SIZE: DCss.Px["value"] = 36;
|
|
22
|
+
const MAIN_TEXT_FONT_SIZE: DCss.Px = { _unit: "px", value: 36 };
|
|
23
|
+
const MAIN_TEXT_WIDTH: DCss.Percent = { _unit: "percent", value: 80 };
|
|
24
|
+
|
|
25
|
+
const BTN_PADDING_LEFT = 10;
|
|
26
|
+
const BTN_PADDING_TOP = 10;
|
|
21
27
|
|
|
22
28
|
const buttonBaseCss = (): CssTheme => ({
|
|
23
29
|
css: {
|
|
24
30
|
fontWeight: FONT_WEIGHT,
|
|
31
|
+
|
|
25
32
|
fontSize: { _unit: "px", value: FONT_SIZE },
|
|
26
33
|
letterSpacing: { _unit: "px", value: 2 },
|
|
27
34
|
paddingLeft: { _unit: "px", value: BTN_PADDING_LEFT },
|
|
@@ -30,6 +37,8 @@ namespace BuilderOptionTheme {
|
|
|
30
37
|
paddingRight: { _unit: "px", value: BTN_PADDING_LEFT },
|
|
31
38
|
borderRadius: { _unit: "px", value: BTN_BORDER_RADIUS },
|
|
32
39
|
borderWidth: { _unit: "px", value: BTN_BORDER_WIDTH },
|
|
40
|
+
width: BTN_WIDTH_LONG,
|
|
41
|
+
height: { _unit: "px", value: BTN_HEIGHT },
|
|
33
42
|
borderStyle: BTN_BORDER_STYLE,
|
|
34
43
|
// boxShadow: "3px 3px gray",
|
|
35
44
|
position: "relative",
|
|
@@ -67,6 +76,7 @@ namespace BuilderOptionTheme {
|
|
|
67
76
|
backgroundColor: WHITE,
|
|
68
77
|
borderColor: LIGHT_BLUE,
|
|
69
78
|
textColor: BLUE,
|
|
79
|
+
width: BTN_WIDTH_SHORT,
|
|
70
80
|
},
|
|
71
81
|
cssDisabled,
|
|
72
82
|
cssEnabled,
|
|
@@ -87,9 +97,10 @@ const audioHighTop = 20;
|
|
|
87
97
|
const audioLowTop = 55;
|
|
88
98
|
|
|
89
99
|
const textBase: PStyle = {
|
|
90
|
-
width:
|
|
100
|
+
width: 76,
|
|
101
|
+
// backgroundColor: "red",
|
|
91
102
|
top: textHighTop,
|
|
92
|
-
left:
|
|
103
|
+
left: 12,
|
|
93
104
|
textAlign: "center",
|
|
94
105
|
textColor: "black",
|
|
95
106
|
fontSize: { _unit: "px", value: 40 },
|
|
@@ -162,7 +173,7 @@ export const DefaultTheme: IDefaultTheme = {
|
|
|
162
173
|
bottom: 0,
|
|
163
174
|
left: 0, // h: 10,
|
|
164
175
|
alignItems: "center",
|
|
165
|
-
backgroundColor: "yellow",
|
|
176
|
+
// backgroundColor: "yellow",
|
|
166
177
|
},
|
|
167
178
|
whenSingle: { justifyContent: "space-evenly" },
|
|
168
179
|
whenMany: { justifyContent: "space-evenly" },
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { BuilderSchemaDto } from "../Builder-schema";
|
|
2
1
|
import { SchemaDto } from "@media-quest/engine";
|
|
2
|
+
import { CompilerOption } from "../builder-compiler";
|
|
3
|
+
import { BuilderSchemaDto } from "../Builder-schema-dto";
|
|
3
4
|
|
|
4
5
|
export interface ThemeCompiler<ThemeSchema> {
|
|
5
6
|
currentTheme: ThemeSchema;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
const SPLITTER = " ";
|
|
2
|
+
|
|
3
|
+
const maxWordLength = (text: string) => {
|
|
4
|
+
const splitt = text.split(" ");
|
|
5
|
+
return Math.max(...splitt.map((w) => w.length));
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
type Splitted = {
|
|
9
|
+
index: number;
|
|
10
|
+
first: string;
|
|
11
|
+
second: string;
|
|
12
|
+
longest: number;
|
|
13
|
+
lineDiff: number;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const allSplits = (text: string): ReadonlyArray<Splitted> => {
|
|
17
|
+
const lines = text.split(SPLITTER);
|
|
18
|
+
const slices: Array<Splitted> = [];
|
|
19
|
+
lines.forEach((line, index, array) => {
|
|
20
|
+
const first = array.slice(0, index).join(SPLITTER);
|
|
21
|
+
const last = array.slice(index).join(SPLITTER);
|
|
22
|
+
const longest = Math.max(first.length, last.length);
|
|
23
|
+
const lineDiff = Math.abs(first.length - last.length);
|
|
24
|
+
const slice: Splitted = {
|
|
25
|
+
first,
|
|
26
|
+
second: last,
|
|
27
|
+
index,
|
|
28
|
+
longest,
|
|
29
|
+
lineDiff,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
slices.push(slice);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return slices;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const splitInTwo = (buttonText: string) => {
|
|
39
|
+
const all = allSplits(buttonText);
|
|
40
|
+
let result = { first: "", last: "", longest: 0 };
|
|
41
|
+
all.forEach((slice, index) => {
|
|
42
|
+
if (index === 0) {
|
|
43
|
+
result.first = slice.first;
|
|
44
|
+
result.last = slice.second;
|
|
45
|
+
result.longest = slice.longest;
|
|
46
|
+
} else if (result.longest > slice.longest) {
|
|
47
|
+
result.first = slice.first;
|
|
48
|
+
result.last = slice.second;
|
|
49
|
+
result.longest = slice.longest;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return result;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
type ButtonTextLength = {
|
|
57
|
+
readonly text: string;
|
|
58
|
+
/**
|
|
59
|
+
* Text is on one line.
|
|
60
|
+
*/
|
|
61
|
+
readonly max: number;
|
|
62
|
+
/**
|
|
63
|
+
* Text is on two lines.
|
|
64
|
+
*/
|
|
65
|
+
readonly min: number;
|
|
66
|
+
};
|
|
67
|
+
const checkLength = (buttonText: string): ButtonTextLength => {
|
|
68
|
+
const max = buttonText.length;
|
|
69
|
+
const onTwo = splitInTwo(buttonText);
|
|
70
|
+
const min = onTwo.longest;
|
|
71
|
+
return {
|
|
72
|
+
text: buttonText,
|
|
73
|
+
min,
|
|
74
|
+
max,
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
type ButtonTextSanitized = string & { __sanitized: true };
|
|
79
|
+
export class ButtonTextState {
|
|
80
|
+
private readonly text: string;
|
|
81
|
+
private _isSplit: boolean;
|
|
82
|
+
private readonly twoLineWidth: number;
|
|
83
|
+
private readonly oneLineWidth: number;
|
|
84
|
+
|
|
85
|
+
get width() {
|
|
86
|
+
return this._isSplit ? this.twoLineWidth : this.oneLineWidth;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get isSplit() {
|
|
90
|
+
return this._isSplit;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
get canSplit() {
|
|
94
|
+
return this.oneLineWidth > this.twoLineWidth;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
get splitDiff() {
|
|
98
|
+
return this.oneLineWidth - this.twoLineWidth;
|
|
99
|
+
}
|
|
100
|
+
// get si
|
|
101
|
+
constructor(text: string) {
|
|
102
|
+
this.text = text;
|
|
103
|
+
this.oneLineWidth = text.length;
|
|
104
|
+
this._isSplit = false;
|
|
105
|
+
this.twoLineWidth = splitInTwo(text).longest;
|
|
106
|
+
}
|
|
107
|
+
tryToSplit() {
|
|
108
|
+
this._isSplit = true;
|
|
109
|
+
}
|
|
110
|
+
unSplit() {
|
|
111
|
+
this._isSplit = false;
|
|
112
|
+
}
|
|
113
|
+
getState() {
|
|
114
|
+
const sanitizedText = this.text as ButtonTextSanitized;
|
|
115
|
+
return { raw: this.text, sanitizedText, isSplit: this._isSplit, width: this.width };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
type FittedButton = {
|
|
120
|
+
width: number;
|
|
121
|
+
isSingleLine: boolean;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
type FitAllOptions = {
|
|
125
|
+
oneLine: { min: number; max: number };
|
|
126
|
+
twoLine: { min: number; max: number };
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
type FittedResult = {
|
|
130
|
+
success: boolean;
|
|
131
|
+
isSingleLine: boolean;
|
|
132
|
+
requiredSpace: number;
|
|
133
|
+
twoLineCount: number;
|
|
134
|
+
result: ReadonlyArray<FittedButton>;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const sumReducer = (acc: number, number: number) => acc + number;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Calculates the sum of an array of numbers.
|
|
141
|
+
*
|
|
142
|
+
* @param {number[]} numbers - An array of numbers to calculate the sum for.
|
|
143
|
+
* @returns {number} - The sum of the numbers in the array.
|
|
144
|
+
*/
|
|
145
|
+
const sum = (numbers: number[]): number => {
|
|
146
|
+
return numbers.reduce(sumReducer, 0);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export class ButtonBarState {
|
|
150
|
+
private readonly buttons: ReadonlyArray<ButtonTextState>;
|
|
151
|
+
private readonly oneLineMax: number;
|
|
152
|
+
constructor(buttons: ReadonlyArray<string>, options: { oneLineMax: number; twoLineMax: number }) {
|
|
153
|
+
this.buttons = buttons.map((text) => new ButtonTextState(text));
|
|
154
|
+
// this.fitAllOptions = fitAllOptions;
|
|
155
|
+
this.oneLineMax = options.oneLineMax;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
fitAll() {
|
|
159
|
+
// const result = fitAll(this.buttons, this.fitAllOptions);
|
|
160
|
+
// return result;
|
|
161
|
+
}
|
|
162
|
+
isFitting(): boolean {
|
|
163
|
+
return this.getWidth() <= this.oneLineMax;
|
|
164
|
+
}
|
|
165
|
+
getWidth() {
|
|
166
|
+
return this.buttons.reduce((acc, b) => acc + b.width, 0);
|
|
167
|
+
}
|
|
168
|
+
isOneLine() {
|
|
169
|
+
return this.buttons.every((b) => !b.isSplit);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
compressOneButton(): boolean {
|
|
173
|
+
let btn: ButtonTextState | false = false;
|
|
174
|
+
let didCompress = false;
|
|
175
|
+
this.buttons.forEach((b) => {
|
|
176
|
+
if (!didCompress && b.canSplit) {
|
|
177
|
+
b.tryToSplit();
|
|
178
|
+
didCompress = true;
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return didCompress;
|
|
183
|
+
}
|
|
184
|
+
canCompress() {
|
|
185
|
+
return true;
|
|
186
|
+
// return this.buttons.some((b) => b.canSplit);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const fitAll = (buttons: string[], options: FitAllOptions): FittedResult => {
|
|
190
|
+
const bar = new ButtonBarState(buttons, {
|
|
191
|
+
oneLineMax: options.oneLine.max,
|
|
192
|
+
twoLineMax: options.twoLine.max,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
let isSingleLine = true;
|
|
196
|
+
|
|
197
|
+
// isSingleLine = state.every((b) => !b.isSplit);
|
|
198
|
+
// const requiredSpace = state.reduce((acc, b) => acc + b.width, 0);
|
|
199
|
+
|
|
200
|
+
let requiredSpace = 0;
|
|
201
|
+
let twoLineCount = 0;
|
|
202
|
+
if (!isSingleLine) {
|
|
203
|
+
twoLineCount = 1;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// const result = textWithLengths.map((text) => {
|
|
207
|
+
// if (text.max <= options.oneLine.max) {
|
|
208
|
+
// requiredSpace+= text.max;
|
|
209
|
+
// return { width: text.max, isSingleLine: true };
|
|
210
|
+
// } else if (text.min <= options.twoLine.max) {
|
|
211
|
+
// twoLineCount++;
|
|
212
|
+
// return { width: text.min, isSingleLine: false };
|
|
213
|
+
// } else {
|
|
214
|
+
// requiredSpace += text.min;
|
|
215
|
+
// return { width: text.min, isSingleLine: false };
|
|
216
|
+
// }
|
|
217
|
+
// });
|
|
218
|
+
return {
|
|
219
|
+
success: true,
|
|
220
|
+
isSingleLine,
|
|
221
|
+
requiredSpace,
|
|
222
|
+
twoLineCount,
|
|
223
|
+
result: [],
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
export const buttonTextUtils = {
|
|
228
|
+
checkLength,
|
|
229
|
+
fitAll,
|
|
230
|
+
splitInTwo,
|
|
231
|
+
allSplits,
|
|
232
|
+
maxWordLength,
|
|
233
|
+
} as const;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { ButtonBarState, ButtonTextState, buttonTextUtils } from "./button-text-utils";
|
|
2
|
+
|
|
3
|
+
const lineCount2 = 2;
|
|
4
|
+
describe("Button-text-utils", () => {
|
|
5
|
+
test("ButtonTextState works", () => {
|
|
6
|
+
const b1 = new ButtonTextState("vet ikke");
|
|
7
|
+
|
|
8
|
+
expect(b1.canSplit).toBe(true);
|
|
9
|
+
expect(b1.splitDiff).toBe(4);
|
|
10
|
+
expect(b1.width).toBe(8);
|
|
11
|
+
expect(b1.isSplit).toBe(false);
|
|
12
|
+
b1.tryToSplit();
|
|
13
|
+
expect(b1.width).toBe(4);
|
|
14
|
+
expect(b1.isSplit).toBe(true);
|
|
15
|
+
b1.unSplit();
|
|
16
|
+
expect(b1.width).toBe(8);
|
|
17
|
+
expect(b1.isSplit).toBe(false);
|
|
18
|
+
|
|
19
|
+
const b2 = new ButtonTextState("ja");
|
|
20
|
+
expect(b2.splitDiff).toBe(0);
|
|
21
|
+
expect(b2.canSplit).toBe(false);
|
|
22
|
+
expect(b2.width).toBe(2);
|
|
23
|
+
expect(b2.isSplit).toBe(false);
|
|
24
|
+
b2.tryToSplit();
|
|
25
|
+
expect(b2.width).toBe(2);
|
|
26
|
+
expect(b2.isSplit).toBe(true);
|
|
27
|
+
const b3 = new ButtonTextState("Mer enn 30 minutter");
|
|
28
|
+
expect(b3.canSplit).toBe(true);
|
|
29
|
+
expect(b3.splitDiff).toBe(9);
|
|
30
|
+
expect(b3.width).toBe(19);
|
|
31
|
+
expect(b3.isSplit).toBe(false);
|
|
32
|
+
b3.tryToSplit();
|
|
33
|
+
expect(b3.width).toBe(10);
|
|
34
|
+
expect(b3.isSplit).toBe(true);
|
|
35
|
+
b3.unSplit();
|
|
36
|
+
expect(b3.getState().width).toBe(19);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("ButtonBarState workss", () => {
|
|
40
|
+
const bar = new ButtonBarState(["ja", "nei", "vet ikke"], { oneLineMax: 10, twoLineMax: 10 });
|
|
41
|
+
expect(bar.getWidth()).toBe(13);
|
|
42
|
+
expect(bar.isFitting()).toBe(false);
|
|
43
|
+
expect(bar.isOneLine()).toBe(true);
|
|
44
|
+
expect(bar.canCompress()).toBe(true);
|
|
45
|
+
expect(bar.compressOneButton()).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("Max word length works", () => {
|
|
49
|
+
const a = buttonTextUtils.maxWordLength("ja");
|
|
50
|
+
expect(buttonTextUtils.maxWordLength("ja")).toBe(2);
|
|
51
|
+
expect(buttonTextUtils.maxWordLength("Ganske fin i dag")).toBe(6);
|
|
52
|
+
expect(buttonTextUtils.maxWordLength("rått")).toBe(4);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("All splitts work. ", () => {
|
|
56
|
+
const a = buttonTextUtils.allSplits("del da");
|
|
57
|
+
expect(a.length).toBe(2);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("Can split a string into two lines at the middle", () => {
|
|
61
|
+
const text = "del da for helvete";
|
|
62
|
+
const a = buttonTextUtils.splitInTwo(text);
|
|
63
|
+
expect(a.first).toBe("del da for");
|
|
64
|
+
const b = buttonTextUtils.splitInTwo("Mer enn 10 minutter");
|
|
65
|
+
expect(b.longest).toBe(10);
|
|
66
|
+
const c = buttonTextUtils.splitInTwo("litt vanskelig og");
|
|
67
|
+
expect(c.first).toBe("litt");
|
|
68
|
+
expect(c.last).toBe("vanskelig og");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("Will check if a text can fit within bounds.", () => {
|
|
72
|
+
const text = "dette blir en altfor lang text. Faen.";
|
|
73
|
+
const a = buttonTextUtils.checkLength(text);
|
|
74
|
+
expect(a.max).toBe(text.length);
|
|
75
|
+
expect(a.min).toBe(20);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("Fit all will detect if buttons dont fit on a single line.", () => {
|
|
79
|
+
const buttons = ["ja", "nei", "vet ikke"];
|
|
80
|
+
const r1 = buttonTextUtils.fitAll(buttons, {
|
|
81
|
+
oneLine: { min: 5, max: 12 },
|
|
82
|
+
twoLine: { min: 10, max: 20 },
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
expect(r1.isSingleLine).toEqual(false);
|
|
86
|
+
expect(r1.requiredSpace).toEqual(buttons.join("").length);
|
|
87
|
+
expect(r1.twoLineCount).toEqual(1);
|
|
88
|
+
const r2 = buttonTextUtils.fitAll(buttons, {
|
|
89
|
+
oneLine: { min: 5, max: 13 },
|
|
90
|
+
twoLine: { min: 10, max: 20 },
|
|
91
|
+
});
|
|
92
|
+
expect(r2.isSingleLine).toEqual(true);
|
|
93
|
+
expect(r2.twoLineCount).toEqual(0);
|
|
94
|
+
});
|
|
95
|
+
test("Will calculate required space, when break", () => {
|
|
96
|
+
const buttons = ["ja", "nei", "vet ikke"];
|
|
97
|
+
const r1 = buttonTextUtils.fitAll(buttons, {
|
|
98
|
+
oneLine: { min: 5, max: 10 },
|
|
99
|
+
twoLine: { min: 5, max: 10 },
|
|
100
|
+
});
|
|
101
|
+
// expect(r1.isSingleLine).toEqual(false);
|
|
102
|
+
// expect(r1.requiredSpace).toEqual("ja".length + "nei".length + "ikke".length);
|
|
103
|
+
// expect(r1.twoLineCount).toEqual(1);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ThemeCompiler } from "./ThemeCompiler";
|
|
2
|
-
import type { BuilderSchemaDto } from "../Builder-schema";
|
|
3
2
|
import { BuilderSchema } from "../Builder-schema";
|
|
4
3
|
import type { BuilderPageDto } from "../page/Builder-page";
|
|
5
4
|
import { DefaultTheme } from "./Default-theme";
|
|
@@ -26,12 +25,13 @@ import { AudioFile } from "../media-files";
|
|
|
26
25
|
import { BuilderRule } from "../rulebuilder";
|
|
27
26
|
import { IDefaultTheme } from "./IDefault-theme";
|
|
28
27
|
import { Theme2 } from "./theme2";
|
|
28
|
+
import { BuilderSchemaDto } from "../Builder-schema-dto";
|
|
29
29
|
|
|
30
30
|
export class DefaultThemeCompiler implements ThemeCompiler<IDefaultTheme> {
|
|
31
31
|
readonly name = "Ispe default theme.";
|
|
32
32
|
readonly defaultTheme = DefaultTheme;
|
|
33
33
|
readonly theme2 = Theme2;
|
|
34
|
-
currentTheme =
|
|
34
|
+
currentTheme = DefaultTheme;
|
|
35
35
|
allThemes = [DefaultTheme, Theme2];
|
|
36
36
|
private readonly TAG = "[ DEFAULT_THEME_COMPILER ]: ";
|
|
37
37
|
|
|
@@ -118,6 +118,7 @@ export class DefaultThemeCompiler implements ThemeCompiler<IDefaultTheme> {
|
|
|
118
118
|
let initialVideoTaskList: Array<PlayVideoTask | DelayTask> = [];
|
|
119
119
|
const newPage: PageDto = {
|
|
120
120
|
background: "white",
|
|
121
|
+
pageNumber,
|
|
121
122
|
elements,
|
|
122
123
|
id,
|
|
123
124
|
prefix,
|
package/src/theme/theme2.ts
CHANGED
|
@@ -22,6 +22,7 @@ const Colors = {
|
|
|
22
22
|
backgroundWhite: "white",
|
|
23
23
|
// progressBackGround: "#164AC4",
|
|
24
24
|
// progressForGround: "#F5F5F5",
|
|
25
|
+
|
|
25
26
|
// red: "red",
|
|
26
27
|
// yellow: "yellow",
|
|
27
28
|
};
|
|
@@ -144,21 +145,24 @@ const muteUnMuteStyles: { css: PStyle; cssDisabled: PStyle; cssEnabled: PStyle }
|
|
|
144
145
|
cssDisabled: { opacity: 0.3, cursor: "not-allowed" },
|
|
145
146
|
cssEnabled: { opacity: 0.8, cursor: "pointer" },
|
|
146
147
|
};
|
|
148
|
+
|
|
149
|
+
const FONT_QUESTION = 20;
|
|
150
|
+
const FONT_ = 20;
|
|
147
151
|
const responseButtonBaseCss = (): CssTheme => ({
|
|
148
152
|
css: {
|
|
149
153
|
backgroundColor: Colors.primary,
|
|
150
154
|
borderColor: Colors.primary,
|
|
151
155
|
textColor: Colors.white,
|
|
152
156
|
fontWeight: 600,
|
|
153
|
-
fontSize: { _unit: "px", value:
|
|
154
|
-
lineHeight: 1,
|
|
155
|
-
maxWidth:
|
|
157
|
+
fontSize: { _unit: "px", value: 28 },
|
|
158
|
+
lineHeight: 1.1,
|
|
159
|
+
maxWidth: 25,
|
|
156
160
|
// width: 20,
|
|
157
161
|
// flex: "0 0 auto",
|
|
158
|
-
paddingLeft: { _unit: "px", value:
|
|
159
|
-
paddingTop: { _unit: "px", value:
|
|
160
|
-
paddingBottom: { _unit: "px", value:
|
|
161
|
-
paddingRight: { _unit: "px", value:
|
|
162
|
+
paddingLeft: { _unit: "px", value: 10 },
|
|
163
|
+
paddingTop: { _unit: "px", value: 5 },
|
|
164
|
+
paddingBottom: { _unit: "px", value: 5 },
|
|
165
|
+
paddingRight: { _unit: "px", value: 10 },
|
|
162
166
|
borderRadius: { _unit: "px", value: 20 },
|
|
163
167
|
borderStyle: "solid",
|
|
164
168
|
boxShadow: "3px 3px gray",
|
|
@@ -365,11 +369,11 @@ export const Theme2: IDefaultTheme = {
|
|
|
365
369
|
display: "flex",
|
|
366
370
|
justifyContent: "flex-start",
|
|
367
371
|
width: BUTTON_BAR_WIDTH,
|
|
368
|
-
height:
|
|
372
|
+
height: 6,
|
|
369
373
|
bottom: Q_AREA_BOTTOM + H_M3,
|
|
370
374
|
left: Q_AREA_LEFT + W_M3,
|
|
371
375
|
// backgroundColor: "green",
|
|
372
|
-
gap: { _unit: "px", value:
|
|
376
|
+
gap: { _unit: "px", value: 40 },
|
|
373
377
|
alignItems: "stretch",
|
|
374
378
|
},
|
|
375
379
|
whenSingle: { justifyContent: "center" },
|