@arcblock/terminal 2.1.61

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/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2018-2022 ArcBlock
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,19 @@
1
+ ![@arcblock/terminal](https://www.arcblock.io/.netlify/functions/badge/?text=terminal)
2
+
3
+ > Terminal Player is a react wrapper for `xterm` allowing you to easily render a terminal in the browser.
4
+
5
+ ## Usage
6
+
7
+ ```shell
8
+ yarn add @arcblock/terminal
9
+ ```
10
+
11
+ Then:
12
+
13
+ ```javascript
14
+ import Terminal from '@arcblock/terminal';
15
+
16
+ export default function Demo() {
17
+ return <Player frames={records} options={config} />;
18
+ }
19
+ ```
package/lib/Player.js ADDED
@@ -0,0 +1,464 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = Player;
7
+
8
+ var _react = require("react");
9
+
10
+ var _propTypes = _interopRequireDefault(require("prop-types"));
11
+
12
+ var _useInterval = _interopRequireDefault(require("@arcblock/react-hooks/lib/useInterval"));
13
+
14
+ var _useWindowSize = _interopRequireDefault(require("react-use/lib/useWindowSize"));
15
+
16
+ var _terminal = _interopRequireDefault(require("./terminal"));
17
+
18
+ require("./player.css");
19
+
20
+ var _util = require("./util");
21
+
22
+ var _jsxRuntime = require("react/jsx-runtime");
23
+
24
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
+
26
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
27
+
28
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
29
+
30
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
31
+
32
+ function Player(props) {
33
+ const options = Object.assign({}, _util.defaultOptions, props.options);
34
+ const {
35
+ frames,
36
+ totalDuration
37
+ } = (0, _util.formatFrames)(props.frames, options);
38
+ const terminalOptions = {
39
+ cols: options.cols,
40
+ rows: options.rows,
41
+ cursorStyle: options.cursorStyle,
42
+ fontFamily: options.fontFamily,
43
+ fontSize: options.fontSize,
44
+ lineHeight: options.lineHeight,
45
+ letterSpacing: options.letterSpacing,
46
+ allowTransparency: true,
47
+ scrollback: 0 // theme: options.theme,
48
+
49
+ };
50
+
51
+ const stateReducer = (state, action) => {
52
+ // console.log(`dispatch.${action.type}`, action.payload);
53
+ switch (action.type) {
54
+ case 'jump':
55
+ return _objectSpread(_objectSpread({}, state), {}, {
56
+ isPlaying: false
57
+ }, action.payload);
58
+
59
+ case 'start':
60
+ return _objectSpread(_objectSpread({}, state), {}, {
61
+ isStarted: true,
62
+ lastTickTime: Date.now()
63
+ });
64
+
65
+ case 'play':
66
+ return _objectSpread(_objectSpread({}, state), {}, {
67
+ isPlaying: true,
68
+ lastTickTime: Date.now()
69
+ }, action.payload);
70
+
71
+ case 'pause':
72
+ return _objectSpread(_objectSpread({}, state), {}, {
73
+ isPlaying: false
74
+ }, action.payload);
75
+
76
+ case 'tickStart':
77
+ return _objectSpread(_objectSpread({}, state), {}, {
78
+ isRendering: true,
79
+ lastTickTime: Date.now()
80
+ }, action.payload);
81
+
82
+ case 'tickEnd':
83
+ return _objectSpread(_objectSpread({}, state), {}, {
84
+ isRendering: false,
85
+ lastTickTime: Date.now()
86
+ }, action.payload);
87
+
88
+ case 'reset':
89
+ return _objectSpread(_objectSpread({}, state), {}, {
90
+ currentFrame: 0,
91
+ currentTime: 0
92
+ }, action.payload);
93
+
94
+ default:
95
+ return _objectSpread(_objectSpread({}, state), {}, {
96
+ lastTickTime: Date.now()
97
+ }, action.payload);
98
+ }
99
+ };
100
+
101
+ const terminal = (0, _react.useRef)(null);
102
+ const progress = (0, _react.useRef)(null);
103
+ const container = (0, _react.useRef)(null);
104
+ const [maxWidth, setMaxWidth] = (0, _react.useState)(0);
105
+ const {
106
+ width
107
+ } = (0, _useWindowSize.default)();
108
+ const [state, dispatch] = (0, _react.useReducer)(stateReducer, _util.defaultState);
109
+ (0, _react.useEffect)(() => {
110
+ if (!terminal.current) {
111
+ return;
112
+ }
113
+
114
+ try {
115
+ const COLUMN_WIDTH = 972 / 121;
116
+ const child = container.current.getBoundingClientRect();
117
+ let containerWidth = child.x < 0 ? child.width + child.x : child.width;
118
+
119
+ if (container.current.parentNode) {
120
+ const parent = container.current.parentNode.getBoundingClientRect();
121
+
122
+ if (child.width > parent.width) {
123
+ containerWidth = parent.width;
124
+ }
125
+ }
126
+
127
+ if (options.controls) {
128
+ containerWidth -= 12;
129
+ }
130
+
131
+ const colContainer = Math.ceil(containerWidth / COLUMN_WIDTH);
132
+ const cols = Math.min(Math.max(colContainer, 40), options.cols);
133
+ terminal.current.resize(cols, options.rows);
134
+ } catch (err) {// Do nothing
135
+ } // eslint-disable-next-line react-hooks/exhaustive-deps
136
+
137
+ }, [width, maxWidth]); // console.log('main.render', state, { totalFrame: frames.length, totalDuration });
138
+ // Render a frame
139
+
140
+ const renderFrame = (frameIndex, done) => {
141
+ const frame = frames[frameIndex];
142
+
143
+ if (frame.content) {
144
+ if (state.requireReset) {
145
+ terminal.current.reset();
146
+ }
147
+
148
+ terminal.current.write(frame.content, () => {
149
+ if (typeof done === 'function') {
150
+ done();
151
+ }
152
+ });
153
+ }
154
+ }; // Emit a event
155
+
156
+
157
+ const emitEvent = name => {
158
+ if (typeof props[name] === 'function') {
159
+ props[name]({
160
+ state,
161
+ frames,
162
+ options
163
+ });
164
+ }
165
+ }; // Render thumbnailTime
166
+
167
+
168
+ (0, _react.useEffect)(() => {
169
+ if (!terminal.current) {
170
+ return;
171
+ }
172
+
173
+ if (container.current) {
174
+ try {
175
+ setMaxWidth(container.current.getBoundingClientRect().width);
176
+ } catch (e) {// Do nothing
177
+ }
178
+ }
179
+
180
+ if (options.autoplay) {
181
+ onStart();
182
+ } else {
183
+ doJump(Math.min(Math.abs(options.thumbnailTime), totalDuration));
184
+ } // eslint-disable-next-line react-hooks/exhaustive-deps
185
+
186
+ }, []); // Tick intervals
187
+
188
+ (0, _useInterval.default)(async () => {
189
+ if (state.isRendering) {
190
+ return false;
191
+ }
192
+
193
+ const tickDelay = Date.now() - state.lastTickTime;
194
+ const newState = {};
195
+
196
+ if (state.currentTime < totalDuration) {
197
+ newState.currentTime = state.currentTime + tickDelay;
198
+ }
199
+
200
+ if (state.currentTime > totalDuration) {
201
+ newState.currentTime = totalDuration;
202
+ }
203
+
204
+ const alreadyRendered = (0, _util.isFrameAt)(frames, newState.currentTime, state.currentFrame);
205
+
206
+ if (state.currentFrame !== -1 && alreadyRendered) {
207
+ return dispatch({
208
+ type: 'tick',
209
+ payload: newState
210
+ });
211
+ } // Reached the end
212
+
213
+
214
+ if (state.currentFrame === frames.length - 1) {
215
+ emitEvent('onComplete');
216
+
217
+ if (options.repeat) {
218
+ // console.log('tick.restart', newState, state);
219
+ return dispatch({
220
+ type: 'reset',
221
+ payload: newState
222
+ });
223
+ } // console.log('tick.end', newState, state);
224
+
225
+
226
+ newState.currentTime = 0;
227
+ newState.currentFrame = 0;
228
+ newState.requireReset = true;
229
+ newState.isStarted = false;
230
+ return dispatch({
231
+ type: 'pause',
232
+ payload: newState
233
+ });
234
+ } // Check if current time belongs to the next frame's duration
235
+
236
+
237
+ if ((0, _util.isFrameAt)(newState.currentTime, state.currentFrame + 1)) {
238
+ newState.currentFrame = state.currentFrame + 1;
239
+ } else {
240
+ newState.currentFrame = (0, _util.findFrameAt)(frames, newState.currentTime);
241
+ } // console.log('tick.tick', newState, state);
242
+
243
+
244
+ dispatch({
245
+ type: 'tickStart',
246
+ payload: newState
247
+ });
248
+ return renderFrame(newState.currentFrame, () => {
249
+ if (state.requireReset) {
250
+ newState.requireReset = false;
251
+ }
252
+
253
+ dispatch({
254
+ type: 'tickEnd',
255
+ payload: newState
256
+ });
257
+ return emitEvent('onTick');
258
+ });
259
+ }, state.isPlaying ? 8 : null); // If controls are enabled, we need to disable frameBox
260
+
261
+ if (options.controls) {
262
+ options.frameBox.title = null;
263
+ options.frameBox.type = null;
264
+ options.frameBox.style = {};
265
+
266
+ if (options.theme.background === 'transparent') {
267
+ options.frameBox.style.background = 'black';
268
+ } else {
269
+ options.frameBox.style.background = options.theme.background;
270
+ }
271
+
272
+ options.frameBox.style.padding = '10px';
273
+ options.frameBox.style.paddingBottom = '40px';
274
+ }
275
+
276
+ const doJump = time => {
277
+ terminal.current.reset();
278
+ const toFrameIndex = (0, _util.findFrameAt)(frames, time);
279
+
280
+ for (let i = 0; i < toFrameIndex; i++) {
281
+ renderFrame(i);
282
+ }
283
+ };
284
+
285
+ const onJump = e => {
286
+ if (!progress.current || !terminal.current || !state.isStarted) {
287
+ return false;
288
+ }
289
+
290
+ const length = progress.current.getBoundingClientRect().width;
291
+ const position = e.nativeEvent.offsetX; // console.log('onJump', { length, position, e });
292
+
293
+ const currentTime = Math.floor(totalDuration * position / length);
294
+ dispatch({
295
+ type: 'jump',
296
+ payload: {
297
+ currentTime
298
+ }
299
+ });
300
+ doJump(currentTime);
301
+ emitEvent('onJump');
302
+ return false;
303
+ };
304
+
305
+ const onStart = () => {
306
+ if (state.isStarted === false) {
307
+ dispatch({
308
+ type: 'start'
309
+ });
310
+ terminal.current.reset();
311
+ }
312
+
313
+ dispatch({
314
+ type: 'play'
315
+ });
316
+ emitEvent('onStart');
317
+ return false;
318
+ };
319
+
320
+ const onPause = () => {
321
+ dispatch({
322
+ type: 'pause'
323
+ });
324
+ emitEvent('onPause');
325
+ return false;
326
+ };
327
+
328
+ const onPlay = async () => {
329
+ if (state.currentFrame === frames.length - 1 && state.currentTime === totalDuration) {
330
+ dispatch({
331
+ type: 'reset'
332
+ });
333
+ terminal.current.reset();
334
+ }
335
+
336
+ emitEvent('onPlay');
337
+ return onStart();
338
+ };
339
+
340
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
341
+ className: (0, _util.getPlayerClass)(options, state),
342
+ ref: container,
343
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
344
+ className: "cover",
345
+ onClick: onStart
346
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
347
+ className: "start",
348
+ onClick: onStart,
349
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("svg", {
350
+ style: {
351
+ enableBackground: 'new 0 0 30 30'
352
+ },
353
+ viewBox: "0 0 30 30",
354
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("polygon", {
355
+ points: "6.583,3.186 5,4.004 5,15 26,15 26.483,14.128 "
356
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("polygon", {
357
+ points: "6.583,26.814 5,25.996 5,15 26,15 26.483,15.872 "
358
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("circle", {
359
+ cx: "26",
360
+ cy: "15",
361
+ r: "1"
362
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("circle", {
363
+ cx: "6",
364
+ cy: "4",
365
+ r: "1"
366
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("circle", {
367
+ cx: "6",
368
+ cy: "26",
369
+ r: "1"
370
+ })]
371
+ })
372
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
373
+ className: "terminal",
374
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
375
+ className: (0, _util.getFrameClass)(options),
376
+ style: options.frameBox.style || {},
377
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
378
+ className: "terminal-titlebar",
379
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
380
+ className: "buttons",
381
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
382
+ className: "close-button"
383
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
384
+ className: "minimize-button"
385
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
386
+ className: "maximize-button"
387
+ })]
388
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
389
+ className: "title",
390
+ children: options.frameBox.title || ''
391
+ })]
392
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
393
+ className: "terminal-body",
394
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_terminal.default, {
395
+ ref: terminal,
396
+ options: terminalOptions
397
+ })
398
+ })]
399
+ })
400
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
401
+ className: "controller",
402
+ children: [state.isPlaying && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
403
+ className: "pause",
404
+ onClick: onPause,
405
+ title: "Pause",
406
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
407
+ className: "icon"
408
+ })
409
+ }), !state.isPlaying && state.isStarted && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
410
+ className: "play",
411
+ onClick: onPlay,
412
+ title: "Play",
413
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
414
+ className: "icon"
415
+ })
416
+ }), !state.isPlaying && !state.isStarted && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
417
+ className: "play",
418
+ onClick: onStart,
419
+ title: "Start",
420
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
421
+ className: "icon"
422
+ })
423
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
424
+ className: "timer",
425
+ children: (0, _util.formatTime)(state.currentTime)
426
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
427
+ className: "progressbar-wrapper",
428
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
429
+ className: "progressbar",
430
+ ref: progress,
431
+ onClick: onJump,
432
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
433
+ className: "progress",
434
+ style: {
435
+ width: "".concat(state.currentTime / totalDuration * 100, "%")
436
+ }
437
+ })
438
+ })
439
+ })]
440
+ })]
441
+ });
442
+ }
443
+
444
+ Player.propTypes = {
445
+ frames: _propTypes.default.array.isRequired,
446
+ options: _propTypes.default.object.isRequired,
447
+ onComplete: _propTypes.default.func,
448
+ onStart: _propTypes.default.func,
449
+ onStop: _propTypes.default.func,
450
+ onPause: _propTypes.default.func,
451
+ onTick: _propTypes.default.func,
452
+ onJump: _propTypes.default.func
453
+ };
454
+
455
+ const noop = () => {};
456
+
457
+ Player.defaultProps = {
458
+ onComplete: noop,
459
+ onStart: noop,
460
+ onStop: noop,
461
+ onPause: noop,
462
+ onTick: noop,
463
+ onJump: noop
464
+ };
package/lib/index.js ADDED
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "default", {
7
+ enumerable: true,
8
+ get: function get() {
9
+ return _Player.default;
10
+ }
11
+ });
12
+
13
+ var _Player = _interopRequireDefault(require("./Player"));
14
+
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }