Major overhaul
New Packages
- Package has been renamed from
ink-componentsto@iooxa/article - There are a few other packages added:
@iooxa/runtimeDeals with the reactivity of components@iooxa/componentsBase components hooked up to reactivity@iooxa/svgDiagrams and reactive svg components@iooxa/articleThat is this one! Includes all of the above and exposesiooxain your window
New Features and Major Changes
- Performance improvements - only render the components that actually changed! 🚀
- Execution is now in the main context by default and can access scripts defined there (see #12)
- Opinionated styles are removed (e.g. color, font), and these can be overridden with css vars
- Packages are now in typescript 🎉
- All components are prefixed with
r-, rather than the previousink- - The
bindsyntax has changed slightly, see below
New Components
Working with material web components to bring new components!
<r-switch>- material UI switch<r-checkbox>- material UI checkbox<r-radio>- material UI radio<r-select>- material UI select box #9<r-input>- material UI textarea<r-visible>- Div that makes things invisible on demand
New Documentation
See https://iooxa.dev for up to date documentation.
Changes to Article - Use more HTML!
- Now using
<article> - Now using
<aside>for both asides and callouts.<aside class="callout info"> - These are now just plain CSS - so should be easy for people to re-theme
<r-equation>no longer suffers from a 1-frame lag- Outline see #2
- Helper functions to render math inline.
Charting
- Updated the svg library. See https://github.com/iooxa/svg
Runtime State
I have moved to a single redux store to manage the state. This is split up into {variables, components} the low-level interface looks like:
const x = store.dispatch(runtime.actions.createVariable('scope.x', 3));
const max = store.dispatch(runtime.actions.createVariable('scope.max', 9));
const range = store.dispatch(runtime.actions.createComponent(
'range', 'scope.myRange',
{ value: { func: 'x' }, min: { value: 1 }, max },
{ change: { func: '{x: value}' } },
));
// Can set/get the properties
x.get()
x.set(4)
const { min, max } = range.state;A version of this will be exposed in the window as iooxa so that you can get/set variables in other programs which is needed for more control: (e.g. see #12 #10).
Creating a new component
I have added a base-class BaseComponent that does the generic registering and unregistering of the component as well as a class wrapper @withRuntime that injects properties that you define in a ComponentSpec and give the relevant setters/getters for properties and events as well as playing nice with lit-element. The basics of this new setup gets the boiler-plate from 74 --> 18 lines of code (~25% of the size). The @withRuntime wrapper I think is also more accessible (to debug etc.) than what I had before.
export const DisplaySpec = {
name: 'display',
description: 'Inline display of values',
properties: {
value: { type: types.PropTypes.number, default: NaN },
format: { type: types.PropTypes.string, default: '.1f' },
},
events: {},
};
@withRuntime(DisplaySpec)
class Display extends BaseComponent<typeof DisplaySpec> {
updated(updated: PropertyValues) { onBindChange(updated, this); }
render() {
const { value, format } = this.$runtime!.state;
return html`${formatter(value, format)}`;
}
}Other Details
- Packages are now in typescript 🎉
- Packages are now linted (with
eslint)! - Included testing for the store and evaluation scripts
- Move to a redux architecture that can include the evaluate middleware or not. (by default this will be included)
- single file for each component
- Removed boiler-plate code for creating components, including fighting with typescript generics so new components don't have too!!!
Breaking Changes
Name/Value/Bind
There were a couple of issues with the previous naming conventions. It was is not specific enough for multiple event types (hover, drag, click, etc.) and there is no option for being able to add named components. This could be very helpful to react to events when a component enters the screen, show the component.min value, etc. The previous name attribute was used to set :value="${name}" and bind="{[name]: value}" which amounted to two way binding in the component. This was a handy shortcut and I think it should stay, however, be renamed to bind now that events are explicitly named.
namefor components will now be used for the actual name of the component (should be unique in that scope)- introducing named
events, which will allow components to have multiple types of events bindis used as the default event type on components that allow it.
Previous version:
When you eat <r-dynamic name="cookies" min="2" max="100"> cookies</r-dynamic>,
you consume <r-display :value="cookies * 50" format=".0f"/></r-display> calories.Changes to:
When you eat <r-dynamic bind="cookies" min="2" max="100"> cookies</r-dynamic>,
you consume <r-display :value="cookies * 50" format=".0f"/></r-display> calories.This is equivalent to:
When you eat <r-dynamic :value="cookies" :change="{cookies: value}" min="2" max="100"> cookies</r-dynamic>,
you consume <r-display :value="cookies * 50" format=".0f"/></r-display> calories.Action / Button
The bind syntax doesn't make sense for the r-action and r-button components, it should really be an event and there isn't a value to "bind" to. This should change to :click to return an event transform object. There is also a :hover action!
Transform
- The
transformis an evaluated string, and has been renamed to:transform.
Resume
The resume styles/functions have temporarily been removed.
Deprecated Components
h2-more: please use "float: right" on a button preceding an h2 elementink-span: please user-visibleink-p: please user-visibleink-div: please user-visibleink-a: please user-visible