mirror of
https://github.com/qlik-oss/nebula.js.git
synced 2025-12-19 09:48:18 -05:00
feat(theme): add theme API (#137)
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
"@material-ui/icons": "^4.5.1",
|
||||
"@material-ui/styles": "^4.5.0",
|
||||
"@nebula.js/supernova": "0.1.0-alpha.21",
|
||||
"@nebula.js/theme": "0.1.0-alpha.21",
|
||||
"@nebula.js/ui": "0.1.0-alpha.21",
|
||||
"node-event-emitter": "^0.0.1",
|
||||
"react": "^16.10.2",
|
||||
|
||||
@@ -19,6 +19,7 @@ describe('viz', () => {
|
||||
const { api: foo } = create({
|
||||
model: 'a',
|
||||
config: {},
|
||||
context: {},
|
||||
});
|
||||
api = foo;
|
||||
});
|
||||
@@ -40,7 +41,7 @@ describe('viz', () => {
|
||||
it('should not initiate mount when layout and sn are not defined', async () => {
|
||||
const boot = sinon.spy();
|
||||
const [{ default: create }] = doMock({ boot });
|
||||
const { api, setObjectProps } = create({});
|
||||
const { api, setObjectProps } = create({ context: {} });
|
||||
|
||||
api.mount('element');
|
||||
|
||||
@@ -53,7 +54,7 @@ describe('viz', () => {
|
||||
it('should initiate React mount when layout and supernova are valid', async () => {
|
||||
const boot = sinon.spy();
|
||||
const [{ default: create }] = doMock({ boot });
|
||||
const { api, setObjectProps } = create({});
|
||||
const { api, setObjectProps } = create({ context: {} });
|
||||
|
||||
api.mount('element');
|
||||
|
||||
@@ -73,7 +74,7 @@ describe('viz', () => {
|
||||
return {};
|
||||
});
|
||||
const [{ default: create }] = doMock({ boot });
|
||||
const { api, setObjectProps } = create({});
|
||||
const { api, setObjectProps } = create({ context: {} });
|
||||
|
||||
let mounted = false;
|
||||
|
||||
@@ -102,6 +103,7 @@ describe('viz', () => {
|
||||
};
|
||||
const { api } = create({
|
||||
model,
|
||||
context: {},
|
||||
});
|
||||
await api.setTemporaryProperties('new');
|
||||
expect(getter).to.have.been.calledWithExactly(model, 'effectiveProperties');
|
||||
@@ -118,6 +120,7 @@ describe('viz', () => {
|
||||
};
|
||||
const { api } = create({
|
||||
model,
|
||||
context: {},
|
||||
});
|
||||
await api.setTemporaryProperties('new');
|
||||
expect(getter).to.have.been.calledWithExactly(model, 'effectiveProperties');
|
||||
|
||||
@@ -136,8 +136,16 @@ class Supernova extends React.Component {
|
||||
resizeObserver.observe(this.element);
|
||||
}
|
||||
|
||||
const onThemeChanged = () => {
|
||||
this.setState({});
|
||||
};
|
||||
|
||||
this.props.snContext.theme.on('changed', onThemeChanged);
|
||||
this.theme = this.props.snContext.theme;
|
||||
|
||||
this.onUnmount = () => {
|
||||
this.onUnmount = null;
|
||||
this.props.snContext.theme.removeListener('changed', onThemeChanged);
|
||||
if (resizeObserver) {
|
||||
resizeObserver.unobserve(this.element);
|
||||
resizeObserver.disconnect();
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/* eslint no-underscore-dangle:0 */
|
||||
import 'regenerator-runtime/runtime'; // Polyfill for using async/await
|
||||
|
||||
import themeFn from '@nebula.js/theme';
|
||||
|
||||
import localeFn from './locale';
|
||||
|
||||
import { createAppSelectionAPI } from './selections';
|
||||
@@ -112,6 +114,8 @@ function nuked(configuration = {}, prev = {}) {
|
||||
direction: configuration.direction,
|
||||
});
|
||||
|
||||
const theme = themeFn();
|
||||
|
||||
const context = {
|
||||
nebbie: null,
|
||||
app,
|
||||
@@ -119,6 +123,7 @@ function nuked(configuration = {}, prev = {}) {
|
||||
logger,
|
||||
types,
|
||||
root,
|
||||
theme: theme.externalAPI,
|
||||
};
|
||||
|
||||
let selectionsApi = null;
|
||||
@@ -142,6 +147,9 @@ function nuked(configuration = {}, prev = {}) {
|
||||
*/
|
||||
create: (createCfg, vizConfig) => create(createCfg, vizConfig, context),
|
||||
theme(t) {
|
||||
theme.internalAPI.setTheme({
|
||||
type: t,
|
||||
});
|
||||
root.theme(t);
|
||||
return api;
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@ import eventMixin from './selections/event-mixin';
|
||||
|
||||
const noopi = () => {};
|
||||
|
||||
export default function({ model, context, initialUserProps = {} } = {}) {
|
||||
export default function({ model, context: nebulaContext, initialUserProps = {} } = {}) {
|
||||
let reference = noopi;
|
||||
let elementReference = null;
|
||||
|
||||
@@ -28,6 +28,7 @@ export default function({ model, context, initialUserProps = {} } = {}) {
|
||||
let userProps = {
|
||||
options: {},
|
||||
context: {
|
||||
theme: nebulaContext.theme,
|
||||
permissions: [],
|
||||
},
|
||||
...initialUserProps,
|
||||
@@ -58,6 +59,12 @@ export default function({ model, context, initialUserProps = {} } = {}) {
|
||||
userProps = {
|
||||
...userProps,
|
||||
...up,
|
||||
context: {
|
||||
// DO NOT MAKE A DEEP COPY OF THEME AS IT WOULD MESS UP THE INSTANCE
|
||||
...(userProps || {}).context,
|
||||
...(up || {}).context,
|
||||
theme: nebulaContext.theme,
|
||||
},
|
||||
};
|
||||
update();
|
||||
};
|
||||
@@ -100,7 +107,7 @@ export default function({ model, context, initialUserProps = {} } = {}) {
|
||||
element,
|
||||
model,
|
||||
api: cellApi,
|
||||
nebulaContext: context,
|
||||
nebulaContext,
|
||||
onInitial: mounted,
|
||||
});
|
||||
return whenMounted;
|
||||
|
||||
30
apis/theme/package.json
Normal file
30
apis/theme/package.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "@nebula.js/theme",
|
||||
"version": "0.1.0-alpha.21",
|
||||
"description": "",
|
||||
"license": "MIT",
|
||||
"author": "QlikTech International AB",
|
||||
"keywords": [],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/qlik-oss/nebula.js.git"
|
||||
},
|
||||
"main": "dist/theme.js",
|
||||
"module": "dist/theme.esm.js",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "cross-env NODE_ENV=production rollup --config ../../rollup.config.js",
|
||||
"build:dev": "rollup --config ../../rollup.config.js",
|
||||
"build:watch": "rollup --config ../../rollup.config.js -w",
|
||||
"prepublishOnly": "rm -rf dist && yarn run build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"extend": "^3.0.2",
|
||||
"node-event-emitter": "^0.0.1"
|
||||
}
|
||||
}
|
||||
100
apis/theme/src/index.js
Normal file
100
apis/theme/src/index.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import extend from 'extend';
|
||||
import EventEmitter from 'node-event-emitter';
|
||||
|
||||
import styleResolverFn from './style-resolver';
|
||||
import paletteResolverFn from './paletter-resolver';
|
||||
|
||||
import baseRawJSON from './themes/base.json';
|
||||
import lightRawJSON from './themes/light.json';
|
||||
import darkRawJSON from './themes/dark.json';
|
||||
|
||||
export default function theme() {
|
||||
let rawThemeJSON;
|
||||
let resolvedThemeJSON;
|
||||
let styleResolverInstanceCache = {};
|
||||
|
||||
let paletteResolver;
|
||||
|
||||
/**
|
||||
* @interface
|
||||
* @alias Theme
|
||||
*/
|
||||
const externalAPI = /** @lends Theme */ {
|
||||
palettes(...a) {
|
||||
return paletteResolver.palettes(...a);
|
||||
},
|
||||
dataScales(...a) {
|
||||
return paletteResolver.dataScales(...a);
|
||||
},
|
||||
dataPalettes(...a) {
|
||||
return paletteResolver.dataPalettes(...a);
|
||||
},
|
||||
uiPalettes(...a) {
|
||||
return paletteResolver.uiPalettes(...a);
|
||||
},
|
||||
dataColors(...a) {
|
||||
return paletteResolver.dataColors(...a);
|
||||
},
|
||||
/**
|
||||
* Resolve a color object using the UI palette from the provided JSON theme
|
||||
* @param {object} c
|
||||
* @param {number=} c.index
|
||||
* @param {string=} c.color
|
||||
* @returns {string}
|
||||
*
|
||||
* @example
|
||||
* theme.uiColor({ index: 1, color: 'red' });
|
||||
*/
|
||||
uiColor(...a) {
|
||||
return paletteResolver.uiColor(...a);
|
||||
},
|
||||
/**
|
||||
* Get the value of a style attribute in the theme by searching in the theme's json structure.
|
||||
* The search starts at the specified base path and continue upwards until the value is found.
|
||||
* If possible it will get the attribute's value using the given path.
|
||||
*
|
||||
* @param {string} basePath - Base path in the theme's json structure to start the search in (specified as a name path separated by dots)
|
||||
* @param {string} path - Expected path for the attribute (specified as a name path separated by dots)
|
||||
* @param {string} attribute - Name of the style attribute
|
||||
* @return {string} The style value
|
||||
*
|
||||
* @example
|
||||
* theme.getStyle('object', 'title.main', 'fontSize'));
|
||||
* theme.getStyle('', '', 'fontSize'));
|
||||
*/
|
||||
getStyle(basePath, path, attribute) {
|
||||
if (!styleResolverInstanceCache[basePath]) {
|
||||
styleResolverInstanceCache[basePath] = styleResolverFn(basePath, resolvedThemeJSON);
|
||||
}
|
||||
return styleResolverInstanceCache[basePath].getStyle(path, attribute, false);
|
||||
},
|
||||
};
|
||||
|
||||
const internalAPI = {
|
||||
/**
|
||||
* @param {object} t Raw JSON theme
|
||||
*/
|
||||
setTheme(t) {
|
||||
const colorRawJSON = t.type === 'dark' ? darkRawJSON : lightRawJSON;
|
||||
rawThemeJSON = extend(true, {}, baseRawJSON, colorRawJSON, t);
|
||||
styleResolverInstanceCache = {};
|
||||
|
||||
resolvedThemeJSON = styleResolverFn.resolveRawTheme(rawThemeJSON);
|
||||
paletteResolver = paletteResolverFn(resolvedThemeJSON);
|
||||
|
||||
externalAPI.emit('changed');
|
||||
},
|
||||
};
|
||||
|
||||
Object.keys(EventEmitter.prototype).forEach(key => {
|
||||
externalAPI[key] = EventEmitter.prototype[key];
|
||||
});
|
||||
EventEmitter.init(externalAPI);
|
||||
|
||||
internalAPI.setTheme({});
|
||||
|
||||
return {
|
||||
externalAPI,
|
||||
internalAPI,
|
||||
};
|
||||
}
|
||||
84
apis/theme/src/paletter-resolver.js
Normal file
84
apis/theme/src/paletter-resolver.js
Normal file
@@ -0,0 +1,84 @@
|
||||
export default function theme(resolvedTheme) {
|
||||
let uiPalette;
|
||||
|
||||
return {
|
||||
palettes(type, key = '') {
|
||||
const pals = [];
|
||||
if (type === 'qualitative') {
|
||||
pals.push(...this.dataPalettes());
|
||||
} else if (type === 'scale') {
|
||||
pals.push(...this.dataScales());
|
||||
} else {
|
||||
pals.push(...this.dataPalettes(), ...this.dataScales());
|
||||
}
|
||||
if (key) {
|
||||
return pals.filter(p => p.key === key);
|
||||
}
|
||||
return pals;
|
||||
},
|
||||
dataScales() {
|
||||
const pals = [];
|
||||
resolvedTheme.scales.forEach(s => {
|
||||
pals.push({
|
||||
key: s.propertyValue,
|
||||
name: s.name,
|
||||
translation: s.translation,
|
||||
scheme: true, // indicate that this is scheme that can be used to generate more colors
|
||||
type: s.type, // gradient, class, pyramid, row
|
||||
colors: s.scale,
|
||||
});
|
||||
});
|
||||
|
||||
return pals;
|
||||
},
|
||||
dataPalettes() {
|
||||
const pals = [];
|
||||
resolvedTheme.palettes.data.forEach(s => {
|
||||
pals.push({
|
||||
key: s.propertyValue,
|
||||
name: s.name,
|
||||
translation: s.translation,
|
||||
type: s.type,
|
||||
colors: s.scale,
|
||||
});
|
||||
});
|
||||
|
||||
return pals;
|
||||
},
|
||||
uiPalettes() {
|
||||
const pals = [];
|
||||
resolvedTheme.palettes.ui.forEach(s => {
|
||||
pals.push({
|
||||
key: 'ui',
|
||||
name: s.name,
|
||||
translation: s.translation,
|
||||
type: 'row',
|
||||
colors: s.colors,
|
||||
});
|
||||
});
|
||||
return pals;
|
||||
},
|
||||
dataColors() {
|
||||
return {
|
||||
primary: resolvedTheme.dataColors.primaryColor,
|
||||
nil: resolvedTheme.dataColors.nullColor,
|
||||
others: resolvedTheme.dataColors.othersColor,
|
||||
};
|
||||
},
|
||||
uiColor(c) {
|
||||
if (c.index < 0 || typeof c.index === 'undefined') {
|
||||
return c.color;
|
||||
}
|
||||
if (typeof uiPalette === 'undefined') {
|
||||
uiPalette = this.uiPalettes()[0] || false;
|
||||
}
|
||||
if (!uiPalette) {
|
||||
return c.color;
|
||||
}
|
||||
if (typeof uiPalette.colors[c.index] === 'undefined') {
|
||||
return c.color;
|
||||
}
|
||||
return uiPalette.colors[c.index];
|
||||
},
|
||||
};
|
||||
}
|
||||
141
apis/theme/src/style-resolver.js
Normal file
141
apis/theme/src/style-resolver.js
Normal file
@@ -0,0 +1,141 @@
|
||||
import extend from 'extend';
|
||||
|
||||
/**
|
||||
* Creates the follwing array of paths
|
||||
* object.barChart - legend.title - fontSize
|
||||
* object - legend.title - fontSize
|
||||
* legend.title - fontSize
|
||||
* object.barChart - legend - fontSize
|
||||
* object - legend - fontSize
|
||||
* legend - fontSize
|
||||
* object.barChart - fontSize
|
||||
* object - fontSize
|
||||
* fontSize
|
||||
* @ignore
|
||||
*/
|
||||
function constructPaths(pathSteps, baseSteps) {
|
||||
const ret = [];
|
||||
let localBaseSteps;
|
||||
let baseLength;
|
||||
if (pathSteps) {
|
||||
let pathLength = pathSteps.length;
|
||||
while (pathLength >= 0) {
|
||||
localBaseSteps = baseSteps.slice();
|
||||
baseLength = localBaseSteps.length;
|
||||
while (baseLength >= 0) {
|
||||
ret.push(localBaseSteps.concat(pathSteps));
|
||||
localBaseSteps.pop();
|
||||
baseLength--;
|
||||
}
|
||||
pathSteps.pop();
|
||||
pathLength--;
|
||||
}
|
||||
} else {
|
||||
localBaseSteps = baseSteps.slice();
|
||||
baseLength = localBaseSteps.length;
|
||||
while (baseLength >= 0) {
|
||||
ret.push(localBaseSteps.concat());
|
||||
localBaseSteps.pop();
|
||||
baseLength--;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getObject(root, steps) {
|
||||
let obj = root;
|
||||
for (let i = 0; i < steps.length; i++) {
|
||||
if (obj[steps[i]]) {
|
||||
obj = obj[steps[i]];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
function searchPathArray(pathArray, attribute, theme) {
|
||||
for (let i = 0; i < pathArray.length; i++) {
|
||||
const target = getObject(theme, pathArray[i]);
|
||||
if (target !== null && target[attribute]) {
|
||||
return target[attribute];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function searchValue(path, attribute, baseSteps, component) {
|
||||
let pathArray;
|
||||
if (path === '') {
|
||||
pathArray = constructPaths(null, baseSteps);
|
||||
} else {
|
||||
const steps = path.split('.');
|
||||
pathArray = constructPaths(steps, baseSteps);
|
||||
}
|
||||
return searchPathArray(pathArray, attribute, component);
|
||||
}
|
||||
|
||||
export default function styleResolver(basePath, themeJSON) {
|
||||
const basePathSteps = basePath.split('.');
|
||||
|
||||
const api = {
|
||||
/**
|
||||
*
|
||||
* Get the value of a style attribute, starting in the given base path + path
|
||||
* Ex: Base path: "object.barChart", Path: "legend.title", Attribute: "fontSize"
|
||||
* Will search in, and fall back to:
|
||||
* object.barChart - legend.title - fontSize
|
||||
* object - legend.title - fontSize
|
||||
* legend.title - fontSize
|
||||
* object.barChart - legend - fontSize
|
||||
* object - legend - fontSize
|
||||
* legend - fontSize
|
||||
* object.barChart - fontSize
|
||||
* object - fontSize
|
||||
* fontSize
|
||||
* @ignore
|
||||
*
|
||||
* @param {string} component string of properties seperated by dots to search in
|
||||
* @param {string} attribute to return
|
||||
* @returns {any} value of the resolved path, undefined if not found
|
||||
*/
|
||||
getStyle(component, attribute) {
|
||||
// TODO - object overrides
|
||||
// TODO - feature flag on font-family?
|
||||
// TODO - caching
|
||||
const baseSteps = basePathSteps.concat();
|
||||
const result = searchValue(component, attribute, baseSteps, themeJSON);
|
||||
|
||||
// TODO - support functions
|
||||
return result;
|
||||
},
|
||||
};
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate the object tree and resolve variables and functions.
|
||||
* @ignore
|
||||
* @param {Object} - objTree
|
||||
* @param {Object} - variables
|
||||
*/
|
||||
function resolveVariables(objTree, variables) {
|
||||
Object.keys(objTree).forEach(key => {
|
||||
if (typeof objTree[key] === 'object' && objTree[key] !== null) {
|
||||
resolveVariables(objTree[key], variables);
|
||||
} else if (typeof objTree[key] === 'string' && objTree[key].charAt(0) === '@') {
|
||||
// Resolve variables
|
||||
objTree[key] = variables[objTree[key]]; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
styleResolver.resolveRawTheme = raw => {
|
||||
// TODO - validate format
|
||||
// TODO - generate class-pyramid
|
||||
const c = extend(true, {}, raw);
|
||||
resolveVariables(c, c._variables); // eslint-disable-line
|
||||
|
||||
return c;
|
||||
};
|
||||
102
apis/theme/src/themes/base.json
Normal file
102
apis/theme/src/themes/base.json
Normal file
@@ -0,0 +1,102 @@
|
||||
{
|
||||
"fontSize": "13px",
|
||||
"fontFamily": "'Source Sans Pro', 'Arial', 'sans-serif'",
|
||||
"backgroundColor": "transparent",
|
||||
"dataColors": {
|
||||
"primaryColor": "#26a0a7",
|
||||
"othersColor": "#a5a5a5",
|
||||
"errorColor": "#ff4444",
|
||||
"nullColor": "#d2d2d2"
|
||||
},
|
||||
"scales": [
|
||||
{
|
||||
"name": "Sequential Gradient",
|
||||
"translation": "properties.colorScheme.sequential",
|
||||
"type": "gradient",
|
||||
"propertyValue": "sg",
|
||||
"scale": [
|
||||
"#26a0a7",
|
||||
"#c7ea8b"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Sequential Classes",
|
||||
"translation": "properties.colorScheme.sequentialC",
|
||||
"propertyValue": "sc",
|
||||
"type": "class",
|
||||
"scale": [
|
||||
"#26a0a7",
|
||||
"#c7ea8b"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Diverging gradient",
|
||||
"translation": "properties.colorScheme.diverging",
|
||||
"propertyValue": "dg",
|
||||
"type": "gradient",
|
||||
"scale": [
|
||||
"#26a0a7",
|
||||
"#c3ea8c",
|
||||
"#ec983d"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Diverging Classes",
|
||||
"translation": "properties.colorScheme.divergingC",
|
||||
"propertyValue": "dc",
|
||||
"type": "class",
|
||||
"scale": [
|
||||
"#26a0a7",
|
||||
"#c3ea8c",
|
||||
"#ec983d"
|
||||
]
|
||||
}
|
||||
],
|
||||
"palettes": {
|
||||
"data": [
|
||||
{
|
||||
"name": "12 Colors",
|
||||
"translation": "properties.colorNumberOfColors.12",
|
||||
"propertyValue": "12",
|
||||
"type": "pyramid",
|
||||
"scale": [
|
||||
[ "#26A0A7" ],
|
||||
[ "#26A0A7", "#EC983D" ],
|
||||
[ "#26A0A7", "#CBE989", "#EC983D" ],
|
||||
[ "#26A0A7", "#79D69F", "#F9EC86", "#EC983D" ],
|
||||
[ "#26A0A7", "#79D69F", "#CBE989", "#F9EC86", "#EC983D" ],
|
||||
[ "#26A0A7", "#65D3DA", "#79D69F", "#CBE989", "#F9EC86", "#EC983D" ],
|
||||
[ "#26A0A7", "#65D3DA", "#79D69F", "#CBE989", "#F9EC86", "#EC983D", "#D76C6C" ],
|
||||
[ "#26A0A7", "#65D3DA", "#79D69F", "#CBE989", "#F9EC86", "#FAD144", "#EC983D", "#D76C6C" ],
|
||||
[ "#138185", "#26A0A7", "#65D3DA", "#79D69F", "#CBE989", "#F9EC86", "#FAD144", "#EC983D", "#D76C6C" ],
|
||||
[ "#138185", "#26A0A7", "#65D3DA", "#79D69F", "#CBE989", "#EBF898", "#F9EC86", "#FAD144", "#EC983D", "#D76C6C" ],
|
||||
[ "#138185", "#26A0A7", "#65D3DA", "#79D69F", "#CBE989", "#EBF898", "#F9EC86", "#FAD144", "#EC983D", "#D76C6C", "#A54343" ],
|
||||
[ "#138185", "#26A0A7", "#65D3DA", "#79D69F", "#70BA6E", "#CBE989", "#EBF898", "#F9EC86", "#FAD144", "#EC983D", "#D76C6C", "#A54343" ]
|
||||
]
|
||||
}
|
||||
],
|
||||
"ui": [
|
||||
{
|
||||
"name": "Palette",
|
||||
"colors": [
|
||||
"#b0afae",
|
||||
"#7b7a78",
|
||||
"#a54343",
|
||||
"#d76c6c",
|
||||
"#ec983d",
|
||||
"#ecc43d",
|
||||
"#f9ec86",
|
||||
"#cbe989",
|
||||
"#70ba6e",
|
||||
"#578b60",
|
||||
"#79d69f",
|
||||
"#26a0a7",
|
||||
"#138185",
|
||||
"#65d3da",
|
||||
"#ffffff",
|
||||
"#000000"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
21
apis/theme/src/themes/dark.json
Normal file
21
apis/theme/src/themes/dark.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"_variables": {
|
||||
"@B20": "#333333",
|
||||
"@B35": "#595959",
|
||||
"@B45": "#737373",
|
||||
"@B50": "#808080",
|
||||
"@B60": "#999999",
|
||||
"@B80": "#cccccc",
|
||||
"@B90": "#e6e6e6",
|
||||
"@B98": "#fbfbfb",
|
||||
"@B100": "#ffffff",
|
||||
"@H1": "24px",
|
||||
"@H2": "18px",
|
||||
"@H3": "14px",
|
||||
"@H4": "13px",
|
||||
"@H5": "12px",
|
||||
"@H6": "10px"
|
||||
},
|
||||
"type": "dark",
|
||||
"color": "@B98"
|
||||
}
|
||||
21
apis/theme/src/themes/light.json
Normal file
21
apis/theme/src/themes/light.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"_variables": {
|
||||
"@B20": "#333333",
|
||||
"@B35": "#595959",
|
||||
"@B45": "#737373",
|
||||
"@B50": "#808080",
|
||||
"@B60": "#999999",
|
||||
"@B80": "#cccccc",
|
||||
"@B90": "#e6e6e6",
|
||||
"@B98": "#fbfbfb",
|
||||
"@B100": "#ffffff",
|
||||
"@H1": "24px",
|
||||
"@H2": "18px",
|
||||
"@H3": "14px",
|
||||
"@H4": "13px",
|
||||
"@H5": "12px",
|
||||
"@H6": "10px"
|
||||
},
|
||||
"type": "light",
|
||||
"color": "@B35"
|
||||
}
|
||||
@@ -29,6 +29,7 @@ const cfg = ({ srcDir, distDir, snPath, dev = false }) => {
|
||||
'@nebula.js/nucleus/src/object': path.resolve(process.cwd(), 'apis/nucleus/src/object'),
|
||||
'@nebula.js/nucleus': path.resolve(process.cwd(), 'apis/nucleus/src'),
|
||||
'@nebula.js/supernova': path.resolve(process.cwd(), 'apis/supernova/src'),
|
||||
'@nebula.js/theme': path.resolve(process.cwd(), 'apis/theme/src'),
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@ const nodeResolve = require('rollup-plugin-node-resolve');
|
||||
const commonjs = require('rollup-plugin-commonjs');
|
||||
const babel = require('rollup-plugin-babel');
|
||||
const replace = require('rollup-plugin-replace');
|
||||
const json = require('rollup-plugin-json');
|
||||
const { terser } = require('rollup-plugin-terser');
|
||||
|
||||
const cwd = process.cwd();
|
||||
@@ -102,6 +103,7 @@ const config = isEsm => {
|
||||
nodeResolve({
|
||||
extensions: ['.js', '.jsx'],
|
||||
}),
|
||||
json(),
|
||||
commonjs({
|
||||
namedExports: {
|
||||
react: [
|
||||
|
||||
@@ -10798,6 +10798,7 @@ rollup-plugin-dependency-flow@^0.3.0:
|
||||
rollup-plugin-json@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz#a18da0a4b30bf5ca1ee76ddb1422afbb84ae2b9e"
|
||||
integrity sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==
|
||||
dependencies:
|
||||
rollup-pluginutils "^2.5.0"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user