# My first subscriber component

Learn how to build a subscriber component, styled with tailwind, 
which could be used as a regular component or could be filled from a dataprovider.

## Create a classic lit component

<sonic-code language="javascript" >
  <template>
  import { html, LitElement, nothing } from "lit";
  import { customElement, property } from "lit/decorators.js";
  // name component
  @customElement("docs-user")
  export class user extends LitElement {
    // set a few props
    @property({ type: String }) first_name = "";
    @property({ type: String }) last_name = "";
    @property({ type: String }) avatar = "";
    @property({ type: String }) email = "";
    // output
    render() {
      return html`
        <img src="${this.avatar}"  /> <br>
        ${this.first_name} ${this.last_name} <br>
        ${this.email}`;
    }
  }
  </template>
</sonic-code>


### Style with tailwind and ui components

First export tailwind, in a tailwind.ts file, stylesheet to add it in our component when needed.

<sonic-code language="javascript">
  <template>
  import { css, unsafeCSS } from "lit";
  import tailwindImport from "./css/tailwind.css?inline";
  export const tailwind = css`${unsafeCSS(tailwindImport)}`;
  </template>
</sonic-code>

<sonic-code language="javascript">
  <template>
    import { html, LitElement, nothing } from "lit";
    import { customElement, property } from "lit/decorators.js";
    // add tailwind and needed components
    import { tailwind } from "../tailwind";
    import '@supersoniks/concode/ui/image'
    import '@supersoniks/concode/ui/button'
    import '@supersoniks/concode/ui/icon'
    //
    @customElement("docs-user")
    export class user extends LitElement {
      // add tailwind stylesheed
      static styles = [tailwind];
      @property({ type: String }) first_name = "";
      @property({ type: String }) last_name = "";
      @property({ type: String }) avatar = "";
      @property({ type: String }) email = "";
      // use utility class in your markup
      render() {
        return html`<div
          class="flex items-center gap-3 rounded-md hover:bg-neutral-50 -mx-2 p-2"
        >
          <sonic-image
            src=${this.avatar}
            rounded="md"
            ratio="1/1"
            class="w-16 block"
          ></sonic-image>
          <div>
            <div>
              ${this.first_name} <span class="font-bold">${this.last_name}</span>
            </div>
            <div class="text-sm text-neutral-400">${this.email}</div>
          </div>
          <div class="ml-auto relative">
            <sonic-button
              href="mailto:${this.email}"
              size="sm"
              variant="outline"
              shape="circle"
              class="relative"
              icon
            >
              <sonic-icon library="iconoir" name="chat-bubble"></sonic-icon>
            </sonic-button>
          </div>
        </div>`;
      }
    }
  </template>
</sonic-code>

### Basic usage

Reactive properties can be filled by its attributes as a simple lit component.

<sonic-code>
<template>
<docs-user
  first_name="Paul"
  last_name="Metrand"
  avatar="/img/paul_metrand_xs.jpg"
  email="paulmetrand@concorde.fr"
  ></docs-user>
</template>
</sonic-code>

## Add Subscriber mixin

Import Subscriber mixin, and add it around LitElement.
<sonic-code language="javascript">
  <template>
    import { html, LitElement, nothing } from "lit";
    import { customElement, property } from "lit/decorators.js";
    import { tailwind } from "../tailwind";
    import Subscriber from "@supersoniks/concorde/core/mixins/Subscriber";
    @customElement("docs-user")
    export class user extends Subscriber(LitElement) {
      //...
    }
  </template>
</sonic-code>

## Autofill properties from a dataProvider

Without a dataProvider attribute, a subscriber set its own dataprovider from first ancestor found, and then reactive properties automatically filled and update from it.
A fetcher is a simple component which set its fetch result to props of its dataprovider.
<sonic-code >
<template>
<sonic-fetch 
    serviceURL="https://reqres.in"
    dataProvider="api/users/3" 
    key="data">
     <docs-user></docs-user>
</sonic-fetch>
</template>
</sonic-code>

A subscriber can subscribe data from anywhere in the DOM, with its dataprovider set as a provider id.  
<sonic-code >
<template>
<sonic-fetch 
    serviceURL="https://reqres.in"
    dataProvider="api/users/2" 
    key="data"></sonic-fetch>
<docs-user dataProvider="api/users/2" ></docs-user>
<docs-user dataProvider="api/users/2" ></docs-user>
<docs-user dataProvider="api/users/2" ></docs-user>
</template>
</sonic-code>


<sonic-code >
<template>

<div class="grid grid-cols-1 gap-4">
<form formDataProvider="userPreview" class="grid grid-cols-4 gap-3" >
  <sonic-input label="First name" type="text" name="first_name" placeholder="John" value="Paul"></sonic-input>
  <sonic-input label="Last name" type="text" name="last_name" placeholder="Doe" value="Metrand"></sonic-input>
  <sonic-input class="col-span-2"  label="email" type="text" name="email" placeholder="johndoe@concorde.fr" value="paulmetrand@concorde.fr"></sonic-input>
  <sonic-input type="file" name="avatar" value="/img/paul_metrand_xs.jpg"></sonic-input>
</form>
<sonic-divider align="left">Preview before submit</sonic-divider>
<docs-user dataProvider="userPreview" ></docs-user>
<sonic-button onClick="alert(JSON.stringify(SonicPublisherManager.get('userPreview').get()))">
  Update data
</sonic-button>
</div>
</template>
</sonic-code>