@wcstack/tilt 1.16.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 +108 -0
- package/README.md +109 -0
- package/dist/auto.js +3 -0
- package/dist/auto.min.js +1 -0
- package/dist/index.d.ts +160 -0
- package/dist/index.esm.js +305 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.esm.min.js +2 -0
- package/dist/index.esm.min.js.map +1 -0
- package/package.json +70 -0
package/README.ja.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# @wcstack/tilt
|
|
2
|
+
|
|
3
|
+
`@wcstack/tilt` は wcstack エコシステム向けのヘッドレスな Device Orientation コンポーネントです。
|
|
4
|
+
|
|
5
|
+
視覚的な UI ウィジェットではありません。デバイスの傾き(`deviceorientation`)をリアクティブな state に変える**非同期プリミティブノード**です。
|
|
6
|
+
|
|
7
|
+
`@wcstack/state` と組み合わせると、`<wcs-tilt>` はパス契約で直接バインドできます:
|
|
8
|
+
|
|
9
|
+
- **入力サーフェス**: 無し
|
|
10
|
+
- **出力 state サーフェス**: `alpha`、`beta`、`gamma`、`absolute`、`permissionState`、`error`
|
|
11
|
+
|
|
12
|
+
## なぜ存在するか — `@wcstack/idle`の兄弟、iOSのgesture-gateを吸収する
|
|
13
|
+
|
|
14
|
+
iOS 13+ Safariは`deviceorientation`が発火する前に、明示的でgesture-gatedな`DeviceOrientationEvent.requestPermission()`を要求します。他の全プラットフォーム(Android Chrome、デスクトップ)にはこのgateがありません。`<wcs-tilt>`はこの差異を吸収します: gatingの無いプラットフォームでは`requestPermission()`は即座に`"granted"`でresolveするため、呼び出し元は**どこでも動く単一の**`requestPermission()` → `start()`フローを書けます。
|
|
15
|
+
|
|
16
|
+
> **`permissionState`は3値の語彙**(`"granted"` / `"denied"` / `"unknown"`)——このAPIに対応する`navigator.permissions.query()`エントリが存在しないため、意図的に4値のPermissions API状態とは別物にしています。`@wcstack/idle`(`@wcstack/permission`と合成)とは異なり、ローカルで追跡します。
|
|
17
|
+
|
|
18
|
+
> **connect時に自動startしません** — `@wcstack/idle`と同じ理由: 許可前の購読はiOSで無音のまま何も受け取れません。
|
|
19
|
+
|
|
20
|
+
> **secure context(HTTPSまたはlocalhost)が必須です。**
|
|
21
|
+
|
|
22
|
+
## インストール
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @wcstack/tilt
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## クイックスタート
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<script type="module" src="https://esm.run/@wcstack/state/auto"></script>
|
|
32
|
+
<script type="module" src="https://esm.run/@wcstack/tilt/auto"></script>
|
|
33
|
+
|
|
34
|
+
<wcs-state>
|
|
35
|
+
<script type="module">
|
|
36
|
+
export default {
|
|
37
|
+
tiltBeta: null,
|
|
38
|
+
tiltGamma: null,
|
|
39
|
+
async enableTilt() {
|
|
40
|
+
const el = document.querySelector("wcs-tilt");
|
|
41
|
+
const result = await el.requestPermission();
|
|
42
|
+
if (result === "granted") el.start();
|
|
43
|
+
},
|
|
44
|
+
get tiltTransform() {
|
|
45
|
+
return `rotate(${this.tiltBeta ?? 0}deg)`;
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
</script>
|
|
49
|
+
</wcs-state>
|
|
50
|
+
|
|
51
|
+
<wcs-tilt data-wcs="beta: tiltBeta; gamma: tiltGamma"></wcs-tilt>
|
|
52
|
+
<button data-wcs="onclick: enableTilt">傾き検知を有効にする</button>
|
|
53
|
+
<div data-wcs="style.transform: tiltTransform"></div>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`data-wcs` が参照する全てのパス(`tiltBeta`、`tiltGamma`、`tiltTransform`、`enableTilt`)は state オブジェクトに宣言が必須です——未宣言の top-level パスはバインド初期化時に例外を投げます。`tiltTransform` は素の path getter(計算プロパティ、`@wcstack/state` の README 参照)です——`@wcstack/state` には文字列テンプレート化フィルタが無いため、CSS 文字列は getter 側で組み立てます。`tiltBeta` が変わるたびに再計算されます。
|
|
57
|
+
|
|
58
|
+
## 観測可能プロパティ(出力)
|
|
59
|
+
|
|
60
|
+
| プロパティ | イベント | 説明 |
|
|
61
|
+
| ----------------- | ----------------------------- | ---- |
|
|
62
|
+
| `alpha` | `wcs-tilt:change` | Z軸回転、`start()`前は`null`。 |
|
|
63
|
+
| `beta` | `wcs-tilt:change` | X軸回転。 |
|
|
64
|
+
| `gamma` | `wcs-tilt:change` | Y軸回転。 |
|
|
65
|
+
| `absolute` | `wcs-tilt:change` | 地磁気に対する絶対方位かどうか。ブラウザにより信頼性が異なるため実機で確認してください。 |
|
|
66
|
+
| `permissionState` | `wcs-tilt:permission-changed` | `"granted"` \| `"denied"` \| `"unknown"`。 |
|
|
67
|
+
| `error` | `wcs-tilt:error` | 直近の`requestPermission()`の失敗(gesture文脈外呼び出しのrejectなど)、無ければ`null`。never-throw: 失敗はreject/throwせず、ここに流れます。 |
|
|
68
|
+
|
|
69
|
+
## コマンド
|
|
70
|
+
|
|
71
|
+
| コマンド | 非同期 | 説明 |
|
|
72
|
+
| -------------------- | ------ | ---- |
|
|
73
|
+
| `requestPermission` | はい | iOSではgesture-gatedな静的メソッドを呼ぶ(**実際のuser gestureハンドラ内から呼ぶ必要があります**)。それ以外の全プラットフォームでは即座に`"granted"`でresolve。 |
|
|
74
|
+
| `start` | いいえ | `deviceorientation`を購読。冪等。 |
|
|
75
|
+
| `stop` | いいえ | 購読解除。未開始でも安全に呼べます。 |
|
|
76
|
+
|
|
77
|
+
## 属性 / 入力
|
|
78
|
+
|
|
79
|
+
**無し。**
|
|
80
|
+
|
|
81
|
+
## 注意・制限
|
|
82
|
+
|
|
83
|
+
- **connect時に自動startしません。**
|
|
84
|
+
- **`@wcstack/permission`とは合成しません**(対応するPermissions APIエントリが存在しないため)——`permissionState`はローカルで追跡します。
|
|
85
|
+
- `_gen`世代ガードは無し: 購読は完全に同期的です。
|
|
86
|
+
- **非secure context(素のHTTP)では`deviceorientation`は一切発火しません**——ブラウザがネイティブに抑止し、`<wcs-tilt>`自身はガードを持たない(nativeの非発火を信頼する設計)ため、傾き値は`null`のまま・`wcs-tilt:change`は飛ばず・`permissionState`も(`requestPermission()`を呼ばない限り)`"unknown"`のまま変化しません。`requestPermission()`でも検出できません: gatingの無いプラットフォームではフォールバックが何も問い合わせずに`"granted"`を返します。何も起きないときは、まず配信元(HTTPS/localhost)を確認してください。
|
|
87
|
+
- **Permissions-Policyでゲートされます。** `deviceorientation`イベントは`accelerometer`と`gyroscope`のPermissions-Policyディレクティブが許可されている場合にのみ発火します(既定allowlist: `self`、Device Orientation Events仕様§4準拠)。クロスオリジンの`<iframe>`内で`<wcs-tilt>`を使うには、その`<iframe>`要素に`allow="accelerometer; gyroscope"`が必要です——無いとイベントは無音のまま一切発火しません。上記の非secure originのケースと同じ失敗モードです。
|
|
88
|
+
- **高頻度なイベントストリーム。** `deviceorientation`は多くのデバイスで毎秒数十回発火します。`@wcstack/state`にビルトインのdebounce/throttleフィルタは無いため、より粗い頻度に間引きたい場合は`@wcstack/debounce`のvalue surfaceで中継してください: `<wcs-tilt data-wcs="beta: tiltBeta">`のあと`<wcs-throttle wait="100" data-wcs="source: tiltBeta; value: throttledBeta"></wcs-throttle>`(詳細は`@wcstack/debounce`のREADME参照)。
|
|
89
|
+
|
|
90
|
+
## ヘッドレス利用(`TiltCore`)
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import { TiltCore } from "@wcstack/tilt";
|
|
94
|
+
|
|
95
|
+
const core = new TiltCore();
|
|
96
|
+
core.addEventListener("wcs-tilt:change", (e) => {
|
|
97
|
+
console.log((e as CustomEvent).detail); // { alpha, beta, gamma, absolute }
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
await core.requestPermission();
|
|
101
|
+
core.start();
|
|
102
|
+
// 後始末:
|
|
103
|
+
core.dispose();
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## ライセンス
|
|
107
|
+
|
|
108
|
+
MIT
|
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# @wcstack/tilt
|
|
2
|
+
|
|
3
|
+
`@wcstack/tilt` is a headless Device Orientation component for the wcstack ecosystem.
|
|
4
|
+
|
|
5
|
+
It is not a visual UI widget.
|
|
6
|
+
It is an **async primitive node** that turns device tilt (`deviceorientation`) into reactive state.
|
|
7
|
+
|
|
8
|
+
With `@wcstack/state`, `<wcs-tilt>` can be bound directly through path contracts:
|
|
9
|
+
|
|
10
|
+
- **input surface**: none
|
|
11
|
+
- **output state surface**: `alpha`, `beta`, `gamma`, `absolute`, `permissionState`, `error`
|
|
12
|
+
|
|
13
|
+
## Why this exists — the iOS gesture-gate absorption sibling to `@wcstack/idle`
|
|
14
|
+
|
|
15
|
+
iOS 13+ Safari requires an explicit, gesture-gated `DeviceOrientationEvent.requestPermission()` before `deviceorientation` fires at all. Every other platform (Android Chrome, desktop) has no such gate. `<wcs-tilt>` absorbs this difference: `requestPermission()` resolves immediately to `"granted"` on ungated platforms, so callers can write **one** `requestPermission()` → `start()` flow that works everywhere.
|
|
16
|
+
|
|
17
|
+
> **`permissionState` is a 3-value vocabulary** (`"granted"` / `"denied"` / `"unknown"`) — deliberately distinct from the 4-value Permissions API state, since there is no `navigator.permissions.query()` entry for this feature. It is tracked locally, unlike `@wcstack/idle` (which composes with `@wcstack/permission`).
|
|
18
|
+
|
|
19
|
+
> **Does not auto-start on connect** — same reasoning as `@wcstack/idle`: attempting to subscribe before permission is granted silently receives nothing on iOS.
|
|
20
|
+
|
|
21
|
+
> **Requires a secure context** (HTTPS or localhost).
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install @wcstack/tilt
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<script type="module" src="https://esm.run/@wcstack/state/auto"></script>
|
|
33
|
+
<script type="module" src="https://esm.run/@wcstack/tilt/auto"></script>
|
|
34
|
+
|
|
35
|
+
<wcs-state>
|
|
36
|
+
<script type="module">
|
|
37
|
+
export default {
|
|
38
|
+
tiltBeta: null,
|
|
39
|
+
tiltGamma: null,
|
|
40
|
+
async enableTilt() {
|
|
41
|
+
const el = document.querySelector("wcs-tilt");
|
|
42
|
+
const result = await el.requestPermission();
|
|
43
|
+
if (result === "granted") el.start();
|
|
44
|
+
},
|
|
45
|
+
get tiltTransform() {
|
|
46
|
+
return `rotate(${this.tiltBeta ?? 0}deg)`;
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
</script>
|
|
50
|
+
</wcs-state>
|
|
51
|
+
|
|
52
|
+
<wcs-tilt data-wcs="beta: tiltBeta; gamma: tiltGamma"></wcs-tilt>
|
|
53
|
+
<button data-wcs="onclick: enableTilt">Enable tilt</button>
|
|
54
|
+
<div data-wcs="style.transform: tiltTransform"></div>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Every path referenced by `data-wcs` (`tiltBeta`, `tiltGamma`, `tiltTransform`, `enableTilt`) must be declared on the state object — an undeclared top-level path throws during bind initialization. `tiltTransform` is a plain path getter (computed property, see `@wcstack/state`'s README) — `@wcstack/state` has no string-templating filter, so build the CSS string in a getter instead. It recomputes whenever `tiltBeta` changes.
|
|
58
|
+
|
|
59
|
+
## Observable Properties (outputs)
|
|
60
|
+
|
|
61
|
+
| Property | Event | Description |
|
|
62
|
+
| ----------------- | --------------------------- | ------------ |
|
|
63
|
+
| `alpha` | `wcs-tilt:change` | Z-axis rotation, or `null` before `start()`. |
|
|
64
|
+
| `beta` | `wcs-tilt:change` | X-axis rotation. |
|
|
65
|
+
| `gamma` | `wcs-tilt:change` | Y-axis rotation. |
|
|
66
|
+
| `absolute` | `wcs-tilt:change` | Whether the reading is relative to the Earth's frame. Reliability varies by browser — verify on your target devices. |
|
|
67
|
+
| `permissionState` | `wcs-tilt:permission-changed` | `"granted"` \| `"denied"` \| `"unknown"`. |
|
|
68
|
+
| `error` | `wcs-tilt:error` | The last `requestPermission()` failure (e.g. a gesture-context rejection), or `null`. never-throw: failures never reject/throw, they land here instead. |
|
|
69
|
+
|
|
70
|
+
## Commands
|
|
71
|
+
|
|
72
|
+
| Command | Async | Description |
|
|
73
|
+
| ------------------- | ----- | ------------ |
|
|
74
|
+
| `requestPermission` | yes | On iOS, calls the gesture-gated static method (**must be invoked from within a real user gesture handler**). On every other platform, resolves to `"granted"` immediately. |
|
|
75
|
+
| `start` | no | Subscribe to `deviceorientation`. Idempotent. |
|
|
76
|
+
| `stop` | no | Unsubscribe. Safe to call when not started. |
|
|
77
|
+
|
|
78
|
+
## Attributes / Inputs
|
|
79
|
+
|
|
80
|
+
**None.**
|
|
81
|
+
|
|
82
|
+
## Notes & limitations
|
|
83
|
+
|
|
84
|
+
- **Does not auto-start on connect.**
|
|
85
|
+
- **Does not compose with `@wcstack/permission`** (no matching Permissions API entry exists) — `permissionState` is tracked locally.
|
|
86
|
+
- No `_gen` generation guard: subscribing is fully synchronous.
|
|
87
|
+
- **On a non-secure origin (plain HTTP), `deviceorientation` never fires** — the browser suppresses it natively and `<wcs-tilt>` adds no guard of its own, so tilt values stay `null`, `wcs-tilt:change` never dispatches, and `permissionState` stays `"unknown"` (until you call `requestPermission()`). Calling `requestPermission()` cannot detect this either: on gate-less platforms its fallback resolves `"granted"` without probing anything. If nothing seems to happen, check your origin first.
|
|
88
|
+
- **Permissions-Policy gate.** The `deviceorientation` event is only dispatched when the `accelerometer` and `gyroscope` Permissions-Policy directives are allowed (default allowlist: `self`, per the Device Orientation Events spec §4). Using `<wcs-tilt>` inside a cross-origin `<iframe>` requires `allow="accelerometer; gyroscope"` on that `<iframe>` element — otherwise the event silently never fires, the same failure mode as the non-secure-origin case above.
|
|
89
|
+
- **High-frequency stream.** `deviceorientation` can fire tens of times per second on many devices. `@wcstack/state` has no built-in debounce/throttle filter — if you need a coarser rate, relay through `@wcstack/debounce`'s value surface: `<wcs-tilt data-wcs="beta: tiltBeta">` then `<wcs-throttle wait="100" data-wcs="source: tiltBeta; value: throttledBeta"></wcs-throttle>` (see `@wcstack/debounce`'s README).
|
|
90
|
+
|
|
91
|
+
## Headless usage (`TiltCore`)
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { TiltCore } from "@wcstack/tilt";
|
|
95
|
+
|
|
96
|
+
const core = new TiltCore();
|
|
97
|
+
core.addEventListener("wcs-tilt:change", (e) => {
|
|
98
|
+
console.log((e as CustomEvent).detail); // { alpha, beta, gamma, absolute }
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
await core.requestPermission();
|
|
102
|
+
core.start();
|
|
103
|
+
// later:
|
|
104
|
+
core.dispose();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
MIT
|
package/dist/auto.js
ADDED
package/dist/auto.min.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{bootstrapTilt}from"./index.esm.min.js";bootstrapTilt();
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
interface IWcBindableProperty {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly event: string;
|
|
4
|
+
readonly getter?: (event: Event) => any;
|
|
5
|
+
}
|
|
6
|
+
interface IWcBindableInput {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly attribute?: string;
|
|
9
|
+
}
|
|
10
|
+
interface IWcBindableCommand {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly async?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface IWcBindable {
|
|
15
|
+
readonly protocol: "wc-bindable";
|
|
16
|
+
readonly version: 1;
|
|
17
|
+
readonly properties: readonly IWcBindableProperty[];
|
|
18
|
+
readonly inputs?: readonly IWcBindableInput[];
|
|
19
|
+
readonly commands?: readonly IWcBindableCommand[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface ITagNames {
|
|
23
|
+
readonly tilt: string;
|
|
24
|
+
}
|
|
25
|
+
interface IWritableTagNames {
|
|
26
|
+
tilt?: string;
|
|
27
|
+
}
|
|
28
|
+
interface IConfig {
|
|
29
|
+
readonly tagNames: ITagNames;
|
|
30
|
+
}
|
|
31
|
+
interface IWritableConfig {
|
|
32
|
+
tagNames?: IWritableTagNames;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 3-value vocabulary, deliberately distinct from the 4-value permission state
|
|
37
|
+
* (prompt/granted/denied/unsupported) used elsewhere: `"unknown"` means
|
|
38
|
+
* "no gating exists on this platform, so there is nothing to have asked"
|
|
39
|
+
* (docs/device-orientation-tag-design.md §2) — not the same concept as
|
|
40
|
+
* Permissions API's `"prompt"`.
|
|
41
|
+
*/
|
|
42
|
+
type TiltPermissionState = "granted" | "denied" | "unknown";
|
|
43
|
+
/**
|
|
44
|
+
* Value types for TiltCore (headless) — the observable state properties.
|
|
45
|
+
*/
|
|
46
|
+
interface WcsTiltCoreValues {
|
|
47
|
+
alpha: number | null;
|
|
48
|
+
beta: number | null;
|
|
49
|
+
gamma: number | null;
|
|
50
|
+
absolute: boolean | null;
|
|
51
|
+
permissionState: TiltPermissionState;
|
|
52
|
+
error: any;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Value types for the Shell (`<wcs-tilt>`) — identical observable surface to
|
|
56
|
+
* the Core.
|
|
57
|
+
*/
|
|
58
|
+
type WcsTiltValues = WcsTiltCoreValues;
|
|
59
|
+
|
|
60
|
+
declare function bootstrapTilt(userConfig?: IWritableConfig): void;
|
|
61
|
+
|
|
62
|
+
declare function getConfig(): IConfig;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Headless Device Orientation primitive. A thin, framework-agnostic wrapper
|
|
66
|
+
* around `window`'s `deviceorientation` event exposed through the wc-bindable
|
|
67
|
+
* protocol.
|
|
68
|
+
*
|
|
69
|
+
* The batch2 sibling of `@wcstack/idle` (docs/device-orientation-tag-design.md).
|
|
70
|
+
* Unlike Idle Detection, there is no matching Permissions API entry for this
|
|
71
|
+
* feature (`navigator.permissions.query` has no "device-orientation" name), so
|
|
72
|
+
* `permissionState` must be tracked **locally** rather than composed with
|
|
73
|
+
* `<wcs-permission>` — the defining asymmetry within batch2.
|
|
74
|
+
*
|
|
75
|
+
* No `_gen` generation guard: subscribing/unsubscribing to `deviceorientation`
|
|
76
|
+
* (start/stop) is fully synchronous, so that path never needs one. This node
|
|
77
|
+
* does have an async probe — `requestPermission()` awaits the static
|
|
78
|
+
* `DeviceOrientationEvent.requestPermission()` — but its post-await write is
|
|
79
|
+
* a benign `permissionState`/`error` value set + dispatch with no
|
|
80
|
+
* subscription/resource management to race, so `_gen` is unneeded there too
|
|
81
|
+
* (docs/device-orientation-tag-design.md §4, corrected after an earlier
|
|
82
|
+
* revision mistakenly reused `@wcstack/network`'s "no async probe at all"
|
|
83
|
+
* rationale).
|
|
84
|
+
*/
|
|
85
|
+
declare class TiltCore extends EventTarget {
|
|
86
|
+
static wcBindable: IWcBindable;
|
|
87
|
+
private _target;
|
|
88
|
+
private _snapshot;
|
|
89
|
+
private _permissionState;
|
|
90
|
+
private _error;
|
|
91
|
+
private _subscribed;
|
|
92
|
+
private _ready;
|
|
93
|
+
constructor(target?: EventTarget);
|
|
94
|
+
get ready(): Promise<void>;
|
|
95
|
+
get alpha(): number | null;
|
|
96
|
+
get beta(): number | null;
|
|
97
|
+
get gamma(): number | null;
|
|
98
|
+
get absolute(): boolean | null;
|
|
99
|
+
get permissionState(): TiltPermissionState;
|
|
100
|
+
get error(): any;
|
|
101
|
+
observe(): Promise<void>;
|
|
102
|
+
dispose(): void;
|
|
103
|
+
private _deviceOrientationEventCtor;
|
|
104
|
+
private _setPermissionState;
|
|
105
|
+
private _setError;
|
|
106
|
+
/**
|
|
107
|
+
* Wraps iOS 13+ Safari's static, gesture-gated
|
|
108
|
+
* `DeviceOrientationEvent.requestPermission()`. On platforms without this
|
|
109
|
+
* gate (Android Chrome, desktop) there is nothing to ask, so this resolves
|
|
110
|
+
* to `"granted"` immediately without querying anything — callers can write
|
|
111
|
+
* one `requestPermission()` → `start()` flow that works everywhere
|
|
112
|
+
* (docs/device-orientation-tag-design.md §3).
|
|
113
|
+
*
|
|
114
|
+
* never-throw (§3.6): a gesture-context rejection resolves to `"denied"`
|
|
115
|
+
* and the raw error lands in `error` instead of propagating. Mirrors
|
|
116
|
+
* `<wcs-idle>`'s `requestPermission()` (docs/idle-detection-tag-design.md
|
|
117
|
+
* §4.1) — any settled (non-throwing) outcome supersedes a stale `error`
|
|
118
|
+
* from an earlier attempt.
|
|
119
|
+
*/
|
|
120
|
+
requestPermission(): Promise<TiltPermissionState>;
|
|
121
|
+
/** Subscribe to `deviceorientation`. Idempotent — a second start() while already subscribed is a no-op. */
|
|
122
|
+
start(): void;
|
|
123
|
+
/** Unsubscribe from `deviceorientation`. Safe to call when not started. */
|
|
124
|
+
stop(): void;
|
|
125
|
+
private _onOrientation;
|
|
126
|
+
private _apply;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* `<wcs-tilt>` — declarative Device Orientation API monitor.
|
|
131
|
+
*
|
|
132
|
+
* Named `tilt` (not `orientation`/`device-orientation`) to avoid colliding
|
|
133
|
+
* with `<wcs-screen-orientation>` (docs/device-orientation-tag-design.md §9).
|
|
134
|
+
*
|
|
135
|
+
* Does NOT auto-start on connect, mirroring `<wcs-idle>`: on iOS, subscribing
|
|
136
|
+
* before permission is granted silently receives no events. Callers drive
|
|
137
|
+
* `requestPermission()` → `start()` explicitly.
|
|
138
|
+
*/
|
|
139
|
+
declare class WcsTilt extends HTMLElement {
|
|
140
|
+
static hasConnectedCallbackPromise: boolean;
|
|
141
|
+
static wcBindable: IWcBindable;
|
|
142
|
+
private _core;
|
|
143
|
+
private _connectedCallbackPromise;
|
|
144
|
+
constructor();
|
|
145
|
+
get alpha(): number | null;
|
|
146
|
+
get beta(): number | null;
|
|
147
|
+
get gamma(): number | null;
|
|
148
|
+
get absolute(): boolean | null;
|
|
149
|
+
get permissionState(): TiltPermissionState;
|
|
150
|
+
get error(): any;
|
|
151
|
+
get connectedCallbackPromise(): Promise<void>;
|
|
152
|
+
requestPermission(): Promise<TiltPermissionState>;
|
|
153
|
+
start(): void;
|
|
154
|
+
stop(): void;
|
|
155
|
+
connectedCallback(): void;
|
|
156
|
+
disconnectedCallback(): void;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export { TiltCore, WcsTilt, bootstrapTilt, getConfig };
|
|
160
|
+
export type { IWritableConfig, IWritableTagNames, TiltPermissionState, WcsTiltCoreValues, WcsTiltValues };
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
const _config = {
|
|
2
|
+
tagNames: {
|
|
3
|
+
tilt: "wcs-tilt",
|
|
4
|
+
},
|
|
5
|
+
};
|
|
6
|
+
function deepFreeze(obj) {
|
|
7
|
+
if (obj === null || typeof obj !== "object")
|
|
8
|
+
return obj;
|
|
9
|
+
Object.freeze(obj);
|
|
10
|
+
for (const key of Object.keys(obj)) {
|
|
11
|
+
deepFreeze(obj[key]);
|
|
12
|
+
}
|
|
13
|
+
return obj;
|
|
14
|
+
}
|
|
15
|
+
function deepClone(obj) {
|
|
16
|
+
if (obj === null || typeof obj !== "object")
|
|
17
|
+
return obj;
|
|
18
|
+
const clone = {};
|
|
19
|
+
for (const key of Object.keys(obj)) {
|
|
20
|
+
clone[key] = deepClone(obj[key]);
|
|
21
|
+
}
|
|
22
|
+
return clone;
|
|
23
|
+
}
|
|
24
|
+
let frozenConfig = null;
|
|
25
|
+
const config = _config;
|
|
26
|
+
function getConfig() {
|
|
27
|
+
if (!frozenConfig) {
|
|
28
|
+
frozenConfig = deepFreeze(deepClone(_config));
|
|
29
|
+
}
|
|
30
|
+
return frozenConfig;
|
|
31
|
+
}
|
|
32
|
+
function setConfig(partialConfig) {
|
|
33
|
+
if (partialConfig.tagNames) {
|
|
34
|
+
Object.assign(_config.tagNames, partialConfig.tagNames);
|
|
35
|
+
}
|
|
36
|
+
frozenConfig = null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const UNSUPPORTED_SNAPSHOT = Object.freeze({
|
|
40
|
+
alpha: null,
|
|
41
|
+
beta: null,
|
|
42
|
+
gamma: null,
|
|
43
|
+
absolute: null,
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* Headless Device Orientation primitive. A thin, framework-agnostic wrapper
|
|
47
|
+
* around `window`'s `deviceorientation` event exposed through the wc-bindable
|
|
48
|
+
* protocol.
|
|
49
|
+
*
|
|
50
|
+
* The batch2 sibling of `@wcstack/idle` (docs/device-orientation-tag-design.md).
|
|
51
|
+
* Unlike Idle Detection, there is no matching Permissions API entry for this
|
|
52
|
+
* feature (`navigator.permissions.query` has no "device-orientation" name), so
|
|
53
|
+
* `permissionState` must be tracked **locally** rather than composed with
|
|
54
|
+
* `<wcs-permission>` — the defining asymmetry within batch2.
|
|
55
|
+
*
|
|
56
|
+
* No `_gen` generation guard: subscribing/unsubscribing to `deviceorientation`
|
|
57
|
+
* (start/stop) is fully synchronous, so that path never needs one. This node
|
|
58
|
+
* does have an async probe — `requestPermission()` awaits the static
|
|
59
|
+
* `DeviceOrientationEvent.requestPermission()` — but its post-await write is
|
|
60
|
+
* a benign `permissionState`/`error` value set + dispatch with no
|
|
61
|
+
* subscription/resource management to race, so `_gen` is unneeded there too
|
|
62
|
+
* (docs/device-orientation-tag-design.md §4, corrected after an earlier
|
|
63
|
+
* revision mistakenly reused `@wcstack/network`'s "no async probe at all"
|
|
64
|
+
* rationale).
|
|
65
|
+
*/
|
|
66
|
+
class TiltCore extends EventTarget {
|
|
67
|
+
static wcBindable = {
|
|
68
|
+
protocol: "wc-bindable",
|
|
69
|
+
version: 1,
|
|
70
|
+
properties: [
|
|
71
|
+
{ name: "alpha", event: "wcs-tilt:change", getter: (e) => e.detail.alpha },
|
|
72
|
+
{ name: "beta", event: "wcs-tilt:change", getter: (e) => e.detail.beta },
|
|
73
|
+
{ name: "gamma", event: "wcs-tilt:change", getter: (e) => e.detail.gamma },
|
|
74
|
+
{ name: "absolute", event: "wcs-tilt:change", getter: (e) => e.detail.absolute },
|
|
75
|
+
{ name: "permissionState", event: "wcs-tilt:permission-changed" },
|
|
76
|
+
// never-throw (§3.6): requestPermission() failures land here instead of
|
|
77
|
+
// rejecting/throwing. Mirrors idle (same batch2) and the accelerometer
|
|
78
|
+
// family (batch5) — see docs/io-node-batch-implementation-plan.md.
|
|
79
|
+
{ name: "error", event: "wcs-tilt:error" },
|
|
80
|
+
],
|
|
81
|
+
commands: [
|
|
82
|
+
{ name: "requestPermission", async: true },
|
|
83
|
+
{ name: "start" },
|
|
84
|
+
{ name: "stop" },
|
|
85
|
+
],
|
|
86
|
+
};
|
|
87
|
+
_target;
|
|
88
|
+
_snapshot = UNSUPPORTED_SNAPSHOT;
|
|
89
|
+
_permissionState = "unknown";
|
|
90
|
+
_error = null;
|
|
91
|
+
_subscribed = false;
|
|
92
|
+
// SSR (§3.8): never auto-starts on connect, so there is no probe to await —
|
|
93
|
+
// readiness is always immediate.
|
|
94
|
+
_ready = Promise.resolve();
|
|
95
|
+
constructor(target) {
|
|
96
|
+
super();
|
|
97
|
+
this._target = target ?? this;
|
|
98
|
+
}
|
|
99
|
+
get ready() {
|
|
100
|
+
return this._ready;
|
|
101
|
+
}
|
|
102
|
+
get alpha() {
|
|
103
|
+
return this._snapshot.alpha;
|
|
104
|
+
}
|
|
105
|
+
get beta() {
|
|
106
|
+
return this._snapshot.beta;
|
|
107
|
+
}
|
|
108
|
+
get gamma() {
|
|
109
|
+
return this._snapshot.gamma;
|
|
110
|
+
}
|
|
111
|
+
get absolute() {
|
|
112
|
+
return this._snapshot.absolute;
|
|
113
|
+
}
|
|
114
|
+
get permissionState() {
|
|
115
|
+
return this._permissionState;
|
|
116
|
+
}
|
|
117
|
+
get error() {
|
|
118
|
+
return this._error;
|
|
119
|
+
}
|
|
120
|
+
// Lifecycle (§3.5). observe() is a synchronous no-op: like `<wcs-idle>`,
|
|
121
|
+
// this Core deliberately does NOT auto-start on connect (§6) on platforms
|
|
122
|
+
// that gate deviceorientation behind requestPermission().
|
|
123
|
+
observe() {
|
|
124
|
+
return this._ready;
|
|
125
|
+
}
|
|
126
|
+
dispose() {
|
|
127
|
+
this.stop();
|
|
128
|
+
}
|
|
129
|
+
_deviceOrientationEventCtor() {
|
|
130
|
+
const g = globalThis;
|
|
131
|
+
return typeof g.DeviceOrientationEvent !== "undefined" ? g.DeviceOrientationEvent : undefined;
|
|
132
|
+
}
|
|
133
|
+
_setPermissionState(state) {
|
|
134
|
+
if (this._permissionState === state)
|
|
135
|
+
return;
|
|
136
|
+
this._permissionState = state;
|
|
137
|
+
this._target.dispatchEvent(new CustomEvent("wcs-tilt:permission-changed", {
|
|
138
|
+
detail: state,
|
|
139
|
+
bubbles: true,
|
|
140
|
+
}));
|
|
141
|
+
}
|
|
142
|
+
_setError(error) {
|
|
143
|
+
if (this._error === error)
|
|
144
|
+
return;
|
|
145
|
+
this._error = error;
|
|
146
|
+
this._target.dispatchEvent(new CustomEvent("wcs-tilt:error", {
|
|
147
|
+
detail: error,
|
|
148
|
+
bubbles: true,
|
|
149
|
+
}));
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Wraps iOS 13+ Safari's static, gesture-gated
|
|
153
|
+
* `DeviceOrientationEvent.requestPermission()`. On platforms without this
|
|
154
|
+
* gate (Android Chrome, desktop) there is nothing to ask, so this resolves
|
|
155
|
+
* to `"granted"` immediately without querying anything — callers can write
|
|
156
|
+
* one `requestPermission()` → `start()` flow that works everywhere
|
|
157
|
+
* (docs/device-orientation-tag-design.md §3).
|
|
158
|
+
*
|
|
159
|
+
* never-throw (§3.6): a gesture-context rejection resolves to `"denied"`
|
|
160
|
+
* and the raw error lands in `error` instead of propagating. Mirrors
|
|
161
|
+
* `<wcs-idle>`'s `requestPermission()` (docs/idle-detection-tag-design.md
|
|
162
|
+
* §4.1) — any settled (non-throwing) outcome supersedes a stale `error`
|
|
163
|
+
* from an earlier attempt.
|
|
164
|
+
*/
|
|
165
|
+
async requestPermission() {
|
|
166
|
+
const Ctor = this._deviceOrientationEventCtor();
|
|
167
|
+
if (typeof Ctor?.requestPermission !== "function") {
|
|
168
|
+
this._setError(null);
|
|
169
|
+
this._setPermissionState("granted");
|
|
170
|
+
return "granted";
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const result = await Ctor.requestPermission();
|
|
174
|
+
const state = result === "granted" ? "granted" : "denied";
|
|
175
|
+
this._setError(null);
|
|
176
|
+
this._setPermissionState(state);
|
|
177
|
+
return state;
|
|
178
|
+
}
|
|
179
|
+
catch (e) {
|
|
180
|
+
// never-throw: a gesture-context rejection resolves to "denied".
|
|
181
|
+
this._setError({ error: e });
|
|
182
|
+
this._setPermissionState("denied");
|
|
183
|
+
return "denied";
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/** Subscribe to `deviceorientation`. Idempotent — a second start() while already subscribed is a no-op. */
|
|
187
|
+
start() {
|
|
188
|
+
if (this._subscribed)
|
|
189
|
+
return;
|
|
190
|
+
this._subscribed = true;
|
|
191
|
+
globalThis.window?.addEventListener("deviceorientation", this._onOrientation);
|
|
192
|
+
}
|
|
193
|
+
/** Unsubscribe from `deviceorientation`. Safe to call when not started. */
|
|
194
|
+
stop() {
|
|
195
|
+
if (!this._subscribed)
|
|
196
|
+
return;
|
|
197
|
+
this._subscribed = false;
|
|
198
|
+
globalThis.window?.removeEventListener("deviceorientation", this._onOrientation);
|
|
199
|
+
}
|
|
200
|
+
_onOrientation = (event) => {
|
|
201
|
+
this._apply({
|
|
202
|
+
alpha: event.alpha,
|
|
203
|
+
beta: event.beta,
|
|
204
|
+
gamma: event.gamma,
|
|
205
|
+
absolute: event.absolute,
|
|
206
|
+
});
|
|
207
|
+
};
|
|
208
|
+
// Same-value guard (§3.3 MUST).
|
|
209
|
+
_apply(next) {
|
|
210
|
+
const prev = this._snapshot;
|
|
211
|
+
if (prev.alpha === next.alpha &&
|
|
212
|
+
prev.beta === next.beta &&
|
|
213
|
+
prev.gamma === next.gamma &&
|
|
214
|
+
prev.absolute === next.absolute) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
this._snapshot = next;
|
|
218
|
+
this._target.dispatchEvent(new CustomEvent("wcs-tilt:change", {
|
|
219
|
+
detail: next,
|
|
220
|
+
bubbles: true,
|
|
221
|
+
}));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* `<wcs-tilt>` — declarative Device Orientation API monitor.
|
|
227
|
+
*
|
|
228
|
+
* Named `tilt` (not `orientation`/`device-orientation`) to avoid colliding
|
|
229
|
+
* with `<wcs-screen-orientation>` (docs/device-orientation-tag-design.md §9).
|
|
230
|
+
*
|
|
231
|
+
* Does NOT auto-start on connect, mirroring `<wcs-idle>`: on iOS, subscribing
|
|
232
|
+
* before permission is granted silently receives no events. Callers drive
|
|
233
|
+
* `requestPermission()` → `start()` explicitly.
|
|
234
|
+
*/
|
|
235
|
+
class WcsTilt extends HTMLElement {
|
|
236
|
+
static hasConnectedCallbackPromise = true;
|
|
237
|
+
static wcBindable = {
|
|
238
|
+
...TiltCore.wcBindable,
|
|
239
|
+
inputs: [],
|
|
240
|
+
// Core の commands をそのまま継承(単一情報源)。
|
|
241
|
+
commands: TiltCore.wcBindable.commands,
|
|
242
|
+
};
|
|
243
|
+
_core;
|
|
244
|
+
_connectedCallbackPromise = Promise.resolve();
|
|
245
|
+
constructor() {
|
|
246
|
+
super();
|
|
247
|
+
this._core = new TiltCore(this);
|
|
248
|
+
}
|
|
249
|
+
// --- Core delegated getters ---
|
|
250
|
+
get alpha() {
|
|
251
|
+
return this._core.alpha;
|
|
252
|
+
}
|
|
253
|
+
get beta() {
|
|
254
|
+
return this._core.beta;
|
|
255
|
+
}
|
|
256
|
+
get gamma() {
|
|
257
|
+
return this._core.gamma;
|
|
258
|
+
}
|
|
259
|
+
get absolute() {
|
|
260
|
+
return this._core.absolute;
|
|
261
|
+
}
|
|
262
|
+
get permissionState() {
|
|
263
|
+
return this._core.permissionState;
|
|
264
|
+
}
|
|
265
|
+
get error() {
|
|
266
|
+
return this._core.error;
|
|
267
|
+
}
|
|
268
|
+
get connectedCallbackPromise() {
|
|
269
|
+
return this._connectedCallbackPromise;
|
|
270
|
+
}
|
|
271
|
+
// --- Commands (delegated to Core) ---
|
|
272
|
+
requestPermission() {
|
|
273
|
+
return this._core.requestPermission();
|
|
274
|
+
}
|
|
275
|
+
start() {
|
|
276
|
+
this._core.start();
|
|
277
|
+
}
|
|
278
|
+
stop() {
|
|
279
|
+
this._core.stop();
|
|
280
|
+
}
|
|
281
|
+
// --- Lifecycle ---
|
|
282
|
+
connectedCallback() {
|
|
283
|
+
this.style.display = "none";
|
|
284
|
+
this._connectedCallbackPromise = this._core.observe();
|
|
285
|
+
}
|
|
286
|
+
disconnectedCallback() {
|
|
287
|
+
this._core.dispose();
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function registerComponents() {
|
|
292
|
+
if (!customElements.get(config.tagNames.tilt)) {
|
|
293
|
+
customElements.define(config.tagNames.tilt, WcsTilt);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function bootstrapTilt(userConfig) {
|
|
298
|
+
if (userConfig) {
|
|
299
|
+
setConfig(userConfig);
|
|
300
|
+
}
|
|
301
|
+
registerComponents();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export { TiltCore, WcsTilt, bootstrapTilt, getConfig };
|
|
305
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/core/TiltCore.ts","../src/components/Tilt.ts","../src/registerComponents.ts","../src/bootstrapTilt.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n tilt: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n tilt: \"wcs-tilt\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable, TiltPermissionState } from \"../types.js\";\n\ninterface DeviceOrientationEventCtor {\n requestPermission?: () => Promise<\"granted\" | \"denied\">;\n}\n\ninterface WcsTiltSnapshot {\n alpha: number | null;\n beta: number | null;\n gamma: number | null;\n absolute: boolean | null;\n}\n\nconst UNSUPPORTED_SNAPSHOT: WcsTiltSnapshot = Object.freeze({\n alpha: null,\n beta: null,\n gamma: null,\n absolute: null,\n});\n\n/**\n * Headless Device Orientation primitive. A thin, framework-agnostic wrapper\n * around `window`'s `deviceorientation` event exposed through the wc-bindable\n * protocol.\n *\n * The batch2 sibling of `@wcstack/idle` (docs/device-orientation-tag-design.md).\n * Unlike Idle Detection, there is no matching Permissions API entry for this\n * feature (`navigator.permissions.query` has no \"device-orientation\" name), so\n * `permissionState` must be tracked **locally** rather than composed with\n * `<wcs-permission>` — the defining asymmetry within batch2.\n *\n * No `_gen` generation guard: subscribing/unsubscribing to `deviceorientation`\n * (start/stop) is fully synchronous, so that path never needs one. This node\n * does have an async probe — `requestPermission()` awaits the static\n * `DeviceOrientationEvent.requestPermission()` — but its post-await write is\n * a benign `permissionState`/`error` value set + dispatch with no\n * subscription/resource management to race, so `_gen` is unneeded there too\n * (docs/device-orientation-tag-design.md §4, corrected after an earlier\n * revision mistakenly reused `@wcstack/network`'s \"no async probe at all\"\n * rationale).\n */\nexport class TiltCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"alpha\", event: \"wcs-tilt:change\", getter: (e: Event) => (e as CustomEvent).detail.alpha },\n { name: \"beta\", event: \"wcs-tilt:change\", getter: (e: Event) => (e as CustomEvent).detail.beta },\n { name: \"gamma\", event: \"wcs-tilt:change\", getter: (e: Event) => (e as CustomEvent).detail.gamma },\n { name: \"absolute\", event: \"wcs-tilt:change\", getter: (e: Event) => (e as CustomEvent).detail.absolute },\n { name: \"permissionState\", event: \"wcs-tilt:permission-changed\" },\n // never-throw (§3.6): requestPermission() failures land here instead of\n // rejecting/throwing. Mirrors idle (same batch2) and the accelerometer\n // family (batch5) — see docs/io-node-batch-implementation-plan.md.\n { name: \"error\", event: \"wcs-tilt:error\" },\n ],\n commands: [\n { name: \"requestPermission\", async: true },\n { name: \"start\" },\n { name: \"stop\" },\n ],\n };\n\n private _target: EventTarget;\n private _snapshot: WcsTiltSnapshot = UNSUPPORTED_SNAPSHOT;\n private _permissionState: TiltPermissionState = \"unknown\";\n private _error: any = null;\n private _subscribed = false;\n\n // SSR (§3.8): never auto-starts on connect, so there is no probe to await —\n // readiness is always immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n get alpha(): number | null {\n return this._snapshot.alpha;\n }\n\n get beta(): number | null {\n return this._snapshot.beta;\n }\n\n get gamma(): number | null {\n return this._snapshot.gamma;\n }\n\n get absolute(): boolean | null {\n return this._snapshot.absolute;\n }\n\n get permissionState(): TiltPermissionState {\n return this._permissionState;\n }\n\n get error(): any {\n return this._error;\n }\n\n // Lifecycle (§3.5). observe() is a synchronous no-op: like `<wcs-idle>`,\n // this Core deliberately does NOT auto-start on connect (§6) on platforms\n // that gate deviceorientation behind requestPermission().\n observe(): Promise<void> {\n return this._ready;\n }\n\n dispose(): void {\n this.stop();\n }\n\n private _deviceOrientationEventCtor(): DeviceOrientationEventCtor | undefined {\n const g = globalThis as any;\n return typeof g.DeviceOrientationEvent !== \"undefined\" ? g.DeviceOrientationEvent : undefined;\n }\n\n private _setPermissionState(state: TiltPermissionState): void {\n if (this._permissionState === state) return;\n this._permissionState = state;\n this._target.dispatchEvent(new CustomEvent(\"wcs-tilt:permission-changed\", {\n detail: state,\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n if (this._error === error) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-tilt:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n /**\n * Wraps iOS 13+ Safari's static, gesture-gated\n * `DeviceOrientationEvent.requestPermission()`. On platforms without this\n * gate (Android Chrome, desktop) there is nothing to ask, so this resolves\n * to `\"granted\"` immediately without querying anything — callers can write\n * one `requestPermission()` → `start()` flow that works everywhere\n * (docs/device-orientation-tag-design.md §3).\n *\n * never-throw (§3.6): a gesture-context rejection resolves to `\"denied\"`\n * and the raw error lands in `error` instead of propagating. Mirrors\n * `<wcs-idle>`'s `requestPermission()` (docs/idle-detection-tag-design.md\n * §4.1) — any settled (non-throwing) outcome supersedes a stale `error`\n * from an earlier attempt.\n */\n async requestPermission(): Promise<TiltPermissionState> {\n const Ctor = this._deviceOrientationEventCtor();\n if (typeof Ctor?.requestPermission !== \"function\") {\n this._setError(null);\n this._setPermissionState(\"granted\");\n return \"granted\";\n }\n try {\n const result = await Ctor.requestPermission();\n const state: TiltPermissionState = result === \"granted\" ? \"granted\" : \"denied\";\n this._setError(null);\n this._setPermissionState(state);\n return state;\n } catch (e) {\n // never-throw: a gesture-context rejection resolves to \"denied\".\n this._setError({ error: e });\n this._setPermissionState(\"denied\");\n return \"denied\";\n }\n }\n\n /** Subscribe to `deviceorientation`. Idempotent — a second start() while already subscribed is a no-op. */\n start(): void {\n if (this._subscribed) return;\n this._subscribed = true;\n globalThis.window?.addEventListener(\"deviceorientation\", this._onOrientation as EventListener);\n }\n\n /** Unsubscribe from `deviceorientation`. Safe to call when not started. */\n stop(): void {\n if (!this._subscribed) return;\n this._subscribed = false;\n globalThis.window?.removeEventListener(\"deviceorientation\", this._onOrientation as EventListener);\n }\n\n private _onOrientation = (event: DeviceOrientationEvent): void => {\n this._apply({\n alpha: event.alpha,\n beta: event.beta,\n gamma: event.gamma,\n absolute: event.absolute,\n });\n };\n\n // Same-value guard (§3.3 MUST).\n private _apply(next: WcsTiltSnapshot): void {\n const prev = this._snapshot;\n if (\n prev.alpha === next.alpha &&\n prev.beta === next.beta &&\n prev.gamma === next.gamma &&\n prev.absolute === next.absolute\n ) {\n return;\n }\n this._snapshot = next;\n this._target.dispatchEvent(new CustomEvent(\"wcs-tilt:change\", {\n detail: next,\n bubbles: true,\n }));\n }\n}\n","import { IWcBindable, TiltPermissionState } from \"../types.js\";\nimport { TiltCore } from \"../core/TiltCore.js\";\n\n/**\n * `<wcs-tilt>` — declarative Device Orientation API monitor.\n *\n * Named `tilt` (not `orientation`/`device-orientation`) to avoid colliding\n * with `<wcs-screen-orientation>` (docs/device-orientation-tag-design.md §9).\n *\n * Does NOT auto-start on connect, mirroring `<wcs-idle>`: on iOS, subscribing\n * before permission is granted silently receives no events. Callers drive\n * `requestPermission()` → `start()` explicitly.\n */\nexport class WcsTilt extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n\n static wcBindable: IWcBindable = {\n ...TiltCore.wcBindable,\n inputs: [],\n // Core の commands をそのまま継承(単一情報源)。\n commands: TiltCore.wcBindable.commands,\n };\n\n private _core: TiltCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n\n constructor() {\n super();\n this._core = new TiltCore(this);\n }\n\n // --- Core delegated getters ---\n\n get alpha(): number | null {\n return this._core.alpha;\n }\n\n get beta(): number | null {\n return this._core.beta;\n }\n\n get gamma(): number | null {\n return this._core.gamma;\n }\n\n get absolute(): boolean | null {\n return this._core.absolute;\n }\n\n get permissionState(): TiltPermissionState {\n return this._core.permissionState;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Commands (delegated to Core) ---\n\n requestPermission(): Promise<TiltPermissionState> {\n return this._core.requestPermission();\n }\n\n start(): void {\n this._core.start();\n }\n\n stop(): void {\n this._core.stop();\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.style.display = \"none\";\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n}\n","import { WcsTilt } from \"./components/Tilt.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.tilt)) {\n customElements.define(config.tagNames.tilt, WcsTilt);\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapTilt(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const t={tagNames:{tilt:"wcs-tilt"}};function e(t){if(null===t||"object"!=typeof t)return t;Object.freeze(t);for(const s of Object.keys(t))e(t[s]);return t}function s(t){if(null===t||"object"!=typeof t)return t;const e={};for(const r of Object.keys(t))e[r]=s(t[r]);return e}let r=null;const n=t;function a(){return r||(r=e(s(t))),r}const i=Object.freeze({alpha:null,beta:null,gamma:null,absolute:null});class o extends EventTarget{static wcBindable={protocol:"wc-bindable",version:1,properties:[{name:"alpha",event:"wcs-tilt:change",getter:t=>t.detail.alpha},{name:"beta",event:"wcs-tilt:change",getter:t=>t.detail.beta},{name:"gamma",event:"wcs-tilt:change",getter:t=>t.detail.gamma},{name:"absolute",event:"wcs-tilt:change",getter:t=>t.detail.absolute},{name:"permissionState",event:"wcs-tilt:permission-changed"},{name:"error",event:"wcs-tilt:error"}],commands:[{name:"requestPermission",async:!0},{name:"start"},{name:"stop"}]};_target;_snapshot=i;_permissionState="unknown";_error=null;_subscribed=!1;_ready=Promise.resolve();constructor(t){super(),this._target=t??this}get ready(){return this._ready}get alpha(){return this._snapshot.alpha}get beta(){return this._snapshot.beta}get gamma(){return this._snapshot.gamma}get absolute(){return this._snapshot.absolute}get permissionState(){return this._permissionState}get error(){return this._error}observe(){return this._ready}dispose(){this.stop()}_deviceOrientationEventCtor(){const t=globalThis;return void 0!==t.DeviceOrientationEvent?t.DeviceOrientationEvent:void 0}_setPermissionState(t){this._permissionState!==t&&(this._permissionState=t,this._target.dispatchEvent(new CustomEvent("wcs-tilt:permission-changed",{detail:t,bubbles:!0})))}_setError(t){this._error!==t&&(this._error=t,this._target.dispatchEvent(new CustomEvent("wcs-tilt:error",{detail:t,bubbles:!0})))}async requestPermission(){const t=this._deviceOrientationEventCtor();if("function"!=typeof t?.requestPermission)return this._setError(null),this._setPermissionState("granted"),"granted";try{const e="granted"===await t.requestPermission()?"granted":"denied";return this._setError(null),this._setPermissionState(e),e}catch(t){return this._setError({error:t}),this._setPermissionState("denied"),"denied"}}start(){this._subscribed||(this._subscribed=!0,globalThis.window?.addEventListener("deviceorientation",this._onOrientation))}stop(){this._subscribed&&(this._subscribed=!1,globalThis.window?.removeEventListener("deviceorientation",this._onOrientation))}_onOrientation=t=>{this._apply({alpha:t.alpha,beta:t.beta,gamma:t.gamma,absolute:t.absolute})};_apply(t){const e=this._snapshot;e.alpha===t.alpha&&e.beta===t.beta&&e.gamma===t.gamma&&e.absolute===t.absolute||(this._snapshot=t,this._target.dispatchEvent(new CustomEvent("wcs-tilt:change",{detail:t,bubbles:!0})))}}class c extends HTMLElement{static hasConnectedCallbackPromise=!0;static wcBindable={...o.wcBindable,inputs:[],commands:o.wcBindable.commands};_core;_connectedCallbackPromise=Promise.resolve();constructor(){super(),this._core=new o(this)}get alpha(){return this._core.alpha}get beta(){return this._core.beta}get gamma(){return this._core.gamma}get absolute(){return this._core.absolute}get permissionState(){return this._core.permissionState}get error(){return this._core.error}get connectedCallbackPromise(){return this._connectedCallbackPromise}requestPermission(){return this._core.requestPermission()}start(){this._core.start()}stop(){this._core.stop()}connectedCallback(){this.style.display="none",this._connectedCallbackPromise=this._core.observe()}disconnectedCallback(){this._core.dispose()}}function l(e){var s;e&&((s=e).tagNames&&Object.assign(t.tagNames,s.tagNames),r=null),customElements.get(n.tagNames.tilt)||customElements.define(n.tagNames.tilt,c)}export{o as TiltCore,c as WcsTilt,l as bootstrapTilt,a as getConfig};
|
|
2
|
+
//# sourceMappingURL=index.esm.min.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.min.js","sources":["../src/config.ts","../src/core/TiltCore.ts","../src/components/Tilt.ts","../src/bootstrapTilt.ts","../src/registerComponents.ts"],"sourcesContent":["import { IConfig, IWritableConfig } from \"./types.js\";\n\ninterface IInternalConfig extends IConfig {\n tagNames: {\n tilt: string;\n };\n}\n\nconst _config: IInternalConfig = {\n tagNames: {\n tilt: \"wcs-tilt\",\n },\n};\n\nfunction deepFreeze<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n Object.freeze(obj);\n for (const key of Object.keys(obj)) {\n deepFreeze((obj as Record<string, unknown>)[key]);\n }\n return obj;\n}\n\nfunction deepClone<T>(obj: T): T {\n if (obj === null || typeof obj !== \"object\") return obj;\n const clone: Record<string, unknown> = {};\n for (const key of Object.keys(obj)) {\n clone[key] = deepClone((obj as Record<string, unknown>)[key]);\n }\n return clone as T;\n}\n\nlet frozenConfig: IConfig | null = null;\n\nexport const config: IConfig = _config as IConfig;\n\nexport function getConfig(): IConfig {\n if (!frozenConfig) {\n frozenConfig = deepFreeze(deepClone(_config));\n }\n return frozenConfig;\n}\n\nexport function setConfig(partialConfig: IWritableConfig): void {\n if (partialConfig.tagNames) {\n Object.assign(_config.tagNames, partialConfig.tagNames);\n }\n frozenConfig = null;\n}\n","import { IWcBindable, TiltPermissionState } from \"../types.js\";\n\ninterface DeviceOrientationEventCtor {\n requestPermission?: () => Promise<\"granted\" | \"denied\">;\n}\n\ninterface WcsTiltSnapshot {\n alpha: number | null;\n beta: number | null;\n gamma: number | null;\n absolute: boolean | null;\n}\n\nconst UNSUPPORTED_SNAPSHOT: WcsTiltSnapshot = Object.freeze({\n alpha: null,\n beta: null,\n gamma: null,\n absolute: null,\n});\n\n/**\n * Headless Device Orientation primitive. A thin, framework-agnostic wrapper\n * around `window`'s `deviceorientation` event exposed through the wc-bindable\n * protocol.\n *\n * The batch2 sibling of `@wcstack/idle` (docs/device-orientation-tag-design.md).\n * Unlike Idle Detection, there is no matching Permissions API entry for this\n * feature (`navigator.permissions.query` has no \"device-orientation\" name), so\n * `permissionState` must be tracked **locally** rather than composed with\n * `<wcs-permission>` — the defining asymmetry within batch2.\n *\n * No `_gen` generation guard: subscribing/unsubscribing to `deviceorientation`\n * (start/stop) is fully synchronous, so that path never needs one. This node\n * does have an async probe — `requestPermission()` awaits the static\n * `DeviceOrientationEvent.requestPermission()` — but its post-await write is\n * a benign `permissionState`/`error` value set + dispatch with no\n * subscription/resource management to race, so `_gen` is unneeded there too\n * (docs/device-orientation-tag-design.md §4, corrected after an earlier\n * revision mistakenly reused `@wcstack/network`'s \"no async probe at all\"\n * rationale).\n */\nexport class TiltCore extends EventTarget {\n static wcBindable: IWcBindable = {\n protocol: \"wc-bindable\",\n version: 1,\n properties: [\n { name: \"alpha\", event: \"wcs-tilt:change\", getter: (e: Event) => (e as CustomEvent).detail.alpha },\n { name: \"beta\", event: \"wcs-tilt:change\", getter: (e: Event) => (e as CustomEvent).detail.beta },\n { name: \"gamma\", event: \"wcs-tilt:change\", getter: (e: Event) => (e as CustomEvent).detail.gamma },\n { name: \"absolute\", event: \"wcs-tilt:change\", getter: (e: Event) => (e as CustomEvent).detail.absolute },\n { name: \"permissionState\", event: \"wcs-tilt:permission-changed\" },\n // never-throw (§3.6): requestPermission() failures land here instead of\n // rejecting/throwing. Mirrors idle (same batch2) and the accelerometer\n // family (batch5) — see docs/io-node-batch-implementation-plan.md.\n { name: \"error\", event: \"wcs-tilt:error\" },\n ],\n commands: [\n { name: \"requestPermission\", async: true },\n { name: \"start\" },\n { name: \"stop\" },\n ],\n };\n\n private _target: EventTarget;\n private _snapshot: WcsTiltSnapshot = UNSUPPORTED_SNAPSHOT;\n private _permissionState: TiltPermissionState = \"unknown\";\n private _error: any = null;\n private _subscribed = false;\n\n // SSR (§3.8): never auto-starts on connect, so there is no probe to await —\n // readiness is always immediate.\n private _ready: Promise<void> = Promise.resolve();\n\n constructor(target?: EventTarget) {\n super();\n this._target = target ?? this;\n }\n\n get ready(): Promise<void> {\n return this._ready;\n }\n\n get alpha(): number | null {\n return this._snapshot.alpha;\n }\n\n get beta(): number | null {\n return this._snapshot.beta;\n }\n\n get gamma(): number | null {\n return this._snapshot.gamma;\n }\n\n get absolute(): boolean | null {\n return this._snapshot.absolute;\n }\n\n get permissionState(): TiltPermissionState {\n return this._permissionState;\n }\n\n get error(): any {\n return this._error;\n }\n\n // Lifecycle (§3.5). observe() is a synchronous no-op: like `<wcs-idle>`,\n // this Core deliberately does NOT auto-start on connect (§6) on platforms\n // that gate deviceorientation behind requestPermission().\n observe(): Promise<void> {\n return this._ready;\n }\n\n dispose(): void {\n this.stop();\n }\n\n private _deviceOrientationEventCtor(): DeviceOrientationEventCtor | undefined {\n const g = globalThis as any;\n return typeof g.DeviceOrientationEvent !== \"undefined\" ? g.DeviceOrientationEvent : undefined;\n }\n\n private _setPermissionState(state: TiltPermissionState): void {\n if (this._permissionState === state) return;\n this._permissionState = state;\n this._target.dispatchEvent(new CustomEvent(\"wcs-tilt:permission-changed\", {\n detail: state,\n bubbles: true,\n }));\n }\n\n private _setError(error: any): void {\n if (this._error === error) return;\n this._error = error;\n this._target.dispatchEvent(new CustomEvent(\"wcs-tilt:error\", {\n detail: error,\n bubbles: true,\n }));\n }\n\n /**\n * Wraps iOS 13+ Safari's static, gesture-gated\n * `DeviceOrientationEvent.requestPermission()`. On platforms without this\n * gate (Android Chrome, desktop) there is nothing to ask, so this resolves\n * to `\"granted\"` immediately without querying anything — callers can write\n * one `requestPermission()` → `start()` flow that works everywhere\n * (docs/device-orientation-tag-design.md §3).\n *\n * never-throw (§3.6): a gesture-context rejection resolves to `\"denied\"`\n * and the raw error lands in `error` instead of propagating. Mirrors\n * `<wcs-idle>`'s `requestPermission()` (docs/idle-detection-tag-design.md\n * §4.1) — any settled (non-throwing) outcome supersedes a stale `error`\n * from an earlier attempt.\n */\n async requestPermission(): Promise<TiltPermissionState> {\n const Ctor = this._deviceOrientationEventCtor();\n if (typeof Ctor?.requestPermission !== \"function\") {\n this._setError(null);\n this._setPermissionState(\"granted\");\n return \"granted\";\n }\n try {\n const result = await Ctor.requestPermission();\n const state: TiltPermissionState = result === \"granted\" ? \"granted\" : \"denied\";\n this._setError(null);\n this._setPermissionState(state);\n return state;\n } catch (e) {\n // never-throw: a gesture-context rejection resolves to \"denied\".\n this._setError({ error: e });\n this._setPermissionState(\"denied\");\n return \"denied\";\n }\n }\n\n /** Subscribe to `deviceorientation`. Idempotent — a second start() while already subscribed is a no-op. */\n start(): void {\n if (this._subscribed) return;\n this._subscribed = true;\n globalThis.window?.addEventListener(\"deviceorientation\", this._onOrientation as EventListener);\n }\n\n /** Unsubscribe from `deviceorientation`. Safe to call when not started. */\n stop(): void {\n if (!this._subscribed) return;\n this._subscribed = false;\n globalThis.window?.removeEventListener(\"deviceorientation\", this._onOrientation as EventListener);\n }\n\n private _onOrientation = (event: DeviceOrientationEvent): void => {\n this._apply({\n alpha: event.alpha,\n beta: event.beta,\n gamma: event.gamma,\n absolute: event.absolute,\n });\n };\n\n // Same-value guard (§3.3 MUST).\n private _apply(next: WcsTiltSnapshot): void {\n const prev = this._snapshot;\n if (\n prev.alpha === next.alpha &&\n prev.beta === next.beta &&\n prev.gamma === next.gamma &&\n prev.absolute === next.absolute\n ) {\n return;\n }\n this._snapshot = next;\n this._target.dispatchEvent(new CustomEvent(\"wcs-tilt:change\", {\n detail: next,\n bubbles: true,\n }));\n }\n}\n","import { IWcBindable, TiltPermissionState } from \"../types.js\";\nimport { TiltCore } from \"../core/TiltCore.js\";\n\n/**\n * `<wcs-tilt>` — declarative Device Orientation API monitor.\n *\n * Named `tilt` (not `orientation`/`device-orientation`) to avoid colliding\n * with `<wcs-screen-orientation>` (docs/device-orientation-tag-design.md §9).\n *\n * Does NOT auto-start on connect, mirroring `<wcs-idle>`: on iOS, subscribing\n * before permission is granted silently receives no events. Callers drive\n * `requestPermission()` → `start()` explicitly.\n */\nexport class WcsTilt extends HTMLElement {\n static hasConnectedCallbackPromise = true;\n\n static wcBindable: IWcBindable = {\n ...TiltCore.wcBindable,\n inputs: [],\n // Core の commands をそのまま継承(単一情報源)。\n commands: TiltCore.wcBindable.commands,\n };\n\n private _core: TiltCore;\n private _connectedCallbackPromise: Promise<void> = Promise.resolve();\n\n constructor() {\n super();\n this._core = new TiltCore(this);\n }\n\n // --- Core delegated getters ---\n\n get alpha(): number | null {\n return this._core.alpha;\n }\n\n get beta(): number | null {\n return this._core.beta;\n }\n\n get gamma(): number | null {\n return this._core.gamma;\n }\n\n get absolute(): boolean | null {\n return this._core.absolute;\n }\n\n get permissionState(): TiltPermissionState {\n return this._core.permissionState;\n }\n\n get error(): any {\n return this._core.error;\n }\n\n get connectedCallbackPromise(): Promise<void> {\n return this._connectedCallbackPromise;\n }\n\n // --- Commands (delegated to Core) ---\n\n requestPermission(): Promise<TiltPermissionState> {\n return this._core.requestPermission();\n }\n\n start(): void {\n this._core.start();\n }\n\n stop(): void {\n this._core.stop();\n }\n\n // --- Lifecycle ---\n\n connectedCallback(): void {\n this.style.display = \"none\";\n this._connectedCallbackPromise = this._core.observe();\n }\n\n disconnectedCallback(): void {\n this._core.dispose();\n }\n}\n","import { setConfig } from \"./config.js\";\nimport { registerComponents } from \"./registerComponents.js\";\nimport { IWritableConfig } from \"./types.js\";\n\nexport function bootstrapTilt(userConfig?: IWritableConfig): void {\n if (userConfig) {\n setConfig(userConfig);\n }\n registerComponents();\n}\n","import { WcsTilt } from \"./components/Tilt.js\";\nimport { config } from \"./config.js\";\n\nexport function registerComponents(): void {\n if (!customElements.get(config.tagNames.tilt)) {\n customElements.define(config.tagNames.tilt, WcsTilt);\n }\n}\n"],"names":["_config","tagNames","tilt","deepFreeze","obj","Object","freeze","key","keys","deepClone","clone","frozenConfig","config","getConfig","UNSUPPORTED_SNAPSHOT","alpha","beta","gamma","absolute","TiltCore","EventTarget","static","protocol","version","properties","name","event","getter","e","detail","commands","async","_target","_snapshot","_permissionState","_error","_subscribed","_ready","Promise","resolve","constructor","target","super","this","ready","permissionState","error","observe","dispose","stop","_deviceOrientationEventCtor","g","globalThis","DeviceOrientationEvent","undefined","_setPermissionState","state","dispatchEvent","CustomEvent","bubbles","_setError","requestPermission","Ctor","start","window","addEventListener","_onOrientation","removeEventListener","_apply","next","prev","WcsTilt","HTMLElement","wcBindable","inputs","_core","_connectedCallbackPromise","connectedCallbackPromise","connectedCallback","style","display","disconnectedCallback","bootstrapTilt","userConfig","partialConfig","assign","customElements","get","define"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wcstack/tilt",
|
|
3
|
+
"version": "1.16.0",
|
|
4
|
+
"description": "Declarative Device Orientation component for Web Components. Framework-agnostic deviceorientation wrapper via wc-bindable-protocol.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.esm.js",
|
|
7
|
+
"module": "./dist/index.esm.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.esm.js"
|
|
13
|
+
},
|
|
14
|
+
"./auto": "./dist/auto.min.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"clean": "rimraf dist .tsc-out",
|
|
21
|
+
"build": "rimraf dist .tsc-out && tsc && rollup -c",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest",
|
|
24
|
+
"test:coverage": "vitest run --coverage",
|
|
25
|
+
"lint": "eslint src",
|
|
26
|
+
"version:patch": "npm version patch",
|
|
27
|
+
"version:minor": "npm version minor",
|
|
28
|
+
"version:major": "npm version major",
|
|
29
|
+
"prepublishOnly": "npm run build && npm run test:coverage"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"web-components",
|
|
33
|
+
"device-orientation",
|
|
34
|
+
"tilt",
|
|
35
|
+
"custom-elements",
|
|
36
|
+
"wc-bindable",
|
|
37
|
+
"declarative",
|
|
38
|
+
"zero-dependencies",
|
|
39
|
+
"framework-agnostic"
|
|
40
|
+
],
|
|
41
|
+
"author": "mogera551",
|
|
42
|
+
"homepage": "https://wcstack.github.io",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/wcstack/wcstack.git",
|
|
46
|
+
"directory": "packages/tilt"
|
|
47
|
+
},
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/wcstack/wcstack/issues"
|
|
50
|
+
},
|
|
51
|
+
"license": "MIT",
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@eslint/js": "^9.39.1",
|
|
54
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
55
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
56
|
+
"@vitest/coverage-v8": "^4.0.15",
|
|
57
|
+
"@vitest/ui": "^4.0.15",
|
|
58
|
+
"eslint": "^9.39.1",
|
|
59
|
+
"globals": "^16.5.0",
|
|
60
|
+
"happy-dom": "^20.0.11",
|
|
61
|
+
"rimraf": "^6.0.1",
|
|
62
|
+
"rollup": "^4.22.4",
|
|
63
|
+
"rollup-plugin-dts": "^6.1.1",
|
|
64
|
+
"rollup-plugin-copy": "^3.5.0",
|
|
65
|
+
"tslib": "^2.8.1",
|
|
66
|
+
"typescript": "^5.9.3",
|
|
67
|
+
"typescript-eslint": "^8.49.0",
|
|
68
|
+
"vitest": "^4.0.15"
|
|
69
|
+
}
|
|
70
|
+
}
|