Skip to content

Instantly share code, notes, and snippets.

@Swatinem
Last active September 21, 2015 22:58
Show Gist options
  • Save Swatinem/e0c0fa51a45dca2e84d9 to your computer and use it in GitHub Desktop.
Save Swatinem/e0c0fa51a45dca2e84d9 to your computer and use it in GitHub Desktop.
yet some more dom ideas
// The data structure of your favorite data structure libary.
// Might just be a plain JS Object. Keys are guaranteed to be Strings
DataMap = Any
// The library should be agnostic to what kind of data library is used,
// therefore every kind of data access should go through this interface
Data = {
// Creates a new Map, optionally with an initial JS object provided
create: (Object?) => DataMap,
// Used to retrieve a key, for example from the `Context`.
get: (key, DataMap) => Any,
// Merge a set of `DataMap` into a single one, right-ones override left-ones.
merge: (...DataMap) => DataMap,
// A straight forward equality function
equals: (DataMap, DataMap) => Boolean,
}
// Props are owned and passed down from the parent, they are immutable from inside
Props = DataMap
// State is internal to a `Component` and not observable from the outside
State = DataMap
// global helpers that will be merged into `Context`
Globals = DataMap
// The `render` function will receive the above objects merged.
Context = Globals + Props + State
SetStateFn = (State) => undefined
ElementRequest = First | Last | All
Driver = {
// see above
Data: Data,
ElementRequest: ElementRequest,
// Instance Management:
// Components should not create children directly, but use the `Driver` instead.
// The driver can do more optimizations like reusing previous instances and such.
create: (Class, Props) => Component,
// Components should call this to update a child `Component` with new `Props`.
update: (Component, Props) => undefined,
// This will recycle the instance so that the driver can reuse it.
reuse: (Component) => undefined,
// DOM Manipulation:
insert: (Component, parent: Element, before?: Element) => undefined,
remove: (Component) => undefined,
// Just a convenience method that does `beforeUnmount`, `remove` and `reuse`
unmount: (Component) => undefined,
// Lifecycle hooks:
// These should be called through the `Driver` instead of directly on
// children. The `Driver` can use a default implementation when none is
// provided by the `Class`.
afterMount: (Component) => undefined,
beforeUnmount: (Component) => undefined,
}
// A concrete instance
Component = {
// public for use by the parent or when monkeypatching, will be set by the Driver
klass: Class,
// public: the `Driver` needs access to this in the defaulted
// implementations of `afterMount` and `beforeUnmount`
children: [Component],
// public for use when monkeypatching
refs: {key: Element}, // references to certain elements that should be exposed
}
// This is the API Contract for Components, they are just a set of pure functions.
// These will be used by either the driver or parent components, hereafter just called `parent`.
Class = {
// will be used in debugging later
name: String,
// Essential methods:
// Component and DOM Management:
// will be called by the parent to create a new `Component`.
create: (Driver) => Component,
// will be called by the parent to render the `Component` with the provided `Context`.
render: (Component, Context) => undefined,
// will be called by the parent when mounting, reordering or unmounting the `Component`.
// see ElementRequest above for the cases
getElements: (Component, ElementRequest) => [Element],
// Optional methods:
// Context Management:
// will be called when creating the inital `State` for a `Component`
init: (Data, Props, SetStateFn) => State,
// when a new set of Props is set by the parent
update: (Data, Props, SetStateFn) => State,
// Lifecycle hooks:
// will be called by the parent after the `Component` has been mounted into the DOM
afterMount: (Component, SetStateFn) => undefined,
// will be called by the parent before the `Component` will be unmounted
beforeUnmount: (Component) => undefined,
}
DriverPublic = {
// public
update: (Props) => undefined,
unmount: () => undefined,
}
Options = {
// the Data implementation to be used by all the children
Data?: Data,
// a global Map that all Components will have access to
globals?: DataMap,
}
start = (Options, Class, Props, parent: Element, before?: Element) => DriverPublic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment