@smoovy/composer
TypeScript icon, indicating that this package has built-in type declarations

1.0.10 • Public • Published

@smoovy/composer

Version Size

Very simple component/service system. Optimized for TypesScript usage.

Installation

yarn add @smoovy/composer

or

npm install --save @smoovy/composer

Component

A component is a very simple class, you just tell the composer what selector to use and it'll manage all updates and detects if the element is still in the DOM etc.

import { component } from  '@smoovy/composer';

/** Elements with the attribute `data-test` will be selected */
@component('test')
class TestComponent {
  constructor(
    private element: HTMLelement
  ) {}

  /** On creation after the injectors are done */
  onCreate() {}

  /** After the element is no longer in the DOM */
  onDestroy() {}

  /** Helper method to make unlistening easier **/
  onListen() {
    return () => {
      console.log('unlisten from listeners');
    };
  }
}

// you can change specify a different selector like this
@component({
  selector: '.select-this-class'
})

Lifecycle methods are: onCreate, onListen and onDestroy. All are optional ´

Component config

You can inject config from the element dataset into your component like this:

<div
  data-test-message="Hello Universe!"
  data-test-count="8"
></div>

<!-- It's also possible to define an object. So the following is the same: -->
<div
  data-test='{ "message": "Hello Universe!", "count": 8 }'
></div>

If you define both the "non-json" value has priority

import { component, config } from  '@smoovy/composer';

@component('test')
class TestComponent {
  @config('message')
  private message: string;

  @config('count', {
    type: Number,
    parse: (val: number) => val * val
  })
  private count = 0;

  onCreate() {
    console.log(this.message); // "Hello Universe!"
    console.log(this.count); // 64
  }
}

Component query

To simplify the step of querying elements from your root element, you can use the query or queryAll injector like this:

import { component, query, queryAll } from  '@smoovy/composer';

@component('test')
class TestComponent {
  @query('.headline')
  private headline: HTMLElement;

  @queryAll('p', { parse: list => Array.from(list) })
  private paragraphs: HTMLElement[] = [];

  onCreate() {
    console.log(this.headline); // contains DOM element
    console.log(this.paragraphs); // contains array of DOM p elements
  }
}

Service

A service is a class that exists as a singleton inside your project. This "singleton functionality" is achieved by using injectors. So you can inject services inside components and other services. A service is basically a Promise with extra functionality.

import { Service } from '@smoovy/composer';

class TestService extends Service<any, TestService> {
  get name() {
    return 'test';
  }

  get child() {
    return TestService;
  }

  async init() {
    this.resolve(this.config.msg);
  }
}

Creating sub services

A service can have children, so you can split the service into smaller ones and give them a separate context. For example you have a ScrollerService. Now you have a sidescroller which uses a different scroller, you could create a sub service with a name and different configuration. This allows you to create reusable components easier. Here's an example

const testService = new TestService({ msg: "I'm the parent" });

testService.addChild('sub1', { msg: "I'm the child" });

// now inside your components you can for the children
let message = '';

if (testService.hasChild('sub1')) {
  const sub1 = testService.getChild('sub1');
  message = await sub1;
} else {
  message = await testService;
}

// message will be "I'm the child"
console.log(message);

Using a service

Services can be injected into components or other services like this:

import { service, component } from  '@smoovy/composer';

class TestService2 {
  @service(TestService)
  private testService: TestService;

  async init() {
    // make sure to check if it's been activated otherwise it would wait forever
    if (this.testService.activated) {
      await this.testService;
    }
  }
}

@component('[data-test]')
class TestComponent {
  @service(TestService, true /** await automatically **/)
  private message: string;

  onCreate() {
    // We'll get value immediately since we told
    // to await the service on injection
    console.log(this.message);
  }
}

Composer

The composer glues components and services together. It manages injections, configurations and "garbage collection". Composers are defined with a class like this:

import { composer } from '@smoovy/composer';

@composer({
  services: [],
  components: []
})
class App {
  @composer()
  private composer!: Composer;

  onCreate() {
    console.log(this.composer);
  }
}

// Create the app to kick off initialization
new App();

Using composer in components

You can inject the composer into child components and services like this:

import { component, composer } from  '@smoovy/composer';

@component('[data-test]')
class TestComponent {
  @composer()
  private composer: Composer;

  onCreate() {
    this.composer.update();
  }
}

This also works for services

License

See the LICENSE file for license rights and limitations (MIT).

Package Sidebar

Install

npm i @smoovy/composer

Weekly Downloads

3

Version

1.0.10

License

MIT

Unpacked Size

23.3 kB

Total Files

16

Last publish

Collaborators

  • davideperozzi