diff --git a/src/components/Settings.jsx b/src/components/Settings.jsx
index 6286448..31e3658 100644
--- a/src/components/Settings.jsx
+++ b/src/components/Settings.jsx
@@ -1,32 +1,21 @@
import { h, Component } from 'preact';
import { editorThemes } from '../editorThemes';
+import Switch from './Switch';
+import Tabs, { TabPanel } from './Tabs';
+import { Divider } from './common';
-function CheckboxSetting({
- title,
- label,
- onChange,
- pref,
- name,
- showWhenExtension
-}) {
+function CheckboxSetting({ label, onChange, pref }) {
return (
-
+
);
}
export default class Settings extends Component {
- updateSetting(e) {
- this.props.onChange(e);
+ updateSetting(e, settingName) {
+ const value =
+ e.target.type === 'checkbox' ? e.target.checked : e.target.value;
+ this.props.onChange(settingName, value);
}
shouldComponentUpdate() {
// TODO: add check on prefs
@@ -38,304 +27,335 @@ export default class Settings extends Component {
Settings
-
Indentation
-
-
-
-
-
-
-
-
-
Editor
-
-
-
+
+
-
-
-
-
- this.updateSetting(e, 'preserveLastCode')}
/>
+
+ Loads the last open creation when app starts
+
+
-
- this.updateSetting(e, 'lightVersion')}
/>
-
-
+
+ Switch to lighter version for better performance. Removes things
+ like blur etc.
+
+
+
this.updateSetting(e, 'autoPreview')}
+ />
+
+ Refreshes the preview as you code. Otherwise use the 'Run' button
+
+
+ this.updateSetting(e, 'autoSave')}
+ />
+
+ Auto-save keeps saving your code at regular intervals after you
+ hit save manually the first time
+
+
+ this.updateSetting(e, 'refreshOnResize')}
+ />
+
+ Preview will refresh when you resize the preview pane
+
+
+
+
this.updateSetting(e, 'replaceNewTab')}
+ showWhenExtension
+ />
+
+ Turning this on will start showing Web Maker in every new tab
+ you open
+
+
+
+ this.updateSetting(e, 'preserveConsoleLogs')}
+ />
+
+ Preserves the console logs across your preview refreshes
+
+
+
+
+
+
+
+
+
+
+
Default Preprocessors
+
+
+
+
+
+
+
+
+
-
+
+
-
Fun
-
-
+
+
-
-
+
+
+
-
+
+
this.updateSetting(e, 'lineWrap')}
+ />
+
- Advanced
-
-
-
- If any loop iteration takes more than the defined time, it is
- detected as a potential infinite loop and further iterations are
- stopped.
-
-
+ this.updateSetting(e, 'autoComplete')}
+ />
+
+
+
+
+ this.updateSetting(e, 'isCodeBlastOn')}
+ />
+
+ Enjoy wonderful particle blasts while you type
+
+
+ this.updateSetting(e, 'isJs13kModeOn')}
+ />
+
+ Make the app ready to build some games for{' '}
+
+ Js13kGames
+ .
+
+
+
+
+
+
+ If any loop iteration takes more than the defined time, it is
+ detected as a potential infinite loop and further iterations are
+ stopped.
+
+
+
-
-
-
+
+
+
+
+
);
}
diff --git a/src/components/Switch.jsx b/src/components/Switch.jsx
new file mode 100644
index 0000000..b56c282
--- /dev/null
+++ b/src/components/Switch.jsx
@@ -0,0 +1,35 @@
+import { h, Component } from 'preact';
+
+export default class Switch extends Component {
+ render() {
+ return (
+
+ );
+ }
+}
diff --git a/src/components/Tabs.jsx b/src/components/Tabs.jsx
new file mode 100644
index 0000000..db792b4
--- /dev/null
+++ b/src/components/Tabs.jsx
@@ -0,0 +1,89 @@
+import { h, Component } from 'preact';
+
+function hyphenate(text) {
+ return text.replace(/\s/g, '-');
+}
+const ID_PREFIX = 'tab-panel-';
+
+export function TabPanel({ label }) {
+ return (
+
+ {this.props.children}
+
+ );
+}
+function Tab({ label, isSelected, onKeyUp, onClick }) {
+ return (
+
+ );
+}
+export default class Tabs extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ selectedTab: 0
+ };
+ }
+ isSelected(index) {
+ return this.state.selectedTab === index;
+ }
+ switchTab(selectedTab) {
+ this.setState({ selectedTab: selectedTab });
+ this.tabListEl.querySelectorAll('[role=tab]')[selectedTab].focus();
+ }
+ keyUpHandler(e) {
+ let { selectedTab } = this.state;
+ if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
+ selectedTab--;
+ selectedTab =
+ selectedTab < 0 ? this.props.children.length - 1 : selectedTab;
+ this.switchTab(selectedTab);
+ e.preventDefault();
+ } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
+ selectedTab++;
+ selectedTab %= this.props.children.length;
+ this.switchTab(selectedTab);
+ e.preventDefault();
+ }
+ }
+ render() {
+ const tabs = this.props.children;
+ return (
+
+
(this.tabListEl = el)}
+ >
+ {tabs.map((child, index) => (
+ this.setState({ selectedTab: index })}
+ />
+ ))}
+
+
+ {tabs.map(
+ (child, index) => (this.state.selectedTab === index ? child : null)
+ )}
+
+
+ );
+ }
+}
diff --git a/src/components/app.jsx b/src/components/app.jsx
index 82b38b8..7c192fd 100644
--- a/src/components/app.jsx
+++ b/src/components/app.jsx
@@ -887,15 +887,14 @@ export default class App extends Component {
/**
* Handles all user triggered preference changes in the UI.
*/
- updateSetting(e) {
+ updateSetting(settingName, value) {
// If this was triggered from user interaction, save the setting
- if (e) {
- var settingName = e.target.dataset.setting;
+ if (settingName) {
+ // var settingName = e.target.dataset.setting;
var obj = {};
- var el = e.target;
- log(settingName, el.type === 'checkbox' ? el.checked : el.value);
+ log(settingName, value);
const prefs = { ...this.state.prefs };
- prefs[settingName] = el.type === 'checkbox' ? el.checked : el.value;
+ prefs[settingName] = value;
obj[settingName] = prefs[settingName];
this.setState({ prefs });
diff --git a/src/components/common.jsx b/src/components/common.jsx
index 4c53f63..90e7b31 100644
--- a/src/components/common.jsx
+++ b/src/components/common.jsx
@@ -32,3 +32,7 @@ export function AutoFocusInput(props) {
el && setTimeout(() => el.focus(), 100)} {...props} />
);
}
+
+export function Divider(props) {
+ return ;
+}
diff --git a/src/style.css b/src/style.css
index c8cc02e..fc7b3c5 100644
--- a/src/style.css
+++ b/src/style.css
@@ -212,6 +212,11 @@ hr {
label {
cursor: pointer;
}
+.divider {
+ margin: 10px 0;
+ height: 1px;
+ background: rgba(255, 255, 255, 0.1);
+}
[class*='hint--']:after {
text-transform: none;
@@ -221,8 +226,10 @@ label {
}
.line {
- display: block;
+ /* display: block; */
margin-bottom: 1em;
+ display: flex;
+ justify-content: space-between;
}
.caret {
@@ -249,6 +256,86 @@ a > svg {
bottom: 0;
}
+.check-switch {
+ display: block;
+ overflow: hidden;
+ position: relative;
+
+ /* breathing space for outline */
+ padding: 2px 0;
+}
+
+.check-switch:hover {
+ background: rgba(0, 0, 0, 0.1);
+}
+
+.check-switch .check-switch__toggle {
+ position: relative;
+ margin: 0 5px;
+}
+.check-switch .check-switch__toggle:after {
+ background: #fff;
+ position: absolute;
+ border-radius: 100%;
+ width: 1.1em;
+ height: 1.1em;
+ top: 3px;
+ right: 1.5em;
+ box-shadow: 0 2px 3px rgba(0, 0, 0, 0.5);
+ transition: right 0.1825s ease-in-out;
+}
+
+.check-switch .check-switch__toggle:before,
+.check-switch .check-switch__toggle:after {
+ content: '';
+ display: block;
+}
+
+.check-switch .check-switch__toggle:before {
+ background: rgba(255, 255, 255, 0.2);
+ border-radius: 1.75em;
+ width: 2.75em;
+ height: 1.45em;
+ right: 0.25em;
+ transition: background 0.2s ease-in-out;
+}
+
+.check-switch input:not([role='button']) {
+ pointer-events: none;
+}
+
+.check-switch input {
+ top: 0;
+ left: 0;
+ opacity: 0.0001;
+ position: absolute;
+}
+
+.check-switch__status {
+ text-transform: uppercase;
+ font-size: 14px;
+ font-weight: 600;
+}
+
+.check-switch input:focus + * .check-switch__toggle:before {
+ outline: 2px solid;
+ outline-color: var(--color-focus-outline);
+}
+
+.check-switch input:checked + * .check-switch__toggle:after {
+ right: 0.15em;
+ left: auto;
+}
+
+.check-switch input:checked + * .check-switch__toggle:before {
+ background: #61ad1c;
+}
+.check-switch__toggle-wrap {
+ float: right;
+ display: flex;
+ align-items: center;
+}
+
.btn {
display: inline-block;
color: var(--color-button);
@@ -907,10 +994,9 @@ body > #demo-frame {
/* Make settings modal smaller */
-@media screen and (min-width: 600px) {
- .modal--settings {
- /* width: 600px; */
- /* margin-lef.t: -300px; */
+@media screen and (min-width: 850px) {
+ .modal--settings > .modal__content {
+ width: 850px;
}
}
@@ -1577,6 +1663,7 @@ body:not(.is-app) .show-when-app {
.help-text {
font-size: 0.9em;
color: rgba(255, 255, 255, 0.5);
+ margin: 5px 0;
}
.social-login-btn:after,
@@ -1822,6 +1909,29 @@ while the theme CSS file is loading */
padding: 5px;
z-index: 1;
}
+.tabs {
+ display: flex;
+}
+.tabs__tablist {
+ margin-right: 40px;
+ flex-shrink: 0;
+}
+.tabs__tab {
+ display: block;
+ margin-bottom: 10px;
+ background: transparent;
+ border: 0;
+ text-align: left;
+ width: 100%;
+ color: inherit;
+}
+.tabs__tab--selected {
+ background-color: rgba(0, 0, 0, 0.5);
+}
+.tabs__tabpanel-wrap {
+ flex: 1;
+}
+
@media screen and (max-width: 600px) {
body {
font-size: 70%;