Fixed a bug relating to custom-elements's first vnode where render(){ return <div class="example" /> } would set the example-class on the custom-element itself.
Added support for className and style similar to react Cleaned up some comments Reworked how tests are built in order to add a new test "pdf" which was a small side-project where previous mentioned bug showed up, it's an example using HTML to create a PDF for printing
This commit is contained in:
23
tests/.babelrc
Normal file
23
tests/.babelrc
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"presets": [
|
||||
["@babel/preset-env", {
|
||||
"targets": {
|
||||
"node": "current"
|
||||
}
|
||||
}]
|
||||
],
|
||||
"plugins": [
|
||||
[ "@babel/plugin-proposal-decorators", { "legacy": true }],
|
||||
[ "@babel/plugin-proposal-class-properties", { "loose": true } ],
|
||||
[ "@babel/plugin-proposal-private-methods", {"loose": true } ],
|
||||
[ "@babel/plugin-proposal-optional-chaining" ],
|
||||
[ "@babel/plugin-proposal-nullish-coalescing-operator" ],
|
||||
[ "@babel/plugin-proposal-export-namespace-from" ],
|
||||
[ "@babel/plugin-proposal-export-default-from" ],
|
||||
[ "../packages/babel-plugin-transform-csx/dist", {
|
||||
//"pragma": "render",
|
||||
//"pragmaFrag": "render",
|
||||
"throwIfNamespace": false
|
||||
}]
|
||||
]
|
||||
}
|
||||
10
tests/basic/index.html
Normal file
10
tests/basic/index.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Cerxes - CustomElements</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
18
tests/basic/index.jsx
Normal file
18
tests/basic/index.jsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import {render} from "../../packages/csx";
|
||||
import style from "./index.scss";
|
||||
import {ExamplePage} from "./page";
|
||||
|
||||
document.body.appendChild(render(<style>{style}</style>));
|
||||
document.body.appendChild(render(<div class="center-me" iCanDoUpperCaseAttrs={ "yes" }>
|
||||
<h1>I am a title!</h1>
|
||||
</div>));
|
||||
|
||||
//document.body.appendChild(render(<example-page />));
|
||||
document.body.appendChild(render(<ExamplePage />));
|
||||
|
||||
/**
|
||||
* Continuation suggestionss:
|
||||
* - style-attribute untested
|
||||
* - Want a way to toggle classes: <Host class={{'bq-checkbox': true, 'checked': this.isChecked}}> could do
|
||||
* - Supporting fragments <>...</>?
|
||||
*/
|
||||
19
tests/basic/index.scss
Normal file
19
tests/basic/index.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
html{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.center-me{
|
||||
align-self: center;
|
||||
}
|
||||
12
tests/basic/page.jsx
Normal file
12
tests/basic/page.jsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import {defineElement, render, CustomElement} from "../../packages/csx";
|
||||
|
||||
@defineElement('example-page')
|
||||
export class ExamplePage extends CustomElement{
|
||||
connectedCallback() {
|
||||
this.appendChild(render(
|
||||
<div class="page">
|
||||
<h1>This page is an example!</h1>
|
||||
</div>
|
||||
));
|
||||
}
|
||||
}
|
||||
19
tests/cfg/.babelrc
Normal file
19
tests/cfg/.babelrc
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"sourceMaps": "both",
|
||||
"presets": [
|
||||
["@babel/preset-env", {
|
||||
"targets": {
|
||||
"node": "current"
|
||||
}
|
||||
}]
|
||||
],
|
||||
"plugins": [
|
||||
[ "@babel/plugin-proposal-decorators", { "legacy": true }],
|
||||
[ "@babel/plugin-proposal-class-properties", { "loose": true } ],
|
||||
[ "@babel/plugin-proposal-private-methods", {"loose": true } ],
|
||||
[ "@babel/plugin-proposal-optional-chaining" ],
|
||||
[ "@babel/plugin-proposal-nullish-coalescing-operator" ],
|
||||
[ "@babel/plugin-proposal-export-namespace-from" ],
|
||||
[ "@babel/plugin-proposal-export-default-from" ]
|
||||
]
|
||||
}
|
||||
166
tests/cfg/rollup-build.js
Normal file
166
tests/cfg/rollup-build.js
Normal file
@@ -0,0 +1,166 @@
|
||||
// @cerxes
|
||||
import {host, Host} from "@cerxes/host";
|
||||
|
||||
// Observables
|
||||
import {Observable} from "zen-observable/lib/Observable";
|
||||
import {merge, combineLatest, zip} from "zen-observable/lib/extras";
|
||||
|
||||
// Rollup and plugins
|
||||
import * as rollup from 'rollup';
|
||||
import babel from 'rollup-plugin-babel';
|
||||
import resolve from 'rollup-plugin-node-resolve';
|
||||
import commonjs from 'rollup-plugin-commonjs';
|
||||
import json from "rollup-plugin-json";
|
||||
import postcss from "rollup-plugin-postcss";
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
|
||||
/** @type {Host} */
|
||||
const srcDir = host.from("tests");
|
||||
/** @type {Host} */
|
||||
const distDir = host.from("public");
|
||||
const assetsGlob = `**/*.@(${[
|
||||
"html",
|
||||
"otf",
|
||||
'svg',
|
||||
'ico',
|
||||
'png',
|
||||
'jpg',
|
||||
'jpeg'
|
||||
].join('|')})`;
|
||||
const sourcesGlob = `**/index.@(js|jsx)`;
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
const entryConfig = (entry, output)=>({
|
||||
input: srcDir.resolve(entry),
|
||||
output: {
|
||||
file: distDir.resolve(output),
|
||||
format: 'esm',
|
||||
sourcemap: true
|
||||
},
|
||||
plugins: [
|
||||
// json
|
||||
json(),
|
||||
// PostCSS-style
|
||||
postcss({
|
||||
plugins: [],
|
||||
inject: false,
|
||||
minimize: !!args.includes('build')
|
||||
}),
|
||||
// babel
|
||||
babel(),
|
||||
// node_modules
|
||||
resolve({
|
||||
extensions: ['.mjs', '.js', '.jsx', '.json'],
|
||||
}),
|
||||
// CJS-modules
|
||||
commonjs({
|
||||
namedExports: {
|
||||
// If there were any...
|
||||
}
|
||||
}),
|
||||
// minify, but only in production
|
||||
args.includes('build') && terser(),
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
function logBundle(output, duration){
|
||||
let relativeOut = distDir.relative(output);
|
||||
console.log(relativeOut + " built in " + (duration/1000)+"s");
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the tests
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function build(){
|
||||
// Clean host
|
||||
await host.remove(distDir.workingDirectory, {recursive: true});
|
||||
console.log("Dist cleaned!");
|
||||
|
||||
let assetsJob = srcDir.glob(assetsGlob).then(
|
||||
matched=>Promise.all(
|
||||
matched.map(asset=>host.copy(srcDir.resolve(asset), distDir.resolve(asset)).then(()=>asset))
|
||||
)
|
||||
).then((assets)=>{
|
||||
console.log("Assets copied");
|
||||
return assets;
|
||||
});
|
||||
|
||||
let sourceJobs = srcDir.glob(sourcesGlob).then(
|
||||
matched=>Promise.all(
|
||||
matched.map(async (source)=>{
|
||||
let sourceStart = new Date();
|
||||
let entry = source;
|
||||
let output = distDir.resolve(source,'..','index.js');
|
||||
let rollupCfg = entryConfig(entry,output);
|
||||
return await rollup.rollup(rollupCfg).then(async (bundle)=>{
|
||||
let written = await bundle.write(rollupCfg.output);
|
||||
logBundle(output, (new Date()).getTime()-sourceStart.getTime());
|
||||
return {bundle, written};
|
||||
});
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
// Wait for both to be done
|
||||
let [app, assets] = await Promise.all([sourceJobs, assetsJob]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch the app (watch asset files and automatically rebuild, this triggers development mode, as it should never be used on the server!)
|
||||
*/
|
||||
async function watch(){
|
||||
let lastUpdate = new Date();
|
||||
// Clean host
|
||||
await host.remove(distDir.workingDirectory, { recursive: true });
|
||||
console.log("Dist cleaned!");
|
||||
|
||||
// Configure a WebPackage (containing build-info)
|
||||
|
||||
// Watch sources and map them to an observable
|
||||
let sourceJobs = await srcDir.glob(sourcesGlob).then(
|
||||
matched=>matched.map((source)=>{
|
||||
let entry = source;
|
||||
let output = distDir.resolve(source,'..','index.js');
|
||||
let rollupCfg = entryConfig(entry,output);
|
||||
let sourceWatcher = rollup.watch(rollupCfg);
|
||||
return new Observable(observer => {
|
||||
sourceWatcher.on('event', event => {
|
||||
if(event.code==='BUNDLE_END'){
|
||||
logBundle(output, event.duration);
|
||||
observer.next(event);
|
||||
}else if(event.code==='FATAL'){
|
||||
observer.complete();
|
||||
}else if(event.code==='ERROR'){
|
||||
console.error(event.error.toString());
|
||||
}
|
||||
});
|
||||
|
||||
return () =>{
|
||||
// On unsubscription, do what?
|
||||
};
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
let assetsObservable = srcDir.watch().glob(assetsGlob).sync(distDir.workingDirectory).map(event=>{
|
||||
console.log("Assets synced!");
|
||||
// console.log(event.files.join('\n'));
|
||||
return event.files;
|
||||
});
|
||||
|
||||
combineLatest(...sourceJobs, assetsObservable).subscribe(async (built)=>{
|
||||
let newUpdate = new Date();
|
||||
console.log(`Updated in ${(newUpdate.getTime()- lastUpdate.getTime())/1000}s`);
|
||||
lastUpdate = newUpdate;
|
||||
});
|
||||
}
|
||||
|
||||
// Run!
|
||||
if(args.includes('watch')){
|
||||
watch();
|
||||
}else{
|
||||
build();
|
||||
}
|
||||
|
||||
29
tests/index.html
Normal file
29
tests/index.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CSX - CE Tests</title>
|
||||
<style type="text/css">
|
||||
html{ width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-items:center; }
|
||||
body{ flex: 1 1 auto;overflow:auto;display:flex;flex-direction:column;align-items:center;justify-items:center; }
|
||||
ul { list-style-type: none;font-size: 1.5em; }
|
||||
li{ padding: .5em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="./basic/">Basic testing</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="./svg/">SVG Rendering</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="./pdf/">PDF Rendering</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="./todos-mvc/">Todos MVC</a>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
1
tests/index.jsx
Normal file
1
tests/index.jsx
Normal file
@@ -0,0 +1 @@
|
||||
/** I don't do nothing! (but it might later...) **/
|
||||
BIN
tests/pdf/assets/fonts/DINPro-Black.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-Black.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-BlackItalic.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-BlackItalic.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-Bold.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-Bold.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-BoldItalic.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-BoldItalic.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-Cond.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-Cond.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-CondBlack.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-CondBlack.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-CondBlackIta.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-CondBlackIta.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-CondBold.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-CondBold.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-CondBoldIta.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-CondBoldIta.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-CondIta.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-CondIta.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-CondLight.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-CondLight.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-CondLightIta.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-CondLightIta.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-CondMediIta.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-CondMediIta.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-CondMedium.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-CondMedium.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-Italic.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-Italic.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro-Light.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro-Light.otf
Normal file
Binary file not shown.
BIN
tests/pdf/assets/fonts/DINPro.otf
Normal file
BIN
tests/pdf/assets/fonts/DINPro.otf
Normal file
Binary file not shown.
73
tests/pdf/assets/logo.svg
Normal file
73
tests/pdf/assets/logo.svg
Normal file
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 1133.3333 392"
|
||||
height="392"
|
||||
width="1133.3333"
|
||||
xml:space="preserve"
|
||||
id="svg4485"
|
||||
version="1.1"><metadata
|
||||
id="metadata4491"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs4489"><clipPath
|
||||
id="clipPath4501"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path4499"
|
||||
d="M 0.06,293.854 H 849.394 V 0.06 H 0.06 Z" /></clipPath><clipPath
|
||||
id="clipPath4515"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path4513"
|
||||
d="M 0.06,293.854 H 849.394 V 0.06 H 0.06 Z" /></clipPath></defs><g
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,392)"
|
||||
id="g4493"><g
|
||||
id="g4495"><g
|
||||
clip-path="url(#clipPath4501)"
|
||||
id="g4497"><path
|
||||
id="path4503"
|
||||
style="fill:#43a998;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="M 849.394,160.098 833.52,42.32 285.572,0 263.592,160.098 h 585.802" /></g></g><g
|
||||
id="text4507"
|
||||
style="font-variant:normal;font-weight:900;font-size:91.8742981px;font-family:Simplo;-inkscape-font-specification:Simplo-Black;writing-mode:lr-tb;display:inline;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
transform="scale(1,-1)"
|
||||
aria-label="LUMMEN"><path
|
||||
id="path4534"
|
||||
d="M 414.79861,-66.139618 H 366.61843 V -132.9369 h 17.22644 v 53.877459 h 30.95374 z" /><path
|
||||
id="path4536"
|
||||
d="m 483.61461,-90.319426 q 0,12.381497 -7.53656,18.97599 -7.53657,6.594493 -22.20595,6.594493 -14.66938,0 -22.20594,-6.594493 -7.49171,-6.594493 -7.49171,-18.931129 V -132.9369 h 17.31615 v 41.675404 q 0,6.953377 2.91594,10.362775 2.91593,3.409397 9.46556,3.409397 6.45991,0 9.42071,-3.274816 3.00565,-3.274816 3.00565,-10.497356 V -132.9369 h 17.31615 z" /><path
|
||||
id="path4538"
|
||||
d="m 569.79162,-66.139618 h -17.13671 v -44.725912 l -12.3815,29.024738 h -11.88803 l -12.3815,-29.024738 v 44.725912 h -16.2395 V -132.9369 h 20.00779 l 15.02826,33.510793 14.98341,-33.510793 h 20.00778 z" /><path
|
||||
id="path4540"
|
||||
d="m 656.82099,-66.139618 h -17.13671 v -44.725912 l -12.38149,29.024738 h -11.88803 l -12.3815,-29.024738 v 44.725912 h -16.2395 V -132.9369 h 20.00778 l 15.02827,33.510793 14.9834,-33.510793 h 20.00778 z" /><path
|
||||
id="path4542"
|
||||
d="M 722.13787,-66.139618 H 673.82312 V -132.9369 h 48.31475 v 12.91983 h -31.17804 v 11.52914 h 28.93502 v 12.919826 h -28.93502 v 16.508663 h 31.17804 z" /><path
|
||||
id="path4544"
|
||||
d="M 797.36892,-66.139618 H 780.77053 L 752.4187,-111.98705 v 45.847432 H 736.6278 V -132.9369 h 20.59097 l 24.35925,38.266006 V -132.9369 h 15.7909 z" /></g><g
|
||||
id="g4509"><g
|
||||
clip-path="url(#clipPath4515)"
|
||||
id="g4511"><path
|
||||
id="path4517"
|
||||
style="fill:#7b7979;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="M 368.363,140.416 285.572,0 264.044,152.94 368.363,140.416" /><path
|
||||
id="path4519"
|
||||
style="fill:#00897e;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 0,293.854 15.874,-111.118 352.489,-42.32 21.98,153.438 H 0" /></g></g><path
|
||||
id="path4521"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="M 326.403,265.506 V 241.099 L 292,266.583 v -63.156 h 19.345 v 24.404 l 34.401,-25.482 v 63.157 h -19.343" /><path
|
||||
id="path4523"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 261.052,227.149 h 25.056 v 15.564 h -25.056 v 5.812 h 25.499 v 16.999 h -44.817 v -62.085 h 44.913 v 17.535 h -25.595 v 6.175" /><path
|
||||
id="path4525"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 212.916,224.493 c -2.776,-2.685 -5.994,-4.025 -9.846,-4.025 -3.936,0 -7.154,1.34 -9.929,4.025 -2.685,2.772 -4.028,6.086 -4.028,9.932 0,3.846 1.343,7.154 4.028,9.836 2.775,2.778 5.993,4.12 9.929,4.12 3.852,0 7.07,-1.342 9.846,-4.12 2.863,-2.682 4.2,-5.99 4.2,-9.836 0,-3.846 -1.337,-7.16 -4.2,-9.932 z m -9.846,43.302 c -9.211,0 -16.999,-3.313 -23.526,-9.842 -6.442,-6.44 -9.752,-14.317 -9.752,-23.528 0,-9.128 3.31,-17 9.752,-23.531 6.527,-6.443 14.315,-9.751 23.526,-9.751 9.217,0 17.006,3.308 23.537,9.751 6.529,6.531 9.834,14.403 9.834,23.531 0,9.211 -3.305,17.088 -9.834,23.528 -6.531,6.529 -14.32,9.842 -23.537,9.842" /><path
|
||||
id="path4527"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 126.495,239.23 v 7.243 h 11.361 c 4.07,0 7.255,-3.245 7.321,-7.214 -0.066,-3.965 -3.251,-7.207 -7.321,-7.207 h -11.361 z m 30.322,-18.812 c 5.151,5.153 7.827,11.542 7.866,18.812 h 0.006 c 0,0.009 0,0.018 0,0.029 0,0.013 0,0.025 0,0.033 h -0.006 c -0.039,7.268 -2.715,13.663 -7.866,18.81 -5.186,5.188 -11.629,7.422 -18.961,7.422 h -30.778 v -62.082 h 19.417 v 9.554 h 9.974 l 20.613,-27.512 15.481,11.629 -16.764,22.382 c 0.336,0.303 0.691,0.592 1.018,0.923" /><path
|
||||
id="path4529"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
d="m 101.633,234.478 c 0,0.274 0,0.539 0,0.811 0,0.892 0,3.771 0,3.771 H 69.73 v -12.308 h 10.78 c -0.538,-0.812 -1.164,-1.533 -1.884,-2.25 -2.697,-2.688 -6.023,-4.04 -9.884,-4.04 -3.862,0 -7.187,1.352 -9.968,4.04 -2.697,2.79 -4.046,6.115 -4.046,9.976 0,3.871 1.349,7.191 4.046,9.882 2.781,2.786 6.106,4.138 9.968,4.138 3.861,0 6.561,-0.807 9.256,-3.507 l 14.376,13.12 c -6.555,6.558 -14.376,9.881 -23.632,9.881 -9.164,0 -17.071,-3.323 -23.633,-9.881 -6.552,-6.467 -9.788,-14.38 -9.788,-23.633 0,-9.163 3.236,-17.07 9.788,-23.629 6.562,-6.47 14.469,-9.792 23.633,-9.792 9.256,0 17.077,3.322 23.632,9.792 6.559,6.559 9.259,14.466 9.259,23.629" /></g></svg>
|
||||
|
After Width: | Height: | Size: 6.0 KiB |
106
tests/pdf/fonts.pcss
Normal file
106
tests/pdf/fonts.pcss
Normal file
@@ -0,0 +1,106 @@
|
||||
/* DINPro */
|
||||
@font-face {
|
||||
font-family: 'DINPro';
|
||||
src: url('assets/fonts/DINPro.otf');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DINPro';
|
||||
src: url('assets/fonts/DINPro-Light.otf');
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'DINPro';
|
||||
src: url('assets/fonts/DINPro-Italic.otf');
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DINPro';
|
||||
src: url('assets/fonts/DINPro-Bold.otf');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'DINPro';
|
||||
src: url('assets/fonts/DINPro-BoldItalic.otf');
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'DINPro';
|
||||
src: url('assets/fonts/DINPro-Black.otf');
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'DINPro';
|
||||
src: url('assets/fonts/DINPro-BlackItalic.otf');
|
||||
font-weight: 900;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
||||
/* DINPro Condensed */
|
||||
@font-face {
|
||||
font-family: 'DINPro Condensed';
|
||||
src: url('assets/fonts/DINPro.otf');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DINPro Condensed';
|
||||
src: url('assets/fonts/DINPro-CondLight.otf');
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'DINPro Condensed';
|
||||
src: url('assets/fonts/DINPro-CondIta.otf');
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: 'DINPro Condensed';
|
||||
src: url('assets/fonts/DINPro-CondMedium.otf');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'DINPro Condensed';
|
||||
src: url('assets/fonts/DINPro-CondMediIta.otf');
|
||||
font-weight: 600;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'DINPro Condensed';
|
||||
src: url('assets/fonts/DINPro-CondBold.otf');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'DINPro Condensed';
|
||||
src: url('assets/fonts/DINPro-CondBoldIta.otf');
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'DINPro Condensed';
|
||||
src: url('assets/fonts/DINPro-CondBlack.otf');
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'DINPro Condensed';
|
||||
src: url('assets/fonts/DINPro-CondBlackIta.otf');
|
||||
font-weight: 900;
|
||||
font-style: italic;
|
||||
}
|
||||
10
tests/pdf/index.html
Normal file
10
tests/pdf/index.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Pastabuffet Groen Lummen</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="module" src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
88
tests/pdf/index.jsx
Normal file
88
tests/pdf/index.jsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import kaartStyle from "./index.pcss";
|
||||
import {render, defineElement, CustomElement, Host, State, Prop, ShadowDOM} from "../../packages/csx";
|
||||
|
||||
// Style
|
||||
document.head.appendChild(render(<style>{kaartStyle}</style>));
|
||||
|
||||
// Kaart
|
||||
@defineElement("pasta-buffet-kaart")
|
||||
class PastaBuffetKaart extends CustomElement{
|
||||
|
||||
@Prop() eigenExemplaar;
|
||||
|
||||
render(){
|
||||
return <div className="kaart">
|
||||
<div className="header">
|
||||
<img src="assets/logo.svg" alt={"logo"} className="logo"/>
|
||||
<div className="header-info">
|
||||
<div className="title">Pastabuffet</div>
|
||||
<div className="sub-title">Zondag 02/02/2020 vanaf 17u</div>
|
||||
<div className="sub-title">O.C De Link, Linkhoutstraat 194</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="content">
|
||||
<h3>Bestelling</h3>
|
||||
<table className="order">
|
||||
<tr>
|
||||
<td className="product-name">Volwassenen</td>
|
||||
<td className="product-amount"><input type="text"/></td>
|
||||
<td className="product-multiplier">x</td>
|
||||
<td className="product-price">14,00€ =</td>
|
||||
<td className="product-total"><input type="text"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="product-name">Kinderen</td>
|
||||
<td className="product-amount"><input type="text"/></td>
|
||||
<td className="product-multiplier">x</td>
|
||||
<td className="product-price">8,00€ =</td>
|
||||
<td className="product-total"><input type="text"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colSpan={3}/>
|
||||
<td className="total-label">Totaal =</td>
|
||||
<td className="order-total"><input type="text"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table className="account">
|
||||
<tr>
|
||||
<td className="product-name">Naam</td>
|
||||
<td className="product-input"><input type="text"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div className="payment-options">
|
||||
<div className="option">
|
||||
Cash betaald
|
||||
<input type="checkbox"/>
|
||||
</div>
|
||||
<div className="option">
|
||||
Overschrijving
|
||||
<input type="checkbox"/>
|
||||
BE50 9731 5197 8018
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer">
|
||||
{this.eigenExemplaar ? ([
|
||||
<div className="form-for">Eigen exemplaar</div>,
|
||||
<div className="contact">Contactpersoon: Peter Aerts 0499 26 54 99</div>
|
||||
]) : ([
|
||||
<div className="form-for">Exemplaar voor Groen Lummen</div>
|
||||
])}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
// Kaarten
|
||||
document.body.appendChild(render(<div className="kaarten-print">
|
||||
<div className="kaarten-pair">
|
||||
<PastaBuffetKaart eigenExemplaar={true}/>
|
||||
<PastaBuffetKaart/>
|
||||
</div>
|
||||
<div className="kaarten-pair">
|
||||
<PastaBuffetKaart eigenExemplaar={true}/>
|
||||
<PastaBuffetKaart/>
|
||||
</div>
|
||||
</div>));
|
||||
158
tests/pdf/index.pcss
Normal file
158
tests/pdf/index.pcss
Normal file
@@ -0,0 +1,158 @@
|
||||
@import "./fonts.pcss";
|
||||
|
||||
@page {
|
||||
size: A4 landscape;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media print {
|
||||
html {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: none !important;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 297mm;
|
||||
height: 210mm;
|
||||
size: landscape A4;
|
||||
border: none !important;
|
||||
background: none !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
html{
|
||||
background: #aeaeae;
|
||||
font-family: 'DINPro';
|
||||
font-size: 10.5pt;
|
||||
}
|
||||
body{
|
||||
background: white;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
width: 289mm;
|
||||
height: 202mm;
|
||||
border: 1px solid black;
|
||||
padding: 4mm;
|
||||
}
|
||||
|
||||
.kaarten-print{
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.kaarten-pair{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 auto;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.kaart{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 148mm;
|
||||
padding: 1em;
|
||||
|
||||
& .header{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
& .logo{
|
||||
flex: 0 1 35%;
|
||||
max-width: 35%;
|
||||
}
|
||||
|
||||
& .header-info{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex: 1 1 auto;
|
||||
|
||||
& .title{
|
||||
font-size: 200%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
& .sub-title{
|
||||
font-weight: 700;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& .content{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
& table{
|
||||
margin-bottom: .75em;
|
||||
}
|
||||
|
||||
& .order >tr >td{
|
||||
padding-bottom: .25em;
|
||||
}
|
||||
|
||||
& .product-name{
|
||||
font-weight: 600;
|
||||
width: 6em;
|
||||
}
|
||||
& .product-multiplier{
|
||||
font-weight: 600;
|
||||
width: 1em;
|
||||
}
|
||||
& .product-price, & .total-label{
|
||||
font-weight: 600;
|
||||
text-align: right;
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
& .payment-options{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
|
||||
& .option{
|
||||
padding: 0 0 1em;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
& .footer{
|
||||
align-self: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
& .form-for{
|
||||
font-weight: bold;
|
||||
}
|
||||
& .contact{
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
input[type=text]{
|
||||
border: none;
|
||||
border-bottom: 1px dashed darkgray;
|
||||
|
||||
width: calc(100% - 1em);
|
||||
}
|
||||
|
||||
input[type=checkbox]{
|
||||
-webkit-appearance: none;
|
||||
border: 1px solid #999;
|
||||
padding: 9px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
margin: 3px 6px;
|
||||
}
|
||||
9
tests/postcss.config.js
Normal file
9
tests/postcss.config.js
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
//require('autoprefixer'),
|
||||
require('postcss-import'),
|
||||
require('postcss-preset-env')({
|
||||
stage: 1,
|
||||
})
|
||||
]
|
||||
};
|
||||
10
tests/svg/index.html
Normal file
10
tests/svg/index.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Cerxes - CustomElements - SVG</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
47
tests/svg/index.jsx
Normal file
47
tests/svg/index.jsx
Normal file
@@ -0,0 +1,47 @@
|
||||
import {render} from "../../packages/csx";
|
||||
import style from "./index.scss";
|
||||
import {SvgLoader} from "./svg-loader";
|
||||
import {SvgTester} from "./svg-tester";
|
||||
import {SvgTesterTwo} from "./svg-tester-two";
|
||||
|
||||
let loader = render(<SvgLoader inverted="yes"/>);
|
||||
|
||||
document.body.appendChild(render(<style>{style}</style>));
|
||||
document.body.appendChild(render(
|
||||
<div class="center-me">
|
||||
<h3>SVG Loader</h3>
|
||||
{loader}
|
||||
<h3>SVG Tester</h3>
|
||||
<SvgTester/>
|
||||
<h3>SVG Tester Two</h3>
|
||||
<SvgTesterTwo/>
|
||||
</div>
|
||||
));
|
||||
|
||||
|
||||
setTimeout(()=>{
|
||||
console.log("Uninverting");
|
||||
loader.removeAttribute("inverted");
|
||||
|
||||
setTimeout(()=>{
|
||||
console.log("Inverting");
|
||||
loader.setAttribute("inverted", "ja");
|
||||
|
||||
setTimeout(()=>{
|
||||
console.log("Stays inverted");
|
||||
loader.setAttribute("inverted", "");
|
||||
|
||||
setTimeout(()=>{
|
||||
console.log("Inverted color");
|
||||
loader.setAttribute("inverted-color", "#0F0");
|
||||
}, 1000);
|
||||
}, 1000);
|
||||
}, 1000);
|
||||
|
||||
|
||||
}, 1000);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
19
tests/svg/index.scss
Normal file
19
tests/svg/index.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
html{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.center-me{
|
||||
align-self: center;
|
||||
}
|
||||
57
tests/svg/svg-loader.jsx
Normal file
57
tests/svg/svg-loader.jsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import {CustomElement, defineElement, Host, ShadowDOM, State, Prop} from "../../packages/csx";
|
||||
import loaderComponentShadowStyle from './svg-loader.shadow.scss';
|
||||
|
||||
// TODO configurability, like inverted and not with props...
|
||||
|
||||
@defineElement('svg-loader')
|
||||
export class SvgLoader extends CustomElement{
|
||||
// Constructor
|
||||
constructor(){
|
||||
super();
|
||||
}
|
||||
|
||||
// Private properties
|
||||
|
||||
// Properties
|
||||
@Prop({reflect: true}) inverted;
|
||||
@Prop({reflect: true, attr: "inverted-color"}) invertedColor = "#000";
|
||||
|
||||
// Handlers
|
||||
|
||||
// CustomElement
|
||||
render(){
|
||||
return (
|
||||
<Host>
|
||||
<ShadowDOM>
|
||||
<style>
|
||||
{ loaderComponentShadowStyle }
|
||||
</style>
|
||||
|
||||
<div class="loader-content">
|
||||
<div class="spinner">
|
||||
<svg width="38" height="38" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg" stroke={(this.inverted??false)!==false? this.invertedColor : "#F00"}>
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<g transform="translate(1 1)" stroke-width="2">
|
||||
<circle stroke-opacity=".5" cx="18" cy="18" r="18"/>
|
||||
<path d="M36 18c0-9.94-8.06-18-18-18">
|
||||
<animateTransform
|
||||
attributeName="transform"
|
||||
type="rotate"
|
||||
from="0 18 18"
|
||||
to="360 18 18"
|
||||
dur="1s"
|
||||
repeatCount="indefinite"/>
|
||||
</path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<slot>
|
||||
</slot>
|
||||
</div>
|
||||
</ShadowDOM>
|
||||
</Host>
|
||||
)
|
||||
}
|
||||
}
|
||||
10
tests/svg/svg-loader.shadow.scss
Normal file
10
tests/svg/svg-loader.shadow.scss
Normal file
@@ -0,0 +1,10 @@
|
||||
:host{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.spinner{
|
||||
padding: .5rem;
|
||||
}
|
||||
}
|
||||
43
tests/svg/svg-tester-two.jsx
Normal file
43
tests/svg/svg-tester-two.jsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import {CustomElement, defineElement, Host, ShadowDOM, State, Prop} from "../../packages/csx";
|
||||
import {SvgLoader} from "./svg-loader";
|
||||
|
||||
@defineElement('svg-tester-two')
|
||||
export class SvgTesterTwo extends CustomElement{
|
||||
// Constructor
|
||||
constructor(){
|
||||
super();
|
||||
}
|
||||
|
||||
// Private properties
|
||||
states = [
|
||||
{ inverted: true, invertedColor: "#F00"},
|
||||
{ inverted: true, invertedColor: "#FF0"},
|
||||
{ inverted: true, invertedColor: "#0FF"},
|
||||
{ inverted: false},
|
||||
{ inverted: true, invertedColor: "#0F0"},
|
||||
];
|
||||
|
||||
// Properties
|
||||
@State() state = this.states[0];
|
||||
|
||||
// Handlers
|
||||
|
||||
// CustomElement
|
||||
connectedCallback() {
|
||||
setInterval(()=>{
|
||||
// Moving state
|
||||
let curIndex = this.states.indexOf(this.state);
|
||||
this.state = this.states[(curIndex+1)>=this.states.length?0:curIndex+1];
|
||||
}, 1000);
|
||||
super.connectedCallback();
|
||||
}
|
||||
|
||||
render(){
|
||||
// invertedColor instead of inverted-color is the only difference!
|
||||
return (
|
||||
<Host>
|
||||
<SvgLoader inverted={this.state.inverted} invertedColor={this.state.invertedColor} />
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
}
|
||||
42
tests/svg/svg-tester.jsx
Normal file
42
tests/svg/svg-tester.jsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import {CustomElement, defineElement, Host, ShadowDOM, State, Prop} from "../../packages/csx";
|
||||
import {SvgLoader} from "./svg-loader";
|
||||
|
||||
@defineElement('svg-tester')
|
||||
export class SvgTester extends CustomElement{
|
||||
// Constructor
|
||||
constructor(){
|
||||
super();
|
||||
}
|
||||
|
||||
// Private properties
|
||||
states = [
|
||||
{ inverted: true, invertedColor: "#F00"},
|
||||
{ inverted: true, invertedColor: "#FF0"},
|
||||
{ inverted: true, invertedColor: "#0FF"},
|
||||
{ inverted: false},
|
||||
{ inverted: true, invertedColor: "#0F0"},
|
||||
];
|
||||
|
||||
// Properties
|
||||
@State() state = this.states[0];
|
||||
|
||||
// Handlers
|
||||
|
||||
// CustomElement
|
||||
connectedCallback() {
|
||||
setInterval(()=>{
|
||||
// Moving state
|
||||
let curIndex = this.states.indexOf(this.state);
|
||||
this.state = this.states[(curIndex+1)>=this.states.length?0:curIndex+1];
|
||||
}, 1000);
|
||||
super.connectedCallback();
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<Host>
|
||||
<SvgLoader inverted={this.state.inverted} inverted-color={this.state.invertedColor} />
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
}
|
||||
58
tests/todos-mvc/components/my-todo.jsx
Normal file
58
tests/todos-mvc/components/my-todo.jsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import {defineElement, render, CustomElement, Host, State} from "../../../packages/csx";
|
||||
|
||||
import style from './my-todo.scss';
|
||||
import {TodoInput} from './todo-input';
|
||||
import {TodoItem} from './todo-item';
|
||||
|
||||
@defineElement('my-todo')
|
||||
export class MyTodo extends CustomElement{
|
||||
uid = 1;
|
||||
@State() todos = [
|
||||
{id: this.uid++, text: "my initial todo", checked: false },
|
||||
{id: this.uid++, text: "Learn about Web Components", checked: false },
|
||||
];
|
||||
|
||||
render(){
|
||||
return (
|
||||
<Host>
|
||||
<style>{ style }</style>
|
||||
<h1>CSX Todo</h1>
|
||||
<section>
|
||||
<TodoInput onSubmit={this.handleSubmit}/>
|
||||
<ul id="list-container"
|
||||
onCheck={this.handleCheck}
|
||||
onRemove={this.handleRemove}
|
||||
>
|
||||
{this.todos.map(item =>
|
||||
<TodoItem
|
||||
key={item.id}
|
||||
model={ item.id }
|
||||
checked={ item.checked }
|
||||
>
|
||||
{ item.text }
|
||||
</TodoItem>
|
||||
)}
|
||||
</ul>
|
||||
</section>
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
|
||||
handleSubmit = ({ detail: text }) => {
|
||||
if(text) {
|
||||
console.log("Submit rcvd: " + text);
|
||||
this.todos = [...this.todos, { id: this.uid++, text, checked: false }];
|
||||
}
|
||||
};
|
||||
handleCheck = ({detail: {checked,id}}) => {
|
||||
let indexOf = this.todos.findIndex(t=>t.id===id);
|
||||
if(indexOf>=0) {
|
||||
let updated = { ...this.todos[ indexOf ], checked };
|
||||
this.todos = [...this.todos.slice(0, indexOf), updated, ...this.todos.slice(indexOf + 1)];
|
||||
}
|
||||
};
|
||||
handleRemove = ({detail: {id}})=>{
|
||||
let indexOf = this.todos.findIndex(t=>t.id===id);
|
||||
this.todos = [...this.todos.slice(0,indexOf), ...this.todos.slice(indexOf+1)];
|
||||
}
|
||||
}
|
||||
24
tests/todos-mvc/components/my-todo.scss
Normal file
24
tests/todos-mvc/components/my-todo.scss
Normal file
@@ -0,0 +1,24 @@
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 60px;
|
||||
font-weight: 100;
|
||||
text-align: center;
|
||||
color: rgba(175, 47, 47, 0.15);
|
||||
}
|
||||
|
||||
section {
|
||||
background: #fff;
|
||||
margin: 30px 0 40px 0;
|
||||
position: relative;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
#list-container {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
border-top: 1px solid #e6e6e6;
|
||||
}
|
||||
35
tests/todos-mvc/components/todo-input.jsx
Normal file
35
tests/todos-mvc/components/todo-input.jsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import {defineElement, render, CustomElement, Host, State} from "../../../packages/csx";
|
||||
import style from './todo-input.scss';
|
||||
|
||||
@defineElement('todo-input')
|
||||
export class TodoInput extends CustomElement{
|
||||
@State() value = "";
|
||||
|
||||
render(){
|
||||
return (
|
||||
<Host>
|
||||
<style>{ style }</style>
|
||||
<form onSubmit={ this.handleSubmit }>
|
||||
<input
|
||||
value={this.value}
|
||||
type="text"
|
||||
placeholder="What needs to be done?"
|
||||
onInput={this.handleInput}
|
||||
/>
|
||||
</form>
|
||||
</Host>
|
||||
)
|
||||
}
|
||||
|
||||
handleSubmit = (e)=>{
|
||||
e.preventDefault();
|
||||
if (!this.value) return;
|
||||
this.dispatchEvent(new CustomEvent('submit', {
|
||||
detail: this.value
|
||||
}));
|
||||
this.value = "";
|
||||
};
|
||||
handleInput = ({target: {value}})=>{
|
||||
this.value = value;
|
||||
};
|
||||
}
|
||||
29
tests/todos-mvc/components/todo-input.scss
Normal file
29
tests/todos-mvc/components/todo-input.scss
Normal file
@@ -0,0 +1,29 @@
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
form {
|
||||
position: relative;
|
||||
font-size: 24px;
|
||||
border-bottom: 1px solid #ededed;
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 16px 16px 16px 60px;
|
||||
border: none;
|
||||
background: rgba(0, 0, 0, 0.003);
|
||||
position: relative;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-size: 24px;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
line-height: 1.4em;
|
||||
border: 0;
|
||||
outline: none;
|
||||
color: inherit;
|
||||
padding: 6px;
|
||||
border: 1px solid #CCC;
|
||||
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
41
tests/todos-mvc/components/todo-item.jsx
Normal file
41
tests/todos-mvc/components/todo-item.jsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import {defineElement, render, CustomElement, Host, ShadowDOM, State, Prop} from "../../../packages/csx";
|
||||
import style from './todo-item.scss';
|
||||
|
||||
@defineElement('todo-item')
|
||||
export class TodoItem extends CustomElement{
|
||||
@Prop() checked = false;
|
||||
@Prop() model;
|
||||
|
||||
render(){
|
||||
return (
|
||||
<Host>
|
||||
<ShadowDOM>
|
||||
<style>{ style }</style>
|
||||
<li class={( this.checked ? 'completed' : '' )}>
|
||||
<input
|
||||
type="checkbox" checked={ this.checked }
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<label>
|
||||
<slot />
|
||||
</label>
|
||||
<button onClick={this.handleClick}>x</button>
|
||||
</li>
|
||||
</ShadowDOM>
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
|
||||
handleChange = ()=>{
|
||||
this.dispatchEvent(new CustomEvent('check', {
|
||||
detail: {checked: (this.checked=!this.checked), id: this.model},
|
||||
bubbles: true
|
||||
}));
|
||||
};
|
||||
handleClick = ()=>{
|
||||
this.dispatchEvent(new CustomEvent('remove', {
|
||||
detail: {id: this.model},
|
||||
bubbles: true
|
||||
}));
|
||||
};
|
||||
}
|
||||
88
tests/todos-mvc/components/todo-item.scss
Normal file
88
tests/todos-mvc/components/todo-item.scss
Normal file
@@ -0,0 +1,88 @@
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
li {
|
||||
font-size: 24px;
|
||||
display: block;
|
||||
position: relative;
|
||||
border-bottom: 1px solid #ededed;
|
||||
}
|
||||
|
||||
li input {
|
||||
text-align: center;
|
||||
width: 40px;
|
||||
/* auto, since non-WebKit browsers doesn't support input styling */
|
||||
height: auto;
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
bottom: 0;
|
||||
margin: auto 0;
|
||||
border: none;
|
||||
/* Mobile Safari */
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
li input:after {
|
||||
content: url('data:image/svg+xml;utf8,<svg%20xmlns%3D"http%3A//www.w3.org/2000/svg"%20width%3D"40"%20height%3D"40"%20viewBox%3D"-10%20-18%20100%20135"><circle%20cx%3D"50"%20cy%3D"50"%20r%3D"50"%20fill%3D"none"%20stroke%3D"%23ededed"%20stroke-width%3D"3"/></svg>');
|
||||
}
|
||||
|
||||
li input:checked:after {
|
||||
content: url('data:image/svg+xml;utf8,<svg%20xmlns%3D"http%3A//www.w3.org/2000/svg"%20width%3D"40"%20height%3D"40"%20viewBox%3D"-10%20-18%20100%20135"><circle%20cx%3D"50"%20cy%3D"50"%20r%3D"50"%20fill%3D"none"%20stroke%3D"%23bddad5"%20stroke-width%3D"3"/><path%20fill%3D"%235dc2af"%20d%3D"M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z"/></svg>');
|
||||
}
|
||||
|
||||
li label {
|
||||
white-space: pre;
|
||||
word-break: break-word;
|
||||
padding: 15px 60px 15px 15px;
|
||||
margin-left: 45px;
|
||||
display: block;
|
||||
line-height: 1.2;
|
||||
transition: color 0.4s;
|
||||
}
|
||||
|
||||
li.completed label {
|
||||
color: #d9d9d9;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
li button,
|
||||
li input[type="checkbox"] {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
li button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
color: inherit;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-font-smoothing: antialiased;
|
||||
font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
li button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 10px;
|
||||
bottom: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: auto 0;
|
||||
font-size: 30px;
|
||||
color: #cc9a9a;
|
||||
margin-bottom: 11px;
|
||||
transition: color 0.2s ease-out;
|
||||
}
|
||||
|
||||
li button:hover {
|
||||
color: #af5b5e;
|
||||
}
|
||||
10
tests/todos-mvc/index.html
Normal file
10
tests/todos-mvc/index.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Todos MVC</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
10
tests/todos-mvc/index.jsx
Normal file
10
tests/todos-mvc/index.jsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import {render} from "../../packages/csx";
|
||||
import style from "./index.scss";
|
||||
import {MyTodo} from "./components/my-todo";
|
||||
|
||||
// Replace this with an example implementation of the Todos-MVC app
|
||||
// look for inspiration here: https://github.com/shprink/web-components-todo
|
||||
document.body.appendChild(render(<style>{style}</style>));
|
||||
document.body.appendChild(render(<div class="center-me">
|
||||
<MyTodo />
|
||||
</div>));
|
||||
19
tests/todos-mvc/index.scss
Normal file
19
tests/todos-mvc/index.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
html{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.center-me{
|
||||
align-self: center;
|
||||
}
|
||||
Reference in New Issue
Block a user