@24i/bigscreen-sdk 1.0.29-alpha.2491 → 1.0.30-alpha.2517
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@24i/bigscreen-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.30-alpha.2517",
|
|
4
4
|
"description": "SmartApps BIGscreen SDK monorepo",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -44,9 +44,6 @@
|
|
|
44
44
|
"@24i/smartapps-datalayer": "3.0.11-alpha.1019",
|
|
45
45
|
"@sentry/browser": "7.35.0",
|
|
46
46
|
"@sentry/types": "7.35.0",
|
|
47
|
-
"@types/gtag.js": "^0.0.14",
|
|
48
|
-
"@types/prop-types": "^15.7.7",
|
|
49
|
-
"@types/scheduler": "^0.16.4",
|
|
50
47
|
"csstype": "^3.1.2",
|
|
51
48
|
"date-fns": "2.29.3",
|
|
52
49
|
"lottie-web": "5.12.2",
|
|
@@ -56,14 +53,17 @@
|
|
|
56
53
|
"@24i/bigscreen-sdk": "file:.",
|
|
57
54
|
"@24i/eslint-config-smartapps-bigscreen-linters": "file:./libs/linters",
|
|
58
55
|
"@24i/smartapps-bigscreen-changelog-generator": "0.17.0",
|
|
59
|
-
"@babel/core": "^7.23.
|
|
60
|
-
"@babel/preset-env": "^7.
|
|
61
|
-
"@types/fs-extra": "^11.0.
|
|
62
|
-
"@types/
|
|
63
|
-
"@types/
|
|
64
|
-
"@types/
|
|
65
|
-
"@types/
|
|
56
|
+
"@babel/core": "^7.23.2",
|
|
57
|
+
"@babel/preset-env": "^7.23.2",
|
|
58
|
+
"@types/fs-extra": "^11.0.3",
|
|
59
|
+
"@types/gtag.js": "^0.0.17",
|
|
60
|
+
"@types/inquirer": "^9.0.6",
|
|
61
|
+
"@types/jest": "^29.5.7",
|
|
62
|
+
"@types/minimist": "^1.2.4",
|
|
63
|
+
"@types/node": "^20.8.10",
|
|
64
|
+
"@types/prop-types": "^15.7.9",
|
|
66
65
|
"@types/react": "18.0.33",
|
|
66
|
+
"@types/scheduler": "^0.16.5",
|
|
67
67
|
"babel-jest": "^29.7.0",
|
|
68
68
|
"chalk": "^5.3.0",
|
|
69
69
|
"coveralls": "^3.1.1",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"jest-sonar": "^0.2.15",
|
|
79
79
|
"minimist": "^1.2.8",
|
|
80
80
|
"patch-package": "^8.0.0",
|
|
81
|
-
"sass": "^1.
|
|
81
|
+
"sass": "^1.69.5",
|
|
82
82
|
"sass-true": "^6.1.0",
|
|
83
83
|
"ts-jest": "^29.1.1",
|
|
84
84
|
"ts-node": "^10.9.1",
|
package/packages/input/README.md
CHANGED
|
@@ -60,3 +60,6 @@ The reason for no styling is to limit unnecessary CSS code that would be overrid
|
|
|
60
60
|
`.native-input-wrap` is set to `display: none`. This is the native input used on the background.
|
|
61
61
|
|
|
62
62
|
`.input-field` is a custom component that should look like input field with possibility of custom styling.
|
|
63
|
+
|
|
64
|
+
`.caret` position is counted from the left side of the input in LTR layout and from the right side of the
|
|
65
|
+
input in RTL layout.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createRef, Component,
|
|
1
|
+
import { createRef, Component, DeclareProps } from '@24i/bigscreen-sdk/jsx';
|
|
2
2
|
import { Interactable } from '@24i/bigscreen-sdk/interactable';
|
|
3
3
|
import { IFocusable } from '@24i/bigscreen-sdk/focus';
|
|
4
4
|
import { isRtl } from '@24i/bigscreen-sdk/i18n';
|
|
@@ -9,7 +9,7 @@ import { stopEvent } from '@24i/bigscreen-sdk/utils/stopEvent';
|
|
|
9
9
|
import { addClass } from '@24i/bigscreen-sdk/utils/addClass';
|
|
10
10
|
import { removeClass } from '@24i/bigscreen-sdk/utils/removeClass';
|
|
11
11
|
import { offsetPosition } from '@24i/bigscreen-sdk/utils/offsetPosition';
|
|
12
|
-
import { handleOverflow } from './
|
|
12
|
+
import { checkCharOrderMishmash, handleOverflow } from './utils';
|
|
13
13
|
import './Input.scss';
|
|
14
14
|
|
|
15
15
|
type Props = {
|
|
@@ -42,6 +42,8 @@ export class Input extends Component<Props> implements IFocusable {
|
|
|
42
42
|
|
|
43
43
|
caret = createRef<HTMLDivElement>();
|
|
44
44
|
|
|
45
|
+
caretPosition = 0;
|
|
46
|
+
|
|
45
47
|
isInputting = false;
|
|
46
48
|
|
|
47
49
|
lastValue: string;
|
|
@@ -68,6 +70,11 @@ export class Input extends Component<Props> implements IFocusable {
|
|
|
68
70
|
this.isPlaceholderVisible = value.length === 0;
|
|
69
71
|
}
|
|
70
72
|
|
|
73
|
+
componentDidMount() {
|
|
74
|
+
const { value } = this.props;
|
|
75
|
+
if (value) this.setText(value);
|
|
76
|
+
}
|
|
77
|
+
|
|
71
78
|
getType() {
|
|
72
79
|
return this.nativeInput.current?.type;
|
|
73
80
|
}
|
|
@@ -85,13 +92,10 @@ export class Input extends Component<Props> implements IFocusable {
|
|
|
85
92
|
|
|
86
93
|
onCaretPositionChange = (position: number | null) => {
|
|
87
94
|
if (position === null) return;
|
|
88
|
-
const { shouldHandleOverflow } = this.props;
|
|
89
95
|
const value = this.getValue();
|
|
90
|
-
|
|
91
|
-
this.
|
|
92
|
-
|
|
93
|
-
handleOverflow(this.wrap.current, this.caret.current, this.text.current);
|
|
94
|
-
}
|
|
96
|
+
this.setText(value);
|
|
97
|
+
this.updateCaretPosition(position);
|
|
98
|
+
this.updateTextOverflow();
|
|
95
99
|
if (this.lastValue !== value) {
|
|
96
100
|
const { onChange } = this.props;
|
|
97
101
|
this.lastValue = value;
|
|
@@ -106,33 +110,59 @@ export class Input extends Component<Props> implements IFocusable {
|
|
|
106
110
|
|
|
107
111
|
setValue(value: string) {
|
|
108
112
|
this.nativeInput.current!.value = value;
|
|
113
|
+
this.setText(value);
|
|
109
114
|
}
|
|
110
115
|
|
|
111
116
|
setType(type: Props['type']) {
|
|
112
117
|
if (this.getType() === type) return;
|
|
113
118
|
const value = this.getValue();
|
|
114
119
|
this.nativeInput.current!.type = type;
|
|
115
|
-
|
|
120
|
+
this.setText(value);
|
|
116
121
|
}
|
|
117
122
|
|
|
118
|
-
|
|
123
|
+
setText(text: string): void {
|
|
124
|
+
const filtered = this.filterText(text);
|
|
125
|
+
this.renderText(filtered);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
updateCaretPosition(position: number) {
|
|
119
129
|
const textNode = this.text.current!.firstChild;
|
|
120
|
-
if (!textNode) {
|
|
130
|
+
if (!textNode || position <= 0) {
|
|
131
|
+
this.caretPosition = 0;
|
|
121
132
|
offsetPosition(this.caret, { x: 0 });
|
|
122
133
|
return;
|
|
123
134
|
}
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
135
|
+
const wholeTextDimensions = this.text.current!.getBoundingClientRect();
|
|
136
|
+
if (position >= this.text.current!.children.length) {
|
|
137
|
+
const offset = wholeTextDimensions.right - wholeTextDimensions.left;
|
|
138
|
+
this.caretPosition = isRtl() ? -offset : offset;
|
|
139
|
+
offsetPosition(this.caret, { x: this.caretPosition }, false);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const charNode = this.text.current!.children[position - 1];
|
|
143
|
+
const charDimensions = charNode!.getBoundingClientRect();
|
|
144
|
+
const isCharMishmash = checkCharOrderMishmash(this.text.current!, position - 1);
|
|
145
|
+
if (isRtl()) {
|
|
146
|
+
if (isCharMishmash) {
|
|
147
|
+
this.caretPosition = charDimensions.right - wholeTextDimensions.right;
|
|
148
|
+
} else {
|
|
149
|
+
this.caretPosition = charDimensions.left - wholeTextDimensions.right;
|
|
150
|
+
}
|
|
151
|
+
} else if (isCharMishmash) {
|
|
152
|
+
this.caretPosition = charDimensions.left - wholeTextDimensions.left;
|
|
153
|
+
} else {
|
|
154
|
+
this.caretPosition = charDimensions.right - wholeTextDimensions.left;
|
|
155
|
+
}
|
|
156
|
+
offsetPosition(this.caret, { x: this.caretPosition }, false);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
updateTextOverflow() {
|
|
160
|
+
const { shouldHandleOverflow } = this.props;
|
|
161
|
+
if (!shouldHandleOverflow) return;
|
|
162
|
+
const textMargin = handleOverflow(
|
|
163
|
+
this.wrap.current, this.caret.current, this.text.current,
|
|
164
|
+
);
|
|
165
|
+
offsetPosition(this.caret, { x: this.caretPosition - textMargin }, false);
|
|
136
166
|
}
|
|
137
167
|
|
|
138
168
|
/**
|
|
@@ -196,6 +226,14 @@ export class Input extends Component<Props> implements IFocusable {
|
|
|
196
226
|
return text.replace(/ /g, NBSP);
|
|
197
227
|
}
|
|
198
228
|
|
|
229
|
+
renderText(text: string): void {
|
|
230
|
+
const chars: JSX.Element[] = [];
|
|
231
|
+
for (let i = 0; i < text.length; i++) {
|
|
232
|
+
chars.push(<span className="char">{text[i]}</span>);
|
|
233
|
+
}
|
|
234
|
+
this.clearMount(chars, this.text);
|
|
235
|
+
}
|
|
236
|
+
|
|
199
237
|
render() {
|
|
200
238
|
const { value, type, placeholder, onFocus, onBlur } = this.props;
|
|
201
239
|
return (
|
|
@@ -220,9 +258,7 @@ export class Input extends Component<Props> implements IFocusable {
|
|
|
220
258
|
>
|
|
221
259
|
{placeholder}
|
|
222
260
|
</div>
|
|
223
|
-
<div ref={this.text} className="text"
|
|
224
|
-
{this.filterText(value)}
|
|
225
|
-
</div>
|
|
261
|
+
<div ref={this.text} className="text" />
|
|
226
262
|
<div ref={this.caret} className="caret" />
|
|
227
263
|
</div>
|
|
228
264
|
</Interactable>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { isRtl } from '@24i/bigscreen-sdk/i18n';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Handles overflowing text in the input by moving with the inner
|
|
5
|
+
* text element.
|
|
6
|
+
* @param wrap input wrapper
|
|
7
|
+
* @param caret caret element
|
|
8
|
+
* @param text input inner text element
|
|
9
|
+
* @returns value how much is text element moved
|
|
10
|
+
*/
|
|
11
|
+
export const handleOverflow = (
|
|
12
|
+
wrap: HTMLDivElement | null,
|
|
13
|
+
caret: HTMLDivElement | null,
|
|
14
|
+
text: HTMLDivElement | null,
|
|
15
|
+
) => {
|
|
16
|
+
if (!wrap || !caret || !text) return 0;
|
|
17
|
+
const { width: wrapWidth, left: wrapLeft } = wrap.getBoundingClientRect();
|
|
18
|
+
const { width: caretWidth, left: caretLeft } = caret.getBoundingClientRect();
|
|
19
|
+
const caretOffset = isRtl() ? caretLeft - caretWidth : caretLeft + caretWidth;
|
|
20
|
+
if (!isRtl() && wrapWidth + wrapLeft < caretOffset) {
|
|
21
|
+
const margin = -(caretOffset - wrapWidth - wrapLeft);
|
|
22
|
+
text.style.marginLeft = `${margin}px`;
|
|
23
|
+
text.style.marginRight = '0px';
|
|
24
|
+
return margin;
|
|
25
|
+
}
|
|
26
|
+
if (isRtl() && caretOffset < wrapLeft) {
|
|
27
|
+
const margin = -(wrapLeft - caretOffset);
|
|
28
|
+
text.style.marginLeft = '0px';
|
|
29
|
+
text.style.marginRight = `${margin}px`;
|
|
30
|
+
return margin;
|
|
31
|
+
}
|
|
32
|
+
text.style.marginLeft = '0px';
|
|
33
|
+
text.style.marginRight = '0px';
|
|
34
|
+
return 0;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Check for char element position mishmash in the input's text element. This is
|
|
39
|
+
* necessary to recognize if the char is in the wrong direction than it's position
|
|
40
|
+
* in children collection, this means that the char is LTR char in RTL scheme or RTL
|
|
41
|
+
* char in LTR scheme.
|
|
42
|
+
* @param text input inner text element
|
|
43
|
+
* @param position position of the char in children collection
|
|
44
|
+
* @returns true if char has position mishmash
|
|
45
|
+
*/
|
|
46
|
+
export const checkCharOrderMishmash = (text: HTMLDivElement, position: number) => {
|
|
47
|
+
const { children } = text!;
|
|
48
|
+
if (!children.length) return false;
|
|
49
|
+
const charOffsets: {
|
|
50
|
+
index: number,
|
|
51
|
+
offset: number,
|
|
52
|
+
}[] = [];
|
|
53
|
+
for (let i = 0; i < children.length; i++) {
|
|
54
|
+
charOffsets.push({
|
|
55
|
+
index: i,
|
|
56
|
+
offset: (children[i] as HTMLElement).getBoundingClientRect().left,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
charOffsets.sort((a, b) => {
|
|
60
|
+
if (a.offset < b.offset) return isRtl() ? 1 : -1;
|
|
61
|
+
if (a.offset > b.offset) return isRtl() ? -1 : 1;
|
|
62
|
+
return 0;
|
|
63
|
+
});
|
|
64
|
+
const lastPos = children.length - 1;
|
|
65
|
+
const posBefore = position - 1;
|
|
66
|
+
const mishmashBefore = posBefore < 0
|
|
67
|
+
? false : charOffsets[posBefore].index !== posBefore;
|
|
68
|
+
const mishmashCurrent = charOffsets[position].index !== position;
|
|
69
|
+
if (mishmashCurrent) return true;
|
|
70
|
+
return !mishmashCurrent && mishmashBefore && position !== lastPos;
|
|
71
|
+
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { isRtl } from '@24i/bigscreen-sdk/i18n';
|
|
2
|
-
|
|
3
|
-
export const handleOverflow = (
|
|
4
|
-
wrap: HTMLDivElement | null,
|
|
5
|
-
caret: HTMLDivElement | null,
|
|
6
|
-
text: HTMLDivElement | null,
|
|
7
|
-
) => {
|
|
8
|
-
if (!wrap || !caret || !text) return;
|
|
9
|
-
const { width: wrapWidth, left: wrapLeft } = wrap.getBoundingClientRect();
|
|
10
|
-
const { width: caretWidth, left: caretLeft } = caret.getBoundingClientRect();
|
|
11
|
-
const textMargin = parseInt(text.dataset.margin!, 10) || 0;
|
|
12
|
-
const caretOffset = isRtl()
|
|
13
|
-
? caretLeft + textMargin - caretWidth
|
|
14
|
-
: caretLeft - textMargin + caretWidth;
|
|
15
|
-
if (!isRtl() && wrapWidth + wrapLeft < caretOffset) {
|
|
16
|
-
const margin = -(caretOffset - wrapWidth - wrapLeft);
|
|
17
|
-
text.style.marginLeft = `${margin}px`;
|
|
18
|
-
text.style.marginRight = '0px';
|
|
19
|
-
text.dataset.margin = margin.toString();
|
|
20
|
-
} else if (isRtl() && caretOffset < wrapLeft) {
|
|
21
|
-
const margin = -(wrapLeft - caretOffset);
|
|
22
|
-
text.style.marginLeft = '0px';
|
|
23
|
-
text.style.marginRight = `${margin}px`;
|
|
24
|
-
text.dataset.margin = margin.toString();
|
|
25
|
-
} else {
|
|
26
|
-
text.style.marginLeft = '0px';
|
|
27
|
-
text.style.marginRight = '0px';
|
|
28
|
-
}
|
|
29
|
-
};
|