-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
- Loading branch information
1 parent
6a632a6
commit f6fcc6e
Showing
44 changed files
with
1,025 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,5 +4,7 @@ | |
"initialVersions": { | ||
"haunted": "5.0.0" | ||
}, | ||
"changesets": [] | ||
"changesets": [ | ||
"chilly-ants-swim" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; |
Oops, something went wrong.