npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@youfocus-technology/matrix

v1.0.17

Published

Componentes web customizados baseados em Lit.

Readme

Youfocus Matrix

Este documento demonstra como utilizar a biblioteca de componente Youfocus Matrix

Instalação

No seu projeto externo instale nossa biblioteca

npm i @youfocus-technology/matrix

Exemplo Vanilla

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Meu Projeto Lit</title>
  <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600&display=swap" rel="stylesheet" />
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" />
  <link rel="stylesheet" href="./src/styles/palette.css" />
  <script type="module" src="./src/components/MatrixButton/matrix-button.ts"></script>
  <script type="module" src="./src/components/MatrixInput/matrix-input.ts"></script>
  <script type="module" src="./src/components/MatrixSlider/matrix-slider.ts"></script>
  <script type="module" src="./src/components/MatrixIcon/matrix-icon.ts"></script>
  <script type="module" src="./src/components/MatrixIconButton/matrix-icon-button.ts"></script>
  <script type="module" src="./src/components/MatrixTooltip/matrix-tooltip.ts"></script>
  <script type="module" src="./src/components/MatrixSwitch/matrix-switch.ts"></script>
  <script type="module" src="./src/components/MatrixWarning/matrix-warning.ts"></script>
  <script type="module" src="./src/components/MatrixHelpTip/matrix-help-tip.ts"></script>
  <script type="module" src="./src/components/MatrixCheckbox/matrix-checkbox.ts"></script>
  <script type="module" src="./src/components/MatrixRadio/matrix-radio.ts"></script>

  <style>
    body {
      font-family: "Open Sans", sans-serif;
      padding: 32px;
      /* background: #a4a4a7; */
    }

    .demo-row {
      display: flex;
      align-items: flex-end;
      margin-bottom: 24px;
      gap: 10px;
    }

    #formExemplo {
      display: flex;
      flex-direction: column;
      margin-bottom: 10px;
    }
  </style>
</head>

<body>
  <div class="demo-row">
    <mx-button type="primary" color="light-blue" size="small" id="btnSalvar">
      <i slot="icon" class="fa-solid fa-check"></i>
      Small button
    </mx-button>
    <mx-button type="primary" color="light-blue" size="small">
      Small button
      <mx-icon slot="icon" name="check-on" size="small"></mx-icon>
    </mx-button>
    <mx-button type="secondary" color="light-blue" size="medium" id="btnSalvar" loading>
      <i slot="icon" class="fa-solid fa-check"></i>
      Medium button
    </mx-button>
    <mx-button type="upload" color="light-blue" size="medium" id="btnSalvar">
      <i slot="icon" class="fa-solid fa-check"></i>
      Large button
    </mx-button>
    <button id="btnMostrarValores" style="margin-left: 16px; padding: 8px 16px">
      Mostrar valores dos inputs
    </button>
  </div>

  <mx-input id="inputNome" label="Nome" placeholder="Digite seu nome" type="text" required
    helpMessage="Digite seu nome completo." alert="Olá"></mx-input>

  <mx-input id="meuSelect" label="Selecione uma opção" type="select" required placeholder="Escolha..."
    helpMessage="Escolha uma das opções disponíveis."></mx-input>

  <div style="display: flex">
    <mx-input id="inputMoney" label="Valor" placeholder="0,00" isMoney required
      helpMessage="Digite o valor desejado e selecione a moeda."></mx-input>

    <mx-switch id="meuSwitch" label="Label" size="small" required
      helpMessage="Você precisa aceitar para continuar"></mx-switch>
    <mx-slider min="-10" max="50" step="1" value="0"></mx-slider>
  </div>

  <div>
    <mx-tooltip text="Rótulo curto" position="top" type="label">
      <mx-icon name="cloud-circle" size="small"></mx-icon>
    </mx-tooltip>

    <mx-tooltip>
      <div slot="content">I'm not <strong>just</strong> a tooltip, I'm a <em>tooltip</em> with HTML!</div>
      <mx-icon name="cloud-circle" size="small"></mx-icon>
    </mx-tooltip>

    <mx-icon name="restore" size="medium" color="#00f" required></mx-icon>
    <mx-icon name="home" size="large" color="#00f"></mx-icon>
  </div>

  <mx-tooltip text="Este é um texto informativo sem link." position="top" type="info">
    <span>Hover para informação</span>
  </mx-tooltip>

  <mx-tooltip text="Este é um texto informativo com um link abaixo." position="bottom" type="info"
    linkText="Clique aqui para saber mais" linkHref="https://exemplo.com">
    <span>Hover para informação com link</span>
  </mx-tooltip>

  <div style="width: 50%">
    <mx-warning type="error">Informe a senha aos clientes da galeria.</mx-warning>

    <mx-warning type="info">
      <ol>
        <li>Crie pelo menos uma pasta para a galeria;</li>
        <li>Clique em "Carregar fotos" para adicionar as fotos na pasta;</li>
        <li>
          Após finalizar o carregamento, clique em "Salvar fotos" para voltar
          à lista de pastas - Texto em B3.
        </li>
      </ol>
      <a href="https://google.com.br" target="_blank" rel="noopener noreferrer">
        Link para ação
      </a>
    </mx-warning>
  </div>

  <div>
    <p>HelpTooltip<mx-help-tip message="Sua mensagem de ajuda aqui"></mx-help-tip></p>
  </div>

  <div>
    <mx-icon-button name="star"></mx-icon-button>
  </div>

  <form id="formExemplo">
    <mx-checkbox name="aceito" value="sim" dark>Aceito os termos</mx-checkbox>
    <mx-checkbox name="novidade">Quero receber novidades</mx-checkbox>
    <mx-checkbox name="ofertas" value="ofertas">Receber ofertas</mx-checkbox>
  </form>

  <button type="button" id="btnMostrarCheckboxes" style="margin-top: 16px;">
    Mostrar valores dos checkboxes
  </button>

  <form id="formExemplo">
    <mx-radio name="group1" value="1" disabled>Opção 1</mx-radio>
    <mx-radio name="group1" value="2">Opção 2</mx-radio>
    <mx-radio name="group1" value="3">Opção 3</mx-radio>
  </form>

  <button type="button" id="btnMostrarRadios" style="margin-top: 16px;">
    Mostrar valor do radio selecionado
  </button>

  <script>
    document.getElementById("meuSelect").options = [
      { label: "Opção 1", value: "1" },
      { label: "Opção 2", value: "2" },
      { label: "Opção 3", value: "3" },
    ];

    const inputMoney = document.getElementById("inputMoney");
    inputMoney.currency = "BRL";

    function validateInputs() {
      let valid = true;

      const inputNome = document.getElementById("inputNome");
      const nome = (inputNome.value || "").trim();
      if (!nome) {
        inputNome.error = "O nome é obrigatório";
        inputNome.alert = "";
        valid = false;
      } else if (nome.length === 2) {
        inputNome.error = "";
        inputNome.alert =
          "Seu nome parece muito curto. Tem certeza que está correto?";
        valid = false;
      } else {
        inputNome.error = "";
        inputNome.alert = "";
      }

      const meuSelect = document.getElementById("meuSelect");
      const select = meuSelect.value;
      if (!select) {
        meuSelect.error = "Selecione uma opção";
        valid = false;
      } else {
        meuSelect.error = "";
      }

      const money = (inputMoney.value || "").trim();
      if (!money) {
        inputMoney.error = "Informe um valor";
        valid = false;
      } else {
        inputMoney.error = "";
      }

      return valid;
    }

    document
      .getElementById("inputNome")
      .addEventListener("input-change", (e) => {
        const el = document.getElementById("inputNome");
        el.error = "";
        el.alert = "";
      });

    document
      .getElementById("meuSelect")
      .addEventListener("input-change", (e) => {
        document.getElementById("meuSelect").error = "";
      });

    document
      .getElementById("inputMoney")
      .addEventListener("input-change", (e) => {
        document.getElementById("inputMoney").error = "";
      });

    document
      .getElementById("btnMostrarValores")
      .addEventListener("click", () => {
        if (!validateInputs()) return;

        const nome = document.getElementById("inputNome").value;
        const select = document.getElementById("meuSelect").value;
        const money = document.getElementById("inputMoney").value;
        const moeda = document.getElementById("inputMoney").currency;

        alert(
          `Nome: ${nome}\n` +
          `Opção selecionada: ${select}\n` +
          `Valor: ${money}\n` +
          `Moeda: ${moeda}`
        );
      });

    document.getElementById('btnMostrarCheckboxes').addEventListener('click', function () {
      const checkboxes = Array.from(document.querySelectorAll('#formExemplo mx-checkbox'))
        .filter(cb => cb.checked);

      if (checkboxes.length === 0) {
        alert('Nenhuma opção selecionada.');
        return;
      }

      const msg = checkboxes.map(cb => {
        let value = cb.value;
        if (!value) value = cb.textContent.trim();
        const name = cb.name || '(sem name)';
        return `${name}: ${value}`;
      }).join('\n');

      alert(msg);
    });

    document.getElementById('btnMostrarRadios').addEventListener('click', function () {
      const radios = Array.from(document.querySelectorAll('mx-radio[name="group1"]'));
      const checkedRadio = radios.find(r => r.checked);

      if (!checkedRadio) {
        alert('Nenhuma opção selecionada.');
        return;
      }

      let value = checkedRadio.value;
      if (!value) value = checkedRadio.textContent.trim();

      alert(`Selecionado: ${value}`);
    });
  </script>
</body>

</html>

Exemplo Vue

No main.ts

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import "@youfocus-technology/matrix";
import '@youfocus-technology/matrix/dist/palette.css';

createApp(App).mount('#app')

Na tela ou componente

<script setup lang="ts">
import { ref, reactive } from "vue";

// Dados do formulário principal
const data = ref({
  name: "",
  lastname: "",
  option: "",
  money: "",
  currency: "BRL",
});

const errors = reactive({
  name: "",
  lastname: "",
  option: "",
  money: "",
});

const alerts = reactive({
  name: "",
  lastname: "",
  option: "",
  money: "",
});

const options = [
  { label: "Opção 1", value: "1" },
  { label: "Opção 2", value: "2" },
  { label: "Opção 3", value: "3" },
];

function validate() {
  let valid = true;

  if (!data.value.name.trim()) {
    errors.name = "O nome é obrigatório";
    alerts.name = "";
    valid = false;
  } else if (data.value.name.trim().length === 2) {
    errors.name = "";
    alerts.name = "Seu nome parece muito curto. Tem certeza que está correto?";
    valid = false;
  } else {
    errors.name = "";
    alerts.name = "";
  }

  if (!data.value.lastname.trim()) {
    errors.lastname = "O sobrenome é obrigatório";
    valid = false;
  } else {
    errors.lastname = "";
  }

  if (!data.value.option) {
    errors.option = "Selecione uma opção";
    valid = false;
  } else {
    errors.option = "";
  }

  if (!data.value.money.trim()) {
    errors.money = "Informe um valor";
    valid = false;
  } else {
    errors.money = "";
  }

  return valid;
}

function handleClick() {
  if (!validate()) {
    return;
  }
  alert(
    `Nome: ${data.value.name}\n` +
      `Sobrenome: ${data.value.lastname}\n` +
      `Opção: ${data.value.option}\n` +
      `Valor: ${data.value.money}\n` +
      `Moeda: ${data.value.currency}`
  );
}

const sliderValue = ref(50);
const switchChecked = ref(false);

function onSliderInput(e: any) {
  sliderValue.value = e.detail;
}

function onSwitchChange(e: any) {
  switchChecked.value = e.detail.checked;
}

// --- CHECKBOXES ---
const checkboxes = reactive({
  termos: false,
  novidades: false,
  ofertas: false,
});

function handleCheckboxChange(name: string, checked: boolean) {
  checkboxes[name as keyof typeof checkboxes] = checked;
}

function mostrarCheckboxes() {
  const selecionados = Object.entries(checkboxes)
    .filter(([_, checked]) => checked)
    .map(([name]) => name)
    .join(", ");
  alert(selecionados ? `Checkboxes marcados: ${selecionados}` : "Nenhum checkbox marcado.");
}

// --- RADIOS ---
const radioValue = ref<string>("");

function handleRadioChange(value: string) {
  radioValue.value = value;
}

function mostrarRadio() {
  alert(radioValue.value ? `Radio selecionado: ${radioValue.value}` : "Nenhum radio selecionado.");
}
</script>

<template>
  <div class="home">
    <mx-input
      label="Nome"
      placeholder="Digite seu nome"
      :error="errors.name"
      :alert="alerts.name"
      type="text"
      required
      :value="data.name"
      @input-change="(e: any) => { data.name = e.detail; errors.name = ''; alerts.name = '' }"
      helpMessage="Seu nome completo como consta no documento."
    />

    <mx-input
      label="Sobrenome"
      placeholder="Digite seu sobrenome"
      :error="errors.lastname"
      type="text"
      required
      :value="data.lastname"
      @input-change="(e: any) => { data.lastname = e.detail; errors.lastname = '' }"
      helpMessage="Seu nome completo como consta no documento."
    />

    <mx-input
      label="Selecione uma opção"
      type="select"
      required
      placeholder="Escolha..."
      :options="options"
      :error="errors.option"
      :value="data.option"
      @input-change="(e: any) => { data.option = e.detail; errors.option = '' }"
    />

    <div style="display: flex">
      <mx-input
        label="Valor"
        placeholder="0,00"
        isMoney
        :error="errors.money"
        :value="data.money"
        :currency="data.currency"
        @input-change="(e: any) => { data.money = e.detail; errors.money = '' }"
        @currency-change="(e: any) => data.currency = e.detail"
        required
      />
      <mx-switch
        :checked="switchChecked"
        label="Ativar opção"
        helpMessage="Ativa ou desativa a opção"
        size="small"
        @change="onSwitchChange"
      ></mx-switch>
      <mx-slider
        :value="sliderValue"
        min="0"
        max="100"
        step="1"
        unit="%"
        @change="onSliderInput"
      ></mx-slider>
      <div>Valor do slider: {{ sliderValue }}</div>
    </div>

    <div style="width: 10%;">
      <mx-button
        type="primary"
        color="light-blue"
        size="medium"
        @button-click="handleClick"
        href="https://www.google.com"
        target="_blank"
      >
        <i slot="icon" class="fa-solid fa-house"></i>
        Medium button
      </mx-button>
    </div>
    <mx-button type="primary" color="light-blue" size="small">
      Small button
      <mx-icon slot="icon" name="check-on" size="small"></mx-icon>
    </mx-button>
    <mx-button
      type="tertiary"
      color="light-blue"
      size="small"
      loading
      dark
      @button-click="handleClick"
    >
      <i slot="icon" class="fa-solid fa-check"></i>
      Small button
    </mx-button>

    <div
      style="
        display: flex;
        flex-direction: column;
        gap: 10px;
        margin-top: 40px;
        border-top: 1px solid #eee;
        padding-top: 24px;
      "
    >
      <h3>Exemplos dos 5 componentes Lit</h3>

      <mx-icon name="home" size="large" color="green"></mx-icon>
      <mx-icon name="home" :size="'small'" color="green"></mx-icon>

      <mx-slider
        :value="sliderValue"
        min="0"
        max="100"
        step="1"
        unit="%"
        @change="onSliderInput"
      ></mx-slider>
      <div>Valor do slider: {{ sliderValue }}</div>

      <mx-switch
        :checked="switchChecked"
        label="Ativar opção"
        helpMessage="Ativa ou desativa a opção"
        size="small"
        @change="onSwitchChange"
      ></mx-switch>
      <div>Switch está {{ switchChecked ? "ligado" : "desligado" }}</div>

      <mx-tooltip text="Dica importante!" position="top">
        <mx-button>Hover me</mx-button>
      </mx-tooltip>

      <mx-tooltip>
        <div slot="content">I'm not <strong>just</strong> a tooltip, I'm a <em>tooltip</em> with HTML!</div>
        <mx-button>Hover me</mx-button>
      </mx-tooltip>

      <mx-button type="primary" color="light-blue" size="small">
        <mx-icon slot="icon" name="check-on" size="small"></mx-icon>
        Small button
      </mx-button>

      <mx-warning type="info">
        <ol>
          <li>Crie pelo menos uma pasta para a galeria;</li>
          <li>Clique em "Carregar fotos" para adicionar as fotos na pasta;</li>
          <li>
            Após finalizar o carregamento, clique em "Salvar fotos" para voltar
            à lista de pastas - Texto em B3.
          </li>
        </ol>
        <a href="https://google.com.br" target="_blank" rel="noopener noreferrer">
          Link para ação
        </a>
      </mx-warning>
    </div>

    <div style="margin-top: 32px;">
      <span style="display: flex; align-items: center;">
        Nome completo
        <mx-help-tip message="Seu nome completo como consta no documento."></mx-help-tip>
      </span>
      <span style="display: flex; align-items: center;">
        Valor em reais
        <mx-help-tip message="Digite o valor em reais, sem pontos ou vírgulas."></mx-help-tip>
      </span>
      <span style="display: flex; align-items: center;">
        Dica importante
        <mx-help-tip message="Esta é uma dica importante para o usuário!"></mx-help-tip>
      </span>
    </div>

    <div style="display: flex; gap: 5px; margin-top: 10px;">
      <mx-icon-button
        name="star"
      ></mx-icon-button>
      <mx-icon-button
        name="home"
      ></mx-icon-button>
      <mx-icon-button
        name="check-on"
      ></mx-icon-button>
    </div>

    <div style="display: flex; flex-direction: column; gap: 5px; margin-top: 10px;">
      <mx-checkbox
        name="termos"
        :checked="checkboxes.termos"
        @change="(e: any) => handleCheckboxChange('termos', e.detail.checked)"
      >Aceito os termos</mx-checkbox>
      <mx-checkbox
        name="novidades"
        :checked="checkboxes.novidades"
        @change="(e: any) => handleCheckboxChange('novidades', e.detail.checked)"
      >Quero receber novidades</mx-checkbox>
      <mx-checkbox
        name="ofertas"
        :checked="checkboxes.ofertas"
        @change="(e: any) => handleCheckboxChange('ofertas', e.detail.checked)"
      >Receber ofertas</mx-checkbox>
      <br />
      <mx-button type="primary" size="small" @button-click="mostrarCheckboxes">
        Mostrar checkboxes marcados
      </mx-button>
    </div>

    <div style="display: flex; flex-direction: column; gap: 5px; margin-top: 10px;">
      <mx-radio
        name="grupo1"
        value="1"
        :checked="radioValue === '1'"
        @change="() => handleRadioChange('1')"
      >Opção 1</mx-radio>
      <mx-radio
        name="grupo1"
        value="2"
        :checked="radioValue === '2'"
        @change="() => handleRadioChange('2')"
      >Opção 2</mx-radio>
      <mx-radio
        name="grupo1"
        value="3"
        :checked="radioValue === '3'"
        @change="() => handleRadioChange('3')"
      >Opção 3</mx-radio>
      <br />
      <mx-button type="primary" size="small" @button-click="mostrarRadio">
        Mostrar radio selecionado
      </mx-button>
    </div>
  </div>
</template>

<style scoped>
.home {
  width: 100vw;
  min-height: 100vh;
  padding: 25px;
  background-color: #fff;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
</style>

Como usar o Storybook

Clone nosso repositório e execute o comando

npm run Storybook