UNPKG

react-terminal-plus

Version:

A improved version of `react-terminal` - react-terminal-plus

2 lines (1 loc) 19 kB
import*as e from"react";import{CancelablePromise as t}from"cancelable-promise";!function(e,t){void 0===t&&(t={});var n=t.insertAt;if(e&&"undefined"!=typeof document){var r=document.head||document.getElementsByTagName("head")[0],o=document.createElement("style");o.type="text/css","top"===n&&r.firstChild?r.insertBefore(o,r.firstChild):r.appendChild(o),o.styleSheet?o.styleSheet.cssText=e:o.appendChild(document.createTextNode(e))}}('@import url("https://fonts.googleapis.com/css?family=Source+Code+Pro&display=swap");\n#index-module_terminalContainer__i6yCT {\n --control-default-bg-color: #ccc;\n --control-close-bg-color: #fc5b57;\n --control-minimize-bg-color: #e5bf3c;\n --control-maximize-bg-color: #57c038;\n}\n\n.index-module_controls__-Pz-7 {\n text-align: left;\n height: 26px;\n position: relative;\n top: 4px;\n margin-left: 4px;\n}\n.index-module_controls__-Pz-7 .index-module_consoleCtrl__wASVf {\n display: inline-block;\n width: 13px;\n height: 13px;\n margin: 0 3px;\n border-radius: 50%;\n background: var(--control-default-bg-color);\n}\n.index-module_controls__-Pz-7 .index-module_close__Etu85 {\n background: var(--control-close-bg-color);\n}\n.index-module_controls__-Pz-7 .index-module_minimize__bT0-I {\n background: var(--control-minimize-bg-color);\n}\n.index-module_controls__-Pz-7 .index-module_maximize__mPPF7 {\n background: var(--control-maximize-bg-color);\n}\n\n.index-module_editor__CBDCJ {\n text-align: left;\n height: 100%;\n padding: 10px 15px;\n overflow-wrap: break-word;\n overflow-y: scroll;\n outline: none;\n font-family: "Source Code Pro", monospace;\n font-size: 18px;\n line-height: 22px;\n caret-color: transparent;\n --scroll-bar-thumb-color: transparent;\n --scroll-bar-track-color: transparent;\n --scroll-bar-width: 10px;\n scrollbar-color: var(--scroll-bar-thumb-color) var(--scroll-bar-track-color);\n scrollbar-width: var(--scroll-bar-width);\n}\n.index-module_editor--rounded__-VOd4 {\n border-radius: 5px;\n}\n.index-module_editor__CBDCJ::selection {\n background: transparent;\n}\n.index-module_editor__CBDCJ:focus, .index-module_editor__CBDCJ:hover {\n --scroll-bar-thumb-color: rgb(211 211 211 / 40%);\n}\n.index-module_editor__CBDCJ::-webkit-scrollbar {\n width: var(--scroll-bar-width);\n}\n.index-module_editor__CBDCJ::-webkit-scrollbar-track {\n background-color: var(--scroll-bar-track-color);\n}\n.index-module_editor__CBDCJ::-webkit-scrollbar-thumb {\n background-color: var(--scroll-bar-thumb-color);\n}\n.index-module_editor__CBDCJ .index-module_lineText__avQ48 {\n display: inline;\n position: relative;\n top: -1px;\n margin-left: 8px;\n}\n.index-module_editor__CBDCJ .index-module_preWhiteSpace__v4IYf {\n white-space: pre-wrap;\n}\n.index-module_editor__CBDCJ .index-module_preWhiteSpace__v4IYf:focus-visible {\n outline: none;\n}\n.index-module_editor__CBDCJ .index-module_charUnderCaret__-M0qT {\n z-index: 10;\n position: relative;\n}\n.index-module_editor__CBDCJ .index-module_caret__YobLn {\n position: relative;\n}\n.index-module_editor__CBDCJ .index-module_caret__YobLn .index-module_caretAfter__SMMlh {\n content: "";\n position: absolute;\n top: 2px;\n width: 10px;\n height: 22px;\n z-index: 10;\n}\n@-moz-keyframes index-module_blink__l83VF {\n 0% {\n opacity: 0;\n -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";\n filter: alpha(opacity=0);\n }\n 100% {\n opacity: 1;\n -ms-filter: none;\n filter: none;\n }\n}\n@-webkit-keyframes index-module_blink__l83VF {\n 0% {\n opacity: 0;\n -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";\n filter: alpha(opacity=0);\n }\n 100% {\n opacity: 1;\n -ms-filter: none;\n filter: none;\n }\n}\n@-o-keyframes index-module_blink__l83VF {\n 0% {\n opacity: 0;\n -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";\n filter: alpha(opacity=0);\n }\n 100% {\n opacity: 1;\n -ms-filter: none;\n filter: none;\n }\n}\n@keyframes index-module_blink__l83VF {\n 0% {\n opacity: 0;\n -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";\n filter: alpha(opacity=0);\n }\n 100% {\n opacity: 1;\n -ms-filter: none;\n filter: none;\n }\n}\n.index-module_editor__CBDCJ a {\n color: #1a87b5;\n}\n\n.index-module_editorWithTopBar__opXWp {\n height: calc(100% - 46px);\n}\n\n#index-module_terminalContainer__i6yCT {\n height: 100%;\n}\n\n.index-module_terminal__EWHbJ {\n height: 100%;\n width: 100%;\n margin: auto;\n}\n.index-module_terminal--rounded__DZuxh {\n border-radius: 5px;\n}');const n={terminalContainer:"index-module_terminalContainer__i6yCT",controls:"index-module_controls__-Pz-7",consoleCtrl:"index-module_consoleCtrl__wASVf",close:"index-module_close__Etu85",minimize:"index-module_minimize__bT0-I",maximize:"index-module_maximize__mPPF7",editor:"index-module_editor__CBDCJ","editor--rounded":"index-module_editor--rounded__-VOd4",lineText:"index-module_lineText__avQ48",preWhiteSpace:"index-module_preWhiteSpace__v4IYf",charUnderCaret:"index-module_charUnderCaret__-M0qT",caret:"index-module_caret__YobLn",caretAfter:"index-module_caretAfter__SMMlh",editorWithTopBar:"index-module_editorWithTopBar__opXWp",terminal:"index-module_terminal__EWHbJ","terminal--rounded":"index-module_terminal--rounded__DZuxh",blink:"index-module_blink__l83VF"},r=e.createContext(null),o=t=>{const{children:o}=t;return e.createElement(r.Provider,{value:n},o)};const a={dark:{themeBGColor:"rgb(2, 40, 51)",themeToolbarColor:"rgb(19, 21, 25)",themeColor:"rgb(131, 148, 150)",themePromptColor:"rgb(169, 23, 168)"},light:{themeBGColor:"#fdf6e4",themeToolbarColor:"#d8d8d8",themeColor:"#333333",themePromptColor:"#a917a8"},dracula:{themeBGColor:"#272B36",themeToolbarColor:"#DBDBDB",themeColor:"#FFFEFC",themePromptColor:"#a917a8"},"material-dark":{themeBGColor:"#151515",themeToolbarColor:"#424242",themeColor:"#fff",themePromptColor:"#42A5F5"},"material-light":{themeBGColor:"#fafafa",themeToolbarColor:"#424242",themeColor:"#151515",themePromptColor:"#42A5F5"},"material-ocean":{themeBGColor:"#263238",themeToolbarColor:"#37474F",themeColor:"#fff",themePromptColor:"#C3D82C"},matrix:{themeBGColor:"#0D0208",themeToolbarColor:"#0D0208",themeColor:"#00FF41",themePromptColor:"#008F11"}},i=e.createContext(null),l=t=>{const{children:n}=t,r=Object.assign(Object.assign({},a),n.props.themes||{}),o=r[n.props.theme]||r.light;return e.createElement(i.Provider,{value:o},n)},s=(t,n,r)=>{const o=e=>{t.current&&!t.current.contains(e.target)?r(!1):r(!0)};e.useEffect((()=>(document.addEventListener("mousedown",o),()=>{document.removeEventListener("mousedown",o)})))};function c(t){const n=e.useContext(r),{controlButtonLabels:o}=t,{showControlButtons:a}=t,i=a?o.map((t=>e.createElement("div",{key:t,className:`${n.consoleCtrl} ${n[t]}`}))):null;return e.createElement("div",{className:n.controls},i)}const d=["clear","cls"],u=e=>d.includes(e);class m{static splitStringAtIndex(e,t){return e?[e.substring(0,t),e.substring(t)]:["",""]}static splitStringAtNextSpace(e,t){if(!e)return["",""];let n=e.indexOf(" ",t);for(-1===n&&(n=e.length);n<e.length&&" "===e[n];)n++;return[e.substring(0,n),e.substring(n)]}static splitStringAtPreviousSpace(e,t){if(!e)return["",""];let n=e.substring(0,t).trimEnd().lastIndexOf(" ");return-1===n||0===n?n=0:n+=1,[e.substring(0,n),e.substring(n)]}}const p="react-terminal-plus-commandHistory",f=()=>{var e;try{const t=null!==(e=localStorage.getItem(p))&&void 0!==e?e:"[]";return JSON.parse(t)}catch(e){return console.error(e),[]}},C=e=>{let t=f();t.push(e);try{JSON.stringify(t).length>52e5&&(t=t.slice(50)),localStorage.setItem(p,JSON.stringify(t))}catch(n){console.error(n),t=[e],localStorage.setItem(p,JSON.stringify(t))}},_=e.createContext(null);function x(e,t){switch(e.currentLineStatus){case"processing":switch(t.type){case"CANCEL":return Object.assign(Object.assign({},e),{bufferedContent:t.cancelNode,editorInput:"",currentLineStatus:"idle",caretPosition:0,textBeforeCaret:"",textAfterCaret:""});case"SUBMIT_SUCCESS":return Object.assign(Object.assign({},e),{bufferedContent:t.successNode,currentLineStatus:"success",editorInput:"",caretPosition:0,textBeforeCaret:"",textAfterCaret:""});default:return e}case"success":case"error":case"idle":switch(t.type){case"CLEAR":return Object.assign(Object.assign({},e),{bufferedContent:null});case"CANCEL":return Object.assign(Object.assign({},e),{bufferedContent:t.cancelNode,editorInput:"",currentLineStatus:"idle",caretPosition:0,textBeforeCaret:"",textAfterCaret:""});case"SUBMIT":{const{command:n}=t,r=[...e.commandsHistory];return n&&n!==r[r.length-1]&&(r.push(n),C(n)),u(n)?Object.assign(Object.assign({},e),{commandsHistory:r,bufferedContent:null,editorInput:"",currentLineStatus:"idle",caretPosition:0,textBeforeCaret:"",textAfterCaret:""}):Object.assign(Object.assign({},e),{commandsHistory:r,bufferedContent:t.loaderNode,currentLineStatus:"processing",editorInput:"",caretPosition:0,textBeforeCaret:"",textAfterCaret:""})}case"TYPE":{const[n,r]=g(e),o=n+t.text+r,a=e.caretPosition+1,[i,l]=h(o,a);return Object.assign(Object.assign({},e),{caretPosition:a,editorInput:o,textAfterCaret:l,textBeforeCaret:i})}case"DELETE":{const[t,n]=g(e),r=t.slice(0,-1)+n,o=e.caretPosition-1,[a,i]=h(r,o);return Object.assign(Object.assign({},e),{editorInput:r,caretPosition:o,textAfterCaret:i,textBeforeCaret:a})}case"COPY":return e;case"PASTE":{const[n,r]=g(e),o=n+t.text+r,a=e.caretPosition+t.text.length,[i,l]=h(o,a);return Object.assign(Object.assign({},e),{editorInput:o,caretPosition:a,textAfterCaret:l,textBeforeCaret:i})}case"ARROW_UP":{const n=t.previousCommand,r=t.previousCommand.length,[o,a]=h(n,r);return Object.assign(Object.assign({},e),{editorInput:n,caretPosition:r,textAfterCaret:a,textBeforeCaret:o})}case"ARROW_DOWN":{const n=t.nextCommand,r=t.nextCommand.length,[o,a]=h(n,r);return Object.assign(Object.assign({},e),{editorInput:n,caretPosition:r,textAfterCaret:a,textBeforeCaret:o})}case"RESET_CARET_POSITION":return Object.assign(Object.assign({},e),{editorInput:"",textBeforeCaret:"",textAfterCaret:"",caretPosition:0});case"ARROW_LEFT":{const t=e.caretPosition-1,[n,r]=h(e.editorInput,t);return Object.assign(Object.assign({},e),{caretPosition:t,textAfterCaret:r,textBeforeCaret:n})}case"ARROW_RIGHT":{const t=e.caretPosition+1,[n,r]=h(e.editorInput,t);return Object.assign(Object.assign({},e),{caretPosition:t,textAfterCaret:r,textBeforeCaret:n})}case"FORWARD_WORD":{const[t,n]=function(e,t){const[n,r]=m.splitStringAtNextSpace(e,t);return[n,r]}(e.editorInput,e.caretPosition);return Object.assign(Object.assign({},e),{caretPosition:t.length,textAfterCaret:n,textBeforeCaret:t})}case"BACKWARD_WORD":{const[t,n]=function(e,t){const[n,r]=m.splitStringAtPreviousSpace(e,t);return[n,r]}(e.editorInput,e.caretPosition);return Object.assign(Object.assign({},e),{caretPosition:t.length,textAfterCaret:n,textBeforeCaret:t})}case"MOVE_CARET_TO_START":return Object.assign(Object.assign({},e),{caretPosition:0,textAfterCaret:e.editorInput,textBeforeCaret:""});case"MOVE_CARET_TO_END":return Object.assign(Object.assign({},e),{caretPosition:e.editorInput.length,textAfterCaret:"",textBeforeCaret:e.editorInput});default:throw new Error(`Unhandled action type: ${JSON.stringify(t)}`)}default:return e}}function g(e){const[t,n]=m.splitStringAtIndex(e.editorInput,e.caretPosition);return[t,n]}function h(e,t){const[n,r]=m.splitStringAtIndex(e,t);return[n,r]}function b(){const t=e.useContext(_);if(void 0===t)throw new Error("useTerminal must be used within a TerminalContextProvider");return t}function y(e,t,n,r){return new(n||(n=Promise))((function(o,a){function i(e){try{s(r.next(e))}catch(e){a(e)}}function l(e){try{s(r.throw(e))}catch(e){a(e)}}function s(e){var t;e.done?o(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(i,l)}s((r=r.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;const E=(n,o,a,l,s,c,d)=>{const m=e.useContext(r),p=e.useContext(i),{store:f}=b(),C=f.textAfterCaret[0],_=f.textAfterCaret.slice(1),x=o&&n,g="processing"!==f.currentLineStatus?e.createElement(e.Fragment,null,e.createElement("span",{style:{color:p.themePromptColor}},a),e.createElement("div",{className:m.lineText},e.createElement("span",{className:m.preWhiteSpace},f.textBeforeCaret),x?e.createElement("span",{className:m.caret},e.createElement("span",{className:m.caretAfter,style:{background:p.themeColor}})):null,e.createElement("span",{className:`${m.preWhiteSpace}`},e.createElement("span",{style:{color:x?p.themeBGColor:p.themeColor},className:m.charUnderCaret},C),_))):e.createElement(e.Fragment,null,e.createElement("div",{className:m.lineText},x?e.createElement("span",{className:m.caret},e.createElement("span",{className:m.caretAfter,style:{background:p.themeColor}})):null));return(({consoleFocused:n,enableInput:o,commands:a,defaultHandler:l,errorMessage:s,prompt:c})=>{const d=e.useContext(r),m=e.useContext(i),{getPreviousCommand:p,getNextCommand:f,store:C,send:_}=b(),x=e.useRef(null),g=e.useCallback((()=>{x.current&&x.current.cancel();let t=e.createElement(e.Fragment,null,C.bufferedContent,e.createElement("span",{style:{color:m.themePromptColor}},c),e.createElement("span",{className:`${d.lineText} ${d.preWhiteSpace}`},C.editorInput),e.createElement("br",null));"processing"===C.currentLineStatus&&(t=e.createElement(e.Fragment,null,C.bufferedContent)),_({type:"CANCEL",cancelNode:t})}),[c,_,C.bufferedContent,C.currentLineStatus,C.editorInput,d.lineText,d.preWhiteSpace,m.themePromptColor]),h=e.useCallback((()=>y(void 0,void 0,void 0,(function*(){const[n,...r]=C.editorInput.trim().split(" "),o=C.editorInput.trim();let i="";const p=e.createElement(e.Fragment,null,C.bufferedContent,e.createElement("span",{style:{color:m.themePromptColor}},c),e.createElement("span",{className:`${d.lineText} ${d.preWhiteSpace}`},C.editorInput),e.createElement("br",null));if(_({type:"SUBMIT",loaderNode:p,command:o}),u(o))return;if(C.editorInput){const e=r.join(" ");if(o&&a[o]){const n=a[o];"function"==typeof n?(x.current=new t((t=>{t(n(e))})),i=yield x.current):i=n}else"function"==typeof l?(x.current=new t((t=>{t(l(n,e))})),i=yield x.current):"function"==typeof s?(x.current=new t((t=>{t(s(n,e))})),i=yield x.current):i=s}const f=e.createElement(e.Fragment,null,C.bufferedContent,e.createElement("span",{style:{color:m.themePromptColor}},c),e.createElement("span",{className:`${d.lineText} ${d.preWhiteSpace}`},C.editorInput),i?e.createElement("span",null,e.createElement("br",null),i):null,e.createElement("br",null));_({type:"SUBMIT_SUCCESS",successNode:f})}))),[_,C.bufferedContent,C.editorInput]),E=e.useCallback((e=>{if(!n)return;if(!o)return;e.preventDefault();const t=e.key;let r=null;if("Enter"===t)"processing"!==C.currentLineStatus&&h();else if("Backspace"===t)C.editorInput&&0!==C.editorInput.length&&_({type:"DELETE"});else if("ArrowUp"===t)r=p(),r&&_({type:"ARROW_UP",previousCommand:r});else if("ArrowDown"===t)r=f(),_(r?{type:"ARROW_DOWN",nextCommand:r}:{type:"RESET_CARET_POSITION"});else if((e.metaKey||e.ctrlKey)&&"ArrowLeft"===t)_({type:"BACKWARD_WORD"});else if((e.metaKey||e.ctrlKey)&&"ArrowRight"==t)_({type:"FORWARD_WORD"});else if("ArrowLeft"===t)C.caretPosition>0&&_({type:"ARROW_LEFT"}),r=C.editorInput;else if("ArrowRight"===t)C.caretPosition<C.editorInput.length&&_({type:"ARROW_RIGHT"}),r=C.editorInput;else if((e.metaKey||e.ctrlKey)&&"l"===t.toLowerCase())_({type:"CLEAR"});else if((e.metaKey||e.ctrlKey)&&"v"===t.toLowerCase())navigator.clipboard.readText().then((e=>{_({type:"PASTE",text:e})}));else if((e.metaKey||e.ctrlKey)&&"c"===t.toLowerCase()){const e=window.getSelection().toString();e?navigator.clipboard.writeText(e).then((()=>{_({type:"COPY"})})):g()}else(e.metaKey||e.ctrlKey)&&"a"==t.toLowerCase()||"Home"===t?_({type:"MOVE_CARET_TO_START"}):(e.metaKey||e.ctrlKey)&&"e"==t.toLowerCase()||"End"===t?_({type:"MOVE_CARET_TO_END"}):t&&1===t.length&&_({type:"TYPE",text:t})}),[g,n,o,f,p,h,_,C.caretPosition,C.currentLineStatus,C.editorInput]);e.useEffect((()=>(document.addEventListener("keydown",E),()=>{document.removeEventListener("keydown",E)})),[E])})({commands:l,errorMessage:s,defaultHandler:d,enableInput:c,prompt:a,consoleFocused:o}),g},O=(t,n)=>{e.useEffect((()=>{n.current&&(n.current.scrollTop=n.current.scrollHeight)}),[t])};function A(t){const n=e.useRef(null),o=e.useContext(r),a=e.useContext(i),{store:l,send:s}=b();O(l.bufferedContent,n);const{enableInput:c,caret:d,consoleFocused:u,prompt:m,commands:p,welcomeMessage:f,errorMessage:C,showControlBar:_,defaultHandler:x,rounded:g}=t,h=g?o["terminal--rounded"]:"",y=E(d,u,m,p,C,c,x);return e.createElement("div",{id:"terminalEditor",tabIndex:0,ref:n,onMouseDown:e=>{n.current&&2===e.button&&(n.current.contentEditable="true",setTimeout((()=>{n.current.contentEditable="false"}),20))},onPaste:e=>{e.preventDefault(),s({type:"PASTE",text:e.clipboardData.getData("text")})},className:`${o.editor} ${h} ${_?o.editorWithTopBar:null}`,style:{background:a.themeBGColor}},e.createElement(e.Fragment,null,f,l.bufferedContent,y))}function T(t){const n=e.useRef(null),[o,a]=e.useState(!0),l=e.useContext(r),d=e.useContext(i);s(n,o,a);const{caret:u=!0,theme:m="light",showControlBar:p=!0,showControlButtons:f=!0,controlButtonLabels:C=["close","minimize","maximize"],prompt:_=">>>",commands:x={},welcomeMessage:g="",errorMessage:h="not found!",enableInput:b=!0,defaultHandler:y=null,rounded:E=!1}=t,O=E?l["terminal--rounded"]:"",T=p?e.createElement(c,{consoleFocused:o,showControlButtons:f,controlButtonLabels:C}):null,S=e.createElement(A,{caret:u,consoleFocused:o,prompt:_,commands:x,welcomeMessage:g,errorMessage:h,enableInput:b,showControlBar:p,defaultHandler:y,rounded:E});return e.createElement("div",{ref:n,id:l.terminalContainer,className:l[`theme--${m}`],"data-testid":"terminal"},e.createElement("div",{className:`${l.terminal} ${O}`,style:{background:d.themeToolbarColor,color:d.themeColor}},T,S))}function S(t){const{children:n}=t;return e.createElement(o,null,e.createElement(l,null,n))}function P(t){return e.createElement(S,null,e.createElement(T,Object.assign({},t)))}const B=function({children:t,useLocalStorage:n=!0}){const[r,o]=e.useState(null),a={bufferedContent:null,commandsHistory:n?f():[],editorInput:"",currentLineStatus:"idle",caretPosition:0,textBeforeCaret:"",textAfterCaret:""},[i,l]=e.useReducer(x,a),s=e.useCallback((e=>{"SUBMIT"===e.type&&o(i.commandsHistory.length),l(e)}),[i.commandsHistory.length]);e.useEffect((()=>{o(i.commandsHistory.length)}),[i.commandsHistory.length]);const c=e.useMemo((()=>({send:s,store:i,getPreviousCommand:()=>{if(0===r)return 0===i.commandsHistory.length?"":i.commandsHistory[0];const e=i.commandsHistory[r-1];return r>0&&o(r-1),e},getNextCommand:()=>{if(r+1<=i.commandsHistory.length){const e=i.commandsHistory[r+1];return o(r+1),e}return""}})),[r,s,i]);return e.createElement(_.Provider,{value:c},t)};var v={ReactTerminal:P,TerminalContextProvider:B};export{P as ReactTerminal,B as TerminalContextProvider,v as default};