mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2025-12-24 20:42:43 +00:00
Merge branch 'master' into refactorVersionHistory
This commit is contained in:
@@ -25,12 +25,11 @@
|
||||
|
||||
.homebrew nav {
|
||||
background-color : #333333;
|
||||
.navContent {
|
||||
position : relative;
|
||||
z-index : 2;
|
||||
display : flex;
|
||||
justify-content : space-between;
|
||||
}
|
||||
position : relative;
|
||||
z-index : 2;
|
||||
display : flex;
|
||||
justify-content : space-between;
|
||||
|
||||
.navSection {
|
||||
display : flex;
|
||||
align-items : center;
|
||||
|
||||
@@ -429,42 +429,40 @@ const EditPage = createClass({
|
||||
<Meta name='robots' content='noindex, nofollow' />
|
||||
{this.renderNavbar()}
|
||||
|
||||
<div className='content'>
|
||||
{this.props.brew.lock && <LockNotification shareId={this.props.brew.shareId} message={this.props.brew.lock.editMessage} />}
|
||||
<SplitPane onDragFinish={this.handleSplitMove}>
|
||||
<Editor
|
||||
ref={this.editor}
|
||||
brew={this.state.brew}
|
||||
onTextChange={this.handleTextChange}
|
||||
onStyleChange={this.handleStyleChange}
|
||||
onMetaChange={this.handleMetaChange}
|
||||
reportError={this.errorReported}
|
||||
renderer={this.state.brew.renderer}
|
||||
userThemes={this.props.userThemes}
|
||||
snippetBundle={this.state.themeBundle.snippets}
|
||||
updateBrew={this.updateBrew}
|
||||
onCursorPageChange={this.handleEditorCursorPageChange}
|
||||
onViewPageChange={this.handleEditorViewPageChange}
|
||||
currentEditorViewPageNum={this.state.currentEditorViewPageNum}
|
||||
currentEditorCursorPageNum={this.state.currentEditorCursorPageNum}
|
||||
currentBrewRendererPageNum={this.state.currentBrewRendererPageNum}
|
||||
/>
|
||||
<BrewRenderer
|
||||
text={this.state.brew.text}
|
||||
style={this.state.brew.style}
|
||||
renderer={this.state.brew.renderer}
|
||||
theme={this.state.brew.theme}
|
||||
themeBundle={this.state.themeBundle}
|
||||
errors={this.state.htmlErrors}
|
||||
lang={this.state.brew.lang}
|
||||
onPageChange={this.handleBrewRendererPageChange}
|
||||
currentEditorViewPageNum={this.state.currentEditorViewPageNum}
|
||||
currentEditorCursorPageNum={this.state.currentEditorCursorPageNum}
|
||||
currentBrewRendererPageNum={this.state.currentBrewRendererPageNum}
|
||||
allowPrint={true}
|
||||
/>
|
||||
</SplitPane>
|
||||
</div>
|
||||
{this.props.brew.lock && <LockNotification shareId={this.props.brew.shareId} message={this.props.brew.lock.editMessage} />}
|
||||
<SplitPane onDragFinish={this.handleSplitMove}>
|
||||
<Editor
|
||||
ref={this.editor}
|
||||
brew={this.state.brew}
|
||||
onTextChange={this.handleTextChange}
|
||||
onStyleChange={this.handleStyleChange}
|
||||
onMetaChange={this.handleMetaChange}
|
||||
reportError={this.errorReported}
|
||||
renderer={this.state.brew.renderer}
|
||||
userThemes={this.props.userThemes}
|
||||
snippetBundle={this.state.themeBundle.snippets}
|
||||
updateBrew={this.updateBrew}
|
||||
onCursorPageChange={this.handleEditorCursorPageChange}
|
||||
onViewPageChange={this.handleEditorViewPageChange}
|
||||
currentEditorViewPageNum={this.state.currentEditorViewPageNum}
|
||||
currentEditorCursorPageNum={this.state.currentEditorCursorPageNum}
|
||||
currentBrewRendererPageNum={this.state.currentBrewRendererPageNum}
|
||||
/>
|
||||
<BrewRenderer
|
||||
text={this.state.brew.text}
|
||||
style={this.state.brew.style}
|
||||
renderer={this.state.brew.renderer}
|
||||
theme={this.state.brew.theme}
|
||||
themeBundle={this.state.themeBundle}
|
||||
errors={this.state.htmlErrors}
|
||||
lang={this.state.brew.lang}
|
||||
onPageChange={this.handleBrewRendererPageChange}
|
||||
currentEditorViewPageNum={this.state.currentEditorViewPageNum}
|
||||
currentEditorCursorPageNum={this.state.currentEditorCursorPageNum}
|
||||
currentBrewRendererPageNum={this.state.currentBrewRendererPageNum}
|
||||
allowPrint={true}
|
||||
/>
|
||||
</SplitPane>
|
||||
</div>;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -100,35 +100,31 @@ const HomePage = createClass({
|
||||
return <div className='homePage sitePage'>
|
||||
<Meta name='google-site-verification' content='NwnAQSSJZzAT7N-p5MY6ydQ7Njm67dtbu73ZSyE5Fy4' />
|
||||
{this.renderNavbar()}
|
||||
|
||||
<div className='content'>
|
||||
<SplitPane onDragFinish={this.handleSplitMove}>
|
||||
<Editor
|
||||
ref={this.editor}
|
||||
brew={this.state.brew}
|
||||
onTextChange={this.handleTextChange}
|
||||
renderer={this.state.brew.renderer}
|
||||
showEditButtons={false}
|
||||
snippetBundle={this.state.themeBundle.snippets}
|
||||
onCursorPageChange={this.handleEditorCursorPageChange}
|
||||
onViewPageChange={this.handleEditorViewPageChange}
|
||||
currentEditorViewPageNum={this.state.currentEditorViewPageNum}
|
||||
currentEditorCursorPageNum={this.state.currentEditorCursorPageNum}
|
||||
currentBrewRendererPageNum={this.state.currentBrewRendererPageNum}
|
||||
/>
|
||||
<BrewRenderer
|
||||
text={this.state.brew.text}
|
||||
style={this.state.brew.style}
|
||||
renderer={this.state.brew.renderer}
|
||||
onPageChange={this.handleBrewRendererPageChange}
|
||||
currentEditorViewPageNum={this.state.currentEditorViewPageNum}
|
||||
currentEditorCursorPageNum={this.state.currentEditorCursorPageNum}
|
||||
currentBrewRendererPageNum={this.state.currentBrewRendererPageNum}
|
||||
themeBundle={this.state.themeBundle}
|
||||
/>
|
||||
</SplitPane>
|
||||
</div>
|
||||
|
||||
<SplitPane onDragFinish={this.handleSplitMove}>
|
||||
<Editor
|
||||
ref={this.editor}
|
||||
brew={this.state.brew}
|
||||
onTextChange={this.handleTextChange}
|
||||
renderer={this.state.brew.renderer}
|
||||
showEditButtons={false}
|
||||
snippetBundle={this.state.themeBundle.snippets}
|
||||
onCursorPageChange={this.handleEditorCursorPageChange}
|
||||
onViewPageChange={this.handleEditorViewPageChange}
|
||||
currentEditorViewPageNum={this.state.currentEditorViewPageNum}
|
||||
currentEditorCursorPageNum={this.state.currentEditorCursorPageNum}
|
||||
currentBrewRendererPageNum={this.state.currentBrewRendererPageNum}
|
||||
/>
|
||||
<BrewRenderer
|
||||
text={this.state.brew.text}
|
||||
style={this.state.brew.style}
|
||||
renderer={this.state.brew.renderer}
|
||||
onPageChange={this.handleBrewRendererPageChange}
|
||||
currentEditorViewPageNum={this.state.currentEditorViewPageNum}
|
||||
currentEditorCursorPageNum={this.state.currentEditorCursorPageNum}
|
||||
currentBrewRendererPageNum={this.state.currentBrewRendererPageNum}
|
||||
themeBundle={this.state.themeBundle}
|
||||
/>
|
||||
</SplitPane>
|
||||
<div className={cx('floatingSaveButton', { show: this.state.welcomeText != this.state.brew.text })} onClick={this.handleSave}>
|
||||
Save current <i className='fas fa-save' />
|
||||
</div>
|
||||
|
||||
@@ -91,13 +91,6 @@ If you are looking for more 5e Homebrew resources check out [r/UnearthedArcana](
|
||||
|
||||
\page
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Markdown+
|
||||
The Homebrewery aims to make homebrewing as simple as possible, providing a live editor with Markdown syntax that is more human-readable and faster to write with than raw HTML.
|
||||
|
||||
|
||||
@@ -223,39 +223,37 @@ const NewPage = createClass({
|
||||
render : function(){
|
||||
return <div className='newPage sitePage'>
|
||||
{this.renderNavbar()}
|
||||
<div className='content'>
|
||||
<SplitPane onDragFinish={this.handleSplitMove}>
|
||||
<Editor
|
||||
ref={this.editor}
|
||||
brew={this.state.brew}
|
||||
onTextChange={this.handleTextChange}
|
||||
onStyleChange={this.handleStyleChange}
|
||||
onMetaChange={this.handleMetaChange}
|
||||
renderer={this.state.brew.renderer}
|
||||
userThemes={this.props.userThemes}
|
||||
snippetBundle={this.state.themeBundle.snippets}
|
||||
onCursorPageChange={this.handleEditorCursorPageChange}
|
||||
onViewPageChange={this.handleEditorViewPageChange}
|
||||
currentEditorViewPageNum={this.state.currentEditorViewPageNum}
|
||||
currentEditorCursorPageNum={this.state.currentEditorCursorPageNum}
|
||||
currentBrewRendererPageNum={this.state.currentBrewRendererPageNum}
|
||||
/>
|
||||
<BrewRenderer
|
||||
text={this.state.brew.text}
|
||||
style={this.state.brew.style}
|
||||
renderer={this.state.brew.renderer}
|
||||
theme={this.state.brew.theme}
|
||||
themeBundle={this.state.themeBundle}
|
||||
errors={this.state.htmlErrors}
|
||||
lang={this.state.brew.lang}
|
||||
onPageChange={this.handleBrewRendererPageChange}
|
||||
currentEditorViewPageNum={this.state.currentEditorViewPageNum}
|
||||
currentEditorCursorPageNum={this.state.currentEditorCursorPageNum}
|
||||
currentBrewRendererPageNum={this.state.currentBrewRendererPageNum}
|
||||
allowPrint={true}
|
||||
/>
|
||||
</SplitPane>
|
||||
</div>
|
||||
<SplitPane onDragFinish={this.handleSplitMove}>
|
||||
<Editor
|
||||
ref={this.editor}
|
||||
brew={this.state.brew}
|
||||
onTextChange={this.handleTextChange}
|
||||
onStyleChange={this.handleStyleChange}
|
||||
onMetaChange={this.handleMetaChange}
|
||||
renderer={this.state.brew.renderer}
|
||||
userThemes={this.props.userThemes}
|
||||
snippetBundle={this.state.themeBundle.snippets}
|
||||
onCursorPageChange={this.handleEditorCursorPageChange}
|
||||
onViewPageChange={this.handleEditorViewPageChange}
|
||||
currentEditorViewPageNum={this.state.currentEditorViewPageNum}
|
||||
currentEditorCursorPageNum={this.state.currentEditorCursorPageNum}
|
||||
currentBrewRendererPageNum={this.state.currentBrewRendererPageNum}
|
||||
/>
|
||||
<BrewRenderer
|
||||
text={this.state.brew.text}
|
||||
style={this.state.brew.style}
|
||||
renderer={this.state.brew.renderer}
|
||||
theme={this.state.brew.theme}
|
||||
themeBundle={this.state.themeBundle}
|
||||
errors={this.state.htmlErrors}
|
||||
lang={this.state.brew.lang}
|
||||
onPageChange={this.handleBrewRendererPageChange}
|
||||
currentEditorViewPageNum={this.state.currentEditorViewPageNum}
|
||||
currentEditorCursorPageNum={this.state.currentEditorCursorPageNum}
|
||||
currentBrewRendererPageNum={this.state.currentBrewRendererPageNum}
|
||||
allowPrint={true}
|
||||
/>
|
||||
</SplitPane>
|
||||
</div>;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.sharePage{
|
||||
.navContent .navSection.titleSection {
|
||||
nav .navSection.titleSection {
|
||||
flex-grow: 1;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
const React = require('react');
|
||||
const createClass = require('create-react-class');
|
||||
const _ = require('lodash');
|
||||
const { useState } = React;
|
||||
const _ = require('lodash');
|
||||
|
||||
const ListPage = require('../basePages/listPage/listPage.jsx');
|
||||
|
||||
const Nav = require('naturalcrit/nav/nav.jsx');
|
||||
const Navbar = require('../../navbar/navbar.jsx');
|
||||
|
||||
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
|
||||
const Account = require('../../navbar/account.navitem.jsx');
|
||||
const NewBrew = require('../../navbar/newbrew.navitem.jsx');
|
||||
@@ -14,69 +13,48 @@ const HelpNavItem = require('../../navbar/help.navitem.jsx');
|
||||
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
|
||||
const VaultNavitem = require('../../navbar/vault.navitem.jsx');
|
||||
|
||||
const UserPage = createClass({
|
||||
displayName : 'UserPage',
|
||||
getDefaultProps : function() {
|
||||
return {
|
||||
username : '',
|
||||
brews : [],
|
||||
query : '',
|
||||
error : null
|
||||
};
|
||||
},
|
||||
getInitialState : function() {
|
||||
const usernameWithS = this.props.username + (this.props.username.endsWith('s') ? `’` : `’s`);
|
||||
const UserPage = (props)=>{
|
||||
props = {
|
||||
username : '',
|
||||
brews : [],
|
||||
query : '',
|
||||
...props
|
||||
};
|
||||
|
||||
const brews = _.groupBy(this.props.brews, (brew)=>{
|
||||
return (brew.published ? 'published' : 'private');
|
||||
});
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const brewCollection = [
|
||||
{
|
||||
title : `${usernameWithS} published brews`,
|
||||
class : 'published',
|
||||
brews : brews.published
|
||||
}
|
||||
];
|
||||
if(this.props.username == global.account?.username){
|
||||
brewCollection.push(
|
||||
{
|
||||
title : `${usernameWithS} unpublished brews`,
|
||||
class : 'unpublished',
|
||||
brews : brews.private
|
||||
}
|
||||
);
|
||||
}
|
||||
const usernameWithS = props.username + (props.username.endsWith('s') ? `’` : `’s`);
|
||||
const groupedBrews = _.groupBy(props.brews, (brew)=>brew.published ? 'published' : 'private');
|
||||
|
||||
return {
|
||||
brewCollection : brewCollection
|
||||
};
|
||||
},
|
||||
errorReported : function(error) {
|
||||
this.setState({
|
||||
error
|
||||
});
|
||||
},
|
||||
const brewCollection = [
|
||||
{
|
||||
title : `${usernameWithS} published brews`,
|
||||
class : 'published',
|
||||
brews : groupedBrews.published || []
|
||||
},
|
||||
...(props.username === global.account?.username ? [{
|
||||
title : `${usernameWithS} unpublished brews`,
|
||||
class : 'unpublished',
|
||||
brews : groupedBrews.private || []
|
||||
}] : [])
|
||||
];
|
||||
|
||||
navItems : function() {
|
||||
return <Navbar>
|
||||
const navItems = (
|
||||
<Navbar>
|
||||
<Nav.section>
|
||||
{this.state.error ?
|
||||
<ErrorNavItem error={this.state.error} parent={this}></ErrorNavItem> :
|
||||
null
|
||||
}
|
||||
{error && (<ErrorNavItem error={error} parent={null}></ErrorNavItem>)}
|
||||
<NewBrew />
|
||||
<HelpNavItem />
|
||||
<VaultNavitem/>
|
||||
<VaultNavitem />
|
||||
<RecentNavItem />
|
||||
<Account />
|
||||
</Nav.section>
|
||||
</Navbar>;
|
||||
},
|
||||
</Navbar>
|
||||
);
|
||||
|
||||
render : function(){
|
||||
return <ListPage brewCollection={this.state.brewCollection} navItems={this.navItems()} query={this.props.query} reportError={this.errorReported}></ListPage>;
|
||||
}
|
||||
});
|
||||
return (
|
||||
<ListPage brewCollection={brewCollection} navItems={navItems} query={props.query} reportError={(err)=>setError(err)} />
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = UserPage;
|
||||
|
||||
@@ -415,16 +415,13 @@ const VaultPage = (props)=>{
|
||||
<link href='/themes/V3/Blank/style.css' rel='stylesheet' />
|
||||
<link href='/themes/V3/5ePHB/style.css' rel='stylesheet' />
|
||||
{renderNavItems()}
|
||||
<div className='content'>
|
||||
<SplitPane showDividerButtons={false}>
|
||||
<div className='form dataGroup'>{renderForm()}</div>
|
||||
|
||||
<div className='resultsContainer dataGroup'>
|
||||
{renderSortBar()}
|
||||
{renderFoundBrews()}
|
||||
</div>
|
||||
</SplitPane>
|
||||
</div>
|
||||
<SplitPane showDividerButtons={false}>
|
||||
<div className='form dataGroup'>{renderForm()}</div>
|
||||
<div className='resultsContainer dataGroup'>
|
||||
{renderSortBar()}
|
||||
{renderFoundBrews()}
|
||||
</div>
|
||||
</SplitPane>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
190
package-lock.json
generated
190
package-lock.json
generated
@@ -10,9 +10,9 @@
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.25.9",
|
||||
"@babel/core": "^7.26.0",
|
||||
"@babel/plugin-transform-runtime": "^7.25.9",
|
||||
"@babel/preset-env": "^7.25.9",
|
||||
"@babel/preset-env": "^7.26.0",
|
||||
"@babel/preset-react": "^7.25.9",
|
||||
"@googleapis/drive": "^8.14.0",
|
||||
"body-parser": "^1.20.2",
|
||||
@@ -39,7 +39,7 @@
|
||||
"marked-smartypants-lite": "^1.0.2",
|
||||
"markedLegacy": "npm:marked@^0.3.19",
|
||||
"moment": "^2.30.1",
|
||||
"mongoose": "^8.7.2",
|
||||
"mongoose": "^8.7.3",
|
||||
"nanoid": "3.3.4",
|
||||
"nconf": "^0.12.1",
|
||||
"react": "^18.3.1",
|
||||
@@ -83,11 +83,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.9.tgz",
|
||||
"integrity": "sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ==",
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.0.tgz",
|
||||
"integrity": "sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==",
|
||||
"dependencies": {
|
||||
"@babel/highlight": "^7.25.9",
|
||||
"@babel/helper-validator-identifier": "^7.25.9",
|
||||
"js-tokens": "^4.0.0",
|
||||
"picocolors": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -95,28 +96,28 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/compat-data": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.9.tgz",
|
||||
"integrity": "sha512-yD+hEuJ/+wAJ4Ox2/rpNv5HIuPG82x3ZlQvYVn8iYCprdxzE7P1udpGF1jyjQVBU4dgznN+k2h103vxZ7NdPyw==",
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.0.tgz",
|
||||
"integrity": "sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/core": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.9.tgz",
|
||||
"integrity": "sha512-WYvQviPw+Qyib0v92AwNIrdLISTp7RfDkM7bPqBvpbnhY4wq8HvHBZREVdYDXk98C8BkOIVnHAY3yvj7AVISxQ==",
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz",
|
||||
"integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==",
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.25.9",
|
||||
"@babel/generator": "^7.25.9",
|
||||
"@babel/code-frame": "^7.26.0",
|
||||
"@babel/generator": "^7.26.0",
|
||||
"@babel/helper-compilation-targets": "^7.25.9",
|
||||
"@babel/helper-module-transforms": "^7.25.9",
|
||||
"@babel/helpers": "^7.25.9",
|
||||
"@babel/parser": "^7.25.9",
|
||||
"@babel/helper-module-transforms": "^7.26.0",
|
||||
"@babel/helpers": "^7.26.0",
|
||||
"@babel/parser": "^7.26.0",
|
||||
"@babel/template": "^7.25.9",
|
||||
"@babel/traverse": "^7.25.9",
|
||||
"@babel/types": "^7.25.9",
|
||||
"@babel/types": "^7.26.0",
|
||||
"convert-source-map": "^2.0.0",
|
||||
"debug": "^4.1.0",
|
||||
"gensync": "^1.0.0-beta.2",
|
||||
@@ -132,11 +133,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/generator": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.9.tgz",
|
||||
"integrity": "sha512-omlUGkr5EaoIJrhLf9CJ0TvjBRpd9+AXRG//0GEQ9THSo8wPiTlbpy1/Ow8ZTrbXpjd9FHXfbFQx32I04ht0FA==",
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.0.tgz",
|
||||
"integrity": "sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.25.9",
|
||||
"@babel/parser": "^7.26.0",
|
||||
"@babel/types": "^7.26.0",
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.25",
|
||||
"jsesc": "^3.0.2"
|
||||
@@ -260,12 +262,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-module-transforms": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.9.tgz",
|
||||
"integrity": "sha512-TvLZY/F3+GvdRYFZFyxMvnsKi+4oJdgZzU3BoGN9Uc2d9C6zfNwJcKKhjqLAhK8i46mv93jsO74fDh3ih6rpHA==",
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
|
||||
"integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
|
||||
"dependencies": {
|
||||
"@babel/helper-module-imports": "^7.25.9",
|
||||
"@babel/helper-simple-access": "^7.25.9",
|
||||
"@babel/helper-validator-identifier": "^7.25.9",
|
||||
"@babel/traverse": "^7.25.9"
|
||||
},
|
||||
@@ -389,37 +390,23 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helpers": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.9.tgz",
|
||||
"integrity": "sha512-oKWp3+usOJSzDZOucZUAMayhPz/xVjzymyDzUN8dk0Wd3RWMlGLXi07UCQ/CgQVb8LvXx3XBajJH4XGgkt7H7g==",
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz",
|
||||
"integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==",
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.25.9",
|
||||
"@babel/types": "^7.25.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz",
|
||||
"integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==",
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.25.9",
|
||||
"chalk": "^2.4.2",
|
||||
"js-tokens": "^4.0.0",
|
||||
"picocolors": "^1.0.0"
|
||||
"@babel/types": "^7.26.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz",
|
||||
"integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==",
|
||||
"version": "7.26.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.1.tgz",
|
||||
"integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.25.9"
|
||||
"@babel/types": "^7.26.0"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
@@ -554,9 +541,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-syntax-import-assertions": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.9.tgz",
|
||||
"integrity": "sha512-4GHX5uzr5QMOOuzV0an9MFju4hKlm0OyePl/lHhcsTVae5t/IKVHnb8W67Vr6FuLlk5lPqLB7n7O+K5R46emYg==",
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz",
|
||||
"integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.25.9"
|
||||
},
|
||||
@@ -568,9 +555,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-syntax-import-attributes": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.9.tgz",
|
||||
"integrity": "sha512-u3EN9ub8LyYvgTnrgp8gboElouayiwPdnM7x5tcnW3iSt09/lQYPwMNK40I9IUxo7QOZhAsPHCmmuO7EPdruqg==",
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz",
|
||||
"integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==",
|
||||
"dependencies": {
|
||||
"@babel/helper-plugin-utils": "^7.25.9"
|
||||
},
|
||||
@@ -837,9 +824,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-class-static-block": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.25.9.tgz",
|
||||
"integrity": "sha512-UIf+72C7YJ+PJ685/PpATbCz00XqiFEzHX5iysRwfvNT0Ko+FaXSvRgLytFSp8xUItrG9pFM/KoBBZDrY/cYyg==",
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz",
|
||||
"integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==",
|
||||
"dependencies": {
|
||||
"@babel/helper-create-class-features-plugin": "^7.25.9",
|
||||
"@babel/helper-plugin-utils": "^7.25.9"
|
||||
@@ -1396,6 +1383,21 @@
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-regexp-modifiers": {
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz",
|
||||
"integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==",
|
||||
"dependencies": {
|
||||
"@babel/helper-create-regexp-features-plugin": "^7.25.9",
|
||||
"@babel/helper-plugin-utils": "^7.25.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-reserved-words": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz",
|
||||
@@ -1560,11 +1562,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/preset-env": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.9.tgz",
|
||||
"integrity": "sha512-XqDEt+hfsQukahSX9JOBDHhpUHDhj2zGSxoqWQFCMajOSBnbhBdgON/bU/5PkBA1yX5tqW6tTzuIPVsZTQ7h5Q==",
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz",
|
||||
"integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==",
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.25.9",
|
||||
"@babel/compat-data": "^7.26.0",
|
||||
"@babel/helper-compilation-targets": "^7.25.9",
|
||||
"@babel/helper-plugin-utils": "^7.25.9",
|
||||
"@babel/helper-validator-option": "^7.25.9",
|
||||
@@ -1574,8 +1576,8 @@
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9",
|
||||
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9",
|
||||
"@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
|
||||
"@babel/plugin-syntax-import-assertions": "^7.25.9",
|
||||
"@babel/plugin-syntax-import-attributes": "^7.25.9",
|
||||
"@babel/plugin-syntax-import-assertions": "^7.26.0",
|
||||
"@babel/plugin-syntax-import-attributes": "^7.26.0",
|
||||
"@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
|
||||
"@babel/plugin-transform-arrow-functions": "^7.25.9",
|
||||
"@babel/plugin-transform-async-generator-functions": "^7.25.9",
|
||||
@@ -1583,7 +1585,7 @@
|
||||
"@babel/plugin-transform-block-scoped-functions": "^7.25.9",
|
||||
"@babel/plugin-transform-block-scoping": "^7.25.9",
|
||||
"@babel/plugin-transform-class-properties": "^7.25.9",
|
||||
"@babel/plugin-transform-class-static-block": "^7.25.9",
|
||||
"@babel/plugin-transform-class-static-block": "^7.26.0",
|
||||
"@babel/plugin-transform-classes": "^7.25.9",
|
||||
"@babel/plugin-transform-computed-properties": "^7.25.9",
|
||||
"@babel/plugin-transform-destructuring": "^7.25.9",
|
||||
@@ -1616,6 +1618,7 @@
|
||||
"@babel/plugin-transform-private-property-in-object": "^7.25.9",
|
||||
"@babel/plugin-transform-property-literals": "^7.25.9",
|
||||
"@babel/plugin-transform-regenerator": "^7.25.9",
|
||||
"@babel/plugin-transform-regexp-modifiers": "^7.26.0",
|
||||
"@babel/plugin-transform-reserved-words": "^7.25.9",
|
||||
"@babel/plugin-transform-shorthand-properties": "^7.25.9",
|
||||
"@babel/plugin-transform-spread": "^7.25.9",
|
||||
@@ -1724,9 +1727,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz",
|
||||
"integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==",
|
||||
"version": "7.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
|
||||
"integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.25.9",
|
||||
"@babel/helper-validator-identifier": "^7.25.9"
|
||||
@@ -3359,17 +3362,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
@@ -4457,19 +4449,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/char-regex": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
|
||||
@@ -4622,19 +4601,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
||||
},
|
||||
"node_modules/colord": {
|
||||
"version": "2.9.3",
|
||||
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
|
||||
@@ -5691,14 +5657,6 @@
|
||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "9.13.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz",
|
||||
@@ -10652,9 +10610,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mongoose": {
|
||||
"version": "8.7.2",
|
||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.7.2.tgz",
|
||||
"integrity": "sha512-Ok4VzMds9p5G3ZSUhmvBm1GdxanbzhS29jpSn02SPj+IXEVFnIdfwAlHHXWkyNscZKlcn8GuMi68FH++jo0flg==",
|
||||
"version": "8.7.3",
|
||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.7.3.tgz",
|
||||
"integrity": "sha512-Xl6+dzU5ZpEcDoJ8/AyrIdAwTY099QwpolvV73PIytpK13XqwllLq/9XeVzzLEQgmyvwBVGVgjmMrKbuezxrIA==",
|
||||
"dependencies": {
|
||||
"bson": "^6.7.0",
|
||||
"kareem": "2.6.3",
|
||||
|
||||
@@ -86,9 +86,9 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.25.9",
|
||||
"@babel/core": "^7.26.0",
|
||||
"@babel/plugin-transform-runtime": "^7.25.9",
|
||||
"@babel/preset-env": "^7.25.9",
|
||||
"@babel/preset-env": "^7.26.0",
|
||||
"@babel/preset-react": "^7.25.9",
|
||||
"@googleapis/drive": "^8.14.0",
|
||||
"body-parser": "^1.20.2",
|
||||
@@ -115,7 +115,7 @@
|
||||
"marked-smartypants-lite": "^1.0.2",
|
||||
"markedLegacy": "npm:marked@^0.3.19",
|
||||
"moment": "^2.30.1",
|
||||
"mongoose": "^8.7.2",
|
||||
"mongoose": "^8.7.3",
|
||||
"nanoid": "3.3.4",
|
||||
"nconf": "^0.12.1",
|
||||
"react": "^18.3.1",
|
||||
|
||||
@@ -12,10 +12,8 @@ const Nav = {
|
||||
displayName : 'Nav.base',
|
||||
render : function(){
|
||||
return <nav>
|
||||
<div className='navContent'>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</nav>;
|
||||
</nav>;
|
||||
}
|
||||
}),
|
||||
logo : function(){
|
||||
|
||||
@@ -1,200 +1,110 @@
|
||||
require('./splitPane.less');
|
||||
const React = require('react');
|
||||
const createClass = require('create-react-class');
|
||||
const cx = require('classnames');
|
||||
const { useState, useEffect } = React;
|
||||
|
||||
const SplitPane = createClass({
|
||||
displayName : 'SplitPane',
|
||||
getDefaultProps : function() {
|
||||
return {
|
||||
storageKey : 'naturalcrit-pane-split',
|
||||
onDragFinish : function(){}, //fires when dragging
|
||||
showDividerButtons : true
|
||||
};
|
||||
},
|
||||
const storageKey = 'naturalcrit-pane-split';
|
||||
|
||||
getInitialState : function() {
|
||||
return {
|
||||
currentDividerPos : null,
|
||||
windowWidth : 0,
|
||||
isDragging : false,
|
||||
moveSource : false,
|
||||
moveBrew : false,
|
||||
showMoveArrows : true
|
||||
};
|
||||
},
|
||||
const SplitPane = (props)=>{
|
||||
const {
|
||||
onDragFinish = ()=>{},
|
||||
showDividerButtons = true
|
||||
} = props;
|
||||
|
||||
pane1 : React.createRef(null),
|
||||
pane2 : React.createRef(null),
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
const [dividerPos, setDividerPos] = useState(null);
|
||||
const [moveSource, setMoveSource] = useState(false);
|
||||
const [moveBrew, setMoveBrew] = useState(false);
|
||||
const [showMoveArrows, setShowMoveArrows] = useState(true);
|
||||
const [liveScroll, setLiveScroll] = useState(false);
|
||||
|
||||
componentDidMount : function() {
|
||||
const dividerPos = window.localStorage.getItem(this.props.storageKey);
|
||||
if(dividerPos){
|
||||
this.setState({
|
||||
currentDividerPos : this.limitPosition(dividerPos, 0.1*(window.innerWidth-13), 0.9*(window.innerWidth-13)),
|
||||
userSetDividerPos : dividerPos,
|
||||
windowWidth : window.innerWidth
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
currentDividerPos : window.innerWidth / 2,
|
||||
userSetDividerPos : window.innerWidth / 2
|
||||
});
|
||||
}
|
||||
window.addEventListener('resize', this.handleWindowResize);
|
||||
useEffect(()=>{
|
||||
const savedPos = window.localStorage.getItem(storageKey);
|
||||
setDividerPos(savedPos ? limitPosition(savedPos, 0.1 * (window.innerWidth - 13), 0.9 * (window.innerWidth - 13)) : window.innerWidth / 2);
|
||||
setLiveScroll(window.localStorage.getItem('liveScroll') === 'true');
|
||||
|
||||
// This lives here instead of in the initial render because you cannot touch localStorage until the componant mounts.
|
||||
const loadLiveScroll = window.localStorage.getItem('liveScroll') === 'true';
|
||||
this.setState({ liveScroll: loadLiveScroll });
|
||||
},
|
||||
window.addEventListener('resize', handleResize);
|
||||
return ()=>window.removeEventListener('resize', handleResize);
|
||||
}, []);
|
||||
|
||||
componentWillUnmount : function() {
|
||||
window.removeEventListener('resize', this.handleWindowResize);
|
||||
},
|
||||
const limitPosition = (x, min = 1, max = window.innerWidth - 13)=>Math.round(Math.min(max, Math.max(min, x)));
|
||||
|
||||
handleWindowResize : function() {
|
||||
// Allow divider to increase in size to last user-set position
|
||||
// Limit current position to between 10% and 90% of visible space
|
||||
const newLoc = this.limitPosition(this.state.userSetDividerPos, 0.1*(window.innerWidth-13), 0.9*(window.innerWidth-13));
|
||||
|
||||
this.setState({
|
||||
currentDividerPos : newLoc,
|
||||
windowWidth : window.innerWidth
|
||||
});
|
||||
},
|
||||
|
||||
limitPosition : function(x, min = 1, max = window.innerWidth - 13) {
|
||||
const result = Math.round(Math.min(max, Math.max(min, x)));
|
||||
return result;
|
||||
},
|
||||
|
||||
handleUp : function(e){
|
||||
//when resizing, the divider should grow smaller if less space is given, then grow back if the space is restored, to the original position
|
||||
const handleResize = () =>setDividerPos(limitPosition(window.localStorage.getItem(storageKey), 0.1 * (window.innerWidth - 13), 0.9 * (window.innerWidth - 13)));
|
||||
|
||||
const handleUp =(e)=>{
|
||||
e.preventDefault();
|
||||
if(this.state.isDragging){
|
||||
this.props.onDragFinish(this.state.currentDividerPos);
|
||||
window.localStorage.setItem(this.props.storageKey, this.state.currentDividerPos);
|
||||
if(isDragging) {
|
||||
onDragFinish(dividerPos);
|
||||
window.localStorage.setItem(storageKey, dividerPos);
|
||||
}
|
||||
this.setState({ isDragging: false });
|
||||
},
|
||||
setIsDragging(false);
|
||||
};
|
||||
|
||||
handleDown : function(e){
|
||||
const handleDown = (e)=>{
|
||||
e.preventDefault();
|
||||
this.setState({ isDragging: true });
|
||||
//this.unFocus()
|
||||
},
|
||||
|
||||
handleMove : function(e){
|
||||
if(!this.state.isDragging) return;
|
||||
setIsDragging(true);
|
||||
};
|
||||
|
||||
const handleMove = (e)=>{
|
||||
if(!isDragging) return;
|
||||
e.preventDefault();
|
||||
const newSize = this.limitPosition(e.pageX);
|
||||
this.setState({
|
||||
currentDividerPos : newSize,
|
||||
userSetDividerPos : newSize
|
||||
});
|
||||
},
|
||||
setDividerPos(limitPosition(e.pageX));
|
||||
};
|
||||
|
||||
liveScrollToggle : function() {
|
||||
window.localStorage.setItem('liveScroll', String(!this.state.liveScroll));
|
||||
this.setState({ liveScroll: !this.state.liveScroll });
|
||||
},
|
||||
/*
|
||||
unFocus : function() {
|
||||
if(document.selection){
|
||||
document.selection.empty();
|
||||
}else{
|
||||
window.getSelection().removeAllRanges();
|
||||
}
|
||||
},
|
||||
*/
|
||||
const liveScrollToggle = ()=>{
|
||||
window.localStorage.setItem('liveScroll', String(!liveScroll));
|
||||
setLiveScroll(!liveScroll);
|
||||
};
|
||||
|
||||
setMoveArrows : function(newState) {
|
||||
if(this.state.showMoveArrows != newState){
|
||||
this.setState({
|
||||
showMoveArrows : newState
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
renderMoveArrows : function(){
|
||||
if(this.state.showMoveArrows) {
|
||||
return <>
|
||||
<div className='arrow left'
|
||||
style={{ left: this.state.currentDividerPos-4 }}
|
||||
onClick={()=>this.setState({ moveSource: !this.state.moveSource })} >
|
||||
<i className='fas fa-arrow-left' />
|
||||
</div>
|
||||
<div className='arrow right'
|
||||
style={{ left: this.state.currentDividerPos-4 }}
|
||||
onClick={()=>this.setState({ moveBrew: !this.state.moveBrew })} >
|
||||
<i className='fas fa-arrow-right' />
|
||||
</div>
|
||||
<div id='scrollToggleDiv' className={this.state.liveScroll ? 'arrow lock' : 'arrow unlock'}
|
||||
style={{ left: this.state.currentDividerPos-4 }}
|
||||
onClick={this.liveScrollToggle} >
|
||||
<i id='scrollToggle' className={this.state.liveScroll ? 'fas fa-lock' : 'fas fa-unlock'} />
|
||||
</div>
|
||||
</>;
|
||||
}
|
||||
},
|
||||
|
||||
renderDivider : function(){
|
||||
return <>
|
||||
{this.props.showDividerButtons && this.renderMoveArrows()}
|
||||
<div className='divider' onPointerDown={this.handleDown} >
|
||||
<div className='dots'>
|
||||
<i className='fas fa-circle' />
|
||||
<i className='fas fa-circle' />
|
||||
<i className='fas fa-circle' />
|
||||
</div>
|
||||
const renderMoveArrows = (showMoveArrows &&
|
||||
<>
|
||||
<div className='arrow left'
|
||||
onClick={()=>setMoveSource(!moveSource)} >
|
||||
<i className='fas fa-arrow-left' />
|
||||
</div>
|
||||
</>;
|
||||
},
|
||||
<div className='arrow right'
|
||||
onClick={()=>setMoveBrew(!moveBrew)} >
|
||||
<i className='fas fa-arrow-right' />
|
||||
</div>
|
||||
<div id='scrollToggleDiv' className={liveScroll ? 'arrow lock' : 'arrow unlock'}
|
||||
onClick={liveScrollToggle} >
|
||||
<i id='scrollToggle' className={liveScroll ? 'fas fa-lock' : 'fas fa-unlock'} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
render : function(){
|
||||
return <div className='splitPane' onPointerMove={this.handleMove} onPointerUp={this.handleUp}>
|
||||
<Pane
|
||||
width={this.state.currentDividerPos}
|
||||
>
|
||||
{React.cloneElement(this.props.children[0], {
|
||||
...(this.props.showDividerButtons && {
|
||||
moveBrew : this.state.moveBrew,
|
||||
moveSource : this.state.moveSource,
|
||||
liveScroll : this.state.liveScroll,
|
||||
setMoveArrows : this.setMoveArrows,
|
||||
}),
|
||||
})}
|
||||
const renderDivider = (
|
||||
<div className={`divider ${isDragging && 'dragging'}`} onPointerDown={handleDown}>
|
||||
{showDividerButtons && renderMoveArrows}
|
||||
<div className='dots'>
|
||||
<i className='fas fa-circle' />
|
||||
<i className='fas fa-circle' />
|
||||
<i className='fas fa-circle' />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className='splitPane' onPointerMove={handleMove} onPointerUp={handleUp}>
|
||||
<Pane width={dividerPos} moveBrew={moveBrew} moveSource={moveSource} liveScroll={liveScroll} setMoveArrows={setShowMoveArrows}>
|
||||
{props.children[0]}
|
||||
</Pane>
|
||||
{this.renderDivider()}
|
||||
<Pane isDragging={this.state.isDragging}>{this.props.children[1]}</Pane>
|
||||
</div>;
|
||||
}
|
||||
});
|
||||
{renderDivider}
|
||||
<Pane isDragging={isDragging}>{props.children[1]}</Pane>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Pane = createClass({
|
||||
displayName : 'Pane',
|
||||
getDefaultProps : function() {
|
||||
return {
|
||||
width : null
|
||||
};
|
||||
},
|
||||
render : function(){
|
||||
let styles = {};
|
||||
if(this.props.width){
|
||||
styles = {
|
||||
flex : 'none',
|
||||
width : `${this.props.width}px`
|
||||
};
|
||||
} else {
|
||||
styles = {
|
||||
pointerEvents : this.props.isDragging ? 'none' : 'auto' //Disable mouse capture in the rightmost pane; dragging into the iframe drops the divider otherwise
|
||||
};
|
||||
}
|
||||
const Pane = ({ width, children, isDragging, moveBrew, moveSource, liveScroll, setMoveArrows })=>{
|
||||
const styles = width
|
||||
? { flex: 'none', width: `${width}px` }
|
||||
: { pointerEvents: isDragging ? 'none' : 'auto' }; //Disable mouse capture in the right pane; else dragging into the iframe drops the divider
|
||||
|
||||
return <div className={cx('pane', this.props.className)} style={styles}>
|
||||
{this.props.children}
|
||||
</div>;
|
||||
}
|
||||
});
|
||||
return (
|
||||
<div className='pane' style={styles}>
|
||||
{React.cloneElement(children, { moveBrew, moveSource, liveScroll, setMoveArrows })}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = SplitPane;
|
||||
|
||||
@@ -1,69 +1,68 @@
|
||||
|
||||
.splitPane{
|
||||
.splitPane {
|
||||
position : relative;
|
||||
display : flex;
|
||||
flex-direction : row;
|
||||
height : 100%;
|
||||
outline : none;
|
||||
flex-direction : row;
|
||||
.pane{
|
||||
.pane {
|
||||
flex : 1;
|
||||
overflow-x : hidden;
|
||||
overflow-y : hidden;
|
||||
flex : 1;
|
||||
}
|
||||
.divider{
|
||||
touch-action : none;
|
||||
.divider {
|
||||
position : relative;
|
||||
display : table;
|
||||
height : 100%;
|
||||
width : 15px;
|
||||
cursor : ew-resize;
|
||||
background-color : #bbb;
|
||||
height : 100%;
|
||||
text-align : center;
|
||||
.dots{
|
||||
touch-action : none;
|
||||
cursor : ew-resize;
|
||||
background-color : #BBBBBB;
|
||||
.dots {
|
||||
display : table-cell;
|
||||
vertical-align : middle;
|
||||
text-align : center;
|
||||
i{
|
||||
vertical-align : middle;
|
||||
i {
|
||||
display : block !important;
|
||||
margin : 10px 0px;
|
||||
font-size : 6px;
|
||||
color : #666;
|
||||
color : #666666;
|
||||
}
|
||||
}
|
||||
&:hover{
|
||||
background-color: #999;
|
||||
}
|
||||
&:hover,&.dragging { background-color : #999999; }
|
||||
}
|
||||
.arrow{
|
||||
.arrow {
|
||||
position : absolute;
|
||||
left : 50%;
|
||||
z-index : 999;
|
||||
width : 25px;
|
||||
height : 25px;
|
||||
border : 2px solid #bbb;
|
||||
border-radius : 15px;
|
||||
text-align : center;
|
||||
font-size : 1.2em;
|
||||
text-align : center;
|
||||
cursor : pointer;
|
||||
background-color : #ddd;
|
||||
z-index : 999;
|
||||
box-shadow : 0 4px 5px #0000007f;
|
||||
&.left{
|
||||
background-color : #DDDDDD;
|
||||
border : 2px solid #BBBBBB;
|
||||
border-radius : 15px;
|
||||
box-shadow : 0 4px 5px #0000007F;
|
||||
translate : -50%;
|
||||
&.left {
|
||||
.tooltipLeft('Jump to location in Editor');
|
||||
top : 30px;
|
||||
}
|
||||
&.right{
|
||||
&.right {
|
||||
.tooltipRight('Jump to location in Preview');
|
||||
top : 60px;
|
||||
}
|
||||
&.lock{
|
||||
&.lock {
|
||||
.tooltipRight('De-sync Editor and Preview locations.');
|
||||
top : 90px;
|
||||
background: #666;
|
||||
top : 90px;
|
||||
background : #666666;
|
||||
}
|
||||
&.unlock{
|
||||
&.unlock {
|
||||
.tooltipRight('Sync Editor and Preview locations');
|
||||
top : 90px;
|
||||
}
|
||||
&:hover{
|
||||
background-color: #666;
|
||||
}
|
||||
&:hover { background-color : #666666; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user