Reactify the Tag Selector
This commit is contained in:
parent
506ed313da
commit
897e74c7f1
33 changed files with 1396 additions and 1597 deletions
1
.babelrc
1
.babelrc
|
@ -18,6 +18,7 @@
|
||||||
"syntax-jsx",
|
"syntax-jsx",
|
||||||
"transform-react-jsx",
|
"transform-react-jsx",
|
||||||
"transform-react-display-name",
|
"transform-react-display-name",
|
||||||
|
"transform-class-properties",
|
||||||
[
|
[
|
||||||
"transform-es2015-modules-commonjs",
|
"transform-es2015-modules-commonjs",
|
||||||
{
|
{
|
||||||
|
|
File diff suppressed because it is too large
Load diff
455
chrome/content/zotero/reactUI/containers/tag-selector.jsx
Normal file
455
chrome/content/zotero/reactUI/containers/tag-selector.jsx
Normal file
|
@ -0,0 +1,455 @@
|
||||||
|
/* global Zotero: false */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
const React = require('react');
|
||||||
|
const ReactDom = require('react-dom');
|
||||||
|
const TagSelector = require('react-ui/components/tag-selector.js');
|
||||||
|
const noop = Promise.resolve();
|
||||||
|
const defaults = {
|
||||||
|
tags: [],
|
||||||
|
searchString: '',
|
||||||
|
shouldFocus: false,
|
||||||
|
onSelection: noop,
|
||||||
|
viewOnly: false
|
||||||
|
};
|
||||||
|
const { Cc, Ci } = require('chrome');
|
||||||
|
|
||||||
|
ZoteroPane.React.TagSelector = class TagSelectorContainer extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.opts = Object.assign({}, defaults, props);
|
||||||
|
this.selectedTags = new Set();
|
||||||
|
this.updateScope = Promise.resolve;
|
||||||
|
this.filterToScope = true;
|
||||||
|
this.showAutomatic = true;
|
||||||
|
this._notifierID = Zotero.Notifier.registerObserver(
|
||||||
|
this,
|
||||||
|
['collection-item', 'item', 'item-tag', 'tag', 'setting'],
|
||||||
|
'tagSelector'
|
||||||
|
);
|
||||||
|
this._scope = null;
|
||||||
|
this._allTags = null;
|
||||||
|
this.state = null;
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
this.opts = Object.assign({}, this.opts, nextProps);
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
async notify(event, type, ids, extraData) {
|
||||||
|
if (type === 'setting') {
|
||||||
|
if (ids.some(val => val.split('/')[1] == 'tagColors')) {
|
||||||
|
await this.refresh(true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore anything other than deletes in duplicates view
|
||||||
|
if (this.collectionTreeRow.isDuplicates()) {
|
||||||
|
switch (event) {
|
||||||
|
case 'delete':
|
||||||
|
case 'trash':
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore item events other than 'trash'
|
||||||
|
if (type == 'item' && event != 'trash') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// If a selected tag no longer exists, deselect it
|
||||||
|
if (event == 'delete' || event == 'trash' || event == 'modify') {
|
||||||
|
for (let tag of this.selectedTags) {
|
||||||
|
if (tag == extraData[ids[0]].old.tag) {
|
||||||
|
this.selectedTags.delete(tag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.refresh(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == 'add') {
|
||||||
|
if (type == 'item-tag') {
|
||||||
|
let tagObjs = ids
|
||||||
|
// Get tag name and type
|
||||||
|
.map(x => extraData[x])
|
||||||
|
// Ignore tag adds for items not in the current library, if there is one
|
||||||
|
.filter(x => {
|
||||||
|
if (!this._libraryID) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return x.libraryID == this._libraryID;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (tagObjs.length) {
|
||||||
|
this.insertSorted(tagObjs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, just update the tag selector
|
||||||
|
return this.updateScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
async refresh(fetch) {
|
||||||
|
let t = new Date;
|
||||||
|
|
||||||
|
if(this._allTags === null) {
|
||||||
|
fetch = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fetch) {
|
||||||
|
Zotero.debug('Reloading tags selector');
|
||||||
|
} else {
|
||||||
|
Zotero.debug('Refreshing tags selector');
|
||||||
|
}
|
||||||
|
|
||||||
|
// If new data, rebuild boxes
|
||||||
|
if (fetch) {
|
||||||
|
let tagColors = Zotero.Tags.getColors(this.libraryID);
|
||||||
|
this._allTags = await Zotero.Tags.getAll(this.libraryID, this.showAutomatic ? [0, 1] : [0]);
|
||||||
|
// .tap(() => Zotero.Promise.check(this.mode));
|
||||||
|
|
||||||
|
// Add colored tags that aren't already real tags
|
||||||
|
let regularTags = new Set(this._allTags.map(tag => tag.tag));
|
||||||
|
let coloredTags = Array.from(tagColors.keys());
|
||||||
|
|
||||||
|
coloredTags.filter(ct => !regularTags.has(ct)).forEach(x =>
|
||||||
|
this._allTags.push(Zotero.Tags.cleanData({ tag: x }))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Sort by name
|
||||||
|
this._allTags.sort(function (a, b) {
|
||||||
|
return Zotero.getLocaleCollation().compareString(1, a.tag, b.tag);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this.update();
|
||||||
|
|
||||||
|
Zotero.debug('Loaded tag selector in ' + (new Date - t) + ' ms');
|
||||||
|
|
||||||
|
// var event = new Event('refresh');
|
||||||
|
// this.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
var tags;
|
||||||
|
let flatScopeTags = Array.isArray(this._scope) ? this._scope.map(tag => tag.tag) : [];
|
||||||
|
|
||||||
|
if('libraryID' in this) {
|
||||||
|
var tagColors = Zotero.Tags.getColors(this.libraryID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.filterToScope && Array.isArray(this._scope)) {
|
||||||
|
tags = this._allTags.filter(tag =>
|
||||||
|
flatScopeTags.includes(tag.tag) || (tagColors && tagColors.has(tag.tag))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
tags = this._allTags ? this._allTags.slice(0) : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.opts.searchString) {
|
||||||
|
tags = tags.filter(tag => !!tag.tag.match(new RegExp(this.opts.searchString, 'i')));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.opts.tags = tags.map(t => {
|
||||||
|
let name = t.tag;
|
||||||
|
let selected = this.selectedTags.has(name);
|
||||||
|
let color = tagColors && tagColors.has(name) ? tagColors.get(name).color : '';
|
||||||
|
let disabled = !flatScopeTags.includes(name);
|
||||||
|
return { name, selected, color, disabled };
|
||||||
|
});
|
||||||
|
this.state ? this.setState(this.opts) : this.state = Object.assign({}, this.opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <TagSelector
|
||||||
|
tags={ this.state.tags }
|
||||||
|
searchString={ this.state.searchString }
|
||||||
|
shouldFocus={ this.state.shouldFocus }
|
||||||
|
onSelect={ this.state.viewOnly ? () => {} : this.onTagSelectedHandler.bind(this) }
|
||||||
|
onTagContext={ this.onTagContextHandler.bind(this) }
|
||||||
|
onSearch={ this.onSearchHandler.bind(this) }
|
||||||
|
onSettings={ this.onTagSelectorViewSettingsHandler.bind(this) }
|
||||||
|
/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMode(mode) {
|
||||||
|
this.setState({viewOnly: mode == 'view'});
|
||||||
|
}
|
||||||
|
|
||||||
|
focusTextbox() {
|
||||||
|
this.opts.shouldFocus = true;
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle() {
|
||||||
|
this._isCollapsed = !this._isCollapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
unregister() {
|
||||||
|
ReactDom.unmountComponentAtNode(this.domEl);
|
||||||
|
if (this._notifierID) {
|
||||||
|
Zotero.Notifier.unregisterObserver(this._notifierID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uninit() {
|
||||||
|
this.selectedTags = new Set();
|
||||||
|
this.opts.searchString = '';
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
onTagContextHandler(tag, ev) {
|
||||||
|
let tagContextMenu = document.getElementById('tag-menu');
|
||||||
|
ev.preventDefault();
|
||||||
|
tagContextMenu.openPopup(ev.target, 'end_before', 0, 0, true);
|
||||||
|
this.contextTag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
onTagSelectorViewSettingsHandler(ev) {
|
||||||
|
let settingsContextMenu = document.getElementById('tag-selector-view-settings-menu');
|
||||||
|
ev.preventDefault();
|
||||||
|
settingsContextMenu.openPopup(ev.target, 'end_before', 0, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
onTagSelectedHandler(tag) {
|
||||||
|
if(this.selectedTags.has(tag)) {
|
||||||
|
this.selectedTags.delete(tag);
|
||||||
|
} else {
|
||||||
|
this.selectedTags.add(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if('onSelection' in this.opts && typeof(this.opts.onSelection) === 'function') {
|
||||||
|
this.opts.onSelection(this.selectedTags).then(this.refresh.bind(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchHandler(searchString) {
|
||||||
|
this.opts.searchString = searchString;
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
getTagSelection() {
|
||||||
|
return this.selectedTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearTagSelection() {
|
||||||
|
this.selectedTags = new Set();
|
||||||
|
return this.selectedTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
async openColorPickerWindow() {
|
||||||
|
var io = {
|
||||||
|
libraryID: this.libraryID,
|
||||||
|
name: this.contextTag.name
|
||||||
|
};
|
||||||
|
|
||||||
|
var tagColors = Zotero.Tags.getColors(this.libraryID);
|
||||||
|
if (tagColors.size >= Zotero.Tags.MAX_COLORED_TAGS && !tagColors.has(io.name)) {
|
||||||
|
var ps = Cc['@mozilla.org/embedcomp/prompt-service;1']
|
||||||
|
.getService(Ci.nsIPromptService);
|
||||||
|
ps.alert(null, '', Zotero.getString('pane.tagSelector.maxColoredTags', Zotero.Tags.MAX_COLORED_TAGS));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
io.tagColors = tagColors;
|
||||||
|
|
||||||
|
window.openDialog(
|
||||||
|
'chrome://zotero/content/tagColorChooser.xul',
|
||||||
|
'zotero-tagSelector-colorChooser',
|
||||||
|
'chrome,modal,centerscreen', io
|
||||||
|
);
|
||||||
|
|
||||||
|
// Dialog cancel
|
||||||
|
if (typeof io.color == 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Zotero.Tags.setColor(this.libraryID, io.name, io.color, io.position);
|
||||||
|
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
async openRenamePrompt() {
|
||||||
|
var promptService = Cc['@mozilla.org/embedcomp/prompt-service;1']
|
||||||
|
.getService(Ci.nsIPromptService);
|
||||||
|
|
||||||
|
var newName = { value: this.contextTag.name };
|
||||||
|
var result = promptService.prompt(window,
|
||||||
|
Zotero.getString('pane.tagSelector.rename.title'),
|
||||||
|
Zotero.getString('pane.tagSelector.rename.message'),
|
||||||
|
newName, '', {});
|
||||||
|
|
||||||
|
if (!result || !newName.value || this.contextTag.name == newName.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.selectedTags.has(this.contextTag.name)) {
|
||||||
|
var wasSelected = true;
|
||||||
|
this.selectedTags.delete(this.contextTag.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Zotero.Tags.getID(this.contextTag.name)) {
|
||||||
|
await Zotero.Tags.rename(this.libraryID, this.contextTag.name, newName.value);
|
||||||
|
}
|
||||||
|
// Colored tags don't need to exist, so in that case
|
||||||
|
// just rename the color setting
|
||||||
|
else {
|
||||||
|
let color = Zotero.Tags.getColor(this.libraryID, this.contextTag.name);
|
||||||
|
if (!color) {
|
||||||
|
throw new Error("Can't rename missing tag");
|
||||||
|
}
|
||||||
|
await Zotero.Tags.setColor(this.libraryID, this.contextTag.name, false);
|
||||||
|
await Zotero.Tags.setColor(this.libraryID, newName, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wasSelected) {
|
||||||
|
this.selectedTags.add(newName.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
async openDeletePrompt() {
|
||||||
|
var promptService = Cc['@mozilla.org/embedcomp/prompt-service;1']
|
||||||
|
.getService(Ci.nsIPromptService);
|
||||||
|
|
||||||
|
var confirmed = promptService.confirm(window,
|
||||||
|
Zotero.getString('pane.tagSelector.delete.title'),
|
||||||
|
Zotero.getString('pane.tagSelector.delete.message'));
|
||||||
|
|
||||||
|
if (!confirmed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tagID = Zotero.Tags.getID(this.contextTag.name);
|
||||||
|
|
||||||
|
if (tagID) {
|
||||||
|
await Zotero.Tags.removeFromLibrary(this.libraryID, tagID);
|
||||||
|
}
|
||||||
|
// If only a tag color setting, remove that
|
||||||
|
else {
|
||||||
|
await Zotero.Tags.setColor(this.libraryID, this.contextTag.name, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleFilterToScope(newValue) {
|
||||||
|
this.filterToScope = typeof(newValue) === 'undefined' ? !this.filterToScope : newValue;
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleShowAutomatic(newValue) {
|
||||||
|
this.showAutomatic = typeof(newValue) === 'undefined' ? !this.showAutomatic : newValue;
|
||||||
|
this.refresh(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
deselectAll() {
|
||||||
|
this.selectedTags = new Set();
|
||||||
|
if('onSelection' in this.opts && typeof(this.opts.onSelection) === 'function') {
|
||||||
|
this.opts.onSelection(this.selectedTags).then(this.refresh.bind(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set scope(newScope) {
|
||||||
|
try {
|
||||||
|
this._scope = Array.from(newScope);
|
||||||
|
} catch(e) {
|
||||||
|
this._scope = null;
|
||||||
|
}
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
get label() {
|
||||||
|
let count = this.selectedTags.size;
|
||||||
|
let mod = count === 1 ? 'singular' : count === 0 ? 'none' : 'plural';
|
||||||
|
|
||||||
|
return Zotero.getString('pane.tagSelector.numSelected.' + mod, [count]);
|
||||||
|
}
|
||||||
|
|
||||||
|
onResize() {
|
||||||
|
const COLLECTIONS_HEIGHT = 32; // minimum height of the collections pane and toolbar
|
||||||
|
|
||||||
|
//Zotero.debug('Updating tag selector size');
|
||||||
|
var zoteroPane = document.getElementById('zotero-pane-stack');
|
||||||
|
var splitter = document.getElementById('zotero-tags-splitter');
|
||||||
|
var tagSelector = document.getElementById('zotero-tag-selector');
|
||||||
|
|
||||||
|
// Nothing should be bigger than appcontent's height
|
||||||
|
var max = document.getElementById('appcontent').boxObject.height
|
||||||
|
- splitter.boxObject.height;
|
||||||
|
|
||||||
|
// Shrink tag selector to appcontent's height
|
||||||
|
var maxTS = max - COLLECTIONS_HEIGHT;
|
||||||
|
var tsHeight = parseInt(tagSelector.getAttribute("height"));
|
||||||
|
if (tsHeight > maxTS) {
|
||||||
|
//Zotero.debug("Limiting tag selector height to appcontent");
|
||||||
|
tagSelector.setAttribute('height', maxTS);
|
||||||
|
}
|
||||||
|
tagSelector.style.height = tsHeight + 'px';
|
||||||
|
|
||||||
|
var height = tagSelector.getBoundingClientRect().height;
|
||||||
|
|
||||||
|
/*Zotero.debug("tagSelector.boxObject.height: " + tagSelector.boxObject.height);
|
||||||
|
Zotero.debug("tagSelector.getAttribute('height'): " + tagSelector.getAttribute('height'));
|
||||||
|
Zotero.debug("zoteroPane.boxObject.height: " + zoteroPane.boxObject.height);
|
||||||
|
Zotero.debug("zoteroPane.getAttribute('height'): " + zoteroPane.getAttribute('height'));*/
|
||||||
|
|
||||||
|
|
||||||
|
// Don't let the Z-pane jump back down to its previous height
|
||||||
|
// (if shrinking or hiding the tag selector let it clear the min-height)
|
||||||
|
if (zoteroPane.getAttribute('height') < zoteroPane.boxObject.height) {
|
||||||
|
//Zotero.debug("Setting Zotero pane height attribute to " + zoteroPane.boxObject.height);
|
||||||
|
zoteroPane.setAttribute('height', zoteroPane.boxObject.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tagSelector.getAttribute('collapsed') == 'true') {
|
||||||
|
// 32px is the default Z pane min-height in overlay.css
|
||||||
|
height = 32;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// tS.boxObject.height doesn't exist at startup, so get from attribute
|
||||||
|
if (!height) {
|
||||||
|
height = parseInt(tagSelector.getAttribute('height'));
|
||||||
|
}
|
||||||
|
// 121px seems to be enough room for the toolbar and collections
|
||||||
|
// tree at minimum height
|
||||||
|
height = height + COLLECTIONS_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Zotero.debug('Setting Zotero pane minheight to ' + height);
|
||||||
|
zoteroPane.setAttribute('minheight', height);
|
||||||
|
|
||||||
|
if (this.isShowing() && !this.isFullScreen()) {
|
||||||
|
zoteroPane.setAttribute('savedHeight', zoteroPane.boxObject.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix bug whereby resizing the Z pane downward after resizing
|
||||||
|
// the tag selector up and then down sometimes caused the Z pane to
|
||||||
|
// stay at a fixed size and get pushed below the bottom
|
||||||
|
tagSelector.height++;
|
||||||
|
tagSelector.height--;
|
||||||
|
}
|
||||||
|
|
||||||
|
static init(domEl, opts) {
|
||||||
|
var ref;
|
||||||
|
console.log(domEl.style);
|
||||||
|
ReactDom.render(<TagSelectorContainer ref={c => ref = c } {...opts} />, domEl);
|
||||||
|
ref.domEl = domEl;
|
||||||
|
new MutationObserver(ref.onResize).observe(domEl, {attributes: true, attributeFilter: ['height']});
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
58
chrome/content/zotero/reactUI/tagSelector.xul
Normal file
58
chrome/content/zotero/reactUI/tagSelector.xul
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright © 2017 Center for History and New Media
|
||||||
|
George Mason University, Fairfax, Virginia, USA
|
||||||
|
http://zotero.org
|
||||||
|
|
||||||
|
This file is part of Zotero.
|
||||||
|
|
||||||
|
Zotero is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Zotero is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
-->
|
||||||
|
<!DOCTYPE overlay [
|
||||||
|
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd"> %globalDTD;
|
||||||
|
<!ENTITY % zoteroDTD SYSTEM "chrome://zotero/locale/zotero.dtd"> %zoteroDTD;
|
||||||
|
]>
|
||||||
|
|
||||||
|
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
<menupopup id="tag-menu">
|
||||||
|
<menuitem label="&zotero.tagSelector.assignColor;"
|
||||||
|
oncommand="ZoteroPane_Local.tagSelector.openColorPickerWindow(); event.stopPropagation();"/>
|
||||||
|
<menuitem label="&zotero.tagSelector.renameTag;"
|
||||||
|
oncommand="ZoteroPane_Local.tagSelector.openRenamePrompt(); event.stopPropagation();"/>
|
||||||
|
<menuitem label="&zotero.tagSelector.deleteTag;"
|
||||||
|
oncommand="ZoteroPane_Local.tagSelector.openDeletePrompt(); event.stopPropagation();"/>
|
||||||
|
</menupopup>
|
||||||
|
<menupopup id="tag-selector-view-settings-menu"
|
||||||
|
onpopupshowing="
|
||||||
|
document.getElementById('show-automatic').setAttribute('checked', ZoteroPane_Local.tagSelector.showAutomatic);
|
||||||
|
document.getElementById('display-all-tags').setAttribute('checked', !ZoteroPane_Local.tagSelector.filterToScope);
|
||||||
|
document.getElementById('num-selected').label = ZoteroPane_Local.tagSelector.label">
|
||||||
|
<menuitem id="num-selected" disabled="true"/>
|
||||||
|
<menuitem id="deselect-all" label="&zotero.tagSelector.clearAll;"
|
||||||
|
oncommand="ZoteroPane_Local.tagSelector.deselectAll(); event.stopPropagation();"/>
|
||||||
|
<menuseparator/>
|
||||||
|
<menuitem id="show-automatic" label="&zotero.tagSelector.showAutomatic;" type="checkbox"
|
||||||
|
oncommand="ZoteroPane_Local.tagSelector.toggleShowAutomatic(); event.stopPropagation();"/>
|
||||||
|
<menuitem
|
||||||
|
id="display-all-tags"
|
||||||
|
label="&zotero.tagSelector.displayAllInLibrary;"
|
||||||
|
type="checkbox"
|
||||||
|
oncommand="ZoteroPane_Local.tagSelector.toggleFilterToScope(); event.stopPropagation();"
|
||||||
|
/>
|
||||||
|
</menupopup>
|
||||||
|
</overlay>
|
40
chrome/content/zotero/reactUI/zoteroPane.js
Normal file
40
chrome/content/zotero/reactUI/zoteroPane.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright © 2018 Center for History and New Media
|
||||||
|
George Mason University, Fairfax, Virginia, USA
|
||||||
|
http://zotero.org
|
||||||
|
|
||||||
|
This file is part of Zotero.
|
||||||
|
|
||||||
|
Zotero is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Zotero is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
ZoteroPane.React = {
|
||||||
|
init() {
|
||||||
|
var tagSelector = document.getElementById('zotero-tag-selector');
|
||||||
|
ZoteroPane_Local.tagSelector = ZoteroPane.React.TagSelector.init(tagSelector, {
|
||||||
|
onSelection: ZoteroPane_Local.updateTagFilter.bind(ZoteroPane_Local)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
ZoteroPane_Local.tagSelector.unregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
35
chrome/content/zotero/reactUI/zoteroPane.xul
Normal file
35
chrome/content/zotero/reactUI/zoteroPane.xul
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright © 2018 Center for History and New Media
|
||||||
|
George Mason University, Fairfax, Virginia, USA
|
||||||
|
http://zotero.org
|
||||||
|
|
||||||
|
This file is part of Zotero.
|
||||||
|
|
||||||
|
Zotero is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Zotero is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
-->
|
||||||
|
<?xml-stylesheet href="chrome://zotero/skin/zotero-react-client.css"?>
|
||||||
|
<?xul-overlay href="chrome://zotero/content/reactUI/tagSelector.xul"?>
|
||||||
|
|
||||||
|
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||||
|
<script src="chrome://zotero/content/include.js"></script>
|
||||||
|
|
||||||
|
<script src="zoteroPane.js"></script>
|
||||||
|
|
||||||
|
<script src="containers/tag-selector.js"></script>
|
||||||
|
</overlay>
|
|
@ -287,4 +287,7 @@
|
||||||
<stack id="zotero-pane-stack" fullscreenmode="true" flex="1"/>
|
<stack id="zotero-pane-stack" fullscreenmode="true" flex="1"/>
|
||||||
</vbox>
|
</vbox>
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
|
<menupopup id="tag-menu"/>
|
||||||
|
<menupopup id="tag-selector-view-settings-menu"/>
|
||||||
</window>
|
</window>
|
||||||
|
|
|
@ -73,6 +73,7 @@ Zotero.Notifier = new function(){
|
||||||
if (priority) {
|
if (priority) {
|
||||||
msg += " with priority " + priority;
|
msg += " with priority " + priority;
|
||||||
}
|
}
|
||||||
|
Zotero.debug(msg);
|
||||||
_observers[hash] = {
|
_observers[hash] = {
|
||||||
ref: ref,
|
ref: ref,
|
||||||
types: types,
|
types: types,
|
||||||
|
|
|
@ -58,8 +58,6 @@ var ZoteroPane = new function()
|
||||||
|
|
||||||
this.document = document;
|
this.document = document;
|
||||||
|
|
||||||
const COLLECTIONS_HEIGHT = 32; // minimum height of the collections pane and toolbar
|
|
||||||
|
|
||||||
var self = this,
|
var self = this,
|
||||||
_loaded = false, _madeVisible = false,
|
_loaded = false, _madeVisible = false,
|
||||||
titlebarcolorState, titleState, observerService,
|
titlebarcolorState, titleState, observerService,
|
||||||
|
@ -171,11 +169,6 @@ var ZoteroPane = new function()
|
||||||
itemsTree.addEventListener("mousedown", ZoteroPane_Local.onTreeMouseDown, true);
|
itemsTree.addEventListener("mousedown", ZoteroPane_Local.onTreeMouseDown, true);
|
||||||
itemsTree.addEventListener("click", ZoteroPane_Local.onTreeClick, true);
|
itemsTree.addEventListener("click", ZoteroPane_Local.onTreeClick, true);
|
||||||
|
|
||||||
var tagSelector = document.getElementById('zotero-tag-selector');
|
|
||||||
tagSelector.onchange = function () {
|
|
||||||
return ZoteroPane_Local.updateTagFilter();
|
|
||||||
};
|
|
||||||
|
|
||||||
Zotero.Keys.windowInit(document);
|
Zotero.Keys.windowInit(document);
|
||||||
|
|
||||||
if (Zotero.restoreFromServer) {
|
if (Zotero.restoreFromServer) {
|
||||||
|
@ -240,6 +233,7 @@ var ZoteroPane = new function()
|
||||||
}
|
}
|
||||||
catch (e) {}
|
catch (e) {}
|
||||||
}
|
}
|
||||||
|
ZoteroPane.React.init();
|
||||||
|
|
||||||
if (Zotero.openPane) {
|
if (Zotero.openPane) {
|
||||||
Zotero.openPane = false;
|
Zotero.openPane = false;
|
||||||
|
@ -351,8 +345,7 @@ var ZoteroPane = new function()
|
||||||
this.serializePersist();
|
this.serializePersist();
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagSelector = document.getElementById('zotero-tag-selector');
|
ZoteroPane_Local.React.destroy();
|
||||||
tagSelector.unregister();
|
|
||||||
|
|
||||||
if(this.collectionsView) this.collectionsView.unregister();
|
if(this.collectionsView) this.collectionsView.unregister();
|
||||||
if(this.itemsView) this.itemsView.unregister();
|
if(this.itemsView) this.itemsView.unregister();
|
||||||
|
@ -1106,85 +1099,17 @@ var ZoteroPane = new function()
|
||||||
// and focus filter textbox
|
// and focus filter textbox
|
||||||
if (showing) {
|
if (showing) {
|
||||||
yield this.setTagScope();
|
yield this.setTagScope();
|
||||||
tagSelector.focusTextbox();
|
ZoteroPane_Local.tagSelector.focusTextbox();
|
||||||
}
|
}
|
||||||
// If hiding, clear selection
|
// If hiding, clear selection
|
||||||
else {
|
else {
|
||||||
tagSelector.uninit();
|
ZoteroPane_Local.tagSelector.uninit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
this.updateTagSelectorSize = function () {
|
this.updateTagSelectorSize = function () {
|
||||||
//Zotero.debug('Updating tag selector size');
|
|
||||||
var zoteroPane = document.getElementById('zotero-pane-stack');
|
|
||||||
var splitter = document.getElementById('zotero-tags-splitter');
|
|
||||||
var tagSelector = document.getElementById('zotero-tag-selector');
|
|
||||||
|
|
||||||
// Nothing should be bigger than appcontent's height
|
|
||||||
var max = document.getElementById('appcontent').boxObject.height
|
|
||||||
- splitter.boxObject.height;
|
|
||||||
|
|
||||||
// Shrink tag selector to appcontent's height
|
|
||||||
var maxTS = max - COLLECTIONS_HEIGHT;
|
|
||||||
if (parseInt(tagSelector.getAttribute("height")) > maxTS) {
|
|
||||||
//Zotero.debug("Limiting tag selector height to appcontent");
|
|
||||||
tagSelector.setAttribute('height', maxTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
var height = tagSelector.boxObject.height;
|
|
||||||
|
|
||||||
|
|
||||||
/*Zotero.debug("tagSelector.boxObject.height: " + tagSelector.boxObject.height);
|
|
||||||
Zotero.debug("tagSelector.getAttribute('height'): " + tagSelector.getAttribute('height'));
|
|
||||||
Zotero.debug("zoteroPane.boxObject.height: " + zoteroPane.boxObject.height);
|
|
||||||
Zotero.debug("zoteroPane.getAttribute('height'): " + zoteroPane.getAttribute('height'));*/
|
|
||||||
|
|
||||||
|
|
||||||
// Don't let the Z-pane jump back down to its previous height
|
|
||||||
// (if shrinking or hiding the tag selector let it clear the min-height)
|
|
||||||
if (zoteroPane.getAttribute('height') < zoteroPane.boxObject.height) {
|
|
||||||
//Zotero.debug("Setting Zotero pane height attribute to " + zoteroPane.boxObject.height);
|
|
||||||
zoteroPane.setAttribute('height', zoteroPane.boxObject.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tagSelector.getAttribute('collapsed') == 'true') {
|
|
||||||
// 32px is the default Z pane min-height in overlay.css
|
|
||||||
height = 32;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// tS.boxObject.height doesn't exist at startup, so get from attribute
|
|
||||||
if (!height) {
|
|
||||||
height = parseInt(tagSelector.getAttribute('height'));
|
|
||||||
}
|
|
||||||
// 121px seems to be enough room for the toolbar and collections
|
|
||||||
// tree at minimum height
|
|
||||||
height = height + COLLECTIONS_HEIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Zotero.debug('Setting Zotero pane minheight to ' + height);
|
|
||||||
zoteroPane.setAttribute('minheight', height);
|
|
||||||
|
|
||||||
if (this.isShowing() && !this.isFullScreen()) {
|
|
||||||
zoteroPane.setAttribute('savedHeight', zoteroPane.boxObject.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix bug whereby resizing the Z pane downward after resizing
|
|
||||||
// the tag selector up and then down sometimes caused the Z pane to
|
|
||||||
// stay at a fixed size and get pushed below the bottom
|
|
||||||
tagSelector.height++;
|
|
||||||
tagSelector.height--;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getTagSelection() {
|
|
||||||
var tagSelector = document.getElementById('zotero-tag-selector');
|
|
||||||
return tagSelector.selection ? tagSelector.selection : new Set();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.clearTagSelection = function () {
|
|
||||||
document.getElementById('zotero-tag-selector').deselectAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1193,7 +1118,7 @@ var ZoteroPane = new function()
|
||||||
*/
|
*/
|
||||||
this.updateTagFilter = Zotero.Promise.coroutine(function* () {
|
this.updateTagFilter = Zotero.Promise.coroutine(function* () {
|
||||||
if (this.itemsView) {
|
if (this.itemsView) {
|
||||||
yield this.itemsView.setFilter('tags', getTagSelection());
|
yield this.itemsView.setFilter('tags', ZoteroPane_Local.tagSelector.getTagSelection());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1212,23 +1137,23 @@ var ZoteroPane = new function()
|
||||||
*
|
*
|
||||||
* Passed to the items tree to trigger on changes
|
* Passed to the items tree to trigger on changes
|
||||||
*/
|
*/
|
||||||
this.setTagScope = Zotero.Promise.coroutine(function* () {
|
this.setTagScope = async function () {
|
||||||
var collectionTreeRow = this.getCollectionTreeRow();
|
var collectionTreeRow = self.getCollectionTreeRow();
|
||||||
var tagSelector = document.getElementById('zotero-tag-selector');
|
var tagSelector = document.getElementById('zotero-tag-selector');
|
||||||
if (this.tagSelectorShown()) {
|
if (self.tagSelectorShown()) {
|
||||||
Zotero.debug('Updating tag selector with current tags');
|
Zotero.debug('Updating tag selector with current tags');
|
||||||
if (collectionTreeRow.editable) {
|
if (collectionTreeRow.editable) {
|
||||||
tagSelector.mode = 'edit';
|
ZoteroPane_Local.tagSelector.setMode('edit');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tagSelector.mode = 'view';
|
ZoteroPane_Local.tagSelector.setMode('view');
|
||||||
}
|
}
|
||||||
tagSelector.collectionTreeRow = collectionTreeRow;
|
ZoteroPane_Local.tagSelector.collectionTreeRow = collectionTreeRow;
|
||||||
tagSelector.updateScope = () => this.setTagScope();
|
ZoteroPane_Local.tagSelector.updateScope = self.setTagScope;
|
||||||
tagSelector.libraryID = collectionTreeRow.ref.libraryID;
|
ZoteroPane_Local.tagSelector.libraryID = collectionTreeRow.ref.libraryID;
|
||||||
tagSelector.scope = yield collectionTreeRow.getChildTags();
|
ZoteroPane_Local.tagSelector.scope = await collectionTreeRow.getChildTags();
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
|
||||||
this.onCollectionSelected = function () {
|
this.onCollectionSelected = function () {
|
||||||
|
@ -1280,7 +1205,7 @@ var ZoteroPane = new function()
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
collectionTreeRow.setSearch('');
|
collectionTreeRow.setSearch('');
|
||||||
collectionTreeRow.setTags(getTagSelection());
|
collectionTreeRow.setTags(ZoteroPane_Local.tagSelector.getTagSelection());
|
||||||
|
|
||||||
this._updateToolbarIconsForRow(collectionTreeRow);
|
this._updateToolbarIconsForRow(collectionTreeRow);
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
<?xml-stylesheet href="chrome://zotero/skin/overlay.css" type="text/css"?>
|
<?xml-stylesheet href="chrome://zotero/skin/overlay.css" type="text/css"?>
|
||||||
<?xml-stylesheet href="chrome://zotero-platform/content/overlay.css" type="text/css"?>
|
<?xml-stylesheet href="chrome://zotero-platform/content/overlay.css" type="text/css"?>
|
||||||
|
<?xul-overlay href="chrome://zotero/content/reactUI/zoteroPane.xul"?>
|
||||||
|
|
||||||
<!DOCTYPE overlay [
|
<!DOCTYPE overlay [
|
||||||
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd"> %globalDTD;
|
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd"> %globalDTD;
|
||||||
|
@ -35,7 +36,8 @@
|
||||||
]>
|
]>
|
||||||
|
|
||||||
<overlay id="zotero"
|
<overlay id="zotero"
|
||||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||||
|
xmlns:html="http://www.w3.org/1999/xhtml">
|
||||||
|
|
||||||
<script src="include.js"/>
|
<script src="include.js"/>
|
||||||
<script src="zoteroPane.js" type="application/javascript;version=1.8"/>
|
<script src="zoteroPane.js" type="application/javascript;version=1.8"/>
|
||||||
|
@ -304,7 +306,7 @@
|
||||||
ondragover="return ZoteroPane_Local.collectionsView.onDragOver(event)"
|
ondragover="return ZoteroPane_Local.collectionsView.onDragOver(event)"
|
||||||
ondrop="return ZoteroPane_Local.collectionsView.onDrop(event)"/>
|
ondrop="return ZoteroPane_Local.collectionsView.onDrop(event)"/>
|
||||||
</tree>
|
</tree>
|
||||||
<splitter id="zotero-tags-splitter" onmouseup="ZoteroPane_Local.updateTagSelectorSize()" collapse="after"
|
<splitter id="zotero-tags-splitter" collapse="after"
|
||||||
zotero-persist="state">
|
zotero-persist="state">
|
||||||
<grippy oncommand="ZoteroPane_Local.toggleTagSelector()"/>
|
<grippy oncommand="ZoteroPane_Local.toggleTagSelector()"/>
|
||||||
</splitter>
|
</splitter>
|
||||||
|
@ -314,7 +316,7 @@
|
||||||
|
|
||||||
TODO: deal with this some other way?
|
TODO: deal with this some other way?
|
||||||
-->
|
-->
|
||||||
<zoterotagselector id="zotero-tag-selector" zotero-persist="height,collapsed,showAutomatic,filterToScope"/>
|
<html:div id="zotero-tag-selector" zotero-persist="height,collapsed,showAutomatic,filterToScope"/>
|
||||||
</vbox>
|
</vbox>
|
||||||
|
|
||||||
<splitter id="zotero-collections-splitter" resizebefore="closest" resizeafter="closest" collapse="before"
|
<splitter id="zotero-collections-splitter" resizebefore="closest" resizeafter="closest" collapse="before"
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* Font sizes */
|
/* Font sizes */
|
||||||
*[zoteroFontSize=medium] #zotero-tb-search, *[zoteroFontSize=large] #zotero-tb-search,
|
*[zoteroFontSize=medium] #zotero-tb-search, *[zoteroFontSize=large] #zotero-tb-search,
|
||||||
*[zoteroFontSize=medium] zoterotagselector textbox, *[zoteroFontSize=large] zoterotagselector textbox
|
|
||||||
{
|
{
|
||||||
font-size: 1em !important;
|
font-size: 1em !important;
|
||||||
}
|
}
|
||||||
|
@ -81,11 +80,6 @@ zoterosearch
|
||||||
-moz-binding: url('chrome://zotero/content/bindings/zoterosearch.xml#search-box');
|
-moz-binding: url('chrome://zotero/content/bindings/zoterosearch.xml#search-box');
|
||||||
}
|
}
|
||||||
|
|
||||||
zoterotagselector
|
|
||||||
{
|
|
||||||
-moz-binding: url('chrome://zotero/content/bindings/tagselector.xml#tag-selector');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
zoterosearchcondition
|
zoterosearchcondition
|
||||||
{
|
{
|
||||||
|
|
326
package-lock.json
generated
326
package-lock.json
generated
|
@ -409,6 +409,29 @@
|
||||||
"esutils": "^2.0.0"
|
"esutils": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-helper-function-name": {
|
||||||
|
"version": "6.24.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
|
||||||
|
"integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-helper-get-function-arity": "^6.24.1",
|
||||||
|
"babel-runtime": "^6.22.0",
|
||||||
|
"babel-template": "^6.24.1",
|
||||||
|
"babel-traverse": "^6.24.1",
|
||||||
|
"babel-types": "^6.24.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"babel-helper-get-function-arity": {
|
||||||
|
"version": "6.24.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
|
||||||
|
"integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "^6.22.0",
|
||||||
|
"babel-types": "^6.24.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-helpers": {
|
"babel-helpers": {
|
||||||
"version": "6.24.1",
|
"version": "6.24.1",
|
||||||
"resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
|
"resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
|
||||||
|
@ -436,7 +459,7 @@
|
||||||
},
|
},
|
||||||
"babel-plugin-syntax-class-properties": {
|
"babel-plugin-syntax-class-properties": {
|
||||||
"version": "6.13.0",
|
"version": "6.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
|
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
|
||||||
"integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=",
|
"integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -476,6 +499,18 @@
|
||||||
"integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
|
"integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"babel-plugin-transform-class-properties": {
|
||||||
|
"version": "6.24.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz",
|
||||||
|
"integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-helper-function-name": "^6.24.1",
|
||||||
|
"babel-plugin-syntax-class-properties": "^6.8.0",
|
||||||
|
"babel-runtime": "^6.22.0",
|
||||||
|
"babel-template": "^6.24.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-plugin-transform-es2015-modules-commonjs": {
|
"babel-plugin-transform-es2015-modules-commonjs": {
|
||||||
"version": "6.26.0",
|
"version": "6.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz",
|
||||||
|
@ -841,11 +876,6 @@
|
||||||
"hoek": "2.x.x"
|
"hoek": "2.x.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bootstrap-sass": {
|
|
||||||
"version": "3.3.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/bootstrap-sass/-/bootstrap-sass-3.3.7.tgz",
|
|
||||||
"integrity": "sha1-ZZbHq0D2Y3OTMjqwvIDQZPxjBJg="
|
|
||||||
},
|
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.8",
|
"version": "1.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
|
||||||
|
@ -1159,6 +1189,11 @@
|
||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"classnames": {
|
||||||
|
"version": "2.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
|
||||||
|
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
|
||||||
|
},
|
||||||
"cliui": {
|
"cliui": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
|
||||||
|
@ -1350,9 +1385,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"create-react-class": {
|
"create-react-class": {
|
||||||
"version": "15.6.0",
|
"version": "15.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz",
|
||||||
"integrity": "sha1-q0SEl8JlZuHilBPogyB9V8/nvtQ=",
|
"integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"fbjs": "^0.8.9",
|
"fbjs": "^0.8.9",
|
||||||
"loose-envify": "^1.3.1",
|
"loose-envify": "^1.3.1",
|
||||||
|
@ -1444,11 +1479,6 @@
|
||||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
|
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"deep-diff": {
|
|
||||||
"version": "0.3.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.4.tgz",
|
|
||||||
"integrity": "sha1-qsXDmVIjar5fA3ojSQYLoBsArkg="
|
|
||||||
},
|
|
||||||
"deep-eql": {
|
"deep-eql": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
|
||||||
|
@ -1458,11 +1488,6 @@
|
||||||
"type-detect": "^4.0.0"
|
"type-detect": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deep-equal": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
|
|
||||||
},
|
|
||||||
"define-properties": {
|
"define-properties": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz",
|
||||||
|
@ -1647,11 +1672,6 @@
|
||||||
"is-symbol": "^1.0.1"
|
"is-symbol": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es6-promise": {
|
|
||||||
"version": "3.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
|
||||||
"integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM="
|
|
||||||
},
|
|
||||||
"escape-string-regexp": {
|
"escape-string-regexp": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
|
@ -1768,9 +1788,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"fbjs": {
|
"fbjs": {
|
||||||
"version": "0.8.12",
|
"version": "0.8.17",
|
||||||
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.12.tgz",
|
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
|
||||||
"integrity": "sha1-ELXZL3bUVXX9Y6IX1OoCvqL47QQ=",
|
"integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"core-js": "^1.0.0",
|
"core-js": "^1.0.0",
|
||||||
"isomorphic-fetch": "^2.1.1",
|
"isomorphic-fetch": "^2.1.1",
|
||||||
|
@ -1778,7 +1798,14 @@
|
||||||
"object-assign": "^4.1.0",
|
"object-assign": "^4.1.0",
|
||||||
"promise": "^7.1.1",
|
"promise": "^7.1.1",
|
||||||
"setimmediate": "^1.0.5",
|
"setimmediate": "^1.0.5",
|
||||||
"ua-parser-js": "^0.7.9"
|
"ua-parser-js": "^0.7.18"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ua-parser-js": {
|
||||||
|
"version": "0.7.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.19.tgz",
|
||||||
|
"integrity": "sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"filename-regex": {
|
"filename-regex": {
|
||||||
|
@ -1810,19 +1837,6 @@
|
||||||
"pinkie-promise": "^2.0.0"
|
"pinkie-promise": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"floatthead": {
|
|
||||||
"version": "1.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/floatthead/-/floatthead-1.4.0.tgz",
|
|
||||||
"integrity": "sha1-0s/94CBGWe1TcDQFDOluq/5z6tM="
|
|
||||||
},
|
|
||||||
"flux-standard-action": {
|
|
||||||
"version": "0.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/flux-standard-action/-/flux-standard-action-0.6.1.tgz",
|
|
||||||
"integrity": "sha1-bzQhG5SDTqHDzDD056+tPQ+/caI=",
|
|
||||||
"requires": {
|
|
||||||
"lodash.isplainobject": "^3.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"for-in": {
|
"for-in": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
||||||
|
@ -2672,17 +2686,6 @@
|
||||||
"integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
|
"integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"history": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/history/-/history-2.1.2.tgz",
|
|
||||||
"integrity": "sha1-SqLeiXoOSGfkU5hDvm7Nsphr/ew=",
|
|
||||||
"requires": {
|
|
||||||
"deep-equal": "^1.0.0",
|
|
||||||
"invariant": "^2.0.0",
|
|
||||||
"query-string": "^3.0.0",
|
|
||||||
"warning": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hmac-drbg": {
|
"hmac-drbg": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||||
|
@ -2700,11 +2703,6 @@
|
||||||
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
|
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"hoist-non-react-statics": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz",
|
|
||||||
"integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs="
|
|
||||||
},
|
|
||||||
"home-or-tmp": {
|
"home-or-tmp": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
|
||||||
|
@ -2821,6 +2819,7 @@
|
||||||
"version": "2.2.2",
|
"version": "2.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz",
|
||||||
"integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=",
|
"integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.0.0"
|
"loose-envify": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
@ -3047,11 +3046,6 @@
|
||||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
|
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"jquery": {
|
|
||||||
"version": "2.2.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz",
|
|
||||||
"integrity": "sha1-LInWiJterFIqfuoywUUhVZxsvwI="
|
|
||||||
},
|
|
||||||
"js-base64": {
|
"js-base64": {
|
||||||
"version": "2.4.5",
|
"version": "2.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.5.tgz",
|
||||||
|
@ -3223,25 +3217,6 @@
|
||||||
"astw": "^2.0.0"
|
"astw": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"libzotero": {
|
|
||||||
"version": "0.1.13",
|
|
||||||
"resolved": "https://registry.npmjs.org/libzotero/-/libzotero-0.1.13.tgz",
|
|
||||||
"integrity": "sha1-QQhFtsHa9jmSZwIfnLw0t8SBuzI=",
|
|
||||||
"requires": {
|
|
||||||
"es6-promise": "^3.1.2",
|
|
||||||
"node-fetch": "^1.6.0",
|
|
||||||
"spark-md5": "^2.0.2",
|
|
||||||
"striptags": "^2.1.1",
|
|
||||||
"whatwg-fetch": "^1.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"whatwg-fetch": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-1.1.1.tgz",
|
|
||||||
"integrity": "sha1-rDydOfMgxtzlM5lp0FTvQ90zMxk="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"load-json-file": {
|
"load-json-file": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
||||||
|
@ -3258,12 +3233,8 @@
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.4",
|
"version": "4.17.4",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
|
||||||
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4="
|
"integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
|
||||||
},
|
"dev": true
|
||||||
"lodash-es": {
|
|
||||||
"version": "4.17.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz",
|
|
||||||
"integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc="
|
|
||||||
},
|
},
|
||||||
"lodash._baseassign": {
|
"lodash._baseassign": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
|
@ -3287,11 +3258,6 @@
|
||||||
"integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=",
|
"integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"lodash._basefor": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz",
|
|
||||||
"integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI="
|
|
||||||
},
|
|
||||||
"lodash._getnative": {
|
"lodash._getnative": {
|
||||||
"version": "3.9.1",
|
"version": "3.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
|
||||||
|
@ -3336,22 +3302,14 @@
|
||||||
"lodash.isarguments": {
|
"lodash.isarguments": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
||||||
"integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo="
|
"integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"lodash.isarray": {
|
"lodash.isarray": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
|
||||||
"integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U="
|
"integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=",
|
||||||
},
|
"dev": true
|
||||||
"lodash.isplainobject": {
|
|
||||||
"version": "3.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-3.2.0.tgz",
|
|
||||||
"integrity": "sha1-moI4rhayAEMpYM1zRlEtASP79MU=",
|
|
||||||
"requires": {
|
|
||||||
"lodash._basefor": "^3.0.0",
|
|
||||||
"lodash.isarguments": "^3.0.0",
|
|
||||||
"lodash.keysin": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"lodash.keys": {
|
"lodash.keys": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
|
@ -3364,15 +3322,6 @@
|
||||||
"lodash.isarray": "^3.0.0"
|
"lodash.isarray": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lodash.keysin": {
|
|
||||||
"version": "3.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-3.0.8.tgz",
|
|
||||||
"integrity": "sha1-IsRJPrvtsUJ5YqVLRFssinZ/tH8=",
|
|
||||||
"requires": {
|
|
||||||
"lodash.isarguments": "^3.0.0",
|
|
||||||
"lodash.isarray": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lodash.memoize": {
|
"lodash.memoize": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
|
||||||
|
@ -4093,12 +4042,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"prop-types": {
|
"prop-types": {
|
||||||
"version": "15.5.10",
|
"version": "15.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
|
||||||
"integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=",
|
"integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"fbjs": "^0.8.9",
|
"loose-envify": "^1.3.1",
|
||||||
"loose-envify": "^1.3.1"
|
"object-assign": "^4.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pseudomap": {
|
"pseudomap": {
|
||||||
|
@ -4132,14 +4081,6 @@
|
||||||
"integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=",
|
"integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"query-string": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-3.0.3.tgz",
|
|
||||||
"integrity": "sha1-ri4UtNBQcdTpuetIc8NbDc1C5jg=",
|
|
||||||
"requires": {
|
|
||||||
"strict-uri-encode": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"querystring": {
|
"querystring": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
||||||
|
@ -4235,41 +4176,6 @@
|
||||||
"prop-types": "^15.5.10"
|
"prop-types": "^15.5.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-redux": {
|
|
||||||
"version": "4.4.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-4.4.8.tgz",
|
|
||||||
"integrity": "sha1-57wd0QDotk6WrIIS2xEyObni4I8=",
|
|
||||||
"requires": {
|
|
||||||
"create-react-class": "^15.5.1",
|
|
||||||
"hoist-non-react-statics": "^1.0.3",
|
|
||||||
"invariant": "^2.0.0",
|
|
||||||
"lodash": "^4.2.0",
|
|
||||||
"loose-envify": "^1.1.0",
|
|
||||||
"prop-types": "^15.5.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"react-router": {
|
|
||||||
"version": "2.8.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-2.8.1.tgz",
|
|
||||||
"integrity": "sha1-c+lJH2zrMW0Pd5gpCBhj43juTtc=",
|
|
||||||
"requires": {
|
|
||||||
"history": "^2.1.2",
|
|
||||||
"hoist-non-react-statics": "^1.2.0",
|
|
||||||
"invariant": "^2.2.1",
|
|
||||||
"loose-envify": "^1.2.0",
|
|
||||||
"warning": "^3.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"warning": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
|
|
||||||
"integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
|
|
||||||
"requires": {
|
|
||||||
"loose-envify": "^1.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"read-only-stream": {
|
"read-only-stream": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz",
|
||||||
|
@ -4337,46 +4243,6 @@
|
||||||
"strip-indent": "^1.0.1"
|
"strip-indent": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"redux": {
|
|
||||||
"version": "3.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/redux/-/redux-3.7.0.tgz",
|
|
||||||
"integrity": "sha512-GHjaOkEQtQnnuLoYPFkRKHIqs1i1tdTlisu/xUHfk2juzCobSy4STxs4Lz5bPkc07Owb6BeGKx/r76c9IVTkOw==",
|
|
||||||
"requires": {
|
|
||||||
"lodash": "^4.2.1",
|
|
||||||
"lodash-es": "^4.2.1",
|
|
||||||
"loose-envify": "^1.1.0",
|
|
||||||
"symbol-observable": "^1.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"redux-logger": {
|
|
||||||
"version": "2.10.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-2.10.2.tgz",
|
|
||||||
"integrity": "sha1-PFpfCm8yV3wd6t9mVfJX+CxsOTc=",
|
|
||||||
"requires": {
|
|
||||||
"deep-diff": "0.3.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"redux-promise": {
|
|
||||||
"version": "0.5.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/redux-promise/-/redux-promise-0.5.3.tgz",
|
|
||||||
"integrity": "sha1-6X5snTvzdurLebq+bZBtogES1tg=",
|
|
||||||
"requires": {
|
|
||||||
"flux-standard-action": "^0.6.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"redux-router": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/redux-router/-/redux-router-2.1.2.tgz",
|
|
||||||
"integrity": "sha1-A0ckutCPQbr3VNtNIuLYWK22TxE=",
|
|
||||||
"requires": {
|
|
||||||
"deep-equal": "^1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"redux-thunk": {
|
|
||||||
"version": "2.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.2.0.tgz",
|
|
||||||
"integrity": "sha1-5hWhbha0ehmlFXZhM9Hj6Zt4UuU="
|
|
||||||
},
|
|
||||||
"regenerator-runtime": {
|
"regenerator-runtime": {
|
||||||
"version": "0.10.5",
|
"version": "0.10.5",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
|
||||||
|
@ -4664,11 +4530,6 @@
|
||||||
"source-map": "^0.5.6"
|
"source-map": "^0.5.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"spark-md5": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-2.0.2.tgz",
|
|
||||||
"integrity": "sha1-N7djhHdjrn56zvLKUjPQHmSaeLc="
|
|
||||||
},
|
|
||||||
"spdx-correct": {
|
"spdx-correct": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
|
||||||
|
@ -4777,11 +4638,6 @@
|
||||||
"readable-stream": "^2.0.2"
|
"readable-stream": "^2.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strict-uri-encode": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
|
|
||||||
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
|
|
||||||
},
|
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||||
|
@ -4843,11 +4699,6 @@
|
||||||
"get-stdin": "^4.0.1"
|
"get-stdin": "^4.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"striptags": {
|
|
||||||
"version": "2.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/striptags/-/striptags-2.2.1.tgz",
|
|
||||||
"integrity": "sha1-TEULcI1BuL85zyTEn/I0/Gqr/TI="
|
|
||||||
},
|
|
||||||
"subarg": {
|
"subarg": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz",
|
||||||
|
@ -4871,11 +4722,6 @@
|
||||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"symbol-observable": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz",
|
|
||||||
"integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0="
|
|
||||||
},
|
|
||||||
"syntax-error": {
|
"syntax-error": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.3.0.tgz",
|
||||||
|
@ -5021,7 +4867,8 @@
|
||||||
"ua-parser-js": {
|
"ua-parser-js": {
|
||||||
"version": "0.7.12",
|
"version": "0.7.12",
|
||||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.12.tgz",
|
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.12.tgz",
|
||||||
"integrity": "sha1-BMgamb3V3FImPqKdJMa/jUgYpLs="
|
"integrity": "sha1-BMgamb3V3FImPqKdJMa/jUgYpLs=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"umd": {
|
"umd": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
|
@ -5110,19 +4957,6 @@
|
||||||
"indexof": "0.0.1"
|
"indexof": "0.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"w3c-xmlhttprequest": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/w3c-xmlhttprequest/-/w3c-xmlhttprequest-2.1.2.tgz",
|
|
||||||
"integrity": "sha1-8LyJN1YoKOLCubQDZkhqE1H+QaA="
|
|
||||||
},
|
|
||||||
"warning": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/warning/-/warning-2.1.0.tgz",
|
|
||||||
"integrity": "sha1-ISINnGOvx3qMkhEeARr3Bc4MaQE=",
|
|
||||||
"requires": {
|
|
||||||
"loose-envify": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"whatwg-fetch": {
|
"whatwg-fetch": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz",
|
||||||
|
@ -5231,28 +5065,6 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"zotero-web-library": {
|
|
||||||
"version": "0.9.4-alpha",
|
|
||||||
"resolved": "https://registry.npmjs.org/zotero-web-library/-/zotero-web-library-0.9.4-alpha.tgz",
|
|
||||||
"integrity": "sha1-AbLMXXqmsDEbhNZeLsc6llBdqS4=",
|
|
||||||
"requires": {
|
|
||||||
"bootstrap-sass": "^3.3.6",
|
|
||||||
"floatthead": "1.4.0",
|
|
||||||
"history": "<3.0.0",
|
|
||||||
"jquery": "^2.2.4",
|
|
||||||
"libzotero": "^0.1.8",
|
|
||||||
"react": "^15.3.2",
|
|
||||||
"react-dom": "^15.3.2",
|
|
||||||
"react-redux": "^4.4.5",
|
|
||||||
"react-router": "<3.0.0",
|
|
||||||
"redux": "^3.6.0",
|
|
||||||
"redux-logger": "^2.6.1",
|
|
||||||
"redux-promise": "^0.5.3",
|
|
||||||
"redux-router": "^2.1.2",
|
|
||||||
"redux-thunk": "^2.1.0",
|
|
||||||
"w3c-xmlhttprequest": "^2.1.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,20 +16,21 @@
|
||||||
"license": "",
|
"license": "",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bluebird": "^3.5.1",
|
"bluebird": "^3.5.1",
|
||||||
|
"classnames": "^2.2.6",
|
||||||
|
"prop-types": "^15.6.2",
|
||||||
"react": "^15.6.2",
|
"react": "^15.6.2",
|
||||||
"react-dom": "^15.6.2",
|
"react-dom": "^15.6.2"
|
||||||
"zotero-web-library": "^0.9.4-alpha"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-core": "^6.26.0",
|
"babel-core": "^6.26.0",
|
||||||
"babel-plugin-syntax-async-generators": "^6.13.0",
|
"babel-plugin-syntax-async-generators": "^6.13.0",
|
||||||
"babel-plugin-syntax-class-properties": "^6.13.0",
|
|
||||||
"babel-plugin-syntax-decorators": "^6.13.0",
|
"babel-plugin-syntax-decorators": "^6.13.0",
|
||||||
"babel-plugin-syntax-do-expressions": "^6.13.0",
|
"babel-plugin-syntax-do-expressions": "^6.13.0",
|
||||||
"babel-plugin-syntax-export-extensions": "^6.13.0",
|
"babel-plugin-syntax-export-extensions": "^6.13.0",
|
||||||
"babel-plugin-syntax-flow": "^6.13.0",
|
"babel-plugin-syntax-flow": "^6.13.0",
|
||||||
"babel-plugin-syntax-jsx": "^6.13.0",
|
"babel-plugin-syntax-jsx": "^6.13.0",
|
||||||
"babel-plugin-syntax-object-rest-spread": "^6.13.0",
|
"babel-plugin-syntax-object-rest-spread": "^6.13.0",
|
||||||
|
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||||
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
|
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
|
||||||
"babel-preset-react": "^6.16.0",
|
"babel-preset-react": "^6.16.0",
|
||||||
"browserify": "^14.5.0",
|
"browserify": "^14.5.0",
|
||||||
|
|
1
resource/classnames.js
Symbolic link
1
resource/classnames.js
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../node_modules/classnames/index.js
|
1
resource/prop-types.js
Symbolic link
1
resource/prop-types.js
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../node_modules/prop-types/prop-types.js
|
155
resource/react-ui/components/form/input.jsx
Normal file
155
resource/react-ui/components/form/input.jsx
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
/* eslint-disable react/no-deprecated */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const React = require('react');
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
const cx = require('classnames');
|
||||||
|
const { noop } = () => {};
|
||||||
|
|
||||||
|
class Input extends React.PureComponent {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
value: props.value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel(event = null) {
|
||||||
|
this.props.onCancel(this.hasChanged, event);
|
||||||
|
this.hasBeenCancelled = true;
|
||||||
|
this.input.blur();
|
||||||
|
}
|
||||||
|
|
||||||
|
commit(event = null) {
|
||||||
|
this.props.onCommit(this.state.value, this.hasChanged, event);
|
||||||
|
this.hasBeenCommitted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
if(this.input != null) {
|
||||||
|
this.input.focus();
|
||||||
|
this.props.selectOnFocus && this.input.select();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps({ value }) {
|
||||||
|
if (value !== this.props.value) {
|
||||||
|
this.setState({ value });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange({ target }) {
|
||||||
|
this.setState({ value: target.value });
|
||||||
|
this.props.onChange(target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBlur(event) {
|
||||||
|
const shouldCancel = this.props.onBlur(event);
|
||||||
|
if (this.hasBeenCancelled || this.hasBeenCommitted) { return; }
|
||||||
|
shouldCancel ? this.cancel(event) : this.commit(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleFocus(event) {
|
||||||
|
this.props.selectOnFocus && event.target.select();
|
||||||
|
this.props.onFocus(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleKeyDown(event) {
|
||||||
|
switch (event.key) {
|
||||||
|
case 'Escape':
|
||||||
|
this.cancel(event);
|
||||||
|
break;
|
||||||
|
case 'Enter':
|
||||||
|
this.commit(event);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get hasChanged() {
|
||||||
|
return this.state.value !== this.props.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
this.hasBeenCancelled = false;
|
||||||
|
this.hasBeenCommitted = false;
|
||||||
|
const extraProps = Object.keys(this.props).reduce((aggr, key) => {
|
||||||
|
if(key.match(/^(aria-|data-).*/)) {
|
||||||
|
aggr[key] = this.props[key];
|
||||||
|
}
|
||||||
|
return aggr;
|
||||||
|
}, {});
|
||||||
|
const input = <input
|
||||||
|
autoFocus={ this.props.autoFocus }
|
||||||
|
className={ this.props.className }
|
||||||
|
disabled={ this.props.isDisabled }
|
||||||
|
form={ this.props.form }
|
||||||
|
id={ this.props.id }
|
||||||
|
inputMode={ this.props.inputMode }
|
||||||
|
max={ this.props.max }
|
||||||
|
maxLength={ this.props.maxLength }
|
||||||
|
min={ this.props.min }
|
||||||
|
minLength={ this.props.minLength }
|
||||||
|
name={ this.props.name }
|
||||||
|
onBlur={ this.handleBlur.bind(this) }
|
||||||
|
onChange={ this.handleChange.bind(this) }
|
||||||
|
onFocus={ this.handleFocus.bind(this) }
|
||||||
|
onKeyDown={ this.handleKeyDown.bind(this) }
|
||||||
|
placeholder={ this.props.placeholder }
|
||||||
|
readOnly={ this.props.isReadOnly }
|
||||||
|
ref={ input => this.input = input }
|
||||||
|
required={ this.props.isRequired }
|
||||||
|
size={ this.props.size }
|
||||||
|
spellCheck={ this.props.spellCheck }
|
||||||
|
step={ this.props.step }
|
||||||
|
tabIndex={ this.props.tabIndex }
|
||||||
|
type={ this.props.type }
|
||||||
|
value={ this.state.value }
|
||||||
|
{ ...extraProps }
|
||||||
|
/>;
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
className: 'form-control',
|
||||||
|
onBlur: noop,
|
||||||
|
onCancel: noop,
|
||||||
|
onChange: noop,
|
||||||
|
onCommit: noop,
|
||||||
|
onFocus: noop,
|
||||||
|
tabIndex: -1,
|
||||||
|
type: 'text',
|
||||||
|
value: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
autoFocus: PropTypes.bool,
|
||||||
|
className: PropTypes.string,
|
||||||
|
form: PropTypes.string,
|
||||||
|
id: PropTypes.string,
|
||||||
|
inputMode: PropTypes.string,
|
||||||
|
isDisabled: PropTypes.bool,
|
||||||
|
isReadOnly: PropTypes.bool,
|
||||||
|
isRequired: PropTypes.bool,
|
||||||
|
max: PropTypes.number,
|
||||||
|
maxLength: PropTypes.number,
|
||||||
|
min: PropTypes.number,
|
||||||
|
minLength: PropTypes.number,
|
||||||
|
name: PropTypes.string,
|
||||||
|
onBlur: PropTypes.func.isRequired,
|
||||||
|
onCancel: PropTypes.func.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
onCommit: PropTypes.func.isRequired,
|
||||||
|
onFocus: PropTypes.func.isRequired,
|
||||||
|
placeholder: PropTypes.string,
|
||||||
|
selectOnFocus: PropTypes.bool,
|
||||||
|
spellCheck: PropTypes.bool,
|
||||||
|
step: PropTypes.number,
|
||||||
|
tabIndex: PropTypes.number,
|
||||||
|
type: PropTypes.string.isRequired,
|
||||||
|
value: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Input;
|
53
resource/react-ui/components/tag-selector.jsx
Normal file
53
resource/react-ui/components/tag-selector.jsx
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const React = require('react');
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
const TagList = require('./tag-selector/tag-list');
|
||||||
|
const Input = require('./form/input');
|
||||||
|
|
||||||
|
class TagSelector extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="tag-selector">
|
||||||
|
<TagList { ...this.props } />
|
||||||
|
<div className="tag-selector-filter-container">
|
||||||
|
<Input
|
||||||
|
type="search"
|
||||||
|
value={ this.props.searchString }
|
||||||
|
onChange={ this.props.onSearch }
|
||||||
|
className="tag-selector-filter"
|
||||||
|
size="1"
|
||||||
|
/>
|
||||||
|
<button className="tag-selector-actions" onClick={ ev => this.props.onSettings(ev) } />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TagSelector.propTypes = {
|
||||||
|
tags: PropTypes.arrayOf(PropTypes.shape({
|
||||||
|
name: PropTypes.string,
|
||||||
|
selected: PropTypes.bool,
|
||||||
|
color: PropTypes.string,
|
||||||
|
disabled: PropTypes.bool
|
||||||
|
})),
|
||||||
|
searchString: PropTypes.string,
|
||||||
|
shouldFocus: PropTypes.bool,
|
||||||
|
onSelect: PropTypes.func,
|
||||||
|
onTagContext: PropTypes.func,
|
||||||
|
onSearch: PropTypes.func,
|
||||||
|
onSettings: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
TagSelector.defaultProps = {
|
||||||
|
tags: [],
|
||||||
|
searchString: '',
|
||||||
|
shouldFocus: false,
|
||||||
|
onSelect: () => Promise.resolve(),
|
||||||
|
onTagContext: () => Promise.resolve(),
|
||||||
|
onSearch: () => Promise.resolve(),
|
||||||
|
onSettings: () => Promise.resolve()
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = TagSelector;
|
55
resource/react-ui/components/tag-selector/tag-list.jsx
Normal file
55
resource/react-ui/components/tag-selector/tag-list.jsx
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
const React = require('react');
|
||||||
|
const PropTypes = require('prop-types');
|
||||||
|
const cx = require('classnames');
|
||||||
|
|
||||||
|
class TagList extends React.PureComponent {
|
||||||
|
renderTag(index) {
|
||||||
|
const { tags } = this.props;
|
||||||
|
const tag = index < tags.length ?
|
||||||
|
tags[index] : {
|
||||||
|
tag: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
const className = cx('tag-selector-item', {
|
||||||
|
selected: tag.selected,
|
||||||
|
colored: tag.color,
|
||||||
|
});
|
||||||
|
|
||||||
|
let props = {
|
||||||
|
className,
|
||||||
|
onClick: ev => this.props.onSelect(tag.name, ev),
|
||||||
|
onContextMenu: ev => this.props.onTagContext(tag, ev),
|
||||||
|
};
|
||||||
|
|
||||||
|
if(tag.color) {
|
||||||
|
props['style'] = {
|
||||||
|
color: tag.color,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li key={ index } { ...props }>
|
||||||
|
{ tag.name }
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const totalTagCount = this.props.tags.length;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="tag-selector-container"
|
||||||
|
ref={ ref => { this.container = ref } }>
|
||||||
|
<ul className="tag-selector-list">
|
||||||
|
{
|
||||||
|
[...Array(totalTagCount).keys()].map(index => this.renderTag(index))
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = TagList;
|
|
@ -1,5 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var Zotero;
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = ['require'];
|
var EXPORTED_SYMBOLS = ['require'];
|
||||||
|
|
||||||
var require = (function() {
|
var require = (function() {
|
||||||
|
@ -56,21 +58,42 @@ var require = (function() {
|
||||||
window.debug = function (msg) {
|
window.debug = function (msg) {
|
||||||
dump(msg + "\n\n");
|
dump(msg + "\n\n");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getZotero() {
|
||||||
|
if (typeof Zotero === 'undefined') {
|
||||||
|
try {
|
||||||
|
Zotero = Components.classes["@zotero.org/Zotero;1"]
|
||||||
|
.getService(Components.interfaces.nsISupports).wrappedJSObject;
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
return Zotero || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var cons;
|
||||||
|
if (typeof console !== 'undefined') {
|
||||||
|
cons = console;
|
||||||
|
}
|
||||||
|
if (!cons) {
|
||||||
|
cons = {};
|
||||||
|
for (let key of ['log', 'warn', 'error']) {
|
||||||
|
cons[key] = text => {getZotero(); typeof Zotero !== 'undefined' && false && Zotero.debug(`console.${key}: ${text}`)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let globals = {
|
||||||
|
document: typeof document !== 'undefined' && document || {},
|
||||||
|
console: cons,
|
||||||
|
navigator: typeof navigator !== 'undefined' && navigator || {},
|
||||||
|
window,
|
||||||
|
setTimeout: window.setTimeout,
|
||||||
|
clearTimeout: window.clearTimeout,
|
||||||
|
};
|
||||||
|
Object.defineProperty(globals, 'Zotero', { get: getZotero });
|
||||||
var loader = Loader({
|
var loader = Loader({
|
||||||
id: 'zotero/require',
|
id: 'zotero/require',
|
||||||
paths: {
|
paths: {
|
||||||
'': 'resource://zotero/',
|
'': 'resource://zotero/',
|
||||||
},
|
},
|
||||||
globals: {
|
globals
|
||||||
document: typeof document !== 'undefined' && document || {},
|
|
||||||
console: typeof console !== 'undefined' && console || {},
|
|
||||||
navigator: typeof navigator !== 'undefined' && navigator || {},
|
|
||||||
window,
|
|
||||||
setTimeout: window.setTimeout,
|
|
||||||
clearTimeout: window.clearTimeout,
|
|
||||||
Zotero: typeof Zotero !== 'undefined' && Zotero || {}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return Require(loader, requirer);
|
return Require(loader, requirer);
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
../node_modules/zotero-web-library/lib
|
|
|
@ -12,7 +12,7 @@ const cluster = require('cluster');
|
||||||
async function babelWorker(ev) {
|
async function babelWorker(ev) {
|
||||||
const t1 = Date.now();
|
const t1 = Date.now();
|
||||||
const sourcefile = ev.file;
|
const sourcefile = ev.file;
|
||||||
const outfile = path.join('build', sourcefile);
|
const outfile = path.join('build', sourcefile.replace('.jsx', '.js'));
|
||||||
const postError = (error) => {
|
const postError = (error) => {
|
||||||
process.send({
|
process.send({
|
||||||
sourcefile,
|
sourcefile,
|
||||||
|
@ -28,7 +28,8 @@ async function babelWorker(ev) {
|
||||||
let contents = await fs.readFile(sourcefile, 'utf8');
|
let contents = await fs.readFile(sourcefile, 'utf8');
|
||||||
if (sourcefile === 'resource/react-dom.js') {
|
if (sourcefile === 'resource/react-dom.js') {
|
||||||
// patch react
|
// patch react
|
||||||
transformed = contents.replace(/ownerDocument\.createElement\((.*?)\)/gi, 'ownerDocument.createElementNS(DOMNamespaces.html, $1)');
|
transformed = contents.replace(/ownerDocument\.createElement\((.*?)\)/gi, 'ownerDocument.createElementNS(DOMNamespaces.html, $1)')
|
||||||
|
.replace("isInputEventSupported = false", 'isInputEventSupported = true');
|
||||||
} else if ('ignore' in options && options.ignore.some(ignoreGlob => multimatch(sourcefile, ignoreGlob).length)) {
|
} else if ('ignore' in options && options.ignore.some(ignoreGlob => multimatch(sourcefile, ignoreGlob).length)) {
|
||||||
transformed = contents;
|
transformed = contents;
|
||||||
isSkipped = true;
|
isSkipped = true;
|
||||||
|
|
|
@ -6,7 +6,7 @@ const getJS = require('./js');
|
||||||
const getSass = require('./sass');
|
const getSass = require('./sass');
|
||||||
const getSymlinks = require('./symlinks');
|
const getSymlinks = require('./symlinks');
|
||||||
const { formatDirsForMatcher, getSignatures, writeSignatures, cleanUp, onSuccess, onError} = require('./utils');
|
const { formatDirsForMatcher, getSignatures, writeSignatures, cleanUp, onSuccess, onError} = require('./utils');
|
||||||
const { dirs, symlinkDirs, copyDirs, symlinkFiles, jsFiles, ignoreMask } = require('./config');
|
const { dirs, symlinkDirs, copyDirs, symlinkFiles, jsFiles, scssFiles, ignoreMask } = require('./config');
|
||||||
|
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
(async () => {
|
(async () => {
|
||||||
|
@ -23,7 +23,7 @@ if (require.main === module) {
|
||||||
getBrowserify(signatures),
|
getBrowserify(signatures),
|
||||||
getCopy(copyDirs.map(d => `${d}/**`), { ignore: ignoreMask }, signatures),
|
getCopy(copyDirs.map(d => `${d}/**`), { ignore: ignoreMask }, signatures),
|
||||||
getJS(jsFiles, { ignore: ignoreMask }, signatures),
|
getJS(jsFiles, { ignore: ignoreMask }, signatures),
|
||||||
getSass('scss/*.scss', { root: 'scss', ignore: ignoreMask }, signatures),
|
getSass(scssFiles, { ignore: ignoreMask }, signatures),
|
||||||
getSymlinks(symlinks, { nodir: true, ignore: ignoreMask }, signatures),
|
getSymlinks(symlinks, { nodir: true, ignore: ignoreMask }, signatures),
|
||||||
getSymlinks(symlinkDirs, { ignore: ignoreMask }, signatures),
|
getSymlinks(symlinkDirs, { ignore: ignoreMask }, signatures),
|
||||||
cleanUp(signatures)
|
cleanUp(signatures)
|
||||||
|
|
|
@ -49,13 +49,20 @@ const browserifyConfigs = [
|
||||||
];
|
];
|
||||||
|
|
||||||
// exclude mask used for js, copy, symlink and sass tasks
|
// exclude mask used for js, copy, symlink and sass tasks
|
||||||
const ignoreMask = ['**/#*'];
|
const ignoreMask = ['**/#*', '**/_*.scss'];
|
||||||
|
|
||||||
const jsFiles = [
|
const jsFiles = [
|
||||||
`{${dirs.join(',')}}/**/*.js`,
|
`{${dirs.join(',')}}/**/*.js`,
|
||||||
`!{${symlinkDirs.concat(copyDirs).join(',')}}/**/*.js`
|
`{${dirs.join(',')}}/**/*.jsx`,
|
||||||
|
`!{${symlinkDirs.concat(copyDirs).join(',')}}/**/*.js`,
|
||||||
|
`!{${symlinkDirs.concat(copyDirs).join(',')}}/**/*.jsx`
|
||||||
|
];
|
||||||
|
|
||||||
|
const scssFiles = [
|
||||||
|
'scss/**/*.scss',
|
||||||
|
'chrome/skin/default/zotero/**/*.scss'
|
||||||
];
|
];
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
dirs, symlinkDirs, copyDirs, symlinkFiles, browserifyConfigs, jsFiles, ignoreMask
|
dirs, symlinkDirs, copyDirs, symlinkFiles, browserifyConfigs, jsFiles, scssFiles, ignoreMask
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,7 @@ const sassRender = universalify.fromCallback(sass.render);
|
||||||
|
|
||||||
const ROOT = path.resolve(__dirname, '..');
|
const ROOT = path.resolve(__dirname, '..');
|
||||||
|
|
||||||
async function getSass(source, options, signatures) {
|
async function getSass(source, options, signatures={}) {
|
||||||
const t1 = Date.now();
|
const t1 = Date.now();
|
||||||
const files = await globby(source, Object.assign({ cwd: ROOT }, options ));
|
const files = await globby(source, Object.assign({ cwd: ROOT }, options ));
|
||||||
const totalCount = files.length;
|
const totalCount = files.length;
|
||||||
|
@ -20,7 +20,9 @@ async function getSass(source, options, signatures) {
|
||||||
|
|
||||||
while ((f = files.pop()) != null) {
|
while ((f = files.pop()) != null) {
|
||||||
let newFileSignature = await getFileSignature(f);
|
let newFileSignature = await getFileSignature(f);
|
||||||
const dest = path.join.apply(this, ['build', 'chrome', 'skin', 'default', 'zotero', 'components', getPathRelativeTo(f, 'scss')]);
|
let destFile = getPathRelativeTo(f, 'scss');
|
||||||
|
destFile = path.join(path.dirname(destFile), path.basename(destFile, '.scss') + '.css');
|
||||||
|
const dest = path.join.apply(this, ['build', 'chrome', 'skin', 'default', 'zotero', destFile]);
|
||||||
|
|
||||||
if (f in signatures) {
|
if (f in signatures) {
|
||||||
if (compareSignatures(newFileSignature, signatures[f])) {
|
if (compareSignatures(newFileSignature, signatures[f])) {
|
||||||
|
@ -34,10 +36,14 @@ async function getSass(source, options, signatures) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const sass = await sassRender({
|
const sass = await sassRender({
|
||||||
file: f
|
file: f,
|
||||||
|
outFile: dest,
|
||||||
|
sourceMap: true,
|
||||||
|
outputStyle: 'compressed'
|
||||||
});
|
});
|
||||||
|
|
||||||
await fs.outputFile(dest, sass);
|
await fs.outputFile(dest, sass.css);
|
||||||
|
await fs.outputFile(`${dest}.map`, sass.map);
|
||||||
onProgress(f, dest, 'sass');
|
onProgress(f, dest, 'sass');
|
||||||
signatures[f] = newFileSignature;
|
signatures[f] = newFileSignature;
|
||||||
count++;
|
count++;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const chokidar = require('chokidar');
|
const chokidar = require('chokidar');
|
||||||
const multimatch = require('multimatch');
|
const multimatch = require('multimatch');
|
||||||
const { dirs, jsFiles, ignoreMask, copyDirs, symlinkFiles } = require('./config');
|
const { dirs, jsFiles, scssFiles, ignoreMask, copyDirs, symlinkFiles } = require('./config');
|
||||||
const { onSuccess, onError, getSignatures, writeSignatures, cleanUp, formatDirsForMatcher } = require('./utils');
|
const { onSuccess, onError, getSignatures, writeSignatures, cleanUp, formatDirsForMatcher } = require('./utils');
|
||||||
const getJS = require('./js');
|
const getJS = require('./js');
|
||||||
const getSass = require('./sass');
|
const getSass = require('./sass');
|
||||||
|
@ -49,8 +49,12 @@ function getWatch() {
|
||||||
try {
|
try {
|
||||||
if (multimatch(path, jsFiles).length && !multimatch(path, ignoreMask).length) {
|
if (multimatch(path, jsFiles).length && !multimatch(path, ignoreMask).length) {
|
||||||
onSuccess(await getJS(path, { ignore: ignoreMask }, signatures));
|
onSuccess(await getJS(path, { ignore: ignoreMask }, signatures));
|
||||||
} else if (multimatch(path, 'scss/*.scss').length) {
|
} else if (multimatch(path, scssFiles).length) {
|
||||||
onSuccess(await getSass(path, {}, signatures));
|
if (multimatch(path, '**/_*.scss').length) {
|
||||||
|
onSuccess(await getSass(scssFiles, { ignore: ignoreMask }));
|
||||||
|
} else {
|
||||||
|
onSuccess(await getSass(path, {}, signatures));
|
||||||
|
}
|
||||||
} else if (multimatch(path, copyDirs.map(d => `${d}/**`)).length) {
|
} else if (multimatch(path, copyDirs.map(d => `${d}/**`)).length) {
|
||||||
onSuccess(await getCopy(path, {}, signatures));
|
onSuccess(await getCopy(path, {}, signatures));
|
||||||
} else if (multimatch(path, symlinks).length) {
|
} else if (multimatch(path, symlinks).length) {
|
||||||
|
|
4
scss/abstracts/_functions.scss
Normal file
4
scss/abstracts/_functions.scss
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
//
|
||||||
|
// Functions
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
4
scss/abstracts/_mixins.scss
Normal file
4
scss/abstracts/_mixins.scss
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
//
|
||||||
|
// Mixins
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
3
scss/abstracts/_placeholders.scss
Normal file
3
scss/abstracts/_placeholders.scss
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
//
|
||||||
|
// Placeholders
|
||||||
|
// --------------------------------------------------
|
4
scss/abstracts/_utilities.scss
Normal file
4
scss/abstracts/_utilities.scss
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
//
|
||||||
|
// Utilities
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
77
scss/abstracts/_variables.scss
Normal file
77
scss/abstracts/_variables.scss
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
//
|
||||||
|
// Variables
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// Dimensions
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
$space-min: 4px;
|
||||||
|
$space-xs: 8px;
|
||||||
|
$space-sm: 12px;
|
||||||
|
$space-md: 16px;
|
||||||
|
$space-lg: 24px;
|
||||||
|
$space-xl: 32px;
|
||||||
|
$space-xxl: 48px;
|
||||||
|
$space-max: 64px;
|
||||||
|
|
||||||
|
$space-thumb: 42px;
|
||||||
|
|
||||||
|
|
||||||
|
// Typography
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
$font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
$font-family-base: $font-family-sans-serif;
|
||||||
|
|
||||||
|
$font-size-base: 13px;
|
||||||
|
|
||||||
|
$font-size-h1: 20px;
|
||||||
|
$font-size-h2: 16px;
|
||||||
|
|
||||||
|
$line-height-base: 1.539;
|
||||||
|
$line-height-computed: ceil($font-size-base * $line-height-base);
|
||||||
|
|
||||||
|
// todo: line-height-small
|
||||||
|
$line-height-large: 26px;
|
||||||
|
$line-height-large-touch: $space-thumb;
|
||||||
|
|
||||||
|
$link-hover-decoration: underline;
|
||||||
|
|
||||||
|
$headings-font-family: inherit;
|
||||||
|
$headings-font-weight: 400;
|
||||||
|
$headings-line-height: 1.2;
|
||||||
|
|
||||||
|
|
||||||
|
// Components
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
$padding-x-sm: $space-sm;
|
||||||
|
$padding-x-md: $space-md;
|
||||||
|
|
||||||
|
$default-padding-x: $space-sm;
|
||||||
|
$default-padding-x-touch: $space-md;
|
||||||
|
|
||||||
|
$border-radius: 4px;
|
||||||
|
$border-radius-sm: 3px;
|
||||||
|
$border-radius-lg: 6px;
|
||||||
|
|
||||||
|
$border-width: 1px;
|
||||||
|
|
||||||
|
$separator-width: 1px;
|
||||||
|
|
||||||
|
// Z-index master list
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
$z-index-mobile-nav: 0;
|
||||||
|
$z-index-navbar-bg: 10;
|
||||||
|
$z-index-main: 10;
|
||||||
|
$z-index-level: 10;
|
||||||
|
$z-index-level-active: 20;
|
||||||
|
$z-index-navbar: 20;
|
||||||
|
$z-index-menu: 30;
|
||||||
|
$z-index-modal: 40;
|
||||||
|
$z-index-drag-layer: 50;
|
||||||
|
$z-index-loading-cover: 60;
|
||||||
|
|
86
scss/components/_tag-selector.scss
Normal file
86
scss/components/_tag-selector.scss
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
//
|
||||||
|
// Tag selector
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
.library .tag-selector {
|
||||||
|
height: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-selector {
|
||||||
|
display: flex;
|
||||||
|
flex: 1 0 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: $tag-selector-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-selector-container {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
justify-content: space-between;
|
||||||
|
overflow: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-selector-filter-container {
|
||||||
|
height: auto;
|
||||||
|
flex: 0 0 1em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-selector-list {
|
||||||
|
list-style: none;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-selector-filter {
|
||||||
|
flex: 1 0 40px;
|
||||||
|
min-width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-selector-actions {
|
||||||
|
flex: 0 0 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-selector-item {
|
||||||
|
border-radius: 1em;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
padding: .05em .5em;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
background-color: $secondary;
|
||||||
|
border: 1px solid $secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.colored {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
opacity: .6;
|
||||||
|
cursor: auto;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.disabled):hover {
|
||||||
|
background-color: lighten($secondary, 15%);
|
||||||
|
border: 1px solid $secondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#zotero-tag-selector {
|
||||||
|
min-height: 100px;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#zotero-tag-selector[collapsed=true] {
|
||||||
|
visibility: collapse;
|
||||||
|
}
|
||||||
|
|
179
scss/themes/_light.scss
Normal file
179
scss/themes/_light.scss
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
//
|
||||||
|
// Light theme
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// Colors
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
$red: #cc2936;
|
||||||
|
$blue: #2e4de5; // 230° 80 90
|
||||||
|
$asphalt: #7a8799;
|
||||||
|
$asphalt-light: #dadee3;
|
||||||
|
|
||||||
|
$primary: $red;
|
||||||
|
$secondary: $blue;
|
||||||
|
|
||||||
|
$blue-dark: #333c66;
|
||||||
|
$blue-darkest: #3d4466;
|
||||||
|
|
||||||
|
$transparent: transparent;
|
||||||
|
|
||||||
|
|
||||||
|
// Grays
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
$shade-0: #fff;
|
||||||
|
$shade-1: #f6f6f6;
|
||||||
|
$shade-2: #e6e6e6;
|
||||||
|
$shade-3: #ddd;
|
||||||
|
$shade-4: #ccc;
|
||||||
|
$shade-5: #bbb;
|
||||||
|
$shade-6: #777;
|
||||||
|
$shade-7: #555;
|
||||||
|
$shade-8: #444;
|
||||||
|
$shade-9: #222;
|
||||||
|
$shade-10: #000;
|
||||||
|
|
||||||
|
|
||||||
|
// Scaffolding
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
$body-bg: $shade-0;
|
||||||
|
$text-color: $shade-9;
|
||||||
|
|
||||||
|
$headings-color: $shade-8;
|
||||||
|
|
||||||
|
$link-color: $blue;
|
||||||
|
$link-hover-color: $blue;
|
||||||
|
|
||||||
|
$focus-color: $secondary;
|
||||||
|
|
||||||
|
|
||||||
|
// Typography
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
$text-selection-color: inherit;
|
||||||
|
$text-selection-bg: rgba($secondary, 0.2);
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
$separator-color: $shade-3;
|
||||||
|
|
||||||
|
|
||||||
|
// Partials
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
// Main
|
||||||
|
$main-bg: $shade-0;
|
||||||
|
|
||||||
|
// Sidebar
|
||||||
|
$sidebar-bg: $shade-1;
|
||||||
|
|
||||||
|
|
||||||
|
// Components
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
// Icon
|
||||||
|
$icon-color: $secondary;
|
||||||
|
$icon-active-color: $shade-9;
|
||||||
|
|
||||||
|
// Collection tree
|
||||||
|
$collection-tree-headings-color: $shade-6;
|
||||||
|
$collection-tree-link-color: $shade-8;
|
||||||
|
$collection-tree-active-link-color: $shade-9;
|
||||||
|
$collection-tree-active-icon-color: $shade-7;
|
||||||
|
$collection-tree-active-link-bg: $shade-2;
|
||||||
|
$collection-tree-focus-color: $asphalt;
|
||||||
|
$collection-tree-icon-color: $shade-6;
|
||||||
|
$touch-collection-tree-active-link-color: $shade-0;
|
||||||
|
$touch-collection-tree-active-link-bg: $blue;
|
||||||
|
$touch-collection-tree-border: $shade-2;
|
||||||
|
$touch-collection-tree-separator: $body-bg;
|
||||||
|
$collection-tree-dnd-target-link-color: $shade-0;
|
||||||
|
$collection-tree-dnd-target-bg-color: $blue;
|
||||||
|
$collection-tree-dnd-target-icon-color: $shade-0;
|
||||||
|
|
||||||
|
// Items
|
||||||
|
$items-bg: $shade-0;
|
||||||
|
$items-odd-bg: $shade-1;
|
||||||
|
$item-list-head-color: $shade-8;
|
||||||
|
$item-list-head-border: $shade-2;
|
||||||
|
|
||||||
|
// Item list
|
||||||
|
$item-odd-bg: $shade-1;
|
||||||
|
$item-active-color: $shade-0;
|
||||||
|
$item-active-bg: $secondary;
|
||||||
|
|
||||||
|
// Item details
|
||||||
|
$item-details-bg: $shade-1;
|
||||||
|
$info-view-color: $shade-5;
|
||||||
|
|
||||||
|
// Panel
|
||||||
|
$panel-bg: $shade-1;
|
||||||
|
$panel-header-color: $shade-8;
|
||||||
|
$panel-header-shadow: rgba($shade-10, 0.08);
|
||||||
|
|
||||||
|
// Tabs
|
||||||
|
$tabs-border-color: $shade-3;
|
||||||
|
$tab-active-color: $secondary;
|
||||||
|
$tab-inactive-color: $headings-color;
|
||||||
|
|
||||||
|
// Metadata list
|
||||||
|
$key-color: $shade-6;
|
||||||
|
$editable-hover-bg: rgba($shade-10, 0.04);
|
||||||
|
$handle-color-touch: $shade-4;
|
||||||
|
$handle-color-mouse: $shade-6;
|
||||||
|
$metadata-heading-color: $shade-5;
|
||||||
|
$metadata-separator-color: $shade-3;
|
||||||
|
|
||||||
|
// Button
|
||||||
|
$btn-primary-color: $shade-0;
|
||||||
|
$btn-primary-bg: $asphalt;
|
||||||
|
$btn-secondary-color: $secondary;
|
||||||
|
$btn-default-color: $text-color;
|
||||||
|
$btn-default-bg: $shade-0;
|
||||||
|
$btn-default-active-color: rgba($btn-default-color, 0.5);
|
||||||
|
$btn-icon-bg: $transparent;
|
||||||
|
$btn-icon-focus-color: $shade-0;
|
||||||
|
$btn-icon-focus-bg: $asphalt;
|
||||||
|
$btn-icon-focus-active-color: rgba($shade-0, 0.5);
|
||||||
|
$btn-icon-active-color: $shade-7;
|
||||||
|
$btn-icon-active-bg: $shade-2;
|
||||||
|
$twisty-color: $shade-6;
|
||||||
|
$twisty-focus-color: $asphalt;
|
||||||
|
$twisty-selected-color: $shade-7;
|
||||||
|
$twisty-dnd-target-color: $shade-0;
|
||||||
|
|
||||||
|
// Forms
|
||||||
|
$input-color: $text-color;
|
||||||
|
$input-bg: $body-bg;
|
||||||
|
$input-border-color: $shade-3;
|
||||||
|
$input-focus-color: $secondary;
|
||||||
|
$placeholder-color: $shade-5;
|
||||||
|
|
||||||
|
// Editable
|
||||||
|
$editable-color: $text-color;
|
||||||
|
$editable-bg: $shade-0;
|
||||||
|
$editable-border-color: $secondary;
|
||||||
|
|
||||||
|
// Menu (select, dropdown, …)
|
||||||
|
$menu-bg: $body-bg;
|
||||||
|
$menu-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08), 0 3px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
$menu-item-hover-bg: $shade-1;
|
||||||
|
$menu-item-selected-bg: $shade-2;
|
||||||
|
$menu-devider: $shade-2;
|
||||||
|
$menu-no-results-color: $shade-5;
|
||||||
|
|
||||||
|
// Drag layer
|
||||||
|
$creator-drag-preview-shadow: rgba($shade-10, 0.2);
|
||||||
|
|
||||||
|
// Modal
|
||||||
|
$modal-backdrop-bg: rgba($shade-10, 0.4);
|
||||||
|
$modal-content-bg: $shade-1;
|
||||||
|
$modal-header-bg: $shade-0;
|
||||||
|
$modal-footer-border-width: 1px;
|
||||||
|
$modal-footer-border-color: $shade-2;
|
||||||
|
$modal-icon-spin-color: $shade-0;
|
||||||
|
|
||||||
|
// Tag selector
|
||||||
|
$tag-selector-bg: $shade-0;
|
23
scss/zotero-react-client.scss
Normal file
23
scss/zotero-react-client.scss
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
//
|
||||||
|
// Zotero React Client
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// Abstracts
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
@import "abstracts/variables";
|
||||||
|
@import "abstracts/functions";
|
||||||
|
@import "abstracts/mixins";
|
||||||
|
@import "abstracts/placeholders";
|
||||||
|
@import "abstracts/utilities";
|
||||||
|
|
||||||
|
// Theme
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
@import "themes/light";
|
||||||
|
|
||||||
|
// Components
|
||||||
|
// --------------------------------------------------
|
||||||
|
|
||||||
|
@import "components/tag-selector";
|
Loading…
Reference in a new issue