@wcstack/geolocation 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ja.md ADDED
@@ -0,0 +1,158 @@
1
+ # @wcstack/geolocation
2
+
3
+ `@wcstack/geolocation` は wcstack エコシステム向けのヘッドレスな位置情報コンポーネントです。
4
+
5
+ これは視覚的な UI ウィジェットではありません。
6
+ `@wcstack/fetch` がネットワークリクエストをリアクティブな状態に変え、`@wcstack/timer` が時間の経過をリアクティブな状態に変えるのと同じように、**デバイスの位置情報をリアクティブな状態に変える非同期プリミティブノード**です。
7
+
8
+ `@wcstack/state` と組み合わせると、`<wcs-geo>` はパス契約を通じて直接バインドできます。
9
+
10
+ - **入力 / コマンド面**: `high-accuracy`, `timeout`, `maximum-age`, `watch`, `manual`, `trigger`
11
+ - **出力状態面**: `position`, `latitude`, `longitude`, `accuracy`, `coords`, `timestamp`, `watching`, `loading`, `error`, `permission`
12
+
13
+ つまり、位置情報を扱う処理を HTML 上で宣言的に表現でき、UI 層に `navigator.geolocation.getCurrentPosition()` / `watchPosition()` / `clearWatch()` や後始末のグルーコードを書く必要がありません。
14
+
15
+ `@wcstack/geolocation` は [CSBC](https://github.com/csbc-dev/arch/blob/main/README.md)(Core / Shell / Binding Contract)アーキテクチャに従います。
16
+
17
+ - **Core**(`GeolocationCore`)が位置取得、一発取得 / 連続監視の二相、位置の正規化、エラー処理、パーミッションのライブ追跡を担当
18
+ - **Shell**(`<wcs-geo>`)がその状態を DOM 属性・ライフサイクル・宣言的コマンドに接続
19
+ - **Binding Contract**(`static wcBindable`)が観測可能な `properties`・書き込み可能な `inputs`・呼び出し可能な `commands` を宣言
20
+
21
+ ## なぜ存在するのか
22
+
23
+ 位置情報は `fetch` と同様、値を非同期に生み出すソースですが、加えて**パーミッションのゲート**と**連続監視モード**を持ちます。命令的に書くと、コールバック配線・パーミッション照会・切断時の後始末が必要になります。
24
+
25
+ `@wcstack/geolocation` はそのロジックを再利用可能なコンポーネントに押し込み、結果をバインド可能な状態として公開します。位置の取得が命令的なコールバック配線ではなく、**状態遷移**になります。これは読み取り専用センサであり、要素は状態へ値を生み出すだけ(`element → state`)で、逆向きの「送信」経路はありません。
26
+
27
+ > **セキュアコンテキストが必須。** Geolocation API はセキュアコンテキスト(HTTPS、または `localhost`)でのみ動作します。non-localhost オリジンの平文 HTTP では取得が失敗し、`<wcs-geo>` は `error` として表面化します。正確なコードはブラウザ依存です。`navigator.geolocation` 自体が存在しない場合のみ `<wcs-geo>` は `POSITION_UNAVAILABLE`(code `2`)を報告しますが、多くのブラウザは `navigator.geolocation` を存在させたままリクエストを拒否するため、エラーは通常 `PERMISSION_DENIED`(code `1`)として届きます。単一のコードで分岐するのではなく、`error` をバインドして失敗を扱ってください。
28
+
29
+ ## インストール
30
+
31
+ ```bash
32
+ npm install @wcstack/geolocation
33
+ ```
34
+
35
+ ## クイックスタート
36
+
37
+ ### 1. 接続時に一発取得(既定)
38
+
39
+ `<wcs-geo>` が DOM に接続されると、単一の位置 fix を要求して結果を公開します。
40
+
41
+ ```html
42
+ <script type="module" src="https://esm.run/@wcstack/state/auto"></script>
43
+ <script type="module" src="https://esm.run/@wcstack/geolocation/auto"></script>
44
+
45
+ <wcs-state>
46
+ <script type="module">
47
+ export default {
48
+ lat: null,
49
+ lng: null,
50
+ get label() {
51
+ return this.lat == null ? "Locating…" : `${this.lat}, ${this.lng}`;
52
+ }
53
+ };
54
+ </script>
55
+ </wcs-state>
56
+
57
+ <wcs-geo data-wcs="latitude: lat; longitude: lng"></wcs-geo>
58
+
59
+ <p data-wcs="textContent: label"></p>
60
+ ```
61
+
62
+ ### 2. 連続監視
63
+
64
+ `watch` 属性を付けると、要素が切断されるまで `watchPosition` を通じて fix をストリームします。
65
+
66
+ ```html
67
+ <wcs-geo watch data-wcs="latitude: lat; longitude: lng; watching: isTracking"></wcs-geo>
68
+ ```
69
+
70
+ ### 3. 高精度 / オプション
71
+
72
+ ```html
73
+ <wcs-geo high-accuracy timeout="10000" maximum-age="0"
74
+ data-wcs="coords: position; error: geoError"></wcs-geo>
75
+ ```
76
+
77
+ ### 4. 必要なときに手動取得
78
+
79
+ `manual` は接続時の自動取得をスキップします。命令的に、DOM のクリックで、あるいは状態から取得を起動できます。
80
+
81
+ ```html
82
+ <wcs-geo id="loc" manual data-wcs="latitude: lat; longitude: lng"></wcs-geo>
83
+
84
+ <!-- DOM トリガ(任意): クリックで一発取得を要求 -->
85
+ <button data-geotarget="loc">Locate me</button>
86
+ ```
87
+
88
+ > `data-geotarget` のクリックはモードに関わらず、常に `getCurrentPosition()` による**単一**の fix を要求します。`watch` 要素に向けた場合は、監視を再起動するのではなく、継続中の監視と並行して一発取得が走ります(その間だけ `loading` がトグルします)。本来の対象は `manual` 要素です。
89
+
90
+ ## 属性 / 入力(Attributes / Inputs)
91
+
92
+ | 属性 | 型 | 既定値 | 説明 |
93
+ | --------------- | ------- | ---------- | ----------------------------------------------------------------------- |
94
+ | `high-accuracy` | boolean | `false` | 可能な限り高精度な結果を要求する(`enableHighAccuracy`)。 |
95
+ | `timeout` | number | `Infinity` | fix を待つ最大ミリ秒。不正な値は `Infinity` にフォールバック。 |
96
+ | `maximum-age` | number | `0` | 許容するキャッシュ済み fix の最大経過時間(ms)。不正な値は `0` にフォールバック。 |
97
+ | `watch` | boolean | `false` | 接続時に単一取得ではなく位置を連続監視する。 |
98
+ | `manual` | boolean | `false` | 接続時に自動取得しない。コマンド / トリガで取得する。 |
99
+
100
+ ## 観測可能なプロパティ(出力)
101
+
102
+ | プロパティ | イベント | 説明 |
103
+ | ------------ | ------------------------------ | --------------------------------------------------------------------- |
104
+ | `position` | `wcs-geo:position` | 正規化されたスナップショット `{ latitude, longitude, accuracy, altitude, altitudeAccuracy, heading, speed, timestamp, coords }`。 |
105
+ | `latitude` | `wcs-geo:position` | 最新 fix の緯度。 |
106
+ | `longitude` | `wcs-geo:position` | 最新 fix の経度。 |
107
+ | `accuracy` | `wcs-geo:position` | 最新 fix の精度(メートル)。 |
108
+ | `coords` | `wcs-geo:position` | 最新 fix の座標サブオブジェクト。 |
109
+ | `timestamp` | `wcs-geo:position` | 最新 fix の取得タイムスタンプ。 |
110
+ | `watching` | `wcs-geo:watching-changed` | 連続監視中は `true`、それ以外は `false`。 |
111
+ | `loading` | `wcs-geo:loading-changed` | 一発取得 `getCurrentPosition` のリクエスト中は `true`。 |
112
+ | `error` | `wcs-geo:error` | 正規化された `{ code, message }`(`PERMISSION_DENIED=1`, `POSITION_UNAVAILABLE=2`, `TIMEOUT=3`)。 |
113
+ | `permission` | `wcs-geo:permission-changed` | `"prompt"` / `"granted"` / `"denied"` / `"unsupported"`。Permissions API でライブ追跡。 |
114
+
115
+ ## コマンド
116
+
117
+ | コマンド | 説明 |
118
+ | ------------------- | ----------------------------------------------------------------- |
119
+ | `getCurrentPosition`| 単一の fix を取得(非同期。reject しない — 失敗は `error` へ)。 |
120
+ | `watchPosition` | 連続監視を開始(既に監視中なら no-op)。 |
121
+ | `clearWatch` | 監視を停止。`watching` が `false` になる。 |
122
+
123
+ 状態からの起動には command-token プロトコルを使います。
124
+
125
+ ```html
126
+ <wcs-geo manual data-wcs="command.getCurrentPosition: $command.locate"></wcs-geo>
127
+ ```
128
+
129
+ ## 注意点と制約
130
+
131
+ - **属性は接続時に読み取られ、監視されない。** `<wcs-geo>` は `observedAttributes` / `attributeChangedCallback` を実装していません。オプション属性(`high-accuracy`, `timeout`, `maximum-age`, `watch`, `manual`)は要素の接続時とコマンド実行のたびに読み取られます。接続*後*に命令的に変更しても、それだけでは再取得・再監視は行われません。新しいオプションを反映するには、`getCurrentPosition()` / `clearWatch()` + `watchPosition()` を再度呼ぶか、要素を再接続してください。
132
+ - **再接続で再取得する。** 要素を削除して再挿入すると `connectedCallback` が再度実行されるため、既定モードの要素は新しい fix を取得し、`watch` 要素は監視を再開します(切断時に監視を解体するのと対称です)。
133
+ - **SSR(`@wcstack/server`)。** 既定の一発取得モードは `static hasConnectedCallbackPromise = true` を宣言し `connectedCallbackPromise` を公開するため、サーバレンダラはスナップショット前に接続時の fix を待機します。(`watch` / `manual` モードには待つべき接続時 fix がありません。)
134
+ - **`timeout` / `maximum-age` のパース。** 値は厳密にパースされます。数値でない(`"10px"`)・有限でない・負の値は既定値(`Infinity` / `0`)にフォールバックします。クリーンな非負数のみが受け入れられます。
135
+ - **無言のエラー処理(ゼロログ)。** wcstack 全体のゼロ依存・最小主義に従い、`<wcs-geo>` は実行時の失敗に対して一切ログ出力も throw もしません。パーミッション照会の失敗(`geolocation` パーミッション名を拒否するブラウザや Permissions API を持たない環境など)は無言で `permission = "unsupported"` にフォールバックします。取得の失敗(`PERMISSION_DENIED` / `POSITION_UNAVAILABLE` / `TIMEOUT`、および Geolocation API の欠如を含む)は `error` プロパティ / `wcs-geo:error` イベントを通じてのみ表面化します — `getCurrentPosition()` は resolve し、決して reject しません。これらの状況を観測・対処するには `error`(および `permission`)をバインドしてください。
136
+
137
+ ## ヘッドレス利用(`GeolocationCore`)
138
+
139
+ Core は DOM に依存せず、`@wc-bindable/core` の `bind()` と直接組み合わせて使えます。
140
+
141
+ ```typescript
142
+ import { GeolocationCore } from "@wcstack/geolocation";
143
+
144
+ const geo = new GeolocationCore();
145
+ geo.addEventListener("wcs-geo:position", (e) => {
146
+ console.log((e as CustomEvent).detail); // { latitude, longitude, accuracy, ... }
147
+ });
148
+
149
+ await geo.getCurrentPosition({ enableHighAccuracy: true });
150
+ // または、連続更新の場合:
151
+ geo.watch();
152
+ // ...後で
153
+ geo.clearWatch();
154
+ ```
155
+
156
+ ## ライセンス
157
+
158
+ MIT
package/README.md ADDED
@@ -0,0 +1,158 @@
1
+ # @wcstack/geolocation
2
+
3
+ `@wcstack/geolocation` is a headless geolocation component for the wcstack ecosystem.
4
+
5
+ It is not a visual UI widget.
6
+ It is an **async primitive node** that turns the device's location into reactive state — the same way `@wcstack/fetch` turns a network request into reactive state and `@wcstack/timer` turns the passage of time into reactive state.
7
+
8
+ With `@wcstack/state`, `<wcs-geo>` can be bound directly through path contracts:
9
+
10
+ - **input / command surface**: `high-accuracy`, `timeout`, `maximum-age`, `watch`, `manual`, `trigger`
11
+ - **output state surface**: `position`, `latitude`, `longitude`, `accuracy`, `coords`, `timestamp`, `watching`, `loading`, `error`, `permission`
12
+
13
+ This means location-aware work can be expressed declaratively in HTML, without writing `navigator.geolocation.getCurrentPosition()`, `watchPosition()`, `clearWatch()`, or teardown glue in your UI layer.
14
+
15
+ `@wcstack/geolocation` follows the [CSBC](https://github.com/csbc-dev/arch/blob/main/README.md) (Core / Shell / Binding Contract) architecture:
16
+
17
+ - **Core** (`GeolocationCore`) handles acquisition, the one-shot / watch phases, position normalization, error handling, and live permission tracking
18
+ - **Shell** (`<wcs-geo>`) connects that state to DOM attributes, lifecycle, and declarative commands
19
+ - **Binding Contract** (`static wcBindable`) declares observable `properties`, writable `inputs`, and callable `commands`
20
+
21
+ ## Why this exists
22
+
23
+ Geolocation is, like `fetch`, an asynchronous source of values — but it also has a permission gate and a continuous-watch mode. Imperatively it requires callback wiring, permission queries, and cleanup on disconnect.
24
+
25
+ `@wcstack/geolocation` moves that logic into a reusable component and exposes the result as bindable state. A location fix becomes a **state transition**, not imperative callback wiring. It is a read-only sensor: the element only produces values for the state (`element → state`), with no "send" path back.
26
+
27
+ > **Secure context required.** The Geolocation API only works in a secure context (HTTPS, or `localhost`). Over plain HTTP on a non-localhost origin acquisition fails and `<wcs-geo>` surfaces an `error`. The exact code is browser-dependent: only when `navigator.geolocation` itself is absent does `<wcs-geo>` report `POSITION_UNAVAILABLE` (code `2`); most browsers keep `navigator.geolocation` present and reject the request, so the error usually arrives as `PERMISSION_DENIED` (code `1`). Bind `error` and handle the failure rather than switching on a single code.
28
+
29
+ ## Install
30
+
31
+ ```bash
32
+ npm install @wcstack/geolocation
33
+ ```
34
+
35
+ ## Quick Start
36
+
37
+ ### 1. One-shot fix on connect (default)
38
+
39
+ When `<wcs-geo>` is connected to the DOM, it requests a single position fix and publishes the result.
40
+
41
+ ```html
42
+ <script type="module" src="https://esm.run/@wcstack/state/auto"></script>
43
+ <script type="module" src="https://esm.run/@wcstack/geolocation/auto"></script>
44
+
45
+ <wcs-state>
46
+ <script type="module">
47
+ export default {
48
+ lat: null,
49
+ lng: null,
50
+ get label() {
51
+ return this.lat == null ? "Locating…" : `${this.lat}, ${this.lng}`;
52
+ }
53
+ };
54
+ </script>
55
+ </wcs-state>
56
+
57
+ <wcs-geo data-wcs="latitude: lat; longitude: lng"></wcs-geo>
58
+
59
+ <p data-wcs="textContent: label"></p>
60
+ ```
61
+
62
+ ### 2. Continuous watch
63
+
64
+ Add the `watch` attribute to stream fixes via `watchPosition` until the element is disconnected.
65
+
66
+ ```html
67
+ <wcs-geo watch data-wcs="latitude: lat; longitude: lng; watching: isTracking"></wcs-geo>
68
+ ```
69
+
70
+ ### 3. High accuracy / options
71
+
72
+ ```html
73
+ <wcs-geo high-accuracy timeout="10000" maximum-age="0"
74
+ data-wcs="coords: position; error: geoError"></wcs-geo>
75
+ ```
76
+
77
+ ### 4. Manual acquisition on demand
78
+
79
+ `manual` skips the auto fix on connect. Trigger acquisition imperatively, via a DOM click, or from state.
80
+
81
+ ```html
82
+ <wcs-geo id="loc" manual data-wcs="latitude: lat; longitude: lng"></wcs-geo>
83
+
84
+ <!-- Optional DOM triggering: click requests a one-shot fix -->
85
+ <button data-geotarget="loc">Locate me</button>
86
+ ```
87
+
88
+ > A `data-geotarget` click always requests a **single** fix via `getCurrentPosition()`, regardless of mode. Pointing it at a `watch` element runs a one-shot fix (briefly toggling `loading`) alongside the ongoing watch, rather than restarting the watch. The intended target is a `manual` element.
89
+
90
+ ## Attributes / Inputs
91
+
92
+ | Attribute | Type | Default | Description |
93
+ | --------------- | ------- | ---------- | ----------------------------------------------------------------------- |
94
+ | `high-accuracy` | boolean | `false` | Request the best possible results (`enableHighAccuracy`). |
95
+ | `timeout` | number | `Infinity` | Max ms to wait for a fix. Invalid values fall back to `Infinity`. |
96
+ | `maximum-age` | number | `0` | Max age (ms) of an acceptable cached fix. Invalid values fall back to `0`. |
97
+ | `watch` | boolean | `false` | Continuously watch the position on connect instead of a single fix. |
98
+ | `manual` | boolean | `false` | Do not auto-acquire on connect; acquire via command / trigger. |
99
+
100
+ ## Observable Properties (outputs)
101
+
102
+ | Property | Event | Description |
103
+ | ------------ | ------------------------------ | --------------------------------------------------------------------- |
104
+ | `position` | `wcs-geo:position` | Normalized snapshot `{ latitude, longitude, accuracy, altitude, altitudeAccuracy, heading, speed, timestamp, coords }`. |
105
+ | `latitude` | `wcs-geo:position` | Latitude of the latest fix. |
106
+ | `longitude` | `wcs-geo:position` | Longitude of the latest fix. |
107
+ | `accuracy` | `wcs-geo:position` | Accuracy in meters of the latest fix. |
108
+ | `coords` | `wcs-geo:position` | The coordinates sub-object of the latest fix. |
109
+ | `timestamp` | `wcs-geo:position` | Acquisition timestamp of the latest fix. |
110
+ | `watching` | `wcs-geo:watching-changed` | `true` while continuously watching, `false` otherwise. |
111
+ | `loading` | `wcs-geo:loading-changed` | `true` during a one-shot `getCurrentPosition` request. |
112
+ | `error` | `wcs-geo:error` | Normalized `{ code, message }` (`PERMISSION_DENIED=1`, `POSITION_UNAVAILABLE=2`, `TIMEOUT=3`). |
113
+ | `permission` | `wcs-geo:permission-changed` | `"prompt"` / `"granted"` / `"denied"` / `"unsupported"`, tracked live via the Permissions API. |
114
+
115
+ ## Commands
116
+
117
+ | Command | Description |
118
+ | ------------------- | ----------------------------------------------------------------- |
119
+ | `getCurrentPosition`| Acquire a single fix (async; never rejects — failures go to `error`). |
120
+ | `watchPosition` | Begin continuously watching (no-op if already watching). |
121
+ | `clearWatch` | Stop watching; `watching` becomes `false`. |
122
+
123
+ State-driven invocation uses the command-token protocol:
124
+
125
+ ```html
126
+ <wcs-geo manual data-wcs="command.getCurrentPosition: $command.locate"></wcs-geo>
127
+ ```
128
+
129
+ ## Notes & limitations
130
+
131
+ - **Attributes are read at connect time, not observed.** `<wcs-geo>` does not implement `observedAttributes` / `attributeChangedCallback`. Option attributes (`high-accuracy`, `timeout`, `maximum-age`, `watch`, `manual`) are read when the element connects and each time a command runs — changing them imperatively *after* connect does not by itself re-acquire or re-watch. To apply new options, call `getCurrentPosition()` / `clearWatch()` + `watchPosition()` again, or re-connect the element.
132
+ - **Reconnect re-acquires.** Removing and re-inserting the element runs `connectedCallback` again, so a default-mode element fetches a fresh fix and a `watch` element restarts watching (matching how it tears watching down on disconnect).
133
+ - **SSR (`@wcstack/server`).** The default one-shot mode declares `static hasConnectedCallbackPromise = true` and exposes `connectedCallbackPromise`, so the server renderer waits for the connect-time fix before snapshotting. (`watch` / `manual` modes have no connect-time fix to await.)
134
+ - **`timeout` / `maximum-age` parsing.** Values are parsed strictly: a non-numeric (`"10px"`), non-finite, or negative value falls back to the default (`Infinity` / `0`). Only a clean non-negative number is accepted.
135
+ - **Silent failure handling (zero-log).** Consistent with the rest of wcstack's zero-dependency, minimal philosophy, `<wcs-geo>` never logs or throws for runtime failures. A failed permission query (e.g. a browser that rejects the `geolocation` permission name, or has no Permissions API) silently falls back to `permission = "unsupported"`. Acquisition failures (`PERMISSION_DENIED` / `POSITION_UNAVAILABLE` / `TIMEOUT`, including a missing Geolocation API) are surfaced only through the `error` property / `wcs-geo:error` event — `getCurrentPosition()` resolves and never rejects. Bind `error` (and `permission`) to observe and react to these conditions.
136
+
137
+ ## Headless usage (`GeolocationCore`)
138
+
139
+ The Core has no DOM dependency and can be used directly with `bind()` from `@wc-bindable/core`:
140
+
141
+ ```typescript
142
+ import { GeolocationCore } from "@wcstack/geolocation";
143
+
144
+ const geo = new GeolocationCore();
145
+ geo.addEventListener("wcs-geo:position", (e) => {
146
+ console.log((e as CustomEvent).detail); // { latitude, longitude, accuracy, ... }
147
+ });
148
+
149
+ await geo.getCurrentPosition({ enableHighAccuracy: true });
150
+ // or, for continuous updates:
151
+ geo.watch();
152
+ // ...later
153
+ geo.clearWatch();
154
+ ```
155
+
156
+ ## License
157
+
158
+ MIT
package/dist/auto.js ADDED
@@ -0,0 +1,3 @@
1
+ import { bootstrapGeolocation } from "./index.esm.js";
2
+
3
+ bootstrapGeolocation();
@@ -0,0 +1,3 @@
1
+ import { bootstrapGeolocation } from "./index.esm.min.js";
2
+
3
+ bootstrapGeolocation();
@@ -0,0 +1,280 @@
1
+ interface ITagNames {
2
+ readonly geo: string;
3
+ }
4
+ interface IWritableTagNames {
5
+ geo?: string;
6
+ }
7
+ interface IConfig {
8
+ readonly autoTrigger: boolean;
9
+ readonly triggerAttribute: string;
10
+ readonly tagNames: ITagNames;
11
+ }
12
+ interface IWritableConfig {
13
+ autoTrigger?: boolean;
14
+ triggerAttribute?: string;
15
+ tagNames?: IWritableTagNames;
16
+ }
17
+ interface IWcBindableProperty {
18
+ readonly name: string;
19
+ readonly event: string;
20
+ readonly getter?: (event: Event) => any;
21
+ }
22
+ interface IWcBindableInput {
23
+ readonly name: string;
24
+ readonly attribute?: string;
25
+ }
26
+ interface IWcBindableCommand {
27
+ readonly name: string;
28
+ readonly async?: boolean;
29
+ }
30
+ interface IWcBindable {
31
+ readonly protocol: "wc-bindable";
32
+ readonly version: number;
33
+ readonly properties: IWcBindableProperty[];
34
+ readonly inputs?: IWcBindableInput[];
35
+ readonly commands?: IWcBindableCommand[];
36
+ }
37
+ /**
38
+ * Permission state for the Geolocation API, mirroring the Permissions API
39
+ * `PermissionState` plus `"unsupported"` for environments without
40
+ * `navigator.permissions` (or where the `geolocation` permission cannot be
41
+ * queried).
42
+ */
43
+ type GeoPermissionState = "prompt" | "granted" | "denied" | "unsupported";
44
+ /**
45
+ * Payload carried by the `wcs-geo:position` event — a structured-clone-friendly
46
+ * snapshot of `GeolocationPosition`. Unlike the live `GeolocationCoordinates`
47
+ * object, every field is a plain value so it can flow through data binding and
48
+ * be serialized.
49
+ *
50
+ * The coordinate fields are intentionally exposed twice: flattened at the top
51
+ * level (so `latitude` / `longitude` bind directly) and nested under `coords`
52
+ * (a `GeolocationPosition`-compatible copy, for consumers that expect the
53
+ * native shape). The two views always hold the same values.
54
+ */
55
+ interface WcsGeoPositionDetail {
56
+ latitude: number;
57
+ longitude: number;
58
+ accuracy: number;
59
+ altitude: number | null;
60
+ altitudeAccuracy: number | null;
61
+ heading: number | null;
62
+ speed: number | null;
63
+ timestamp: number;
64
+ coords: WcsGeoCoords;
65
+ }
66
+ interface WcsGeoCoords {
67
+ latitude: number;
68
+ longitude: number;
69
+ accuracy: number;
70
+ altitude: number | null;
71
+ altitudeAccuracy: number | null;
72
+ heading: number | null;
73
+ speed: number | null;
74
+ }
75
+ /**
76
+ * Normalized `GeolocationPositionError`. `code` mirrors the spec constants
77
+ * (PERMISSION_DENIED=1, POSITION_UNAVAILABLE=2, TIMEOUT=3); `unsupported` is
78
+ * surfaced via code 2 with a descriptive message when `navigator.geolocation`
79
+ * is absent.
80
+ */
81
+ interface WcsGeoErrorDetail {
82
+ code: number;
83
+ message: string;
84
+ }
85
+ /**
86
+ * Options accepted by `getCurrentPosition` / `watch`, mirroring
87
+ * `PositionOptions`.
88
+ */
89
+ interface GeoOptions {
90
+ enableHighAccuracy?: boolean;
91
+ timeout?: number;
92
+ maximumAge?: number;
93
+ }
94
+ /**
95
+ * Value types for GeolocationCore (headless) — the observable state properties.
96
+ * Use with `bind()` from `@wc-bindable/core` for compile-time type checking.
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * const core = new GeolocationCore();
101
+ * bind(core, (name: keyof WcsGeoCoreValues, value) => { ... });
102
+ * ```
103
+ */
104
+ interface WcsGeoCoreValues {
105
+ position: WcsGeoPositionDetail | null;
106
+ latitude: number | null;
107
+ longitude: number | null;
108
+ accuracy: number | null;
109
+ coords: WcsGeoCoords | null;
110
+ timestamp: number | null;
111
+ watching: boolean;
112
+ loading: boolean;
113
+ error: WcsGeoErrorDetail | null;
114
+ permission: GeoPermissionState;
115
+ }
116
+ /**
117
+ * Value types for the Shell (`<wcs-geo>`) — identical observable surface to the
118
+ * Core, plus the DOM-driven `trigger` command-property.
119
+ */
120
+ interface WcsGeoValues extends WcsGeoCoreValues {
121
+ trigger: boolean;
122
+ }
123
+ interface WcsGeoInputs {
124
+ highAccuracy: boolean;
125
+ timeout: number;
126
+ maximumAge: number;
127
+ watch: boolean;
128
+ manual: boolean;
129
+ /**
130
+ * Momentary command-property (no mirrored attribute): a `false`→`true` write
131
+ * requests a single fix, then the flag immediately resets to `false`. Unlike
132
+ * the other inputs it does not reflect to an HTML attribute.
133
+ */
134
+ trigger: boolean;
135
+ }
136
+ interface WcsGeoCoreCommands {
137
+ getCurrentPosition(options?: GeoOptions): Promise<void>;
138
+ watch(options?: GeoOptions): void;
139
+ clearWatch(): void;
140
+ }
141
+ interface WcsGeoCommands {
142
+ getCurrentPosition(): Promise<void>;
143
+ watchPosition(): void;
144
+ clearWatch(): void;
145
+ }
146
+
147
+ declare function bootstrapGeolocation(userConfig?: IWritableConfig): void;
148
+
149
+ declare function getConfig(): IConfig;
150
+
151
+ /**
152
+ * Headless geolocation primitive. A thin, framework-agnostic wrapper around the
153
+ * Geolocation API exposed through the wc-bindable protocol.
154
+ *
155
+ * It has two phases, mirroring the two distinct shapes of the underlying API:
156
+ * - **one-shot** — `getCurrentPosition()` resolves a single fix (like FetchCore's
157
+ * one-shot `fetch()`), toggling `loading` around the async call.
158
+ * - **continuous** — `watch()` / `clearWatch()` stream fixes (like TimerCore's
159
+ * `start()` / `stop()`), toggling the `watching` flag.
160
+ *
161
+ * Every successful fix is published via the single `wcs-geo:position` event;
162
+ * `latitude` / `longitude` / `accuracy` / `coords` / `timestamp` are read from
163
+ * it through getters (mirroring how TimerCore exposes count/elapsed from one
164
+ * `wcs-timer:tick` event), so an observer that binds any of them is notified on
165
+ * every fix.
166
+ *
167
+ * Geolocation also has a permission gate absent from timer/websocket: the
168
+ * `permission` property reflects `navigator.permissions.query({name:
169
+ * "geolocation"})` (`prompt` / `granted` / `denied`, or `unsupported`) and
170
+ * tracks its live `change` event. It is a read-only sensor — there is no
171
+ * element-bound "send" path; element → state only.
172
+ */
173
+ declare class GeolocationCore extends EventTarget {
174
+ static wcBindable: IWcBindable;
175
+ private _target;
176
+ private _watchId;
177
+ private _position;
178
+ private _watching;
179
+ private _loading;
180
+ private _error;
181
+ private _permission;
182
+ private _permissionStatus;
183
+ private _permissionSubscribed;
184
+ private _permGen;
185
+ private _acqGen;
186
+ private _watchGen;
187
+ constructor(target?: EventTarget);
188
+ get position(): WcsGeoPositionDetail | null;
189
+ get latitude(): number | null;
190
+ get longitude(): number | null;
191
+ get accuracy(): number | null;
192
+ get coords(): WcsGeoCoords | null;
193
+ get timestamp(): number | null;
194
+ get watching(): boolean;
195
+ get loading(): boolean;
196
+ get error(): WcsGeoErrorDetail | null;
197
+ get permission(): GeoPermissionState;
198
+ private _setPosition;
199
+ private _setWatching;
200
+ private _setLoading;
201
+ private _setError;
202
+ private _setPermission;
203
+ /**
204
+ * Acquire a single position fix. Resolves once the fix arrives or the request
205
+ * fails — never rejects: failures are surfaced through the `error` property so
206
+ * they flow into the declarative state, symmetrical with FetchCore.
207
+ */
208
+ getCurrentPosition(options?: GeoOptions): Promise<void>;
209
+ /**
210
+ * Begin continuously watching the position. Idempotent while already
211
+ * watching: a redundant watch() must not register a second `watchPosition`
212
+ * (which would leak the handle and double the fix rate). Reconfiguring is done
213
+ * via clearWatch() + watch().
214
+ */
215
+ watch(options?: GeoOptions): void;
216
+ clearWatch(): void;
217
+ /**
218
+ * Re-establish the permission `change` subscription after a dispose() — e.g.
219
+ * the Shell element was disconnected and then reconnected (reparented). No-op
220
+ * while a subscription is already live, so the first connect after
221
+ * construction does not double-subscribe. This keeps permission tracking
222
+ * symmetric with position acquisition, which the Shell also revives on
223
+ * reconnect.
224
+ */
225
+ reinitPermission(): void;
226
+ /**
227
+ * Detach the live permission `change` listener. Call from the Shell's
228
+ * `disconnectedCallback` so a removed element does not leak the subscription.
229
+ * A later reconnect can re-subscribe via reinitPermission().
230
+ */
231
+ dispose(): void;
232
+ private _hasGeolocation;
233
+ private _initPermission;
234
+ private _onPermissionChange;
235
+ private _normalizePosition;
236
+ private _normalizeError;
237
+ private _unsupportedError;
238
+ private _unexpectedError;
239
+ }
240
+
241
+ declare class WcsGeolocation extends HTMLElement {
242
+ static hasConnectedCallbackPromise: boolean;
243
+ static wcBindable: IWcBindable;
244
+ private _core;
245
+ private _trigger;
246
+ private _connectedCallbackPromise;
247
+ constructor();
248
+ get highAccuracy(): boolean;
249
+ set highAccuracy(value: boolean);
250
+ get timeout(): number;
251
+ set timeout(value: number);
252
+ get maximumAge(): number;
253
+ set maximumAge(value: number);
254
+ get watch(): boolean;
255
+ set watch(value: boolean);
256
+ get manual(): boolean;
257
+ set manual(value: boolean);
258
+ get position(): WcsGeoPositionDetail | null;
259
+ get latitude(): number | null;
260
+ get longitude(): number | null;
261
+ get accuracy(): number | null;
262
+ get coords(): WcsGeoCoords | null;
263
+ get timestamp(): number | null;
264
+ get watching(): boolean;
265
+ get loading(): boolean;
266
+ get error(): WcsGeoErrorDetail | null;
267
+ get permission(): GeoPermissionState;
268
+ get connectedCallbackPromise(): Promise<void>;
269
+ get trigger(): boolean;
270
+ set trigger(value: boolean);
271
+ getCurrentPosition(): Promise<void>;
272
+ watchPosition(): void;
273
+ clearWatch(): void;
274
+ private _options;
275
+ connectedCallback(): void;
276
+ disconnectedCallback(): void;
277
+ }
278
+
279
+ export { GeolocationCore, WcsGeolocation, bootstrapGeolocation, getConfig };
280
+ export type { GeoOptions, GeoPermissionState, IWritableConfig, IWritableTagNames, WcsGeoCommands, WcsGeoCoords, WcsGeoCoreCommands, WcsGeoCoreValues, WcsGeoErrorDetail, WcsGeoInputs, WcsGeoPositionDetail, WcsGeoValues };