Atomico a micro-library for creating webcomponents using only functions, hooks and virtual-dom.
MIT License
Bot releases are hidden (Show)
Published by UpperCod over 2 years ago
Fix circular reference bug( ts:2598 ) associated with type Component
, when using it for type autocompletion.
Published by UpperCod over 2 years ago
const
within corecreate-hooks
code has been optimizedPublished by UpperCod over 2 years ago
now the ref property accepts a callback that will receive the associated node instance as a parameter, example:
<button ref={(node)=>{
console.log(node)
}}></button>
The node received by ref associates the type of the assigned node, so if Atomico is used, the interactions at the prop level will be strict and will be validated by typescript, allowing errors to be detected.
<button ref={(node)=>{
console.log(node)
}}></button>
Now fixture can return more than one node depending on the rendering case.
describe("fixture", () => {
it("list", () => {
const list = [];
const children = fixture(html`
<button ref=${(node) => list.push(node)}>button</button>
<button ref=${(node) => list.push(node)}>button</button>
<button ref=${(node) => list.push(node)}>button</button>
`);
expect(children).to.deep.equal(list);
});
});
Published by UpperCod over 2 years ago
Published by UpperCod over 2 years ago
This is an internal improvement, the algorithm that filters values based on types has been improved, now these cases are validated correctly:
new Number(NaN); // if the input is of type number this will throw an error.
document.createElement("div"); // if the input is of type Element this is valid
This enhancement now allows per-instance validation
Published by UpperCod over 2 years ago
The html return is now any, to define a return type you should use the type parameter, example:
html<VNode<"host">>`<host></host>`
This is not required and is only useful when customizing the return.
Published by UpperCod over 2 years ago
This improvement is at the type level for Typescript:
browser native constructors: All Constructors other than String
, Boolean
, Number
, Promise
, Symbol
, Object
and Array
. Native constructors cannot be mirrored and are only used through the use of properties.
Example:
function component(props: Props<typeof component>) {
return (
<host>
<span>{props?.file?.type}</span>
<span>{props?.pattern?.test("check!") ? "Yes" : "NO"}</span>
</host>
);
}
component.props = {
file: File,
pattern: RegExp,
};
Published by UpperCod over 2 years ago
Now the function h infers the types of the props according to the first parameter type.
<host>
{h("img", {
src: "image",
onclick() {},
})}
</host>
This allows validating the props according to the associated tag as the type of the pragma, it also applies to CustomElement, but in case the type assigned to the HTMLElement is not inferred, example:
class E extends HTMLElement {
myProp: number = 10;
}
<host>
{h(E, {
onclick({ currentTarget }) {
currentTarget.myProp; // ✅
},
})}
</host>;
This feature helps instances through Elements or Custom Elements not created with Atomico to infer the types to be defined.
Published by UpperCod over 2 years ago
When using the null declaration to define a prop as Any, the input type is not defined, through the second parameter you can replace the inferred type with props.
type myProps = Props<typeof component, { myPropAny: Promise<any> | number }>
the above declaration allows you to replace the inferred prop myPropAny
with one of type Promise<any> | number
, this helps improve error detection when using Typescript.
Published by UpperCod almost 3 years ago
Example:
myComponent.props = {id: String}
Declarations targeting reactivity on native DOM attributes are now valid against Typescript, allowing CustomElement registration over customElement.defined
.
Published by UpperCod almost 3 years ago
useHost: Current is always defined for Typescript.
Ref: current is always Any unless specified.
Published by UpperCod almost 3 years ago
Props now supports function typeof as webcomponent without the need to point to props
// Before
Props<typeof myComponent.props>;
// After
Props<typeof myComponent>;
Example
import { Props } from "atomico";
function component({ value }: Props<typeof component>) {
return <host shadowDom>{value}</host>;
}
component.props = {
value: String,
};
Meta aims to add meta-types to the component instance, for now the support allows only the use of Events.
Example
import { Meta, DOMEvent } from "atomico";
function component(): Meta<DOMEvent<"MyEvent">> {
return <host shadowDom>{value}</host>;
}
component.props = {
value: String,
};
Published by UpperCod almost 3 years ago
Error only when using TSX with the new type Component, this version corrects the structure rules of the props when interpreting null and boolean type values.
Published by UpperCod almost 3 years ago
Published by UpperCod almost 3 years ago
<img onload={null}/>
defining null before a property will not throw an error when using JSX.
<img onload={(event)=>{
event.currentTarget.src // ✅
}}/>
Every native HTML or SVG tag correctly accesses its currentTarget when defining the event from JSX, this will happen in the same way with the instance of the CustomElement within the JSX.
<MyComponent onMyCustomEvent={(event)=>{
event.currentTarget.myProp // ✅
}}/>
fix Atomico inheritance when extending a class to modify style
import { css } from "atomico";
import { MyComponent } from "./my-component";
class NewComponent extends MyComponent{
get styles(){
return [
super.styles,
css`:host{ --color: red;}`
]
}
}
Published by UpperCod almost 3 years ago
The objective of this functionality is to be able to build the parameter of an exclusive customEvent of a webcomponent, example:
import { DOMEvent } from "atomico";
import { MyComponent } from "./my-component";
export function handlerCustomEventShow (event: DOMEvent<"Show", typeof MyComponent>){
console.log(event.currentTarget.show)
}
type DOMEvent<"Show", typeof MyComponent>
extracts the Show
event from the customElement MyComponent
.
Published by UpperCod almost 3 years ago
This improved feature is oriented to environments based on Types and JSX, now Atomico allows you to declare Events to be shared through JSX, example:
import { Component, DOMEvent, c } from "atomico";
const props = {
myProp: String,
};
type Events = DOMEvent<"MyCustomEvent", CustomEvent<{ id: string }>>;
const myComponent: Component<typeof props & Events> = ({ myProp }) => {
return (
<host>
<h1>{myProp}</h1>
</host>
);
};
myComponent.props = props;
export const MyComponent = c(myComponent);
Thanks to this declaration DOMEvent<"MyCustomEvent", CustomEvent<{ id: string }>>
we are creating an event to listen to from JSX, example:
<MyComponent
onMyCustomEvent={(event) => {
event.currentTarget.myProp; // ✅
event.detail.id; // ✅
}}
></MyComponent>;
This greatly improves the association of events, since now Typescript will encounter errors if an event of its webcomponent is not valid in declaration.
Published by UpperCod almost 3 years ago
the changes in this version only affect JSX and TSX
Methods and properties inaccessible from JSX are eliminated, example appendChild
, this improves the autocompletion since it reduces the list of recommendations.
DOMCustomEvent
: Now DOMEvent
allows creating a custom event from a CustomEvent, example:
DOMEvent<HTMLElement, CustomEvent<{myData:any}>>
AtomBase
renamed to AtomicoThis
Atom
renamed to Atomico
Published by UpperCod almost 3 years ago
Atomic allows props to declare the slot property, example
myComponent.props = {slot: { type: String, value: "my-slot" }};
In order to observe the slot and define a default one, although before using Typescript it did not generate type errors, after the last Typescript updates this began to generate a type error.
this version fixes it, allowing type-level behavior.
Published by UpperCod almost 3 years ago
Core function that allows rendering html content within a template tag, example:
import { template } from "atomico";
const node = template(<div>i am template!</div>);
The objective of this is to enhance the use of the new cloneNode property, example:
import { template, useRef } from "atomico";
import { useSlot } from "@atomico/hooks/use-slot";
const DefaultContent = template(<div>i am template!</div>);
function component() {
const ref = useRef();
const [Content = DefaultContent] = useSlot();
return (
<host>
<slot name="template" ref={ref} style="display:none" />
<Content cloneNode />
<Content cloneNode />
<Content cloneNode />
<Content cloneNode />
</host>
);
}
As you will notice, Content looks for the existence of the [template] slot, but when not finding it replaces it with DefaultContent
, thanks to this feature you will be able to have nodes within your webcomponents that can be consumed as templates for your logic.