oneko 0.3.0 → 0.4.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.
Files changed (41) hide show
  1. package/dist/chunks/{vanilla-CUrawvWx.js → vanilla-BNtPCdx5.js} +1079 -72
  2. package/dist/index.js +29 -7
  3. package/dist/solid.js +8 -3
  4. package/dist/svelte/Oneko.svelte +14 -4
  5. package/dist/svelte/Oneko.svelte.d.ts +2 -2
  6. package/dist/types/components/oneko.d.ts +12 -2
  7. package/dist/types/lib/oneko/affection.d.ts +16 -0
  8. package/dist/types/lib/oneko/animation/deps.d.ts +2 -0
  9. package/dist/types/lib/oneko/animation/errand-point.d.ts +7 -0
  10. package/dist/types/lib/oneko/animation/frame.d.ts +2 -1
  11. package/dist/types/lib/oneko/animation/play-types.d.ts +56 -0
  12. package/dist/types/lib/oneko/animation/play.d.ts +12 -0
  13. package/dist/types/lib/oneko/constants.d.ts +1 -0
  14. package/dist/types/lib/oneko/controls.d.ts +28 -0
  15. package/dist/types/lib/oneko/defaults.d.ts +5 -0
  16. package/dist/types/lib/oneko/initial-state.d.ts +4 -0
  17. package/dist/types/lib/oneko/mood.d.ts +7 -0
  18. package/dist/types/lib/oneko/pack.d.ts +4 -0
  19. package/dist/types/lib/oneko/pixel-art.d.ts +5 -0
  20. package/dist/types/lib/oneko/play-messages.d.ts +8 -0
  21. package/dist/types/lib/oneko/runtime-config.d.ts +2 -2
  22. package/dist/types/lib/oneko/seasons.d.ts +27 -0
  23. package/dist/types/lib/oneko/treats.d.ts +15 -0
  24. package/dist/types/lib/oneko/types.d.ts +61 -0
  25. package/dist/types/lib/oneko/vanilla.d.ts +3 -1
  26. package/dist/types/packages/oneko/src/solid.d.ts +5 -2
  27. package/dist/types/packages/oneko/src/vanilla.d.ts +2 -1
  28. package/dist/types/packages/oneko/src/vue.d.ts +71 -4
  29. package/dist/vanilla.js +4 -4
  30. package/dist/vue.js +38 -8
  31. package/package.json +1 -1
  32. package/dist/cat-sounds/Cat_royal_ambient5.ogg +0 -1
  33. package/dist/cat-sounds/Cat_royal_ambient6.ogg +0 -1
  34. package/dist/cat-sounds/Cat_royal_death.ogg +0 -1
  35. package/dist/cat-sounds/Cat_royal_hurt1.ogg +0 -1
  36. package/dist/cat-sounds/Cat_royal_hurt2.ogg +0 -1
  37. package/dist/cat-sounds/Cat_royal_hurt3.ogg +0 -1
  38. package/dist/cat-sounds/Stray_cat_idle1.ogg +0 -1
  39. package/dist/cat-sounds/Stray_cat_idle2.ogg +0 -1
  40. package/dist/cat-sounds/Stray_cat_idle3.ogg +0 -1
  41. package/dist/cat-sounds/Stray_cat_idle4.ogg +0 -1
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { jsx } from "react/jsx-runtime";
3
- import { useEffect, useRef, useState, useSyncExternalStore } from "react";
4
- import { m as mountLaserCursor, s as startCatAnimation, g as getSkinSource, l as loadSkinSource, a as applyRuntimeConfig, b as createInitialCatState, O as ONEKO_DEFAULTS, r as readPersistedPosition, o as onCatsHiddenChange, d as areCatsHidden, T as TILE } from "./chunks/vanilla-CUrawvWx.js";
5
- import { e, c, i, f } from "./chunks/vanilla-CUrawvWx.js";
3
+ import { useEffect, useRef, useState, useSyncExternalStore, useImperativeHandle } from "react";
4
+ import { m as mountLaserCursor, s as startCatAnimation, g as getSkinSource, l as loadSkinSource, a as applyRuntimeConfig, b as createInitialCatState, O as ONEKO_DEFAULTS, d as createCatControls, r as readPersistedPosition, o as onCatsHiddenChange, e as areCatsHidden, T as TILE } from "./chunks/vanilla-BNtPCdx5.js";
5
+ import { f, c, i, h } from "./chunks/vanilla-BNtPCdx5.js";
6
6
  function LaserCursor({ zIndex }) {
7
7
  useEffect(() => mountLaserCursor(zIndex), [zIndex]);
8
8
  return null;
@@ -158,7 +158,18 @@ function Oneko({
158
158
  napWhileTyping = ONEKO_DEFAULTS.napWhileTyping,
159
159
  followFocus = ONEKO_DEFAULTS.followFocus,
160
160
  perchOnHover = ONEKO_DEFAULTS.perchOnHover,
161
- pettable = ONEKO_DEFAULTS.pettable
161
+ pettable = ONEKO_DEFAULTS.pettable,
162
+ seasonal = ONEKO_DEFAULTS.seasonal,
163
+ grabbable = ONEKO_DEFAULTS.grabbable,
164
+ treats = ONEKO_DEFAULTS.treats,
165
+ timeOfDay = ONEKO_DEFAULTS.timeOfDay,
166
+ affection = ONEKO_DEFAULTS.affection,
167
+ onPet,
168
+ onCatchCursor,
169
+ onSleep,
170
+ onToss,
171
+ onTreat,
172
+ ref
162
173
  }) {
163
174
  const hidden = useCatsHidden();
164
175
  const motionAllowed = useMotionAllowed() && !hidden;
@@ -200,10 +211,21 @@ function Oneko({
200
211
  chase,
201
212
  napWhileTyping,
202
213
  followFocus,
203
- perchOnHover
214
+ perchOnHover,
215
+ seasonal,
216
+ grabbable,
217
+ treats,
218
+ timeOfDay,
219
+ affection,
220
+ onPet,
221
+ onCatchCursor,
222
+ onSleep,
223
+ onToss,
224
+ onTreat
204
225
  };
205
226
  const [initialState] = useState(() => createInitialCatState({ initialPos, ...config }));
206
227
  const stateRef = useRef(initialState);
228
+ useImperativeHandle(ref, () => createCatControls(stateRef), []);
207
229
  useCatAnimation({
208
230
  enabled: motionAllowed,
209
231
  stateRef,
@@ -274,13 +296,13 @@ function RestingCat({
274
296
  );
275
297
  }
276
298
  export {
277
- e as ONEKO_SKINS,
299
+ f as ONEKO_SKINS,
278
300
  Oneko,
279
301
  areCatsHidden,
280
302
  c as createOneko,
281
303
  Oneko as default,
282
304
  i as isOnekoSkin,
283
305
  onCatsHiddenChange,
284
- f as setCatsHidden,
306
+ h as setCatsHidden,
285
307
  useCatsHidden
286
308
  };
package/dist/solid.js CHANGED
@@ -1,15 +1,20 @@
1
1
  import { onMount, onCleanup, createEffect } from "solid-js";
2
- import { c as createOneko } from "./chunks/vanilla-CUrawvWx.js";
2
+ import { c as createOneko } from "./chunks/vanilla-BNtPCdx5.js";
3
3
  import { createPropsUpdater } from "./adapter.js";
4
4
  function Oneko(props) {
5
5
  let update;
6
+ const options = () => {
7
+ const { ref: _ref, ...rest } = props;
8
+ return rest;
9
+ };
6
10
  onMount(() => {
7
11
  const cat = createOneko();
8
12
  update = createPropsUpdater(cat);
9
- update({ ...props });
13
+ update(options());
14
+ props.ref?.(cat);
10
15
  onCleanup(() => cat.destroy());
11
16
  });
12
- createEffect(() => update?.({ ...props }));
17
+ createEffect(() => update?.(options()));
13
18
  return null;
14
19
  }
15
20
  export {
@@ -1,16 +1,26 @@
1
1
  <script lang="ts">
2
2
  import { onMount } from "svelte";
3
- import { createOneko, type OnekoOptions } from "../vanilla.js";
3
+ import { createOneko, type OnekoControls, type OnekoInstance, type OnekoOptions } from "../vanilla.js";
4
4
  import { createPropsUpdater } from "../adapter.js";
5
5
 
6
6
  const props: OnekoOptions = $props();
7
7
  let update = $state.raw<ReturnType<typeof createPropsUpdater>>();
8
+ let cat: OnekoInstance | undefined;
9
+
10
+ // bind:this gives the controls: cat.goTo("#pricing"), cat.say("hi").
11
+ export const goTo: OnekoControls["goTo"] = (target) => cat?.goTo(target) ?? Promise.resolve(false);
12
+ export const say: OnekoControls["say"] = (text, options) => cat?.say(text, options);
13
+ export const sit = () => cat?.sit();
14
+ export const follow = () => cat?.follow();
15
+ export const pet = () => cat?.pet();
16
+ export const dropTreat: OnekoControls["dropTreat"] = (x, y) => cat?.dropTreat(x, y);
8
17
 
9
18
  onMount(() => {
10
- const cat = createOneko();
11
- update = createPropsUpdater(cat);
19
+ const created = createOneko();
20
+ cat = created;
21
+ update = createPropsUpdater(created);
12
22
  update({ ...props });
13
- return () => cat.destroy();
23
+ return () => created.destroy();
14
24
  });
15
25
 
16
26
  $effect(() => update?.({ ...props }));
@@ -1,4 +1,4 @@
1
1
  import type { Component } from "svelte";
2
- import type { OnekoOptions } from "../types/packages/oneko/src/vanilla";
3
- declare const Oneko: Component<OnekoOptions>;
2
+ import type { OnekoControls, OnekoOptions } from "../types/packages/oneko/src/vanilla";
3
+ declare const Oneko: Component<OnekoOptions, OnekoControls>;
4
4
  export default Oneko;
@@ -1,6 +1,13 @@
1
+ /**
2
+ * Installable React component — the classic “cat follows the cursor” idea comes from
3
+ * oneko.js (MIT): https://github.com/adryd325/oneko.js/
4
+ */
5
+ import { type Ref } from "react";
6
+ import { type OnekoControls } from "../lib/oneko/controls";
1
7
  import { setCatsHidden } from "../lib/oneko/pack";
2
8
  import type { CatActivityState, CatLiveState, OnekoProps } from "../lib/oneko/types";
3
- export type { CatActivityState, CatLiveState, OnekoProps };
9
+ export type { CatActivityState, CatLiveState, OnekoControls, OnekoProps };
10
+ export type { OnekoSeason } from "../lib/oneko/seasons";
4
11
  export type { OnekoSkin } from "../lib/oneko/skins";
5
12
  export type { OnekoZone } from "../lib/oneko/zones";
6
13
  export { setCatsHidden };
@@ -8,4 +15,7 @@ export { setCatsHidden };
8
15
  export declare function useCatsHidden(): boolean;
9
16
  export default function Oneko({ paused, followCursor, sleepEnabled, bubblePlacement, bubbleScale, soundBasePath, storageKey, zones, zoneAttractionChance, zoneAttractionDuration, skin, spriteSrc, persistPosition,
10
17
  /** One below max so fixed UI can sit above the cat. */
11
- zIndex, initialPos, speed, scale, opacity, rotationAmount, idleThreshold, meow, onStateChange, freerunChance, freerunDuration, bubbleEnabled, bubbleDisplayFrames, bubbleCooldown, hueRotate, liveStateRef, bubbleChance, followDistance, animationSpeed, bubbleText, volume, laserPointer, reducedMotion, chase, napWhileTyping, followFocus, perchOnHover, pettable, }: OnekoProps): import("react/jsx-runtime").JSX.Element | null;
18
+ zIndex, initialPos, speed, scale, opacity, rotationAmount, idleThreshold, meow, onStateChange, freerunChance, freerunDuration, bubbleEnabled, bubbleDisplayFrames, bubbleCooldown, hueRotate, liveStateRef, bubbleChance, followDistance, animationSpeed, bubbleText, volume, laserPointer, reducedMotion, chase, napWhileTyping, followFocus, perchOnHover, pettable, seasonal, grabbable, treats, timeOfDay, affection, onPet, onCatchCursor, onSleep, onToss, onTreat, ref, }: OnekoProps & {
19
+ /** Imperative controls: goTo, say, sit, follow, pet, and dropTreat. */
20
+ ref?: Ref<OnekoControls>;
21
+ }): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,16 @@
1
+ export type SavedAffection = {
2
+ version: 1;
3
+ affection: number;
4
+ lastVisit: number;
5
+ };
6
+ /** A visit this long after the last one earns a greeting. */
7
+ export declare const GREETING_GAP_MS: number;
8
+ export declare const MAX_AFFECTION = 999;
9
+ export declare function parseAffection(value: unknown): SavedAffection | null;
10
+ export declare function readAffection(key: string): SavedAffection | null;
11
+ export declare function writeAffection(key: string, affection: number, lastVisit?: number): void;
12
+ /** 0 stranger, 1 acquaintance, 2 friend, 3 best friend. */
13
+ export declare function affectionTier(affection: number): 0 | 1 | 2 | 3;
14
+ export declare const GREETINGS: Record<ReturnType<typeof affectionTier>, readonly string[]>;
15
+ /** A greeting for a visitor, or null when they were here a moment ago. */
16
+ export declare function greetingFor(saved: SavedAffection | null, now?: number): string | null;
@@ -18,4 +18,6 @@ export interface CatAnimationDeps {
18
18
  liveStateRef?: {
19
19
  current: CatLiveState;
20
20
  };
21
+ /** Seasonal hat drawn on the cat, repositioned with every sprite frame. */
22
+ hat?: HTMLDivElement;
21
23
  }
@@ -0,0 +1,7 @@
1
+ import type { CatRuntimeState, PathPoint } from "../types";
2
+ import type { Errand } from "./play-types";
3
+ /**
4
+ * Where an errand takes the cat, in viewport coordinates, or null when its element is gone or
5
+ * off screen. Element targets are re-read every tick, so they follow scrolling and layout.
6
+ */
7
+ export declare function errandPoint(s: CatRuntimeState, errand: Errand): PathPoint | null;
@@ -1,2 +1,3 @@
1
1
  import type { CatAnimationDeps } from "./deps";
2
- export declare function createFrameLoop(deps: CatAnimationDeps): () => void;
2
+ import type { CatPlay } from "./play";
3
+ export declare function createFrameLoop(deps: CatAnimationDeps, play?: CatPlay): () => void;
@@ -0,0 +1,56 @@
1
+ import type { Treat } from "../treats";
2
+ export type PointLike = {
3
+ x: number;
4
+ y: number;
5
+ };
6
+ /** Something the cat goes off to do instead of chasing the cursor. */
7
+ export type Errand = {
8
+ kind: "goTo";
9
+ target: Element | PointLike;
10
+ frames: number;
11
+ arrived: boolean;
12
+ resolve?: (arrived: boolean) => void;
13
+ } | {
14
+ kind: "sit";
15
+ } | {
16
+ kind: "treat";
17
+ treat: Treat;
18
+ frames: number;
19
+ } | {
20
+ kind: "box";
21
+ el: Element;
22
+ frames: number;
23
+ arrived: boolean;
24
+ } | {
25
+ kind: "knock";
26
+ el: Element;
27
+ frames: number;
28
+ phase: "approach" | "stare";
29
+ /** 1 pushes the element to the right, -1 to the left. */
30
+ direction: 1 | -1;
31
+ };
32
+ export type GrabState = {
33
+ phase: "held";
34
+ samples: {
35
+ x: number;
36
+ y: number;
37
+ t: number;
38
+ }[];
39
+ startT: number;
40
+ travel: number;
41
+ } | {
42
+ phase: "flying";
43
+ vx: number;
44
+ vy: number;
45
+ spin: number;
46
+ hard: boolean;
47
+ } | {
48
+ phase: "landed";
49
+ frames: number;
50
+ };
51
+ /** Multipliers from the visitor's clock; all 1 when timeOfDay is off. */
52
+ export type Mood = {
53
+ speed: number;
54
+ freerun: number;
55
+ idle: number;
56
+ };
@@ -0,0 +1,12 @@
1
+ import type { CatAnimationDeps } from "./deps";
2
+ /** Pet the cat: a purr, a bubble, and a little more affection. */
3
+ export declare function petCat(deps: CatAnimationDeps): void;
4
+ /** Put every knocked-over element back, for when the last cat leaves. */
5
+ export declare function restoreKnocked(): void;
6
+ export declare function createPlay(deps: CatAnimationDeps): {
7
+ upkeep: () => void;
8
+ tickGrab: () => boolean;
9
+ tickErrand: () => void;
10
+ dispose: () => void;
11
+ };
12
+ export type CatPlay = ReturnType<typeof createPlay>;
@@ -44,6 +44,7 @@ export declare const DEFAULT_ANIMATION_SPEED = 1;
44
44
  export declare const PET_MESSAGES: string[];
45
45
  export declare const PET_SOUND_POOL: string[];
46
46
  export declare const LASER_CATCH_POOL: string[];
47
+ export declare const HISS_POOL: string[];
47
48
  export declare const SOUND_POOLS: Record<CatActivityState, string[]>;
48
49
  export declare const KONAMI_SEQUENCE: string[];
49
50
  export declare const KONAMI_TARGET: string;
@@ -0,0 +1,28 @@
1
+ import type { CatRuntimeState } from "./types";
2
+ /** Imperative controls for a running cat, for tours, games, and onboarding. */
3
+ export interface OnekoControls {
4
+ /**
5
+ * Walk to an element (or a CSS selector, or a viewport point) and stay there until follow() or
6
+ * another request. Resolves true on arrival, false if the cat is sent elsewhere first or the
7
+ * target disappears.
8
+ */
9
+ goTo(target: Element | string | {
10
+ x: number;
11
+ y: number;
12
+ }): Promise<boolean>;
13
+ /** Show a bubble now, even when automatic bubbles are off. Duration defaults to bubbleDisplayFrames. */
14
+ say(text: string, options?: {
15
+ duration?: number;
16
+ }): void;
17
+ /** Sit where the cat is until follow(). */
18
+ sit(): void;
19
+ /** Go back to chasing the cursor after goTo() or sit(). */
20
+ follow(): void;
21
+ /** Pet the cat, as if a visitor did. */
22
+ pet(): void;
23
+ /** Drop a treat at a viewport point, or at the cursor. Works without the treats option. */
24
+ dropTreat(x?: number, y?: number): void;
25
+ }
26
+ export declare function createCatControls(stateRef: {
27
+ current: CatRuntimeState;
28
+ }): OnekoControls;
@@ -36,4 +36,9 @@ export declare const ONEKO_DEFAULTS: {
36
36
  followFocus: boolean;
37
37
  perchOnHover: boolean;
38
38
  pettable: boolean;
39
+ seasonal: NonNullable<OnekoProps["seasonal"]>;
40
+ grabbable: boolean;
41
+ treats: boolean;
42
+ timeOfDay: boolean;
43
+ affection: boolean;
39
44
  };
@@ -1,5 +1,8 @@
1
1
  import { type CatRuntimeConfig } from "./runtime-config";
2
2
  import type { CatRuntimeState } from "./types";
3
+ type PlayStateFields = Pick<CatRuntimeState, "season" | "grab" | "errand" | "errandCooldown" | "sayRequest" | "bubbleForced" | "petRequest" | "chasingFar" | "mood" | "moodCheckedFrame" | "affection" | "affectionLoaded" | "affectionKey" | "zIndex">;
4
+ /** Fresh state for treats, tosses, errands, seasons, and the API. */
5
+ export declare function defaultPlayState(): PlayStateFields;
3
6
  export type InitialCatStateOptions = CatRuntimeConfig & {
4
7
  initialPos?: {
5
8
  x: number;
@@ -7,3 +10,4 @@ export type InitialCatStateOptions = CatRuntimeConfig & {
7
10
  };
8
11
  };
9
12
  export declare function createInitialCatState(options: InitialCatStateOptions): CatRuntimeState;
13
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { Mood } from "./animation/play-types";
2
+ export declare const NEUTRAL_MOOD: Mood;
3
+ /**
4
+ * How a cat feels at a local hour. Cats are crepuscular: most playful at dawn and dusk, drowsy
5
+ * in the early afternoon, and asleep in the small hours. idle scales the rest time before naps.
6
+ */
7
+ export declare function moodForHour(hour: number): Mood;
@@ -2,6 +2,10 @@ import type { CatRuntimeState, PathPoint } from "./types";
2
2
  export declare function joinPack(state: CatRuntimeState): () => void;
3
3
  /** Where the cat ahead of this one is, or null when it leads (or chases the cursor). */
4
4
  export declare function leaderPosition(state: CatRuntimeState): PathPoint | null;
5
+ /** True when no other running cat is closer to a point, so only one cat answers a page event. */
6
+ export declare function isNearestCat(state: CatRuntimeState, point: PathPoint): boolean;
7
+ /** How many cats are running on the page. */
8
+ export declare function packSize(): number;
5
9
  /** True when another cat is asleep close enough to curl up next to. */
6
10
  export declare function napmateNearby(state: CatRuntimeState): boolean;
7
11
  /** Visitor preference, shared by every cat on the site and remembered across visits. */
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Inline SVG for pixel art given as rows of characters ("." is transparent), outlined in the
3
+ * sprite's dark ink so it reads on light and dark pages. The result is one pixel larger on each side.
4
+ */
5
+ export declare function pixelArtSVG(rows: readonly string[], colors: Record<string, string>): string;
@@ -0,0 +1,8 @@
1
+ export declare const TREAT_MESSAGES: string[];
2
+ export declare const TOSS_SOFT_MESSAGES: string[];
3
+ export declare const TOSS_HARD_MESSAGES: string[];
4
+ export declare const HELD_MESSAGES: string[];
5
+ export declare const BOX_MESSAGES: string[];
6
+ export declare const KNOCK_STARE_MESSAGES: string[];
7
+ export declare const KNOCK_MESSAGES: string[];
8
+ export declare const FOND_PET_MESSAGES: string[];
@@ -1,8 +1,8 @@
1
1
  import type { OnekoZone } from "./zones";
2
2
  import type { CatRuntimeState, OnekoProps } from "./types";
3
- type RuntimeConfigStateFields = Pick<CatRuntimeState, "pausedCfg" | "followCursorCfg" | "sleepEnabledCfg" | "bubblePlacementCfg" | "bubbleScaleCfg" | "soundBasePathCfg" | "currentSpeed" | "scale" | "opacity" | "rotationAmount" | "idleThresholdMs" | "freerunChanceCfg" | "freerunDurationCfg" | "bubbleEnabledCfg" | "bubbleDisplayFramesCfg" | "bubbleCooldownFramesCfg" | "bubbleChanceCfg" | "followDistanceCfg" | "animationSpeedCfg" | "customBubbleText" | "currentRotation" | "enableMeow" | "soundVolumeCfg" | "soundCooldown" | "bubbleTimer" | "bubbleCooldown" | "bubbleVisible" | "lastBubbleMsg" | "laserPointerCfg" | "laserCaught" | "chaseCfg" | "napWhileTypingCfg" | "followFocusCfg" | "perchOnHoverCfg">;
3
+ type RuntimeConfigStateFields = Pick<CatRuntimeState, "pausedCfg" | "followCursorCfg" | "sleepEnabledCfg" | "bubblePlacementCfg" | "bubbleScaleCfg" | "soundBasePathCfg" | "currentSpeed" | "scale" | "opacity" | "rotationAmount" | "idleThresholdMs" | "freerunChanceCfg" | "freerunDurationCfg" | "bubbleEnabledCfg" | "bubbleDisplayFramesCfg" | "bubbleCooldownFramesCfg" | "bubbleChanceCfg" | "followDistanceCfg" | "animationSpeedCfg" | "customBubbleText" | "currentRotation" | "enableMeow" | "soundVolumeCfg" | "soundCooldown" | "bubbleTimer" | "bubbleCooldown" | "bubbleVisible" | "lastBubbleMsg" | "laserPointerCfg" | "laserCaught" | "chaseCfg" | "napWhileTypingCfg" | "followFocusCfg" | "perchOnHoverCfg" | "seasonalCfg" | "grabbableCfg" | "treatsCfg" | "timeOfDayCfg" | "affectionCfg" | "handlers">;
4
4
  export declare function defaultRuntimeConfigState(): RuntimeConfigStateFields;
5
- export type CatRuntimeConfig = Pick<OnekoProps, "paused" | "followCursor" | "sleepEnabled" | "bubblePlacement" | "bubbleScale" | "soundBasePath" | "chase" | "napWhileTyping" | "followFocus" | "perchOnHover"> & {
5
+ export type CatRuntimeConfig = Pick<OnekoProps, "paused" | "followCursor" | "sleepEnabled" | "bubblePlacement" | "bubbleScale" | "soundBasePath" | "chase" | "napWhileTyping" | "followFocus" | "perchOnHover" | "seasonal" | "grabbable" | "treats" | "timeOfDay" | "affection" | "onPet" | "onCatchCursor" | "onSleep" | "onToss" | "onTreat"> & {
6
6
  zones?: readonly OnekoZone[];
7
7
  zoneAttractionChance?: number;
8
8
  zoneAttractionDuration?: number;
@@ -0,0 +1,27 @@
1
+ /** Seasonal dress-up: a pixel hat and a few themed thoughts around a holiday. */
2
+ export type OnekoSeason = "halloween" | "winter" | "newYear";
3
+ export declare const ONEKO_SEASONS: readonly ["halloween", "winter", "newYear"];
4
+ export declare function isOnekoSeason(value: unknown): value is OnekoSeason;
5
+ /**
6
+ * The season on a date in the visitor's local time, or null. Halloween runs Oct 20–31, winter
7
+ * Dec 18–29, and the new year Dec 30–Jan 2.
8
+ */
9
+ export declare function seasonForDate(date: Date): OnekoSeason | null;
10
+ /** Which season to dress for: true follows the calendar, a season name forces it, false opts out. */
11
+ export declare function resolveSeason(setting: boolean | OnekoSeason, date?: Date): OnekoSeason | null;
12
+ export declare const SEASON_MESSAGES: Record<OnekoSeason, readonly string[]>;
13
+ /** Hat size in sprite pixels, including the one-pixel outline on every side. */
14
+ export declare const HAT_WIDTH = 13;
15
+ export declare const HAT_HEIGHT = 10;
16
+ /** Inline SVG for a season's hat. */
17
+ export declare function hatSVG(season: OnekoSeason): string;
18
+ /** Offset of the hat's top-left corner within a sprite frame, or null for an unknown frame. */
19
+ export declare function hatOffset(spriteX: number, spriteY: number): {
20
+ left: number;
21
+ top: number;
22
+ } | null;
23
+ /**
24
+ * Where the top of the head is in each 32 × 32 frame, keyed by the sprite offsets used in
25
+ * constants.ts ("-col,-row"). Values are [x, y] of the hat's bottom center within the frame.
26
+ */
27
+ export declare const HAT_ANCHORS: Record<string, readonly [number, number]>;
@@ -0,0 +1,15 @@
1
+ /** A treat on the page, shared by every cat: the first to reach it eats it. */
2
+ export interface Treat {
3
+ x: number;
4
+ y: number;
5
+ el: HTMLDivElement;
6
+ eaten: boolean;
7
+ }
8
+ export declare function availableTreats(): readonly Treat[];
9
+ /** The uneaten treat closest to a point, or undefined when the floor is clean. */
10
+ export declare function nearestTreat(x: number, y: number, skip?: (treat: Treat) => boolean): Treat | undefined;
11
+ /** Drop a treat at a viewport point. Older treats disappear past five on the floor. */
12
+ export declare function dropTreat(x: number, y: number, zIndex: number): Treat;
13
+ /** Eat a treat. Returns false when another cat got there first. */
14
+ export declare function eatTreat(treat: Treat): boolean;
15
+ export declare function clearTreats(): void;
@@ -1,6 +1,8 @@
1
1
  import type { OnekoZone } from "./zones";
2
2
  import type { ZoneRuntimeState } from "./zone-runtime";
3
3
  import type { OnekoSkin } from "./skins";
4
+ import type { OnekoSeason } from "./seasons";
5
+ import type { Errand, GrabState, Mood } from "./animation/play-types";
4
6
  export type CatActivityState = "idle" | "moving" | "sleeping" | "scratchSelf" | "tired" | "alert" | "scratchWallN" | "scratchWallS" | "scratchWallE" | "scratchWallW" | "freerun";
5
7
  export type IdleActivityState = Exclude<CatActivityState, "idle" | "moving" | "freerun">;
6
8
  export interface CatLiveState {
@@ -96,7 +98,35 @@ export interface OnekoProps {
96
98
  perchOnHover?: boolean;
97
99
  /** Make the cat a keyboard-reachable "Pet the cat" button. Default false */
98
100
  pettable?: boolean;
101
+ /** Wear a holiday hat around Halloween, the winter holidays, and New Year. A season name forces it. Default true */
102
+ seasonal?: boolean | OnekoSeason;
103
+ /** Let visitors pick the cat up and toss it; a click without dragging pets it. Default false */
104
+ grabbable?: boolean;
105
+ /** Double-click empty page space to drop a treat the cat runs over to eat. Default false */
106
+ treats?: boolean;
107
+ /** Follow the visitor's clock: zoomies at dawn and dusk, sleepy late at night. Default false */
108
+ timeOfDay?: boolean;
109
+ /** Remember pets and treats in localStorage and greet returning visitors. Default false */
110
+ affection?: boolean;
111
+ /** Called when the cat is petted by keyboard, click, or pet(). */
112
+ onPet?: (detail: {
113
+ affection: number;
114
+ }) => void;
115
+ /** Called when the cat catches up with the cursor after a chase. */
116
+ onCatchCursor?: () => void;
117
+ /** Called when the cat falls asleep. */
118
+ onSleep?: () => void;
119
+ /** Called when a visitor throws the cat; speed is in CSS pixels per second. */
120
+ onToss?: (detail: {
121
+ speed: number;
122
+ }) => void;
123
+ /** Called when the cat eats a treat. */
124
+ onTreat?: (detail: {
125
+ affection: number;
126
+ }) => void;
99
127
  }
128
+ /** Event callbacks, kept in the runtime state so they update without a restart. */
129
+ export type OnekoEventHandlers = Pick<OnekoProps, "onPet" | "onCatchCursor" | "onSleep" | "onToss" | "onTreat">;
100
130
  export interface ObstacleRect {
101
131
  left: number;
102
132
  top: number;
@@ -180,4 +210,35 @@ export interface CatRuntimeState {
180
210
  perchTarget: PathPoint | null;
181
211
  /** Position of the cat this one chases, when chase is "cat" and one exists. */
182
212
  leaderTarget: PathPoint | null;
213
+ seasonalCfg: boolean | OnekoSeason;
214
+ grabbableCfg: boolean;
215
+ treatsCfg: boolean;
216
+ timeOfDayCfg: boolean;
217
+ affectionCfg: boolean;
218
+ handlers: OnekoEventHandlers;
219
+ /** Season currently worn, re-read from the calendar now and then. */
220
+ season: OnekoSeason | null;
221
+ /** Being carried, flying after a toss, or catching its breath after landing. */
222
+ grab: GrabState | null;
223
+ /** Something the cat set out to do: eat a treat, sit in a box, knock something over, or an API request. */
224
+ errand: Errand | null;
225
+ /** Frames until the cat looks for another box or knockable. */
226
+ errandCooldown: number;
227
+ /** Text queued by say() or data-oneko-say, shown on the next tick. */
228
+ sayRequest: {
229
+ text: string;
230
+ frames: number;
231
+ } | null;
232
+ /** The bubble was requested explicitly and stays up even when automatic bubbles are off. */
233
+ bubbleForced: boolean;
234
+ petRequest: boolean;
235
+ /** Chasing a cursor that was far away; reaching it counts as a catch. */
236
+ chasingFar: boolean;
237
+ mood: Mood;
238
+ moodCheckedFrame: number;
239
+ affection: number;
240
+ affectionLoaded: boolean;
241
+ /** localStorage key for affection, derived from storageKey. */
242
+ affectionKey: string;
243
+ zIndex: number;
183
244
  }
@@ -1,6 +1,8 @@
1
+ import { type OnekoControls } from "./controls";
1
2
  import type { OnekoProps } from "./types";
2
3
  export type OnekoOptions = Omit<OnekoProps, "liveStateRef">;
3
- export interface OnekoInstance {
4
+ export type { OnekoControls };
5
+ export interface OnekoInstance extends OnekoControls {
4
6
  /** Merge new options into the running cat; undefined resets one. Engine-level options restart it in place. */
5
7
  update(options: OnekoOptions): void;
6
8
  /** Remove the cat, bubble, laser, and listeners. Saves the position when persistence is on. */
@@ -1,3 +1,6 @@
1
- import { type OnekoOptions } from "./vanilla";
2
- export default function Oneko(props: OnekoOptions): null;
1
+ import { type OnekoControls, type OnekoOptions } from "./vanilla";
2
+ /** Pass ref={(controls) => ...} to get goTo, say, sit, follow, pet, and dropTreat. */
3
+ export default function Oneko(props: OnekoOptions & {
4
+ ref?: (controls: OnekoControls) => void;
5
+ }): null;
3
6
  export type { OnekoOptions } from "./vanilla";
@@ -1,5 +1,6 @@
1
1
  export { createOneko } from "../../../lib/oneko/vanilla";
2
- export type { OnekoInstance, OnekoOptions } from "../../../lib/oneko/vanilla";
2
+ export type { OnekoControls, OnekoInstance, OnekoOptions } from "../../../lib/oneko/vanilla";
3
+ export type { OnekoSeason } from "../../../lib/oneko/seasons";
3
4
  export { areCatsHidden, setCatsHidden, onCatsHiddenChange } from "../../../lib/oneko/pack";
4
5
  export { ONEKO_SKINS, isOnekoSkin } from "../../../lib/oneko/skins";
5
6
  export type { OnekoSkin } from "../../../lib/oneko/skins";
@@ -1,5 +1,5 @@
1
1
  import { type PropType } from "vue";
2
- import { type OnekoOptions, type CatActivityState } from "./vanilla";
2
+ import { type CatActivityState, type OnekoOptions } from "./vanilla";
3
3
  declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
4
4
  skin: PropType<OnekoOptions["skin"]>;
5
5
  spriteSrc: StringConstructor;
@@ -76,8 +76,39 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
76
76
  type: BooleanConstructor;
77
77
  default: undefined;
78
78
  };
79
+ seasonal: {
80
+ type: PropType<OnekoOptions["seasonal"]>;
81
+ default: undefined;
82
+ };
83
+ grabbable: {
84
+ type: BooleanConstructor;
85
+ default: undefined;
86
+ };
87
+ treats: {
88
+ type: BooleanConstructor;
89
+ default: undefined;
90
+ };
91
+ timeOfDay: {
92
+ type: BooleanConstructor;
93
+ default: undefined;
94
+ };
95
+ affection: {
96
+ type: BooleanConstructor;
97
+ default: undefined;
98
+ };
79
99
  }>, () => null, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
80
100
  stateChange: (_state: CatActivityState) => true;
101
+ pet: (_detail: {
102
+ affection: number;
103
+ }) => true;
104
+ catchCursor: () => true;
105
+ sleep: () => true;
106
+ toss: (_detail: {
107
+ speed: number;
108
+ }) => true;
109
+ treat: (_detail: {
110
+ affection: number;
111
+ }) => true;
81
112
  }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
82
113
  skin: PropType<OnekoOptions["skin"]>;
83
114
  spriteSrc: StringConstructor;
@@ -154,20 +185,56 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
154
185
  type: BooleanConstructor;
155
186
  default: undefined;
156
187
  };
188
+ seasonal: {
189
+ type: PropType<OnekoOptions["seasonal"]>;
190
+ default: undefined;
191
+ };
192
+ grabbable: {
193
+ type: BooleanConstructor;
194
+ default: undefined;
195
+ };
196
+ treats: {
197
+ type: BooleanConstructor;
198
+ default: undefined;
199
+ };
200
+ timeOfDay: {
201
+ type: BooleanConstructor;
202
+ default: undefined;
203
+ };
204
+ affection: {
205
+ type: BooleanConstructor;
206
+ default: undefined;
207
+ };
157
208
  }>> & Readonly<{
209
+ onTreat?: ((_detail: {
210
+ affection: number;
211
+ }) => any) | undefined;
158
212
  onStateChange?: ((_state: CatActivityState) => any) | undefined;
213
+ onPet?: ((_detail: {
214
+ affection: number;
215
+ }) => any) | undefined;
216
+ onCatchCursor?: (() => any) | undefined;
217
+ onSleep?: (() => any) | undefined;
218
+ onToss?: ((_detail: {
219
+ speed: number;
220
+ }) => any) | undefined;
159
221
  }>, {
160
222
  paused: boolean;
161
223
  followCursor: boolean;
162
224
  sleepEnabled: boolean;
163
- napWhileTyping: boolean;
164
- followFocus: boolean;
165
- perchOnHover: boolean;
166
225
  persistPosition: boolean;
167
226
  meow: boolean;
168
227
  bubbleEnabled: boolean;
169
228
  laserPointer: boolean;
229
+ napWhileTyping: boolean;
230
+ followFocus: boolean;
231
+ perchOnHover: boolean;
170
232
  pettable: boolean;
233
+ seasonal: boolean | import("../../../components/oneko").OnekoSeason | undefined;
234
+ grabbable: boolean;
235
+ treats: boolean;
236
+ timeOfDay: boolean;
237
+ affection: boolean;
171
238
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
172
239
  export default _default;
173
240
  export type { OnekoOptions } from "./vanilla";