@navita/css 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +35 -0
- package/index.js +198 -0
- package/index.mjs +186 -0
- package/package.json +19 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { StyleRule, GlobalStyleRule, CSSKeyframes, NullableTokens, ThemeVars, Tokens, Contract, MapLeafNodes, CSSVarFunction } from '@navita/types';
|
|
2
|
+
|
|
3
|
+
declare function style(rule: StyleRule): string;
|
|
4
|
+
|
|
5
|
+
declare function globalStyle(selector: string, rule: GlobalStyleRule): void;
|
|
6
|
+
|
|
7
|
+
declare function merge(...classNames: (string | boolean)[]): string;
|
|
8
|
+
|
|
9
|
+
declare function keyframes(rule: CSSKeyframes): string;
|
|
10
|
+
|
|
11
|
+
declare function createThemeContract<ThemeTokens extends NullableTokens>(tokens: ThemeTokens): ThemeVars<ThemeTokens>;
|
|
12
|
+
declare function createGlobalThemeContract<ThemeTokens extends Tokens>(tokens: ThemeTokens): ThemeVars<ThemeTokens>;
|
|
13
|
+
declare function createGlobalThemeContract<ThemeTokens extends NullableTokens>(tokens: ThemeTokens, mapFn: (value: string | null, path: Array<string>) => string): ThemeVars<ThemeTokens>;
|
|
14
|
+
declare function createGlobalTheme<ThemeTokens extends Tokens>(selector: string, tokens: ThemeTokens): ThemeVars<ThemeTokens>;
|
|
15
|
+
declare function createGlobalTheme<ThemeContract extends Contract>(selector: string, themeContract: ThemeContract, tokens: MapLeafNodes<ThemeContract, string>): void;
|
|
16
|
+
declare function createTheme<ThemeTokens extends Tokens>(tokens: ThemeTokens, debugId?: string): [className: string, vars: ThemeVars<ThemeTokens>];
|
|
17
|
+
declare function createTheme<ThemeContract extends Contract>(themeContract: ThemeContract, tokens: MapLeafNodes<ThemeContract, string>, debugId?: string): string;
|
|
18
|
+
|
|
19
|
+
declare function assignVars<VarContract extends Contract>(varContract: VarContract, tokens: MapLeafNodes<VarContract, string>): Record<CSSVarFunction, string>;
|
|
20
|
+
|
|
21
|
+
declare class ClassList extends String {
|
|
22
|
+
classList: {
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
};
|
|
25
|
+
constructor(str: string, classList: {
|
|
26
|
+
[key: string]: any;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
declare const importMap: {
|
|
31
|
+
callee: string;
|
|
32
|
+
source: string;
|
|
33
|
+
}[];
|
|
34
|
+
|
|
35
|
+
export { ClassList, assignVars, createGlobalTheme, createGlobalThemeContract, createTheme, createThemeContract, globalStyle, importMap, keyframes, merge, style };
|
package/index.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@navita/core');
|
|
4
|
+
var cssesc = require('cssesc');
|
|
5
|
+
var chalk = require('chalk');
|
|
6
|
+
var deepObjectDiff = require('deep-object-diff');
|
|
7
|
+
|
|
8
|
+
function style(rule) {
|
|
9
|
+
return core.setCss(rule);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function globalStyle(selector, rule) {
|
|
13
|
+
core.setStaticCss(selector, rule);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function merge(...classNames) {
|
|
17
|
+
return [
|
|
18
|
+
...new Map(classNames.filter(Boolean).reverse().flatMap((className)=>className.split(' ')).map((className)=>className.split('-')).reverse())
|
|
19
|
+
].map((className)=>className.filter(Boolean).join('-')).join(' ');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function keyframes(rule) {
|
|
23
|
+
return core.setKeyFrame(rule);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function walkObject(objectToWalk, transformFn, currentPath = []) {
|
|
27
|
+
const clonedObject = objectToWalk.constructor();
|
|
28
|
+
for(const key in objectToWalk){
|
|
29
|
+
const value = objectToWalk[key];
|
|
30
|
+
const newPath = [
|
|
31
|
+
...currentPath,
|
|
32
|
+
key
|
|
33
|
+
];
|
|
34
|
+
if (typeof value === 'string' || typeof value === 'number' || value == null) {
|
|
35
|
+
clonedObject[key] = transformFn(value, newPath);
|
|
36
|
+
} else if (typeof value === 'object' && !Array.isArray(value)) {
|
|
37
|
+
clonedObject[key] = walkObject(value, transformFn, newPath);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return clonedObject;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const normaliseObject = (obj)=>walkObject(obj, ()=>'');
|
|
44
|
+
function validateContract(contract, tokens) {
|
|
45
|
+
const theDiff = deepObjectDiff.diff(normaliseObject(contract), normaliseObject(tokens));
|
|
46
|
+
const valid = Object.keys(theDiff).length === 0;
|
|
47
|
+
return {
|
|
48
|
+
valid,
|
|
49
|
+
diffString: valid ? '' : renderDiff(contract, theDiff)
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function diffLine(value, nesting, type) {
|
|
53
|
+
const whitespace = [
|
|
54
|
+
...Array(nesting).keys()
|
|
55
|
+
].map(()=>' ').join('');
|
|
56
|
+
const line = `${type ? type : ' '}${whitespace}${value}`;
|
|
57
|
+
{
|
|
58
|
+
if (type === '-') {
|
|
59
|
+
return chalk.red(line);
|
|
60
|
+
}
|
|
61
|
+
if (type === '+') {
|
|
62
|
+
return chalk.green(line);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return line;
|
|
66
|
+
}
|
|
67
|
+
function renderDiff(orig, diff, nesting = 0) {
|
|
68
|
+
const lines = [];
|
|
69
|
+
if (nesting === 0) {
|
|
70
|
+
lines.push(diffLine('{', 0));
|
|
71
|
+
}
|
|
72
|
+
const innerNesting = nesting + 1;
|
|
73
|
+
const keys = Object.keys(diff).sort();
|
|
74
|
+
for (const key of keys){
|
|
75
|
+
const value = diff[key];
|
|
76
|
+
if (!(key in orig)) {
|
|
77
|
+
lines.push(diffLine(`${key}: ...,`, innerNesting, '+'));
|
|
78
|
+
} else if (typeof value === 'object') {
|
|
79
|
+
lines.push(diffLine(`${key}: {`, innerNesting));
|
|
80
|
+
lines.push(renderDiff(orig[key], diff[key], innerNesting));
|
|
81
|
+
lines.push(diffLine('}', innerNesting));
|
|
82
|
+
} else {
|
|
83
|
+
lines.push(diffLine(`${key}: ...,`, innerNesting, '-'));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (nesting === 0) {
|
|
87
|
+
lines.push(diffLine('}', 0));
|
|
88
|
+
}
|
|
89
|
+
return lines.join('\n');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function createVar(name) {
|
|
93
|
+
return `var(--${cssesc(name, {
|
|
94
|
+
isIdentifier: true
|
|
95
|
+
})})`;
|
|
96
|
+
}
|
|
97
|
+
function assignVars(varContract, tokens) {
|
|
98
|
+
const varSetters = {};
|
|
99
|
+
const { valid , diffString } = validateContract(varContract, tokens);
|
|
100
|
+
if (!valid) {
|
|
101
|
+
throw new Error(`Tokens don't match contract.\n${diffString}`);
|
|
102
|
+
}
|
|
103
|
+
walkObject(tokens, (value, path)=>{
|
|
104
|
+
const cssVarWithoutVar = `--${cssesc(path.join('-').toLowerCase(), {
|
|
105
|
+
isIdentifier: true
|
|
106
|
+
})}`;
|
|
107
|
+
varSetters[cssVarWithoutVar] = String(value);
|
|
108
|
+
});
|
|
109
|
+
return varSetters;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function createThemeContract(tokens) {
|
|
113
|
+
return walkObject(tokens, (_value, path)=>{
|
|
114
|
+
return createVar(path.join('-').toLowerCase());
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function createGlobalThemeContract(tokens, mapFn) {
|
|
118
|
+
return walkObject(tokens, (value, path)=>{
|
|
119
|
+
const rawVarName = typeof mapFn === 'function' ? mapFn(value, path) : value;
|
|
120
|
+
const varName = typeof rawVarName === 'string' ? rawVarName.replace(/^\-\-/, '') : null;
|
|
121
|
+
if (typeof varName !== 'string' || varName !== cssesc(varName, {
|
|
122
|
+
isIdentifier: true
|
|
123
|
+
})) {
|
|
124
|
+
throw new Error(`Invalid variable name for "${path.join('.')}": ${varName}`);
|
|
125
|
+
}
|
|
126
|
+
return `var(--${varName})`;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function createGlobalTheme(selector, arg2, arg3) {
|
|
130
|
+
const shouldCreateVars = Boolean(!arg3);
|
|
131
|
+
const themeVars = shouldCreateVars ? createThemeContract(arg2) : arg2;
|
|
132
|
+
const tokens = shouldCreateVars ? arg2 : arg3;
|
|
133
|
+
const temp = assignVars(themeVars, tokens);
|
|
134
|
+
core.setStaticCss(selector, temp);
|
|
135
|
+
// Todo: setStaticCss
|
|
136
|
+
if (shouldCreateVars) {
|
|
137
|
+
return themeVars;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function createTheme(arg1, arg2, arg3) {
|
|
141
|
+
const themeClassName = core.generateIdentifier(typeof arg2 === 'object' ? arg3 : arg2);
|
|
142
|
+
const vars = typeof arg2 === 'object' ? createGlobalTheme(themeClassName, arg1, arg2) : createGlobalTheme(themeClassName, arg1);
|
|
143
|
+
return vars ? [
|
|
144
|
+
themeClassName,
|
|
145
|
+
vars
|
|
146
|
+
] : themeClassName;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
class ClassList extends String {
|
|
150
|
+
constructor(str, classList){
|
|
151
|
+
super(str);
|
|
152
|
+
this.classList = classList;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const source = '@navita/css';
|
|
157
|
+
const importMap = [
|
|
158
|
+
{
|
|
159
|
+
callee: "style",
|
|
160
|
+
source
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
callee: "globalStyle",
|
|
164
|
+
source
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
callee: "keyframes",
|
|
168
|
+
source
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
callee: "createThemeContract",
|
|
172
|
+
source
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
callee: "createGlobalThemeContract",
|
|
176
|
+
source
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
callee: "createGlobalTheme",
|
|
180
|
+
source
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
callee: "createTheme",
|
|
184
|
+
source
|
|
185
|
+
}
|
|
186
|
+
];
|
|
187
|
+
|
|
188
|
+
exports.ClassList = ClassList;
|
|
189
|
+
exports.assignVars = assignVars;
|
|
190
|
+
exports.createGlobalTheme = createGlobalTheme;
|
|
191
|
+
exports.createGlobalThemeContract = createGlobalThemeContract;
|
|
192
|
+
exports.createTheme = createTheme;
|
|
193
|
+
exports.createThemeContract = createThemeContract;
|
|
194
|
+
exports.globalStyle = globalStyle;
|
|
195
|
+
exports.importMap = importMap;
|
|
196
|
+
exports.keyframes = keyframes;
|
|
197
|
+
exports.merge = merge;
|
|
198
|
+
exports.style = style;
|
package/index.mjs
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { setCss, setStaticCss, setKeyFrame, generateIdentifier } from '@navita/core';
|
|
2
|
+
import cssesc from 'cssesc';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { diff } from 'deep-object-diff';
|
|
5
|
+
|
|
6
|
+
function style(rule) {
|
|
7
|
+
return setCss(rule);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function globalStyle(selector, rule) {
|
|
11
|
+
setStaticCss(selector, rule);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function merge(...classNames) {
|
|
15
|
+
return [
|
|
16
|
+
...new Map(classNames.filter(Boolean).reverse().flatMap((className)=>className.split(' ')).map((className)=>className.split('-')).reverse())
|
|
17
|
+
].map((className)=>className.filter(Boolean).join('-')).join(' ');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function keyframes(rule) {
|
|
21
|
+
return setKeyFrame(rule);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function walkObject(objectToWalk, transformFn, currentPath = []) {
|
|
25
|
+
const clonedObject = objectToWalk.constructor();
|
|
26
|
+
for(const key in objectToWalk){
|
|
27
|
+
const value = objectToWalk[key];
|
|
28
|
+
const newPath = [
|
|
29
|
+
...currentPath,
|
|
30
|
+
key
|
|
31
|
+
];
|
|
32
|
+
if (typeof value === 'string' || typeof value === 'number' || value == null) {
|
|
33
|
+
clonedObject[key] = transformFn(value, newPath);
|
|
34
|
+
} else if (typeof value === 'object' && !Array.isArray(value)) {
|
|
35
|
+
clonedObject[key] = walkObject(value, transformFn, newPath);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return clonedObject;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const normaliseObject = (obj)=>walkObject(obj, ()=>'');
|
|
42
|
+
function validateContract(contract, tokens) {
|
|
43
|
+
const theDiff = diff(normaliseObject(contract), normaliseObject(tokens));
|
|
44
|
+
const valid = Object.keys(theDiff).length === 0;
|
|
45
|
+
return {
|
|
46
|
+
valid,
|
|
47
|
+
diffString: valid ? '' : renderDiff(contract, theDiff)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function diffLine(value, nesting, type) {
|
|
51
|
+
const whitespace = [
|
|
52
|
+
...Array(nesting).keys()
|
|
53
|
+
].map(()=>' ').join('');
|
|
54
|
+
const line = `${type ? type : ' '}${whitespace}${value}`;
|
|
55
|
+
{
|
|
56
|
+
if (type === '-') {
|
|
57
|
+
return chalk.red(line);
|
|
58
|
+
}
|
|
59
|
+
if (type === '+') {
|
|
60
|
+
return chalk.green(line);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return line;
|
|
64
|
+
}
|
|
65
|
+
function renderDiff(orig, diff, nesting = 0) {
|
|
66
|
+
const lines = [];
|
|
67
|
+
if (nesting === 0) {
|
|
68
|
+
lines.push(diffLine('{', 0));
|
|
69
|
+
}
|
|
70
|
+
const innerNesting = nesting + 1;
|
|
71
|
+
const keys = Object.keys(diff).sort();
|
|
72
|
+
for (const key of keys){
|
|
73
|
+
const value = diff[key];
|
|
74
|
+
if (!(key in orig)) {
|
|
75
|
+
lines.push(diffLine(`${key}: ...,`, innerNesting, '+'));
|
|
76
|
+
} else if (typeof value === 'object') {
|
|
77
|
+
lines.push(diffLine(`${key}: {`, innerNesting));
|
|
78
|
+
lines.push(renderDiff(orig[key], diff[key], innerNesting));
|
|
79
|
+
lines.push(diffLine('}', innerNesting));
|
|
80
|
+
} else {
|
|
81
|
+
lines.push(diffLine(`${key}: ...,`, innerNesting, '-'));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (nesting === 0) {
|
|
85
|
+
lines.push(diffLine('}', 0));
|
|
86
|
+
}
|
|
87
|
+
return lines.join('\n');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function createVar(name) {
|
|
91
|
+
return `var(--${cssesc(name, {
|
|
92
|
+
isIdentifier: true
|
|
93
|
+
})})`;
|
|
94
|
+
}
|
|
95
|
+
function assignVars(varContract, tokens) {
|
|
96
|
+
const varSetters = {};
|
|
97
|
+
const { valid , diffString } = validateContract(varContract, tokens);
|
|
98
|
+
if (!valid) {
|
|
99
|
+
throw new Error(`Tokens don't match contract.\n${diffString}`);
|
|
100
|
+
}
|
|
101
|
+
walkObject(tokens, (value, path)=>{
|
|
102
|
+
const cssVarWithoutVar = `--${cssesc(path.join('-').toLowerCase(), {
|
|
103
|
+
isIdentifier: true
|
|
104
|
+
})}`;
|
|
105
|
+
varSetters[cssVarWithoutVar] = String(value);
|
|
106
|
+
});
|
|
107
|
+
return varSetters;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function createThemeContract(tokens) {
|
|
111
|
+
return walkObject(tokens, (_value, path)=>{
|
|
112
|
+
return createVar(path.join('-').toLowerCase());
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
function createGlobalThemeContract(tokens, mapFn) {
|
|
116
|
+
return walkObject(tokens, (value, path)=>{
|
|
117
|
+
const rawVarName = typeof mapFn === 'function' ? mapFn(value, path) : value;
|
|
118
|
+
const varName = typeof rawVarName === 'string' ? rawVarName.replace(/^\-\-/, '') : null;
|
|
119
|
+
if (typeof varName !== 'string' || varName !== cssesc(varName, {
|
|
120
|
+
isIdentifier: true
|
|
121
|
+
})) {
|
|
122
|
+
throw new Error(`Invalid variable name for "${path.join('.')}": ${varName}`);
|
|
123
|
+
}
|
|
124
|
+
return `var(--${varName})`;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function createGlobalTheme(selector, arg2, arg3) {
|
|
128
|
+
const shouldCreateVars = Boolean(!arg3);
|
|
129
|
+
const themeVars = shouldCreateVars ? createThemeContract(arg2) : arg2;
|
|
130
|
+
const tokens = shouldCreateVars ? arg2 : arg3;
|
|
131
|
+
const temp = assignVars(themeVars, tokens);
|
|
132
|
+
setStaticCss(selector, temp);
|
|
133
|
+
// Todo: setStaticCss
|
|
134
|
+
if (shouldCreateVars) {
|
|
135
|
+
return themeVars;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function createTheme(arg1, arg2, arg3) {
|
|
139
|
+
const themeClassName = generateIdentifier(typeof arg2 === 'object' ? arg3 : arg2);
|
|
140
|
+
const vars = typeof arg2 === 'object' ? createGlobalTheme(themeClassName, arg1, arg2) : createGlobalTheme(themeClassName, arg1);
|
|
141
|
+
return vars ? [
|
|
142
|
+
themeClassName,
|
|
143
|
+
vars
|
|
144
|
+
] : themeClassName;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
class ClassList extends String {
|
|
148
|
+
constructor(str, classList){
|
|
149
|
+
super(str);
|
|
150
|
+
this.classList = classList;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const source = '@navita/css';
|
|
155
|
+
const importMap = [
|
|
156
|
+
{
|
|
157
|
+
callee: "style",
|
|
158
|
+
source
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
callee: "globalStyle",
|
|
162
|
+
source
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
callee: "keyframes",
|
|
166
|
+
source
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
callee: "createThemeContract",
|
|
170
|
+
source
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
callee: "createGlobalThemeContract",
|
|
174
|
+
source
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
callee: "createGlobalTheme",
|
|
178
|
+
source
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
callee: "createTheme",
|
|
182
|
+
source
|
|
183
|
+
}
|
|
184
|
+
];
|
|
185
|
+
|
|
186
|
+
export { ClassList, assignVars, createGlobalTheme, createGlobalThemeContract, createTheme, createThemeContract, globalStyle, importMap, keyframes, merge, style };
|
package/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"sideEffects": false,
|
|
3
|
+
"name": "@navita/css",
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"import": "./index.mjs",
|
|
8
|
+
"require": "./index.js",
|
|
9
|
+
"types": "./index.d.ts"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"deep-object-diff": "^1.1.9",
|
|
14
|
+
"cssesc": "^3.0.0",
|
|
15
|
+
"chalk": "^4.1.2",
|
|
16
|
+
"@navita/core": "*",
|
|
17
|
+
"@navita/types": "*"
|
|
18
|
+
}
|
|
19
|
+
}
|