- Special props are now unprefixed. All special prefixed props are deprecated.
- Special props are now passed into components via props.
- The
ref
prop behavior has been changed. For host elements, the callback is fired once when the element is created. For component elements, the callback must be manually passed to one of the component’s children to fire. Theref
callback will have no effect for other elements like<Fragment>
. - The special
static
prop has been renamed tocopy
to avoid collisions with thestatic
keyword. - The
context.value
property, which allows you to access the current rendered value of a component from the context, has been deprecated. - Elements which are reused between renders will skip rendering. This means you have to clone elements between renders if you want them to rerender.
- Component contexts are now passed to components as the second parameter.
- React style camelCased event names (
onChange
,onInput
) are now supported. - Stale renders are skipped with using
for await...of
in async generator components. - Components will now warn when yielding multiple times per props iteration.
- Fix keyed elements disappearing incorrectly, a bug introduced in 0.5.5
- Fix
foreignObject
children having the wrongxmlns
(#268 by (@canadaduane)
- Fix keyed component elements not cleaning up properly #267
- Fix DOM renderer bug where input of
type="text"
does not appear in the DOM, causing surprising CSS styling issues (#258 by @waynebaylor)
- The cleanup() functions will be called even if components are unmounted. #249
- Fixes a situation where component errors in async components were being ignored. #253
- Allow
Context<typeof Component>
context types to be passed components with 0 parameters. - Alias jsx-dev-runtime to jsx-runtime for parcel/other bundlers
- Disable hydration mismatch warnings until we figure out the expected DX for warning suppression.
- Fixed a bug where refreshing hydrated components throws errors.
- The internal
RendererImpl
methodescape()
has been renamed totext()
. - The internal
RendererImpl
methodparse()
has been renamed toraw()
, and the valueprop
is always passed into this method, regardless of whether the value is a string. - Generator components which return will restart when re-rerendered, rather than staying stuck on the returned value. This should help debugging components which have accidentally returned.
- Special props like
crank-key
, have an additional$
-prefixed variant. Going forward, this will be the preferred syntax, butcrank-key
andc-key
will continue to be supported as well.<div $key={key} $ref={ref} $static />
- Generator components which are in a
for...of
orfor await...of
loop will now attempt to exit normally, so that cleanup code can be placed after the loop.// before function Counter() { let i = 0; const interval = setInterval(() => { i++; this.refresh(); }, 1000); try { for ({} of this) { yield <div>{i}</div>; } } finally { clearInterval(interval); } } // after function Counter() { let i = 0; const interval = setInterval(() => { i++; this.refresh(); }, 1000); for ({} of this) { yield <div>{i}</div>; } clearInterval(interval); }
- Async generator components can now use for...of loops. Async generator
components which yield from a for...of loop behave like sync generator
components, pausing at each yield.
async function Counter() { let i = 0; const interval = setInterval(() => { i++; this.refresh(); }, 1000); for ({} of this) { yield <div>{i}</div>; } clearInterval(interval); }
- The
Context
type can now be passed a function type as its first parameter to strongly type thethis
props iterators.function *MyComponent( this: Context<typeof MyComponent>, {name}: {name: string}, ) { // name will be correctly inferred for ({name} of this) { yield <div>Hello name</div>; } }
-
The automatic JSX runtime transform is now supported. Here is the babel configuration.
plugins: [ babelPluginSyntaxJSX, [ babelPluginTransformReactJSX, { runtime: "automatic", importSource: "@b9g/crank", }, ], ],
-
Hydration: The DOM Renderer now provides a
hydrate()
method which will attempt to re-use DOM nodes already found on the page. A correspondinghydrate()
method has been defined for custom renderers. -
Crank now provides a tagged template function called
jsx
which replicates JSX syntax and allows templates to be written with vanilla JavaScript.import {jsx} from "@b9g/crank/standalone"; import {renderer} from "@b9g/crank/standalone"; function Greeting({ name }) { return jsx` <div>Hello ${name}</div> `; } renderer.render(jsx`<${Greeting} name="world" />`, document.body);
-
Calling
dispatchEvent()
on a component context will now trigger anyonevent
style props.
- Errors which are thrown in Context event listener functions will not prevent other listeners from being called.
- Async generator components should run more predictably.
- IFrame/IMG
src
and other props which are sensitive to being re-assigned will not be re-assigned. $static
elements which are re-rendered with different tags will now correctly re-render.
- Inlined event listener methods to avoid errors caused by bundling (#238).
- Fix readonly DOM properties not being set correctly (#231).
- Fix null/undefined in className property for HTML renderer.
createElement
andFragment
have been added to default module exports, to work with more JSX tools (#219).
- The HTMLRenderer will now correctly render
className
props (#221). - Fixed a bug where
<Raw />
elements with parsed string values would lose their contents when rerendered (#224).
- As part of #224, the internal
RendererImpl.parse()
method can now take anyElementValue<TNode>
instead ofTNode
. - The
./
export which was added in 0.4 was removed from package.json. - The
main
andmodule
fields will now point to crank.js.
- Special props
crank-key
,crank-ref
,crank-static
now have shorthand equivalentsc-key
,c-ref
, andc-static
to save on typing. - Crank is now published under the NPM package
@b9g/crank
, as well as the old@bikeshaving/crank
. Again, this saves on typing. - The
Context.prototype.flush()
method has been added. It behaves similarly toContext.prototype.schedule()
, with the exception that it runs after a component’s children is in the DOM. This is important for things like focusing after render. See #180 for motivation. - The
c-skip
(crank-skip
) prop has been added as an alternative to<Copy />
elements. See #173 for motivation andsrc/__tests__/static.tsx
for examples.
- I gave up and we now use
.cjs
files instead of/cjs
directories for commonjs fallbacks. innerHTML
now checks against the old prop value rather than reading from the DOM.- Properties and styles which are missing from DOM element props will now be removed.
Crank 0.3 tried to implement uncontrolled properties by saying missing props were uncontrolled. For instance,
<div class="class" />
rerendered as<div />
would preserve the class property even though it was removed. Starting in 0.4, missing props and styles will be removed from DOM elements between renders. - Crank will now log a console error when
undefined
is yielded or returned from a component. To squash these warnings, yield or returnnull
instead. - The default type for
TagProps
is nowRecord<string, unknown>
as opposed tounknown
. - Crank will no longer attempt to reuse or modify elements. Motivated by #198.
- Internal context properties have been hidden using a symbol.
- The internal Renderer API has been overhauled yet again.
- All internal methods which are implemented by the various renderers (
create()
,patch()
,arrange()
) have been removed from the base renderer class. Instead, you will now have to pass in these methods via a call tosuper()
in the constructor. Seesrc/dom.ts
orsrc/html.ts
for examples. - The
complete()
method has been renamed toflush()
. patch()
now runs per prop as opposed to passing all props.patch()
now runs in a post-order call of the tree (yet again).- The signatures of all of the methods have been changed, mainly to avoid passing elements into the renderer, and allow for previous values to be inspected and used.
- All internal methods which are implemented by the various renderers (
- Fixed some edge cases where event bubbling would result in `"Generator is already executing.
- Assigning to
boolean
properties with strings likespellcheck="true"
will now work as expected. See #175 for motivation. "` errors.
- Crank will now always create new elements for internal nodes to prevent subtle aliasing bugs (#198).
- Fixed an edge case where a scheduled refresh failed to update the component when the produced child was a component (#199).
- Optimized multiple components scheduling a refresh synchronously (#155).
- Fixed Copy elements of async generator components causing parents to hang (#197).
- Fixed style strings being incorrectly rendered by the HTMLRenderer (#191).
- Various performance improvements.
create()
andpatch()
calls have been moved to a pre-order traversal of the tree.- The DOM renderer now checks properties and attributes before mutating them.
Mostly some changes when trying to get Crank to play nicely with contenteditables
- Fixed TypeScript sourcemaps not being generated in builds (#165).
- Fixed empty arrays or otherwise non-empty element children not clearing out non-Crank DOM mutations (#167).
- Fixed rerenderings updating DOM Text nodes even when the contents have not changed (#169).
- Changed the algorithm of patch slightly so that
setAttribute
is never used with object/function values.
- Added ChildIterable type to exports to deal with TypeScript errors (#156).
- Fix some edge cases with async generator component rendering.
- Use ducktyping rather than instanceof checks for cross realm use-cases like nw.js (#147).
- Duplicate keys and calling refresh on an unmounted or already executing component will now log errors to the console.
- Changes to some of the error messages thrown by Crank.
- Added official support for Deno. ESM build files now include a triple-slash reference to sibling d.ts files, and the d.ts files have been checked to work in deno.
- The core file has been moved from
index.js
tocrank.js
, following deno best practices. Theindex.js
export is now an alias file. - Module Augmentation is now available via a global
Crank
module.
- The class
StringRenderer
in the html module has been renamed toHTMLRenderer
. TheStringRenderer
export is now an alias and will be removed in the next breaking release.
- The context methods
get
andset
are now namedprovide
andconsume
. - Changes to the internal renderer APIs in preparation for initial documentation.
- Elements are passed in directly, rather than their tag and props.
- The scope is now no longer passed to the patch method.
- Fixed errors not propagating from function component children.
- The context async iterator now suspends at its start if you yield before iterating over it (#137).
- Fixed overloads of Context.prototype.set and Context.prototype.get not appearing in the d.ts file.
- Props are no longer rememebered between renders. For instance, rendering
<input checked />
and then<input />
will not cause the checked prop to be deleted on the actual element. - The internal Renderer API has been changed to use inheritance and away from the intrinsic generator API.
Renderer.prototype.render
andContext.prototype.refresh
now return rendered values rather than undefined.- The library is no longer transpiled.
- The esm directory in the package has been deleted. Refer to index, dom and html in the root of the package instead.
- Some types have been simplified
- Tag no longer takes a type parameter.
- The types
Props
,FunctionComponent
,GeneratorComponent
,IntrinsicProps
,ChildIterator
,ChildGenerator
andKey
have been removed from the public API.
- UMD build.
crank-ref
props.Context.prototype.schedule
.Context.prototype.cleanup
.Context.prototype.props
.Context.prototype.value
.dispatchEvent
now does bubbling and capturing correctly.
- Performance improvements in terms of execution time, runtime memory costs, and library size.
- Fixed
Context.prototype.dispatchEvent
not responding tostopPropagation
andstopImmediatePropagation
. - Fixed nested SVG elements not rendering SVGElements in some cases.
- Improved error handling.
- Backed out of a performance optimization where async generator components caused siblings to remain in the DOM.
- Fixed SVG attributes causing readonly errors (#119).
- Added support for SVG elements in the DOM renderer (#110).
- basic performance improvements, you want to upgrade to at least 0.1.4 and probably 0.2 when it is released
- Got rid of the
HostContext
class in favor of exposing the HostNode directly to intrinsics. - Added a way to pass information in a preorder traversal to child host nodes (search for Scoper/Scopes in the codebase).
- Added new flags for intrinsics to optimize performance (search for dirty in the codebase).
- Made
event-target-shim
a direct dependency so TypeScript doesn’t error (#95).
- Updated the types of
Component
andContext
to take explicit prop types (#51). - Allow createElement to be passed anything as
Children
(#97). - Allow arbitrary elements to be passed to
Renderer.prototype.render
(#97).
- Fixed
Copy
element tag not usingSymbol.for
(#69). - Fixed event listeners not being properly removed when component is unmounted (#70).
- Prevented child components from causing parent components to rerender while it is already rerendering (#70).
- Fixed keyed element logic when an unkeyed element is placed before multiple keyed elements previously rendered.
- Fixed a deadlock when errors are thrown back into async generator components (#77).
- Corrected boolean props not working correctly in html renderer (#44).
- Guarded against potential xss in style objects (#44).
- Wrapped non-string iterables in an implicit Fragment element (#63).
- Made sure stateless renders are unmounted (#63).
- Initial release 🎉