All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Update valueBinding() to automatically parse the passed model value to String
Highlights of breaking changes from the log further down:
To avoid child component props to clash with DOM bindings when using a reserved binding name
the new $element
namespace was created. Inside you'll have access to the ref component element bindings,
and outside the component props are available.
setup({ refs }) {
return [
bind(refs.child, {
// component prop
style: computed(() => 'some-value'),
// element bindings
$element: {
style: computed(() => { 'font-weight': 400 }),
}
}),
];
},
If you have a component that is accessing the child component's element bindings, you'll need to move those bindings inside the $element
namespace
New and exciting additions from the log further down:
If you need to extract a value not supported by the other source types you can use the new custom
source
defineComponent({
name: 'my-component',
refs: { title: 'title' },
props: {
// grab the length of the title component.
// outputs "32" (as a number)
characterCount: propType.number.source({
target: 'title',
type: 'custom',
options: {
// function used for extracting the value
customSource: (element: HTMLElement | Array<HTMLElement> | undefined) =>
(element as HTMLElement)!.innerHTML.length;
}
})
},
})
<div data-component="my-component">
<h1 data-ref="title">This title is 32 characters long</h1>
</div>
See the docs for propType source for more details.
For extraction of initial input values you can use the new form
source
defineComponent({
name: 'my-component',
refs: {
email: 'email',
},
props: {
// get the value from the email ref
// outputs "[email protected]"
email: propType.string.source(
{ target: 'email', type: 'form'},
),
},
})
<div data-component="my-component">
<input type="text" data-ref="email" value="[email protected]"/>
</div>
See the docs for propType source for more details.
- Add
event
binding to refComponents - Add the
'custom'
propType.source
for user-defined extraction functions - Add
form
source, allowing you to easily extract initial values from forms or inputs
- Change style binding types to support
null
andundefined
values - Namespace
$element
bindings on component refs
- Fixed Jest compatibility by renaming the
global
const.
- Fixed importing of non-exported files by also exporting types in
dist/esm
folder.
- Fixed bug from
alpha.31
where component props would be typed asRef
in bindings.
Highlights of breaking changes from the log further down:
In order to use components as lazy
, they had to be exported with the supportLazy
helper. This is
not needed anymore. The lazy
function now determines the export based on the displayName
(1st
parameter), which should match the export based on convention. If you follow this convention for
your components, you don't have to change anything.
If you had a webpackExports: lazy
comment in your import
statement (as was previously
recommended in the docs and examples), this can be removed.
If your component export doesn't match the convention, you can provide the exportName
(3rd
parameter).
See the docs for lazy for more details.
Previously you could pass non-reactive values to component prop
bindings
. While this technically
works, this is often not intended, and results in the unexpected behaviour of the component not
receiving updated values. This change requires all bindings to component props to be reactive.
Even though this is technically a breaking change, any cases that will give an error after upgrading to this version, were probably mistakes in your existing code.
If you do have a need for static values in your bindings, you should now wrap them in a computed
.
Two-way bindings sync up the state between the component and the HTML. If the initial state of the
two match up, there is nothing to do here. But if the initial state is different (e.g. a ref
has
true
, but html has false
), the binding code doesn't know what to do.
By default, it still picks the HTML as the initial source, but a warning is logged that they were
not equal. To change this behaviour, or get rid of the warning, you can explicitly provide the
source by setting the initialValueSource
binding config to either html
or binding
.
See the docs for bindings for more details.
Previously it was possible to abuse the props
objects that is passed in the setup
function as
internal component state. While this can work for extracted props, for the ones passed from parent
components this could result in conflicts.
Since the data flow should be predictable, props should only flow from source (html or parent) to
target (child), and should be immutable. This is why this object is now readonly
. Both at runtime
(will log an error) and in the type system.
If your code relies on this current behaviour, you should copy this state to an internal ref
, and
use that to read and write the value instead.
The biggest change here is that the data
and template
properties are now merged into a single
onUpdate
function, that acts as a watchEffect
. All usages of bindTemplate
have to be updated.
Previously:
bindTemplate(
refs.container,
() => someData.value,
(data) => data.map(renderTemplate),
);
Now:
bindTemplate(refs.container, () => someData.value.map(renderTemplate));
Read the docs on bindTemplate to
understand when the optional onlyWach
parameter from onUpdate
can be used to improve performance
in advanced use cases.
Additionally, the renderImmediate
option has been changed to forceImmediateRender
to indicate
the new behaviour. Previously you would have to be explicit about when the bindTemplate
should
render immediately or not, while the new implementation does this based on the existence of any HTML
inside the container. forceImmediateRender
can override this behaviour.
Note: Previously,
watch
was used to watch for explicit changes to the passed computed. This would have been "shallow" by default, and other reactive data used in the template function would not trigger a rerender.The new implementation uses
watchEffect
, which is triggered by any reactive updates in theonUpdate
function, but also watches refs that have nested objects deeply by default.To only update changes to the
ref.value
, ashallowRef
can be used instead.
- Allow the
.source()
option of thepropType.
helper to receive an array of source configurations. The first hit will be used. - Add support for multiple components in
refComponents
– same as already was possible inrefComponent
- Proxy
watch
/watchEffect
to allow auto-cleanup on component unmount – no need to clean these up yourself anymore. - Allow typing refs as
SVGElement
- Fix usage of the
css
"string" binding. - Fix usage of multiple classes as key for the
css
"object" binding. - Fix issues with two-way input
bindings
. - Allow DOM
bindings
on components withoutprops
- Fix issue with
queryRef
where a nested element would be found and ignored
- Simplify usage of
lazy
components. - Only allow passing reactive values to component
props
inbindings
. - When two-way input
bindings
don't match between the html and the initial binding value, theinitialValueSource
binding config should be added to specify which source should be used. - Make the
props
object parameter in thesetup
functionreadonly
. - Improve control over
bindTemplate
rendering. - Update
@vue/reactivity
and@vue/runtime-core
to3.2.31
- The
supportLazy
is a no-op function, thelazy
export is not used anymore
- Improve bundle size by switching some external libraries, or replace them by internal utils.
- Update internal repo structure into multiple projects folders for specific test cases
Deprecated
- Don't set refs to undefined in component or element ref collections that stay in the DOM.
- Add
propType.any
- Fix
propType.object.defaultValue
to allow receiving function value
- Don't re-create ref components when previously created globally
- Fix
attr
source conversion - Improve
bindMap
and other bindings afterbindTemplate
updates - Fix some internal typing issues that were causing build error
- Check current HTML value before setting innerHTML
- Improve performance with global MutationObserver
- Upgrade
vue/reactivity
andvue/runtime-core
to3.2.22
- Improve types for prop
source
options - Improve error reporting for invalid refs
- Add example stories
- Update docs
- Exclude type test files in Jest
- Update Arrays for refs/elements to ReadonlyArray
- Change target for ESM builds to es6 to be more modern
- Add validation on component bindings that try to set props that don't exist.
- Add an
ignoreGuard
option to allref
helpers to bypass the default child-component guard. - Add support for passing multiple components to
refComponent
– e.g.refComponent([Button, Link], { ref: 'some-button' })
. - Make the
defaultValue
on props actually do something, setting the value when no other "error" case is triggered.
- Fix incorrect invalid binding warnings, showing logs in the console that were not correct.
- Prevent refs on collections to update when "inner" HTML updates, causing bindings to re-apply without cleanup.
- Apply
validation
(correctly) on all variations of how to pass props. Don't run validation onundefined
values.
- Fix small errors in docs
- Update
refs
API docs to be accurate, and add more examples - Reorganize and add more Stories for testing
- Add more unit tests
- Add
minimumItemsRequired
option to collection refs – e.g.refCollection('item', { minimumItemsRequired: 3 })
. - Support
null
in predicates for any type
-
Refactor the propType generation and typing
Drastically reducing the generated TS declarations (was over 96000 lines) to only 60 by using Generics.
Also set a fixed order of setters in the chaining API, while still allowing omitting helpers in the middle.
propType.[type].[optional / defaultValue].[validate].[source]
propType.func.[optional].[shape]
- Add unit tests for props
- Add type tests for props
- Fix ordering of adding the propType source helper
- Allow for optional source "attributes"
- Fix doc typos
- Add support for
source
inpropType
helper - Add
text
andhtml
sources
- Fix all unit tests
- Add propType stories as tests and examples
- Add and update docs about props usage
- Remove template code, use
@muban/template
instead (internal change only)
- Add
object
propType
- Remove old transition prototype code
- Guard
ref
query selection to only select direct children. This will make sure that no refs in child components can be selected.
- Remove old transition prototype code
bindMap
now accepts an "Array
ofrefs
" in addition to acollection
.- [typing] Add and move template types
- [typing] Allow
ComponentFactory
to allow any component in "strict" mode by mapping any toany
instead of{}
in component props.
- Add stories to showcase and test the bindMap use cases
- [typing] Fix all TS errors in example components after previous refactors
- Fix provide/inject bugs by moving
Object.create(provides)
fromprovide
to "component creation".
- Allow
event
bindings on componentrefs
- Add reactive
bindMap
implementation
- Remove
renderChildTemplate
, wasn't doing what it should
- Add
renderChildTemplate
util function
- Add new
bindings
;checked
,html
,style
,text
,textInput
andvalue
. - Allow
refs
to on the root element using itsdata-ref
, helps when wrapping and unwrapping elements and those sometimes becoming the root element.
- Re-export
supportLazy
inindex
. - Use
globalThis
to support building and running in node.
- Add new
bindings
;hasFocus
,enable/disable
,visible/hidden
andsubmit
. - [types] Improve the types of refs/bindings
-
Introduced a "global"
App
usingcreateApp
as a starting point.This will "replace" the
mount
andregisterGlobalComponents
, and other things that were kind of global / settings. -
Change lifecycle hooks to mimic the Vue structure a bit more, and get rid of external eventEmitter dependency.
- Updated the folder structure to match the almost final shape of the API.
- Add some unit tests, and include babel in those tests to get everything working again.
- Introduce "component instances" for
refs
to support devtools, keeping track of bindings and when they update. - Add devtools support, highly inspired by the Vue Devtools.
Older versions are too much PoC to list here retro-actively.