@arcblock/terminal 3.1.8 → 3.1.9

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/lib/styles.js ADDED
@@ -0,0 +1,299 @@
1
+ import e from "@emotion/styled";
2
+ const t = e.div({
3
+ // Base styles for .terminal-player
4
+ display: "inline-block",
5
+ position: "relative",
6
+ fontSize: 0,
7
+ // Terminal styles
8
+ "& .terminal": { display: "inline-block" },
9
+ "& .terminal .xterm .xterm-viewport": { overflowY: "hidden !important" },
10
+ // Terminal frame
11
+ "& .terminal-frame": { position: "relative" },
12
+ // Reset styles for terminal divs
13
+ "& .terminal div": {
14
+ margin: 0,
15
+ padding: 0,
16
+ border: 0,
17
+ outline: 0,
18
+ fontWeight: "inherit",
19
+ fontStyle: "inherit",
20
+ fontSize: "100%",
21
+ fontFamily: "inherit",
22
+ verticalAlign: "baseline"
23
+ },
24
+ // Window theme
25
+ "&.terminal-window .terminal-frame": {
26
+ borderRadius: 6,
27
+ border: "1px solid #b3b3b3",
28
+ boxShadow: "0px 0px 18px #b3b3b3",
29
+ margin: 18,
30
+ overflow: "hidden",
31
+ "& .terminal-titlebar": {
32
+ background: "#e8e8e8",
33
+ borderBottom: "1px solid #b1aeb1",
34
+ borderTop: "1px solid #f3f1f3",
35
+ borderTopLeftRadius: 6,
36
+ borderTopRightRadius: 6,
37
+ color: "#3b4247",
38
+ fontFamily: "Arial, sans-serif",
39
+ fontSize: 14,
40
+ height: 22,
41
+ lineHeight: "22px",
42
+ position: "relative",
43
+ textAlign: "center",
44
+ width: "100%",
45
+ "& .buttons": { left: 8, lineHeight: "0px", position: "absolute", top: 3.5 },
46
+ "& .close-button": {
47
+ background: "#ff5c5c",
48
+ borderRadius: "50%",
49
+ border: "1px solid #e33e41",
50
+ display: "inline-block",
51
+ height: 12,
52
+ width: 12
53
+ },
54
+ "& .minimize-button": {
55
+ background: "#ffbd4c",
56
+ borderRadius: "50%",
57
+ border: "1px solid #e09e3e",
58
+ display: "inline-block",
59
+ height: 12,
60
+ marginLeft: 4,
61
+ width: 12
62
+ },
63
+ "& .maximize-button": {
64
+ background: "#00ca56",
65
+ borderRadius: "50%",
66
+ border: "1px solid #14ae46",
67
+ display: "inline-block",
68
+ height: 12,
69
+ marginLeft: 4,
70
+ width: 12
71
+ }
72
+ },
73
+ "& .terminal-body": { backgroundColor: "#1d1d1d", padding: 10 }
74
+ },
75
+ // Floating theme
76
+ "&.terminal-floating .terminal-frame": {
77
+ backgroundColor: "#1d1d1d",
78
+ borderRadius: 6,
79
+ boxShadow: "0px 0px 18px #b3b3b3",
80
+ margin: 18,
81
+ overflow: "hidden",
82
+ "& .terminal-titlebar": {
83
+ color: "white",
84
+ fontFamily: "Arial, sans-serif",
85
+ fontSize: 14,
86
+ height: 34,
87
+ lineHeight: "34px",
88
+ position: "relative",
89
+ textAlign: "center",
90
+ width: "100%",
91
+ "& .buttons": { left: 13, lineHeight: "0px", position: "absolute", top: 9 },
92
+ "& .close-button": { background: "#ff5c5c", borderRadius: "50%", display: "inline-block", height: 15, width: 15 },
93
+ "& .minimize-button": {
94
+ background: "#ffbd4c",
95
+ borderRadius: "50%",
96
+ display: "inline-block",
97
+ height: 15,
98
+ lineHeight: "10px",
99
+ marginLeft: 4,
100
+ width: 15
101
+ },
102
+ "& .maximize-button": {
103
+ background: "#00ca56",
104
+ borderRadius: "50%",
105
+ display: "inline-block",
106
+ height: 15,
107
+ lineHeight: "10px",
108
+ marginLeft: 4,
109
+ width: 15
110
+ }
111
+ },
112
+ "& .terminal-body": { padding: 20 }
113
+ },
114
+ // Solid theme
115
+ "&.terminal-solid .terminal-frame": {
116
+ backgroundColor: "#1d1d1d",
117
+ borderRadius: 6,
118
+ boxShadow: "0px 0px 18px #b3b3b3",
119
+ margin: 18,
120
+ overflow: "hidden",
121
+ "& .terminal-titlebar": {
122
+ color: "white",
123
+ fontFamily: "Arial, sans-serif",
124
+ fontSize: 14,
125
+ position: "relative",
126
+ textAlign: "center",
127
+ width: "100%",
128
+ "& .title": {
129
+ margin: "15px 15px 15px",
130
+ "&:empty": { display: "none" }
131
+ },
132
+ "& .buttons": { display: "none" }
133
+ },
134
+ "& .terminal-body": { padding: 20 }
135
+ },
136
+ // Player controls
137
+ "& .controller": {
138
+ background: "#45484d",
139
+ // Original first background value
140
+ backgroundColor: "#222222",
141
+ // Override background (matches original CSS)
142
+ bottom: "0px",
143
+ display: "none",
144
+ fontFamily: "Helvetica, Arial, sans-serif",
145
+ fontSize: 12,
146
+ height: 40,
147
+ position: "absolute",
148
+ width: "100%",
149
+ zIndex: 20,
150
+ transition: "height ease 200ms",
151
+ WebkitTransition: "height ease 200ms",
152
+ MozTransition: "height ease 200ms",
153
+ OTransition: "height ease 200ms"
154
+ },
155
+ "&.controls .controller": { display: "block" },
156
+ "&.playing .controller": { height: 0, overflow: "hidden" },
157
+ "&.playing:hover .controller": { height: 40, overflow: "hidden" },
158
+ // Play/Pause buttons
159
+ "& .play, & .pause": {
160
+ fill: "#cacaca",
161
+ float: "left",
162
+ height: 40,
163
+ lineHeight: "40px",
164
+ textAlign: "center",
165
+ width: 40,
166
+ "& .icon": {
167
+ borderColor: "transparent transparent transparent #cacaca",
168
+ boxSizing: "border-box",
169
+ cursor: "pointer",
170
+ display: "inline-block",
171
+ height: 15
172
+ }
173
+ },
174
+ "& .pause": {
175
+ display: "none",
176
+ "& .icon": { borderStyle: "double", borderWidth: "0px 0px 0px 12px", marginTop: 11 }
177
+ },
178
+ "& .play .icon": { borderStyle: "solid", borderWidth: "8px 0px 8px 13px", marginTop: 10 },
179
+ "&.playing .play": { display: "none" },
180
+ "&.playing .pause": { display: "inline-block" },
181
+ // Timer
182
+ "& .timer": { color: "#cacaca", float: "right", lineHeight: "40px", padding: "0 10px" },
183
+ // Progress bar
184
+ "& .progressbar-wrapper": { height: 40, lineHeight: "38px", overflow: "hidden" },
185
+ "& .progressbar": {
186
+ backgroundColor: "#424242",
187
+ display: "inline-block",
188
+ height: 7,
189
+ overflow: "hidden",
190
+ width: "100%",
191
+ borderRadius: 10,
192
+ MozBorderRadius: 10,
193
+ WebkitBorderRadius: 10
194
+ },
195
+ "&.started .progressbar": { cursor: "pointer" },
196
+ "& .progress": { backgroundColor: "#cacaca", height: 7, position: "relative", width: "0%" },
197
+ // Cover and start button
198
+ "& .cover": { cursor: "pointer", height: "100%", position: "absolute", width: "100%", zIndex: 10 },
199
+ "& .start svg": {
200
+ cursor: "pointer",
201
+ fill: "#eaeaea",
202
+ height: 130,
203
+ left: "50%",
204
+ marginLeft: -65,
205
+ marginTop: -65,
206
+ position: "absolute",
207
+ top: "50%",
208
+ width: 130,
209
+ zIndex: 20,
210
+ filter: "drop-shadow(10px 10px 15px rgba(0, 0, 0, 0.4))",
211
+ WebkitFilter: "drop-shadow(10px 10px 15px rgba(0, 0, 0, 0.4))"
212
+ },
213
+ "&.small .start svg": { height: 60, marginLeft: -30, marginTop: -30, width: 60 },
214
+ "&.framed .start svg": {
215
+ transform: "translate(0px, 8px)",
216
+ WebkitTransform: "translate(0px, 8px)",
217
+ MozTransform: "translate(0px, 8px)",
218
+ OTransform: "translate(0px, 8px)",
219
+ MsTransform: "translate(0px, 8px)"
220
+ },
221
+ "& .cover:hover + .start svg, & .start:hover svg": { fill: "white" },
222
+ "&.started .cover, &.started .start": { display: "none" },
223
+ "& .terminal-watermark": { zIndex: 99999 }
224
+ }), o = e.div({
225
+ // Xterm base styles
226
+ "& .xterm": {
227
+ fontFeatureSettings: "'liga' 0",
228
+ position: "relative",
229
+ userSelect: "none",
230
+ MsUserSelect: "none",
231
+ WebkitUserSelect: "none",
232
+ cursor: "text",
233
+ "&.focus, &:focus": { outline: "none" },
234
+ "&.enable-mouse-events": { cursor: "default" },
235
+ "&.xterm-cursor-pointer": { cursor: "pointer" },
236
+ "&.column-select.focus": { cursor: "crosshair" }
237
+ },
238
+ "& .xterm .xterm-helpers": { position: "absolute", top: 0, zIndex: 5 },
239
+ "& .xterm .xterm-helper-textarea": {
240
+ position: "absolute",
241
+ opacity: 0,
242
+ left: "-9999em",
243
+ top: 0,
244
+ width: 0,
245
+ height: 0,
246
+ zIndex: -5,
247
+ whiteSpace: "nowrap",
248
+ overflow: "hidden",
249
+ resize: "none"
250
+ },
251
+ "& .xterm .composition-view": {
252
+ background: "#000",
253
+ color: "#fff",
254
+ display: "none",
255
+ position: "absolute",
256
+ whiteSpace: "nowrap",
257
+ zIndex: 1,
258
+ "&.active": { display: "block" }
259
+ },
260
+ "& .xterm .xterm-viewport": {
261
+ backgroundColor: "#000",
262
+ overflowY: "scroll",
263
+ cursor: "default",
264
+ position: "absolute",
265
+ right: 0,
266
+ left: 0,
267
+ top: 0,
268
+ bottom: 0
269
+ },
270
+ "& .xterm .xterm-screen": {
271
+ position: "relative",
272
+ "& canvas": { position: "absolute", left: 0, top: 0 }
273
+ },
274
+ "& .xterm .xterm-scroll-area": { visibility: "hidden" },
275
+ "& .xterm-char-measure-element": {
276
+ display: "inline-block",
277
+ visibility: "hidden",
278
+ position: "absolute",
279
+ top: 0,
280
+ left: "-9999em",
281
+ lineHeight: "normal"
282
+ },
283
+ "& .xterm .xterm-accessibility, & .xterm .xterm-message": {
284
+ position: "absolute",
285
+ left: 0,
286
+ top: 0,
287
+ bottom: 0,
288
+ right: 0,
289
+ zIndex: 10,
290
+ color: "transparent"
291
+ },
292
+ "& .xterm .live-region": { position: "absolute", left: "-9999px", width: 1, height: 1, overflow: "hidden" },
293
+ "& .xterm-dim": { opacity: 0.5 },
294
+ "& .xterm-underline": { textDecoration: "underline" }
295
+ });
296
+ export {
297
+ t as PlayerRoot,
298
+ o as TerminalRoot
299
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcblock/terminal",
3
- "version": "3.1.8",
3
+ "version": "3.1.9",
4
4
  "description": "A react wrapper for xterm allowing you to easily render a terminal in the browser",
5
5
  "keywords": [
6
6
  "react",
@@ -40,10 +40,10 @@
40
40
  "peerDependencies": {
41
41
  "react": "^19.0.0"
42
42
  },
43
- "gitHead": "bb291c7f0f1afa39ca3dc07471c63b118a377cbe",
43
+ "gitHead": "8f16cf31161be5de93a62c7a8128dc040a0a7559",
44
44
  "dependencies": {
45
- "@arcblock/react-hooks": "3.1.8",
46
- "@arcblock/ux": "3.1.8",
45
+ "@arcblock/react-hooks": "3.1.9",
46
+ "@arcblock/ux": "3.1.9",
47
47
  "@emotion/react": "^11.14.0",
48
48
  "@emotion/styled": "^11.14.0",
49
49
  "ahooks": "^3.8.5",
package/src/Player.jsx CHANGED
@@ -1,14 +1,13 @@
1
1
  /* eslint-disable react/no-unused-prop-types */
2
2
  import { useReducer, useState, useRef, useEffect } from 'react';
3
3
  import PropTypes from 'prop-types';
4
- import useInterval from '@arcblock/react-hooks/lib/useInterval';
5
- import { useSize } from 'ahooks';
4
+ import { useSize, useInterval } from 'ahooks';
6
5
  import isUndefined from 'lodash/isUndefined';
7
6
  import noop from 'lodash/noop';
8
7
 
9
8
  import Terminal from './Terminal';
10
9
 
11
- import './player.css';
10
+ import { PlayerRoot } from './styles';
12
11
 
13
12
  import {
14
13
  formatFrames,
@@ -21,6 +20,8 @@ import {
21
20
  defaultState,
22
21
  } from './util';
23
22
 
23
+ export const PLAYER_FRAME_DELAY = 8;
24
+
24
25
  export default function Player({ ...rawProps }) {
25
26
  const props = Object.assign({}, rawProps);
26
27
  if (isUndefined(props.onComplete)) {
@@ -55,7 +56,7 @@ export default function Player({ ...rawProps }) {
55
56
  letterSpacing: options.letterSpacing,
56
57
  allowTransparency: true,
57
58
  scrollback: 0,
58
- // theme: options.theme,
59
+ theme: options.theme || {},
59
60
  };
60
61
 
61
62
  const stateReducer = (state, action) => {
@@ -66,35 +67,15 @@ export default function Player({ ...rawProps }) {
66
67
  case 'start':
67
68
  return { ...state, isStarted: true, lastTickTime: Date.now() };
68
69
  case 'play':
69
- return {
70
- ...state,
71
- isPlaying: true,
72
- lastTickTime: Date.now(),
73
- ...action.payload,
74
- };
70
+ return { ...state, isPlaying: true, lastTickTime: Date.now(), ...action.payload };
75
71
  case 'pause':
76
72
  return { ...state, isPlaying: false, ...action.payload };
77
73
  case 'tickStart':
78
- return {
79
- ...state,
80
- isRendering: true,
81
- lastTickTime: Date.now(),
82
- ...action.payload,
83
- };
74
+ return { ...state, isRendering: true, lastTickTime: Date.now(), ...action.payload };
84
75
  case 'tickEnd':
85
- return {
86
- ...state,
87
- isRendering: false,
88
- lastTickTime: Date.now(),
89
- ...action.payload,
90
- };
76
+ return { ...state, isRendering: false, lastTickTime: Date.now(), ...action.payload };
91
77
  case 'reset':
92
- return {
93
- ...state,
94
- currentFrame: 0,
95
- currentTime: 0,
96
- ...action.payload,
97
- };
78
+ return { ...state, currentFrame: 0, currentTime: 0, ...action.payload };
98
79
  default:
99
80
  return { ...state, lastTickTime: Date.now(), ...action.payload };
100
81
  }
@@ -141,7 +122,7 @@ export default function Player({ ...rawProps }) {
141
122
  // Render a frame
142
123
  const renderFrame = (frameIndex, done) => {
143
124
  const frame = frames[frameIndex];
144
- if (frame.content) {
125
+ if (frame && frame.content) {
145
126
  if (state.requireReset) {
146
127
  terminal.current.reset();
147
128
  }
@@ -275,7 +256,11 @@ export default function Player({ ...rawProps }) {
275
256
  }
276
257
 
277
258
  // Check if current time belongs to the next frame's duration
278
- if (isFrameAt(newState.currentTime, state.currentFrame + 1)) {
259
+ if (
260
+ newState?.currentTime != null &&
261
+ state?.currentFrame != null &&
262
+ isFrameAt(newState.currentTime, state.currentFrame + 1)
263
+ ) {
279
264
  newState.currentFrame = state.currentFrame + 1;
280
265
  } else {
281
266
  newState.currentFrame = findFrameAt(frames, newState.currentTime);
@@ -291,7 +276,7 @@ export default function Player({ ...rawProps }) {
291
276
  return emitEvent('onTick');
292
277
  });
293
278
  },
294
- state.isPlaying ? 8 : null
279
+ state.isPlaying ? PLAYER_FRAME_DELAY : null
295
280
  );
296
281
 
297
282
  // If controls are enabled, we need to disable frameBox
@@ -300,9 +285,9 @@ export default function Player({ ...rawProps }) {
300
285
  options.frameBox.type = null;
301
286
  options.frameBox.style = {};
302
287
 
303
- if (options.theme.background === 'transparent') {
288
+ if (options.theme?.background === 'transparent') {
304
289
  options.frameBox.style.background = 'black';
305
- } else {
290
+ } else if (options.theme?.background) {
306
291
  options.frameBox.style.background = options.theme.background;
307
292
  }
308
293
 
@@ -311,7 +296,7 @@ export default function Player({ ...rawProps }) {
311
296
  }
312
297
 
313
298
  return (
314
- <div className={getPlayerClass(options, state)} ref={container}>
299
+ <PlayerRoot className={getPlayerClass(options, state)} ref={container}>
315
300
  <div className="cover" onClick={onStart} />
316
301
  <div className="start" onClick={onStart}>
317
302
  <svg style={{ enableBackground: 'new 0 0 30 30' }} viewBox="0 0 30 30">
@@ -360,13 +345,21 @@ export default function Player({ ...rawProps }) {
360
345
  </div>
361
346
  </div>
362
347
  </div>
363
- </div>
348
+ </PlayerRoot>
364
349
  );
365
350
  }
366
351
 
367
352
  Player.propTypes = {
368
353
  frames: PropTypes.array.isRequired,
369
- options: PropTypes.object.isRequired,
354
+ options: PropTypes.shape({
355
+ autoplay: PropTypes.bool,
356
+ repeat: PropTypes.bool,
357
+ controls: PropTypes.bool,
358
+ frameBox: PropTypes.object,
359
+ theme: PropTypes.object,
360
+ cols: PropTypes.number,
361
+ rows: PropTypes.number,
362
+ }).isRequired,
370
363
  onComplete: PropTypes.func,
371
364
  onStart: PropTypes.func,
372
365
  onStop: PropTypes.func,
@@ -1,4 +1,8 @@
1
1
  export { default as Player } from './demo/player';
2
+ export { default as AutoPlay } from './demo/autoplay';
3
+ export { default as Loop } from './demo/loop';
4
+ export { default as AutoPlayLoop } from './demo/autoplay-loop';
5
+ export { default as RecordingGuide } from './demo/recording-guide';
2
6
 
3
7
  export default {
4
8
  title: 'Data Display/Terminal/Player',
package/src/Terminal.jsx CHANGED
@@ -7,8 +7,7 @@ import { WebLinksAddon } from 'xterm-addon-web-links';
7
7
  import { FitAddon } from 'xterm-addon-fit';
8
8
  import debounce from 'lodash/debounce';
9
9
  import noop from 'lodash/noop';
10
-
11
- import './xterm.css';
10
+ import { TerminalRoot } from './styles';
12
11
 
13
12
  export default class Terminal extends React.Component {
14
13
  xterm = null;
@@ -129,8 +128,13 @@ export default class Terminal extends React.Component {
129
128
  const { className = '', style = {} } = this.props;
130
129
  const combinedClassName = ['react-xterm', className].filter(Boolean).join(' ');
131
130
  return (
132
- // eslint-disable-next-line no-return-assign
133
- <div ref={(ref) => (this.container = ref)} className={combinedClassName} style={style} />
131
+ <TerminalRoot
132
+ ref={(ref) => {
133
+ this.container = ref;
134
+ }}
135
+ className={combinedClassName}
136
+ style={style}
137
+ />
134
138
  );
135
139
  }
136
140
  }