@mingxy/opencode-mascot 0.2.3 → 0.2.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mingxy/opencode-mascot",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "OpenCode TUI mascot plugin framework - customizable ASCII mascots for your terminal",
5
5
  "author": "mingxy",
6
6
  "license": "MIT",
@@ -94,12 +94,5 @@ export const baoziPack: MascotPack = {
94
94
  idleTimeout: 120000,
95
95
  },
96
96
 
97
- sidebar: {
98
- greetings: ["热乎乎的包子出炉啦~"],
99
- busyPhrases: ["蒸包子中..."],
100
- },
101
-
102
- bubbleTexts: ["蒸着...", "发酵中...", "冒热气...", "快熟了..."],
103
-
104
97
  effects: baoziEffects,
105
98
  };
@@ -200,12 +200,5 @@ export const yueerPack: MascotPack = {
200
200
  idleTimeout: 90000,
201
201
  },
202
202
 
203
- sidebar: {
204
- greetings: ["师尊,月儿在此候命~"],
205
- busyPhrases: ["铸造法器中..."],
206
- },
207
-
208
- bubbleTexts: ["嗯...", "让我想想...", "等等...", "本帝在算..."],
209
-
210
203
  effects: yueerEffects,
211
204
  };
@@ -2,14 +2,13 @@
2
2
 
3
3
  import { createSignal } from "solid-js";
4
4
  import type { JSX } from "@opentui/solid";
5
- import type { MascotPack, MascotState, SwitchConfig } from "../core/types";
5
+ import type { MascotPack, MascotState } from "../core/types";
6
6
  import { createAnimatedRenderer } from "../core/ascii-renderer";
7
7
  import { onCelebrate } from "../core/celebration-bus";
8
8
  import { useDraggableMascot } from "./use-draggable-mascot";
9
9
 
10
10
  interface SidebarMascotProps {
11
11
  mascots: Record<string, MascotPack>;
12
- switchConfig?: SwitchConfig;
13
12
  initialMascot?: string;
14
13
  api: {
15
14
  event: {
@@ -73,7 +72,7 @@ export function SidebarMascot(props: SidebarMascotProps): JSX.Element {
73
72
  const cur = currentName();
74
73
  renderers[cur].setState(s);
75
74
 
76
- const stateMap = props.switchConfig?.onState ?? DEFAULT_STATE_MAP;
75
+ const stateMap = DEFAULT_STATE_MAP;
77
76
  const target = stateMap[s];
78
77
  if (target && target !== cur && props.mascots[target]) {
79
78
  setCurrentName(target);
@@ -1,7 +1,6 @@
1
1
  /** @jsxImportSource @opentui/solid */
2
2
 
3
3
  import { createSignal, onCleanup, type Accessor } from "solid-js";
4
- import { useTerminalDimensions } from "@opentui/solid";
5
4
 
6
5
  type DragState = "normal" | "edge_hidden" | "returning";
7
6
  type HideSide = "left" | "right" | null;
@@ -26,6 +25,12 @@ interface UseDraggableOpts {
26
25
  enableEdge?: boolean;
27
26
  }
28
27
 
28
+ function getTermSize(): { width: number; height: number } {
29
+ const width = (typeof process !== "undefined" && process.stdout?.columns) || 80;
30
+ const height = (typeof process !== "undefined" && process.stdout?.rows) || 24;
31
+ return { width, height };
32
+ }
33
+
29
34
  export function useDraggableMascot(opts: UseDraggableOpts): {
30
35
  posX: Accessor<number>;
31
36
  posY: Accessor<number>;
@@ -38,7 +43,6 @@ export function useDraggableMascot(opts: UseDraggableOpts): {
38
43
 
39
44
  const [posX, setPosX] = createSignal(opts.initialX);
40
45
  const [posY, setPosY] = createSignal(opts.initialY);
41
- const dims = useTerminalDimensions();
42
46
 
43
47
  let dragStartX = 0;
44
48
  let dragStartY = 0;
@@ -62,7 +66,7 @@ export function useDraggableMascot(opts: UseDraggableOpts): {
62
66
 
63
67
  const clampX = (rawX: number): number => {
64
68
  if (!enableEdge) return rawX;
65
- const { width } = dims();
69
+ const { width } = getTermSize();
66
70
  const minX = -(opts.mascotWidth - peek);
67
71
  const maxX = width - peek;
68
72
  return Math.max(minX, Math.min(rawX, maxX));
@@ -70,7 +74,7 @@ export function useDraggableMascot(opts: UseDraggableOpts): {
70
74
 
71
75
  const clampY = (rawY: number): number => {
72
76
  if (!enableEdge) return rawY;
73
- const { height } = dims();
77
+ const { height } = getTermSize();
74
78
  return Math.max(0, Math.min(rawY, height - opts.mascotHeight));
75
79
  };
76
80
 
@@ -81,7 +85,7 @@ export function useDraggableMascot(opts: UseDraggableOpts): {
81
85
  peekTimer = setInterval(() => {
82
86
  phase = !phase;
83
87
  const stretch = phase ? 2 : 0;
84
- const { width } = dims();
88
+ const { width } = getTermSize();
85
89
  if (hideSide === "left") {
86
90
  setPosX(-(opts.mascotWidth - peek) + stretch);
87
91
  } else if (hideSide === "right") {
@@ -94,7 +98,7 @@ export function useDraggableMascot(opts: UseDraggableOpts): {
94
98
  if (state !== "edge_hidden") return;
95
99
  stopPeek();
96
100
  state = "returning";
97
- const { width } = dims();
101
+ const { width } = getTermSize();
98
102
  const cur = posX();
99
103
  const targetX = hideSide === "left" ? 0 : Math.max(0, width - opts.mascotWidth);
100
104
  const step = targetX > cur ? 2 : -2;
@@ -115,7 +119,7 @@ export function useDraggableMascot(opts: UseDraggableOpts): {
115
119
 
116
120
  const checkEdgeOnRelease = () => {
117
121
  if (!enableEdge) return;
118
- const { width } = dims();
122
+ const { width } = getTermSize();
119
123
  const x = posX();
120
124
  if (x <= -(opts.mascotWidth - peek) + 1) {
121
125
  hideSide = "left";
@@ -269,8 +269,8 @@ export function createAnimatedRenderer(pack: MascotPack): {
269
269
 
270
270
  return (
271
271
  <box flexDirection="column" left={left} top={top}>
272
- {renderLines(lines, fg)}
273
272
  {cel ? <text fg={fg}>{cel.text}</text> : null}
273
+ {renderLines(lines, fg)}
274
274
  </box>
275
275
  );
276
276
  };
@@ -314,8 +314,9 @@ export function createAnimatedRenderer(pack: MascotPack): {
314
314
 
315
315
  // 连续跳跃 + 吐火星文泡泡庆祝更新成功
316
316
  const celebrateUpdate = (newVersion: string) => {
317
- const bubbles = pack.bubbleTexts ?? ["ᵘᵖ~"];
318
- if (currentState() === "sleeping") setState("idle");
317
+ const bubbles = ["ᵘᵖ~", "ⁿᵉʷ!", "ʸᵉ~", "ᵍᵒ~", "ᵒᵏ~"];
318
+ setState("happy");
319
+ setFrameOverride("happy");
319
320
 
320
321
  let step = 0;
321
322
  const JUMPS = 3;
@@ -323,6 +324,8 @@ export function createAnimatedRenderer(pack: MascotPack): {
323
324
  if (step >= JUMPS) {
324
325
  setJumpOffset(0);
325
326
  setCelebrate(null);
327
+ setFrameOverride(null);
328
+ setState("idle");
326
329
  return;
327
330
  }
328
331
  setJumpOffset(step % 2 === 0 ? -2 : 0);
package/src/core/types.ts CHANGED
@@ -25,14 +25,6 @@ export interface AnimationConfig {
25
25
  jumpMaxDelay?: number;
26
26
  }
27
27
 
28
- /**
29
- * Sidebar display configuration.
30
- */
31
- export interface SidebarConfig {
32
- greetings?: string[];
33
- busyPhrases?: string[];
34
- }
35
-
36
28
  // ─── Effect system types ───
37
29
 
38
30
  /**
@@ -130,25 +122,7 @@ export interface MascotPack {
130
122
  };
131
123
 
132
124
  animations?: AnimationConfig;
133
- sidebar?: SidebarConfig;
134
125
 
135
126
  /** Mascot-specific animation effects (timers + render) */
136
127
  effects?: MascotEffects;
137
-
138
- /** Thinking bubble phrases, shown when mascot is in busy/thinking state */
139
- bubbleTexts?: string[];
140
- }
141
-
142
- export interface SwitchConfig {
143
- onState?: Partial<Record<MascotState, string>>;
144
- }
145
-
146
- /**
147
- * User-facing configuration merged from opencode config file.
148
- */
149
- export interface MascotConfig {
150
- mascot: string;
151
- animations: boolean;
152
- idleSleep: boolean;
153
- switchConfig?: SwitchConfig;
154
128
  }