Comparing version 2.0.16 to 2.0.17
310
index.d.ts
// Minimum TypeScript Version: 4.2 | ||
// This requires every property of an object or none at all. | ||
type AllOrNothing<T> = T | { [K in keyof T]?: never } | ||
// This ensures at least one property in an object is present. | ||
type AtLeastOne<T> = { [K in keyof T]: Pick<T, K> }[keyof T] | ||
// Credit: https://stackoverflow.com/a/59987826/1935675 | ||
// This ensures at least one object property group is present. | ||
type AtLeastSomething<T, U> = U | AtLeastOne<T> & AllOrNothing<U> | ||
// Most event typings are provided by TypeScript itself. | ||
type EventsMap = | ||
& { [K in keyof HTMLElementEventMap as `on${K}`]: HTMLElementEventMap[K] } | ||
& { [K in keyof WindowEventMap as `on${K}`]: WindowEventMap[K] } | ||
& { onsearch: Event } | ||
// Indexable values are able to use subscripting. | ||
type Indexable = string | unknown[] | Record<string, any> | ||
// This validates plain objects while invalidating array objects and string | ||
// objects by disallowing numerical indexing. | ||
type IndexableByKey = Record<number, never> | ||
// Empty strings can cause issues in certain places. | ||
type NonEmptyString<T> = T extends "" ? never : T | ||
// ----------------------------------------------------------------------------- | ||
declare module "hyperapp" { | ||
// `app()` initiates a Hyperapp instance. `app()` along with runners and | ||
// subscribers are the only places where side effects are allowed. | ||
// `app()` initiates a Hyperapp instance. Only `app()`'s `node:` property and | ||
// effecters and subscribers are allowed to have side effects. | ||
function app<S>(props: App<S>): Dispatch<S> | ||
@@ -10,105 +38,81 @@ | ||
function h<S, C = unknown, T extends string = string>( | ||
// Tags cannot be empty strings. | ||
tag: T extends "" ? never : T, | ||
props: ValidateCustomPayloads<S, C> & PropList<S>, | ||
children?: MaybeVDOM<S> | readonly MaybeVDOM<S>[] | ||
): VDOM<S> | ||
tag: NonEmptyString<T>, | ||
props: CustomPayloads<S, C> & Props<S>, | ||
children?: MaybeVNode<S> | readonly MaybeVNode<S>[] | ||
): VNode<S> | ||
// `memo()` stores a view along with any given data for it. | ||
function memo< | ||
S, | ||
D extends string | unknown[] | Record<string, any> = | ||
| string | ||
| unknown[] | ||
| Record<string, any> | ||
>(view: View<D>, data: D): VDOM<S> | ||
function memo<S, D extends Indexable = Indexable>( | ||
view: (data: D) => VNode<S>, | ||
data: D | ||
): VNode<S> | ||
// `text()` creates a virtual DOM node representing plain text. | ||
function text<S, T = unknown>( | ||
// While most values can be stringified, symbols and functions cannot. | ||
value: T extends symbol | ((..._: any[]) => any) ? never : T | ||
): VDOM<S> | ||
// Values, aside from symbols and functions, can be handled. | ||
value: T extends symbol | ((..._: unknown[]) => unknown) ? never : T | ||
): VNode<S> | ||
// --------------------------------------------------------------------------- | ||
// This lets you use a version of `h` which assumes your particular app state. | ||
// The `_ extends never` ensures that any such state-aware `h` doesn't have | ||
// an explicitly set state type that contradicts the type it actually uses. | ||
// This lets you make a variant of `h()` which is aware of your Hyperapp | ||
// instance's state. The `_ extends never` ensures that any state-aware | ||
// `h()` doesn't have an explicit state type that contradicts the | ||
// state type it actually uses. | ||
interface TypedH<S> { | ||
<_ extends never, T extends string = string>( | ||
tag: T extends "" ? never : T, | ||
props: PropList<S>, | ||
children?: MaybeVDOM<S> | readonly MaybeVDOM<S>[] | ||
): VDOM<S> | ||
<_ extends never, C = unknown, T extends string = string>( | ||
tag: NonEmptyString<T>, | ||
props: CustomPayloads<S, C> & Props<S>, | ||
children?: MaybeVNode<S> | readonly MaybeVNode<S>[] | ||
): VNode<S> | ||
} | ||
// This helper for `h` lets event handling actions accept custom payloads. | ||
type ValidateCustomPayloads<S, T> = { | ||
[K in keyof T]?: K extends "style" | ||
? StyleProp | ||
: T[K] extends [Action<S, infer P>, unknown] | ||
? [Action<S, P>, P] | ||
: T[K] | ||
} | ||
// --------------------------------------------------------------------------- | ||
// This utility type requires every property of an object or none at all. | ||
// `App` uses this to make sure `view:` always appears alongside `node:`. | ||
type AllOrNothing<T> = T | { [K in keyof T]?: never } | ||
// An action transforms existing state and/or wraps another action. | ||
type Action<S, P = any> = (state: S, payload: P) => Dispatchable<S> | ||
// This utility type ensures at least one property in an object to be present. | ||
// `App` uses this to conveniently invalidate `app({})` because that is | ||
// basically a fancy no-op. | ||
type AtLeastOne<T> = { [K in keyof T]: Pick<T, K> }[keyof T] | ||
// Credit: https://stackoverflow.com/a/59987826/1935675 | ||
// This utility type validates plain objects while invalidating array objects | ||
// and string objects by disallowing numerical indexing. Used by `StyleProp`. | ||
type IndexableByKey = Record<number, never> | ||
// --------------------------------------------------------------------------- | ||
// A Hyperapp instance generally has an initial state and a base view and is | ||
// A Hyperapp instance typically has an initial state and a top-level view | ||
// mounted over an available DOM element. | ||
type App<S> = Readonly< | ||
| { | ||
view: View<S> | ||
node: Node | ||
} | ||
| (AtLeastOne<{ | ||
init: Dispatchable<S> | ||
subscriptions: Subscriptions<S> | ||
dispatch: DispatchInitializer<S> | ||
}> & | ||
AllOrNothing<{ | ||
view: View<S> | ||
node: Node | ||
}>) | ||
> | ||
type App<S> = | ||
Readonly<AtLeastSomething<{ | ||
// State is established through either direct assignment or an action. | ||
init: Dispatchable<S> | ||
// A view builds a virtual DOM node representation of the application state. | ||
type View<S> = (state: S) => VDOM<S> | ||
// The subscriptions function manages a set of subscriptions. | ||
subscriptions: (state: S) => | ||
readonly (boolean | undefined | Subscription<S>)[] | ||
// The subscriptions function manages a set of subscriptions. | ||
type Subscriptions<S> = ( | ||
state: S | ||
) => (boolean | undefined | Subscription<S> | Unsubscribe)[] | ||
// Dispatching can be augmented to do custom processing. | ||
dispatch: (dispatch: Dispatch<S>) => Dispatch<S> | ||
}, { | ||
// The top-level view can build a virtual DOM node depending on the state. | ||
view: (state: S) => VNode<S> | ||
// A subscription reacts to external activity. | ||
type Subscription<S, P = any> = [ | ||
subscriber: (dispatch: Dispatch<S>, payload: P) => void | Unsubscribe, | ||
payload: P | ||
] | ||
// The mount node is where a Hyperapp instance will get placed. | ||
node: Node | ||
}>> | ||
// An unsubscribe function cleans up a canceled subscription. | ||
type Unsubscribe = () => void | ||
// The `class` property represents an HTML class attribute string. | ||
type ClassProp = | ||
| boolean | ||
| string | ||
| undefined | ||
| Record<string, boolean | undefined> | ||
| ClassProp[] | ||
// Dispatching can be augmented to do custom processing. | ||
type DispatchInitializer<S> = (dispatch: Dispatch<S>) => Dispatch<S> | ||
// This lets event-handling actions properly accept custom payloads. | ||
type CustomPayloads<S, T> = { | ||
[K in keyof T]?: | ||
K extends "style" | ||
? StyleProp | ||
: T[K] extends [action: Action<S, infer P>, payload: unknown] | ||
? readonly [action: Action<S, P>, payload: P] | ||
: T[K] | ||
} | ||
// --------------------------------------------------------------------------- | ||
// Dispatching will cause state transitions. | ||
type Dispatch<S> = (dispatchable: Dispatchable<S>, payload?: unknown) => void | ||
// A dispatched action handles an event in the context of the current state. | ||
type Dispatch<S> = (dispatchable: Dispatchable<S>, payload?: any) => void | ||
// A dispatchable entity, when processed, causes a state transition. | ||
// A dispatchable entity is used to cause a state transition. | ||
type Dispatchable<S, P = any> = | ||
@@ -118,9 +122,6 @@ | S | ||
| Action<S, P> | ||
| [action: Action<S, P>, payload: P] | ||
| readonly [action: Action<S, P>, payload: P] | ||
// An action transforms existing state and/or wraps another action. | ||
type Action<S, P = any> = (state: S, payload: P) => Dispatchable<S> | ||
// An effect is where side effects and any additional dispatching may occur. | ||
type Effect<S, P = any> = [ | ||
type Effect<S, P = any> = readonly [ | ||
effecter: (dispatch: Dispatch<S>, payload: P) => void | Promise<void>, | ||
@@ -130,42 +131,14 @@ payload: P | ||
// --------------------------------------------------------------------------- | ||
// A virtual DOM node represents an actual DOM element. | ||
type VDOM<S> = { | ||
readonly type: VDOMNodeType | ||
readonly props: PropList<S> | ||
readonly children: MaybeVDOM<S>[] | ||
node: null | undefined | Node | ||
readonly tag: Tag<S> | ||
readonly key: Key | ||
memo?: PropList<S> | ||
events?: Record<string, Action<S> | [action: Action<S>, payload: any]> | ||
// `_VDOM` is a guard property which gives us a way to tell `VDOM` objects | ||
// apart from `PropList` objects. Since we don't expect users to manually | ||
// create their own VNodes, we can take advantage of this trick that's | ||
// specific to TypeScript without forcing the user to do | ||
// anything different. | ||
_VDOM: true | ||
// Event handlers are implemented using actions. | ||
type EventActions<S> = { | ||
[K in keyof EventsMap]: | ||
| Action<S, EventsMap[K]> | ||
| readonly [action: Action<S>, payload: unknown] | ||
} | ||
// These are based on actual DOM node types: | ||
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType | ||
const enum VDOMNodeType { | ||
SSR = 1, | ||
Text = 3, | ||
} | ||
// In certain places a virtual DOM node can be made optional. | ||
type MaybeVDOM<S> = boolean | null | undefined | VDOM<S> | ||
type MaybeVNode<S> = boolean | null | undefined | VNode<S> | ||
// A virtual DOM node's tag has metadata relevant to it. Virtual DOM nodes are | ||
// tagged by their type to assist rendering. | ||
type Tag<S> = string | View<S> | ||
// A key can uniquely associate a virtual DOM node with a certain DOM element. | ||
type Key = string | null | undefined | ||
// Virtual DOM properties will often correspond to HTML attributes. | ||
type PropList<S> = | ||
type Props<S> = | ||
Readonly< | ||
@@ -184,47 +157,62 @@ Partial< | ||
class?: ClassProp | ||
key?: Key | ||
key?: VNode<S>["key"] | ||
style?: StyleProp | ||
// By disallowing `_VDOM` we ensure that values having the `VDOM` type | ||
// are not mistaken for also having `PropList`. | ||
_VDOM?: never | ||
// By disallowing `_VNode` we ensure values having the `VNode` type are | ||
// not mistaken for also having the `Props` type. | ||
_VNode?: never | ||
} | ||
> | ||
// The `class` property represents an HTML class attribute string. | ||
type ClassProp = | ||
| boolean | ||
| string | ||
| undefined | ||
| Record<string, boolean | undefined> | ||
| ClassProp[] | ||
// The `style` property represents inline CSS. This relies on TypeScript's CSS | ||
// property definitions. Custom properties aren't covered as well as any newer | ||
// properties yet to be recognized by TypeScript. The only way to accommodate | ||
// them is to relax the adherence to TypeScript's CSS property definitions. | ||
// It's a poor trade-off given the likelihood of using such properties. | ||
// However, you can use type casting if you want to use them. | ||
type StyleProp = IndexableByKey & { | ||
[K in keyof CSSStyleDeclaration]?: CSSStyleDeclaration[K] | null | ||
} | ||
// The `style` property represents inline CSS. | ||
// | ||
// NOTE: This relies on what TypeScript itself recognizes as valid CSS | ||
// properties. Custom properties are not covered as well as any newer | ||
// properties that are not yet recognized by TypeScript. Apparently, | ||
// the only way to accommodate them is to relax the adherence to | ||
// TypeScript's CSS property definitions. The trade-off doesn't | ||
// seem worth it given the chances of using such properties. | ||
// However, you can use type casting if you want to them. | ||
type StyleProp = IndexableByKey & | ||
{ | ||
[K in keyof CSSStyleDeclaration]?: CSSStyleDeclaration[K] | null | ||
} | ||
// A subscription reacts to external activity. | ||
type Subscription<S, P = any> = readonly [ | ||
subscriber: (dispatch: Dispatch<S>, payload: P) => Unsubscribe, | ||
payload: P | ||
] | ||
// Event handlers are implemented using actions. | ||
type EventActions<S> = { | ||
[K in keyof EventsMap]: | ||
| Action<S, EventsMap[K]> | ||
| [action: Action<S>, payload: any] | ||
// An unsubscribe function cleans up a canceled subscription. | ||
type Unsubscribe = () => void | ||
// A virtual DOM node (a.k.a. VNode) represents an actual DOM element. | ||
type VNode<S> = { | ||
readonly props: Props<S> | ||
readonly children: readonly MaybeVNode<S>[] | ||
node: null | undefined | Node | ||
// Hyperapp takes care of using native Web platform event handlers for us. | ||
events?: | ||
Record< | ||
string, | ||
Action<S> | readonly [action: Action<S>, payload: unknown] | ||
> | ||
// A key can uniquely associate a VNode with a certain DOM element. | ||
readonly key: string | null | undefined | ||
// A VNode's tag is either an element name or a memoized view function. | ||
readonly tag: string | ((data: Indexable) => VNode<S>) | ||
// If the VNode's tag is a function then this data will get passed to it. | ||
memo?: Indexable | ||
// VNode types are based on actual DOM node types: | ||
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType | ||
readonly type: 1 | 3 | ||
// `_VNode` is a phantom guard property which gives us a way to tell `VNode` | ||
// objects apart from `Props` objects. Since we don't expect users to make | ||
// their own VNodes manually, we can take advantage of this trick which | ||
// is unique to TypeScript type definitions for JavaScript code. | ||
_VNode: true | ||
} | ||
// Most event typings are provided by TypeScript itself. | ||
type EventsMap = { | ||
[K in keyof HTMLElementEventMap as `on${K}`]: HTMLElementEventMap[K] | ||
} & | ||
{ [K in keyof WindowEventMap as `on${K}`]: WindowEventMap[K] } & { | ||
onsearch: Event | ||
} | ||
} |
{ | ||
"name": "hyperapp", | ||
"version": "2.0.16", | ||
"version": "2.0.17", | ||
"type": "module", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23439
550