Skip to content

Commit

Permalink
[ci] release (next) (#391)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
github-actions[bot] and github-actions[bot] committed May 18, 2022
1 parent 6a632a6 commit f6fcc6e
Show file tree
Hide file tree
Showing 44 changed files with 1,025 additions and 3 deletions.
4 changes: 3 additions & 1 deletion .changeset/pre.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
"initialVersions": {
"haunted": "5.0.0"
},
"changesets": []
"changesets": [
"chilly-ants-swim"
]
}
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# haunted

## 6.0.0-next.0

### Major Changes

- f861a4b: Deprecates haunted.js and web.js bundles
20 changes: 20 additions & 0 deletions component.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { GenericRenderer, RenderFunction } from './core';
interface Renderer<P extends object> extends GenericRenderer<HTMLElement, P> {
(this: Component<P>, host: Component<P>): unknown | void;
observedAttributes?: (keyof P)[];
}
declare type Component<P extends object> = HTMLElement & P;
declare type Constructor<P extends object> = new (...args: unknown[]) => Component<P>;
interface Creator {
<P extends object>(renderer: Renderer<P>): Constructor<P>;
<P extends object>(renderer: Renderer<P>, options: Options<P>): Constructor<P>;
<P extends object>(renderer: Renderer<P>, baseElement: Constructor<{}>, options: Omit<Options<P>, 'baseElement'>): Constructor<P>;
}
interface Options<P> {
baseElement?: Constructor<{}>;
observedAttributes?: (keyof P)[];
useShadowDOM?: boolean;
shadowRootInit?: ShadowRootInit;
}
declare function makeComponent(render: RenderFunction): Creator;
export { makeComponent, Component, Constructor as ComponentConstructor, Creator as ComponentCreator };
106 changes: 106 additions & 0 deletions component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { BaseScheduler } from './scheduler';
const toCamelCase = (val = '') => val.replace(/-+([a-z])?/g, (_, char) => char ? char.toUpperCase() : '');
function makeComponent(render) {
class Scheduler extends BaseScheduler {
frag;
constructor(renderer, frag, host) {
super(renderer, (host || frag));
this.frag = frag;
}
commit(result) {
render(result, this.frag);
}
}
function component(renderer, baseElementOrOptions, options) {
const BaseElement = (options || baseElementOrOptions || {}).baseElement || HTMLElement;
const { observedAttributes = [], useShadowDOM = true, shadowRootInit = {} } = options || baseElementOrOptions || {};
class Element extends BaseElement {
_scheduler;
static get observedAttributes() {
return renderer.observedAttributes || observedAttributes || [];
}
constructor() {
super();
if (useShadowDOM === false) {
this._scheduler = new Scheduler(renderer, this);
}
else {
this.attachShadow({ mode: 'open', ...shadowRootInit });
this._scheduler = new Scheduler(renderer, this.shadowRoot, this);
}
}
connectedCallback() {
this._scheduler.update();
}
disconnectedCallback() {
this._scheduler.teardown();
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue === newValue) {
return;
}
let val = newValue === '' ? true : newValue;
Reflect.set(this, toCamelCase(name), val);
}
}
;
function reflectiveProp(initialValue) {
let value = initialValue;
let isSetup = false;
return Object.freeze({
enumerable: true,
configurable: true,
get() {
return value;
},
set(newValue) {
// Avoid scheduling update when prop value hasn't changed
if (isSetup && value === newValue)
return;
isSetup = true;
value = newValue;
if (this._scheduler) {
this._scheduler.update();
}
}
});
}
const proto = new Proxy(BaseElement.prototype, {
getPrototypeOf(target) {
return target;
},
set(target, key, value, receiver) {
let desc;
if (key in target) {
desc = Object.getOwnPropertyDescriptor(target, key);
if (desc && desc.set) {
desc.set.call(receiver, value);
return true;
}
Reflect.set(target, key, value, receiver);
return true;
}
if (typeof key === 'symbol' || key[0] === '_') {
desc = {
enumerable: true,
configurable: true,
writable: true,
value
};
}
else {
desc = reflectiveProp(value);
}
Object.defineProperty(receiver, key, desc);
if (desc.set) {
desc.set.call(receiver, value);
}
return true;
}
});
Object.setPrototypeOf(Element.prototype, proto);
return Element;
}
return component;
}
export { makeComponent };
27 changes: 27 additions & 0 deletions core.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ComponentCreator } from './component';
import { ContextCreator } from './create-context';
import { ChildPart } from 'lit/html';
declare type Component<P> = HTMLElement & P;
declare type ComponentOrVirtualComponent<T extends HTMLElement | ChildPart, P extends object> = T extends HTMLElement ? Component<P> : ChildPart;
declare type GenericRenderer<T extends HTMLElement | ChildPart, P extends object = {}> = (this: ComponentOrVirtualComponent<T, P>, ...args: any[]) => unknown | void;
declare type RenderFunction = (result: unknown, container: DocumentFragment | HTMLElement) => void;
interface Options {
render: RenderFunction;
}
declare function haunted({ render }: Options): {
component: ComponentCreator;
createContext: ContextCreator;
};
export { haunted as default, Options, GenericRenderer, RenderFunction, ComponentOrVirtualComponent };
export { useCallback } from './use-callback';
export { useController } from './use-controller';
export { useEffect } from './use-effect';
export { useLayoutEffect } from './use-layout-effect';
export { useState } from './use-state';
export { useReducer } from './use-reducer';
export { useMemo } from './use-memo';
export { useContext } from './use-context';
export { useRef } from './use-ref';
export { hook, Hook } from './hook';
export { BaseScheduler } from './scheduler';
export { State } from './state';
20 changes: 20 additions & 0 deletions core.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { makeComponent } from './component';
import { makeContext } from './create-context';
function haunted({ render }) {
const component = makeComponent(render);
const createContext = makeContext(component);
return { component, createContext };
}
export { haunted as default };
export { useCallback } from './use-callback';
export { useController } from './use-controller';
export { useEffect } from './use-effect';
export { useLayoutEffect } from './use-layout-effect';
export { useState } from './use-state';
export { useReducer } from './use-reducer';
export { useMemo } from './use-memo';
export { useContext } from './use-context';
export { useRef } from './use-ref';
export { hook, Hook } from './hook';
export { BaseScheduler } from './scheduler';
export { State } from './state';
20 changes: 20 additions & 0 deletions create-context.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ComponentConstructor, ComponentCreator } from './component';
interface ConsumerProps<T> {
render: (value: T) => unknown;
}
interface Creator {
<T>(defaultValue: T): Context<T>;
}
interface Context<T> {
Provider: ComponentConstructor<{}>;
Consumer: ComponentConstructor<ConsumerProps<T>>;
defaultValue: T;
}
interface ContextDetail<T> {
Context: Context<T>;
callback: (value: T) => void;
value: T;
unsubscribe?: (this: Context<T>) => void;
}
declare function makeContext(component: ComponentCreator): Creator;
export { makeContext, Creator as ContextCreator, Context, ContextDetail };
48 changes: 48 additions & 0 deletions create-context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { contextEvent } from './symbols';
import { useContext } from './use-context';
function makeContext(component) {
return (defaultValue) => {
const Context = {
Provider: class extends HTMLElement {
listeners;
_value;
constructor() {
super();
this.listeners = new Set();
this.addEventListener(contextEvent, this);
}
disconnectedCallback() {
this.removeEventListener(contextEvent, this);
}
handleEvent(event) {
const { detail } = event;
if (detail.Context === Context) {
detail.value = this.value;
detail.unsubscribe = this.unsubscribe.bind(this, detail.callback);
this.listeners.add(detail.callback);
event.stopPropagation();
}
}
unsubscribe(callback) {
this.listeners.delete(callback);
}
set value(value) {
this._value = value;
for (let callback of this.listeners) {
callback(value);
}
}
get value() {
return this._value;
}
},
Consumer: component(function ({ render }) {
const context = useContext(Context);
return render(context);
}),
defaultValue,
};
return Context;
};
}
export { makeContext };
4 changes: 4 additions & 0 deletions create-effect.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { State, Callable } from './state';
declare type Effect = (this: State) => void | VoidFunction | Promise<void>;
declare function createEffect(setEffects: (state: State, cb: Callable) => void): (callback: Effect, values?: unknown[] | undefined) => void;
export { createEffect };
36 changes: 36 additions & 0 deletions create-effect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Hook, hook } from './hook';
function createEffect(setEffects) {
return hook(class extends Hook {
callback;
lastValues;
values;
_teardown;
constructor(id, state, ignored1, ignored2) {
super(id, state);
setEffects(state, this);
}
update(callback, values) {
this.callback = callback;
this.values = values;
}
call() {
if (!this.values || this.hasChanged()) {
this.run();
}
this.lastValues = this.values;
}
run() {
this.teardown();
this._teardown = this.callback.call(this.state);
}
teardown() {
if (typeof this._teardown === 'function') {
this._teardown();
}
}
hasChanged() {
return !this.lastValues || this.values.some((value, i) => this.lastValues[i] !== value);
}
});
}
export { createEffect };
3 changes: 3 additions & 0 deletions haunted.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { html, render, component, createContext, virtual } from './lit-haunted';
export * from './core';
export { default } from './core';
13 changes: 13 additions & 0 deletions hook.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { State } from './state';
declare abstract class Hook<P extends unknown[] = unknown[], R = unknown, H = unknown> {
id: number;
state: State<H>;
constructor(id: number, state: State<H>);
abstract update(...args: P): R;
teardown?(): void;
}
interface CustomHook<P extends unknown[] = unknown[], R = unknown, H = unknown> {
new (id: number, state: State<H>, ...args: P): Hook<P, R, H>;
}
declare function hook<P extends unknown[], R, H = unknown>(Hook: CustomHook<P, R, H>): (...args: P) => R;
export { hook, Hook };
24 changes: 24 additions & 0 deletions hook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { current, notify } from './interface';
import { hookSymbol } from './symbols';
class Hook {
id;
state;
constructor(id, state) {
this.id = id;
this.state = state;
}
}
function use(Hook, ...args) {
let id = notify();
let hooks = current[hookSymbol];
let hook = hooks.get(id);
if (!hook) {
hook = new Hook(id, current, ...args);
hooks.set(id, hook);
}
return hook.update(...args);
}
function hook(Hook) {
return use.bind(null, Hook);
}
export { hook, Hook };
6 changes: 6 additions & 0 deletions interface.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { State } from './state';
declare let current: State | null;
declare function setCurrent(state: State): void;
declare function clear(): void;
declare function notify(): number;
export { clear, current, setCurrent, notify };
13 changes: 13 additions & 0 deletions interface.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
let current;
let currentId = 0;
function setCurrent(state) {
current = state;
}
function clear() {
current = null;
currentId = 0;
}
function notify() {
return currentId++;
}
export { clear, current, setCurrent, notify };
4 changes: 4 additions & 0 deletions lit-haunted.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { html, render } from 'lit';
declare const component: import("./component").ComponentCreator, createContext: import("./create-context").ContextCreator;
declare const virtual: any;
export { component, createContext, virtual, html, render };
6 changes: 6 additions & 0 deletions lit-haunted.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { html, render } from 'lit';
import haunted from './core';
import { makeVirtual } from './virtual';
const { component, createContext } = haunted({ render });
const virtual = makeVirtual();
export { component, createContext, virtual, html, render };

0 comments on commit f6fcc6e

Please sign in to comment.