v0.0.11: Added unit-tests, solved the key={...} problem, updated the build/watch configuration of CSX to be able to build minified and non-minified bundle outputs, as well as a CJS version of lib/ (for consuming in Node-environment, like Jest). The previous tests were renamed to examples, and should still need to be updated.
This commit is contained in:
23
examples/.babelrc
Normal file
23
examples/.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
examples/basic/index.html
Normal file
10
examples/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>
|
||||
32
examples/basic/index.jsx
Normal file
32
examples/basic/index.jsx
Normal file
@@ -0,0 +1,32 @@
|
||||
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 pageWidth={200} />));
|
||||
|
||||
/**
|
||||
* Continuation suggestionss:
|
||||
* - style-attribute untested
|
||||
* - Want a way to toggle classes: <Host class={{'bq-checkbox': true, 'checked': this.isChecked}}> could do
|
||||
* - Supporting fragments <>...</>?
|
||||
*/
|
||||
// Private vars are visible, because of loose mode, not desirable...
|
||||
class PrivTest{
|
||||
#privatevar = 1;
|
||||
get someVar(){
|
||||
console.log(Object.getOwnPropertyDescriptors(this));
|
||||
return this.#privatevar;
|
||||
}
|
||||
}
|
||||
let a = new PrivTest();
|
||||
console.log(a);
|
||||
console.log(a.someVar);
|
||||
|
||||
let preRenderedText = render("I can prerender text-nodes");
|
||||
document.body.appendChild(render(preRenderedText));
|
||||
19
examples/basic/index.scss
Normal file
19
examples/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;
|
||||
}
|
||||
32
examples/basic/page.jsx
Normal file
32
examples/basic/page.jsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import {defineElement, render, CustomElement, prop, state} from "../../packages/csx";
|
||||
|
||||
@defineElement('example-page')
|
||||
export class ExamplePage extends CustomElement{
|
||||
|
||||
@prop({reflect: true, attr: 'page-width'})
|
||||
set pageWidth(value){
|
||||
if(value!==this.#pageWidth){
|
||||
this.#pageWidth = value;
|
||||
}
|
||||
}
|
||||
get pageWidth(){
|
||||
return this.#pageWidth;
|
||||
}
|
||||
#pageWidth = undefined;
|
||||
|
||||
render(){
|
||||
return <div className="page" style={{width: `${this.pageWidth}px`}}>
|
||||
<h1>This page is an example!</h1>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean elit enim, lacinia in pellentesque ut, fermentum quis risus. Vivamus condimentum turpis ac mattis blandit. Ut scelerisque nulla suscipit, rhoncus justo eget, pulvinar ligula. Donec vel orci dolor. Etiam non neque non lorem venenatis tincidunt. Cras tristique mauris ut leo imperdiet, in bibendum elit ultricies. Morbi et felis sed arcu efficitur aliquam.<br/>
|
||||
Nam ornare scelerisque vestibulum. In porta non risus a tristique. Donec tincidunt diam sed dictum iaculis. In faucibus placerat justo, ut pulvinar tortor hendrerit viverra. Aliquam erat volutpat. Quisque euismod leo at eros fringilla varius. Nam et vulputate nunc. Nunc mattis purus eu massa lacinia posuere.<br/>
|
||||
In fermentum hendrerit purus non mollis. Duis vel leo nibh. Praesent at odio suscipit, consequat lorem quis, posuere lorem. Donec molestie sodales feugiat. Ut in nisi vel est luctus tristique non eget elit. Donec accumsan quam id scelerisque egestas. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum eu lacus convallis elit eleifend tristique id et sapien. Mauris cursus a enim ut scelerisque. Morbi auctor nisl sem, id dignissim lectus condimentum non. Ut tellus lacus, volutpat eget porttitor et, vulputate pharetra nunc. Donec nec ligula est. Donec eget odio tincidunt, laoreet mi sit amet, euismod odio. Donec vitae dignissim leo, nec ultricies quam.<br/>
|
||||
Proin efficitur arcu sit amet congue commodo. Suspendisse non tristique libero. Maecenas tempor arcu ac felis posuere, eu gravida metus euismod. Vivamus hendrerit nisl id venenatis sodales. Phasellus pharetra arcu a arcu aliquam faucibus. Etiam sodales ligula nisl, sit amet posuere turpis ultricies id. Donec euismod nunc eros, at euismod neque tempor a. Nullam felis eros, imperdiet ac arcu id, lobortis lobortis tellus. Duis mollis sodales leo, et tincidunt enim pretium luctus.<br/>ulputate lorem.
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
}
|
||||
}
|
||||
19
examples/cfg/.babelrc
Normal file
19
examples/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
examples/cfg/rollup-build.js
Normal file
166
examples/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("examples");
|
||||
/** @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 examples
|
||||
* @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();
|
||||
}
|
||||
|
||||
32
examples/index.html
Normal file
32
examples/index.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<!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>
|
||||
<li>
|
||||
<a href="./table/">Tables (arrow functions)</a>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
1
examples/index.jsx
Normal file
1
examples/index.jsx
Normal file
@@ -0,0 +1 @@
|
||||
/** I don't do nothing! (but it might later...) **/
|
||||
BIN
examples/pdf/assets/fonts/DINPro-Black.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-Black.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-BlackItalic.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-BlackItalic.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-Bold.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-Bold.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-BoldItalic.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-BoldItalic.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-Cond.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-Cond.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-CondBlack.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-CondBlack.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-CondBlackIta.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-CondBlackIta.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-CondBold.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-CondBold.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-CondBoldIta.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-CondBoldIta.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-CondIta.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-CondIta.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-CondLight.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-CondLight.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-CondLightIta.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-CondLightIta.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-CondMediIta.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-CondMediIta.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-CondMedium.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-CondMedium.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-Italic.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-Italic.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro-Light.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro-Light.otf
Normal file
Binary file not shown.
BIN
examples/pdf/assets/fonts/DINPro.otf
Normal file
BIN
examples/pdf/assets/fonts/DINPro.otf
Normal file
Binary file not shown.
73
examples/pdf/assets/logo.svg
Normal file
73
examples/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
examples/pdf/fonts.pcss
Normal file
106
examples/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
examples/pdf/index.html
Normal file
10
examples/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
examples/pdf/index.jsx
Normal file
88
examples/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
examples/pdf/index.pcss
Normal file
158
examples/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
examples/postcss.config.js
Normal file
9
examples/postcss.config.js
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
//require('autoprefixer'),
|
||||
require('postcss-import'),
|
||||
require('postcss-preset-env')({
|
||||
stage: 1,
|
||||
})
|
||||
]
|
||||
};
|
||||
10
examples/svg/index.html
Normal file
10
examples/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
examples/svg/index.jsx
Normal file
47
examples/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
examples/svg/index.scss
Normal file
19
examples/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
examples/svg/svg-loader.jsx
Normal file
57
examples/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
examples/svg/svg-loader.shadow.scss
Normal file
10
examples/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
examples/svg/svg-tester-two.jsx
Normal file
43
examples/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
examples/svg/svg-tester.jsx
Normal file
42
examples/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>
|
||||
);
|
||||
}
|
||||
}
|
||||
10
examples/table/index.html
Normal file
10
examples/table/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>
|
||||
108
examples/table/index.jsx
Normal file
108
examples/table/index.jsx
Normal file
@@ -0,0 +1,108 @@
|
||||
import {render, CustomElement, defineElement, Host, prop, state} from "../../packages/csx";
|
||||
import style from "./index.scss";
|
||||
import {TableComponent} from "./table-component";
|
||||
|
||||
@defineElement("table-tester")
|
||||
class TableTester extends CustomElement{
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @type {({[headerRender]: (function(): string), render: (function(User): *), [size]: number})[]}
|
||||
*/
|
||||
#columnDefinitions = [
|
||||
{
|
||||
headerRender: () => "Id",
|
||||
render: (u) => u.userId,
|
||||
size: 110
|
||||
},
|
||||
{
|
||||
headerRender: () => "Email",
|
||||
render: (u) => u.identity?.email,
|
||||
},
|
||||
{
|
||||
headerRender: () => "FirstName",
|
||||
render: (u) => u.identity?.firstName,
|
||||
size: 160
|
||||
},
|
||||
{
|
||||
headerRender: () => "LastName",
|
||||
render: (u) => u.identity?.lastName,
|
||||
size: 160
|
||||
},
|
||||
{
|
||||
headerRender: () => "...",
|
||||
render: (u) => {
|
||||
let d = new Date();
|
||||
return (<button onClick={(ev) => this.testMe(ev, u, d)}>test me</button>)
|
||||
},
|
||||
size: 110
|
||||
},
|
||||
];
|
||||
|
||||
@state()
|
||||
users = [];
|
||||
|
||||
render(){
|
||||
|
||||
return <TableComponent
|
||||
columns={this.#columnDefinitions}
|
||||
data={this.users}
|
||||
/>
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
setTimeout(()=>this.load(), 0);
|
||||
setTimeout(()=>this.load(), 50);
|
||||
setTimeout(()=>this.load(), 100);
|
||||
setTimeout(()=>this.load(), 150);
|
||||
setTimeout(()=>this.load(), 200);
|
||||
setTimeout(()=>this.load(), 250);
|
||||
|
||||
this.interval = setInterval(()=>this.load(), 3000);
|
||||
}
|
||||
|
||||
interval;
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
if(this.interval) {
|
||||
clearInterval(this.interval);
|
||||
}
|
||||
}
|
||||
|
||||
load(){
|
||||
let users = [];
|
||||
|
||||
let rndFirstNames = ['Loes', 'Johnny', 'Maria', 'Jezus', 'Philippe', 'Filip', 'Annie'];
|
||||
let rndLastNames = ['Peeters', 'Wachters', 'Jannsens', 'De Schaetzen', 'Becks', 'Konings', 'De Clerk'];
|
||||
|
||||
for(let i = 0; i < 5; ++i){
|
||||
let first = rndFirstNames[Math.floor(rndFirstNames.length*Math.random())];
|
||||
let last = rndLastNames[Math.floor(rndLastNames.length*Math.random())];
|
||||
users.push({
|
||||
userId: (Math.random()*99999).toString(36).slice(-6).toUpperCase(),
|
||||
identity: {
|
||||
firstName: first,
|
||||
lastName: last,
|
||||
email: `${first}.${last}@example.com`.toLocaleLowerCase()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.users = users;
|
||||
}
|
||||
|
||||
lastClear = new Date();
|
||||
testMe = (ev, u, d)=>{
|
||||
if((new Date()).getTime() - this.lastClear.getTime() > 20){
|
||||
console.log("\n\n");
|
||||
this.lastClear = new Date();
|
||||
}
|
||||
console.log("I should only show up once per click:", d.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
document.body.appendChild(render(<style>{style}</style>));
|
||||
document.body.appendChild(render(<TableTester/>));
|
||||
19
examples/table/index.scss
Normal file
19
examples/table/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;
|
||||
}
|
||||
61
examples/table/table-component.jsx
Normal file
61
examples/table/table-component.jsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import {CustomElement, defineElement, Host, prop, state} from "../../packages/csx";
|
||||
import TableComponentStyle from "./table-component.scss";
|
||||
|
||||
let tableId = 0;
|
||||
|
||||
@defineElement("tripto-table")
|
||||
export class TableComponent extends CustomElement {
|
||||
|
||||
#columnDefinitions;
|
||||
|
||||
@prop()
|
||||
set columns(value) {
|
||||
this.#columnDefinitions = value;
|
||||
}
|
||||
|
||||
@state() data;
|
||||
|
||||
@prop()
|
||||
set data(value) {
|
||||
this.data = value;
|
||||
}
|
||||
|
||||
#tableId = tableId++;
|
||||
render() {
|
||||
console.log(`Table render at for ${this.data?.length??0} rows: ${Date.now()}`);
|
||||
return (
|
||||
<Host>
|
||||
<style>{TableComponentStyle}</style>
|
||||
<style>
|
||||
{this.#columnDefinitions?.map((col, idx) => (
|
||||
`#table_${this.#tableId} .cell.cell_${idx} {` +
|
||||
` flex: ${(col.size ? (`0 0 ${col.size}px`) : `1`)};` +
|
||||
`}`
|
||||
))}
|
||||
</style>
|
||||
<section className="table" id={`table_${this.#tableId}`}>
|
||||
<header>
|
||||
<div className="row">
|
||||
{this.#columnDefinitions.map((col, idx) => (
|
||||
<div className={`cell cell_${idx}`}>
|
||||
{col.headerRender()}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
{this.data?.map(dataRow => (
|
||||
<div className="row">
|
||||
{this.#columnDefinitions.map((col, idx) => (
|
||||
<div className={`cell cell_${idx}`}>
|
||||
{col.render(dataRow)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</main>
|
||||
</section>
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
}
|
||||
32
examples/table/table-component.scss
Normal file
32
examples/table/table-component.scss
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
.table {
|
||||
--box-color: #a0a0a0;
|
||||
--primary-color: #5f74ff;
|
||||
--table-background: #e4e4f0;
|
||||
--box-border: 1px solid #7d7d7d;
|
||||
|
||||
border: var(--box-border);
|
||||
display: block;
|
||||
|
||||
header {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
header > .row,
|
||||
main > .row {
|
||||
background: var(--table-background);
|
||||
display: flex;
|
||||
width: 100%;
|
||||
line-height: 3em;
|
||||
border-bottom: var(--box-border);
|
||||
|
||||
.cell {
|
||||
padding: 0 15px;
|
||||
}
|
||||
}
|
||||
main > .row {
|
||||
&:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
58
examples/todos-mvc/components/my-todo.jsx
Normal file
58
examples/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
examples/todos-mvc/components/my-todo.scss
Normal file
24
examples/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
examples/todos-mvc/components/todo-input.jsx
Normal file
35
examples/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
examples/todos-mvc/components/todo-input.scss
Normal file
29
examples/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
examples/todos-mvc/components/todo-item.jsx
Normal file
41
examples/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({reflect: true}) 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
examples/todos-mvc/components/todo-item.scss
Normal file
88
examples/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
examples/todos-mvc/index.html
Normal file
10
examples/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
examples/todos-mvc/index.jsx
Normal file
10
examples/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
examples/todos-mvc/index.scss
Normal file
19
examples/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