Skip to content

Atomico 1.76 🚀🎉 with new features and type improvements

Compare
Choose a tag to compare
@UpperCod UpperCod released this 26 Feb 03:24
· 41 commits to master since this release

New features

New way to declare a component without the need for types

export const MyComponent = c(
  ({ message }) => <host shadowDom>{message}</host>,
  {
    props: { message: String },
    styles: css`
      :host {
        font-size: 3rem;
      }
    `,
  }
);

customElements.define("my-component", MyComponent);

This form is more compact than the ones already known, but with slight advantages:

  1. You don't depend on types like Component or Props to build props; everything is inferred automatically.
  2. Fewer lines of code, either for function or constant assignment as with the types Component and Props.
  3. Ideal for environments without TypeScript, as types are automatically inferred.

useRef reactive but without rendering

References maintain their usual behavior, but now they allow maintaining an observer model for the change of current, for example:

import { createRef, useRefEffect } from "atomico";

const ref = createRef({ x: 0, y: 0 });

window.addEventListener("mousemove", ({ pageX, pageY }) => {
  ref.current = { x: pageX, y: pageY };
});

function component() {
  useRefEffect(() => {
    console.log(ref.current);
  }, [ref]);
}
  1. To create better APIs that integrate with Atomico, we needed a subscriber handling without impacting rendering, currently.
  2. For future forms of asynchronous rendering, one cannot depend on the closure of the parent cycle to observe changes in references (The same problem as React). That's why, for a future improvement of the Atomico renderer, useRefEffect is created to safely observe changes in references.

useRefEffect

New hook capable of observing changes in one or more references.

function component() {
  useRefEffect(() => {
    console.log(ref.current);
  }, [ref]);
}

Type improvements

useHost

Now Atomico is able to determine which types per instance come assigned with a default value. This is to maintain consistency in validation of instance props.

import { useHost, c } from "core";

export function myComponent() {
  const { current } = useHost<typeof MyComponent>();
  return (
    <host>
      <button
        onclick={() => {
          current.count++;
          current.message?.toLocaleLowerCase();
        }}
      >
        increment
      </button>
    </host>
  );
}

myComponent.props = {
  count: { type: Number, value: 0 },
};

export const MyComponent = c(myComponent);

customType

Now customTypes respect assigned values and distinguish a value to be used from JSX and a value to be used from the instance.

Now customType takes precedence over the type associated with value.

import { Props, c, createType, useRef } from "core";

function myComponent({ date }: Props<typeof myComponent>) {
  return <host shadowDom>{date.toLocaleDateString()}</host>;
}

const TypeDate = createType((value: Date | string) =>
  value instanceof Date ? value : new Date(value)
);

myComponent.props = {
  date: { type: TypeDate, value: new Date() },
};

const MyComponent = c(myComponent);

<MyComponent
  onclick={({ currentTarget }) => {
    currentTarget.date.toLocaleDateString();
  }}
  date={"December 17, 1995 03:24:00"}
>
  ...
</MyComponent>;