@omercnet/paseo-queens 0.1.0-next.129.1 → 0.1.0-next.133.1

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.md CHANGED
@@ -60,7 +60,7 @@ npm run import:puzzles
60
60
 
61
61
  ## Install
62
62
 
63
- ### Paseo 0.9 beta
63
+ ### Paseo 0.9
64
64
 
65
65
  Install the published npm package on the daemon host:
66
66
 
@@ -75,20 +75,6 @@ paseo plugin update queens --check
75
75
  paseo plugin update queens
76
76
  ```
77
77
 
78
- ### Paseo 0.8
79
-
80
- Install from this monorepo:
81
-
82
- ```bash
83
- paseo plugin install omercnet/paseo-plugins:queens
84
- ```
85
-
86
- Or install a local checkout by absolute path on the daemon host:
87
-
88
- ```bash
89
- paseo plugin install /absolute/path/to/paseo-plugins/queens
90
- ```
91
-
92
78
  Open **Queens** from the sidebar or Command Center. Open any agent session to use the composer mini-game.
93
79
 
94
80
  ## Develop
@@ -96,10 +82,10 @@ Open **Queens** from the sidebar or Command Center. Open any agent session to us
96
82
  Use an isolated Paseo home and explicit host. Never reload this development checkout against your default daemon.
97
83
 
98
84
  ```bash
99
- npm ci
100
- npm run check
101
- npm run typecheck
102
- npm test
85
+ bun install
86
+ bun run check
87
+ bun run typecheck
88
+ bun run test
103
89
 
104
90
  paseo daemon config set daemon.listen 127.0.0.1:6802 --home /tmp/queens-dev
105
91
  paseo daemon config set daemon.relay.enabled false --home /tmp/queens-dev
@@ -113,7 +99,7 @@ Release Please owns package versions, changelog generation, component tags, and
113
99
 
114
100
  ## Requirements
115
101
 
116
- - Paseo `^0.8.0` or `^0.9.0-beta.1`
102
+ - Paseo `>=0.8.0 <0.10.0`
117
103
  - Plugins enabled on the target daemon
118
104
  - React Native-compatible Paseo client on web, desktop, iOS, or Android
119
105
 
@@ -134,10 +134,10 @@ function createStyles(theme: PluginSurfaceProps["theme"], compact: boolean): Sel
134
134
  flexDirection: "row",
135
135
  flexWrap: "wrap",
136
136
  justifyContent: "center",
137
- gap: compact ? 8 : 12,
137
+ gap: compact ? 6 : 12,
138
138
  },
139
139
  step: {
140
- minWidth: compact ? 136 : 152,
140
+ minWidth: compact ? 132 : 152,
141
141
  minHeight: 44,
142
142
  flexDirection: "row",
143
143
  alignItems: "center",
@@ -161,7 +161,7 @@ function createStyles(theme: PluginSurfaceProps["theme"], compact: boolean): Sel
161
161
  fontWeight: "500",
162
162
  },
163
163
  valueBlock: {
164
- minWidth: compact ? 56 : 68,
164
+ minWidth: compact ? 52 : 68,
165
165
  flex: 1,
166
166
  alignItems: "center",
167
167
  gap: 1,
@@ -32,18 +32,44 @@ type BoardLayout = {
32
32
 
33
33
  type DragReplacement = "empty" | "excluded";
34
34
 
35
+ type DragSelection = {
36
+ readonly indexes: ReadonlySet<number>;
37
+ readonly replacement: DragReplacement;
38
+ };
39
+
35
40
  type DragGesture = {
36
41
  readonly startIndex: number;
37
- readonly indexes: Set<number>;
38
- readonly replacement: DragReplacement;
42
+ indexes: Set<number>;
43
+ replacement: DragReplacement;
39
44
  moved: boolean;
40
45
  cancelled: boolean;
41
46
  };
42
47
 
43
- type DragPreview = {
44
- readonly indexes: ReadonlySet<number>;
45
- readonly replacement: DragReplacement;
46
- };
48
+ export function resolveDraggedCellState(
49
+ index: number,
50
+ persistedState: CellState,
51
+ dragSelection: DragSelection | null,
52
+ ): CellState {
53
+ if (persistedState === "marked" || dragSelection === null || !dragSelection.indexes.has(index)) {
54
+ return persistedState;
55
+ }
56
+
57
+ if (dragSelection.replacement === "empty") {
58
+ return persistedState === "excluded" ? "empty" : persistedState;
59
+ }
60
+
61
+ return persistedState === "empty" ? "excluded" : persistedState;
62
+ }
63
+
64
+ export function collectDragIndexes(
65
+ cells: readonly CellState[],
66
+ selection: DragSelection,
67
+ ): number[] {
68
+ return [...selection.indexes].filter((index) => {
69
+ const persistedState = cells[index] ?? "empty";
70
+ return resolveDraggedCellState(index, persistedState, selection) !== persistedState;
71
+ });
72
+ }
47
73
 
48
74
  type PendingTap = {
49
75
  readonly releasedAt: number;
@@ -200,7 +226,7 @@ export function QueensBoard({
200
226
  const cellsRef = useRef(cells);
201
227
  const onSetCellsRef = useRef(onSetCells);
202
228
  const onGestureActiveChangeRef = useRef(onGestureActiveChange);
203
- const [dragPreview, setDragPreview] = useState<DragPreview | null>(null);
229
+ const [dragPreview, setDragPreview] = useState<DragSelection | null>(null);
204
230
  cellsRef.current = cells;
205
231
  onSetCellsRef.current = onSetCells;
206
232
  onGestureActiveChangeRef.current = onGestureActiveChange;
@@ -291,6 +317,7 @@ export function QueensBoard({
291
317
  },
292
318
  [dragEnabled, puzzle.size],
293
319
  );
320
+
294
321
  const finishGesture = useCallback(() => {
295
322
  const gesture = gestureRef.current;
296
323
  gestureRef.current = null;
@@ -309,11 +336,9 @@ export function QueensBoard({
309
336
  pending?.cancel();
310
337
  pendingTapsRef.current.delete(index);
311
338
  }
312
- const indexes =
313
- gesture.replacement === "empty"
314
- ? [...gesture.indexes].filter((index) => cellsRef.current[index] === "excluded")
315
- : [...gesture.indexes];
316
- onSetCellsRef.current(indexes, gesture.replacement);
339
+
340
+ const indexes = collectDragIndexes(cellsRef.current, gesture);
341
+ if (indexes.length > 0) onSetCellsRef.current(indexes, gesture.replacement);
317
342
  }, [handleTapRelease]);
318
343
 
319
344
  const cancelGesture = useCallback(() => {
@@ -330,13 +355,8 @@ export function QueensBoard({
330
355
  {coordinates.map((column) => {
331
356
  const index = row * puzzle.size + column;
332
357
  const persistedState = cells[index] ?? "empty";
333
- let state = persistedState;
334
- if (dragPreview?.indexes.has(index)) {
335
- if (dragPreview.replacement === "excluded" || persistedState === "excluded") {
336
- state = dragPreview.replacement;
337
- }
338
- }
339
358
  const region = puzzle.regions[index] ?? 0;
359
+ const state = resolveDraggedCellState(index, persistedState, dragPreview);
340
360
  const conflicted = conflicts.has(index);
341
361
  const markColor = solved
342
362
  ? theme.colors.statusSuccess
@@ -74,7 +74,6 @@ function QueensPopoverGame({
74
74
  theme,
75
75
  host,
76
76
  layout,
77
- close,
78
77
  deck,
79
78
  catalog,
80
79
  }: PluginButtonContentProps & {
@@ -151,25 +150,6 @@ function QueensPopoverGame({
151
150
 
152
151
  return (
153
152
  <View style={styles.root}>
154
- {!layout.compact ? (
155
- <View style={styles.header}>
156
- <View style={styles.titleRow}>
157
- <GameMark size={22} color={theme.colors.accent} />
158
- <Text accessibilityRole="header" style={styles.title}>
159
- Queens
160
- </Text>
161
- </View>
162
- <Pressable
163
- accessibilityRole="button"
164
- accessibilityLabel="Close Queens"
165
- onPress={close}
166
- style={styles.doneButton}
167
- >
168
- <Text style={styles.doneText}>Done</Text>
169
- </Pressable>
170
- </View>
171
- ) : null}
172
-
173
153
  <View style={styles.metaRow}>
174
154
  <Text style={styles.metaText}>
175
155
  #{puzzleNumber}/{state.puzzles.length}
@@ -207,7 +187,7 @@ function QueensPopoverGame({
207
187
  <QueensBoard
208
188
  key={`${host.id}:${puzzle.id}:popover`}
209
189
  dragEnabled={!layout.compact}
210
- maxSize={layout.compact ? 296 : 184}
190
+ maxSize={layout.compact ? 296 : 146}
211
191
  puzzle={puzzle}
212
192
  cells={progress.cells}
213
193
  conflicts={conflicts}
@@ -252,28 +232,11 @@ function QueensPopoverGame({
252
232
  function createStyles(theme: PluginButtonContentProps["theme"], compact: boolean) {
253
233
  return StyleSheet.create({
254
234
  root: {
255
- width: compact ? "100%" : 300,
235
+ width: "100%",
256
236
  alignSelf: "center",
257
237
  alignItems: "center",
258
238
  gap: compact ? 12 : 6,
259
239
  },
260
- header: {
261
- width: "100%",
262
- flexDirection: "row",
263
- alignItems: "center",
264
- justifyContent: "space-between",
265
- gap: 12,
266
- },
267
- titleRow: {
268
- flexDirection: "row",
269
- alignItems: "center",
270
- gap: 8,
271
- },
272
- title: {
273
- color: theme.colors.foreground,
274
- fontSize: 18,
275
- fontWeight: "800",
276
- },
277
240
  doneButton: {
278
241
  minHeight: 36,
279
242
  justifyContent: "center",
@@ -307,7 +270,7 @@ function createStyles(theme: PluginButtonContentProps["theme"], compact: boolean
307
270
  },
308
271
  boardFrame: {
309
272
  width: "100%",
310
- maxWidth: compact ? 296 : 184,
273
+ maxWidth: compact ? 296 : 146,
311
274
  },
312
275
  statusCard: {
313
276
  minHeight: 30,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omercnet/paseo-queens",
3
- "version": "0.1.0-next.129.1",
3
+ "version": "0.1.0-next.133.1",
4
4
  "type": "module",
5
5
  "description": "A cross-platform Queens logic puzzle for Paseo.",
6
6
  "license": "MIT",
@@ -17,7 +17,7 @@
17
17
  "publishConfig": {
18
18
  "access": "public"
19
19
  },
20
- "packageManager": "npm@11.19.1",
20
+ "packageManager": "bun@1.4.2",
21
21
  "engines": {
22
22
  "node": ">=24"
23
23
  },
@@ -38,26 +38,22 @@
38
38
  "paseo-plugin.json"
39
39
  ],
40
40
  "scripts": {
41
- "check": "biome check --error-on-warnings .",
41
+ "check": "biome check .",
42
+ "check:write": "biome check --write .",
42
43
  "import:puzzles": "node scripts/import-curated-puzzles.mjs",
43
- "test": "run-s test:ci:*",
44
+ "test": "vitest run",
44
45
  "typecheck": "tsc --noEmit",
45
- "verify:package": "npm pack --dry-run",
46
- "check:write": "biome check --write .",
47
- "test:ci:unit": "vitest run",
48
- "build": "node ../.github/scripts/build-plugin.mjs"
46
+ "verify:package": "npm pack --dry-run"
49
47
  },
50
48
  "devDependencies": {
51
- "@biomejs/biome": "^2.5.14",
52
- "@getpaseo/plugin": "0.9.0-beta.1",
53
- "@getpaseo/server": "0.9.0-beta.1",
54
- "@types/node": "^24.5.2",
55
- "@types/react": "~19.2.0",
56
- "npm-run-all2": "^9.0.3",
49
+ "@biomejs/biome": "^2.5.10",
50
+ "@getpaseo/plugin": "0.9.0",
51
+ "@types/node": "^24.10.1",
52
+ "@types/react": "^19.2.18",
57
53
  "react": "19.1.0",
58
54
  "react-native": "0.81.5",
59
- "typescript": "^7.0.0",
55
+ "typescript": "^7.0.2",
60
56
  "vitest": "^5.0.0",
61
- "zod": "^4.4.3"
57
+ "zod": "4.4.3"
62
58
  }
63
59
  }
package/paseo-plugin.json CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "id": "queens",
3
- "requirements": { "paseo": "^0.8.0 || ^0.9.0-beta.1" }
3
+ "requirements": { "paseo": ">=0.8.0 <0.10.0" }
4
4
  }