pxt-core 8.2.9 → 8.2.11

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.
@@ -230,21 +230,30 @@
230
230
  }
231
231
 
232
232
  /****************************************************
233
- * Circle Buttons *
233
+ * Square Buttons *
234
234
  ****************************************************/
235
235
 
236
- .common-button.circle-button {
236
+ .common-button.square-button {
237
237
  width: 3rem;
238
238
  height: 3rem;
239
239
  overflow: hidden;
240
240
  padding: 0;
241
- border-radius: 2rem;
242
241
 
243
242
  i, i.fas, i.far {
244
243
  margin: 0;
245
244
  }
246
245
  }
247
246
 
247
+
248
+ /****************************************************
249
+ * Circle Buttons *
250
+ ****************************************************/
251
+
252
+ .common-button.circle-button {
253
+ &:extend(.common-button.square-button);
254
+ border-radius: 2rem;
255
+ }
256
+
248
257
  .common-button.circle-button:focus::after {
249
258
  border-radius: 2rem;
250
259
  }
@@ -253,6 +262,14 @@
253
262
  * Social Buttons *
254
263
  ****************************************************/
255
264
 
265
+ .common-button.social-button {
266
+ font-size: 1.5rem;
267
+
268
+ img {
269
+ max-width: 100%;
270
+ }
271
+ }
272
+
256
273
  .common-button.facebook {
257
274
  background: #4267B2;
258
275
  color: @buttonTextColorDarkBackground;
@@ -273,6 +290,16 @@
273
290
  color: @buttonTextColorDarkBackground;
274
291
  }
275
292
 
293
+ .common-button.whatsapp {
294
+ background: #59CE72;
295
+ color: @buttonTextColorDarkBackground;
296
+ }
297
+
298
+ .common-button.microsoft-teams {
299
+ background: #35258F;
300
+ color: @buttonTextColorDarkBackground;
301
+ }
302
+
276
303
  /****************************************************
277
304
  * High Contrast *
278
305
  ****************************************************/
@@ -24,8 +24,13 @@
24
24
  overflow: hidden;
25
25
  }
26
26
 
27
- @media @mobileAndBelow {
28
- .common-modal {
27
+ .wide > .common-modal {
28
+ width: 75%;
29
+ max-width: 60rem;
30
+ }
31
+
32
+ @media @tabletAndBelow {
33
+ .common-modal, .wide > .common-modal {
29
34
  width: 95%;
30
35
  }
31
36
  }
@@ -23,25 +23,34 @@
23
23
  }
24
24
  }
25
25
 
26
+
26
27
  .project-share-info {
27
28
  display: flex;
28
- flex-direction: column;
29
+ flex-direction: row;
29
30
  justify-content: center;
30
31
  flex: 1;
31
32
 
32
- > div {
33
- margin-bottom: 1rem;
34
- flex-shrink: 0;
33
+ .project-share-content {
34
+ flex-grow: 1;
35
+
36
+ .name-input .common-input-group {
37
+ height: 3rem;
38
+ margin-bottom: 0.5rem;
39
+ }
40
+
41
+ .common-checkbox {
42
+ margin-bottom: 0.5rem;
43
+ }
35
44
  }
36
45
  }
37
46
 
38
47
  .project-share-title {
39
- display: flex;
48
+ margin-bottom: 1rem;
49
+ }
40
50
 
41
- h2 {
42
- flex: 1;
43
- margin: 0;
44
- }
51
+ .project-share-label {
52
+ font-weight: 700;
53
+ margin-bottom: 0.5rem;
45
54
  }
46
55
 
47
56
  #project-share-dropdown {
@@ -51,6 +60,9 @@
51
60
  .project-share-thumbnail {
52
61
  display: flex;
53
62
  flex-direction: column;
63
+ min-width: 15rem;
64
+ align-items: center;
65
+ margin-right: 1rem;
54
66
 
55
67
  .project-thumbnail-placeholder,
56
68
  img {
@@ -58,6 +70,18 @@
58
70
  width: 15rem;
59
71
  height: 11.25rem;
60
72
  background-color: rgba(0, 0, 0, 0.05);
73
+ margin-bottom: 1rem;
74
+ }
75
+
76
+ .project-thumbnail-placeholder {
77
+ display: flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+
81
+ .common-spinner {
82
+ width: 5rem;
83
+ height: 5rem;
84
+ }
61
85
  }
62
86
  }
63
87
 
@@ -74,41 +98,40 @@
74
98
 
75
99
  .share-publish-button {
76
100
  height: 3rem;
101
+ margin-right: 1rem;
77
102
 
78
103
  .common-spinner {
79
104
  display: inline-block;
80
105
  }
81
106
  }
82
107
 
108
+
83
109
  /////////////////////////////////////////
84
110
  // Embed //
85
111
  /////////////////////////////////////////
86
112
 
87
113
  .project-share-actions {
88
114
  display: flex;
115
+ flex-direction: row;
89
116
  margin-top: 1rem;
90
117
  position: relative;
91
118
  margin-bottom: 2rem;
119
+ }
92
120
 
93
- .common-button {
94
- margin-right: 1rem;
95
- }
121
+ .project-share-social {
122
+ display: flex;
123
+ flex-direction: row;
124
+ flex-grow: 1;
125
+ flex-wrap: wrap;
126
+ gap: 0.5rem;
96
127
  }
97
128
 
98
129
  .project-share-text {
99
130
  margin-bottom: 1rem;
100
131
  }
101
132
 
102
- .common-button.menu-button.project-qrcode {
103
- position: absolute;
104
- right: 0;
105
- height: 6rem;
106
- padding: 0.5rem;
107
- top: -0.5rem;
108
-
109
- img {
110
- height: 5rem;
111
- }
133
+ .common-button.menu-button.project-qrcode img {
134
+ height: 5rem;
112
135
  }
113
136
 
114
137
  .common-button.menu-button.project-qrcode:focus::after {
@@ -144,19 +167,59 @@
144
167
  // Gif Recorder //
145
168
  /////////////////////////////////////////
146
169
 
170
+ .gif-recorder-content {
171
+ display: flex;
172
+ flex-direction: row;
173
+ align-items: center;
174
+
175
+ .thumbnail-controls {
176
+ display: flex;
177
+ flex-direction: column;
178
+ padding: 0 4rem;
179
+
180
+ .thumbnail-preview {
181
+ display: flex;
182
+ flex-direction: column;
183
+ flex-grow: 1;
184
+ align-items: center;
185
+
186
+ & > div {
187
+ padding-bottom: 1rem;
188
+ }
189
+
190
+ .thumbnail-image,
191
+ .thumbnail-placeholder {
192
+ display: flex;
193
+ background-color: rgba(0, 0, 0, 0.05);
194
+ width: 15rem;
195
+ height: 12.25rem;
196
+ }
197
+ }
198
+
199
+ .thumbnail-actions {
200
+ display: flex;
201
+ flex-direction: row;
202
+ }
203
+ }
204
+ }
205
+
206
+ .gif-recorder-sim-embed {
207
+ flex-grow: 1;
208
+ padding-right: 1rem;
209
+
210
+ .simframe {
211
+ padding-bottom: 56.25%!important;
212
+ }
213
+ }
214
+
215
+ .gif-recorder-sim {
216
+ flex-grow: 1;
217
+ }
218
+
147
219
  .gif-recorder {
148
- position: absolute;
149
220
  display: flex;
150
221
  flex-direction: column;
151
222
  align-items: center;
152
-
153
- bottom: 0;
154
- left: calc(~'(100vw - 25rem)/2');
155
- padding: 1rem;
156
- transform: translateX(-50%);
157
- background: @white;
158
- border: @teal;
159
- border-radius: 0.2rem;
160
223
  font-family: @segoeUIFont;
161
224
  }
162
225
 
@@ -176,4 +239,79 @@
176
239
  background-color: rgba(0, 0, 0, 0.05);
177
240
  width: 24.5rem;
178
241
  height: 18.375rem;
242
+ }
243
+
244
+ .thumbnail-header {
245
+ display: flex;
246
+ flex-direction: row;
247
+
248
+ .project-share-label {
249
+ flex-grow: 1;
250
+ }
251
+
252
+ .common-button.link-button {
253
+ margin-bottom: 0.5rem;
254
+ }
255
+ }
256
+
257
+
258
+ /////////////////////////////////////////
259
+ // Mobile //
260
+ /////////////////////////////////////////
261
+
262
+ #root.miniSim:not(.fullscreensim) .gif-recorder-sim div.simframe {
263
+ width: 100%;
264
+ }
265
+
266
+ @media @tabletAndBelow {
267
+ .gif-recorder-content .thumbnail-controls {
268
+ padding: 0 2rem;
269
+ }
270
+ }
271
+
272
+ @media @mobileAndBelow {
273
+ .project-share-info, .gif-recorder-content {
274
+ flex-direction: column;
275
+ }
276
+
277
+ .gif-recorder-sim {
278
+ width: 100%;
279
+ }
280
+
281
+ .gif-recorder-actions {
282
+ width: 100%;
283
+
284
+ .spacer {
285
+ flex-grow: 1;
286
+ }
287
+ }
288
+
289
+ .gif-recorder-actions .common-button:not(.mobile-only) {
290
+ width: 3rem;
291
+ height: 3rem;
292
+ overflow: hidden;
293
+ padding: 0;
294
+
295
+ i, i.fas, i.far {
296
+ margin: 0;
297
+ }
298
+
299
+ .common-button-label {
300
+ display: none;
301
+ }
302
+ }
303
+
304
+ .gif-recorder-content {
305
+ &.has-uri {
306
+ .gif-recorder-sim {
307
+ display: none;
308
+ }
309
+ }
310
+
311
+ &:not(.has-uri) {
312
+ .thumbnail-controls {
313
+ display: none;
314
+ }
315
+ }
316
+ }
179
317
  }
@@ -1,63 +0,0 @@
1
- import * as React from "react";
2
- import { Button } from "../controls/Button";
3
- import { GifRecorder } from "./GifRecorder";
4
-
5
- export interface GifInfoProps {
6
- initialUri?: string;
7
-
8
- onApply: (uri: string) => void;
9
- onCancel: () => void;
10
-
11
- screenshotAsync?: () => Promise<string>;
12
- gifRecordAsync?: () => Promise<void>;
13
- gifRenderAsync?: () => Promise<string | void>;
14
- gifAddFrame?: (dataUri: ImageData, delay?: number) => boolean;
15
-
16
- registerSimulatorMsgHandler?: (handler: (msg: any) => void) => void;
17
- unregisterSimulatorMsgHandler?: () => void;
18
- }
19
-
20
- export const GifInfo = (props: GifInfoProps) => {
21
- const { initialUri, onApply, onCancel, screenshotAsync, gifRecordAsync, gifRenderAsync, gifAddFrame,
22
- registerSimulatorMsgHandler, unregisterSimulatorMsgHandler } = props;
23
- const [ uri, setUri ] = React.useState(initialUri);
24
-
25
- const handleApplyClick = (evt?: any) => {
26
- onApply(uri);
27
- }
28
-
29
- const handleScreenshotClick = async () => {
30
- const screenshotUri = await screenshotAsync();
31
- setUri(screenshotUri);
32
- }
33
-
34
- const handleRecordStopClick = async () => {
35
- const gifUri = await gifRenderAsync();
36
- if (gifUri) setUri(gifUri);
37
- }
38
-
39
- return <>
40
- <span className="thumbnail-label">{lf("Current Thumbnail")}</span>
41
- <div className="thumbnail-image">
42
- {uri
43
- ? <img src={uri} />
44
- : <div className="thumbnail-placeholder" />
45
- }
46
- </div>
47
- <div className="thumbnail-actions">
48
- <Button className="primary"
49
- title={lf("Apply")}
50
- label={lf("Apply")}
51
- onClick={handleApplyClick} />
52
- <Button title={lf("Cancel")}
53
- label={lf("Cancel")}
54
- onClick={onCancel} />
55
- </div>
56
- <GifRecorder onScreenshot={screenshotAsync ? handleScreenshotClick : undefined}
57
- onRecordStart={gifRecordAsync}
58
- onRecordStop={handleRecordStopClick}
59
- onGifFrame={gifAddFrame}
60
- registerSimulatorMsgHandler={registerSimulatorMsgHandler}
61
- unregisterSimulatorMsgHandler={unregisterSimulatorMsgHandler} />
62
- </>
63
- }
@@ -1,97 +0,0 @@
1
- import * as React from "react";
2
- import { Button } from "../controls/Button";
3
-
4
- type RecorderState = "default" | "recording" | "rendering";
5
-
6
- export interface GifRecorderProps {
7
- onScreenshot?: () => void;
8
- onRecordStart?: () => void;
9
- onRecordStop?: () => Promise<void>;
10
- onGifFrame?: (dataUri: ImageData, delay?: number) => boolean;
11
- registerSimulatorMsgHandler?: (handler: (msg: any) => void) => void;
12
- unregisterSimulatorMsgHandler?: () => void;
13
- }
14
-
15
- export const GifRecorder = (props: GifRecorderProps) => {
16
- const { onScreenshot, onRecordStart, onRecordStop, onGifFrame,
17
- registerSimulatorMsgHandler, unregisterSimulatorMsgHandler } = props;
18
- const [ recorderState, _setRecorderState ] = React.useState<RecorderState>("default");
19
- const recorderStateRef = React.useRef(recorderState);
20
- const targetTheme = pxt.appTarget.appTheme;
21
-
22
- const setRecorderState = (state: RecorderState) => {
23
- _setRecorderState(state);
24
- recorderStateRef.current = state;
25
- }
26
-
27
- const onGifRecordStop = async () => {
28
- setRecorderState("rendering");
29
- await onRecordStop();
30
- setRecorderState("default");
31
- }
32
-
33
- const handleKeyDown = (e: KeyboardEvent) => {
34
- const pressed = e.key.toLocaleLowerCase();
35
- if (targetTheme.simScreenshotKey && pressed === targetTheme.simScreenshotKey.toLocaleLowerCase()) {
36
- onScreenshot();
37
- } else if (targetTheme.simGifKey && pressed === targetTheme.simGifKey.toLocaleLowerCase()) {
38
- if (recorderStateRef.current === "recording") {
39
- onGifRecordStop();
40
- } else {
41
- onGifRecordStart();
42
- }
43
- }
44
- }
45
-
46
- const handleSimulatorMsg = (e: any) => {
47
- if (e.type === "screenshot") {
48
- if (recorderStateRef.current === "recording") {
49
- // Adds frame, returns true if we've exceeded the max frame count
50
- if (onGifFrame(e.data, e.delay)) {
51
- onGifRecordStop();
52
- }
53
- } else {
54
- onScreenshot();
55
- }
56
- } else if (e.event === "start") {
57
- onGifRecordStart();
58
- } else if (e.event === "stop") {
59
- onGifRecordStop();
60
- }
61
- }
62
-
63
- React.useEffect(() => {
64
- document.addEventListener("keydown", handleKeyDown);
65
- if (registerSimulatorMsgHandler) registerSimulatorMsgHandler(handleSimulatorMsg);
66
-
67
- return () => {
68
- document.removeEventListener("keydown", handleKeyDown);
69
- if (unregisterSimulatorMsgHandler) unregisterSimulatorMsgHandler();
70
- }
71
- }, []);
72
-
73
- const onGifRecordStart = () => {
74
- setRecorderState("recording");
75
- onRecordStart();
76
- }
77
-
78
- const screenshotLabel = lf("Take screenshot ({0})", targetTheme.simScreenshotKey);
79
- const startRecordingLabel = lf("Record game play ({0})", targetTheme.simGifKey);
80
- const stopRecordingLabel = lf("Stop recording ({0})", targetTheme.simGifKey) ;
81
-
82
- return <div className="gif-recorder">
83
- <div className="gif-recorder-label">{lf("Pick your project thumbnail")}</div>
84
- <div className="gif-recorder-actions">
85
- {!!onScreenshot && <Button className="teal inverted"
86
- title={screenshotLabel}
87
- label={screenshotLabel}
88
- leftIcon="fas fa-camera"
89
- onClick={onScreenshot} />}
90
- {!!onRecordStart && <Button className="teal inverted"
91
- title={recorderState === "recording" ? stopRecordingLabel : startRecordingLabel}
92
- label={recorderState === "recording" ? stopRecordingLabel : startRecordingLabel}
93
- leftIcon={`fas fa-${recorderState === "recording" ? "square" : "circle"}`}
94
- onClick={recorderState === "recording" ? onGifRecordStop : onGifRecordStart} />}
95
- </div>
96
- </div>
97
- }