castle-web-cli 0.4.3 → 0.4.4
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/dist/index.js +8 -2
- package/dist/init.js +1 -1
- package/package.json +1 -1
- package/kits/basic-2d-frozen/.prettierrc +0 -8
- package/kits/basic-2d-frozen/CLAUDE.md +0 -131
- package/kits/basic-2d-frozen/behaviors/Camera.jsx +0 -43
- package/kits/basic-2d-frozen/behaviors/Collider.jsx +0 -71
- package/kits/basic-2d-frozen/behaviors/Drawing.jsx +0 -139
- package/kits/basic-2d-frozen/behaviors/Layout.jsx +0 -16
- package/kits/basic-2d-frozen/drawings/floor.drawing +0 -70
- package/kits/basic-2d-frozen/editors/App.jsx +0 -152
- package/kits/basic-2d-frozen/editors/CodeEditor.jsx +0 -112
- package/kits/basic-2d-frozen/editors/DrawingEditor.jsx +0 -222
- package/kits/basic-2d-frozen/editors/FileBrowser.jsx +0 -143
- package/kits/basic-2d-frozen/editors/PlayOnly.jsx +0 -21
- package/kits/basic-2d-frozen/editors/SceneEditor.jsx +0 -1012
- package/kits/basic-2d-frozen/editors/behaviorRegistry.js +0 -24
- package/kits/basic-2d-frozen/editors/editorHistory.js +0 -52
- package/kits/basic-2d-frozen/engine/ScenePlayer.jsx +0 -83
- package/kits/basic-2d-frozen/engine/SceneUI.jsx +0 -67
- package/kits/basic-2d-frozen/engine/TouchControls.jsx +0 -136
- package/kits/basic-2d-frozen/engine/autoInspector.jsx +0 -51
- package/kits/basic-2d-frozen/engine/files.js +0 -62
- package/kits/basic-2d-frozen/engine/scene.js +0 -420
- package/kits/basic-2d-frozen/engine/ui.jsx +0 -344
- package/kits/basic-2d-frozen/engine/ui.module.css +0 -928
- package/kits/basic-2d-frozen/eslint.config.js +0 -50
- package/kits/basic-2d-frozen/index.html +0 -11
- package/kits/basic-2d-frozen/main.jsx +0 -10
- package/kits/basic-2d-frozen/package-lock.json +0 -2706
- package/kits/basic-2d-frozen/package.json +0 -41
- package/kits/basic-2d-frozen/scenes/main.scene +0 -108
- package/kits/basic-2d-frozen/vite.config.js +0 -1
- package/kits/rpg-2d/.prettierrc +0 -8
- package/kits/rpg-2d/behaviors/Camera.tsx +0 -52
- package/kits/rpg-2d/behaviors/Collider.tsx +0 -98
- package/kits/rpg-2d/behaviors/Dialog.tsx +0 -184
- package/kits/rpg-2d/behaviors/Drawing.tsx +0 -161
- package/kits/rpg-2d/behaviors/Friend.tsx +0 -45
- package/kits/rpg-2d/behaviors/Layout.tsx +0 -29
- package/kits/rpg-2d/behaviors/PlayerController.tsx +0 -255
- package/kits/rpg-2d/behaviors/Portal.tsx +0 -60
- package/kits/rpg-2d/behaviors/QuestLog.tsx +0 -90
- package/kits/rpg-2d/behaviors/SaveMenu.tsx +0 -123
- package/kits/rpg-2d/behaviors/Tilemap.tsx +0 -90
- package/kits/rpg-2d/drawings/bld-home.drawing +0 -8136
- package/kits/rpg-2d/drawings/env-crate.drawing +0 -509
- package/kits/rpg-2d/drawings/env-fence.drawing +0 -536
- package/kits/rpg-2d/drawings/env-flower-bed.drawing +0 -607
- package/kits/rpg-2d/drawings/env-fountain.drawing +0 -2622
- package/kits/rpg-2d/drawings/env-hedge.drawing +0 -601
- package/kits/rpg-2d/drawings/env-house-blue.drawing +0 -1
- package/kits/rpg-2d/drawings/env-house-green.drawing +0 -1
- package/kits/rpg-2d/drawings/env-tree-oak.drawing +0 -1540
- package/kits/rpg-2d/drawings/env-tree-pine.drawing +0 -1315
- package/kits/rpg-2d/drawings/floor.drawing +0 -70
- package/kits/rpg-2d/drawings/fx-sparkle.drawing +0 -926
- package/kits/rpg-2d/drawings/npc-juno-idle-down.drawing +0 -1099
- package/kits/rpg-2d/drawings/npc-juno-walk-down.drawing +0 -4177
- package/kits/rpg-2d/drawings/npc-opal-idle-down.drawing +0 -1099
- package/kits/rpg-2d/drawings/npc-opal-walk-down.drawing +0 -4177
- package/kits/rpg-2d/drawings/player-idle-down.drawing +0 -1070
- package/kits/rpg-2d/drawings/player-idle-left.drawing +0 -1070
- package/kits/rpg-2d/drawings/player-idle-right.drawing +0 -1070
- package/kits/rpg-2d/drawings/player-idle-up.drawing +0 -1070
- package/kits/rpg-2d/drawings/player-walk-down.drawing +0 -4148
- package/kits/rpg-2d/drawings/player-walk-left.drawing +0 -4148
- package/kits/rpg-2d/drawings/player-walk-right.drawing +0 -4148
- package/kits/rpg-2d/drawings/player-walk-up.drawing +0 -4148
- package/kits/rpg-2d/editors/App.tsx +0 -163
- package/kits/rpg-2d/editors/CodeEditor.tsx +0 -120
- package/kits/rpg-2d/editors/DrawingEditor.tsx +0 -278
- package/kits/rpg-2d/editors/FileBrowser.tsx +0 -191
- package/kits/rpg-2d/editors/PlayOnly.tsx +0 -26
- package/kits/rpg-2d/editors/SceneEditor.tsx +0 -1093
- package/kits/rpg-2d/editors/behaviorRegistry.ts +0 -33
- package/kits/rpg-2d/editors/editorHistory.ts +0 -75
- package/kits/rpg-2d/editors/editorProps.ts +0 -10
- package/kits/rpg-2d/engine/ScenePlayer.tsx +0 -130
- package/kits/rpg-2d/engine/SceneUI.tsx +0 -74
- package/kits/rpg-2d/engine/TouchControls.tsx +0 -157
- package/kits/rpg-2d/engine/autoInspector.tsx +0 -111
- package/kits/rpg-2d/engine/drawing.ts +0 -81
- package/kits/rpg-2d/engine/files.ts +0 -215
- package/kits/rpg-2d/engine/scene.ts +0 -484
- package/kits/rpg-2d/engine/ui.module.css +0 -928
- package/kits/rpg-2d/engine/ui.tsx +0 -483
- package/kits/rpg-2d/eslint.config.js +0 -46
- package/kits/rpg-2d/index.html +0 -11
- package/kits/rpg-2d/main.tsx +0 -14
- package/kits/rpg-2d/package-lock.json +0 -3149
- package/kits/rpg-2d/package.json +0 -46
- package/kits/rpg-2d/scenes/main.scene +0 -203
- package/kits/rpg-2d/tsconfig.json +0 -17
- package/kits/rpg-2d/vite-env.d.ts +0 -7
- package/kits/rpg-2d/vite.config.js +0 -1
|
@@ -1,344 +0,0 @@
|
|
|
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
|
-
}
|