castle-web-cli 0.4.1 → 0.4.3

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 (158) hide show
  1. package/dist/api.d.ts +53 -5
  2. package/dist/api.js +42 -15
  3. package/dist/config.d.ts +2 -0
  4. package/dist/config.js +25 -11
  5. package/dist/get-deck.d.ts +3 -0
  6. package/dist/get-deck.js +64 -0
  7. package/dist/ide-client.d.ts +1 -0
  8. package/dist/ide-client.js +537 -0
  9. package/dist/ide.d.ts +16 -0
  10. package/dist/ide.js +546 -0
  11. package/dist/index.js +36 -41
  12. package/dist/init.d.ts +3 -1
  13. package/dist/init.js +173 -24
  14. package/dist/localPaths.d.ts +6 -0
  15. package/dist/localPaths.js +33 -0
  16. package/dist/login.js +1 -1
  17. package/dist/preview.d.ts +3 -0
  18. package/dist/preview.js +53 -34
  19. package/dist/save-deck.d.ts +2 -0
  20. package/dist/{push.js → save-deck.js} +66 -5
  21. package/dist/serve.d.ts +2 -0
  22. package/dist/serve.js +290 -27
  23. package/kits/basic-2d/.prettierrc +8 -0
  24. package/kits/basic-2d/CLAUDE.md +131 -0
  25. package/kits/basic-2d/behaviors/Camera.jsx +43 -0
  26. package/kits/basic-2d/behaviors/Collider.jsx +71 -0
  27. package/kits/basic-2d/behaviors/Drawing.jsx +139 -0
  28. package/kits/basic-2d/behaviors/Layout.jsx +16 -0
  29. package/kits/basic-2d/drawings/floor.drawing +70 -0
  30. package/kits/basic-2d/editors/App.jsx +152 -0
  31. package/kits/basic-2d/editors/CodeEditor.jsx +112 -0
  32. package/kits/basic-2d/editors/DrawingEditor.jsx +222 -0
  33. package/kits/basic-2d/editors/FileBrowser.jsx +143 -0
  34. package/kits/basic-2d/editors/PlayOnly.jsx +21 -0
  35. package/kits/basic-2d/editors/SceneEditor.jsx +1012 -0
  36. package/kits/basic-2d/editors/behaviorRegistry.js +24 -0
  37. package/kits/basic-2d/editors/editorHistory.js +52 -0
  38. package/kits/basic-2d/engine/ScenePlayer.jsx +83 -0
  39. package/kits/basic-2d/engine/SceneUI.jsx +67 -0
  40. package/kits/basic-2d/engine/TouchControls.jsx +136 -0
  41. package/kits/basic-2d/engine/autoInspector.jsx +51 -0
  42. package/kits/basic-2d/engine/files.js +62 -0
  43. package/kits/basic-2d/engine/scene.js +420 -0
  44. package/kits/basic-2d/engine/ui.jsx +344 -0
  45. package/kits/basic-2d/engine/ui.module.css +928 -0
  46. package/kits/basic-2d/eslint.config.js +50 -0
  47. package/kits/basic-2d/index.html +11 -0
  48. package/kits/basic-2d/main.jsx +10 -0
  49. package/kits/basic-2d/package-lock.json +2706 -0
  50. package/kits/basic-2d/package.json +41 -0
  51. package/kits/basic-2d/scenes/main.scene +108 -0
  52. package/kits/basic-2d/vite.config.js +1 -0
  53. package/kits/basic-2d-frozen/.prettierrc +8 -0
  54. package/kits/basic-2d-frozen/CLAUDE.md +131 -0
  55. package/kits/basic-2d-frozen/behaviors/Camera.jsx +43 -0
  56. package/kits/basic-2d-frozen/behaviors/Collider.jsx +71 -0
  57. package/kits/basic-2d-frozen/behaviors/Drawing.jsx +139 -0
  58. package/kits/basic-2d-frozen/behaviors/Layout.jsx +16 -0
  59. package/kits/basic-2d-frozen/drawings/floor.drawing +70 -0
  60. package/kits/basic-2d-frozen/editors/App.jsx +152 -0
  61. package/kits/basic-2d-frozen/editors/CodeEditor.jsx +112 -0
  62. package/kits/basic-2d-frozen/editors/DrawingEditor.jsx +222 -0
  63. package/kits/basic-2d-frozen/editors/FileBrowser.jsx +143 -0
  64. package/kits/basic-2d-frozen/editors/PlayOnly.jsx +21 -0
  65. package/kits/basic-2d-frozen/editors/SceneEditor.jsx +1012 -0
  66. package/kits/basic-2d-frozen/editors/behaviorRegistry.js +24 -0
  67. package/kits/basic-2d-frozen/editors/editorHistory.js +52 -0
  68. package/kits/basic-2d-frozen/engine/ScenePlayer.jsx +83 -0
  69. package/kits/basic-2d-frozen/engine/SceneUI.jsx +67 -0
  70. package/kits/basic-2d-frozen/engine/TouchControls.jsx +136 -0
  71. package/kits/basic-2d-frozen/engine/autoInspector.jsx +51 -0
  72. package/kits/basic-2d-frozen/engine/files.js +62 -0
  73. package/kits/basic-2d-frozen/engine/scene.js +420 -0
  74. package/kits/basic-2d-frozen/engine/ui.jsx +344 -0
  75. package/kits/basic-2d-frozen/engine/ui.module.css +928 -0
  76. package/kits/basic-2d-frozen/eslint.config.js +50 -0
  77. package/kits/basic-2d-frozen/index.html +11 -0
  78. package/kits/basic-2d-frozen/main.jsx +10 -0
  79. package/kits/basic-2d-frozen/package-lock.json +2706 -0
  80. package/kits/basic-2d-frozen/package.json +41 -0
  81. package/kits/basic-2d-frozen/scenes/main.scene +108 -0
  82. package/kits/basic-2d-frozen/vite.config.js +1 -0
  83. package/kits/rpg-2d/.prettierrc +8 -0
  84. package/kits/rpg-2d/behaviors/Camera.tsx +52 -0
  85. package/kits/rpg-2d/behaviors/Collider.tsx +98 -0
  86. package/kits/rpg-2d/behaviors/Dialog.tsx +184 -0
  87. package/kits/rpg-2d/behaviors/Drawing.tsx +161 -0
  88. package/kits/rpg-2d/behaviors/Friend.tsx +45 -0
  89. package/kits/rpg-2d/behaviors/Layout.tsx +29 -0
  90. package/kits/rpg-2d/behaviors/PlayerController.tsx +255 -0
  91. package/kits/rpg-2d/behaviors/Portal.tsx +60 -0
  92. package/kits/rpg-2d/behaviors/QuestLog.tsx +90 -0
  93. package/kits/rpg-2d/behaviors/SaveMenu.tsx +123 -0
  94. package/kits/rpg-2d/behaviors/Tilemap.tsx +90 -0
  95. package/kits/rpg-2d/drawings/bld-home.drawing +8136 -0
  96. package/kits/rpg-2d/drawings/env-crate.drawing +509 -0
  97. package/kits/rpg-2d/drawings/env-fence.drawing +536 -0
  98. package/kits/rpg-2d/drawings/env-flower-bed.drawing +607 -0
  99. package/kits/rpg-2d/drawings/env-fountain.drawing +2622 -0
  100. package/kits/rpg-2d/drawings/env-hedge.drawing +601 -0
  101. package/kits/rpg-2d/drawings/env-house-blue.drawing +1 -0
  102. package/kits/rpg-2d/drawings/env-house-green.drawing +1 -0
  103. package/kits/rpg-2d/drawings/env-tree-oak.drawing +1540 -0
  104. package/kits/rpg-2d/drawings/env-tree-pine.drawing +1315 -0
  105. package/kits/rpg-2d/drawings/floor.drawing +70 -0
  106. package/kits/rpg-2d/drawings/fx-sparkle.drawing +926 -0
  107. package/kits/rpg-2d/drawings/npc-juno-idle-down.drawing +1099 -0
  108. package/kits/rpg-2d/drawings/npc-juno-walk-down.drawing +4177 -0
  109. package/kits/rpg-2d/drawings/npc-opal-idle-down.drawing +1099 -0
  110. package/kits/rpg-2d/drawings/npc-opal-walk-down.drawing +4177 -0
  111. package/kits/rpg-2d/drawings/player-idle-down.drawing +1070 -0
  112. package/kits/rpg-2d/drawings/player-idle-left.drawing +1070 -0
  113. package/kits/rpg-2d/drawings/player-idle-right.drawing +1070 -0
  114. package/kits/rpg-2d/drawings/player-idle-up.drawing +1070 -0
  115. package/kits/rpg-2d/drawings/player-walk-down.drawing +4148 -0
  116. package/kits/rpg-2d/drawings/player-walk-left.drawing +4148 -0
  117. package/kits/rpg-2d/drawings/player-walk-right.drawing +4148 -0
  118. package/kits/rpg-2d/drawings/player-walk-up.drawing +4148 -0
  119. package/kits/rpg-2d/editors/App.tsx +163 -0
  120. package/kits/rpg-2d/editors/CodeEditor.tsx +120 -0
  121. package/kits/rpg-2d/editors/DrawingEditor.tsx +278 -0
  122. package/kits/rpg-2d/editors/FileBrowser.tsx +191 -0
  123. package/kits/rpg-2d/editors/PlayOnly.tsx +26 -0
  124. package/kits/rpg-2d/editors/SceneEditor.tsx +1093 -0
  125. package/kits/rpg-2d/editors/behaviorRegistry.ts +33 -0
  126. package/kits/rpg-2d/editors/editorHistory.ts +75 -0
  127. package/kits/rpg-2d/editors/editorProps.ts +10 -0
  128. package/kits/rpg-2d/engine/ScenePlayer.tsx +130 -0
  129. package/kits/rpg-2d/engine/SceneUI.tsx +74 -0
  130. package/kits/rpg-2d/engine/TouchControls.tsx +157 -0
  131. package/kits/rpg-2d/engine/autoInspector.tsx +111 -0
  132. package/kits/rpg-2d/engine/drawing.ts +81 -0
  133. package/kits/rpg-2d/engine/files.ts +215 -0
  134. package/kits/rpg-2d/engine/scene.ts +484 -0
  135. package/kits/rpg-2d/engine/ui.module.css +928 -0
  136. package/kits/rpg-2d/engine/ui.tsx +483 -0
  137. package/kits/rpg-2d/eslint.config.js +46 -0
  138. package/kits/rpg-2d/index.html +11 -0
  139. package/kits/rpg-2d/main.tsx +14 -0
  140. package/kits/rpg-2d/package-lock.json +3149 -0
  141. package/kits/rpg-2d/package.json +46 -0
  142. package/kits/rpg-2d/scenes/main.scene +203 -0
  143. package/kits/rpg-2d/tsconfig.json +17 -0
  144. package/kits/rpg-2d/vite-env.d.ts +7 -0
  145. package/kits/rpg-2d/vite.config.js +1 -0
  146. package/package.json +27 -5
  147. package/AGENTS.md +0 -25
  148. package/dist/push.d.ts +0 -1
  149. package/src/api.ts +0 -160
  150. package/src/bundle.ts +0 -28
  151. package/src/config.ts +0 -36
  152. package/src/index.ts +0 -143
  153. package/src/init.ts +0 -71
  154. package/src/login.ts +0 -24
  155. package/src/preview.ts +0 -94
  156. package/src/push.ts +0 -118
  157. package/src/serve.ts +0 -134
  158. package/tsconfig.json +0 -13
@@ -0,0 +1,344 @@
1
+ import React, { useRef, useState } from 'react';
2
+ import {
3
+ faBars,
4
+ faChevronDown,
5
+ faChevronRight,
6
+ faChevronUp,
7
+ faClone,
8
+ faObjectGroup,
9
+ faPalette,
10
+ faPlay,
11
+ faPlus,
12
+ faRedo,
13
+ faStop,
14
+ faTimes,
15
+ faTrash,
16
+ faUndo,
17
+ faVideo,
18
+ } from '@fortawesome/free-solid-svg-icons';
19
+ import styles from './ui.module.css';
20
+ export { styles };
21
+ export const theme = {
22
+ transparentChecker:
23
+ 'repeating-linear-gradient(45deg, #050505, #050505 4px, #252525 4px, #252525 8px)',
24
+ };
25
+ export function cx(...parts) {
26
+ return parts.filter(Boolean).join(' ');
27
+ }
28
+ export function AppShell({ children }) {
29
+ return <div className={styles.appShell}>{children}</div>;
30
+ }
31
+ export function MainEditor({ children }) {
32
+ return <main className={styles.mainEditor}>{children}</main>;
33
+ }
34
+ export function EditorHeader({ title, subtitle, right, onToggleFiles, filesOpen }) {
35
+ const hasRight = !!right || !!onToggleFiles;
36
+ return (
37
+ <header className={styles.editorHeader}>
38
+ <div className={styles.editorHeaderLeft}>
39
+ <div>
40
+ <div className={styles.editorTitle}>{title}</div>
41
+ {subtitle ? <div className={styles.muted}>{subtitle}</div> : null}
42
+ </div>
43
+ </div>
44
+ {hasRight ? (
45
+ <div className={styles.editorHeaderRight}>
46
+ {right}
47
+ {onToggleFiles ? (
48
+ <button
49
+ type="button"
50
+ className={cx(styles.headerFilesButton, styles.mobileOnly)}
51
+ onClick={onToggleFiles}
52
+ aria-label="Files"
53
+ aria-pressed={filesOpen ? 'true' : 'false'}>
54
+ <Icon name="bars" />
55
+ </button>
56
+ ) : null}
57
+ </div>
58
+ ) : null}
59
+ </header>
60
+ );
61
+ }
62
+ export function EditorBody({ children }) {
63
+ return <div className={styles.editorBody}>{children}</div>;
64
+ }
65
+ export function Button({ children, active = false, variant = '', className = '', ...props }) {
66
+ return (
67
+ <button
68
+ className={cx(
69
+ styles.button,
70
+ active && styles.buttonActive,
71
+ variant === 'primary' && styles.buttonPrimary,
72
+ variant === 'danger' && styles.buttonDanger,
73
+ className
74
+ )}
75
+ {...props}>
76
+ {children}
77
+ </button>
78
+ );
79
+ }
80
+ export function IconButton({ icon, label, active = false, variant = '', ...props }) {
81
+ return (
82
+ <Button
83
+ active={active}
84
+ variant={variant}
85
+ className={styles.iconButton}
86
+ aria-label={label}
87
+ title={label}
88
+ {...props}>
89
+ <Icon name={icon} />
90
+ </Button>
91
+ );
92
+ }
93
+ const icons = {
94
+ bars: faBars,
95
+ camera: faVideo,
96
+ 'chevron-down': faChevronDown,
97
+ 'chevron-right': faChevronRight,
98
+ 'chevron-up': faChevronUp,
99
+ clone: faClone,
100
+ 'object-group': faObjectGroup,
101
+ palette: faPalette,
102
+ play: faPlay,
103
+ plus: faPlus,
104
+ redo: faRedo,
105
+ stop: faStop,
106
+ times: faTimes,
107
+ trash: faTrash,
108
+ undo: faUndo,
109
+ };
110
+ export function Icon({ name }) {
111
+ const def = icons[name];
112
+ if (!def) return null;
113
+ const [width, height, , , path] = def.icon;
114
+ const d = Array.isArray(path) ? path.join(' ') : path;
115
+ return (
116
+ <svg
117
+ viewBox={`0 0 ${width} ${height}`}
118
+ aria-hidden="true"
119
+ style={{ width: '1em', height: '1em', display: 'inline-block', fill: 'currentColor' }}>
120
+ <path d={d} />
121
+ </svg>
122
+ );
123
+ }
124
+ export function Panel({ title, children }) {
125
+ return (
126
+ <section className={styles.panel}>
127
+ {title ? <div className={styles.panelHeader}>{title}</div> : null}
128
+ <div className={styles.panelBody}>{children}</div>
129
+ </section>
130
+ );
131
+ }
132
+ export function FieldRow({ label, children }) {
133
+ return (
134
+ <label className={styles.fieldRow}>
135
+ <span className={styles.fieldLabel}>{label}</span>
136
+ {children}
137
+ </label>
138
+ );
139
+ }
140
+ export function TextField({ label, value, onChange }) {
141
+ return (
142
+ <FieldRow label={label}>
143
+ <input
144
+ className={styles.input}
145
+ value={value ?? ''}
146
+ onChange={(event) => onChange(event.target.value)}
147
+ />
148
+ </FieldRow>
149
+ );
150
+ }
151
+ export function NumberField({ label, value, onChange, min, max, step = 1 }) {
152
+ const current = Number.isFinite(value) ? (value ?? 0) : 0;
153
+ const [draft, setDraft] = useState(String(current));
154
+ const editingRef = useRef(false);
155
+ const cancelRef = useRef(false);
156
+ // keep the draft in sync with the committed value while not editing
157
+ if (!editingRef.current && draft !== String(current)) {
158
+ setDraft(String(current));
159
+ }
160
+ function commit(raw) {
161
+ let next = Number(raw);
162
+ if (!Number.isFinite(next)) next = current;
163
+ if (min != null && next < min) next = min;
164
+ if (max != null && next > max) next = max;
165
+ setDraft(String(next));
166
+ onChange(next);
167
+ }
168
+ function stepBy(delta) {
169
+ let next = current + delta;
170
+ if (min != null && next < min) next = min;
171
+ if (max != null && next > max) next = max;
172
+ setDraft(String(next));
173
+ onChange(next);
174
+ }
175
+ return (
176
+ <FieldRow label={label}>
177
+ <div className={styles.numberField}>
178
+ <input
179
+ className={cx(styles.input, styles.numberInput)}
180
+ type="number"
181
+ min={min}
182
+ max={max}
183
+ step={step}
184
+ value={draft}
185
+ onFocus={() => {
186
+ editingRef.current = true;
187
+ }}
188
+ onChange={(event) => setDraft(event.target.value)}
189
+ onBlur={(event) => {
190
+ editingRef.current = false;
191
+ if (cancelRef.current) {
192
+ cancelRef.current = false;
193
+ setDraft(String(current));
194
+ return;
195
+ }
196
+ commit(event.target.value);
197
+ }}
198
+ onKeyDown={(event) => {
199
+ if (event.key === 'Enter') {
200
+ event.preventDefault();
201
+ commit(event.currentTarget.value);
202
+ event.currentTarget.blur();
203
+ } else if (event.key === 'Escape') {
204
+ event.preventDefault();
205
+ cancelRef.current = true;
206
+ setDraft(String(current));
207
+ event.currentTarget.blur();
208
+ }
209
+ }}
210
+ />
211
+ <div className={styles.numberSteppers}>
212
+ <button
213
+ type="button"
214
+ className={styles.numberStepper}
215
+ tabIndex={-1}
216
+ aria-label="Increment"
217
+ disabled={max != null && current >= max}
218
+ onClick={() => stepBy(step)}>
219
+ <Icon name="chevron-up" />
220
+ </button>
221
+ <button
222
+ type="button"
223
+ className={styles.numberStepper}
224
+ tabIndex={-1}
225
+ aria-label="Decrement"
226
+ disabled={min != null && current <= min}
227
+ onClick={() => stepBy(-step)}>
228
+ <Icon name="chevron-down" />
229
+ </button>
230
+ </div>
231
+ </div>
232
+ </FieldRow>
233
+ );
234
+ }
235
+ export function CheckboxField({ label, checked, onChange }) {
236
+ return (
237
+ <FieldRow label={label}>
238
+ <button
239
+ type="button"
240
+ className={cx(styles.toggle, checked && styles.toggleOn)}
241
+ role="switch"
242
+ aria-checked={!!checked}
243
+ onClick={() => onChange(!checked)}>
244
+ <span className={styles.toggleKnob} />
245
+ </button>
246
+ </FieldRow>
247
+ );
248
+ }
249
+ export function ColorField({ label, value, onChange }) {
250
+ const hex = normalizeHex(value);
251
+ const alpha = hex.length === 9 ? hex.slice(7) : '';
252
+ const rgb = hex.slice(0, 7);
253
+ return (
254
+ <FieldRow label={label}>
255
+ <input
256
+ className={styles.colorInput}
257
+ type="color"
258
+ value={rgb}
259
+ onChange={(event) => onChange(event.target.value + alpha)}
260
+ />
261
+ </FieldRow>
262
+ );
263
+ }
264
+ function normalizeHex(value) {
265
+ const raw = (value ?? '').trim();
266
+ if (/^#[0-9a-fA-F]{3}$/.test(raw)) {
267
+ return '#' + raw.slice(1).replace(/./g, (c) => c + c);
268
+ }
269
+ if (/^#[0-9a-fA-F]{6}([0-9a-fA-F]{2})?$/.test(raw)) return raw;
270
+ return '#000000';
271
+ }
272
+ export function isHexColor(value) {
273
+ return (
274
+ typeof value === 'string' && /^#[0-9a-fA-F]{3}([0-9a-fA-F]{3}([0-9a-fA-F]{2})?)?$/.test(value)
275
+ );
276
+ }
277
+ export function useMobileSheet({ snap, baseClassName, onTransition }) {
278
+ const startY = useRef(0);
279
+ const lastDy = useRef(0);
280
+ const dragging = useRef(false);
281
+ function onPointerDown(event) {
282
+ startY.current = event.clientY;
283
+ lastDy.current = 0;
284
+ dragging.current = true;
285
+ event.currentTarget.setPointerCapture(event.pointerId);
286
+ }
287
+ function onPointerMove(event) {
288
+ if (!dragging.current) return;
289
+ lastDy.current = event.clientY - startY.current;
290
+ }
291
+ function endDrag() {
292
+ if (!dragging.current) return;
293
+ dragging.current = false;
294
+ const dy = lastDy.current;
295
+ lastDy.current = 0;
296
+ if (Math.abs(dy) < 6) onTransition('tap');
297
+ else if (dy > 30) onTransition('down');
298
+ else if (dy < -30) onTransition('up');
299
+ }
300
+ return {
301
+ rootProps: {
302
+ className: baseClassName,
303
+ 'data-sheet-snap': snap,
304
+ },
305
+ grabProps: {
306
+ className: cx(styles.sheetGrab, styles.mobileOnly),
307
+ onPointerDown,
308
+ onPointerMove,
309
+ onPointerUp: endDrag,
310
+ onPointerCancel: endDrag,
311
+ },
312
+ };
313
+ }
314
+ export function SheetGrabHandle({ label, hint }) {
315
+ return (
316
+ <>
317
+ <div className={styles.sheetGrabBar} />
318
+ <div className={styles.sheetGrabLabelRow}>
319
+ <span className={styles.sheetGrabLabel}>{label}</span>
320
+ {hint ? <span className={styles.sheetGrabHint}>{hint}</span> : null}
321
+ </div>
322
+ </>
323
+ );
324
+ }
325
+ export function SelectField({ label, value, onChange, options }) {
326
+ return (
327
+ <FieldRow label={label}>
328
+ <select
329
+ className={styles.select}
330
+ value={value ?? ''}
331
+ onChange={(event) => onChange(event.target.value)}>
332
+ {options.map((option) => {
333
+ const value = typeof option === 'string' ? option : option.value;
334
+ const label = typeof option === 'string' ? option : option.label;
335
+ return (
336
+ <option key={value} value={value}>
337
+ {label}
338
+ </option>
339
+ );
340
+ })}
341
+ </select>
342
+ </FieldRow>
343
+ );
344
+ }