parent
8b195e38e2
commit
802ebce655
@ -0,0 +1,102 @@
|
|||||||
|
/**
|
||||||
|
* Sema channel contract.
|
||||||
|
*
|
||||||
|
* This is the single source for runtime channel ids, channel signatures and
|
||||||
|
* per-channel overrides. `sema-map.ts` owns data; this file owns the open
|
||||||
|
* channel type surface that both the map and event declarations consume.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface SoundSignature {
|
||||||
|
pitch: number;
|
||||||
|
centroid: number;
|
||||||
|
roughness: number;
|
||||||
|
attack: number;
|
||||||
|
decay: number;
|
||||||
|
duration: number;
|
||||||
|
contour: 'flat' | 'ascending' | 'descending' | 'arc' | 'bell';
|
||||||
|
gain: number;
|
||||||
|
sampleUrl?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Haptic / vibration feedback. Categorical `kind` lets future channels map
|
||||||
|
* to platform haptic primitives (iOS Haptic Engine, Android
|
||||||
|
* HapticFeedbackConstants) without breaking consumers; V1 of `HapticChannel`
|
||||||
|
* implements the Vibration API path with intensity-modulated durations.
|
||||||
|
*/
|
||||||
|
export interface HapticSignature {
|
||||||
|
/**
|
||||||
|
* Categorical pattern. Maps to system primitives where available; falls
|
||||||
|
* back to a Vibration API pattern derived from `duration` + `intensity`.
|
||||||
|
*/
|
||||||
|
kind: 'tick' | 'tap' | 'pulse' | 'thud' | 'success' | 'warning' | 'error';
|
||||||
|
|
||||||
|
/** 0..1. Modulates Vibration API duration; ignored on categorical-only platforms. */
|
||||||
|
intensity: number;
|
||||||
|
|
||||||
|
/** Base pulse duration in ms (single Vibration API pulse). */
|
||||||
|
duration: number;
|
||||||
|
|
||||||
|
/** Explicit on/off/on/off… pattern in ms. */
|
||||||
|
pattern?: readonly number[];
|
||||||
|
|
||||||
|
/** Delay relative to signal start (ms). */
|
||||||
|
delay?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Canonical channel registry. Apps extend it via declaration merging:
|
||||||
|
*
|
||||||
|
* declare module '$uix/sema' {
|
||||||
|
* interface SemaChannelSignatures {
|
||||||
|
* a11y: A11ySignature;
|
||||||
|
* voice: VoiceSignature;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export interface SemaChannelSignatures {
|
||||||
|
sound: SoundSignature;
|
||||||
|
haptic: HapticSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open string id of a channel. Known channels autocomplete in editors;
|
||||||
|
* arbitrary strings are accepted for channels registered with the engine but
|
||||||
|
* without a typed signature slice.
|
||||||
|
*/
|
||||||
|
export type SemaChannelId = keyof SemaChannelSignatures | (string & {});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime channels are the things the engine actually dispatches to.
|
||||||
|
* Visual dimensions (`motion`, `color`, `presence`) are not channels.
|
||||||
|
*/
|
||||||
|
export type SemaRuntimeChannelId = 'visual' | 'sound' | 'haptic' | (string & {});
|
||||||
|
|
||||||
|
export type DeltaOp =
|
||||||
|
| { op: 'multiply'; factor: number }
|
||||||
|
| { op: 'replace'; value: number | string | boolean | null | readonly DeltaValue[] }
|
||||||
|
| { op: 'add'; value: number };
|
||||||
|
|
||||||
|
export type DeltaValue =
|
||||||
|
| number
|
||||||
|
| string
|
||||||
|
| boolean
|
||||||
|
| null
|
||||||
|
| DeltaOp
|
||||||
|
| readonly DeltaValue[]
|
||||||
|
| { [key: string]: DeltaValue };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Per-channel partial override applied at resolution time.
|
||||||
|
*/
|
||||||
|
export type SemaSignatureOverride = {
|
||||||
|
/**
|
||||||
|
* Replace the active-channel list for matching signals. Last-write-wins
|
||||||
|
* across the cascade. Empty array silences the signal entirely.
|
||||||
|
*/
|
||||||
|
channels?: readonly SemaChannelId[];
|
||||||
|
} & {
|
||||||
|
[K in keyof SemaChannelSignatures]?:
|
||||||
|
| Partial<SemaChannelSignatures[K]>
|
||||||
|
| Record<string, DeltaValue>;
|
||||||
|
};
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
export const SIDE_OPTIONS = ['top', 'right', 'bottom', 'left'] as const;
|
||||||
|
export const ALIGN_OPTIONS = ['start', 'center', 'end'] as const;
|
||||||
|
|
||||||
|
export type Side = (typeof SIDE_OPTIONS)[number];
|
||||||
|
export type Align = (typeof ALIGN_OPTIONS)[number];
|
||||||
|
export type Boundary = Element | null;
|
||||||
|
|
||||||
|
export const OPPOSITE_SIDE: Record<Side, Side> = {
|
||||||
|
top: 'bottom',
|
||||||
|
right: 'left',
|
||||||
|
bottom: 'top',
|
||||||
|
left: 'right'
|
||||||
|
};
|
||||||
Loading…
Reference in new issue