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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@kokomin/weather-widget

v0.0.5

Published

A simple web component that displays weather information UI.

Downloads

299

Readme

Weather widgets

これは日本語で天気情報を表示するウィジェットを作るためのウェブコンポーネントです。

現在は、特定の1日のみの天気予報の表示のみをサポートしています。

インストール

npm i @kokomin/weather-widget

天気データを表示する

  1. データを用意する

    以下の型を持つデータを用意します。

    interface WeatherInfo {
      weather: Weather;
      temp: number;
      pop: number;
    }
    
    export interface WeatherData {
      date: string;
      location: string;
      main: WeatherInfo;
      hours: (WeatherInfo & {time: string})[];
    }
  2. HTML を記述する

    Web コンポーネントをマークアップに含めます。

    <header>
      <script type="module" src="/weather-widget/dist/index.js"></script>
    </header>
    <body>
      <weather-widget></weather-widget>
    </body>
  3. データをセットする

    要素への参照を取得したら、dataプロパティに値をセットします。

    const weather_widgets = document.querySelector('weather-widget');
    
    if (weather_widgets) {
      fetch('API_ENDPOINT')
        .then((res) => res.json())
        .then((data) => (weather_widgets.data = data));
    }
  4. UI が表示されます。

    ウィジェットのトップ

    ウィジェットのチャート

    ウィジェットの検索ダイアログ

    これで一通りの UI は完成しましたね。

イベントから検索内容を受け取り、UI を更新する。

デフォルトでは、現在地と郵便番号と地域名から検索できるようになっています。

それらの情報は、weather-widget要素で発生するsearchイベントで受け取れます。

event.detail.methodの値で分けると、各検索方法に適した処理を行うことができます。

郵便番号は検証済みであるため、改めて行う必要はありません。

Geolocation API を使用してユーザーの緯度と経度を取得しようとした際、ユーザーがこれを拒否する可能性があります。

その場合、event.detail.locationの値はnullになっています。

weather_widgets.addEventListener('search', (event) => {
  const detail = event.detail;

  switch (detail.method) {
    case 'zipcode':
      console.log('郵便番号', detail.zipcode);
      break;
    case 'area':
      console.log('ユーザーが入力した地域名', detail.area);
      break;
    case 'location':
      const location = detail.location;

      if (!location) {
        console.error('ユーザーが現在地の取得を拒否しました。');
        return;
      }

      console.log('ユーザーがいる場所の緯度', location.latitude);
      console.log('ユーザーがいる場所の経度', location.longitude);
      break;
  }
});

このイベントの中で、先ほど取得したweather-widget要素のdataプロパティに新しい天気データを再割り当てすれば、自動的に UI は更新されます。

また、天気データを取得した後に検索ダイアログを閉じる場合は、weather-widget要素のhide_search_dialog()メソッドをを利用します。

以下に、一般的に利用されるであろうパターンを示しておきます。

weather_widgets.addEventListener('search', (event) => {
  const detail = event.detail;

  switch (detail.method) {
    case 'zipcode':
      fetch(`/weather?zipcode=${detail.zipcode}`)
        .then((res) => res.json())
        .then((data) => {
          weather_widgets.data = data;
          weather_widgets.hide_search_dialog();
        });
      break;

    default:
      return;
  }
});

地域名の検索候補を出す

ユーザーが地域名を検索する際に、検索候補を出すことで UX が改善されたり、天気情報の効率的な検索に役立ちます。

検索候補はarea_suggestions属性またはプロパティより設定可能です。

<weather-widget area-suggestions="['北海道', '青森', '岩手']"></weather-widget>
fetch('/area/search?prefectures')
  .then((res) => res.json())
  .then((data) => (weather_widgets.area_suggestions = data));

またはユーザーの入力文字に合わせて動的に候補を表示したいことがあります。

そのために、input-areaイベントが用意されています。

このイベントはデフォルトで 500 ミリ秒のデバウンスが設定されていますが、input-area-debounce属性から簡単に変更できます。

例えば、デバウンスを 1 秒ごとに設定したいなら、以下のように記述します。

<weather-widget input-area-debounce="1000"></weather-widget>

あとは、イベントから候補を動的に表示させます。

weather-widget.addEventListener("input-area", (event) => {
	console.log("このイベントハンドラはユーザーが前に入力してから少なくとも1秒は経過した後に呼び出されます。");

	const area = event.detail.value;

	fetch(`/area/search?name=${area}`)
		.then(res => res.json())
		.then(data => weather-widget.area_suggestions = data)
});

UI のカスタマイズ

検索の仕方を制限したかったり、そもそも検索させる必要がない場合、これらの表示 / 非表示をsearch-methods属性から簡単に変更できます。

例えば、すべての検索 UI を表示する場合は以下のように記述できます。

<weather-widget
  search-methods="current-location, zipcode, area"
></weather-widget>

<!-- または all 値(デフォルト値) -->

<weather-widget search-methods="all"></weather-widget>

『なんでシンプルにlocationではなく、current-locationなの?』と疑問に思うかもしれません。これは将来的に、現在地からデータを取得するボタンと、単に緯度と経度を入力してsearchイベントの location メソッドから検索する入力フィールド の表示を独立して切り替えられたら UI の柔軟性が高まるという考えのもと、このような仕様になっています。

カンマの後に空白があるのは読みやすさを配慮してのことであり、なくても問題ありません。

それぞれの検索 UI はカンマ区切りで制御できます。例えば、『現在地から取得する』ボタンが必要ないときは以下のように記述します。

<weather-widget search-methods="zipcode, area"></weather-widget>

そもそも検索異能自体が不要な場合は空の文字列に設定してください。

<weather-widget search-methods=""></weather-widget>

チャートに関しては、現在のところ UI の制御ができません。これは、将来的に行う、週のデータや月のデータを表示する計画がどうなるか定かではないからです。

テーマを含むスタイルの変更

豊富な CSS 変数による色の変更は許可していますが、最も簡単で推奨される方法は--weather-widget-hueの値を変更することです。

:root {
  /* change red theme */
  --weather-widget-hue: 30;
}

これにより、今後開発される予定の UI までその色が適用されることになるため、バージョンアップがしやすいというメリットがあります。

レスポンシブに対応するよう既にスタイルが設定されているため、weather-widget要素のmax-widthの値は変更しないでください。

コンポーネントの幅は 220px から 400px までを想定しています。

独自のデータ変換プロセスの利用

weather-widgetは以下ののようなデータを受け取ることを想定しています。

{
  "date": "2024-11-20T00:00:00.000Z",
  "location": "東京都",
  "main": {
    "weather": "晴れ",
    "temp": 22.5,
    "pop": 0.1
  },
  "hours": [
    {
      "time": "2024-11-20T00:00:00.000Z",
      "weather": "曇り",
      "temp": 18.2,
      "pop": 0.2
    },
    {
      "time": "2024-11-20T03:00:00.000Z",
      "weather": "曇り",
      "temp": 17.8,
      "pop": 0.3
    },
    {
      "time": "2024-11-20T06:00:00.000Z",
      "weather": "雨",
      "temp": 16.5,
      "pop": 0.7
    },
    {
      "time": "2024-11-20T09:00:00.000Z",
      "weather": "雨",
      "temp": 20.0,
      "pop": 0.1
    },
    {
      "time": "2024-11-20T12:00:00.000Z",
      "weather": "晴れ",
      "temp": 22.5,
      "pop": 0.05
    },
    {
      "time": "2024-11-20T15:00:00.000Z",
      "weather": "晴れ",
      "temp": 23.0,
      "pop": 0
    },
    {
      "time": "2024-11-20T18:00:00.000Z",
      "weather": "曇り",
      "temp": 21.2,
      "pop": 0.1
    },
    {
      "time": "2024-11-20T21:00:00.000Z",
      "weather": "雪",
      "temp": 19.0,
      "pop": 0.2
    },
    {
      "time": "2024-11-21T00:00:00.000Z",
      "weather": "曇り",
      "temp": 19.0,
      "pop": 0.2
    }
  ]
}

デフォルトでコンポーネントはこの形式のデータを受け取ると、ISO 文字列を日付や 2 桁の時間表記に変換したり、popの値を割合からパーセンテージに変換します。

しかしときには、このような変換が不要であったり、独自の変換プロセスを利用したい場面があると思います。

もし変換が不要であれば、notransform属性を追加してください。

<weather-widget notransform></weather-widget>

独自の変換関数を使用する場合は、weather_widgets.transformから関数を再割り当てしてください。

weather_wigets.transform = (input_weather_data) => {
  // 受け取った天気情報を上記のフォーマットに合わせる...
  // 最後に、変換したデータを返す
  return transformed;
};

その他 API

  • 気温の単位はunit属性(またはプロパティ)から変換する。

  • weather-widget.close_search_dialog()により、検索ダイアログを閉じる。

スタイリング

  • 以下は外部からアクセス可能な CSS パーツの一覧です。

    | パーツ名 | 説明 | | -------- | -------------------------------------------------------- | | search | 検索ダイアログの『現在地を取得する』『検索する』のボタン | | input | ユーザーの検索入力フィールド |

    スタイリングの例:

    weather-widget::part(search) {
      background: red;
    }
    
    weather-widget::part(input) {
      background: blue;
    }
  • 以下の CSS 変数から UI の色も変更できます。

    | 変数名 | 説明 | | --------------------------------- | -------------------------- | | weather-widget-bg-primary | メインの背景色 | | weather-widget-text-primary | メインのテキスト色 | | weather-widget-search-dialog-bg | 検索ダイアログの背景色 | | weather-widget-search-dialog-text | 検索ダイアログのテキスト色 | | weather-widget-chart-label | チャートのラベルの色 | | weather-widget-chart-grid | チャートのグリッドの色 |