Editor updates

This commit is contained in:
Mo Bitar
2018-01-12 14:36:17 -06:00
parent 5db97b0a4c
commit c7ce308a19
22 changed files with 6662 additions and 794 deletions

View File

@@ -96,7 +96,8 @@ module.exports = function(grunt) {
css: {
src: [
'vendor/assets/stylesheets/app.css'
'vendor/assets/stylesheets/app.css',
'node_modules/sn-stylekit/dist/stylekit.css'
],
dest: 'vendor/assets/stylesheets/app.css'
}

View File

@@ -115,19 +115,21 @@ angular.module('app.frontend')
// if plain editor or other editor
this.showEditorMenu = false;
var editor = component;
if(this.selectedEditor && editor !== this.selectedEditor) {
this.disassociateComponentWithCurrentNote(this.selectedEditor);
}
if(editor) {
this.note.setAppDataItem("prefersPlainEditor", false);
this.note.setDirty(true);
componentManager.associateComponentWithItem(editor, this.note);
if(this.note.getAppDataItem("prefersPlainEditor") == true) {
this.note.setAppDataItem("prefersPlainEditor", false);
this.note.setDirty(true);
}
this.associateComponentWithCurrentNote(editor);
} else {
// Note prefers plain editor
if(this.selectedEditor) {
this.disableComponentForCurrentItem(this.selectedEditor);
if(!this.note.getAppDataItem("prefersPlainEditor")) {
this.note.setAppDataItem("prefersPlainEditor", true);
this.note.setDirty(true);
}
this.note.setAppDataItem("prefersPlainEditor", true);
this.note.setDirty(true);
syncManager.sync();
$timeout(() => {
this.reloadFont();
})
@@ -139,6 +141,8 @@ angular.module('app.frontend')
this.toggleStackComponentForCurrentItem(component);
}
// Lots of dirtying can happen above, so we'll sync
syncManager.sync();
}.bind(this)
this.hasAvailableExtensions = function() {
@@ -502,31 +506,34 @@ angular.module('app.frontend')
this.toggleStackComponentForCurrentItem = function(component) {
if(component.isActiveForItem(this.note)) {
this.disableComponentForCurrentItem(component);
componentManager.deactivateComponent(component);
this.disassociateComponentWithCurrentNote(component);
} else {
this.enableComponentForCurrentItem(component);
componentManager.activateComponent(component);
componentManager.contextItemDidChangeInArea("editor-stack");
this.associateComponentWithCurrentNote(component);
}
}
this.disableComponentForCurrentItem = function(component) {
componentManager.deactivateComponent(component);
_.pull(component.associatedItemIds, this.note.uuid);
if(component.disassociatedItemIds.indexOf(this.note.uuid) !== -1) {
return;
this.disassociateComponentWithCurrentNote = function(component) {
component.associatedItemIds = component.associatedItemIds.filter((id) => {return id !== this.note.uuid});
// Only disassociative components should modify the disassociatedItemIds
if(!component.isAssociative() && !component.disassociatedItemIds.includes(this.note.uuid)) {
component.disassociatedItemIds.push(this.note.uuid);
}
component.disassociatedItemIds.push(this.note.uuid);
component.setDirty(true);
syncManager.sync();
}
this.enableComponentForCurrentItem = function(component) {
componentManager.activateComponent(component);
componentManager.contextItemDidChangeInArea("editor-stack");
this.associateComponentWithCurrentNote = function(component) {
component.disassociatedItemIds = component.disassociatedItemIds.filter((id) => {return id !== this.note.uuid});
if(component.isAssociative() && !component.associatedItemIds.includes(this.note.uuid)) {
component.associatedItemIds.push(this.note.uuid);
}
_.pull(component.disassociatedItemIds, this.note.uuid);
component.setDirty(true);
syncManager.sync();
}

View File

@@ -166,6 +166,11 @@ angular.module('app.frontend')
// Safe to create. Create and return object.
let url = window._prolink_package_url;
console.log("Installing ProLink from URL", url);
if(!url) {
console.error("window._prolink_package_url must be set.");
return;
}
packageManager.installPackage(url, (component) => {
valueCallback(component);
})

View File

@@ -23,9 +23,10 @@ class Component extends Item {
/* New */
this.local_url = content.local_url;
this.hosted_url = content.hosted_url;
this.offlineOnly = content.offlineOnly;
this.name = content.name;
this.autoupdate = content.autoupdate;
this.autoupdateDisabled = content.autoupdateDisabled;
this.package_info = content.package_info;
@@ -50,12 +51,13 @@ class Component extends Item {
url: this.url,
hosted_url: this.hosted_url,
local_url: this.local_url,
offlineOnly: this.offlineOnly,
name: this.name,
area: this.area,
package_info: this.package_info,
permissions: this.permissions,
active: this.active,
autoupdate: this.autoupdate,
autoupdateDisabled: this.autoupdateDisabled,
componentData: this.componentData,
disassociatedItemIds: this.disassociatedItemIds,
associatedItemIds: this.associatedItemIds,
@@ -73,14 +75,6 @@ class Component extends Item {
return "SN|Component";
}
computedUrl() {
if(this.offlineOnly || (isDesktopApplication() && this.local_url)) {
return this.local_url.replace("sn://", this.desktopManager.getApplicationDataPath() + "/");
} else {
return this.url || this.hosted_url;
}
}
isEditor() {
return this.area == "editor-editor";
}

View File

@@ -6,10 +6,14 @@ class ItemParams {
this.version = version || "002";
}
paramsForExportFile() {
paramsForExportFile(includeDeleted) {
this.additionalFields = ["updated_at"];
this.forExportFile = true;
return _.omit(this.__params(), ["deleted"]);
if(includeDeleted) {
return this.__params();
} else {
return _.omit(this.__params(), ["deleted"]);
}
}
paramsForExtension() {

View File

@@ -127,7 +127,7 @@ class ComponentManager {
postThemeToComponent(component) {
var activeTheme = this.getActiveTheme();
var data = {
themes: [activeTheme ? activeTheme.computedUrl() : null]
themes: [activeTheme ? this.urlForComponent(activeTheme) : null]
}
this.sendMessageToComponent(component, {action: "themes", data: data})
@@ -196,6 +196,14 @@ class ComponentManager {
})
}
urlForComponent(component) {
if(component.offlineOnly || (isDesktopApplication() && component.local_url)) {
return component.local_url.replace("sn://", this.desktopManager.getApplicationDataPath() + "/");
} else {
return component.url || component.hosted_url;
}
}
componentForUrl(url) {
return this.components.filter(function(component){
return component.url === url || component.hosted_url === url;
@@ -246,8 +254,6 @@ class ComponentManager {
this.handleCreateItemMessage(component, message);
} else if(message.action === "save-items") {
this.handleSaveItemsMessage(component, message);
} else if(message.action === "install-local-component") {
this.handleInstallLocalComponentMessage(component, message);
} else if(message.action === "toggle-activate-component") {
let componentToToggle = this.modelManager.findItem(message.data.uuid);
this.handleToggleComponentMessage(component, componentToToggle, message);
@@ -265,7 +271,7 @@ class ComponentManager {
removePrivatePropertiesFromResponseItems(responseItems, includeUrls) {
// Don't allow component to overwrite these properties.
var privateProperties = ["appData", "autoupdate", "permissions", "active", "encrypted"];
var privateProperties = ["appData", "autoupdateDisabled", "permissions", "active", "encrypted"];
if(includeUrls) {
privateProperties = privateProperties.concat(["url", "hosted_url", "local_url"]);
}
@@ -329,17 +335,21 @@ class ComponentManager {
// push immediately now
for(let handler of this.handlersForArea(component.area)) {
var itemInContext = handler.contextRequestHandler(component);
this.sendContextItemInReply(component, itemInContext, message);
if(handler.contextRequestHandler) {
var itemInContext = handler.contextRequestHandler(component);
this.sendContextItemInReply(component, itemInContext, message);
}
}
}.bind(this))
}
isItemWithinComponentContextJurisdiction(item, component) {
for(let handler of this.handlersForArea(component.area)) {
var itemInContext = handler.contextRequestHandler(component);
if(itemInContext.uuid == item.uuid) {
return true;
if(handler.contextRequestHandler) {
var itemInContext = handler.contextRequestHandler(component);
if(itemInContext.uuid == item.uuid) {
return true;
}
}
}
return false;
@@ -388,6 +398,7 @@ class ComponentManager {
}
item.setDirty(true);
}
this.syncManager.sync((response) => {
// Allow handlers to be notified when a save begins and ends, to update the UI
var saveMessage = Object.assign({}, message);
@@ -443,24 +454,6 @@ class ComponentManager {
});
}
handleInstallLocalComponentMessage(component, message) {
var requiredPermissions = [
{
name: "stream-items",
content_types: [message.data.content_type]
}
];
this.runWithPermissions(component, requiredPermissions, () => {
this.desktopManager.installOfflineComponentFromData(message.data, (response) => {
var component = this.modelManager.mapResponseItemsToLocalModels([response], ModelManager.MappingSourceComponentRetrieved)[0];
// Save updated URL
component.setDirty(true);
this.syncManager.sync();
})
});
}
handleSetComponentDataMessage(component, message) {
// A component setting its own data does not require special permissions
this.runWithPermissions(component, [], () => {
@@ -719,19 +712,6 @@ class ComponentManager {
return component.active;
}
associateComponentWithItem(component, item) {
_.pull(component.disassociatedItemIds, item.uuid);
if(component.associatedItemIds.includes(item.uuid)) {
return;
}
component.associatedItemIds.push(item.uuid);
component.setDirty(true);
this.syncManager.sync();
}
iframeForComponent(component) {
for(var frame of document.getElementsByTagName("iframe")) {
var componentId = frame.dataset.componentId;

View File

@@ -25,14 +25,6 @@ class DesktopManager {
})
}
/* Can handle components and themes */
installOfflineComponentFromData(componentData, callback) {
this.componentInstallationHandler(componentData, (installedComponent) => {
componentData.content.local_url = installedComponent.content.local_url;
callback(componentData);
});
}
getApplicationDataPath() {
console.assert(this.applicationDataPath, "applicationDataPath is null");
return this.applicationDataPath;
@@ -40,24 +32,31 @@ class DesktopManager {
/* Sending a component in its raw state is really slow for the desktop app */
convertComponentForTransmission(component) {
return new ItemParams(component).paramsForExportFile();
return new ItemParams(component).paramsForExportFile(true);
}
// All `components` should be installed
syncComponentsInstallation(components) {
// console.log("Web Syncing Components", components);
if(!this.isDesktop) return;
/* Allows us to look up component on desktop_updateComponentComplete */
this.syncingComponents = components;
var data = components.map((component) => {
console.log("Web Sycying Component", this.convertComponentForTransmission(component));
return this.convertComponentForTransmission(component);
})
this.installationSyncHandler(data);
}
desktop_onComponentInstallationComplete(componentData) {
console.log("Web|Component Installation Complete", componentData);
var component = this.modelManager.mapResponseItemsToLocalModels([componentData], ModelManager.MappingSourceDesktopInstalled)[0];
component.setDirty(true);
this.syncManager.sync();
}
desktop_updateComponentComplete(componentData) {
var component = this.syncingComponents.filter((c) => {return c.uuid == componentData.uuid})[0];
console.log("Web|Component Update Complete", componentData);
var component = this.modelManager.mapResponseItemsToLocalModels([componentData], ModelManager.MappingSourceDesktopInstalled)[0];
component.setDirty(true);
this.syncManager.sync();
}

View File

@@ -35,7 +35,6 @@ class ComponentView {
}.bind(this)});
$scope.$watch('component', function(component, prevComponent){
// console.log("Component View Setting Component", component);
ctrl.componentValueChanging(component, prevComponent);
});
}
@@ -43,22 +42,26 @@ class ComponentView {
controller($scope, $timeout, componentManager, desktopManager) {
'ngInject';
console.log("Creating New Component View");
this.componentValueChanging = (component, prevComponent) => {
if(prevComponent && component !== prevComponent) {
// Deactive old component
console.log("DEACTIVATING OLD COMPONENT", prevComponent);
componentManager.deactivateComponent(prevComponent);
}
if(component) {
componentManager.activateComponent(component);
component.runningLocally = $scope.getUrl
console.log("Loading", $scope.component.name, $scope.getUrl());
}
}
$scope.getUrl = function() {
var url = componentManager.urlForComponent($scope.component);
$scope.component.runningLocally = url !== ($scope.component.url || $scope.component.hosted_url);
return url;
}
$scope.$on("$destroy", function() {
console.log("DESTROY COMPONENT VIEW");
componentManager.deregisterHandler($scope.identifier);
if($scope.component) {
componentManager.deactivateComponent($scope.component);

View File

@@ -39,6 +39,10 @@ class EditorMenu {
}
}
$scope.offlineAvailableForComponent = function(component) {
return component.local_url && isDesktopApplication();
}
$scope.makeEditorDefault = function(component) {
var currentDefault = componentManager.componentsForArea("editor-editor").filter((e) => {return e.isDefaultEditor()})[0];
if(currentDefault) {

View File

@@ -6,6 +6,7 @@ class ModelManager {
ModelManager.MappingSourceLocalSaved = "MappingSourceLocalSaved";
ModelManager.MappingSourceLocalRetrieved = "MappingSourceLocalRetrieved";
ModelManager.MappingSourceComponentRetrieved = "MappingSourceComponentRetrieved";
ModelManager.MappingSourceDesktopInstalled = "MappingSourceDesktopInstalled"; // When a component is installed by the desktop and some of its values change
ModelManager.MappingSourceRemoteActionRetrieved = "MappingSourceRemoteActionRetrieved"; /* aciton-based Extensions like note history */
ModelManager.MappingSourceFileImport = "MappingSourceFileImport";
@@ -147,7 +148,7 @@ class ModelManager {
}
if(!item) {
item = this.createItem(json_obj);
item = this.createItem(json_obj, true);
}
this.addItem(item);
@@ -200,7 +201,7 @@ class ModelManager {
}
}
createItem(json_obj) {
createItem(json_obj, dontNotifyObservers) {
var item;
if(json_obj.content_type == "Note") {
item = new Note(json_obj);
@@ -224,6 +225,15 @@ class ModelManager {
item = new Item(json_obj);
}
// Some observers would be interested to know when an an item is locally created
// If we don't send this out, these observers would have to wait until MappingSourceRemoteSaved
// to hear about it, but sometimes, RemoveSaved is explicitly ignored by the observer to avoid
// recursive callbacks. See componentManager's syncObserver callback.
// dontNotifyObservers is currently only set true by modelManagers mapResponseItemsToLocalModels
if(!dontNotifyObservers) {
this.notifySyncObserversOfModels([item], ModelManager.MappingSourceLocalSaved);
}
item.addObserver(this, function(changedItem){
this.notifyItemChangeObserversOfModels([changedItem]);
}.bind(this));

View File

@@ -18,10 +18,11 @@ class PackageManager {
// Remove private properties
this.componentManager.removePrivatePropertiesFromResponseItems([aPackage]);
var assembled = this.modelManager.createItem(aPackage);
aPackage.package_info = Object.assign({}, aPackage);
assembled.package_info = aPackage;
var assembled = this.modelManager.createItem(aPackage);;
this.modelManager.addItem(assembled);
assembled.setDirty(true);
this.syncManager.sync();

View File

@@ -27,7 +27,6 @@ class SingletonManager {
setTimeout(function () {
var userPrefs = modelManager.itemsForContentType("SN|UserPreferences");
console.assert(userPrefs.length == 1);
console.log("All extant prefs", userPrefs);
}, 1000);
}

View File

@@ -5,6 +5,7 @@ class ThemeManager {
this.modelManager = modelManager;
this.$rootScope = $rootScope;
this.storageManager = storageManager;
this.componentManager = componentManager;
componentManager.registerHandler({identifier: "themeManager", areas: ["themes"], activationHandler: (component) => {
if(component.active) {
@@ -55,8 +56,7 @@ class ThemeManager {
this.deactivateTheme(this.activeTheme);
}
var url = theme.computedUrl();
var url = this.componentManager.urlForComponent(theme);
var link = document.createElement("link");
link.href = url;

View File

@@ -16,6 +16,10 @@
background-color: white;
}
.header .subtitle {
font-size: 1.1rem;
}
.modal {
position: fixed;
margin-left: auto;

View File

@@ -17,7 +17,7 @@
color: rgba(black, 0.8);
}
#tags-content {
&, #tags-content {
background-color: #f6f6f6;
}

View File

@@ -4,6 +4,8 @@
.sn-component
.panel{"ng-attr-id" => "component-{{component.uuid}}"}
.header
%h1.title {{component.name}}
%h1.title
{{component.name}}
%span.subtle.subtitle{"ng-if" => "component.runningLocally"} | Desktop Mode
%a.close-button.info{"ng-click" => "dismiss()"} Close
%component-view.component-view{"component" => "component"}

View File

@@ -1,6 +1,6 @@
%iframe{"ng-if" => "component",
"ng-attr-id" => "component-{{component.uuid}}",
"ng-src" => "{{component.computedUrl() | trusted}}", "frameBorder" => "0",
"sandbox" => "allow-scripts allow-top-navigation-by-user-activation allow-popups allow-popups-to-escape-sandbox allow-modals",
"ng-src" => "{{getUrl() | trusted}}", "frameBorder" => "0",
"sandbox" => "allow-scripts allow-top-navigation-by-user-activation allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-modals",
"data-component-id" => "{{component.uuid}}"}
Loading

View File

@@ -12,7 +12,7 @@
.row
.column
%strong.red.medium{"ng-if" => "editor.conflict_of"} Conflicted copy
.sublabel{"ng-if" => "editor.local_url"}
.sublabel{"ng-if" => "offlineAvailableForComponent(editor)"}
Available Offline
%a.no-decoration{"ng-if" => "editors.length == 0", "href" => "https://standardnotes.org/extensions", "target" => "blank"}

View File

@@ -39,7 +39,6 @@
<%= javascript_include_tag "compiled.min.js", debug: false %>
<% end %>
<%= stylesheet_link_tag "app", media: "all", debug: false %>
<%= stylesheet_link_tag 'stylekit.css', media: 'all', 'data-turbolinks-track' => true %>
</head>

6539
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -34,5 +34,8 @@
"karma-jasmine": "^1.1.0",
"karma-phantomjs-launcher": "^1.0.2"
},
"license": "GPL-3.0"
"license": "GPL-3.0",
"dependencies": {
"sn-stylekit": "^1.0.1"
}
}

View File

@@ -1,686 +0,0 @@
.sn-component {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
-webkit-font-smoothing: antialiased;
user-select: none;
}
.sn-component .panel {
box-shadow: 0px 2px 13px #C8C8C8;
border-radius: 0.7rem;
display: flex;
flex-direction: column;
overflow: hidden;
}
.sn-component .panel a:hover {
text-decoration: underline;
}
.sn-component .panel.static {
box-shadow: none;
border: none;
border-radius: 0;
}
.sn-component .panel .header {
flex-shrink: 0;
/* Don't allow to condense in height */
display: flex;
justify-content: space-between;
padding: 1.1rem 2rem;
border-bottom: 1px solid #E1E1E1;
background-color: #F6F6F6;
align-items: center;
}
.sn-component .panel .header .close-button {
font-weight: bold;
}
.sn-component .panel .footer, .sn-component .panel .panel-footer {
padding: 1rem 2rem;
border-top: 1px solid #E1E1E1;
box-sizing: border-box;
}
.sn-component .panel .footer .left, .sn-component .panel .panel-footer .left {
text-align: right;
display: block;
}
.sn-component .panel .footer .right, .sn-component .panel .panel-footer .right {
text-align: right;
display: block;
}
.sn-component .panel .content {
padding: 1.6rem 2rem;
padding-bottom: 0;
flex-grow: 1;
overflow: scroll;
}
.sn-component .panel .content p {
color: #454545;
line-height: 1.3;
}
.sn-component .panel .content .label, .sn-component .panel .content .panel-section .subtitle, .sn-component .panel-section .panel .content .subtitle {
font-weight: bold;
}
.sn-component .panel-section {
padding-bottom: 1.6rem;
display: flex;
flex-direction: column;
}
.sn-component .panel-section.no-bottom-pad {
padding-bottom: 0;
}
.sn-component .panel-section.hero {
text-align: center;
}
.sn-component .panel-section p:last-child {
margin-bottom: 0;
}
.sn-component .panel-section:not(:last-child) {
margin-bottom: 1.5rem;
border-bottom: 1px solid #DDDDDD;
}
.sn-component .panel-section:not(:last-child).no-border {
border-bottom: none;
}
.sn-component .panel-section:last-child {
margin-bottom: 0.5rem;
}
.sn-component .panel-section .outer-title {
border-bottom: 1px solid #DDDDDD;
padding-bottom: 0.9rem;
margin-top: 2.1rem;
margin-bottom: 15px;
}
.sn-component .panel-section .subtitle {
margin-top: -0.5rem;
}
.sn-component .panel-section .subtitle.subtle {
font-weight: normal;
opacity: 0.6;
}
.sn-component .panel-row {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 0.4rem;
}
.sn-component .panel-row.centered {
justify-content: center;
}
.sn-component .panel-row .panel-column {
width: 100%;
}
.sn-component .panel-row.default-padding, .sn-component .panel-row:not(:last-child) {
padding-bottom: 0.4rem;
}
.sn-component .panel-row.default-padding.condensed, .sn-component .panel-row:not(:last-child).condensed {
padding-top: 0.2rem;
padding-bottom: 0.2rem;
}
.sn-component .panel-row p {
margin: 0;
padding: 0;
}
.sn-component .panel-form {
width: 100%;
}
.sn-component .panel-form.half {
width: 50%;
}
.sn-component .panel-form .form-submit {
margin-top: 0.15rem;
}
.sn-component .right-aligned {
justify-content: flex-end;
text-align: right;
}
.sn-component .menu-panel {
box-shadow: 0px 4px 4px #C8C8C8;
border-radius: 0.6rem;
overflow: scroll;
}
.sn-component .menu-panel .header {
padding: 0.8rem 1rem;
border-bottom: 1px solid #E1E1E1;
background-color: #F6F6F6;
display: flex;
justify-content: space-between;
align-items: center;
}
.sn-component .menu-panel .header .subtitle {
font-size: 0.95rem;
margin-top: 0.2rem;
opacity: 0.6;
}
.sn-component .menu-panel .row {
padding: 1rem 1rem;
border-bottom: 1px solid #DDDDDD;
cursor: pointer;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.sn-component .menu-panel .row .column {
display: flex;
justify-content: center;
flex-direction: column;
/* Nested row */
}
.sn-component .menu-panel .row .column:not(:first-child) {
padding-left: 1.0rem;
padding-right: 0.15rem;
}
.sn-component .menu-panel .row .column .row {
padding: 0;
border-bottom: none;
}
.sn-component .menu-panel .row .column .left {
display: flex;
}
.sn-component .menu-panel .row .button .label, .sn-component .menu-panel .row .box .label, .sn-component .menu-panel .row .circle .label, .sn-component .menu-panel .row .button .panel-section .subtitle, .sn-component .panel-section .menu-panel .row .button .subtitle, .sn-component .menu-panel .row .box .panel-section .subtitle, .sn-component .panel-section .menu-panel .row .box .subtitle, .sn-component .menu-panel .row .circle .panel-section .subtitle, .sn-component .panel-section .menu-panel .row .circle .subtitle {
font-size: 0.8rem;
font-weight: normal;
}
.sn-component .menu-panel .row:hover {
background-color: #efefef;
}
.sn-component .menu-panel .row .label, .sn-component .menu-panel .row .panel-section .subtitle, .sn-component .panel-section .menu-panel .row .subtitle {
font-size: 1rem;
font-weight: bold;
}
.sn-component .menu-panel .row .sublabel {
font-size: 0.9rem;
margin-top: 0.2rem;
opacity: 0.6;
}
.sn-component .red {
color: #F80324;
}
.sn-component .tinted {
color: #086DD6;
}
.sn-component h1, .sn-component h2, .sn-component h3, .sn-component h4, .sn-component h5 {
margin: 0;
padding: 0;
}
.sn-component h1 {
font-weight: 500;
font-size: 1.3rem;
line-height: 1.9rem;
}
.sn-component h2 {
font-size: 1.2rem;
line-height: 1.8rem;
}
.sn-component h3 {
font-weight: normal;
font-size: 1.2rem;
line-height: 1.7rem;
}
.sn-component h4 {
font-weight: bold;
font-size: 0.95rem;
line-height: 1.4rem;
}
.sn-component h5 {
font-weight: bold;
font-size: 0.85rem;
}
.sn-component a {
cursor: pointer;
}
.sn-component .wrap {
word-wrap: break-word;
}
.sn-component *.info {
color: #086DD6;
}
.sn-component *.warning {
color: #f6a200;
}
.sn-component *.danger {
color: #F80324;
}
.sn-component *.success {
color: #2B9612;
}
.sn-component *.clear {
background-color: transparent;
border: none;
}
.sn-component .center-text {
text-align: center;
justify-content: center;
}
.sn-component p {
margin: 0.5rem 0;
}
.sn-component input {
box-sizing: border-box;
padding: 0.75rem 0.8rem;
margin: 0.30rem 0;
border-radius: 3px;
border: 1px solid #e1e1e1;
font-size: 1.1rem;
width: 100%;
outline: 0;
resize: none;
}
.sn-component input.info {
border-color: #086DD6;
background-color: transparent;
color: #086DD6;
}
.sn-component input.info::-webkit-input-placeholder {
color: rgba(8, 109, 214, 0.5);
}
.sn-component label {
margin: 0.7rem 0;
display: block;
font-size: 1.1rem;
}
.sn-component label input[type='checkbox'], .sn-component input[type='radio'] {
width: auto;
margin-right: 0.45rem;
/* Space after checkbox */
}
.sn-component .horizontal-group > *, .sn-component .input-group > * {
display: inline-block;
vertical-align: middle;
}
.sn-component .horizontal-group > *:not(:first-child), .sn-component .input-group > *:not(:first-child) {
margin-left: 0.9rem;
}
.sn-component .border-bottom {
border-bottom: 1px solid #DDDDDD;
}
.sn-component .checkbox-group {
padding-top: 0.5rem;
padding-bottom: 0.3rem;
}
.sn-component ::placeholder {
/* Chrome, Firefox, Opera, Safari 10.1+ */
color: #c4c4c4;
}
.sn-component :-ms-input-placeholder {
/* Internet Explorer 10-11 */
color: #c4c4c4;
}
.sn-component ::-ms-input-placeholder {
/* Microsoft Edge */
color: #c4c4c4;
}
.sn-component .button-group.stretch {
display: flex;
width: 100%;
}
.sn-component .button-group.stretch .button, .sn-component .button-group.stretch .box, .sn-component .button-group.stretch .circle {
display: block;
flex-grow: 1;
text-align: center;
}
.sn-component .button-group .button, .sn-component .button-group .box, .sn-component .button-group .circle {
display: inline-block;
}
.sn-component .button-group .button:not(:last-child), .sn-component .button-group .box:not(:last-child), .sn-component .button-group .circle:not(:last-child) {
margin-right: 5px;
}
.sn-component .button-group .button:not(:last-child).featured, .sn-component .button-group .box:not(:last-child).featured, .sn-component .button-group .circle:not(:last-child).featured {
margin-right: 8px;
}
.sn-component .box-group .box {
display: inline-block;
}
.sn-component .box-group .box:not(:last-child) {
margin-right: 5px;
}
.sn-component a.button, .sn-component a.box, .sn-component a.circle {
text-decoration: none;
}
.sn-component .button, .sn-component .box, .sn-component .circle {
display: table;
border-radius: 3px;
padding: 0.5rem 0.7rem;
font-size: 0.9rem;
cursor: pointer;
text-align: center;
border: 1px solid;
}
.sn-component .button .label, .sn-component .box .label, .sn-component .circle .label, .sn-component .button .panel-section .subtitle, .sn-component .panel-section .button .subtitle, .sn-component .box .panel-section .subtitle, .sn-component .panel-section .box .subtitle, .sn-component .circle .panel-section .subtitle, .sn-component .panel-section .circle .subtitle {
font-weight: bold;
display: block;
text-align: center;
}
.sn-component .button.big, .sn-component .big.box, .sn-component .big.circle {
font-size: 1.1rem;
padding: 0.7rem 2.5rem;
}
.sn-component .box {
padding: 2.5rem 1.5rem;
}
.sn-component .button.default, .sn-component .default.box, .sn-component .default.circle, .sn-component .box.default, .sn-component .circle.default {
background-color: rgba(139, 139, 139, 0.1);
border-color: #8b8b8b;
color: #8b8b8b;
}
.sn-component .button.default:hover, .sn-component .default.box:hover, .sn-component .default.circle:hover, .sn-component .box.default:hover, .sn-component .circle.default:hover {
background-color: white;
color: #939393;
}
.sn-component .button.default.featured, .sn-component .default.featured.box, .sn-component .default.featured.circle, .sn-component .box.default.featured, .sn-component .circle.default.featured {
background-color: #8b8b8b;
border: none;
color: white;
padding: 0.75rem 1.25rem;
font-size: 1.1rem;
}
.sn-component .button.default.featured:hover, .sn-component .default.featured.box:hover, .sn-component .default.featured.circle:hover, .sn-component .box.default.featured:hover, .sn-component .circle.default.featured:hover {
background-color: #9f9f9f;
}
.sn-component .button.info, .sn-component .info.box, .sn-component .info.circle, .sn-component .box.info, .sn-component .circle.info {
background-color: rgba(8, 109, 214, 0.1);
border-color: #086DD6;
color: #086DD6;
}
.sn-component .button.info:hover, .sn-component .info.box:hover, .sn-component .info.circle:hover, .sn-component .box.info:hover, .sn-component .circle.info:hover {
background-color: #d5e9fd;
color: #0975e5;
}
.sn-component .button.info.featured, .sn-component .info.featured.box, .sn-component .info.featured.circle, .sn-component .box.info.featured, .sn-component .circle.info.featured {
background-color: #086DD6;
border: none;
color: white;
padding: 0.75rem 1.25rem;
font-size: 1.1rem;
}
.sn-component .button.info.featured:hover, .sn-component .info.featured.box:hover, .sn-component .info.featured.circle:hover, .sn-component .box.info.featured:hover, .sn-component .circle.info.featured:hover {
background-color: #1181f6;
}
.sn-component .button.warning, .sn-component .warning.box, .sn-component .warning.circle, .sn-component .box.warning, .sn-component .circle.warning {
background-color: rgba(246, 162, 0, 0.1);
border-color: #f6a200;
color: #f6a200;
}
.sn-component .button.warning:hover, .sn-component .warning.box:hover, .sn-component .warning.circle:hover, .sn-component .box.warning:hover, .sn-component .circle.warning:hover {
background-color: #fff8ec;
color: #ffaa06;
}
.sn-component .button.warning.featured, .sn-component .warning.featured.box, .sn-component .warning.featured.circle, .sn-component .box.warning.featured, .sn-component .circle.warning.featured {
background-color: #f6a200;
border: none;
color: white;
padding: 0.75rem 1.25rem;
font-size: 1.1rem;
}
.sn-component .button.warning.featured:hover, .sn-component .warning.featured.box:hover, .sn-component .warning.featured.circle:hover, .sn-component .box.warning.featured:hover, .sn-component .circle.warning.featured:hover {
background-color: #ffb320;
}
.sn-component .button.danger, .sn-component .danger.box, .sn-component .danger.circle, .sn-component .box.danger, .sn-component .circle.danger {
background-color: rgba(248, 3, 36, 0.1);
border-color: #F80324;
color: #F80324;
}
.sn-component .button.danger:hover, .sn-component .danger.box:hover, .sn-component .danger.circle:hover, .sn-component .box.danger:hover, .sn-component .circle.danger:hover {
background-color: #fff1f3;
color: #fc0e2e;
}
.sn-component .button.danger.featured, .sn-component .danger.featured.box, .sn-component .danger.featured.circle, .sn-component .box.danger.featured, .sn-component .circle.danger.featured {
background-color: #F80324;
border: none;
color: white;
padding: 0.75rem 1.25rem;
font-size: 1.1rem;
}
.sn-component .button.danger.featured:hover, .sn-component .danger.featured.box:hover, .sn-component .danger.featured.circle:hover, .sn-component .box.danger.featured:hover, .sn-component .circle.danger.featured:hover {
background-color: #fc2744;
}
.sn-component .button.success, .sn-component .success.box, .sn-component .success.circle, .sn-component .box.success, .sn-component .circle.success {
background-color: rgba(43, 150, 18, 0.1);
border-color: #2B9612;
color: #2B9612;
}
.sn-component .button.success:hover, .sn-component .success.box:hover, .sn-component .success.circle:hover, .sn-component .box.success:hover, .sn-component .circle.success:hover {
background-color: #b7f5a8;
color: #2fa414;
}
.sn-component .button.success.featured, .sn-component .success.featured.box, .sn-component .success.featured.circle, .sn-component .box.success.featured, .sn-component .circle.success.featured {
background-color: #2B9612;
border: none;
color: white;
padding: 0.75rem 1.25rem;
font-size: 1.1rem;
}
.sn-component .button.success.featured:hover, .sn-component .success.featured.box:hover, .sn-component .success.featured.circle:hover, .sn-component .box.success.featured:hover, .sn-component .circle.success.featured:hover {
background-color: #35ba16;
}
.sn-component .notification.default {
background-color: #F6F6F6;
border-color: #c4c4c4;
}
.sn-component .notification.info {
background-color: rgba(8, 109, 214, 0.1);
border-color: #086DD6;
color: #086DD6;
}
.sn-component .notification.info.featured {
background-color: #086DD6;
border: none;
color: white;
padding: 0.75rem 1.25rem;
font-size: 1.1rem;
}
.sn-component .notification.info.featured:hover {
background-color: #1181f6;
}
.sn-component .notification.warning {
background-color: rgba(246, 162, 0, 0.1);
border-color: #f6a200;
color: #f6a200;
}
.sn-component .notification.warning.featured {
background-color: #f6a200;
border: none;
color: white;
padding: 0.75rem 1.25rem;
font-size: 1.1rem;
}
.sn-component .notification.warning.featured:hover {
background-color: #ffb320;
}
.sn-component .notification.danger {
background-color: rgba(248, 3, 36, 0.1);
border-color: #F80324;
color: #F80324;
}
.sn-component .notification.danger.featured {
background-color: #F80324;
border: none;
color: white;
padding: 0.75rem 1.25rem;
font-size: 1.1rem;
}
.sn-component .notification.danger.featured:hover {
background-color: #fc2744;
}
.sn-component .notification.success {
background-color: rgba(43, 150, 18, 0.1);
border-color: #2B9612;
color: #2B9612;
}
.sn-component .notification.success.featured {
background-color: #2B9612;
border: none;
color: white;
padding: 0.75rem 1.25rem;
font-size: 1.1rem;
}
.sn-component .notification.success.featured:hover {
background-color: #35ba16;
}
.sn-component .notification {
border: 1px solid;
padding: 1.1rem 1rem;
margin: 1.4rem 0;
text-align: left;
border-radius: 0.2rem;
cursor: default;
}
.sn-component .notification.one-line {
padding: 0rem 0.4rem;
}
.sn-component .notification.stretch {
width: 100%;
}
.sn-component .notification.dashed {
border-style: dashed;
}
.sn-component .notification .text {
line-height: 1.5rem;
font-size: 1.05rem;
text-align: left;
font-weight: normal;
}
.sn-component .circle {
border-color: #DDDDDD;
background-color: #F6F6F6;
padding: 0;
border-radius: 50%;
}
.sn-component .circle.small {
width: 11px;
height: 11px;
}
.sn-component .spinner {
border: 1px solid #515263;
border-radius: 50%;
animation: rotate 0.8s infinite linear;
border-right-color: transparent;
}
.sn-component .spinner.small {
width: 12px;
height: 12px;
}
.sn-component .spinner.info {
border-color: #086DD6;
border-right-color: transparent;
}
.sn-component .spinner.warning {
border-color: #f6a200;
border-right-color: transparent;
}
.sn-component .spinner.danger {
border-color: #F80324;
border-right-color: transparent;
}
.sn-component .spinner.success {
border-color: #2B9612;
border-right-color: transparent;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.sn-component .app-bar {
display: flex;
width: 100%;
height: 2rem;
padding: 0.1rem 0.8rem;
background-color: #F6F6F6;
justify-content: space-between;
align-items: center;
border: 1px solid #DDDDDD;
}
.sn-component .app-bar.no-edges {
border-left: 0;
border-right: 0;
}
.sn-component .app-bar .left, .sn-component .app-bar .right {
display: flex;
height: 100%;
}
.sn-component .app-bar .item {
flex-grow: 1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.sn-component .app-bar .item:not(:first-child) {
margin-left: 1rem;
}
.sn-component .app-bar .item.border {
border-left: 1px solid #DDDDDD;
}
.sn-component .app-bar .item > .column {
height: 100%;
display: flex;
align-items: center;
}
.sn-component .app-bar .item > .column:not(:first-child) {
margin-left: 0.5rem;
}
.sn-component .app-bar .item.no-pointer {
cursor: default;
}
.sn-component .app-bar .item:hover > .label:not(.subtle), .sn-component .app-bar .panel-section .item:hover > .subtitle:not(.subtle), .sn-component .panel-section .app-bar .item:hover > .subtitle:not(.subtle), .sn-component .app-bar .item:hover > .sublabel:not(.subtle), .sn-component .app-bar .item:hover > .column > .label:not(.subtle), .sn-component .app-bar .panel-section .item:hover > .column > .subtitle:not(.subtle), .sn-component .panel-section .app-bar .item:hover > .column > .subtitle:not(.subtle), .sn-component .app-bar .item:hover > .column > .sublabel:not(.subtle) {
color: #086DD6;
}
.sn-component .app-bar .item > .label, .sn-component .app-bar .panel-section .item > .subtitle, .sn-component .panel-section .app-bar .item > .subtitle, .sn-component .app-bar .item > .column > .label, .sn-component .app-bar .panel-section .item > .column > .subtitle, .sn-component .panel-section .app-bar .item > .column > .subtitle {
font-weight: bold;
font-size: 0.9rem;
white-space: nowrap;
}
.sn-component .app-bar .item > .sublabel, .sn-component .app-bar .item > .column > .sublabel {
font-size: 0.9rem;
font-weight: normal;
white-space: nowrap;
}
.sn-component .app-bar .item .subtle {
font-weight: normal;
opacity: 0.6;
}
.sn-component .panel-table {
display: flex;
flex-wrap: wrap;
padding-left: 1px;
padding-top: 1px;
}
.sn-component .panel-table .table-item {
flex: 45%;
flex-flow: wrap;
border: 1px solid #DDDDDD;
padding: 1rem;
margin-left: -1px;
margin-top: -1px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.sn-component .panel-table .table-item img {
max-width: 100%;
margin-bottom: 1rem;
}
.sn-component .panel-table .table-item .item-content {
display: flex;
flex-direction: row;
}
.sn-component .panel-table .table-item .item-column {
align-items: center;
}
.sn-component .panel-table .table-item .item-column:not(:first-child) {
padding-left: 0.75rem;
}
.sn-component .panel-table .table-item .item-column.quarter {
flex-basis: 25%;
}
.sn-component .panel-table .table-item .item-column.three-quarters {
flex-basis: 75%;
}
.sn-component .panel-table .table-item .item-footer {
margin-top: 1.25rem;
}
.sn-component .panel-table .table-item.no-border {
border: none;
}
/*# sourceMappingURL=stylekit.css.map */