~repos /atoms-element

#js

git clone https://pyrossh.dev/repos/atoms-element.git

A simple web component library for defining your custom elements. It works on both client and server.


ba5668fd Peter John

4 years ago
improve add tw support
Files changed (8) hide show
  1. element.d.ts +0 -2
  2. element.js +400 -73
  3. example/app-counter.js +14 -44
  4. example/index.js +8 -14
  5. example/server.js +5 -3
  6. example/styles.js +1 -1
  7. page.d.ts +0 -1
  8. page.js +4 -3
element.d.ts CHANGED
@@ -24,7 +24,6 @@ export class AtomsElement {
24
24
  attrs: {[key: string]: any};
25
25
  state: {[key: string]: any};
26
26
  computed: {[key: string]: any};
27
- styles: {[key: string]: any};
28
27
  }
29
28
  export const getConfig = () => Config;
30
29
  export const getLocation = () => Location;
@@ -34,7 +33,6 @@ export type CreateElementProps = {
34
33
  attrTypes?: () => {[key: string]: any};
35
34
  stateTypes?: () => {[key: string]: any};
36
35
  computedTypes?: () => {[key: string]: any};
37
- styles?: {[key: string]: any};
38
36
  render: () => any
39
37
  }
40
38
 
element.js CHANGED
@@ -3,71 +3,402 @@ import { html, render as litRender, directive, NodePart, AttributePart, Property
3
3
  const isBrowser = typeof window !== 'undefined';
4
4
  export { html, isBrowser };
5
5
 
6
+ const hyphenate = (s) => s.replace(/[A-Z]|^ms/g, '-$&').toLowerCase();
7
+
8
+ export const css = (obj, isChild = false, indent = '') => {
6
- // Taken from emotion
9
+ const cssText = Object.keys(obj).reduce((acc, key) => {
7
- const murmur2 = (str) => {
10
+ const value = obj[key];
8
- var h = 0;
9
- var k,
10
- i = 0,
11
- len = str.length;
11
+ acc += !isChild ? `${key} {\n` : '';
12
- for (; len >= 4; ++i, len -= 4) {
12
+ if (typeof value === 'object') {
13
- k = (str.charCodeAt(i) & 0xff) | ((str.charCodeAt(++i) & 0xff) << 8) | ((str.charCodeAt(++i) & 0xff) << 16) | ((str.charCodeAt(++i) & 0xff) << 24);
14
- k = (k & 0xffff) * 0x5bd1e995 + (((k >>> 16) * 0xe995) << 16);
13
+ acc += '\n ' + indent + css(value, true, indent + ' ');
15
- k ^= k >>> 24;
14
+ } else {
16
- h = ((k & 0xffff) * 0x5bd1e995 + (((k >>> 16) * 0xe995) << 16)) ^ ((h & 0xffff) * 0x5bd1e995 + (((h >>> 16) * 0xe995) << 16));
15
+ acc += ' ' + indent + hyphenate(key) + ': ' + value + ';\n';
17
- }
16
+ }
18
- switch (len) {
19
- case 3:
20
- h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
21
- case 2:
22
- h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
23
- case 1:
24
- h ^= str.charCodeAt(i) & 0xff;
17
+ acc += !isChild ? `\n}\n` : '';
25
- h = (h & 0xffff) * 0x5bd1e995 + (((h >>> 16) * 0xe995) << 16);
18
+ return acc;
26
- }
27
- h ^= h >>> 13;
19
+ }, '');
28
- h = (h & 0xffff) * 0x5bd1e995 + (((h >>> 16) * 0xe995) << 16);
29
- return ((h ^ (h >>> 15)) >>> 0).toString(36);
20
+ return cssText;
30
21
  };
31
22
 
32
- const hyphenate = (s) => s.replace(/[A-Z]|^ms/g, '-$&').toLowerCase();
23
+ // const width = Dimensions.get('screen').width;
24
+ // let bp = '';
25
+ // if (width >= 640 && width <= 768) {
26
+ // bp = 'sm';
27
+ // } else if (width >= 768 && width < 1024) {
28
+ // bp = 'md';
29
+ // } else if (width >= 1024 && width < 1280) {
30
+ // bp = 'lg';
31
+ // } else if (width >= 1280 && width < 1536) {
32
+ // bp = 'xl';
33
+ // } else if (width >= 1536) {
34
+ // bp = '2xl';
35
+ // }
36
+
37
+ const colors = {
38
+ keys: {
39
+ bg: 'backgroundColor',
40
+ text: 'color',
41
+ b: 'borderColor',
42
+ bl: 'borderLeftColor',
43
+ br: 'borderRightColor',
44
+ bt: 'borderTopColor',
45
+ bb: 'borderBottomColor',
46
+ },
47
+ values: {
48
+ transparent: 'transparent',
49
+ current: 'currentColor',
50
+ black: 'rgba(0, 0, 0, 1)',
51
+ white: 'rgba(255, 255, 255, 1)',
52
+ 'gray-50': 'rgba(249, 250, 251, 1)',
53
+ 'gray-100': 'rgba(243, 244, 246, 1)',
54
+ 'gray-200': 'rgba(229, 231, 235, 1)',
55
+ 'gray-300': 'rgba(209, 213, 219, 1)',
56
+ 'gray-400': 'rgba(156, 163, 175, 1)',
57
+ 'gray-500': 'rgba(107, 114, 128, 1)',
58
+ 'gray-600': 'rgba(75, 85, 99, 1)',
59
+ 'gray-700': 'rgba(55, 65, 81, 1)',
60
+ 'gray-800': 'rgba(31, 41, 55, 1)',
61
+ 'gray-900': 'rgba(17, 24, 39, 1)',
62
+ 'red-50': 'rgba(254, 242, 242, 1)',
63
+ 'red-100': 'rgba(254, 226, 226, 1)',
64
+ 'red-200': 'rgba(254, 202, 202, 1)',
65
+ 'red-300': 'rgba(252, 165, 165, 1)',
66
+ 'red-400': 'rgba(248, 113, 113, 1)',
67
+ 'red-500': 'rgba(239, 68, 68, 1)',
68
+ 'red-600': 'rgba(220, 38, 38, 1)',
69
+ 'red-700': 'rgba(185, 28, 28, 1)',
70
+ 'red-800': 'rgba(153, 27, 27, 1)',
71
+ 'red-900': 'rgba(127, 29, 29, 1)',
72
+ 'yellow-50': 'rgba(255, 251, 235, 1)',
73
+ 'yellow-100': 'rgba(254, 243, 199, 1)',
74
+ 'yellow-200': 'rgba(253, 230, 138, 1)',
75
+ 'yellow-300': 'rgba(252, 211, 77, 1)',
76
+ 'yellow-400': 'rgba(251, 191, 36, 1)',
77
+ 'yellow-500': 'rgba(245, 158, 11, 1)',
78
+ 'yellow-600': 'rgba(217, 119, 6, 1)',
79
+ 'yellow-700': 'rgba(180, 83, 9, 1)',
80
+ 'yellow-800': 'rgba(146, 64, 14, 1)',
81
+ 'yellow-900': 'rgba(120, 53, 15, 1)',
82
+ 'green-50': 'rgba(236, 253, 245, 1)',
83
+ 'green-100': 'rgba(209, 250, 229, 1)',
84
+ 'green-200': 'rgba(167, 243, 208, 1)',
85
+ 'green-300': 'rgba(110, 231, 183, 1)',
86
+ 'green-400': 'rgba(52, 211, 153, 1)',
87
+ 'green-500': 'rgba(16, 185, 129, 1)',
88
+ 'green-600': 'rgba(5, 150, 105, 1)',
89
+ 'green-700': 'rgba(4, 120, 87, 1)',
90
+ 'green-800': 'rgba(6, 95, 70, 1)',
91
+ 'green-900': 'rgba(6, 78, 59, 1)',
92
+ 'blue-50': 'rgba(239, 246, 255, 1)',
93
+ 'blue-100': 'rgba(219, 234, 254, 1)',
94
+ 'blue-200': 'rgba(191, 219, 254, 1)',
95
+ 'blue-300': 'rgba(147, 197, 253, 1)',
96
+ 'blue-400': 'rgba(96, 165, 250, 1)',
97
+ 'blue-500': 'rgba(59, 130, 246, 1)',
98
+ 'blue-600': 'rgba(37, 99, 235, 1)',
99
+ 'blue-700': 'rgba(29, 78, 216, 1)',
100
+ 'blue-800': 'rgba(30, 64, 175, 1)',
101
+ 'blue-900': 'rgba(30, 58, 138, 1)',
102
+ 'indigo-50': 'rgba(238, 242, 255, 1)',
103
+ 'indigo-100': 'rgba(224, 231, 255, 1)',
104
+ 'indigo-200': 'rgba(199, 210, 254, 1)',
105
+ 'indigo-300': 'rgba(165, 180, 252, 1)',
106
+ 'indigo-400': 'rgba(129, 140, 248, 1)',
107
+ 'indigo-500': 'rgba(99, 102, 241, 1)',
108
+ 'indigo-600': 'rgba(79, 70, 229, 1)',
109
+ 'indigo-700': 'rgba(67, 56, 202, 1)',
110
+ 'indigo-800': 'rgba(55, 48, 163, 1)',
111
+ 'indigo-900': 'rgba(49, 46, 129, 1)',
112
+ 'purple-50': 'rgba(245, 243, 255, 1)',
113
+ 'purple-100': 'rgba(237, 233, 254, 1)',
114
+ 'purple-200': 'rgba(221, 214, 254, 1)',
115
+ 'purple-300': 'rgba(196, 181, 253, 1)',
116
+ 'purple-400': 'rgba(167, 139, 250, 1)',
117
+ 'purple-500': 'rgba(139, 92, 246, 1)',
118
+ 'purple-600': 'rgba(124, 58, 237, 1)',
119
+ 'purple-700': 'rgba(109, 40, 217, 1)',
120
+ 'purple-800': 'rgba(91, 33, 182, 1)',
121
+ 'purple-900': 'rgba(76, 29, 149, 1)',
122
+ 'pink-50': 'rgba(253, 242, 248, 1)',
123
+ 'pink-100': 'rgba(252, 231, 243, 1)',
124
+ 'pink-200': 'rgba(251, 207, 232, 1)',
125
+ 'pink-300': 'rgba(249, 168, 212, 1)',
126
+ 'pink-400': 'rgba(244, 114, 182, 1)',
127
+ 'pink-500': 'rgba(236, 72, 153, 1)',
128
+ 'pink-600': 'rgba(219, 39, 119, 1)',
129
+ 'pink-700': 'rgba(190, 24, 93, 1)',
130
+ 'pink-800': 'rgba(157, 23, 77, 1)',
131
+ 'pink-900': 'rgba(131, 24, 67, 1)',
132
+ },
133
+ };
134
+
135
+ const spacing = {
136
+ keys: {
137
+ mr: 'marginRight',
138
+ ml: 'marginLeft',
139
+ mt: 'marginTop',
140
+ mb: 'marginBottom',
141
+ mx: ['marginLeft', 'marginRight'],
142
+ my: ['marginTop', 'marginBottom'],
143
+ m: 'margin',
144
+ pr: 'paddingRight',
145
+ pl: 'paddingLeft',
146
+ pt: 'paddingTop',
147
+ pb: 'paddingBottom',
148
+ px: ['paddingLeft', 'paddingRight'],
149
+ py: ['paddingTop', 'paddingBottom'],
150
+ p: 'padding',
151
+ },
152
+ values: {
153
+ auto: 'auto',
154
+ 0: '0px',
155
+ px: '1px',
156
+ 0.5: '0.125rem',
157
+ 1: '0.25rem',
158
+ 1.5: '0.375rem',
159
+ 2: '0.5rem',
160
+ 2.5: '0.625rem',
161
+ 3: '0.75rem',
162
+ 3.5: '0.875rem',
163
+ 4: '1rem',
164
+ 5: '1.25rem',
165
+ 6: '1.5rem',
166
+ 7: '1.75rem',
167
+ 8: '2rem',
168
+ 9: '2.25rem',
169
+ 10: '2.5rem',
170
+ 11: '2.75rem',
171
+ 12: '3rem',
172
+ 14: '3.5rem',
173
+ 16: '4rem',
174
+ 20: '5rem',
175
+ 24: '6rem',
176
+ 28: '7rem',
177
+ 32: '8rem',
178
+ 36: '9rem',
179
+ 40: '10rem',
180
+ 44: '11rem',
181
+ 48: '12rem',
182
+ 52: '13rem',
183
+ 56: '14rem',
184
+ 60: '15rem',
185
+ 64: '16rem',
186
+ 72: '18rem',
187
+ 80: '20rem',
188
+ 96: '24rem',
189
+ },
190
+ };
191
+
192
+ // rounded-none border-radius: 0px;
193
+ // rounded-sm border-radius: 0.125rem;
194
+ // rounded border-radius: 0.25rem;
195
+ // rounded-md border-radius: 0.375rem;
196
+ // rounded-lg border-radius: 0.5rem;
197
+ // rounded-xl border-radius: 0.75rem;
198
+ // rounded-2xl border-radius: 1rem;
199
+ // rounded-3xl border-radius: 1.5rem;
200
+ // rounded-full border-radius: 9999px;
201
+ // rounded-t-
202
+ // rounded-r
203
+ // rounded-b
204
+ // rounded-l
205
+ // rounded-tl
206
+ // rounded-tr
207
+ // rounded-br
208
+ // rounded-bl
209
+
210
+ const borders = {
211
+ keys: {
212
+ bw: 'borderWidth',
213
+ bwl: 'borderLeftWidth',
214
+ bwr: 'borderRightWidth',
215
+ bwt: 'borderTopWidth',
216
+ bwb: 'borderBottomWidth',
217
+ },
218
+ values: {
219
+ '': '1px',
220
+ 0: '0px',
221
+ 2: '2px',
222
+ 4: '4px',
223
+ 8: '8px',
224
+ },
225
+ };
226
+
227
+ const sizes = {
228
+ keys: {
229
+ h: 'height',
230
+ w: 'width',
231
+ minh: 'minHeight',
232
+ minw: 'minWidth',
233
+ maxh: 'maxHeight',
234
+ maxw: 'maxWidth',
235
+ },
236
+ values: {
237
+ '1/2': 1 / 1,
238
+ '1/4': 1 / 4,
239
+ '2/4': 2 / 4,
240
+ '3/4': 3 / 4,
241
+ '1/5': 1 / 5,
242
+ '2/5': 2 / 5,
243
+ '3/5': 3 / 5,
244
+ '4/5': 4 / 5,
245
+ '1/6': 1 / 6,
246
+ '2/6': 2 / 6,
247
+ '3/6': 3 / 6,
248
+ '4/6': 4 / 6,
249
+ '5/6': 5 / 6,
250
+ '1/12': 1 / 12,
251
+ '2/12': 2 / 12,
252
+ '3/12': 3 / 12,
253
+ '4/12': 4 / 12,
254
+ '5/12': 5 / 12,
255
+ '6/12': 6 / 12,
256
+ '7/12': 7 / 12,
257
+ '8/12': 8 / 12,
258
+ '9/12': 9 / 12,
259
+ '10/12': 10 / 12,
260
+ '11/12': 11 / 12,
261
+ full: 1,
262
+ },
263
+ };
33
264
 
265
+ const createStyle = (...kvs) => {
266
+ const style = {};
267
+ for (let i = 0; i < kvs.length; i += 2) {
268
+ style[hyphenate(kvs[i])] = kvs[i + 1];
269
+ }
270
+ return style;
271
+ };
272
+
273
+ const mapApply = (obj) =>
34
- export const convertStyles = (prefix, obj, parentClassName, indent = '') => {
274
+ Object.keys(obj.keys).reduce((acc, key) => {
275
+ Object.keys(obj.values).map((vkey) => {
35
- const isGlobal = parentClassName === '__global__';
276
+ const suffix = vkey ? '-' + vkey : '';
36
- const className = isGlobal ? '' : parentClassName || prefix + '-' + murmur2(JSON.stringify(obj)).toString(36);
37
- const cssText = Object.keys(obj).reduce(
277
+ if (Array.isArray(obj.keys[key])) {
38
- (acc, key) => {
39
- const value = obj[key];
278
+ const args = [];
279
+ obj.keys[key].forEach((kk) => {
280
+ args.push(kk, obj.values[vkey]);
281
+ });
40
- if (typeof value === 'object') {
282
+ acc[key + suffix] = createStyle(...args);
41
- acc += '\n ' + indent + convertStyles(prefix, value, key, indent + ' ').cssText;
42
283
  } else {
43
- acc += ' ' + indent + hyphenate(key) + ': ' + value + ';\n';
284
+ acc[key + suffix] = createStyle(obj.keys[key], obj.values[vkey]);
44
285
  }
45
- return acc;
46
- },
47
- isGlobal ? '' : `${parentClassName ? '' : '.'}${className} {\n`,
48
- );
49
- return { className, cssText: cssText + `\n${indent}${isGlobal ? '' : '}'}` };
286
+ });
287
+ return acc;
288
+ }, {});
289
+
290
+ const classLookup = {
291
+ flex: createStyle('display', 'flex'),
292
+ block: createStyle('display', 'block'),
293
+ hidden: createStyle('display', 'none'),
294
+ 'flex-1': createStyle('flex', '1'),
295
+ 'flex-row': createStyle('flexDirection', 'row'),
296
+ 'flex-col': createStyle('flexDirection', 'column'),
297
+ 'flex-wrap': createStyle('flexWrap', 'wrap'),
298
+ 'flex-nowrap': createStyle('flexWrap', 'nowrap'),
299
+ 'flex-wrap-reverse': createStyle('flexWrap', 'wrap-reverse'),
300
+ 'items-baseline': createStyle('alignItems', 'baseline'),
301
+ 'items-start': createStyle('alignItems', 'flex-start'),
302
+ 'items-center': createStyle('alignItems', 'center'),
303
+ 'items-end': createStyle('alignItems', 'flex-end'),
304
+ 'items-stretch': createStyle('alignItems', 'stretch'),
305
+ 'justify-start': createStyle('justifyContent', 'flex-start'),
306
+ 'justify-end': createStyle('justifyContent', 'flex-end'),
307
+ 'justify-center': createStyle('justifyContent', 'center'),
308
+ 'justify-between': createStyle('justifyContent', 'space-between'),
309
+ 'justify-around': createStyle('justifyContent', 'space-around'),
310
+ 'justify-evenly': createStyle('justifyContent', 'space-evenly'),
311
+ 'text-left': createStyle('textAlign', 'left'),
312
+ 'text-center': createStyle('textAlign', 'center'),
313
+ 'text-right': createStyle('textAlign', 'right'),
314
+ 'text-justify': createStyle('textAlign', 'justify'),
315
+ underline: createStyle('textDecoration', 'underline'),
316
+ 'line-through': createStyle('textDecoration', 'line-through'),
317
+ 'no-underline': createStyle('textDecoration', 'none'),
318
+ 'whitespace-normal': createStyle('whiteSpace', 'normal'),
319
+ 'whitespace-nowrap': createStyle('whiteSpace', 'nowrap'),
320
+ 'whitespace-pre': createStyle('whiteSpace', 'pre'),
321
+ 'whitespace-pre-line': createStyle('whiteSpace', 'pre-line'),
322
+ 'whitespace-pre-wrap': createStyle('whiteSpace', 'pre-wrap'),
323
+ 'break-normal': createStyle('wordBreak', 'normal', 'overflowWrap', 'normal'),
324
+ 'break-words': createStyle('wordBreak', 'break-word'),
325
+ 'break-all': createStyle('wordBreak', 'break-all'),
326
+ 'font-sans': createStyle(
327
+ 'font-family',
328
+ `ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"`,
329
+ ),
330
+ 'font-serif': createStyle('font-family', `ui-serif, Georgia, Cambria, "Times New Roman", Times, serif`),
331
+ 'font-mono': createStyle('font-family', `ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace`),
332
+ 'font-thin': createStyle('fontWeight', '100'),
333
+ 'font-extralight': createStyle('fontWeight', '200'),
334
+ 'font-light': createStyle('fontWeight', '300'),
335
+ 'font-normal': createStyle('fontWeight', '400'),
336
+ 'font-medium': createStyle('fontWeight', '500'),
337
+ 'font-semibold': createStyle('fontWeight', '600'),
338
+ 'font-bold': createStyle('fontWeight', '700'),
339
+ 'font-extrabold': createStyle('fontWeight', '800'),
340
+ 'font-black': createStyle('fontWeight', '900'),
341
+ 'text-xs': createStyle('fontSize', '0.75rem', 'lineHeight', '1rem'),
342
+ 'text-sm': createStyle('fontSize', '0.875rem', 'lineHeight', '1.25rem'),
343
+ 'text-base': createStyle('fontSize', '1rem', 'lineHeight', '1.5rem'),
344
+ 'text-lg': createStyle('fontSize', '1.125rem', 'lineHeight', '1.75rem'),
345
+ 'text-xl': createStyle('fontSize', '1.25rem', 'lineHeight', '1.75rem'),
346
+ 'text-2xl': createStyle('fontSize', '1.5rem', 'lineHeight', '2rem'),
347
+ 'text-3xl': createStyle('fontSize', '1.875rem', 'lineHeight', '2.25rem'),
348
+ 'text-4xl': createStyle('fontSize', '2.25rem', 'lineHeight', '2.5rem'),
349
+ 'text-5xl': createStyle('fontSize', '3rem', 'lineHeight', '1'),
350
+ 'text-6xl': createStyle('fontSize', '3.75rem;', 'lineHeight', '1'),
351
+ 'text-7xl': createStyle('fontSize', '4.5rem', 'lineHeight', '1'),
352
+ 'text-8xl': createStyle('fontSize', '6rem', 'lineHeight', '1'),
353
+ 'text-9xl': createStyle('fontSize', '8rem', 'lineHeight', '1'),
354
+ 'cursor-auto': createStyle('cursor', 'auto'),
355
+ 'cursor-default': createStyle('cursor', 'default'),
356
+ 'cursor-pointer': createStyle('cursor', 'pointer'),
357
+ 'cursor-wait': createStyle('cursor', 'wait'),
358
+ 'cursor-text': createStyle('cursor', 'text'),
359
+ 'cursor-move': createStyle('cursor', 'move'),
360
+ 'cursor-help': createStyle('cursor', 'help'),
361
+ 'cursor-not-allowed': createStyle('cursor', 'not-allowed'),
362
+ 'pointer-events-none': createStyle('pointer-events', 'none'),
363
+ 'pointer-events-auto': createStyle('pointer-events', 'auto'),
364
+ 'select-none': createStyle('user-select', 'none'),
365
+ 'select-text': createStyle('user-select', 'text'),
366
+ 'select-all': createStyle('user-select', 'all'),
367
+ 'select-auto': createStyle('user-select', 'auto'),
368
+ ...mapApply(sizes),
369
+ ...mapApply(spacing),
370
+ ...mapApply(colors),
371
+ ...mapApply(borders),
50
372
  };
51
-
373
+ // console.log('classLookup', classLookup);
374
+
52
- export const css = (obj) => {
375
+ export const getTWStyleSheet = (template) => {
376
+ const classList = template.strings
377
+ .reduce((acc, item) => {
378
+ const matches = item.match(/(?:class|className)=(?:["']\W+\s*(?:\w+)\()?["']([^'"]+)['"]/gim);
379
+ if (matches) {
380
+ matches.forEach((matched) => {
381
+ acc += matched.replace('class="', '').replace('"', '') + ' ';
382
+ });
383
+ }
384
+ return acc;
385
+ }, '')
386
+ .split(' ')
387
+ .filter((it) => it !== '');
388
+ let style = ``;
53
- Object.keys(obj).forEach((key) => {
389
+ classList.forEach((k) => {
54
- const value = obj[key];
390
+ const item = classLookup[k];
55
- if (key === '__global__') {
56
- const { cssText } = convertStyles(key, value, '__global__');
57
- obj[key] = cssText;
58
- } else {
391
+ if (item) {
59
- const { className, cssText } = convertStyles(key, value);
392
+ style += `
393
+ .${k} {
60
- obj[key] = className;
394
+ ${Object.keys(item)
395
+ .map((key) => `${key}: ${item[key]};`)
61
- obj[className] = cssText;
396
+ .join('\n')}
397
+ }
398
+ `;
62
399
  }
63
400
  });
64
- obj.render = () => {
65
- return Object.keys(obj).reduce((acc, key) => {
66
- acc += key.includes('-') || key === '__global__' ? obj[key] + '\n\n' : '';
67
- return acc;
401
+ return style;
68
- }, '');
69
- };
70
- return obj;
71
402
  };
72
403
 
73
404
  const lastAttributeNameRegex =
@@ -417,28 +748,26 @@ export class AtomsElement extends BaseElement {
417
748
  const template = this.render();
418
749
  const result = render(template, this);
419
750
  if (isBrowser) {
420
- if (!this.stylesMounted && this.constructor.styles) {
751
+ if (!this.stylesMounted) {
752
+ const twStyles = getTWStyleSheet(template);
421
- this.appendChild(document.createElement('style')).textContent = this.constructor.styles.render();
753
+ this.appendChild(document.createElement('style')).textContent = twStyles;
422
754
  this.stylesMounted = true;
423
755
  }
424
756
  } else {
425
- if (this.constructor.styles) {
757
+ const twStyles = getTWStyleSheet(template);
426
- return `
758
+ return `
427
- ${result}
759
+ ${result}
428
- <style>
760
+ <style>
429
- ${this.constructor.styles.render()}
761
+ ${twStyles}
430
- </style>
762
+ </style>
431
- `;
763
+ `;
432
- } else {
433
- return result;
434
- }
435
764
  }
436
765
  }
437
766
  }
438
767
  export const getConfig = () => (isBrowser ? window.config : global.config);
439
768
  export const getLocation = () => (isBrowser ? window.location : global.location);
440
769
 
441
- export const createElement = ({ name, attrTypes, stateTypes, computedTypes, styles, render }) => {
770
+ export const createElement = ({ name, attrTypes, stateTypes, computedTypes, render }) => {
442
771
  const Element = class extends AtomsElement {
443
772
  static name = name();
444
773
 
@@ -448,8 +777,6 @@ export const createElement = ({ name, attrTypes, stateTypes, computedTypes, styl
448
777
 
449
778
  static computedTypes = computedTypes ? computedTypes() : {};
450
779
 
451
- static styles = styles;
452
-
453
780
  constructor(ssrAttributes) {
454
781
  super(ssrAttributes);
455
782
  }
@@ -462,5 +789,5 @@ export const createElement = ({ name, attrTypes, stateTypes, computedTypes, styl
462
789
  }
463
790
  };
464
791
  Element.register();
465
- return { name, attrTypes, stateTypes, computedTypes, styles, render };
792
+ return { name, attrTypes, stateTypes, computedTypes, render };
466
793
  };
example/app-counter.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createElement, html, css, object, number, string } from '../element.js';
1
+ import { createElement, html, object, number, string, unsafeHTML } from '../element.js';
2
2
 
3
3
  const name = () => 'app-counter';
4
4
 
@@ -23,39 +23,6 @@ const computedTypes = () => ({
23
23
  }),
24
24
  });
25
25
 
26
- const styles = css({
27
- title: {
28
- fontSize: '20px',
29
- marginBottom: '0.5rem',
30
- textAlign: 'center',
31
- },
32
- span: {
33
- fontSize: '16px',
34
- },
35
- container: {
36
- display: 'flex',
37
- flex: 1,
38
- flexDirection: 'row',
39
- fontSize: '32px',
40
- color: 'rgba(55, 65, 81, 1)',
41
- },
42
- mx: {
43
- marginLeft: '5rem',
44
- marginRight: '5rem',
45
- fontSize: '30px',
46
- fontFamily: `ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace`,
47
- },
48
- button: {
49
- paddingTop: '0.5rem',
50
- paddingBottom: '0.5rem',
51
- paddingLeft: '1rem',
52
- paddingRight: '1rem',
53
- color: 'rgba(55, 65, 81, 1)',
54
- borderRadius: '0.25rem',
55
- backgroundColor: 'rgba(209, 213, 219, 1)',
56
- },
57
- });
58
-
59
26
  const render = ({ attrs, state, computed }) => {
60
27
  const { name, meta } = attrs;
61
28
  const { count, setCount } = state;
@@ -63,19 +30,23 @@ const render = ({ attrs, state, computed }) => {
63
30
 
64
31
  return html`
65
32
  <div>
66
- <div class=${styles.title}>
33
+ <div class="mb-2">
67
34
  Counter: ${name}
68
- <span class=${styles.span}>starts at ${meta?.start}</span>
35
+ <span>starts at ${meta?.start}</span>
69
36
  </div>
70
- <div class=${styles.container}>
71
- <button class=${styles.button} @click=${() => setCount((v) => v - 1)}>-</button>
37
+ <div class="flex flex-1 flex-row items-center text-gray-700">
38
+ <button class="bg-gray-300 text-gray-700 rounded hover:bg-gray-200 px-4 py-2 text-3xl focus:outline-none" @click=${() => setCount((v) => v - 1)}>
39
+ -
40
+ </button>
72
- <div class=${styles.mx}>
41
+ <div class="mx-20">
73
- <h1>${count}</h1>
42
+ <h1 class="text-2xl font-mono">${count < 10 ? unsafeHTML('&nbsp;') : ''}${count}</h1>
74
43
  </div>
75
- <button class=${styles.button} @click=${() => setCount((v) => v + 1)}>+</button>
44
+ <button class="bg-gray-300 text-gray-700 rounded hover:bg-gray-200 px-4 py-2 text-3xl focus:outline-none" @click=${() => setCount((v) => v + 1)}>
45
+ +
46
+ </button>
76
47
  </div>
77
- <div class=${styles.mx}>
48
+ <div class="mx-20">
78
- <h1>Sum: ${sum}</h1>
49
+ <h1 class="text-xl font-mono">Sum: ${sum}</h1>
79
50
  </div>
80
51
  </div>
81
52
  `;
@@ -86,6 +57,5 @@ export default createElement({
86
57
  attrTypes,
87
58
  stateTypes,
88
59
  computedTypes,
89
- styles,
90
60
  render,
91
61
  });
example/index.js CHANGED
@@ -1,29 +1,24 @@
1
1
  import { html, css } from '../element.js';
2
2
  import { createPage } from '../page.js';
3
- import { __global__ } from './styles.js';
3
+ import { pageStyles } from './styles.js';
4
4
  import './app-counter.js';
5
5
 
6
6
  const route = () => {
7
7
  return '/counter';
8
8
  };
9
9
 
10
- const styles = css({
11
- __global__,
12
- center: {
13
- display: 'flex',
14
- flex: 1,
15
- alignItems: 'center',
16
- justifyContent: 'center',
17
- },
18
- });
19
-
20
10
  const head = ({ config }) => {
11
+ return html`
21
- return html` <title>${config.title}</title> `;
12
+ <title>${config.title}</title>
13
+ <style>
14
+ ${css(pageStyles)}
15
+ </style>
16
+ `;
22
17
  };
23
18
 
24
19
  const body = () => {
25
20
  return html`
26
- <div class=${styles.center}>
21
+ <div class="flex flex-1 items-center justify-center">
27
22
  <app-counter name="1" meta="{'start': 5}"></app-counter>
28
23
  </div>
29
24
  `;
@@ -31,7 +26,6 @@ const body = () => {
31
26
 
32
27
  export default createPage({
33
28
  route,
34
- styles,
35
29
  head,
36
30
  body,
37
31
  });
example/server.js CHANGED
@@ -33,9 +33,11 @@ http
33
33
  return;
34
34
  }
35
35
  const filename = srcMap[req.url];
36
+ if (filename) {
36
- const data = fs.readFileSync(filename);
37
+ const data = fs.readFileSync(filename);
37
- res.setHeader('Content-type', 'application/javascript');
38
+ res.setHeader('Content-type', 'application/javascript');
38
- res.end(data);
39
+ res.end(data);
40
+ }
39
41
  })
40
42
  .listen(parseInt(port));
41
43
 
example/styles.js CHANGED
@@ -1,4 +1,4 @@
1
- export const __global__ = {
1
+ export const pageStyles = {
2
2
  '*, ::before, ::after': {
3
3
  boxSizing: 'border-box',
4
4
  borderWidth: '0',
page.d.ts CHANGED
@@ -29,7 +29,6 @@ export type CreatePageProps = {
29
29
  datapaths: Handler;
30
30
  head: Handler;
31
31
  body: Handler;
32
- styles: {[key: string]: any};
33
32
  }
34
33
  export type PageRenderProps = {
35
34
  config: Config;
page.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import parse5 from 'parse5';
2
- import { AtomsElement, render } from './element.js';
2
+ import { AtomsElement, render, getTWStyleSheet } from './element.js';
3
3
 
4
4
  export const find = (node) => {
5
5
  for (const child of node.childNodes) {
@@ -28,7 +28,8 @@ export const createPage = ({ route, datapaths, head, body, styles }) => {
28
28
  const isProd = process.env.NODE_ENV === 'production';
29
29
  const props = { config, data, item };
30
30
  const headHtml = ssr(head(props));
31
+ const bodyTemplate = body(props);
31
- const bodyHtml = ssr(body(props));
32
+ const bodyHtml = ssr(bodyTemplate);
32
33
  return `
33
34
  <!DOCTYPE html>
34
35
  <html lang="${config.lang}">
@@ -41,7 +42,7 @@ export const createPage = ({ route, datapaths, head, body, styles }) => {
41
42
  <link rel="icon" type="image/png" href="/assets/icon.png" />
42
43
  ${headHtml}
43
44
  <style>
44
- ${styles.render()}
45
+ ${getTWStyleSheet(bodyTemplate)}
45
46
  </style>
46
47
  ${headScript}
47
48
  </head>