{"id":48644022,"url":"https://github.com/wcstack/wcstack","last_synced_at":"2026-07-18T00:02:02.212Z","repository":{"id":333043826,"uuid":"1136004758","full_name":"wcstack/wcstack","owner":"wcstack","description":"Web Components Stack","archived":false,"fork":false,"pushed_at":"2026-07-14T21:55:38.000Z","size":16527,"stargazers_count":5,"open_issues_count":10,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-14T23:10:37.364Z","etag":null,"topics":["buildless","custom-elements","navigation-api","no-build","state-management","web-components"],"latest_commit_sha":null,"homepage":"https://wcstack.github.io/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wcstack.png","metadata":{"files":{"readme":"README.ja.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-16T22:54:19.000Z","updated_at":"2026-07-14T07:12:04.000Z","dependencies_parsed_at":"2026-05-03T04:04:40.870Z","dependency_job_id":null,"html_url":"https://github.com/wcstack/wcstack","commit_stats":null,"previous_names":["wcstack/wcstack"],"tags_count":70,"template":false,"template_full_name":null,"purl":"pkg:github/wcstack/wcstack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wcstack%2Fwcstack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wcstack%2Fwcstack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wcstack%2Fwcstack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wcstack%2Fwcstack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wcstack","download_url":"https://codeload.github.com/wcstack/wcstack/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wcstack%2Fwcstack/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35599510,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-17T02:00:06.162Z","response_time":116,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["buildless","custom-elements","navigation-api","no-build","state-management","web-components"],"created_at":"2026-04-10T00:08:41.716Z","updated_at":"2026-07-18T00:02:02.202Z","avatar_url":"https://github.com/wcstack.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wcstack\n\n**もしブラウザにこれが最初からあったら？**\n\nwcstack は「未来のWeb標準を想像し、ライブラリとして実装する」プロジェクトです。リアクティブなデータバインディング、宣言的ルーティング、コンポーネントの自動読み込み — これらがブラウザに最初から組み込まれていたら、どんな形になるでしょうか？\n\nフレームワークではなく、*あるべきだった* HTMLタグの実現を目指しています。\n\n---\n\n## ルール\n\nこのプロジェクトには5つの縛りがあります。これが面白さの源泉です。\n\n| # | ルール | 理由 |\n|---|--------|------|\n| 1 | **CDN一発** | `\u003cscript\u003e` タグ1つ。npm不要、バンドラー不要、設定不要。 |\n| 2 | **機能はカスタムタグで提供** | すべてがカスタム要素。`\u003cwcs-something\u003e` で表現できないなら、このプロジェクトの範囲外。 |\n| 3 | **初期ロード = タグ定義だけ** | スクリプトはカスタム要素を登録するだけ。初期化コードもブートストラップも不要。 |\n| 4 | **HTMLのセマンティクスを崩さない** | 式は `data-*` 属性とテキストノードに収まる — HTMLが拡張を許している場所だけを使う。DOM構造とセマンティクスはそのまま。 |\n| 5 | **最新のECMAScript** | 最新のJS機能を積極的に採用。ES5へのトランスパイルはしない。未来を作ってるんだから。 |\n\nこの縛り、簡単そうに見えるでしょう？　そうでもないです。\n\nHTMLのセマンティクスを崩さないためには、仕様のどこが拡張を許していて、どこが許していないかを深く理解していないと破綻する。すべてをカスタムタグで作るには、ライフサイクル・順序制御・コンポーネント間通信をCustom Elementsの仕組みの中で解決しないといけない。依存ライブラリゼロということは、すべてのアルゴリズムを自分で書くということ。そしてそのすべてが、「ブラウザ組み込みかも」と思えるクオリティでなければならない。\n\n---\n\n## 設計の核心\n\n既存のすべてのフレームワークでは、**コンポーネント**がUIと状態の出会う場所になっている。状態ストアを外部に切り出しても、コンポーネント内に状態を引き込むグルーコードを書くことになる。UIと状態は常にJavaScriptの中で結合する。\n\nwcstack は、文字通り別の **パス** を選んだ。\n\nUIと状態を結びつけている**唯一の契約（コントラクト）**は**パス文字列**です。 — `user.name`、`cart.items.*.subtotal`、`@shared`。フックもインポートも結合のためのコードもありません。コンポーネントのJavaScriptには状態を参照するコードが一切含まれていません。HTMLだけが、すべてのデータ依存関係を宣言的に記述します。\n\n```\nState  ← \"user.name\" →  UI          パスが2つのレイヤーを結ぶ\nComp A ← \"@app\" →       Comp B      名前付きパスがコンポーネントを横断する\nLoop   ← \"items.*\" →    Template    ワイルドカードがインデックスを抽象化する\n```\n\nつまり、UIを作り直しても状態に触れなくていい。状態をリファクタリングしてもDOMに触れなくていい。HTMLを読めばすべてが分かる。REST APIのURLと同じ発想 — シンプルな文字列契約、共有コードなし。\n\n---\n\n## パッケージ\n\n41個の独立したランタイムパッケージ + 1つのツール拡張パッケージ。ランタイム依存ゼロ（SSR用のhappy-domを除く）。ビルド不要。\n\n### もしHTMLにリアクティブなデータバインディングがあったら？\n\n[`@wcstack/state`](packages/state/) — 状態をインラインで宣言し、属性でDOMにバインドする。\n\n```html\n\u003cwcs-state\u003e\n  \u003cscript type=\"module\"\u003e\n    export default {\n      taxRate: 0.1,\n      cart: {\n        items: [\n          { name: \"ウィジェット\", price: 500, quantity: 2 },\n          { name: \"ガジェット\", price: 1200, quantity: 1 }\n        ]\n      },\n      removeItem(event, index) {\n        this[\"cart.items\"] = this[\"cart.items\"].toSpliced(index, 1);\n      },\n      get \"cart.items.*.subtotal\"() {\n        return this[\"cart.items.*.price\"] * this[\"cart.items.*.quantity\"];\n      },\n      get \"cart.total\"() {\n        return this.$getAll(\"cart.items.*.subtotal\", []).reduce((a, b) =\u003e a + b, 0);\n      },\n      get \"cart.grandTotal\"() {\n        return this[\"cart.total\"] * (1 + this.taxRate);\n      }\n    };\n  \u003c/script\u003e\n\u003c/wcs-state\u003e\n\n\u003ctemplate data-wcs=\"for: cart.items\"\u003e\n  \u003cdiv\u003e\n    {{ .name }} \u0026times;\n    \u003cinput type=\"number\" data-wcs=\"value: .quantity\"\u003e\n    = \u003cspan data-wcs=\"textContent: .subtotal|locale\"\u003e\u003c/span\u003e\n    \u003cbutton data-wcs=\"onclick: removeItem\"\u003e削除\u003c/button\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\u003cp\u003e合計: \u003cspan data-wcs=\"textContent: cart.grandTotal|locale(ja-JP)\"\u003e\u003c/span\u003e\u003c/p\u003e\n```\n\n- **パスgetter** — `get \"users.*.fullName\"()` あらゆる深さの算出プロパティ\n- **構造ディレクティブ** — `\u003ctemplate\u003e` による `for`、`if` / `elseif` / `else`\n- **40以上のフィルタ** — 比較、算術、文字列、日付、フォーマット\n- **双方向バインディング** — `\u003cinput\u003e`、`\u003cselect\u003e`、`\u003ctextarea\u003e` で自動\n- **Mustache構文** — テキストノード内の `{{ path|filter }}`\n- **Web Componentバインディング** — Shadow DOMとの双方向状態同期\n\n[詳細ドキュメント \u0026rarr;](packages/state/README.ja.md)\n\n---\n\n### もしルーティングがただのHTMLタグだったら？\n\n[`@wcstack/router`](packages/router/) — アプリのナビゲーション構造をマークアップで定義する。\n\n```html\n\u003cwcs-router\u003e\n  \u003ctemplate\u003e\n    \u003cwcs-route path=\"/\"\u003e\n      \u003cwcs-layout layout=\"main-layout\"\u003e\n        \u003cnav slot=\"header\"\u003e\n          \u003cwcs-link to=\"/\"\u003eホーム\u003c/wcs-link\u003e\n          \u003cwcs-link to=\"/products\"\u003e商品一覧\u003c/wcs-link\u003e\n        \u003c/nav\u003e\n        \u003cwcs-route index\u003e\n          \u003cwcs-head\u003e\u003ctitle\u003eホーム\u003c/title\u003e\u003c/wcs-head\u003e\n          \u003capp-home\u003e\u003c/app-home\u003e\n        \u003c/wcs-route\u003e\n        \u003cwcs-route path=\"products\"\u003e\n          \u003cwcs-route index\u003e\n            \u003cproduct-list\u003e\u003c/product-list\u003e\n          \u003c/wcs-route\u003e\n          \u003cwcs-route path=\":id(int)\"\u003e\n            \u003cproduct-detail data-bind=\"props\"\u003e\u003c/product-detail\u003e\n          \u003c/wcs-route\u003e\n        \u003c/wcs-route\u003e\n      \u003c/wcs-layout\u003e\n    \u003c/wcs-route\u003e\n    \u003cwcs-route fallback\u003e\n      \u003cerror-404\u003e\u003c/error-404\u003e\n    \u003c/wcs-route\u003e\n  \u003c/template\u003e\n\u003c/wcs-router\u003e\n\u003cwcs-outlet\u003e\u003c/wcs-outlet\u003e\n```\n\n- **ネストされたルート \u0026 レイアウト** — Light DOMで宣言的にUI構造を組み立て\n- **型付きパラメータ** — `:id(int)`、`:slug(slug)`、`:date(isoDate)` で自動変換\n- **自動バインディング** — `data-bind` でURLパラメータをコンポーネントに注入\n- **Head管理** — `\u003cwcs-head\u003e` でルートごとに `\u003ctitle\u003e` と `\u003cmeta\u003e` を切り替え\n- **Navigation API** — モダンな標準APIベース、popstateフォールバック付き\n- **ルートガード** — 非同期の判定関数でルートを保護\n\n[詳細ドキュメント \u0026rarr;](packages/router/README.ja.md)\n\n---\n\n### もし fetch がタグだったら？\n\n[`@wcstack/fetch`](packages/fetch/) — 宣言的な HTTP 通信をヘッドレス Web Component として。\n\n```html\n\u003cwcs-state\u003e\n  \u003cscript type=\"module\"\u003e\n    export default {\n      users: [],\n      loading: false,\n      filterRole: \"\",\n      get usersUrl() {\n        const role = this.filterRole;\n        return role ? \"/api/users?role=\" + role : \"/api/users\";\n      },\n    };\n  \u003c/script\u003e\n\u003c/wcs-state\u003e\n\n\u003c!-- URL が変わると自動的に再フェッチ --\u003e\n\u003cwcs-fetch data-wcs=\"url: usersUrl; value: users; loading: loading\"\u003e\u003c/wcs-fetch\u003e\n\n\u003ctemplate data-wcs=\"if: loading\"\u003e\n  \u003cp\u003e読み込み中...\u003c/p\u003e\n\u003c/template\u003e\n\u003ctemplate data-wcs=\"for: users\"\u003e\n  \u003cdiv data-wcs=\"textContent: .name\"\u003e\u003c/div\u003e\n\u003c/template\u003e\n```\n\n- **CSBC アーキテクチャ** — Core / Shell / Binding Contract 分離\n- **wc-bindable-protocol** — React、Vue、Svelte、Solid と薄いアダプタで連携\n- **URL 監視** — バインドされた URL の変更で自動再フェッチ\n- **trigger プロパティ** — 状態から宣言的に fetch 実行、DOM 参照不要\n- **HTML リプレースモード** — htmx 的な `target` 属性でサーバーレンダリング断片を差し替え\n- **ヘッドレス Core** — `FetchCore` は Node.js、Deno、Cloudflare Workers で動作\n\n[詳細ドキュメント \u0026rarr;](packages/fetch/README.ja.md)\n\n---\n\n### もしカスタム要素が勝手に読み込まれたら？\n\n[`@wcstack/autoloader`](packages/autoloader/) — タグを書くだけで読み込まれる。登録コード不要。\n\n```html\n\u003cscript type=\"importmap\"\u003e\n  {\n    \"imports\": {\n      \"@components/ui/\": \"./components/ui/\",\n      \"@components/ui|lit/\": \"./components/ui-lit/\"\n    }\n  }\n\u003c/script\u003e\n\n\u003c!-- ./components/ui/button.js から自動読み込み --\u003e\n\u003cui-button\u003e\u003c/ui-button\u003e\n\n\u003c!-- Litローダーで ./components/ui-lit/card.js から自動読み込み --\u003e\n\u003cui-lit-card\u003e\u003c/ui-lit-card\u003e\n```\n\n- **Import Mapベース** — 名前空間解決、コンポーネントごとの登録不要\n- **即時 \u0026 遅延読み込み** — 重要なコンポーネントを先に、残りはオンデマンドで\n- **MutationObserver** — 動的に追加された要素も自動検知\n- **プラガブルローダー** — Vanilla、Lit、カスタムローダーを混在可能\n- **`is` 属性** — カスタマイズされた組み込み要素の `extends` 自動検出\n\n[詳細ドキュメント \u0026rarr;](packages/autoloader/README.ja.md)\n\n---\n\n### もしテンプレートがサーバーでレンダリングされたら？\n\n[`@wcstack/server`](packages/server/) — 同じHTML、サーバーでレンダリング。特別な構文不要。\n\n```javascript\nimport { renderToString } from \"@wcstack/server\";\n\nconst html = await renderToString(`\n  \u003cwcs-state enable-ssr\u003e\n    \u003cscript type=\"module\"\u003e\n      export default {\n        items: [],\n        async $connectedCallback() {\n          const res = await fetch(\"/api/items\");\n          this.items = await res.json();\n        }\n      };\n    \u003c/script\u003e\n  \u003c/wcs-state\u003e\n  \u003ctemplate data-wcs=\"for: items\"\u003e\n    \u003cdiv data-wcs=\"textContent: items.*.name\"\u003e\u003c/div\u003e\n  \u003c/template\u003e\n`);\n```\n\n- **ドロップインSSR** — `\u003cwcs-state\u003e` に `enable-ssr` を追加して `renderToString()` を呼ぶだけ\n- **自動ハイドレーション** — クライアントがサーバーの続きをシームレスに引き継ぎ、フリッカーなし\n- **相対URL自動解決** — `baseUrl` オプションで `fetch(\"/api/...\")` がサーバー上でも動作\n- **バージョン安全フォールバック** — バージョン不一致時はDOMをクリーンアップしてCSRにフォールバック\n- **`\u003cwcs-ssr\u003e` ハイドレーションデータ** — 状態スナップショット、テンプレート、プロパティを1要素に集約\n\n[詳細ドキュメント \u0026rarr;](packages/server/README.ja.md)\n\n---\n\n### 追加パッケージ\n\n- [`@wcstack/websocket`](packages/websocket/) — `\u003cwcs-ws\u003e` でリアルタイム通信を宣言的に扱い、接続状態や受信データをバインド可能。\n- [`@wcstack/upload`](packages/upload/) — ファイルアップロードを宣言的に記述し、進捗・状態管理をフレームワーク非依存で提供。\n- [`@wcstack/storage`](packages/storage/) — `\u003cwcs-storage\u003e` で localStorage / sessionStorage と状態を宣言的に同期。\n- [`@wcstack/timer`](packages/timer/) — `\u003cwcs-timer\u003e` で時刻経過やポーリングを宣言的な状態変化として扱う。\n- [`@wcstack/raf`](packages/raf/) — `\u003cwcs-raf\u003e` で requestAnimationFrame を宣言的に。フレーム tick・一級の `dt`・非表示タブの `suspended` 出力。\n- [`@wcstack/geolocation`](packages/geolocation/) — `\u003cwcs-geo\u003e` で位置情報を宣言的に扱い、単発/継続取得、精度、ライブな権限状態を提供。\n- [`@wcstack/debounce`](packages/debounce/) — `\u003cwcs-debounce\u003e` と `\u003cwcs-throttle\u003e` で値・シグナルのストリームをまとめる debounce/throttle を宣言的に。\n- [`@wcstack/clipboard`](packages/clipboard/) — `\u003cwcs-clipboard\u003e` でクリップボードの読み書き、リッチな `ClipboardItem`、copy/cut/paste 監視、ライブな権限状態を宣言的に。\n- [`@wcstack/broadcast`](packages/broadcast/) — `\u003cwcs-broadcast\u003e` で同一オリジンの BroadcastChannel による pub/sub をバインド可能な状態としてタブ間メッセージング。\n- [`@wcstack/worker`](packages/worker/) — `\u003cwcs-worker\u003e` で重い処理をバックグラウンドスレッドに退避し、message/error/running 状態をバインド可能に。\n- [`@wcstack/sse`](packages/sse/) — `\u003cwcs-sse\u003e` で Server-Sent Events（EventSource）による一方向ストリーミングを、message/接続状態をバインド可能な状態として、名前付きイベント対応で。\n- [`@wcstack/intersection`](packages/intersection/) — `\u003cwcs-intersect\u003e` で遅延読み込み・無限スクロール・スクロールスパイを、可視状態をバインド可能な IntersectionObserver として。\n- [`@wcstack/wakelock`](packages/wakelock/) — `\u003cwcs-wakelock\u003e` で Screen Wake Lock を宣言的に。バインドした boolean が true の間スクリーンを起こしたままにし、visibility 変化をまたいで再取得する。\n- [`@wcstack/resize`](packages/resize/) — `\u003cwcs-resize\u003e` で要素サイズ・コンテナ幅の測定・サイズ依存ロジックを、バインド可能な状態として ResizeObserver で。\n- [`@wcstack/speech`](packages/speech/) — `\u003cwcs-speak\u003e`（text-to-speech を command-token として）と `\u003cwcs-listen\u003e`（認識結果を event-token 状態として）で音声を宣言的に。\n- [`@wcstack/permission`](packages/permission/) — `\u003cwcs-permission\u003e` で Permissions API を監視し、ライブな `granted`/`denied`/`prompt` 状態を公開。読み取り専用ウォッチャー（コマンドなし）で、`\u003cwcs-geo\u003e` などの機能ノードと組み合わせる。\n- [`@wcstack/network`](packages/network/) — `\u003cwcs-network\u003e` で Network Information を監視し、アダプティブ読み込み向けにライブな `effectiveType`/`downlink`/`rtt`/`saveData` 状態を公開。読み取り専用ウォッチャー（コマンド・属性なし）で、非対応（Firefox/Safari）がエッジケースではなく常態。\n- [`@wcstack/screen-orientation`](packages/screen-orientation/) — `\u003cwcs-screen-orientation\u003e` で画面の向きを監視し `lock`/`unlock` コマンドを提供、`type`/`angle`/`portrait`/`landscape` を公開。監視は同期のため `_gen` ガード不要、`lock()` は非同期のため必要（監視とは独立）。\n- [`@wcstack/fullscreen`](packages/fullscreen/) — `\u003cwcs-fullscreen target=\"...\"\u003e` で Fullscreen API を宣言的に。`\u003cwcs-intersect\u003e` の target 解決パターンを再利用し、`active` は解決した target が document の `fullscreenElement` かを追跡。\n- [`@wcstack/picture-in-picture`](packages/picture-in-picture/) — `\u003cwcs-pip target=\"...\"\u003e`（target は `\u003cvideo\u003e` 要素）で Picture-in-Picture を宣言的に。`\u003cwcs-fullscreen\u003e` と同じ target 解決パターン。\n- [`@wcstack/pointer-lock`](packages/pointer-lock/) — `\u003cwcs-pointer-lock target=\"...\"\u003e` でゲームや canvas UI 向けの Pointer Lock を。`movementX`/`movementY` は v1 では意図的に対象外（必要なら後日 `@wcstack/debounce`/`@wcstack/throttle` と組み合わせ）。\n- [`@wcstack/share`](packages/share/) — `\u003cwcs-share\u003e` で Web Share API を宣言的に。`share(data)` コマンド、`value`/`loading`/`error`/`cancelled` 状態。`cancelled`（ユーザーが共有シートを閉じた）は `error`（真の失敗）と区別。\n- [`@wcstack/eyedropper`](packages/eyedropper/) — `\u003cwcs-eyedropper\u003e` で EyeDropper API（デスクトップのカラーピッカー）を。`open()`/`abort()` コマンド、`value` は `{ sRGBHex }`。`\u003cwcs-share\u003e` と同じ `value`/`loading`/`error`/`cancelled` の形。\n- [`@wcstack/contacts`](packages/contacts/) — `\u003cwcs-contacts\u003e` で Contact Picker API を。`select(properties, options)` コマンド（Android Chrome のみ — それ以外は非対応が既定）。`value` は `multiple: false` でも常に配列。\n- [`@wcstack/credential`](packages/credential/) — `\u003cwcs-credential\u003e` で Credential Management（パスワード/フェデレーションのみ — WebAuthn は明確に対象外）を。`get(options)`/`store(credential)` コマンドが1つの `_gen` を共有（文書化済みの並行性制限）。\n- [`@wcstack/idle`](packages/idle/) — `\u003cwcs-idle\u003e` で Idle Detection を。ジェスチャ必須の `requestPermission()` + `start`/`stop`、`userState`/`screenState`/`active` を公開。権限状態は重複させず `\u003cwcs-permission name=\"idle-detection\"\u003e` と組み合わせる。接続時に自動開始しない。\n- [`@wcstack/tilt`](packages/tilt/) — `\u003cwcs-tilt\u003e` で Device Orientation を。iOS のジェスチャ必須 `requestPermission()`（他環境では no-op）を吸収し、どこでも同じフローで書ける。`permissionState` はローカルで追跡する3値語彙（対応する Permissions API エントリが存在しない）。\n- [`@wcstack/accelerometer`](packages/accelerometer/) / [`@wcstack/gyroscope`](packages/gyroscope/) / [`@wcstack/magnetometer`](packages/magnetometer/) / [`@wcstack/ambient-light-sensor`](packages/ambient-light-sensor/) — Generic Sensor API ファミリ。`\u003cwcs-accelerometer\u003e`/`\u003cwcs-gyroscope\u003e`/`\u003cwcs-magnetometer\u003e` は `x`/`y`/`z` を、`\u003cwcs-ambient-light-sensor\u003e` は単一の `illuminance` スカラーを公開（ブラウザ対応が最も弱く、フィンガープリンティング対策で無効化しているブラウザもある）。4つとも権限状態を重複させず `\u003cwcs-permission name=\"...\"\u003e` と組み合わせ、ガード付きセンサーコンストラクタ呼び出し以外に `_gen` ガードは不要（同期的な start/stop）。\n- [`@wcstack/notification`](packages/notification/) — `\u003cwcs-notify\u003e` でデスクトップ通知を宣言的に。command-token（`notify`）で表示し、event-token（`clicked`）でクリックを受け取る — 双方向を1タグで。権限は自己完結、モバイル向けに Service Worker フォールバック。\n- [`@wcstack/defined`](packages/defined/) — `\u003cwcs-defined\u003e` でカスタム要素の準備完了を。タグ集合の `whenDefined()` を監視し `defined`/`pending`/`missing`/`count`/`total` 状態を公開、タイムアウトによる読み込み失敗検知付き。autoloader の相棒で、CSS `:defined` にできないことを実現。\n- [`@wcstack/camera`](packages/camera/) — `\u003cwcs-camera\u003e`（getUserMedia + 組み込みプレビュー）と `\u003cwcs-recorder\u003e`（MediaRecorder）でカメラ撮影・録画を宣言的に。ライブな `MediaStream` は command-token 引数で要素へ直接バインドし、**シリアライズ可能な状態には決して格納しない** — 派生値（権限、録画フラグ、録画した `Blob`/URL）だけが状態を流れる。\n- [`@wcstack/signals`](packages/signals/) — シグナルベースのきめ細かいリアクティブ**コア**（`@wcstack/state` の JS ファースト版）。`signal`/`computed`/`effect`、非同期の `resource`/`streamResource`、keyed な `For`/`Index`、同じ wc-bindable IO ノードをシグナル経由で駆動する `bindNode` アダプタ。TC39-Signals 準拠、依存ゼロ。\n- [`@wcstack/devtools`](packages/devtools/) — `\u003cwcs-devtools\u003e` によるページ内 DevTools オーバーレイ。state ツリーの検査（通常のリアクティブパイプラインを通るインライン編集付き）、各パスがどの DOM ノードに配線されているかの表示、write / 更新バッチ / command・event トークン発火のライブタイムライン — 購読者ゼロの「空撃ち」警告付き。`\u003cscript\u003e` 一行、DevTools Hook Protocol で接続、依存ゼロ。\n- [`wcstack-intellisense`](packages/vscode-wcs/) — `\u003cwcs-state\u003e` インラインスクリプト向けの VS Code 言語サポート拡張。\n\n---\n\n## Quick Start\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n  \u003cscript type=\"module\" src=\"https://esm.run/@wcstack/state/auto\"\u003e\u003c/script\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\n\u003cwcs-state\u003e\n  \u003cscript type=\"module\"\u003e\n    export default {\n      count: 0,\n      countUp() { this.count++; }\n    };\n  \u003c/script\u003e\n\u003c/wcs-state\u003e\n\n\u003cp\u003eCount: {{ count }}\u003c/p\u003e\n\u003cbutton data-wcs=\"onclick: countUp\"\u003e+1\u003c/button\u003e\n\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n`\u003cscript\u003e` タグ1つ。カスタム要素1つ。あとはHTML。以上。\n\n---\n\n## コンポーネント状態で CSS を切り替える — `:state()`\n\n全 I/O ノードは boolean の出力状態（`loading` / `connected` / `error` / `granted` など）を [CustomStateSet](https://developer.mozilla.org/ja/docs/Web/API/CustomStateSet) に反映します。JavaScript を書かずに、CSS だけでコンポーネントの状態に反応できます:\n\n```css\nwcs-fetch:state(loading) ~ .spinner    { display: block; }\nform:has(wcs-fetch:state(error)) .msg  { display: block; }\nwcs-ws:state(connected) ~ .indicator   { color: limegreen; }\nwcs-permission:state(denied) ~ .help   { display: block; }\n```\n\n各パッケージの README に反映される状態の一覧があります。対応ブラウザは Chrome/Edge 125+・Safari 17.4+・Firefox 126+。非対応ブラウザではスタイルが当たらないだけで、コンポーネントの機能は完全に動作します。SSR 出力には状態がシリアライズされません（初期描画のスタイリングには `wcs-x:not(:defined)` を併用してください）。\n\nデバッグ時はタグに `debug-states` 属性を付けると、状態が `data-wcs-state-*` 属性としてミラーされ、DevTools の Elements パネルでリアルタイムに観測できます（`debugStates` プロパティでも読めます）。本番の CSS はこの属性ではなく `:state()` に書いてください。\n\n---\n\n## プロジェクト構成\n\n```\nwcstack/\n├── packages/\n│   ├── state/         # @wcstack/state\n│   ├── router/        # @wcstack/router\n│   ├── fetch/         # @wcstack/fetch\n│   ├── autoloader/    # @wcstack/autoloader\n│   ├── server/        # @wcstack/server\n│   ├── storage/       # @wcstack/storage\n│   ├── timer/         # @wcstack/timer\n│   ├── raf/           # @wcstack/raf\n│   ├── geolocation/   # @wcstack/geolocation\n│   ├── websocket/     # @wcstack/websocket\n│   ├── upload/        # @wcstack/upload\n│   ├── debounce/      # @wcstack/debounce\n│   ├── clipboard/     # @wcstack/clipboard\n│   ├── broadcast/     # @wcstack/broadcast\n│   ├── worker/        # @wcstack/worker\n│   ├── sse/           # @wcstack/sse\n│   ├── intersection/  # @wcstack/intersection\n│   ├── wakelock/      # @wcstack/wakelock\n│   ├── resize/        # @wcstack/resize\n│   ├── speech/        # @wcstack/speech\n│   ├── permission/    # @wcstack/permission\n│   ├── network/       # @wcstack/network\n│   ├── screen-orientation/     # @wcstack/screen-orientation\n│   ├── fullscreen/             # @wcstack/fullscreen\n│   ├── picture-in-picture/     # @wcstack/picture-in-picture\n│   ├── pointer-lock/           # @wcstack/pointer-lock\n│   ├── share/                  # @wcstack/share\n│   ├── eyedropper/             # @wcstack/eyedropper\n│   ├── contacts/               # @wcstack/contacts\n│   ├── credential/             # @wcstack/credential\n│   ├── idle/                   # @wcstack/idle\n│   ├── tilt/                   # @wcstack/tilt\n│   ├── accelerometer/          # @wcstack/accelerometer\n│   ├── gyroscope/              # @wcstack/gyroscope\n│   ├── magnetometer/           # @wcstack/magnetometer\n│   ├── ambient-light-sensor/   # @wcstack/ambient-light-sensor\n│   ├── notification/  # @wcstack/notification\n│   ├── defined/       # @wcstack/defined\n│   ├── camera/        # @wcstack/camera\n│   ├── signals/       # @wcstack/signals\n│   ├── devtools/      # @wcstack/devtools\n│   └── vscode-wcs/    # wcstack-intellisense (VS Code拡張)\n```\n\n各パッケージは独立してビルド・テスト・公開されます。\n\n`examples/` 配下のデモは、このリポジトリに残っている package に対応します。旧 AI/Auth0 デモは `@csbc-dev/ai-agent` と `@csbc-dev/auth0` へ移動したため、このリポジトリには含めていません。従来の npm package である `@wcstack/ai` と `@wcstack/auth0` は deprecated 扱いです。\n\n## 開発\n\n各パッケージのディレクトリ内で実行します（例: `packages/state/`）:\n\n```bash\nnpm run build            # dist削除、TypeScriptコンパイル、Rollupバンドル\nnpm test                 # テスト実行 (Vitest)\nnpm run test:coverage    # カバレッジ（statements/functions/lines は100%、branches は97%以上）\nnpm run lint             # ESLint\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwcstack%2Fwcstack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwcstack%2Fwcstack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwcstack%2Fwcstack/lists"}