1.0.16 • Published 1 year ago
@not-react/main v1.0.16
NotReact
A minimalist React alternative.
Install
npm install @not-react/main webpack style-loader css-loader
Setup
npx not-react-init
Bare Example
import * as N from '@not-react/main'
const pool = new N.Pool('main');
pool.set('click-count', 0);
document.body.append(
N.Component('main')
.addItems(
N.Component('p')
.bind(pool.ref('click-count'), self =>
self
.setText(`You clicked the button ${pool.get('click-count')} times.`)
)
.update(pool.ref('click-count')),
N.Component('button')
.setText('Click here')
.listen('click', () => pool.set('click-count', pool.get('click-count') + 1)),
)
)
Reactivity
- A state is a changeable piece of data.
- A pool holds states
- There may be multiple pools in edge use cases
- A StateRef references a state inside a specific pool
/** references a state of a pool */
export class StateRef {
pool: Pool;
id: string;
constructor(pool: Pool, id: string) {
this.pool = pool;
this.id = id;
}
get value() {
return this.pool.get(this.id);
}
}
/** holds a set of states */
export class Pool {
states = new Map<string, any>();
id: string;
constructor(id: string) {
this.id = id;
}
set(id: string, value: any) {
this.states.set(id, value);
this.trigger(id);
}
get(id: string) {
return this.states.get(id);
}
ref(id: string): StateRef {
return new StateRef(this, id);
}
flip(id: string) {
this.states.set(id, !this.states.get(id));
this.trigger(id);
}
push(id: string, ...states: any[]) {
this.states.get(id).push(...states);
this.trigger(id);
}
splice(id: string, start: number, deleteCount: number, ...states: any) {
this.states.get(id).splice(start, deleteCount, ...states);
this.trigger(id);
}
/** forces binding components to refresh */
trigger(id: string) {
document.querySelectorAll(`[binding-${this.id}-${id}]`).forEach(el => {
dispatchStateEvent(el, this.ref(id));
})
}
}
Components
- Created and nested declaratively
export class ComponentTracker {
components: Map<string, Component>;
constructor() {
this.components = new Map();
}
track(component: Component) {
this.components.set(component.id, component);
}
get(id: string) {
return this.components.get(id);
}
}
export interface Component extends HTMLElement {
value: any;
/** clears the innerHTML of the component */
clear: () => this;
/** exposes the component in a callback function */
modify: (fn: (self: this) => void) => this;
/** tracks the component using its id */
track: (tracker: ComponentTracker) => this;
setId: (id: string) => this;
setClass: (className: string) => this;
addClass: (className: string) => this;
rmClass: (className: string) => this;
toggleClass: (className: string, toggle?: boolean) => this;
addAttr: (key: string, value?: string) => this;
rmAttr: (key: string) => this;
toggleAttr: (key: string, toggle?: boolean) => this;
setCss: (css: string) => this;
setStyle: (property: keyof CSSStyleDeclaration, style: string) => this;
addItems: (...children: (Element|string|undefined)[]) => this;
setText: (text: string) => this;
setHTML: (html: string) => this;
setVal: (value: string) => this;
listen: (type: string, listener: (self: this, event: Event) => void) => this;
/** binds to a state. callback function is triggered on state change */
bind: (ref: StateRef, callback: (self: this) => void) => this;
/** triggers the binding callback of a state */
update: (ref: StateRef) => this;
}
Custom Components
- These are examples on how to create a custom component
//simple
function Headline(text: string) {
return Component('h1')
.setText(text)
}
//with custom properties
interface MyComponent extends Component {
myProperty: string;
}
function MyComponent() {
return (Component('div') as MyComponent)
.modify(self => {
self.myProperty = 'hello';
})
}
1.0.16
1 year ago
1.0.15-beta1
1 year ago
1.0.14
1 year ago
1.0.13
1 year ago
1.0.12
1 year ago
1.0.12-beta2
1 year ago
1.0.12-beta1
1 year ago
1.0.13-beta1
1 year ago
1.0.11
1 year ago
1.0.10
1 year ago
1.0.9
1 year ago
1.0.9-beta1
1 year ago
1.0.8
1 year ago
1.0.8-beta1
1 year ago
1.0.7
1 year ago
1.0.6
1 year ago
1.0.5
1 year ago
1.0.5-beta4
1 year ago