SVG handling
This commit is contained in:
parent
029fe16b6d
commit
698656c8f6
@ -62,6 +62,10 @@ export function render(vnode, opts = {}) {
|
|||||||
let {item, meta, previous} = state.queue.splice(0,1)[0];
|
let {item, meta, previous} = state.queue.splice(0,1)[0];
|
||||||
let renderer = meta.renderer;
|
let renderer = meta.renderer;
|
||||||
if(!renderer) throw new Error("No renderer for vnode", item.vnode);
|
if(!renderer) throw new Error("No renderer for vnode", item.vnode);
|
||||||
|
|
||||||
|
// SVG handling..
|
||||||
|
if(!item.inSvg && item.vnode?.type === 'svg') item.inSvg = true;
|
||||||
|
else if(item.inSvg && item.vnode?.type === 'foreignObject') item.inSvg = false;
|
||||||
|
|
||||||
// Create the element if no matching existing element was set
|
// Create the element if no matching existing element was set
|
||||||
let newlyCreated = false;
|
let newlyCreated = false;
|
||||||
|
|||||||
@ -13,6 +13,10 @@ const VNODEPROP_IGNORE = {
|
|||||||
['ref']: true
|
['ref']: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let namespace = {
|
||||||
|
svg: "http://www.w3.org/2000/svg"
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes care of rendering a typical VNode (like div, span or any custom-element)
|
* Takes care of rendering a typical VNode (like div, span or any custom-element)
|
||||||
*
|
*
|
||||||
@ -28,7 +32,11 @@ export const NodeTreeRenderer = {
|
|||||||
let vnode = item.vnode;
|
let vnode = item.vnode;
|
||||||
if(typeof(vnode.type) === 'string'){
|
if(typeof(vnode.type) === 'string'){
|
||||||
// String-type -> DOM
|
// String-type -> DOM
|
||||||
return item.document.createElement(vnode.type);
|
if(item.inSvg){
|
||||||
|
return item.document.createElementNS(namespace.svg, vnode.type);
|
||||||
|
}else{
|
||||||
|
return item.document.createElement(vnode.type);
|
||||||
|
}
|
||||||
}else if(vnode.type?.tagName){
|
}else if(vnode.type?.tagName){
|
||||||
// Object-type -> CUSTOM-ELEMENT
|
// Object-type -> CUSTOM-ELEMENT
|
||||||
return item.document.createElement(vnode.type.tagName);
|
return item.document.createElement(vnode.type.tagName);
|
||||||
@ -90,7 +98,8 @@ export const NodeTreeRenderer = {
|
|||||||
}
|
}
|
||||||
// TODO might want to support objects for defining events, so we can specifiy passive or not, and other event options
|
// TODO might want to support objects for defining events, so we can specifiy passive or not, and other event options
|
||||||
}else{
|
}else{
|
||||||
if(!VNODEPROP_EXCLUDE_DIRECT[key]){
|
if(!VNODEPROP_EXCLUDE_DIRECT[key] && !item.inSvg){
|
||||||
|
// TODO there are many properties we do not want to be setting directly.. (transform attr on svg's is a good example...)
|
||||||
// Unless otherwise excluded, set the prop directly on the Element as well (because this is what we'd typically want to do passing complex objects into custom-elements)
|
// Unless otherwise excluded, set the prop directly on the Element as well (because this is what we'd typically want to do passing complex objects into custom-elements)
|
||||||
host[key] = newVal;
|
host[key] = newVal;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,30 @@ export default [
|
|||||||
})
|
})
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
// SVG test
|
||||||
|
{
|
||||||
|
input: 'test/svg/index.jsx',
|
||||||
|
output: {
|
||||||
|
file: 'public/svg/index.js',
|
||||||
|
format: 'iife', // immediately-invoked function expression — suitable for <script> tags
|
||||||
|
sourcemap: true
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
sass(),
|
||||||
|
babel(), // babel
|
||||||
|
resolve({
|
||||||
|
extensions: [ '.mjs', '.js', '.jsx', '.json' ],
|
||||||
|
}), // node_modules
|
||||||
|
commonjs(), // CJS-modules
|
||||||
|
production && terser(), // minify, but only in production
|
||||||
|
copy({
|
||||||
|
targets: [
|
||||||
|
{ src: 'test/svg/index.html', dest: 'public/svg' }
|
||||||
|
],
|
||||||
|
copyOnce: true
|
||||||
|
})
|
||||||
|
]
|
||||||
|
},
|
||||||
// Todos MVC
|
// Todos MVC
|
||||||
{
|
{
|
||||||
input: 'test/todos-mvc/index.jsx',
|
input: 'test/todos-mvc/index.jsx',
|
||||||
|
|||||||
@ -10,21 +10,9 @@ document.body.appendChild(render(<div class="center-me" iCanDoUpperCaseAttrs={ "
|
|||||||
//document.body.appendChild(render(<example-page />));
|
//document.body.appendChild(render(<example-page />));
|
||||||
document.body.appendChild(render(<ExamplePage />));
|
document.body.appendChild(render(<ExamplePage />));
|
||||||
|
|
||||||
/**
|
|
||||||
* Findings:
|
|
||||||
* - JSX does not allow dot-notation in attributes: language error
|
|
||||||
* - Current code lower-cases attributes that result: this a limitation of setAttribute
|
|
||||||
* - React uses on<EventName> to capture events and the IDE auto-suggests using this (can we generalize this approach for customEvents?)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Continuation suggestionss:
|
* Continuation suggestionss:
|
||||||
* - ref={...} does not work yet
|
|
||||||
* - style-attribute untested
|
* - style-attribute untested
|
||||||
* - Want a way to toggle classes: <Host class={{'bq-checkbox': true, 'checked': this.isChecked}}> could do
|
* - Want a way to toggle classes: <Host class={{'bq-checkbox': true, 'checked': this.isChecked}}> could do
|
||||||
* - Need to support update an existing DOM-tree to a VNode-tree
|
|
||||||
* - Need to support the key-attribute for lists (linking with previous to have an idea how to update DOM-tree efficiently, are we going atomico/react/prect style diffing with a Virtual-DOM?)
|
|
||||||
* - <Host> and <ShadowDom> special handlers
|
|
||||||
* - Supporting fragments <>...</>?
|
* - Supporting fragments <>...</>?
|
||||||
* - Try working towards a simple ToDo-MVC application
|
|
||||||
*/
|
*/
|
||||||
@ -15,6 +15,9 @@
|
|||||||
<li>
|
<li>
|
||||||
<a href="./basic/">Basic testing</a>
|
<a href="./basic/">Basic testing</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="./svg/">SVG Rendering</a>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="./todos-mvc/">Todos MVC</a>
|
<a href="./todos-mvc/">Todos MVC</a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
10
test/svg/index.html
Normal file
10
test/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>
|
||||||
11
test/svg/index.jsx
Normal file
11
test/svg/index.jsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import {render} from "../../packages/csx";
|
||||||
|
import style from "./index.scss";
|
||||||
|
import {SvgLoader} from "./svg-loader";
|
||||||
|
|
||||||
|
document.body.appendChild(render(<style>{style}</style>));
|
||||||
|
document.body.appendChild(render(
|
||||||
|
<div class="center-me">
|
||||||
|
<h3>SVG Loader</h3>
|
||||||
|
<SvgLoader />
|
||||||
|
</div>
|
||||||
|
));
|
||||||
19
test/svg/index.scss
Normal file
19
test/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;
|
||||||
|
}
|
||||||
55
test/svg/svg-loader.jsx
Normal file
55
test/svg/svg-loader.jsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import {CustomElement, defineElement, Host, ShadowDOM, State} 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
|
||||||
|
|
||||||
|
// 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="#000">
|
||||||
|
<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
test/svg/svg-loader.shadow.scss
Normal file
10
test/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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user