- Simplified @typedef declarations.
- Updated updateView function to use AND/OR expressions instead of ternary operators.
- Updated Eslint rules to include modern JavaScript features like const and destructuring.
- Updated to use more const and destructuring.
- Renamed to
jsx.d.ts
.
- Amalgamated all types into a single file. Use import and namespaced batch imports of types in source files.
- Update TypeScript to version 3.7.3. This added new capabilities for type support, enabling batch imports mentioned above, as well as automatic generation of
d.ts
files from JavaScript using JSDoc comments.
types: constants.d.ts, effects.d.ts, fragment.d.ts, h.d.ts, index.d.ts, render.d.ts, runtime.d.ts, types.d.ts, union.d.ts, vdom.d.ts, vnode.d.ts
- These are all auto-generated when running build script.
-
Replaced some
if/else
statements with logical expressions where possible. -
Refactored some functions in vdom into arrow functions for simplicity.
- Used logical expressions to remove
if/else
blocks for cleaner and easier to read code.
- Use destructuring to simplify union message management.
-
Updated behavior of send function. Now you can pass a destructured tag union function without inoviking it. You can also provide an optional second parameter as a data payload.
-
In the example below, notice how we just send
AddItem
, whereas withUpdateInputValue
we provide a second argument for the data:
const Msg = union('UpdateInputValue', 'AddItem')
const {UpdateInputValue, AddItem} = Msg
function List({state, send}) {
return (
<div>
<input oninput={e => send(UpdateInputValue, e.target.value)} type='text'/>
<button onclick={() => send(AddItem)}>Add Item</button>
</div>
)
}
- Added error checking for when user tries to use "match" as a method. The union function produces and object that always has a match method, so trying to create a tagged union that can handle a "match" message can be problematic. The developer will now get a console error message warning not to create a union with type "match".
- Added
.pretterignore
to control what files Prettier formats.
- Add Prettier config options to
package.json
.
-
Added error checking to union match method. Now if the message type sent does not match the provided action methods, it will log an error.
-
Added catchAll for message union match method as an optional third argument. This overrides the default error handling mentioned above. You can use this to handle a default case when the message sent does not match any of the methods provided. You could use this to provide a default action to perform or to log an error:
Msg.match(
msg,
{
DoIt: () => {
return prevState
}
},
// Handle case where message doesn't match:
() => {
console.error(`You sent the message "${msg.type}", but it does not have a match in the actions provided.`)
prevState.errorMessage = `You sent the message "${msg.type}", but it does not have a match in the actions provided.`
return prevState
}
)
// Send wrong message:
send({type: 'EatPizza'})
// Will result in above message being logged to console:
// You sent the message "EatPizza", but it does not have a match in the actions provided.
## 2.6.1 (November 18, 2019)
### index.d.ts
* Updated IntrinsicAttributes interface to have property `children` of type `Children` (child vnodes) as the final argument for a JSX functional component. This enables function components to allow accepting a final arguemnt of `children`, which provides a slot for insertion of random child content into the component using open and close tags around the child:
```javascript
function Title({ title }, children) {
return (
<header>
<h1>Hello, {title}!</h1>
{
children
}
</header>
)
}
<Title title="World"><h2>Extra Text</h2></Title>
- Changed return type of
batch
fromany
tovoid
.
- Switch around parameters for subscriptions. The new order is
subscriptions: (send, getState)
.getState
is now optional.getState
is used so rarely with subscriptions it was annoying always having to provide it as the first argument. Now you can have a subscript with just the argumentsend
:
function effect(send) {
// code here...
}
- Made both
send
andgetState
as optional arguments for subscriptions since it is possible to have a subscription that does not access state or send a message.
- Updaed tests for runtime to accomodate change in how subscriptions handle parameters.
function effect(send) {
/...
}
- Refactored h function to return VNode by default. Previously the defaul was wrapped in a conditional check.
-
Broke out match function from createUnion function and gave it proper types.
-
Provide overall type coverage for tags and tagged union result.
- In
createNode
function got rid of need for type coercion by convertingnode.type
to string first.
- Added
@babel/preset-modules
as build dependency. This tells Babel to only target browsers that support importing es modules. This results in a smaller bundle size, knocking of up to 250 bytes by eliminating unnecessary polyfills.
- Modified
.babelrc
to use@babel/preset-modules
as plugin instead of@babel/preset-env
. This results in smaller bundle sizes for modern browser that support es modules.
- Provided short form for
batchEffects
asbatch
. Less typing same thing. The longer form ofbatchEffects
is still available and works for backwards compatibility.
- Removed automatic lower casing of inline events. This is so users can use DOM level 3 custom events with camel case names. We lower cased the inline events to make it easier for people use to React events to use. But since the default inline events are lower case, we are dropping this for DOM level 3 support.
- Exported Props type.
- Improved types for onmount, onupdate and onunmount.
- Updated type exports to include GetState.
- Added index.d.ts to src so that it gets imported automatically by Editors for type information. This is paricularlly to expose JSX types for functional components, as well as the types of @composi/core.
- Updated for better type handling.
- Added function
areNotEqual
which is used to check if the old props and new props of a VNode are identical. If they are not identical thenonupdate
executes, otherwise not.
- Added tsconfig to simplify NPM script
checkjs
. No it is just"checkjs": "tsc"
- Modified definition of VNode to optionally be an empty object literal. This was necessary for properly typing or
h
. This change enablesh
working properly with theJSX d.ts
file provided by the@composi/create-composi-app
forJSX
Intellisense in Composi projects.
- Improved types for both effects.js and union.js.
- Removed
jsconfig.json
and replaced withtsconfig.json
. The tsconfig has type check options. This removes need for NPM script testcheckjs
to use options, simplifying it to just"checkjs": "tsc"
.
- Fixed issue where type for send required a parameter when in fact it is optional. Yes, you can just send an empty message, but then your update can only handle that one case. Works for very simple programs.
- Added tsconfig.json file. This simplified the NPM checkjs script to just 'tsc'.
- Added settings.json file for VSCode to set up live type linting for source code.
- Improved internal types for runtime.js, vdom.js and vnode.js
- Simplified union code and removed unused feature for default behavior. This was never used or useful for anything.
- Added error handling for when message does not have expected structure.
- Removed unnecessary dependency on @composi/merge-objects.
- Updated how the runtime works. Now
init
does not require brackets for state. Just return the state you want to use. Same foractions
--just return the new state. This means that you can no longer execute an optional effect in theinit
method to run at startup. If you want to execute an effect at startup, use thesubscriptions
method. That's what it's for. Similarly, you can no longer return an effect with state in an action. Instead send a message for another action before returning state.
- Updated runtime test to handle changes to how state get returned now.
- Fixed so when render mount function component with onmount hook on existing element, the onmount hook fires.
- Made sure that read-only properties like
list
,form
, etc. are rendered as attributes.
- Fixed tests to hanlde new vdom patching method.
-
Refactored virtual DOM for speed improvement. The new approach now directly hydrates and element in the DOM. Previously it required a container into which it appended the rendered functional component. This meant only one component could exist in a container. Now rendering is executed directly on the provided element. This means multiple components can be rendered in the same container as long as each has its own stub to use.
-
Improved diffing for faster renders.
- Due to changes in the virtual DOM, the render function now only takes two arguemnts, the component to render and an element to hydrate or update.
- The
hydrate
function was removed since hydration is now automatic when therender
function is called the first time.
- Dropped the hydrate and removeWhiteSpaceNodes function and updated both createVNode and v for changes in vdom parsing.
- Updated runtime tests to handle latest version of subscriptions properly.
- Made improvements to JSDocs comments for better Intellisense for
h
,union
and runtime types.
- Made types State, Message and Send importable by projects.
- Cleaned up type export.
- Make types State, Message and Send importable by projects. Cleaned up type export.
- Made type
Program
defined insrc/runtime.js
available to importing in projects like this:
/**
* @type {import('@composi/core').Program}
*/
const program = {
init() {},
view(state, send) {},
update(state, msg, send) {}
}
-
Cleaned up how subscriptions are initialized.
-
Refactored types for runtime program for better Intellisense and type coverage.
- Added import of
createVNode
fromvnode.js
toindex.js
, even though it isn't being exported. This is to get around a bud in TypeScript parser that fails to get types imported with@typedef {import('./vnode').VNode} VNode
format. The indirection of theindex.js
file causes TypeScript to cast JSDoc type imports asany
. Importingvnode.js
here makes its types avaiabale to TypeScript so that when it find the type imports in other files, it knows what they are. This then provides complete type safety forh
andrender
functions.
- Fixed typo in comment.
- Added back in build for UMD package. This is needed for use in only JavaScript editors like Codepen, JSBin, etc.n
- Updated to use the latest version of @composi/mergeObjects
- This version now properly clones Sets and Maps, as well as merges them together. Of course, you can only merge Sets or Maps. You cannnot merge these with other object types.
- Bumped version for publishing purposes.
- Removed UMD build
- Switched from using UMD bundle to load Composi for tests to using ES 6 module syntax.
- Updated version of merge-objects dependency due to security vulnerability.
- Added UMB build back in because Mocha tests need it!
- Set initial value for
isFirstRun
to true for first run instead of false since technically it will always be the frist run initially.
- Removed unnecessary UMD bundle from build.
- Switched around properties of program JSDoc type comments to match actual usage. (They were out of order.)
- Simplified
childNodes
assignment. - Removed unnecessary parameter in
createVNode
call. createVNode
now has default values ofnull
forkey
andflag
parameters.
- Updated tests to reflect changes in
h.js
.
- Improved old and new VNode comparison in
patch
so thatonupdate
lifecycle hook only fires when the props have changed.
- Instead of assigning default value to
createVNode
function inside its body, moved assignment as default value in the call signature itself. - Marked flag parameter as optional.
- Added delay for render test that needed a longer delay before accessing the updated DOM.
- Updated merge-objects dependency version.
- Now taking the VNode passed as an argument to the render function and clone it to save on the component container element as the value of property
previousVNode
.
- Now the
patchElement
function checks the newpreviousVNode
property on the parent element to see if the new VNode is identical to the older vision. If they are it exits the patch immediately. Previously, the diff was checking a plain VNode against one which resulted from patching. Problem was, patching made the saved VNode always have DOM values for element, where as a fresh VNode has elements with a value of null. UsingpreviousVNode
allows the diff to check the resulting new VNode with the previous version before patching adds elements. This allows for quick exiting from the diff if there are no differences.
The save VNode in the vnode
property of the continer is still used for patching, since it holds the last DOM render information.
- Renamed variables for clarifying their identities better.
- lastChildren = oldVNodeChildren
- lastChildStart = oldVNodeChildStart
- lastChildEnd = oldVNodeChildEnd
- nextChildren = newVNodeChildren
- nextChildStart = newVNodeChildStart
- nextChildEnd = newVNodeChildEnd
- Created a function
getState
that gets exposed to subscriptions. This allows subscription to access the current state of a program. Previously subscriptions got passed a reference to state as their first argument. However, this was state as it was at the time the program started. Subscriptions had no way to know the current state of a program at any given time. Providing subscriptions withgetState
solves this problem. Now an action can change a value in state and a subscription can check for a change in that value in a loop, after which the subscription can do something, such as canceling a loop, etc. getState
is now the first argument of a subscription, followed bysend
:
const program = {
init() {
return [state]
}
subscriptions(getState, send) {
return effect
}
}
function effect(getState, send) {
// Access state from the program:
const currentState = getState()
// Do something with currentState...
}
-
Using
getState
also lets you store any references to a setInterval, web sockets or services that you implement in subscriptions and want to affect from an action. You can expose them on the program's state so you can access them from other actions. -
Never use this to directly change a program's state. Instead send the data as the value of a message for an action to handle.
- Refactored
updateElement
function to handleonmount
andonupdate
separately. Previously both were getting passed the same parameters:element
,oldProps
andnewProps
. Passing props as arguments foronmount
makes no sense. Added a conditional soonmount
only gets passed a reference to the mounted element.onupdate
still getselement
,oldProps
andnewProps
.
- Updated runtime test to use the new
getState
function in subscriptions.
- Fixed erroneous urls. These were pointing to older version of Composi in a different Github group. Now they point to the correct repository.
- Switched parameters around for unmount lifecycle hook. The correct order is function(element, done). This makes unmount feel more inline with onmount and onupdate, which get the element as the first argument.
- Updated onmount lifecycle test for changes to onunmount parameter order.
- Updated README to document changes to onunmount parameter order.
- Documented new union function call signature.
- Changed batchEffects argument to not require enclosing effects in array. Use of spread operator means just passing in effects separated by commas:
const batchedEffects = batchEffects(effect1, effect2, effect3)
- Same thing when batching subscriptions:
const batchedSupcriptions = batchEffects(sub1, sub2, sub3)
- Changed union argument to not require enclosing message names in array. Use of spread operator means just passing in messages separated by commas:
const Msg = union('updateInputValue', 'addItem', 'deleteItem')
.
- Added back in empty block conditional check for comparing oldVNode and newVNode in patchElement function. This helps prevent certain edge cases where a vnode might be undefined, particularly when dealing with creating new text nodes.
- Moved function
removeWhiteSpaceNodes
beforehydrate
function to avoid need for hoisting.
- Updated tests to use new arrayless arguments for union and batchEffects functions.
- Added in read-only attributes to setProp function to set this is properties instead of attributes.
- Updated render tests to check read-only attributes being set.
- Renamed node variable to vnode in removeChildren function, since that’s what it is.
- Hydrate gets used internally by the render function when a third argument for the element to hydrate is provided, so no need to expose it.
- Updated render test to reflect this change.
- Removed empty check for oldVNode and newVNode equality and instead added check for their inequality at end.
- Removed unnecessary, unused dependency: @composi/get-type.
- Removed unused mapEffects function. Was never used by anything, so time to go.
- Added check in hydration to see if container has a ‘vnode’ property. If it does, we know this has already been hydrated and use it. Otherwise we hydrate the element. This prevents unnecessarily re-hydrating a component by mistake.
- updateElement function now also checks for ‘selected’ value for updating properties.
- Rolled functionality of ‘vnodeFromChild’ directly into hydrate function. No need for separate function.
- Previously a vnode element property could be null or undefined. They are now always null by default.
- Added new function: removeWhiteSpaceNodes. This is used during hydration to remove whitespace nodes before creating a virtual node. That way, if the server-rendered node is the same as the client-rendered vnode, they should match, reducing patch work.
- Updated h test for vnode changes.
- Use TEXT_NODE for nodeValue of 3.
- Update to use latest version of @composi/merge-objects 1.2.3.
- Updated version of merge-objects dependency to 1.2.2.
- batchEffects was not passing state and send to effects.
- This batched subscriptions in particular were not getting access to state and send properly because of flaw in batchEffects.
- batchEffects now exposes state and send to its effects.
- Updated runtime tests to use new exposed state and send parameters in effects.
- Enabled effects to have access to program state.
- Exposed send function to effects.
- Gave subscriptions access to state.
- Exposed send function to subscriptions.
- Added tests for changes to effects and subscriptions.
- Previous Fragment was a separate package. Now it is part of Composi core.
- Updated Fragment to handle a single argument of an array of nodes.
- Fragment being exported as part of composi/core
- Added tests for Fragment.
- Removed unnecessry prop type checks from setProp function.
- Simplified check for null or false in props to detemine when to remove attribute in setProp function.
- Removed unnecessary isRecycled check from updateElement function.
- Removed check for RECYCLED_NODE from patchElement function.
- Fixed bug affecting subscriptions in runtime programs. 1. The send function wasn't getting passed to batched effects when used as subscriptions. Fixed.
- Added test for batched subscriptions.
- Version bump for changes to how lifecycle hooks are implemented.
- Minor edits to README.
- Created a constant named LIFECYCLE. This is for holding lifecycle hooks.
- Refactored all methods to use the new constant LIFECYCLE.
- Text formatting clean up.
- Added param type VNode for render function.
- Style prop should accept either an object of properties and values or a string of normal CSS to define component styles.
- Cleanup of union function code.
- Added gzip for ES6 module version (mjs).
- Fixed runtime test that needed longer delay to finalize result for assertion.
- Mention in JSDoc comment that hydrate creates a virtual node from a DOM element.
- Updated license date.
- When the program subscriptions method was empty, encluding it caused throws during runtime in browser because there is no subscription to invoke.
- Resolved this by checking that the program includes a subscription and also returns an effect to execute.
- Bumped dependency versions.
- Subscriptions now get state and send passed to them automatically, just like view. This lets you access state from a subscription, and send a message to an effect when necessary.
- Updated runtime tests to subscription changes.
- Fixed typo in JSDoc comment.
- subscriptions were being re-executed every time there was a state change. They should only run during program startup. Fixed.
- Clarification in JSDoc comment about subscriptions as method of runtime program.
- Added shortcut
subs
for subscriptions. Less typing, less likely to misspell.
- Added test for use of subs for subscriptions.
- Isolated subscription execution to avoid overwritting effects from update.
- Updated runtime test for addition of subscriptions.
- Added Subscriptions API. Subscriptions provide way to run effects when a runtime program first starts.
- Update signature now takes state first, then message.
- Updated runtime tests to reflect API changes.
- Updated README for new signature for update function.
- Removed dist version to avoid conflicts when merging V1 branch.
- Latest build.
- Added Subscriptions API.
- The subscriptions method is for setting up effects that run during the program start. These are the same as running an effect as the second value of the array returned by init. However, subscriptions does the same thing in a more explicit way. Easier for people to understand how to implement startup subscriptions when the name is subscriptions.
- Updated order for parameters in update function.
- Updated tests for update function parameter order changes.
- Documented changes to update function parameter order.
- update funtion parameter order is reversed. Changes match init and view parameter order where state is the first value, followed by effect, send or message.
- update function parameter order reversed so that state comes first.
** Bumped version or npm-run to avoid security vulnerability.
- Renamed private variable from
cont
tocontainer
for understability.
- Fixed menu typo.
- Simplified code for tagged unions.
- Added more detail for JSDoc comments.
- Added mjs version for use in browsers.
- Added information about how to use mjs module version in the browser.
- Exposing "send" as program static function of program allows sending message to program update method from other contexts. This was introduced to facilitate easier integration with @composi/router. Now in a router action you can send a message to the program to affect state which the program update actions can deal with for rendering the proper subview for the route.
- Added test for static version of send function.
- Updated to latest version of prettier.
- batchEffects was sometimes failing when an argument was falsy. Fixed.
- Fixed bad links.
- Simplified mapEffect function by using arrow function.
- Renamed mapEffects.js to effect.js
- Updated import of renamed effects.js functions.
- Added new function: batchEffects. This allows you to batch effects together. When they are executed in the order they are batched.
- Added test for batched effects.
- Reverted order change in updateView function that introduced bug.
- Checked in dist versions that got missed in previous checkin.
- Refactor of updateView function.
- Tests require that hydrate be exported!
- Simplified how run function returns.
- No need to export hydrate function.
- Refactored to use while loop instead of for.
- Refactored to use while loop instead of for.
- Use arrow function to return union.
- Renamed private variable from change to updateView.
- Removed this file - giblet.
- Added error checking for when user provides invalid container for render function.
- Composi will now log an error and bail when an invalid container argument is used with the render function. Will output an error message detailing the reason for failure to render, along with the selector used.
- Fixed bug in runtime test.
- Refactored runtime so init method can be a NOOP.
- Normally program.init needs to return an array. But now you can make a default program with noop methods:
const program = {
init() {},
view() {},
update() {}
}
- Update test for null init return value.
- Updated how the run function handles state.
- Previously a program's init was just an array assignment. Now its a function that returns a tuple of state and effect: init() { return [state, effect]}
- Updated init tests for changes to how it returns state.
- Updated to include changes to how init returns state.
- Fixed onupdate bug. onupdate was not getting passed the previous props. Fixed.
- README edit.
- Checkin dist build. Was missed in last checkin.
- Modified return of state by update actions to enable immutable data. Previously an action just returned state to the view. Now when you return state, it also reassigns it to the program's state. This lets you clone the state inside the action, make changes and then return it. In so doing you update the program state and the view.
- Update dependency on @composi/merge-objects to latest version.
- Fixed issue for SVG image rendering. Needed to restore empty block in h function.
- Checked in dist build, left out in last checkin.
- Fixed returning null for component bug. patch function was trying to attach element to vnode even when the vnode was null. Fixed by checking if element exists first.
- Added export of mapEffects.
- Add runtime for creating encapsulated programs with state management.
- Added new file. This exposes run function. This creates a runtime for a program. This provides a Redux-style state manager for functional components.
- A runtime program has four parts:
- Init: holds state and runs effects at startup.
- update: handles actions for modifying application state.
- view: creates representation of state.
- done: method to cleanup environment before program stops.
- Added new file.
- mapEffect makes it easy to share an effect between a parent program and a child program for inter-program communication.
- Added new file.
- The function “union” creates tagged unions. These are used to simplify invoking update actions from the view and handling them in the program’s update method.
- Added new file. Includes tests for new runtime environment for program state management.
- No empty blocks.
- General clean up. Set Eslint to allow reassignment of parameters, enabling elimination of a bunch of variables.
- Refactored virtual DOM functions, fixing some erroneous flag uses.
- Minor code cleanup and variable renaming.
- Switched to using Reflect.get to get properites from objects. Reflect doesn't throw if the property doesn't exist.
- Simplified render function.
- Added hydrateThis as type parameter in JSDoc comments.
- Fixed lifecycle tests that were failing.
- Refactored patch algorithm for simplicity.
render
now takes two arguments, the component and its container.- No need for mount,
render
mounts and updates the component. - Removed separate
unmount
function. Was not useful and was too problematic. Instead use boolean logic to manage when a component renders. render
function now caches the last rendered vnode on the component’s container. Each time you render a component, it checks the container for the cache and uses that to patch the DOM efficiently.- Only one component can be rendered in a container, but you can make a parent wrapper to compose many components to render them all in one container.
- To hydrate a server-rendered element, pass its DOM reference or string selector as the third argument for
render
. - Updated tests for all changes.
- Deleted file as no longer necessary. See above changes to API.
- Refactored code to fix eslint error about parameter reassignment.
- Previously the patch algo returned a vnode which you had to capture and return to the next render.
- Now patch returns the element base of the component. As such, you capture on the first render only. After that, just render.
- You do need to pass the component element as the thrid parameter during re-renders, but no re-capture any more.
- Changes to patch required updates to render, unmount, hydrate, removeElement and updateElement.
- Updated tests for changes.
- Fixed error in JSDoc coment for setProp function.
- Updated @composi get-type and merge-objects to latest versions.
- Updated eslint rules.
- Updated source code to resolve Eslint errors.
- Updated @composi/merge-objects to version 1.0.6 to resolve issues with merge bugs.
- Bumped version for publishing to NPM.
- Added publishConfig for publishing to NPM.
- Updted to use latest version of @composi/merge-objects.
- Made @composi/get-type and @composi/merge-objects as dependencies.
- Added error catching for attempt to render array of elements into DOM.
- Updated render test for array error.
- Props in h function should be optional.
- Rollup now creating minified dist version.
- Updated package name for scoped NPM package.
- Fixed typo in README.
- Converted Composi into scoped packages. @composi/core encompasses the virtual DOM and functional components.
- constants.js are values used by @composi/core.
- h.js provides hypersrcipt function for defining virtual nodes.
- vnode.js provides functions to create virtual element nodes and virtual text nodes.
- vdom.js provides virtual DOM for diffing and patching the DOM.
- render.js provides function to mount function components in the DOM and update them in place.
- unmount.js provides function to remove a mounted component form the DOM.
- Included mocha/chai tests for h, render, lifecycle hooks and unmount.