Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
Hydrophobefireman committed Oct 31, 2019
0 parents commit f0e9ea3
Show file tree
Hide file tree
Showing 18 changed files with 4,686 additions and 0 deletions.
88 changes: 88 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# next.js build output
.next

# nuxt.js build output
.nuxt

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

.rts2_cache_es/
.rts2_cache_umd/
.rts2_cache_cjs/
89 changes: 89 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# QWC - Quick Web Components

QWC is the simplest way to create a new webcomponent, no need to write classes, QWC does that for you.

# Usage

1. Quick dirty non reactive element:
### index.html
```html
<template is="custom" custom-element="custom-element-name">
<style>
.your-scoped-css {
}
</style>
<button>My Custom Element</button>
</template>
<custom-element-name></custom-element-name>
```
### App.js
```javascript
import { init } from "@hydrophobefireman/qwc";
init();
```
2. Custom logic for your element
### index.html
```html
<template is="custom" custom-element="my-custom-element">
...
</template>
<my-custom-element></my-custom-element>
```
### App.js
```javascript
import { init } from "@hydrophobefireman/qwc";
init({
"my-custom-element": {
modifyConstructor(constructor) {
// modify class constructor
Object.defineProperty(constructor, "observedAttributes", {
get() {
return ["src"];
}
});
},
modifyPrototype(prototype) {
Object.defineProperty(prototype, "attributeChangedCallback", {
value() {
//do something with the new attributes
}
});
}
}
});
```

3) Dynamic properties in the dom
### index.html
```html
<template is="custom" custom-element="button-counter">
<div data-text-content="currentDate"></div>
<button
updates-reactively
data-text-content="count"
data-onclick="handleClick"
></button>
</template>
<button-counter></button-counter>
```
Note: only use attribute `updates-reactively` if your event listeners bring changes to your `<custom-element/>` otherwise using the attribute has no effect and leads to unnecessary updates.
### App.js
```javascript
import { init } from "@hydrophobefireman/qwc";
const conf = {
"button-counter": {
count: 0,
handleClick() {
conf.count++;
},
currentDate: new Date().toString()
}
};
init(null, conf);
```
NOTE: QWC prefers your `<template>` elements to be inlined in your html instead of having to write html-in-js. But you can provide it with all template elements if you prefer, as the 3<sup>rd</sup> argument
# Installation
`npm i @hydrophobefireman/qwc --save`
70 changes: 70 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const config = {
"animated-link": {
href: null,
animate(e) {
e.preventDefault();
const el = document.createElement("animate-text");
const div = document.createElement("div");
const url = this.customElement.config.href;
div.textContent = "Loading " + url;
el.appendChild(div);
document.body.appendChild(el);
setTimeout(() => (location = url), 500);
}
},
"button-counter-demo": {
count: 0,
val: "Not Clicked Yet",
handleClick() {
const cfg = this.customElement.config;
const c = ++cfg.count;
cfg.val = "Clicked " + c + " time" + (c === 1 ? "" : "s");
},
currentDate: new Date().toString()
}
};
const mods = {
"button-counter-demo": {
modifyPrototype(p) {
Object.defineProperties(p, {
connectedCallback: {
value() {
this.__interval = setInterval(() => {
this.config.currentDate = new Date().toString();
this.update();
}, 1000);
}
},
disconnectedCallback: {
value() {
clearInterval(this.__interval);
}
}
});
}
},
"animated-link": {
observedAttributes: [
{
prop: "unstyled",
type: "bool",
listener(o, n) {
const a = this.shadowRoot.querySelector("a");
const div = this.shadowRoot.querySelector("div");
if (n !== null) {
a.className = div.className = "unstyled";
} else {
a.className = div.className = "styled";
}
}
},
{
prop: "href",
listener(ov, nv) {
this.config.href = nv;
this.update();
}
}
]
}
};
48 changes: 48 additions & 0 deletions applyProps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { arrFrom } from "./util.js";
/**
*
* @param {HTMLElement} el
* @param {{[key:string]:any}} props
*/
export function recursivelyApplyProps(el, props, recursive, customElement) {
/**
* @type {HTMLElement[]}
*/
const children = arrFrom(el.children);
for (const child of children) {
child.customElement = customElement;
const ds = child.dataset;
for (let prop in ds) {
const val = ds[prop];
let v = props[val];
prop = prop === "class" ? "className" : prop;
if (prop[0] === "o" && prop[1] === "n") {
v = v.bind(child);
let fn;
if (!child.hasAttribute("updates-reactively")) {
fn = v;
} else {
if (recursive) continue;
fn = function() {
const args = arrFrom(arguments);
v.apply(null, args);
recursivelyApplyProps(el, props, true, customElement);
};
}
const evt = prop.substr(2);
child._events || (child._events = {});
if (!child._events[evt]) {
child.addEventListener(evt, eventListenerProxy);
}
child._events[evt] = fn;
} else {
child[prop] = v;
}
}
recursivelyApplyProps(child, props, false, customElement);
}
}

function eventListenerProxy(e) {
this._events[e.type](e);
}
2 changes: 2 additions & 0 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit f0e9ea3

Please sign in to comment.