mirror of
https://github.com/chinchang/web-maker.git
synced 2025-04-04 19:02:27 +02:00
moreeee stuff
This commit is contained in:
parent
a3fae1e2d8
commit
aaa9dc4c97
31
webmaker/src/components/CodeMirrorBox.jsx
Normal file
31
webmaker/src/components/CodeMirrorBox.jsx
Normal file
@ -0,0 +1,31 @@
|
||||
import { h, Component } from 'preact';
|
||||
import CodeMirror from '../CodeMirror';
|
||||
|
||||
import 'codemirror/mode/javascript/javascript.js';
|
||||
|
||||
export default class CodeMirrorBox extends Component {
|
||||
componentDidMount() {
|
||||
this.initEditor();
|
||||
}
|
||||
shouldComponentUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
initEditor() {
|
||||
const options = this.props.options;
|
||||
this.cm = CodeMirror.fromTextArea(this.textarea, this.props.options);
|
||||
this.props.onCreation(this.cm);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<textarea
|
||||
ref={el => (this.textarea = el)}
|
||||
name=""
|
||||
id=""
|
||||
cols="30"
|
||||
rows="10"
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
@ -197,6 +197,9 @@ export default class ContentWrap extends Component {
|
||||
isValidItem(item) {
|
||||
return !!item.title;
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return this.state.isConsoleOpen !== nextState.isConsoleOpen;
|
||||
}
|
||||
componentDidUpdate() {
|
||||
// HACK: becuase its a DOM manipulation
|
||||
window.logCountEl.textContent = this.logCount;
|
||||
@ -241,8 +244,10 @@ export default class ContentWrap extends Component {
|
||||
prefs.fontSize,
|
||||
10
|
||||
)}px`;
|
||||
|
||||
// consoleEl.querySelector('.CodeMirror').style.fontSize = prefs.fontSize;
|
||||
window.consoleEl.querySelector('.CodeMirror').style.fontSize = `${parseInt(
|
||||
prefs.fontSize,
|
||||
10
|
||||
)}px`;
|
||||
|
||||
// Replace correct css file in LINK tags's href
|
||||
window.editorThemeLinkTag.href = `lib/codemirror/theme/${
|
||||
@ -257,6 +262,7 @@ export default class ContentWrap extends Component {
|
||||
// window.customEditorFontInput.classList[
|
||||
// prefs.editorFont === 'other' ? 'remove' : 'add'
|
||||
// ]('hide');
|
||||
this.consoleCm.setOption('theme', prefs.editorTheme);
|
||||
|
||||
['html', 'js', 'css'].forEach(type => {
|
||||
this.cm[type].setOption('indentWithTabs', prefs.indentWith !== 'spaces');
|
||||
@ -527,7 +533,6 @@ export default class ContentWrap extends Component {
|
||||
}
|
||||
|
||||
onMessageFromConsole() {
|
||||
const self = this;
|
||||
/* eslint-disable no-param-reassign */
|
||||
[...arguments].forEach(arg => {
|
||||
if (
|
||||
@ -584,6 +589,24 @@ export default class ContentWrap extends Component {
|
||||
trackEvent('ui', 'consoleClearBtnClick');
|
||||
}
|
||||
|
||||
evalConsoleExpr(e) {
|
||||
// Clear console on CTRL + L
|
||||
if ((e.which === 76 || e.which === 12) && e.ctrlKey) {
|
||||
this.clearConsole();
|
||||
trackEvent('ui', 'consoleClearKeyboardShortcut');
|
||||
} else if (e.which === 13) {
|
||||
this.onMessageFromConsole('> ' + e.target.value);
|
||||
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
this.frame.contentWindow._wmEvaluate(e.target.value);
|
||||
|
||||
/* eslint-enable no-underscore-dangle */
|
||||
|
||||
e.target.value = '';
|
||||
trackEvent('fn', 'evalConsoleExpr');
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<SplitPane
|
||||
@ -826,7 +849,10 @@ export default class ContentWrap extends Component {
|
||||
<svg width="18" height="18" fill="#346fd2">
|
||||
Chevron
|
||||
</svg>
|
||||
<input d-keyup="evalConsoleExpr" class="console-exec-input" />
|
||||
<input
|
||||
onKeyUp={this.evalConsoleExpr.bind(this)}
|
||||
class="console-exec-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -168,7 +168,7 @@ export default class Footer extends Component {
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
onClick={() => this.setState({ isKeyboardShortcutsModalOpen: true })}
|
||||
onClick={this.props.keyboardShortcutsBtnClickHandler}
|
||||
data-event-category="ui"
|
||||
data-event-action="keyboardShortcutButtonClick"
|
||||
class="footer__link hint--rounded hint--top-right hide-on-mobile"
|
||||
@ -209,98 +209,6 @@ export default class Footer extends Component {
|
||||
>
|
||||
Support the developer
|
||||
</a>
|
||||
<Modal
|
||||
show={this.state.isKeyboardShortcutsModalOpen}
|
||||
closeHandler={() =>
|
||||
this.setState({ isKeyboardShortcutsModalOpen: false })
|
||||
}
|
||||
>
|
||||
<h1>Keyboard Shortcuts</h1>
|
||||
|
||||
<div class="flex">
|
||||
<div>
|
||||
<h2>Global</h2>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + Shift + ?</span>
|
||||
<span class="kbd-shortcut__details">
|
||||
See keyboard shortcuts
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + Shift + 5</span>
|
||||
<span class="kbd-shortcut__details">Refresh preview</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + S</span>
|
||||
<span class="kbd-shortcut__details">
|
||||
Save current creations
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + O</span>
|
||||
<span class="kbd-shortcut__details">
|
||||
Open list of saved creations
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl + L</span>
|
||||
<span class="kbd-shortcut__details">
|
||||
Clear console (works when console input is focused)
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Esc</span>
|
||||
<span class="kbd-shortcut__details">
|
||||
Close saved creations panel & modals
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="ml-2">
|
||||
<h2>Editor</h2>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + F</span>
|
||||
<span class="kbd-shortcut__details">Find</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + G</span>
|
||||
<span class="kbd-shortcut__details">Select next match</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + Shift + G</span>
|
||||
<span class="kbd-shortcut__details">Select previous match</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + Opt/Alt + F</span>
|
||||
<span class="kbd-shortcut__details">Find & replace</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Shift + Tab</span>
|
||||
<span class="kbd-shortcut__details">Realign code</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + ]</span>
|
||||
<span class="kbd-shortcut__details">Indent code right</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + [</span>
|
||||
<span class="kbd-shortcut__details">Indent code left</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Tab</span>
|
||||
<span class="kbd-shortcut__details">
|
||||
Emmet code completion{' '}
|
||||
<a href="https://emmet.io/" target="_blank">
|
||||
Read more
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + /</span>
|
||||
<span class="kbd-shortcut__details">Single line comment</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
92
webmaker/src/components/KeyboardShortcutsModal.jsx
Normal file
92
webmaker/src/components/KeyboardShortcutsModal.jsx
Normal file
@ -0,0 +1,92 @@
|
||||
import { h, Component } from 'preact';
|
||||
import Modal from './Modal';
|
||||
|
||||
export default class KeyboardShortcutsModal extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Modal show={this.props.show} closeHandler={this.props.closeHandler}>
|
||||
<h1>Keyboard Shortcuts</h1>
|
||||
|
||||
<div class="flex">
|
||||
<div>
|
||||
<h2>Global</h2>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + Shift + ?</span>
|
||||
<span class="kbd-shortcut__details">See keyboard shortcuts</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + Shift + 5</span>
|
||||
<span class="kbd-shortcut__details">Refresh preview</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + S</span>
|
||||
<span class="kbd-shortcut__details">Save current creations</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + O</span>
|
||||
<span class="kbd-shortcut__details">
|
||||
Open list of saved creations
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl + L</span>
|
||||
<span class="kbd-shortcut__details">
|
||||
Clear console (works when console input is focused)
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Esc</span>
|
||||
<span class="kbd-shortcut__details">
|
||||
Close saved creations panel & modals
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="ml-2">
|
||||
<h2>Editor</h2>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + F</span>
|
||||
<span class="kbd-shortcut__details">Find</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + G</span>
|
||||
<span class="kbd-shortcut__details">Select next match</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + Shift + G</span>
|
||||
<span class="kbd-shortcut__details">Select previous match</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + Opt/Alt + F</span>
|
||||
<span class="kbd-shortcut__details">Find & replace</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Shift + Tab</span>
|
||||
<span class="kbd-shortcut__details">Realign code</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + ]</span>
|
||||
<span class="kbd-shortcut__details">Indent code right</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + [</span>
|
||||
<span class="kbd-shortcut__details">Indent code left</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Tab</span>
|
||||
<span class="kbd-shortcut__details">
|
||||
Emmet code completion{' '}
|
||||
<a href="https://emmet.io/" target="_blank">
|
||||
Read more
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="kbd-shortcut__keys">Ctrl/⌘ + /</span>
|
||||
<span class="kbd-shortcut__details">Single line comment</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ export default class Header extends Component {
|
||||
id="runBtn"
|
||||
class="hide flex flex-v-center hint--rounded hint--bottom-left"
|
||||
aria-label="Run preview (Ctrl/⌘ + Shift + 5)"
|
||||
d-click="onRunBtnClick"
|
||||
onClick={this.props.runBtnClickHandler}
|
||||
>
|
||||
<svg style="width: 14px; height: 14px;">
|
||||
<use xlinkHref="#play-icon" />
|
||||
|
@ -16,11 +16,58 @@ export default class SavedItemPane extends Component {
|
||||
e.stopPropagation();
|
||||
this.props.itemForkBtnClickHandler(item);
|
||||
}
|
||||
keyDownHandler(event) {
|
||||
if (!this.props.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isCtrlOrMetaPressed = event.ctrlKey || event.metaKey;
|
||||
const isForkKeyPressed = isCtrlOrMetaPressed && event.keyCode === 70;
|
||||
const isDownKeyPressed = event.keyCode === 40;
|
||||
const isUpKeyPressed = event.keyCode === 38;
|
||||
const isEnterKeyPressed = event.keyCode === 13;
|
||||
|
||||
const selectedItemElement = $('.js-saved-item-tile.selected');
|
||||
const havePaneItems = $all('.js-saved-item-tile').length !== 0;
|
||||
|
||||
if ((isDownKeyPressed || isUpKeyPressed) && havePaneItems) {
|
||||
const method = isDownKeyPressed ? 'nextUntil' : 'previousUntil';
|
||||
|
||||
if (selectedItemElement) {
|
||||
selectedItemElement.classList.remove('selected');
|
||||
selectedItemElement[method](
|
||||
'.js-saved-item-tile:not(.hide)'
|
||||
).classList.add('selected');
|
||||
} else {
|
||||
$('.js-saved-item-tile:not(.hide)').classList.add('selected');
|
||||
}
|
||||
$('.js-saved-item-tile.selected').scrollIntoView(false);
|
||||
}
|
||||
|
||||
if (isEnterKeyPressed && selectedItemElement) {
|
||||
const item = this.props.items.filter(
|
||||
item => (item.id = selectedItemElement.dataset.itemId)
|
||||
)[0];
|
||||
this.props.itemClickHandler(item);
|
||||
}
|
||||
|
||||
// Fork shortcut inside saved creations panel with Ctrl/⌘ + F
|
||||
if (isForkKeyPressed) {
|
||||
event.preventDefault();
|
||||
const item = this.props.items.filter(
|
||||
item => (item.id = selectedItemElement.dataset.itemId)
|
||||
)[0];
|
||||
this.props.itemForkBtnClickHandler(item);
|
||||
trackEvent('ui', 'forkKeyboardShortcut');
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
id="js-saved-items-pane"
|
||||
class={`saved-items-pane ${this.props.isOpen ? 'is-open' : ''}`}
|
||||
onKeyDown={this.keyDownHandler.bind(this)}
|
||||
>
|
||||
<button
|
||||
onClick={this.onCloseIntent.bind(this)}
|
||||
|
@ -4,7 +4,7 @@ import Modal from './Modal';
|
||||
export default class SupportDeveloperModal extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Modal show={this.props.isOpen} closeHandler={this.props.closeHandler}>
|
||||
<Modal show={this.props.show} closeHandler={this.props.closeHandler}>
|
||||
<div class="tac">
|
||||
<h1>Support the Developer</h1>
|
||||
<p>
|
||||
|
@ -118,7 +118,9 @@ export default class UserCodeMirror extends Component {
|
||||
) {
|
||||
return;
|
||||
}
|
||||
CodeMirror.commands.autocomplete(cm, null, { completeSingle: false });
|
||||
CodeMirror.commands.autocomplete(this.cm, null, {
|
||||
completeSingle: false
|
||||
});
|
||||
});
|
||||
}
|
||||
this.props.onCreation(this.cm);
|
||||
|
@ -23,6 +23,7 @@ import 'firebase/auth';
|
||||
import Profile from './Profile';
|
||||
import { auth } from '../auth';
|
||||
import SupportDeveloperModal from './SupportDeveloperModal';
|
||||
import KeyboardShortcutsModal from './KeyboardShortcutsModal';
|
||||
|
||||
if (module.hot) {
|
||||
require('preact/debug');
|
||||
@ -49,6 +50,7 @@ export default class App extends Component {
|
||||
isLoginModalOpen: false,
|
||||
isProfileModalOpen: false,
|
||||
isSupportDeveloperModalOpen: false,
|
||||
isKeyboardShortcutsModalOpen: false,
|
||||
prefs: {},
|
||||
currentItem: {
|
||||
title: '',
|
||||
@ -438,7 +440,9 @@ export default class App extends Component {
|
||||
) {
|
||||
// Ctrl/⌘ + Shift + ?
|
||||
event.preventDefault();
|
||||
// scope.toggleModal(keyboardShortcutsModal);
|
||||
this.setState({
|
||||
isKeyboardShortcutsModalOpen: !this.state.isKeyboardShortcutsModalOpen
|
||||
});
|
||||
trackEvent('ui', 'showKeyboardShortcutsShortcut');
|
||||
} else if (event.keyCode === 27) {
|
||||
this.closeAllOverlays();
|
||||
@ -668,7 +672,6 @@ export default class App extends Component {
|
||||
this.contentWrap.applyCodemirrorSettings(this.state.prefs);
|
||||
|
||||
/*
|
||||
scope.consoleCm.setOption('theme', $('[data-setting=editorTheme]').value);
|
||||
scope.acssSettingsCm.setOption(
|
||||
'theme',
|
||||
$('[data-setting=editorTheme]').value
|
||||
@ -804,6 +807,10 @@ export default class App extends Component {
|
||||
trackEvent('ui', 'saveHtmlClick');
|
||||
e.preventDefault();
|
||||
}
|
||||
runBtnClickHandler() {
|
||||
this.contentWrap.setPreviewContent(true, true);
|
||||
trackEvent('ui', 'runBtnClick');
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
@ -817,6 +824,7 @@ export default class App extends Component {
|
||||
loginBtnHandler={this.loginBtnClickHandler.bind(this)}
|
||||
profileBtnHandler={this.profileBtnClickHandler.bind(this)}
|
||||
addLibraryBtnHandler={this.openAddLibrary.bind(this)}
|
||||
runBtnClickHandler={this.runBtnClickHandler.bind(this)}
|
||||
isFetchingItems={this.state.isFetchingItems}
|
||||
isSaving={this.state.isSaving}
|
||||
title={this.state.currentItem.title}
|
||||
@ -852,6 +860,9 @@ export default class App extends Component {
|
||||
)}
|
||||
codepenBtnClickHandler={this.codepenBtnClickHandler.bind(this)}
|
||||
saveHtmlBtnClickHandler={this.saveHtmlBtnClickHandler.bind(this)}
|
||||
keyboardShortcutsBtnClickHandler={() =>
|
||||
this.setState({ isKeyboardShortcutsModalOpen: true })
|
||||
}
|
||||
hasUnseenChangelog={this.state.hasUnseenChangelog}
|
||||
/>
|
||||
</div>
|
||||
@ -934,11 +945,17 @@ export default class App extends Component {
|
||||
closeHandler={() => this.setState({ isHelpModalOpen: false })}
|
||||
/>
|
||||
<SupportDeveloperModal
|
||||
isOpen={this.state.isSupportDeveloperModalOpen}
|
||||
show={this.state.isSupportDeveloperModalOpen}
|
||||
closeHandler={() =>
|
||||
this.setState({ isSupportDeveloperModalOpen: false })
|
||||
}
|
||||
/>
|
||||
<KeyboardShortcutsModal
|
||||
show={this.state.isKeyboardShortcutsModalOpen}
|
||||
closeHandler={() =>
|
||||
this.setState({ isKeyboardShortcutsModalOpen: false })
|
||||
}
|
||||
/>
|
||||
|
||||
<div class="modal-overlay" />
|
||||
|
||||
|
@ -30,11 +30,21 @@ var alphaNum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
* @return element Next element that mathes `selector`
|
||||
*/
|
||||
Node.prototype.nextUntil = function (selector) {
|
||||
const siblings = [...this.parentNode.querySelectorAll(selector)];
|
||||
const siblings = Array.from(this.parentNode.querySelectorAll(selector));
|
||||
const index = siblings.indexOf(this);
|
||||
return siblings[index + 1];
|
||||
};
|
||||
|
||||
/*
|
||||
* @param Selector that should match for next siblings
|
||||
* @return element Next element that mathes `selector`
|
||||
*/
|
||||
Node.prototype.previousUntil = function (selector) {
|
||||
const siblings = Array.from(this.parentNode.querySelectorAll(selector));
|
||||
const index = siblings.indexOf(this);
|
||||
return siblings[index - 1];
|
||||
};
|
||||
|
||||
// Safari doesn't have this!
|
||||
window.requestIdleCallback =
|
||||
window.requestIdleCallback ||
|
||||
@ -42,16 +52,6 @@ window.requestIdleCallback =
|
||||
setTimeout(fn, 10);
|
||||
};
|
||||
|
||||
/*
|
||||
* @param Selector that should match for next siblings
|
||||
* @return element Next element that mathes `selector`
|
||||
*/
|
||||
Node.prototype.previousUntil = function (selector) {
|
||||
const siblings = [...this.parentNode.querySelectorAll(selector)];
|
||||
const index = siblings.indexOf(this);
|
||||
return siblings[index - 1];
|
||||
};
|
||||
|
||||
// https://github.com/substack/semver-compare/blob/master/index.js
|
||||
export function semverCompare(a, b) {
|
||||
var pa = a.split('.');
|
||||
|
Loading…
x
Reference in New Issue
Block a user