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.
Files changed (96) hide show
  1. package/dist/index.js +8 -2
  2. package/dist/init.js +1 -1
  3. package/package.json +1 -1
  4. package/kits/basic-2d-frozen/.prettierrc +0 -8
  5. package/kits/basic-2d-frozen/CLAUDE.md +0 -131
  6. package/kits/basic-2d-frozen/behaviors/Camera.jsx +0 -43
  7. package/kits/basic-2d-frozen/behaviors/Collider.jsx +0 -71
  8. package/kits/basic-2d-frozen/behaviors/Drawing.jsx +0 -139
  9. package/kits/basic-2d-frozen/behaviors/Layout.jsx +0 -16
  10. package/kits/basic-2d-frozen/drawings/floor.drawing +0 -70
  11. package/kits/basic-2d-frozen/editors/App.jsx +0 -152
  12. package/kits/basic-2d-frozen/editors/CodeEditor.jsx +0 -112
  13. package/kits/basic-2d-frozen/editors/DrawingEditor.jsx +0 -222
  14. package/kits/basic-2d-frozen/editors/FileBrowser.jsx +0 -143
  15. package/kits/basic-2d-frozen/editors/PlayOnly.jsx +0 -21
  16. package/kits/basic-2d-frozen/editors/SceneEditor.jsx +0 -1012
  17. package/kits/basic-2d-frozen/editors/behaviorRegistry.js +0 -24
  18. package/kits/basic-2d-frozen/editors/editorHistory.js +0 -52
  19. package/kits/basic-2d-frozen/engine/ScenePlayer.jsx +0 -83
  20. package/kits/basic-2d-frozen/engine/SceneUI.jsx +0 -67
  21. package/kits/basic-2d-frozen/engine/TouchControls.jsx +0 -136
  22. package/kits/basic-2d-frozen/engine/autoInspector.jsx +0 -51
  23. package/kits/basic-2d-frozen/engine/files.js +0 -62
  24. package/kits/basic-2d-frozen/engine/scene.js +0 -420
  25. package/kits/basic-2d-frozen/engine/ui.jsx +0 -344
  26. package/kits/basic-2d-frozen/engine/ui.module.css +0 -928
  27. package/kits/basic-2d-frozen/eslint.config.js +0 -50
  28. package/kits/basic-2d-frozen/index.html +0 -11
  29. package/kits/basic-2d-frozen/main.jsx +0 -10
  30. package/kits/basic-2d-frozen/package-lock.json +0 -2706
  31. package/kits/basic-2d-frozen/package.json +0 -41
  32. package/kits/basic-2d-frozen/scenes/main.scene +0 -108
  33. package/kits/basic-2d-frozen/vite.config.js +0 -1
  34. package/kits/rpg-2d/.prettierrc +0 -8
  35. package/kits/rpg-2d/behaviors/Camera.tsx +0 -52
  36. package/kits/rpg-2d/behaviors/Collider.tsx +0 -98
  37. package/kits/rpg-2d/behaviors/Dialog.tsx +0 -184
  38. package/kits/rpg-2d/behaviors/Drawing.tsx +0 -161
  39. package/kits/rpg-2d/behaviors/Friend.tsx +0 -45
  40. package/kits/rpg-2d/behaviors/Layout.tsx +0 -29
  41. package/kits/rpg-2d/behaviors/PlayerController.tsx +0 -255
  42. package/kits/rpg-2d/behaviors/Portal.tsx +0 -60
  43. package/kits/rpg-2d/behaviors/QuestLog.tsx +0 -90
  44. package/kits/rpg-2d/behaviors/SaveMenu.tsx +0 -123
  45. package/kits/rpg-2d/behaviors/Tilemap.tsx +0 -90
  46. package/kits/rpg-2d/drawings/bld-home.drawing +0 -8136
  47. package/kits/rpg-2d/drawings/env-crate.drawing +0 -509
  48. package/kits/rpg-2d/drawings/env-fence.drawing +0 -536
  49. package/kits/rpg-2d/drawings/env-flower-bed.drawing +0 -607
  50. package/kits/rpg-2d/drawings/env-fountain.drawing +0 -2622
  51. package/kits/rpg-2d/drawings/env-hedge.drawing +0 -601
  52. package/kits/rpg-2d/drawings/env-house-blue.drawing +0 -1
  53. package/kits/rpg-2d/drawings/env-house-green.drawing +0 -1
  54. package/kits/rpg-2d/drawings/env-tree-oak.drawing +0 -1540
  55. package/kits/rpg-2d/drawings/env-tree-pine.drawing +0 -1315
  56. package/kits/rpg-2d/drawings/floor.drawing +0 -70
  57. package/kits/rpg-2d/drawings/fx-sparkle.drawing +0 -926
  58. package/kits/rpg-2d/drawings/npc-juno-idle-down.drawing +0 -1099
  59. package/kits/rpg-2d/drawings/npc-juno-walk-down.drawing +0 -4177
  60. package/kits/rpg-2d/drawings/npc-opal-idle-down.drawing +0 -1099
  61. package/kits/rpg-2d/drawings/npc-opal-walk-down.drawing +0 -4177
  62. package/kits/rpg-2d/drawings/player-idle-down.drawing +0 -1070
  63. package/kits/rpg-2d/drawings/player-idle-left.drawing +0 -1070
  64. package/kits/rpg-2d/drawings/player-idle-right.drawing +0 -1070
  65. package/kits/rpg-2d/drawings/player-idle-up.drawing +0 -1070
  66. package/kits/rpg-2d/drawings/player-walk-down.drawing +0 -4148
  67. package/kits/rpg-2d/drawings/player-walk-left.drawing +0 -4148
  68. package/kits/rpg-2d/drawings/player-walk-right.drawing +0 -4148
  69. package/kits/rpg-2d/drawings/player-walk-up.drawing +0 -4148
  70. package/kits/rpg-2d/editors/App.tsx +0 -163
  71. package/kits/rpg-2d/editors/CodeEditor.tsx +0 -120
  72. package/kits/rpg-2d/editors/DrawingEditor.tsx +0 -278
  73. package/kits/rpg-2d/editors/FileBrowser.tsx +0 -191
  74. package/kits/rpg-2d/editors/PlayOnly.tsx +0 -26
  75. package/kits/rpg-2d/editors/SceneEditor.tsx +0 -1093
  76. package/kits/rpg-2d/editors/behaviorRegistry.ts +0 -33
  77. package/kits/rpg-2d/editors/editorHistory.ts +0 -75
  78. package/kits/rpg-2d/editors/editorProps.ts +0 -10
  79. package/kits/rpg-2d/engine/ScenePlayer.tsx +0 -130
  80. package/kits/rpg-2d/engine/SceneUI.tsx +0 -74
  81. package/kits/rpg-2d/engine/TouchControls.tsx +0 -157
  82. package/kits/rpg-2d/engine/autoInspector.tsx +0 -111
  83. package/kits/rpg-2d/engine/drawing.ts +0 -81
  84. package/kits/rpg-2d/engine/files.ts +0 -215
  85. package/kits/rpg-2d/engine/scene.ts +0 -484
  86. package/kits/rpg-2d/engine/ui.module.css +0 -928
  87. package/kits/rpg-2d/engine/ui.tsx +0 -483
  88. package/kits/rpg-2d/eslint.config.js +0 -46
  89. package/kits/rpg-2d/index.html +0 -11
  90. package/kits/rpg-2d/main.tsx +0 -14
  91. package/kits/rpg-2d/package-lock.json +0 -3149
  92. package/kits/rpg-2d/package.json +0 -46
  93. package/kits/rpg-2d/scenes/main.scene +0 -203
  94. package/kits/rpg-2d/tsconfig.json +0 -17
  95. package/kits/rpg-2d/vite-env.d.ts +0 -7
  96. package/kits/rpg-2d/vite.config.js +0 -1
@@ -1,483 +0,0 @@
1
- import React, { useRef, useState } from 'react';
2
- import type { ButtonHTMLAttributes, PointerEvent, ReactNode } from 'react';
3
- import {
4
- faBars,
5
- faChevronDown,
6
- faChevronRight,
7
- faChevronUp,
8
- faClone,
9
- faObjectGroup,
10
- faPalette,
11
- faPlay,
12
- faPlus,
13
- faRedo,
14
- faStop,
15
- faTimes,
16
- faTrash,
17
- faUndo,
18
- faVideo,
19
- } from '@fortawesome/free-solid-svg-icons';
20
- import type { IconDefinition } from '@fortawesome/free-solid-svg-icons';
21
- import styles from './ui.module.css';
22
-
23
- export { styles };
24
-
25
- export const theme = {
26
- transparentChecker:
27
- 'repeating-linear-gradient(45deg, #050505, #050505 4px, #252525 4px, #252525 8px)',
28
- };
29
-
30
- export function cx(...parts: Array<string | false | null | undefined>): string {
31
- return parts.filter(Boolean).join(' ');
32
- }
33
-
34
- export function AppShell({ children }: { children: ReactNode }) {
35
- return <div className={styles.appShell}>{children}</div>;
36
- }
37
-
38
- export function MainEditor({ children }: { children: ReactNode }) {
39
- return <main className={styles.mainEditor}>{children}</main>;
40
- }
41
-
42
- export function EditorHeader({
43
- title,
44
- subtitle,
45
- right,
46
- onToggleFiles,
47
- filesOpen,
48
- }: {
49
- title: ReactNode;
50
- subtitle?: ReactNode;
51
- right?: ReactNode;
52
- onToggleFiles?: () => void;
53
- filesOpen?: boolean;
54
- }) {
55
- const hasRight = !!right || !!onToggleFiles;
56
- return (
57
- <header className={styles.editorHeader}>
58
- <div className={styles.editorHeaderLeft}>
59
- <div>
60
- <div className={styles.editorTitle}>{title}</div>
61
- {subtitle ? <div className={styles.muted}>{subtitle}</div> : null}
62
- </div>
63
- </div>
64
- {hasRight ? (
65
- <div className={styles.editorHeaderRight}>
66
- {right}
67
- {onToggleFiles ? (
68
- <button
69
- type="button"
70
- className={cx(styles.headerFilesButton, styles.mobileOnly)}
71
- onClick={onToggleFiles}
72
- aria-label="Files"
73
- aria-pressed={filesOpen ? 'true' : 'false'}>
74
- <Icon name="bars" />
75
- </button>
76
- ) : null}
77
- </div>
78
- ) : null}
79
- </header>
80
- );
81
- }
82
-
83
- export function EditorBody({ children }: { children: ReactNode }) {
84
- return <div className={styles.editorBody}>{children}</div>;
85
- }
86
-
87
- export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
88
- active?: boolean;
89
- variant?: '' | 'primary' | 'danger';
90
- }
91
-
92
- export function Button({
93
- children,
94
- active = false,
95
- variant = '',
96
- className = '',
97
- ...props
98
- }: ButtonProps) {
99
- return (
100
- <button
101
- className={cx(
102
- styles.button,
103
- active && styles.buttonActive,
104
- variant === 'primary' && styles.buttonPrimary,
105
- variant === 'danger' && styles.buttonDanger,
106
- className
107
- )}
108
- {...props}>
109
- {children}
110
- </button>
111
- );
112
- }
113
-
114
- export interface IconButtonProps extends Omit<ButtonProps, 'children'> {
115
- icon: string;
116
- label: string;
117
- }
118
-
119
- export function IconButton({
120
- icon,
121
- label,
122
- active = false,
123
- variant = '',
124
- ...props
125
- }: IconButtonProps) {
126
- return (
127
- <Button
128
- active={active}
129
- variant={variant}
130
- className={styles.iconButton}
131
- aria-label={label}
132
- title={label}
133
- {...props}>
134
- <Icon name={icon} />
135
- </Button>
136
- );
137
- }
138
-
139
- const icons: Record<string, IconDefinition> = {
140
- bars: faBars,
141
- camera: faVideo,
142
- 'chevron-down': faChevronDown,
143
- 'chevron-right': faChevronRight,
144
- 'chevron-up': faChevronUp,
145
- clone: faClone,
146
- 'object-group': faObjectGroup,
147
- palette: faPalette,
148
- play: faPlay,
149
- plus: faPlus,
150
- redo: faRedo,
151
- stop: faStop,
152
- times: faTimes,
153
- trash: faTrash,
154
- undo: faUndo,
155
- };
156
-
157
- export function Icon({ name }: { name: string }) {
158
- const def = icons[name];
159
- if (!def) return null;
160
- const [width, height, , , path] = def.icon;
161
- const d = Array.isArray(path) ? path.join(' ') : path;
162
- return (
163
- <svg
164
- viewBox={`0 0 ${width} ${height}`}
165
- aria-hidden="true"
166
- style={{ width: '1em', height: '1em', display: 'inline-block', fill: 'currentColor' }}>
167
- <path d={d} />
168
- </svg>
169
- );
170
- }
171
-
172
- export function Panel({ title, children }: { title?: ReactNode; children: ReactNode }) {
173
- return (
174
- <section className={styles.panel}>
175
- {title ? <div className={styles.panelHeader}>{title}</div> : null}
176
- <div className={styles.panelBody}>{children}</div>
177
- </section>
178
- );
179
- }
180
-
181
- export function FieldRow({ label, children }: { label: ReactNode; children: ReactNode }) {
182
- return (
183
- <label className={styles.fieldRow}>
184
- <span className={styles.fieldLabel}>{label}</span>
185
- {children}
186
- </label>
187
- );
188
- }
189
-
190
- export function TextField({
191
- label,
192
- value,
193
- onChange,
194
- }: {
195
- label: ReactNode;
196
- value: string | null | undefined;
197
- onChange: (value: string) => void;
198
- }) {
199
- return (
200
- <FieldRow label={label}>
201
- <input
202
- className={styles.input}
203
- value={value ?? ''}
204
- onChange={(event) => onChange(event.target.value)}
205
- />
206
- </FieldRow>
207
- );
208
- }
209
-
210
- export function NumberField({
211
- label,
212
- value,
213
- onChange,
214
- min,
215
- max,
216
- step = 1,
217
- }: {
218
- label: ReactNode;
219
- value: number | null | undefined;
220
- onChange: (value: number) => void;
221
- min?: number;
222
- max?: number;
223
- step?: number;
224
- }) {
225
- const current = Number.isFinite(value) ? (value ?? 0) : 0;
226
- const [draft, setDraft] = useState(String(current));
227
- const editingRef = useRef(false);
228
- const cancelRef = useRef(false);
229
-
230
- // keep the draft in sync with the committed value while not editing
231
- if (!editingRef.current && draft !== String(current)) {
232
- setDraft(String(current));
233
- }
234
-
235
- function commit(raw: string): void {
236
- let next = Number(raw);
237
- if (!Number.isFinite(next)) next = current;
238
- if (min != null && next < min) next = min;
239
- if (max != null && next > max) next = max;
240
- setDraft(String(next));
241
- onChange(next);
242
- }
243
-
244
- function stepBy(delta: number): void {
245
- let next = current + delta;
246
- if (min != null && next < min) next = min;
247
- if (max != null && next > max) next = max;
248
- setDraft(String(next));
249
- onChange(next);
250
- }
251
-
252
- return (
253
- <FieldRow label={label}>
254
- <div className={styles.numberField}>
255
- <input
256
- className={cx(styles.input, styles.numberInput)}
257
- type="number"
258
- min={min}
259
- max={max}
260
- step={step}
261
- value={draft}
262
- onFocus={() => {
263
- editingRef.current = true;
264
- }}
265
- onChange={(event) => setDraft(event.target.value)}
266
- onBlur={(event) => {
267
- editingRef.current = false;
268
- if (cancelRef.current) {
269
- cancelRef.current = false;
270
- setDraft(String(current));
271
- return;
272
- }
273
- commit(event.target.value);
274
- }}
275
- onKeyDown={(event) => {
276
- if (event.key === 'Enter') {
277
- event.preventDefault();
278
- commit(event.currentTarget.value);
279
- event.currentTarget.blur();
280
- } else if (event.key === 'Escape') {
281
- event.preventDefault();
282
- cancelRef.current = true;
283
- setDraft(String(current));
284
- event.currentTarget.blur();
285
- }
286
- }}
287
- />
288
- <div className={styles.numberSteppers}>
289
- <button
290
- type="button"
291
- className={styles.numberStepper}
292
- tabIndex={-1}
293
- aria-label="Increment"
294
- disabled={max != null && current >= max}
295
- onClick={() => stepBy(step)}>
296
- <Icon name="chevron-up" />
297
- </button>
298
- <button
299
- type="button"
300
- className={styles.numberStepper}
301
- tabIndex={-1}
302
- aria-label="Decrement"
303
- disabled={min != null && current <= min}
304
- onClick={() => stepBy(-step)}>
305
- <Icon name="chevron-down" />
306
- </button>
307
- </div>
308
- </div>
309
- </FieldRow>
310
- );
311
- }
312
-
313
- export function CheckboxField({
314
- label,
315
- checked,
316
- onChange,
317
- }: {
318
- label: ReactNode;
319
- checked: boolean | null | undefined;
320
- onChange: (checked: boolean) => void;
321
- }) {
322
- return (
323
- <FieldRow label={label}>
324
- <button
325
- type="button"
326
- className={cx(styles.toggle, checked && styles.toggleOn)}
327
- role="switch"
328
- aria-checked={!!checked}
329
- onClick={() => onChange(!checked)}>
330
- <span className={styles.toggleKnob} />
331
- </button>
332
- </FieldRow>
333
- );
334
- }
335
-
336
- export function ColorField({
337
- label,
338
- value,
339
- onChange,
340
- }: {
341
- label: ReactNode;
342
- value: string | null | undefined;
343
- onChange: (value: string) => void;
344
- }) {
345
- const hex = normalizeHex(value);
346
- const alpha = hex.length === 9 ? hex.slice(7) : '';
347
- const rgb = hex.slice(0, 7);
348
- return (
349
- <FieldRow label={label}>
350
- <input
351
- className={styles.colorInput}
352
- type="color"
353
- value={rgb}
354
- onChange={(event) => onChange(event.target.value + alpha)}
355
- />
356
- </FieldRow>
357
- );
358
- }
359
-
360
- function normalizeHex(value: string | null | undefined): string {
361
- const raw = (value ?? '').trim();
362
- if (/^#[0-9a-fA-F]{3}$/.test(raw)) {
363
- return '#' + raw.slice(1).replace(/./g, (c) => c + c);
364
- }
365
- if (/^#[0-9a-fA-F]{6}([0-9a-fA-F]{2})?$/.test(raw)) return raw;
366
- return '#000000';
367
- }
368
-
369
- export function isHexColor(value: unknown): value is string {
370
- return (
371
- typeof value === 'string' && /^#[0-9a-fA-F]{3}([0-9a-fA-F]{3}([0-9a-fA-F]{2})?)?$/.test(value)
372
- );
373
- }
374
-
375
- export type SheetSnap = 'high' | 'low' | 'hidden';
376
-
377
- export type SheetTransition = 'up' | 'down' | 'tap';
378
-
379
- export interface MobileSheetController {
380
- rootProps: { className: string; 'data-sheet-snap': SheetSnap };
381
- grabProps: {
382
- className: string;
383
- onPointerDown: (event: PointerEvent<HTMLDivElement>) => void;
384
- onPointerMove: (event: PointerEvent<HTMLDivElement>) => void;
385
- onPointerUp: (event: PointerEvent<HTMLDivElement>) => void;
386
- onPointerCancel: (event: PointerEvent<HTMLDivElement>) => void;
387
- };
388
- }
389
-
390
- export function useMobileSheet({
391
- snap,
392
- baseClassName,
393
- onTransition,
394
- }: {
395
- snap: SheetSnap;
396
- baseClassName: string;
397
- onTransition: (direction: SheetTransition) => void;
398
- }): MobileSheetController {
399
- const startY = useRef(0);
400
- const lastDy = useRef(0);
401
- const dragging = useRef(false);
402
-
403
- function onPointerDown(event: PointerEvent<HTMLDivElement>): void {
404
- startY.current = event.clientY;
405
- lastDy.current = 0;
406
- dragging.current = true;
407
- event.currentTarget.setPointerCapture(event.pointerId);
408
- }
409
-
410
- function onPointerMove(event: PointerEvent<HTMLDivElement>): void {
411
- if (!dragging.current) return;
412
- lastDy.current = event.clientY - startY.current;
413
- }
414
-
415
- function endDrag(): void {
416
- if (!dragging.current) return;
417
- dragging.current = false;
418
- const dy = lastDy.current;
419
- lastDy.current = 0;
420
- if (Math.abs(dy) < 6) onTransition('tap');
421
- else if (dy > 30) onTransition('down');
422
- else if (dy < -30) onTransition('up');
423
- }
424
-
425
- return {
426
- rootProps: {
427
- className: baseClassName,
428
- 'data-sheet-snap': snap,
429
- },
430
- grabProps: {
431
- className: cx(styles.sheetGrab, styles.mobileOnly),
432
- onPointerDown,
433
- onPointerMove,
434
- onPointerUp: endDrag,
435
- onPointerCancel: endDrag,
436
- },
437
- };
438
- }
439
-
440
- export function SheetGrabHandle({ label, hint }: { label: ReactNode; hint?: ReactNode }) {
441
- return (
442
- <>
443
- <div className={styles.sheetGrabBar} />
444
- <div className={styles.sheetGrabLabelRow}>
445
- <span className={styles.sheetGrabLabel}>{label}</span>
446
- {hint ? <span className={styles.sheetGrabHint}>{hint}</span> : null}
447
- </div>
448
- </>
449
- );
450
- }
451
-
452
- type SelectOption = string | { value: string; label: string };
453
-
454
- export function SelectField({
455
- label,
456
- value,
457
- onChange,
458
- options,
459
- }: {
460
- label: ReactNode;
461
- value: string | null | undefined;
462
- onChange: (value: string) => void;
463
- options: SelectOption[];
464
- }) {
465
- return (
466
- <FieldRow label={label}>
467
- <select
468
- className={styles.select}
469
- value={value ?? ''}
470
- onChange={(event) => onChange(event.target.value)}>
471
- {options.map((option) => {
472
- const value = typeof option === 'string' ? option : option.value;
473
- const label = typeof option === 'string' ? option : option.label;
474
- return (
475
- <option key={value} value={value}>
476
- {label}
477
- </option>
478
- );
479
- })}
480
- </select>
481
- </FieldRow>
482
- );
483
- }
@@ -1,46 +0,0 @@
1
- import js from '@eslint/js';
2
- import tseslint from 'typescript-eslint';
3
- import reactHooks from 'eslint-plugin-react-hooks';
4
-
5
- export default tseslint.config(
6
- {
7
- ignores: ['node_modules/**', 'dist/**', '.castle/**', '*.config.js'],
8
- },
9
- js.configs.recommended,
10
- ...tseslint.configs.recommendedTypeChecked,
11
- {
12
- files: ['engine/**/*.{ts,tsx}', 'editors/**/*.{ts,tsx}', 'behaviors/**/*.{ts,tsx}', '*.ts', '*.tsx'],
13
- languageOptions: {
14
- parserOptions: {
15
- project: './tsconfig.json',
16
- tsconfigRootDir: import.meta.dirname,
17
- ecmaFeatures: { jsx: true },
18
- },
19
- },
20
- plugins: {
21
- 'react-hooks': reactHooks,
22
- },
23
- rules: {
24
- // disable noisy rules per spec
25
- '@typescript-eslint/no-unsafe-assignment': 'off',
26
- '@typescript-eslint/no-unsafe-member-access': 'off',
27
- '@typescript-eslint/no-unsafe-call': 'off',
28
- '@typescript-eslint/no-unsafe-return': 'off',
29
- '@typescript-eslint/no-unsafe-argument': 'off',
30
- '@typescript-eslint/explicit-function-return-type': 'off',
31
- '@typescript-eslint/explicit-module-boundary-types': 'off',
32
-
33
- // enabled rules per spec
34
- complexity: ['error', 70],
35
- 'max-lines-per-function': ['error', 200],
36
- '@typescript-eslint/no-explicit-any': 'error',
37
- '@typescript-eslint/no-unused-vars': 'error',
38
- '@typescript-eslint/no-floating-promises': 'error',
39
- 'prefer-const': 'error',
40
- 'no-var': 'error',
41
- eqeqeq: 'warn',
42
- 'react-hooks/rules-of-hooks': 'error',
43
- 'react-hooks/exhaustive-deps': 'warn',
44
- },
45
- },
46
- );
@@ -1,11 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
5
- <title>Castle Basic 2D Kit</title>
6
- </head>
7
- <body>
8
- <div id="root"></div>
9
- <script type="module" src="/main.tsx"></script>
10
- </body>
11
- </html>
@@ -1,14 +0,0 @@
1
- import React from 'react';
2
- import { createRoot } from 'react-dom/client';
3
- import { isEdit, setup } from 'castle-web-sdk';
4
- import { App } from './editors/App';
5
- import { PlayOnly } from './editors/PlayOnly';
6
-
7
- document.body.dataset.castleScreenshotTarget = 'viewport';
8
-
9
- setup();
10
-
11
- const root = document.getElementById('root');
12
- if (!root) throw new Error('Missing root element');
13
-
14
- createRoot(root).render(isEdit() ? <App /> : <PlayOnly />);