castle-web-cli 0.4.74 → 0.4.76

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 (72) hide show
  1. package/dist/agent-prompts.d.ts +4 -0
  2. package/dist/agent-prompts.js +20 -8
  3. package/dist/agent.js +301 -28
  4. package/dist/castle-host/host.js +59 -5
  5. package/dist/commonInstructions.d.ts +1 -1
  6. package/dist/commonInstructions.js +5 -1
  7. package/dist/ide.d.ts +1 -0
  8. package/dist/ide.js +250 -1
  9. package/dist/init.js +46 -4
  10. package/dist/save-deck.js +8 -1
  11. package/dist/serve.js +27 -1
  12. package/dist/shell/assets/index-DNWEQd4R.js +141 -0
  13. package/dist/shell/assets/{index-WNbOHPBj.css → index-DuKq-Grp.css} +1 -1
  14. package/dist/shell/index.html +2 -2
  15. package/kits/basic-2d/CLAUDE.md +12 -4
  16. package/kits/basic-2d/castle.json +15 -0
  17. package/kits/basic-2d/drawings/pig.pxart +22 -55
  18. package/kits/basic-2d/editors/PxArtEditor.jsx +237 -4
  19. package/kits/basic-2d/editors/SceneEditor.jsx +0 -3
  20. package/kits/basic-2d/editors/SingleEditor.jsx +6 -51
  21. package/kits/basic-2d/editors/pixelEditorChrome.jsx +17 -11
  22. package/kits/basic-2d/editors/pixelGeometry.js +95 -0
  23. package/kits/basic-2d/editors/pixelInspector.jsx +229 -51
  24. package/kits/basic-2d/editors/pxArtTools.js +109 -1
  25. package/kits/basic-2d/engine/ScenePlayer.jsx +11 -163
  26. package/kits/basic-2d/engine/ui.jsx +15 -0
  27. package/kits/basic-2d/engine/ui.module.css +44 -117
  28. package/kits/basic-2d/main.jsx +6 -10
  29. package/kits/basic-2d/pnpm-workspace.yaml +3 -0
  30. package/package.json +10 -1
  31. package/dist/shell/assets/index-Dfn29Bkt.js +0 -108
  32. package/kits/basic-2d/editors/App.jsx +0 -226
  33. package/kits/basic-2d/editors/CodeEditor.jsx +0 -79
  34. package/kits/basic-2d/editors/FileBrowser.jsx +0 -349
  35. package/kits/basic-2d/editors/codeTheme.js +0 -135
  36. package/kits/basic-2d/engine/TouchControls.jsx +0 -136
  37. package/kits/basic-2d/engine/playConsole.js +0 -66
  38. package/kits/basic-3d/.prettierrc +0 -8
  39. package/kits/basic-3d/CLAUDE.md +0 -162
  40. package/kits/basic-3d/behaviors/Camera.jsx +0 -56
  41. package/kits/basic-3d/behaviors/Collider.jsx +0 -78
  42. package/kits/basic-3d/behaviors/Mesh.jsx +0 -82
  43. package/kits/basic-3d/behaviors/Model.jsx +0 -61
  44. package/kits/basic-3d/behaviors/Transform.jsx +0 -35
  45. package/kits/basic-3d/editors/App.jsx +0 -147
  46. package/kits/basic-3d/editors/CodeEditor.jsx +0 -112
  47. package/kits/basic-3d/editors/FileBrowser.jsx +0 -143
  48. package/kits/basic-3d/editors/ModelEditor.jsx +0 -400
  49. package/kits/basic-3d/editors/PlayOnly.jsx +0 -22
  50. package/kits/basic-3d/editors/SceneEditor.jsx +0 -1087
  51. package/kits/basic-3d/editors/behaviorRegistry.js +0 -24
  52. package/kits/basic-3d/editors/editorHistory.js +0 -52
  53. package/kits/basic-3d/editors/viewportRig.js +0 -90
  54. package/kits/basic-3d/engine/ScenePlayer.jsx +0 -61
  55. package/kits/basic-3d/engine/SceneUI.jsx +0 -67
  56. package/kits/basic-3d/engine/SceneViewport.jsx +0 -102
  57. package/kits/basic-3d/engine/TouchControls.jsx +0 -136
  58. package/kits/basic-3d/engine/autoInspector.jsx +0 -51
  59. package/kits/basic-3d/engine/files.js +0 -73
  60. package/kits/basic-3d/engine/scene.js +0 -502
  61. package/kits/basic-3d/engine/threeUtil.js +0 -260
  62. package/kits/basic-3d/engine/ui.jsx +0 -352
  63. package/kits/basic-3d/engine/ui.module.css +0 -944
  64. package/kits/basic-3d/eslint.config.js +0 -51
  65. package/kits/basic-3d/index.html +0 -11
  66. package/kits/basic-3d/main.jsx +0 -10
  67. package/kits/basic-3d/models/block.model +0 -14
  68. package/kits/basic-3d/package-lock.json +0 -2713
  69. package/kits/basic-3d/package.json +0 -41
  70. package/kits/basic-3d/pnpm-lock.yaml +0 -1769
  71. package/kits/basic-3d/scenes/main.scene +0 -76
  72. package/kits/basic-3d/vite.config.js +0 -1
@@ -1,23 +1,15 @@
1
- import React, { useCallback, useEffect, useRef, useState } from 'react';
2
- import { createPortal } from 'react-dom';
1
+ import React, { useCallback, useEffect, useRef } from 'react';
3
2
  import { configureSceneCanvas, makeScene } from './scene';
4
3
  import { SceneUI } from './SceneUI';
5
- import { TouchControls } from './TouchControls';
6
- import { cx, Icon, styles } from './ui';
7
- import { usePlayLogs } from './playConsole';
8
4
  // Engine-level scene player: mount a `SceneRuntime` against a canvas, wire
9
5
  // keyboard / pointer input, run the update+draw loop, and render the
10
6
  // behavior-driven UI overlay. No game logic lives here -- behaviors and
11
- // scenes are the place for that.
7
+ // scenes are the place for that. The dev logs drawer is a builtin shell panel
8
+ // now (cli/src/shell), not rendered here.
12
9
  export function ScenePlayer({ sceneData, sprites, behaviorClasses, onFirstFrame }) {
13
10
  const canvasRef = useRef(null);
14
11
  const runtimeRef = useRef(null);
15
- // Bumping this re-runs the mount effect below, which tears down the running
16
- // loop/runtime and rebuilds a fresh scene from the same data -- a clean restart.
17
- const [runToken, setRunToken] = useState(0);
18
- const getKeys = useCallback(() => runtimeRef.current?.keys ?? null, []);
19
12
  const getRuntime = useCallback(() => runtimeRef.current, []);
20
- const restart = useCallback(() => setRunToken((token) => token + 1), []);
21
13
  useEffect(() => {
22
14
  const canvas = canvasRef.current;
23
15
  if (!canvas) return undefined;
@@ -63,9 +55,7 @@ export function ScenePlayer({ sceneData, sprites, behaviorClasses, onFirstFrame
63
55
  canvas.addEventListener('pointerup', onPointerUp);
64
56
  canvas.addEventListener('pointercancel', onPointerUp);
65
57
  canvas.focus();
66
- // Only signal first-frame readiness on the initial run; a restart shouldn't
67
- // re-fire the host launcher reveal.
68
- const stopLoop = startPlayerLoop(canvas, ctx, runtime, runToken === 0 ? onFirstFrame : undefined);
58
+ const stopLoop = startPlayerLoop(canvas, ctx, runtime, onFirstFrame);
69
59
  return () => {
70
60
  stopLoop();
71
61
  window.removeEventListener('keydown', onKeyDown);
@@ -77,157 +67,15 @@ export function ScenePlayer({ sceneData, sprites, behaviorClasses, onFirstFrame
77
67
  runtimeRef.current = null;
78
68
  };
79
69
  // eslint-disable-next-line react-hooks/exhaustive-deps
80
- }, [runToken]);
81
- return (
82
- <>
83
- <div style={{ position: 'fixed', inset: 0, background: '#000' }}>
84
- <canvas
85
- ref={canvasRef}
86
- tabIndex={0}
87
- style={{ width: '100%', height: '100%', display: 'block', outline: 'none' }}
88
- />
89
- <SceneUI getRuntime={getRuntime} />
90
- <TouchControls getKeys={getKeys} />
91
- </div>
92
- {/* Portal to <body> so the console drawer escapes the SDK's card-sized,
93
- transformed `#root > *` wrapper and pins to the panel, outside the
94
- play preview. */}
95
- {createPortal(<PlayConsole onRestart={restart} />, document.body)}
96
- </>
97
- );
98
- }
99
- function PlayConsole({ onRestart }) {
100
- const { logs, clearLogs } = usePlayLogs();
101
- const [open, setOpen] = useState(false);
102
- const rootRef = useRef(null);
103
- const bodyRef = useRef(null);
104
- // Reserve the drawer's footprint by shrinking + lifting the SDK deck card so it
105
- // sits fully above the drawer (visible + interactive) instead of behind it.
106
- // Driven by the live drawer height; recomputed on toggle (height change via the
107
- // ResizeObserver) and on window/card resize.
108
- useEffect(() => {
109
- const el = rootRef.current;
110
- if (!el) return undefined;
111
- const docEl = document.documentElement;
112
- docEl.dataset.castleLogs = '';
113
- const TOP_MARGIN = 16;
114
- const MIN_CARD_SCALE = 0.2;
115
- const apply = () => {
116
- const drawerHeight = el.offsetHeight;
117
- const cs = getComputedStyle(docEl);
118
- const fullW = parseFloat(cs.getPropertyValue('--castle-card-w'));
119
- const fullH = parseFloat(cs.getPropertyValue('--castle-card-h'));
120
- docEl.style.setProperty('--castle-logs-shift', `${drawerHeight / 2}px`);
121
- // Only resize the card when we know its natural size; otherwise leave it to
122
- // the SDK fallback (the rule's var() defaults handle this).
123
- if (fullW > 0 && fullH > 0) {
124
- const available = window.innerHeight - drawerHeight - TOP_MARGIN;
125
- // Floor the scale so a very short panel (drawer taller than the area)
126
- // can't drive the card to 0/negative and make the deck disappear.
127
- const scale = Math.min(1, Math.max(MIN_CARD_SCALE, available / fullH));
128
- docEl.style.setProperty('--castle-logs-card-w', `${fullW * scale}px`);
129
- docEl.style.setProperty('--castle-logs-card-h', `${fullH * scale}px`);
130
- } else {
131
- docEl.style.removeProperty('--castle-logs-card-w');
132
- docEl.style.removeProperty('--castle-logs-card-h');
133
- }
134
- };
135
- apply();
136
- const observer = new ResizeObserver(apply);
137
- observer.observe(el);
138
- window.addEventListener('resize', apply);
139
- return () => {
140
- observer.disconnect();
141
- window.removeEventListener('resize', apply);
142
- delete docEl.dataset.castleLogs;
143
- docEl.style.removeProperty('--castle-logs-card-w');
144
- docEl.style.removeProperty('--castle-logs-card-h');
145
- docEl.style.removeProperty('--castle-logs-shift');
146
- };
147
70
  }, []);
148
- // Keep the newest line in view while expanded.
149
- useEffect(() => {
150
- if (open && bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
151
- }, [logs, open]);
152
- const copy = useCallback(() => {
153
- const text = logs.map((line) => line.text).join('\n');
154
- navigator.clipboard?.writeText(text).catch(() => {});
155
- }, [logs]);
156
- const hasLogs = logs.length > 0;
157
71
  return (
158
- <div ref={rootRef} className={styles.playConsole}>
159
- {/* The whole header row toggles; the action buttons stopPropagation so
160
- they don't also collapse/expand. */}
161
- <div
162
- className={styles.playConsoleHeader}
163
- role="button"
164
- tabIndex={-1}
165
- aria-expanded={open}
166
- aria-label={open ? 'Collapse logs' : 'Expand logs'}
167
- onClick={() => setOpen((value) => !value)}>
168
- <span className={styles.playConsoleToggle}>
169
- <span className={styles.playConsoleCaret}>
170
- <Icon name={open ? 'chevron-down' : 'chevron-right'} />
171
- </span>
172
- <span className={styles.playConsoleTitle}>Logs</span>
173
- </span>
174
- <div
175
- className={styles.playConsoleActions}
176
- onClick={(event) => event.stopPropagation()}>
177
- {open ? (
178
- <>
179
- <button
180
- type="button"
181
- tabIndex={-1}
182
- className={styles.playConsoleBtn}
183
- aria-label="Copy logs"
184
- title="Copy logs"
185
- disabled={!hasLogs}
186
- onClick={copy}>
187
- <Icon name="clone" />
188
- </button>
189
- <button
190
- type="button"
191
- tabIndex={-1}
192
- className={styles.playConsoleBtn}
193
- aria-label="Clear logs"
194
- title="Clear logs"
195
- disabled={!hasLogs}
196
- onClick={clearLogs}>
197
- <Icon name="trash" />
198
- </button>
199
- </>
200
- ) : null}
201
- <button
202
- type="button"
203
- tabIndex={-1}
204
- className={styles.playConsoleBtn}
205
- aria-label="Restart"
206
- title="Restart"
207
- onClick={onRestart}>
208
- <Icon name="rotate" />
209
- </button>
210
- </div>
211
- </div>
212
- {open ? (
213
- <div ref={bodyRef} className={styles.playConsoleBody}>
214
- {hasLogs ? (
215
- logs.map((line) => (
216
- <div
217
- key={line.id}
218
- className={cx(
219
- styles.playConsoleLine,
220
- line.level === 'warn' && styles.playConsoleLineWarn,
221
- line.level === 'error' && styles.playConsoleLineError
222
- )}>
223
- {line.text}
224
- </div>
225
- ))
226
- ) : (
227
- <div className={styles.playConsoleEmpty}>no output</div>
228
- )}
229
- </div>
230
- ) : null}
72
+ <div style={{ position: 'fixed', inset: 0, background: '#000' }}>
73
+ <canvas
74
+ ref={canvasRef}
75
+ tabIndex={0}
76
+ style={{ width: '100%', height: '100%', display: 'block', outline: 'none' }}
77
+ />
78
+ <SceneUI getRuntime={getRuntime} />
231
79
  </div>
232
80
  );
233
81
  }
@@ -2,10 +2,13 @@ import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
2
2
  import { createPortal } from 'react-dom';
3
3
  import {
4
4
  faArrowsAlt,
5
+ faArrowsAltH,
6
+ faArrowsAltV,
5
7
  faBars,
6
8
  faChevronDown,
7
9
  faChevronRight,
8
10
  faChevronUp,
11
+ faCircle,
9
12
  faClone,
10
13
  faCode,
11
14
  faEraser,
@@ -22,6 +25,9 @@ import {
22
25
  faPlay,
23
26
  faPlus,
24
27
  faRedo,
28
+ faShapes,
29
+ faSlash,
30
+ faVectorSquare,
25
31
  faSquare,
26
32
  faStamp,
27
33
  faStop,
@@ -149,16 +155,20 @@ const icons = {
149
155
  'chevron-down': faChevronDown,
150
156
  'chevron-right': faChevronRight,
151
157
  'chevron-up': faChevronUp,
158
+ circle: faCircle,
152
159
  clone: faClone,
153
160
  code: faCode,
154
161
  eraser: faEraser,
155
162
  eyedropper: faEyeDropper,
156
163
  fill: faFillDrip,
164
+ 'flip-h': faArrowsAltH,
165
+ 'flip-v': faArrowsAltV,
157
166
  file: faFile,
158
167
  film: faFilm,
159
168
  globe: faGlobe,
160
169
  image: faImage,
161
170
  'layer-group': faLayerGroup,
171
+ marquee: faVectorSquare,
162
172
  move: faArrowsAlt,
163
173
  'object-group': faObjectGroup,
164
174
  palette: faPalette,
@@ -167,10 +177,15 @@ const icons = {
167
177
  plus: faPlus,
168
178
  redo: faRedo,
169
179
  rotate: faSyncAlt,
180
+ shapes: faShapes,
181
+ slash: faSlash,
170
182
  square: faSquare,
171
183
  stamp: faStamp,
172
184
  stop: faStop,
173
185
  times: faTimes,
186
+ // Hand-rolled equilateral-ish triangle glyph (FA free-solid has no plain
187
+ // triangle); shaped to match the filled-glyph look of the imported icons.
188
+ triangle: { icon: [512, 512, [], '', 'M256 64 L496 448 L16 448 Z'] },
174
189
  trash: faTrash,
175
190
  undo: faUndo,
176
191
  };
@@ -1158,12 +1158,21 @@
1158
1158
  flex-direction: column;
1159
1159
  width: 34px;
1160
1160
  flex: 0 0 auto;
1161
+ gap: 8px;
1162
+ }
1163
+
1164
+ /* Each control group (color, size, shape type, mode toggle) is its own boxed
1165
+ section, separated by the strip's gap. Controls stacked inside a section keep
1166
+ 1px dividers so a multi-button group still reads as one segmented unit. */
1167
+ .paintStripSection {
1168
+ display: flex;
1169
+ flex-direction: column;
1161
1170
  border: 1px solid var(--castle-inspector-border);
1162
1171
  border-radius: var(--castle-radius);
1163
1172
  overflow: hidden;
1164
1173
  }
1165
1174
 
1166
- .paintStrip > * + * {
1175
+ .paintStripSection > * + * {
1167
1176
  border-top: 1px solid var(--castle-inspector-border);
1168
1177
  }
1169
1178
 
@@ -1211,6 +1220,11 @@
1211
1220
  background: var(--castle-inspector-input-bg);
1212
1221
  }
1213
1222
 
1223
+ .paintStripModeButton:disabled {
1224
+ opacity: 0.35;
1225
+ cursor: default;
1226
+ }
1227
+
1214
1228
  .drawingSizeSliderVertical {
1215
1229
  width: 88px;
1216
1230
  height: 14px;
@@ -1292,6 +1306,21 @@
1292
1306
  justify-content: center;
1293
1307
  }
1294
1308
 
1309
+ /* Stacks the native artboard canvas and the display-resolution overlay so the
1310
+ marching-ants outline renders crisp instead of sub-pixel on the upscaled art. */
1311
+ .drawingArtboardFrame {
1312
+ position: relative;
1313
+ flex: 0 0 auto;
1314
+ }
1315
+
1316
+ .drawingOverlay {
1317
+ position: absolute;
1318
+ inset: 0;
1319
+ width: 100%;
1320
+ height: 100%;
1321
+ pointer-events: none;
1322
+ }
1323
+
1295
1324
  .drawingCanvas {
1296
1325
  image-rendering: pixelated;
1297
1326
  background:
@@ -1432,6 +1461,20 @@
1432
1461
  color: var(--castle-selected-ink);
1433
1462
  }
1434
1463
 
1464
+ /* Horizontal segmented row of shape sub-mode buttons in the wide-layout Tool
1465
+ Settings panel. Reuses .drawingToolButton glyph buttons with shared borders. */
1466
+ .drawingShapeModeRow {
1467
+ display: flex;
1468
+ width: max-content;
1469
+ border: 1px solid var(--castle-inspector-border);
1470
+ border-radius: var(--castle-radius);
1471
+ overflow: hidden;
1472
+ }
1473
+
1474
+ .drawingShapeModeRow > * + * {
1475
+ border-left: 1px solid var(--castle-inspector-border);
1476
+ }
1477
+
1435
1478
  .drawingToolHint {
1436
1479
  color: var(--castle-inspector-muted);
1437
1480
  font-size: 14px;
@@ -1902,119 +1945,3 @@
1902
1945
  }
1903
1946
  }
1904
1947
 
1905
- /* On-panel play console: a collapsible log drawer pinned to the bottom of the
1906
- play panel (portaled to <body> so it sits outside the SDK's card wrapper).
1907
- Houses the restart control plus copy/clear log affordances. */
1908
- .playConsole {
1909
- position: fixed;
1910
- left: 0;
1911
- right: 0;
1912
- bottom: 0;
1913
- z-index: 60;
1914
- display: flex;
1915
- flex-direction: column;
1916
- border-top: 1px solid rgba(255, 255, 255, 0.12);
1917
- background: rgba(13, 13, 13, 0.94);
1918
- color: #e6e6e6;
1919
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
1920
- 'Courier New', monospace;
1921
- padding-bottom: env(safe-area-inset-bottom, 0px);
1922
- overflow: hidden;
1923
- }
1924
- .playConsoleHeader {
1925
- display: flex;
1926
- align-items: center;
1927
- justify-content: space-between;
1928
- gap: 8px;
1929
- padding: 7px 8px 7px 10px;
1930
- cursor: pointer;
1931
- }
1932
- .playConsoleHeader:hover {
1933
- background: rgba(255, 255, 255, 0.04);
1934
- }
1935
- .playConsoleToggle {
1936
- display: flex;
1937
- align-items: center;
1938
- gap: 8px;
1939
- }
1940
- .playConsoleCaret {
1941
- display: inline-flex;
1942
- font-size: 11px;
1943
- color: #8a8a8a;
1944
- }
1945
- .playConsoleTitle {
1946
- font-size: 11px;
1947
- font-weight: 700;
1948
- letter-spacing: 1px;
1949
- text-transform: uppercase;
1950
- color: #b3b3b3;
1951
- }
1952
- .playConsoleActions {
1953
- display: flex;
1954
- align-items: center;
1955
- gap: 6px;
1956
- }
1957
- .playConsoleBtn {
1958
- display: inline-flex;
1959
- align-items: center;
1960
- justify-content: center;
1961
- width: 30px;
1962
- height: 28px;
1963
- padding: 0;
1964
- font-size: 13px;
1965
- color: #cfcfcf;
1966
- background: transparent;
1967
- border: 1px solid rgba(255, 255, 255, 0.14);
1968
- border-radius: 6px;
1969
- cursor: pointer;
1970
- }
1971
- .playConsoleBtn:hover {
1972
- background: rgba(255, 255, 255, 0.08);
1973
- color: #fff;
1974
- }
1975
- .playConsoleBtn:disabled {
1976
- opacity: 0.38;
1977
- cursor: default;
1978
- }
1979
- .playConsoleBtn:disabled:hover {
1980
- background: transparent;
1981
- color: #cfcfcf;
1982
- }
1983
- .playConsoleBody {
1984
- border-top: 1px solid rgba(255, 255, 255, 0.08);
1985
- height: 165px;
1986
- overflow-y: auto;
1987
- padding: 8px 10px;
1988
- font-size: 12px;
1989
- line-height: 1.5;
1990
- }
1991
- .playConsoleEmpty {
1992
- color: #6a6a6a;
1993
- }
1994
- .playConsoleLine {
1995
- white-space: pre-wrap;
1996
- word-break: break-word;
1997
- color: #c8c8c8;
1998
- }
1999
- .playConsoleLineWarn {
2000
- color: #e0af68;
2001
- }
2002
- .playConsoleLineError {
2003
- color: #ff7a93;
2004
- }
2005
-
2006
- /* While the logs drawer is mounted, scale the deck card to fit ABOVE the drawer
2007
- (rather than sitting behind it) so play stays fully visible and interactive.
2008
- The SDK's initPlayCard() pins `#root > *` as a viewport-centered card with
2009
- !important; this higher-specificity (attribute + id) rule overrides its size
2010
- and vertical offset. The three custom properties are driven from JS in
2011
- PlayConsole using the live drawer height + the SDK's natural card size. */
2012
- :global(html[data-castle-logs] #root > *) {
2013
- width: var(--castle-logs-card-w, var(--castle-card-w, 100vw)) !important;
2014
- height: var(--castle-logs-card-h, var(--castle-card-h, 100vh)) !important;
2015
- transform: translate(-50%, calc(-50% - var(--castle-logs-shift, 0px))) !important;
2016
- transition:
2017
- transform 0.18s ease,
2018
- width 0.18s ease,
2019
- height 0.18s ease;
2020
- }
@@ -1,27 +1,23 @@
1
1
  import React from 'react';
2
2
  import { createRoot } from 'react-dom/client';
3
3
  import { isEdit, setup } from 'castle-web-sdk';
4
- import { App } from './editors/App';
5
4
  import { PlayOnly } from './editors/PlayOnly';
6
5
  import { ErrorBoundary } from './editors/ErrorBoundary';
7
- import { FileList, SingleEditor } from './editors/SingleEditor';
6
+ import { SingleEditor } from './editors/SingleEditor';
8
7
  document.body.dataset.castleScreenshotTarget = 'viewport';
9
8
  setup();
10
9
  const root = document.getElementById('root');
11
10
  if (!root) throw new Error('Missing root element');
12
- // Route on URL params so the shell can mount each piece in its own panel iframe:
11
+ // Route on URL params so the shell can mount each piece in its own panel iframe.
12
+ // File browsing and the code/text editor are now builtin shell panels, so the
13
+ // kit only renders the deck (play) and its rich per-file editors (scene/pxart):
13
14
  // (no edit / ?edit=0) -> play the deck (playtest panel)
14
- // ?panel=files -> the file list (asks the shell to open files)
15
- // ?file=<path>[&editor=<id>] -> a single editor for that file
16
- // (edit, no params) -> the combined editor app (legacy fallback)
15
+ // ?file=<path>[&editor=<id>] -> a single rich editor for that file
17
16
  const params = new URLSearchParams(window.location.search);
18
17
  function pick() {
19
18
  if (!isEdit()) return <PlayOnly />;
20
- if (params.get('panel') === 'files') {
21
- return <FileList selectedPath={params.get('file') ?? ''} />;
22
- }
23
19
  const file = params.get('file');
24
20
  if (file) return <SingleEditor path={file} editor={params.get('editor') ?? undefined} />;
25
- return <App />;
21
+ return <PlayOnly />;
26
22
  }
27
23
  createRoot(root).render(<ErrorBoundary>{pick()}</ErrorBoundary>);
@@ -0,0 +1,3 @@
1
+ allowBuilds:
2
+ '@fortawesome/fontawesome-common-types': set this to true or false
3
+ '@fortawesome/free-solid-svg-icons': set this to true or false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "castle-web-cli",
3
- "version": "0.4.74",
3
+ "version": "0.4.76",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "castle-web": "./dist/index.js"
@@ -23,15 +23,23 @@
23
23
  ]
24
24
  },
25
25
  "dependencies": {
26
+ "@codemirror/lang-javascript": "^6.2.5",
27
+ "@codemirror/language": "^6.12.3",
28
+ "@codemirror/state": "^6.6.0",
29
+ "@codemirror/view": "^6.41.1",
30
+ "@fortawesome/free-solid-svg-icons": "^5.15.4",
31
+ "@lezer/highlight": "^1.2.3",
26
32
  "@lydell/node-pty": "^1.2.0-beta.12",
27
33
  "@xterm/addon-fit": "^0.11.0",
28
34
  "@xterm/addon-serialize": "^0.14.0",
29
35
  "@xterm/headless": "^6.0.0",
30
36
  "@xterm/xterm": "^6.0.0",
37
+ "codemirror": "^6.0.2",
31
38
  "dockview": "^4.13.1",
32
39
  "marked": "^18.0.5",
33
40
  "nanoid": "^5.1.7",
34
41
  "open": "^10.0.0",
42
+ "picomatch": "^4.0.4",
35
43
  "react": "^18.3.1",
36
44
  "react-dom": "^18.3.1",
37
45
  "vite": "^8.0.3",
@@ -40,6 +48,7 @@
40
48
  },
41
49
  "devDependencies": {
42
50
  "@types/node": "^20.0.0",
51
+ "@types/picomatch": "^4.0.2",
43
52
  "@types/react": "^18.3.31",
44
53
  "@types/react-dom": "^18.3.7",
45
54
  "@types/ws": "^8.18.1",