@crowdedkingdoms/crowdyjs 12.0.0 → 12.2.0
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/MIGRATION.md +45 -0
- package/README.md +70 -1
- package/dist/crowdy-studio/agent-dom-shell.d.ts +29 -1
- package/dist/crowdy-studio/agent-dom-shell.d.ts.map +1 -1
- package/dist/crowdy-studio/agent-dom-shell.js +108 -44
- package/dist/crowdy-studio/dom-shell.d.ts +46 -3
- package/dist/crowdy-studio/dom-shell.d.ts.map +1 -1
- package/dist/crowdy-studio/dom-shell.js +551 -125
- package/dist/crowdy-studio/embed/dock.d.ts +56 -0
- package/dist/crowdy-studio/embed/dock.d.ts.map +1 -0
- package/dist/crowdy-studio/embed/dock.js +231 -0
- package/dist/crowdy-studio/embed/embed-styles.d.ts +12 -0
- package/dist/crowdy-studio/embed/embed-styles.d.ts.map +1 -0
- package/dist/crowdy-studio/embed/embed-styles.js +549 -0
- package/dist/crowdy-studio/embed/hud-layer.d.ts +40 -0
- package/dist/crowdy-studio/embed/hud-layer.d.ts.map +1 -0
- package/dist/crowdy-studio/embed/hud-layer.js +100 -0
- package/dist/crowdy-studio/embed/index.d.ts +5 -0
- package/dist/crowdy-studio/embed/index.d.ts.map +1 -0
- package/dist/crowdy-studio/embed/index.js +4 -0
- package/dist/crowdy-studio/embed/panel.d.ts +162 -0
- package/dist/crowdy-studio/embed/panel.d.ts.map +1 -0
- package/dist/crowdy-studio/embed/panel.js +642 -0
- package/dist/crowdy-studio/index.d.ts +3 -0
- package/dist/crowdy-studio/index.d.ts.map +1 -1
- package/dist/crowdy-studio/index.js +3 -0
- package/dist/crowdy-studio/layout.d.ts +50 -0
- package/dist/crowdy-studio/layout.d.ts.map +1 -0
- package/dist/crowdy-studio/layout.js +155 -0
- package/dist/crowdy-studio/mount.d.ts.map +1 -1
- package/dist/crowdy-studio/mount.js +3 -1
- package/dist/crowdy-studio/splitter.d.ts +33 -0
- package/dist/crowdy-studio/splitter.d.ts.map +1 -0
- package/dist/crowdy-studio/splitter.js +133 -0
- package/dist/crowdy-studio/styles.d.ts +1 -1
- package/dist/crowdy-studio/styles.d.ts.map +1 -1
- package/dist/crowdy-studio/styles.js +128 -13
- package/dist/domains/gameModel.d.ts +68 -1
- package/dist/domains/gameModel.d.ts.map +1 -1
- package/dist/domains/gameModel.js +88 -1
- package/dist/generated/graphql.d.ts +132 -15
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +12 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/kit/npcs.d.ts.map +1 -1
- package/dist/kit/social.d.ts.map +1 -1
- package/dist/player-host/control-banner.d.ts +40 -0
- package/dist/player-host/control-banner.d.ts.map +1 -0
- package/dist/player-host/control-banner.js +252 -0
- package/dist/player-host/control-gate.d.ts +77 -0
- package/dist/player-host/control-gate.d.ts.map +1 -0
- package/dist/player-host/control-gate.js +197 -0
- package/dist/player-host/index.d.ts +2 -0
- package/dist/player-host/index.d.ts.map +1 -1
- package/dist/player-host/index.js +2 -0
- package/package.json +6 -1
|
@@ -0,0 +1,642 @@
|
|
|
1
|
+
import { mountCrowdyStudio, } from '../mount.js';
|
|
2
|
+
import { CROWDY_STUDIO_EMBED_NARROW_BREAKPOINT_PX, CrowdyStudioEmbedDock, addBodyClass, removeBodyClass, } from './dock.js';
|
|
3
|
+
import { ensureCrowdyStudioEmbedStyles } from './embed-styles.js';
|
|
4
|
+
const TITLE_ID = 'ck-crowdy-studio-embed-title';
|
|
5
|
+
const DESCRIPTION_ID = 'ck-crowdy-studio-embed-description';
|
|
6
|
+
const SHELL_ID = 'ck-crowdy-studio-embed-shell';
|
|
7
|
+
const DRAWER_ID = 'ck-crowdy-studio-embed-drawer';
|
|
8
|
+
/**
|
|
9
|
+
* Responsive game shell around CrowdyJS's project-first Crowdy Studio.
|
|
10
|
+
* Desktop uses a resizable right dock; narrow screens use a focus-trapped
|
|
11
|
+
* modal. Construct once per game and `toggle(context)` per open.
|
|
12
|
+
*/
|
|
13
|
+
export class CrowdyStudioEmbed {
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.options = options;
|
|
16
|
+
this.root = null;
|
|
17
|
+
this.mountElement = null;
|
|
18
|
+
this.statusElement = null;
|
|
19
|
+
this.drawerElement = null;
|
|
20
|
+
this.drawerButton = null;
|
|
21
|
+
this.handle = null;
|
|
22
|
+
this.context = null;
|
|
23
|
+
this.previousFocus = null;
|
|
24
|
+
this.restoreGameplayInput = null;
|
|
25
|
+
this.unmountHudPreview = null;
|
|
26
|
+
this.mountGeneration = 0;
|
|
27
|
+
this.displayMode = null;
|
|
28
|
+
this.viewportResize = () => {
|
|
29
|
+
this.updateDisplayMode();
|
|
30
|
+
};
|
|
31
|
+
this.keyDown = (event) => {
|
|
32
|
+
this.handleDialogKey(event);
|
|
33
|
+
};
|
|
34
|
+
this.documentKeyDown = (event) => {
|
|
35
|
+
if (!this.root || this.root.contains(event.target))
|
|
36
|
+
return;
|
|
37
|
+
this.handleDialogKey(event);
|
|
38
|
+
};
|
|
39
|
+
this.captureEscape = (event) => {
|
|
40
|
+
if (!this.root || !this.modal || event.code !== 'Escape' || event.repeat) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
event.preventDefault();
|
|
44
|
+
event.stopPropagation();
|
|
45
|
+
this.close();
|
|
46
|
+
};
|
|
47
|
+
this.stopKeyboardEvent = (event) => {
|
|
48
|
+
event.stopPropagation();
|
|
49
|
+
};
|
|
50
|
+
this.documentKeyUp = (event) => {
|
|
51
|
+
if (this.root && !this.root.contains(event.target)) {
|
|
52
|
+
event.stopPropagation();
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
this.keepFocusInside = (event) => {
|
|
56
|
+
if (!this.root || this.root.contains(event.target))
|
|
57
|
+
return;
|
|
58
|
+
const first = focusableElements(this.root)[0];
|
|
59
|
+
if (first)
|
|
60
|
+
first.focus();
|
|
61
|
+
else
|
|
62
|
+
this.root.focus();
|
|
63
|
+
};
|
|
64
|
+
this.dock = new CrowdyStudioEmbedDock((width) => {
|
|
65
|
+
this.applyDockWidth(width);
|
|
66
|
+
}, options.dockStorage === undefined ? undefined : options.dockStorage);
|
|
67
|
+
}
|
|
68
|
+
get open() {
|
|
69
|
+
return this.root !== null;
|
|
70
|
+
}
|
|
71
|
+
get modal() {
|
|
72
|
+
return this.displayMode === 'fullscreen';
|
|
73
|
+
}
|
|
74
|
+
get mode() {
|
|
75
|
+
return this.displayMode;
|
|
76
|
+
}
|
|
77
|
+
toggle(context) {
|
|
78
|
+
if (this.root)
|
|
79
|
+
this.close();
|
|
80
|
+
else
|
|
81
|
+
this.show(context);
|
|
82
|
+
}
|
|
83
|
+
destroy() {
|
|
84
|
+
this.close();
|
|
85
|
+
this.dock.destroy();
|
|
86
|
+
}
|
|
87
|
+
close() {
|
|
88
|
+
if (!this.root)
|
|
89
|
+
return;
|
|
90
|
+
const context = this.context;
|
|
91
|
+
this.mountGeneration++;
|
|
92
|
+
this.options.onAgentUnmounted?.();
|
|
93
|
+
this.handle?.destroy();
|
|
94
|
+
this.handle = null;
|
|
95
|
+
this.unmountHudPreview?.();
|
|
96
|
+
this.unmountHudPreview = null;
|
|
97
|
+
this.leaveModalMode();
|
|
98
|
+
this.dock.deactivate();
|
|
99
|
+
window.removeEventListener('resize', this.viewportResize);
|
|
100
|
+
this.root.removeEventListener('keydown', this.keyDown);
|
|
101
|
+
this.root.removeEventListener('keyup', this.stopKeyboardEvent);
|
|
102
|
+
this.root.removeEventListener('keypress', this.stopKeyboardEvent);
|
|
103
|
+
this.root.remove();
|
|
104
|
+
removeBodyClass('ck-crowdy-studio-embed-open', 'ck-crowdy-studio-embed-docked', 'ck-crowdy-studio-embed-fullscreen', 'ck-crowdy-studio-embed-resizing');
|
|
105
|
+
this.clearDockWidth();
|
|
106
|
+
this.root = null;
|
|
107
|
+
this.mountElement = null;
|
|
108
|
+
this.statusElement = null;
|
|
109
|
+
this.drawerElement = null;
|
|
110
|
+
this.drawerButton = null;
|
|
111
|
+
this.context = null;
|
|
112
|
+
this.displayMode = null;
|
|
113
|
+
if (context)
|
|
114
|
+
this.options.onLayoutChange?.();
|
|
115
|
+
const restore = this.previousFocus;
|
|
116
|
+
this.previousFocus = null;
|
|
117
|
+
if (restore?.isConnected)
|
|
118
|
+
restore.focus();
|
|
119
|
+
this.options.onClosed?.();
|
|
120
|
+
}
|
|
121
|
+
show(context) {
|
|
122
|
+
ensureCrowdyStudioEmbedStyles();
|
|
123
|
+
this.context = context;
|
|
124
|
+
this.previousFocus =
|
|
125
|
+
document.activeElement instanceof HTMLElement
|
|
126
|
+
? document.activeElement
|
|
127
|
+
: null;
|
|
128
|
+
const root = document.createElement('div');
|
|
129
|
+
root.className = 'ck-crowdy-studio-embed';
|
|
130
|
+
root.setAttribute('aria-labelledby', TITLE_ID);
|
|
131
|
+
root.setAttribute('aria-describedby', DESCRIPTION_ID);
|
|
132
|
+
root.tabIndex = -1;
|
|
133
|
+
root.addEventListener('keydown', this.keyDown);
|
|
134
|
+
root.addEventListener('keyup', this.stopKeyboardEvent);
|
|
135
|
+
root.addEventListener('keypress', this.stopKeyboardEvent);
|
|
136
|
+
root.addEventListener('mousedown', stopEventPropagation);
|
|
137
|
+
root.addEventListener('pointerdown', stopEventPropagation);
|
|
138
|
+
root.addEventListener('pointerup', stopEventPropagation);
|
|
139
|
+
root.addEventListener('click', stopEventPropagation);
|
|
140
|
+
root.addEventListener('dblclick', stopEventPropagation);
|
|
141
|
+
root.addEventListener('wheel', stopEventPropagation);
|
|
142
|
+
root.addEventListener('contextmenu', stopEventPropagation);
|
|
143
|
+
const shell = document.createElement('section');
|
|
144
|
+
shell.className = 'ck-crowdy-studio-embed-shell';
|
|
145
|
+
shell.id = SHELL_ID;
|
|
146
|
+
const header = this.header(context);
|
|
147
|
+
const workspace = document.createElement('div');
|
|
148
|
+
workspace.className = 'ck-crowdy-studio-embed-workspace';
|
|
149
|
+
const main = document.createElement('main');
|
|
150
|
+
main.className = 'ck-crowdy-studio-embed-main';
|
|
151
|
+
const status = document.createElement('div');
|
|
152
|
+
status.className = 'ck-crowdy-studio-embed-status is-loading';
|
|
153
|
+
status.setAttribute('role', 'status');
|
|
154
|
+
status.setAttribute('aria-live', 'polite');
|
|
155
|
+
const mountElement = document.createElement('div');
|
|
156
|
+
mountElement.className = 'ck-crowdy-studio-embed-mount';
|
|
157
|
+
mountElement.setAttribute('data-ck-crowdy-studio-embed-root', '');
|
|
158
|
+
main.append(status, mountElement);
|
|
159
|
+
const drawer = this.drawer(context);
|
|
160
|
+
workspace.append(main, drawer);
|
|
161
|
+
shell.append(header, workspace);
|
|
162
|
+
this.dock.separator.setAttribute('aria-controls', SHELL_ID);
|
|
163
|
+
root.append(this.dock.separator, shell);
|
|
164
|
+
document.body.appendChild(root);
|
|
165
|
+
addBodyClass('ck-crowdy-studio-embed-open');
|
|
166
|
+
this.root = root;
|
|
167
|
+
this.mountElement = mountElement;
|
|
168
|
+
this.statusElement = status;
|
|
169
|
+
this.drawerElement = drawer;
|
|
170
|
+
window.addEventListener('resize', this.viewportResize);
|
|
171
|
+
this.updateDisplayMode();
|
|
172
|
+
header
|
|
173
|
+
.querySelector('.ck-crowdy-studio-embed-close')
|
|
174
|
+
?.focus();
|
|
175
|
+
void this.mountStudio();
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Single compact header row: title, context pill, on-demand Context drawer
|
|
179
|
+
* toggle, Close. Project context and permission details live in the drawer
|
|
180
|
+
* so every workflow starts with maximum studio space.
|
|
181
|
+
*/
|
|
182
|
+
header(context) {
|
|
183
|
+
const header = document.createElement('header');
|
|
184
|
+
header.className = 'ck-crowdy-studio-embed-header';
|
|
185
|
+
const title = document.createElement('h1');
|
|
186
|
+
title.id = TITLE_ID;
|
|
187
|
+
title.textContent = this.options.title ?? 'Crowdy Studio';
|
|
188
|
+
const description = document.createElement('p');
|
|
189
|
+
description.id = DESCRIPTION_ID;
|
|
190
|
+
description.className = 'ck-crowdy-studio-embed-visually-hidden';
|
|
191
|
+
description.textContent = this.accessibleDescription(context.gridId);
|
|
192
|
+
const pill = contextPill('Grid', context.gridId);
|
|
193
|
+
const contextButton = document.createElement('button');
|
|
194
|
+
contextButton.type = 'button';
|
|
195
|
+
contextButton.className = 'ck-crowdy-studio-embed-context-toggle';
|
|
196
|
+
contextButton.textContent = 'Context';
|
|
197
|
+
contextButton.title = context.hud
|
|
198
|
+
? 'Grid bounds, permissions, and HUD preview'
|
|
199
|
+
: 'Grid bounds and permissions';
|
|
200
|
+
contextButton.setAttribute('aria-expanded', 'false');
|
|
201
|
+
contextButton.setAttribute('aria-controls', DRAWER_ID);
|
|
202
|
+
contextButton.addEventListener('click', () => this.toggleDrawer());
|
|
203
|
+
this.drawerButton = contextButton;
|
|
204
|
+
const close = document.createElement('button');
|
|
205
|
+
close.type = 'button';
|
|
206
|
+
close.className = 'ck-crowdy-studio-embed-close';
|
|
207
|
+
close.setAttribute('aria-label', 'Close Crowdy Studio');
|
|
208
|
+
close.title = this.closeKeyLabel()
|
|
209
|
+
? `Close Crowdy Studio (Escape or ${this.closeKeyLabel()})`
|
|
210
|
+
: 'Close Crowdy Studio (Escape)';
|
|
211
|
+
close.textContent = 'Close';
|
|
212
|
+
close.addEventListener('click', () => this.close());
|
|
213
|
+
header.append(title, description, pill, contextButton, close);
|
|
214
|
+
return header;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* On-demand context drawer: grid context, effective permissions, and (when
|
|
218
|
+
* a HUD sink is supplied) a lazily mounted HUD preview. Hidden by default;
|
|
219
|
+
* toggled from the header.
|
|
220
|
+
*/
|
|
221
|
+
drawer(context) {
|
|
222
|
+
const aside = document.createElement('aside');
|
|
223
|
+
aside.className = 'ck-crowdy-studio-embed-drawer';
|
|
224
|
+
aside.id = DRAWER_ID;
|
|
225
|
+
aside.setAttribute('aria-label', 'Crowdy Studio context');
|
|
226
|
+
aside.hidden = true;
|
|
227
|
+
const contextTitle = document.createElement('h2');
|
|
228
|
+
contextTitle.textContent = 'Project context';
|
|
229
|
+
const grid = document.createElement('dl');
|
|
230
|
+
grid.className = 'ck-crowdy-studio-embed-grid-context';
|
|
231
|
+
appendDefinition(grid, 'Grid', context.gridId);
|
|
232
|
+
if (context.grid) {
|
|
233
|
+
appendDefinition(grid, 'Low chunk', formatChunk(context.grid.low));
|
|
234
|
+
appendDefinition(grid, 'High chunk', formatChunk(context.grid.high));
|
|
235
|
+
}
|
|
236
|
+
const permissionsTitle = document.createElement('h2');
|
|
237
|
+
permissionsTitle.textContent = 'Effective permissions';
|
|
238
|
+
const summary = document.createElement('p');
|
|
239
|
+
summary.textContent = permissionSummary(context.targetPermissions);
|
|
240
|
+
const permissions = document.createElement('div');
|
|
241
|
+
permissions.className = 'ck-crowdy-studio-embed-permissions';
|
|
242
|
+
permissions.append(permissionCard('SERVER', context.targetPermissions.SERVER), permissionCard('CLIENT', context.targetPermissions.CLIENT));
|
|
243
|
+
aside.append(contextTitle, grid, permissionsTitle, summary, permissions);
|
|
244
|
+
if (context.permissionsNote) {
|
|
245
|
+
const source = document.createElement('p');
|
|
246
|
+
source.className = 'ck-crowdy-studio-embed-permission-source';
|
|
247
|
+
source.textContent = context.permissionsNote;
|
|
248
|
+
aside.append(source);
|
|
249
|
+
}
|
|
250
|
+
if (context.hud) {
|
|
251
|
+
const hud = context.hud;
|
|
252
|
+
const previewDisclosure = document.createElement('details');
|
|
253
|
+
previewDisclosure.className =
|
|
254
|
+
'ck-crowdy-studio-embed-hud-preview-disclosure';
|
|
255
|
+
const previewSummary = document.createElement('summary');
|
|
256
|
+
previewSummary.textContent = 'HUD preview';
|
|
257
|
+
const preview = document.createElement('div');
|
|
258
|
+
preview.className = 'ck-crowdy-studio-embed-hud-preview';
|
|
259
|
+
preview.setAttribute('aria-live', 'polite');
|
|
260
|
+
previewDisclosure.append(previewSummary, preview);
|
|
261
|
+
previewDisclosure.addEventListener('toggle', () => {
|
|
262
|
+
if (previewDisclosure.open) {
|
|
263
|
+
this.unmountHudPreview ?? (this.unmountHudPreview = hud.mountPreview(preview, this.presentationSource(context.gridId)));
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
this.unmountHudPreview?.();
|
|
267
|
+
this.unmountHudPreview = null;
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
aside.append(previewDisclosure);
|
|
271
|
+
}
|
|
272
|
+
const hint = document.createElement('p');
|
|
273
|
+
hint.className = 'ck-crowdy-studio-embed-shortcuts';
|
|
274
|
+
hint.textContent = this.shortcutHint();
|
|
275
|
+
aside.append(hint);
|
|
276
|
+
return aside;
|
|
277
|
+
}
|
|
278
|
+
toggleDrawer(force) {
|
|
279
|
+
const drawer = this.drawerElement;
|
|
280
|
+
if (!drawer)
|
|
281
|
+
return;
|
|
282
|
+
const open = force ?? drawer.hidden;
|
|
283
|
+
drawer.hidden = !open;
|
|
284
|
+
this.drawerButton?.setAttribute('aria-expanded', String(open));
|
|
285
|
+
if (!open) {
|
|
286
|
+
const disclosure = drawer.querySelector('.ck-crowdy-studio-embed-hud-preview-disclosure');
|
|
287
|
+
if (disclosure)
|
|
288
|
+
disclosure.open = false;
|
|
289
|
+
this.unmountHudPreview?.();
|
|
290
|
+
this.unmountHudPreview = null;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
async mountStudio() {
|
|
294
|
+
const context = this.context;
|
|
295
|
+
const mountElement = this.mountElement;
|
|
296
|
+
const status = this.statusElement;
|
|
297
|
+
if (!context || !mountElement || !status)
|
|
298
|
+
return;
|
|
299
|
+
const generation = ++this.mountGeneration;
|
|
300
|
+
this.options.onAgentUnmounted?.();
|
|
301
|
+
this.handle?.destroy();
|
|
302
|
+
this.handle = null;
|
|
303
|
+
mountElement.replaceChildren();
|
|
304
|
+
status.replaceChildren();
|
|
305
|
+
status.className = 'ck-crowdy-studio-embed-status is-loading';
|
|
306
|
+
const spinner = document.createElement('span');
|
|
307
|
+
spinner.className = 'ck-crowdy-studio-embed-spinner';
|
|
308
|
+
spinner.setAttribute('aria-hidden', 'true');
|
|
309
|
+
const loading = document.createElement('span');
|
|
310
|
+
loading.textContent = 'Opening your projects…';
|
|
311
|
+
status.append(spinner, loading);
|
|
312
|
+
try {
|
|
313
|
+
const handle = await this.mountSdkStudio(mountElement, context);
|
|
314
|
+
if (generation !== this.mountGeneration || this.root === null) {
|
|
315
|
+
handle.destroy();
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
this.handle = handle;
|
|
319
|
+
this.options.onAgentMounted?.(handle);
|
|
320
|
+
status.className = 'ck-crowdy-studio-embed-status hidden';
|
|
321
|
+
status.replaceChildren();
|
|
322
|
+
this.root.dataset.crowdyStudioApi = handle.api;
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
if (generation !== this.mountGeneration || this.root === null)
|
|
326
|
+
return;
|
|
327
|
+
this.options.onAgentUnavailable?.(errorMessage(error));
|
|
328
|
+
status.className = 'ck-crowdy-studio-embed-status is-error';
|
|
329
|
+
status.replaceChildren();
|
|
330
|
+
const title = document.createElement('strong');
|
|
331
|
+
title.textContent = 'Crowdy Studio could not open';
|
|
332
|
+
const message = document.createElement('span');
|
|
333
|
+
message.textContent =
|
|
334
|
+
`${errorMessage(error)}. Your grid access is unchanged and no ` +
|
|
335
|
+
'project data was removed.';
|
|
336
|
+
const retry = document.createElement('button');
|
|
337
|
+
retry.type = 'button';
|
|
338
|
+
retry.className = 'ck-crowdy-studio-embed-retry';
|
|
339
|
+
retry.textContent = 'Retry';
|
|
340
|
+
retry.addEventListener('click', () => void this.mountStudio());
|
|
341
|
+
status.append(title, message, retry);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
/** Assemble mount options from the game client + per-open context. */
|
|
345
|
+
async mountSdkStudio(element, context) {
|
|
346
|
+
const { client } = this.options;
|
|
347
|
+
const appId = this.currentAppId();
|
|
348
|
+
element.className += ' ck-crowdy-studio-embed-sdk-host';
|
|
349
|
+
const hud = context.hud;
|
|
350
|
+
const onPresentation = context.onPresentation ??
|
|
351
|
+
(hud
|
|
352
|
+
? (presentation) => {
|
|
353
|
+
if (presentation.channel !== 'hud')
|
|
354
|
+
return;
|
|
355
|
+
hud.set({
|
|
356
|
+
source: this.presentationSource(context.gridId),
|
|
357
|
+
label: 'Crowdy Studio preview',
|
|
358
|
+
payload: presentation.payload,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
: undefined);
|
|
362
|
+
const handle = await mountCrowdyStudio(element, {
|
|
363
|
+
projectProvider: client.crowdyStudio,
|
|
364
|
+
playerCompute: client.playerCompute,
|
|
365
|
+
playerWallet: client.playerWallet,
|
|
366
|
+
appId,
|
|
367
|
+
gridId: context.gridId,
|
|
368
|
+
grid: context.grid,
|
|
369
|
+
workerUrl: context.workerUrl,
|
|
370
|
+
targetPermissions: context.targetPermissions,
|
|
371
|
+
onHostCall: context.onHostCall,
|
|
372
|
+
onPresentation,
|
|
373
|
+
...(client.crowdyStudioAgent && context.playerHost
|
|
374
|
+
? {
|
|
375
|
+
agent: {
|
|
376
|
+
transport: client.crowdyStudioAgent,
|
|
377
|
+
createSession: {
|
|
378
|
+
appId,
|
|
379
|
+
gridId: context.gridId,
|
|
380
|
+
mode: this.options.agentSession?.mode ?? 'ASK',
|
|
381
|
+
providerDataConsent: this.options.agentSession?.providerDataConsent ?? false,
|
|
382
|
+
idempotencyKey: this.agentIdempotencyKey(),
|
|
383
|
+
},
|
|
384
|
+
playerHost: context.playerHost,
|
|
385
|
+
controlGate: this.options.controlGate,
|
|
386
|
+
onLocalPreempt: this.options.onLocalPreempt,
|
|
387
|
+
},
|
|
388
|
+
}
|
|
389
|
+
: {}),
|
|
390
|
+
...this.options.runtimeOverrides,
|
|
391
|
+
});
|
|
392
|
+
element.dataset.crowdyStudioApi = 'project-first';
|
|
393
|
+
let destroyed = false;
|
|
394
|
+
return {
|
|
395
|
+
api: 'crowdy-studio',
|
|
396
|
+
controller: handle.controller,
|
|
397
|
+
agent: handle.agent,
|
|
398
|
+
controlLeaseManager: handle.controlLeaseManager,
|
|
399
|
+
destroy: () => {
|
|
400
|
+
if (destroyed)
|
|
401
|
+
return;
|
|
402
|
+
destroyed = true;
|
|
403
|
+
handle.destroy();
|
|
404
|
+
},
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
currentAppId() {
|
|
408
|
+
const { appId } = this.options;
|
|
409
|
+
return typeof appId === 'function' ? appId() : appId;
|
|
410
|
+
}
|
|
411
|
+
agentIdempotencyKey() {
|
|
412
|
+
const prefix = this.options.agentSession?.idempotencyKeyPrefix ?? 'ck-agent-session:';
|
|
413
|
+
const random = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'
|
|
414
|
+
? crypto.randomUUID()
|
|
415
|
+
: `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
416
|
+
return `${prefix}${random}`;
|
|
417
|
+
}
|
|
418
|
+
presentationSource(gridId) {
|
|
419
|
+
return `crowdy-studio:${gridId}`;
|
|
420
|
+
}
|
|
421
|
+
accessibleDescription(gridId) {
|
|
422
|
+
const game = this.options.gameName ?? 'This game';
|
|
423
|
+
return (`${game} live coding studio for grid ${gridId}. ` +
|
|
424
|
+
'Edits autosave; Test draft or Deploy live applies them. ' +
|
|
425
|
+
`${this.shortcutHint()}`);
|
|
426
|
+
}
|
|
427
|
+
shortcutHint() {
|
|
428
|
+
const key = this.closeKeyLabel();
|
|
429
|
+
return key
|
|
430
|
+
? `Escape closes. ${key} closes from chrome; ${key} still types in editors.`
|
|
431
|
+
: 'Escape closes.';
|
|
432
|
+
}
|
|
433
|
+
closeKeyLabel() {
|
|
434
|
+
const code = this.closeKeyCode();
|
|
435
|
+
if (!code)
|
|
436
|
+
return null;
|
|
437
|
+
return code.startsWith('Key') ? code.slice(3) : code;
|
|
438
|
+
}
|
|
439
|
+
closeKeyCode() {
|
|
440
|
+
return this.options.closeKeyCode === undefined
|
|
441
|
+
? 'KeyM'
|
|
442
|
+
: this.options.closeKeyCode;
|
|
443
|
+
}
|
|
444
|
+
updateDisplayMode() {
|
|
445
|
+
if (!this.root)
|
|
446
|
+
return;
|
|
447
|
+
const next = window.innerWidth < CROWDY_STUDIO_EMBED_NARROW_BREAKPOINT_PX
|
|
448
|
+
? 'fullscreen'
|
|
449
|
+
: 'docked';
|
|
450
|
+
if (next === this.displayMode) {
|
|
451
|
+
if (next === 'docked')
|
|
452
|
+
this.dock.refresh();
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
const previous = this.displayMode;
|
|
456
|
+
this.displayMode = next;
|
|
457
|
+
this.root.dataset.mode = next;
|
|
458
|
+
this.root.className = `ck-crowdy-studio-embed ${next === 'docked' ? 'is-docked' : 'is-fullscreen'}`;
|
|
459
|
+
if (next === 'fullscreen') {
|
|
460
|
+
this.dock.deactivate();
|
|
461
|
+
removeBodyClass('ck-crowdy-studio-embed-docked');
|
|
462
|
+
addBodyClass('ck-crowdy-studio-embed-fullscreen');
|
|
463
|
+
this.clearDockWidth();
|
|
464
|
+
this.root.setAttribute('role', 'dialog');
|
|
465
|
+
this.root.setAttribute('aria-modal', 'true');
|
|
466
|
+
this.enterModalMode();
|
|
467
|
+
this.options.onLayoutChange?.();
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
this.leaveModalMode();
|
|
471
|
+
removeBodyClass('ck-crowdy-studio-embed-fullscreen');
|
|
472
|
+
addBodyClass('ck-crowdy-studio-embed-docked');
|
|
473
|
+
this.root.setAttribute('role', 'complementary');
|
|
474
|
+
this.root.removeAttribute('aria-modal');
|
|
475
|
+
if (previous === null && document.pointerLockElement) {
|
|
476
|
+
void document.exitPointerLock();
|
|
477
|
+
}
|
|
478
|
+
this.dock.activate();
|
|
479
|
+
}
|
|
480
|
+
enterModalMode() {
|
|
481
|
+
if (!this.root || !this.context || this.restoreGameplayInput)
|
|
482
|
+
return;
|
|
483
|
+
this.restoreGameplayInput =
|
|
484
|
+
this.options.suppressGameplayInput?.() ?? (() => { });
|
|
485
|
+
if (document.pointerLockElement)
|
|
486
|
+
void document.exitPointerLock();
|
|
487
|
+
document.addEventListener('keydown', this.documentKeyDown);
|
|
488
|
+
document.addEventListener('keydown', this.captureEscape, true);
|
|
489
|
+
document.addEventListener('keyup', this.documentKeyUp);
|
|
490
|
+
document.addEventListener('focusin', this.keepFocusInside);
|
|
491
|
+
if (!this.root.contains(document.activeElement)) {
|
|
492
|
+
this.root
|
|
493
|
+
.querySelector('.ck-crowdy-studio-embed-close')
|
|
494
|
+
?.focus();
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
leaveModalMode() {
|
|
498
|
+
document.removeEventListener('keydown', this.documentKeyDown);
|
|
499
|
+
document.removeEventListener('keydown', this.captureEscape, true);
|
|
500
|
+
document.removeEventListener('keyup', this.documentKeyUp);
|
|
501
|
+
document.removeEventListener('focusin', this.keepFocusInside);
|
|
502
|
+
this.restoreGameplayInput?.();
|
|
503
|
+
this.restoreGameplayInput = null;
|
|
504
|
+
}
|
|
505
|
+
applyDockWidth(width) {
|
|
506
|
+
if (!this.root || this.displayMode !== 'docked')
|
|
507
|
+
return;
|
|
508
|
+
document.body.style.setProperty('--ck-crowdy-studio-embed-dock-width', `${width}px`);
|
|
509
|
+
document.body.style.setProperty('--ck-game-right-inset', `${width}px`);
|
|
510
|
+
this.options.onLayoutChange?.();
|
|
511
|
+
}
|
|
512
|
+
clearDockWidth() {
|
|
513
|
+
document.body.style.removeProperty('--ck-crowdy-studio-embed-dock-width');
|
|
514
|
+
document.body.style.removeProperty('--ck-game-right-inset');
|
|
515
|
+
}
|
|
516
|
+
handleDialogKey(event) {
|
|
517
|
+
if (!this.root)
|
|
518
|
+
return;
|
|
519
|
+
if (event.code === 'Escape' && !event.repeat) {
|
|
520
|
+
event.preventDefault();
|
|
521
|
+
event.stopPropagation();
|
|
522
|
+
this.close();
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
const closeKey = this.closeKeyCode();
|
|
526
|
+
if (closeKey !== null &&
|
|
527
|
+
event.code === closeKey &&
|
|
528
|
+
!event.repeat &&
|
|
529
|
+
!event.altKey &&
|
|
530
|
+
!event.ctrlKey &&
|
|
531
|
+
!event.metaKey &&
|
|
532
|
+
!isTextEntryTarget(event.target)) {
|
|
533
|
+
event.preventDefault();
|
|
534
|
+
event.stopPropagation();
|
|
535
|
+
this.close();
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
538
|
+
if (event.code === 'Tab' && this.modal)
|
|
539
|
+
this.trapTab(event);
|
|
540
|
+
event.stopPropagation();
|
|
541
|
+
}
|
|
542
|
+
trapTab(event) {
|
|
543
|
+
if (!this.root)
|
|
544
|
+
return;
|
|
545
|
+
const focusable = focusableElements(this.root);
|
|
546
|
+
if (focusable.length === 0) {
|
|
547
|
+
event.preventDefault();
|
|
548
|
+
this.root.focus();
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
const active = document.activeElement;
|
|
552
|
+
const index = focusable.indexOf(active);
|
|
553
|
+
if (event.shiftKey && index <= 0) {
|
|
554
|
+
event.preventDefault();
|
|
555
|
+
focusable.at(-1)?.focus();
|
|
556
|
+
}
|
|
557
|
+
else if (!event.shiftKey &&
|
|
558
|
+
(index < 0 || index === focusable.length - 1)) {
|
|
559
|
+
event.preventDefault();
|
|
560
|
+
focusable[0]?.focus();
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
/** Convenience factory mirroring the class constructor. */
|
|
565
|
+
export function createCrowdyStudioEmbed(options) {
|
|
566
|
+
return new CrowdyStudioEmbed(options);
|
|
567
|
+
}
|
|
568
|
+
function contextPill(label, value) {
|
|
569
|
+
const pill = document.createElement('span');
|
|
570
|
+
pill.className = 'ck-crowdy-studio-embed-context-pill';
|
|
571
|
+
const key = document.createElement('small');
|
|
572
|
+
key.textContent = label;
|
|
573
|
+
const text = document.createElement('strong');
|
|
574
|
+
text.textContent = value;
|
|
575
|
+
pill.append(key, text);
|
|
576
|
+
return pill;
|
|
577
|
+
}
|
|
578
|
+
function appendDefinition(list, label, value) {
|
|
579
|
+
const term = document.createElement('dt');
|
|
580
|
+
term.textContent = label;
|
|
581
|
+
const description = document.createElement('dd');
|
|
582
|
+
description.textContent = value;
|
|
583
|
+
list.append(term, description);
|
|
584
|
+
}
|
|
585
|
+
function permissionCard(target, permissions) {
|
|
586
|
+
const card = document.createElement('section');
|
|
587
|
+
card.className =
|
|
588
|
+
!permissions.canWrite && !permissions.canRun
|
|
589
|
+
? 'ck-crowdy-studio-embed-permission is-disabled'
|
|
590
|
+
: 'ck-crowdy-studio-embed-permission';
|
|
591
|
+
const title = document.createElement('strong');
|
|
592
|
+
title.textContent = target;
|
|
593
|
+
const write = permissionBadge('Write', permissions.canWrite);
|
|
594
|
+
const run = permissionBadge('Run', permissions.canRun);
|
|
595
|
+
card.append(title, write, run);
|
|
596
|
+
return card;
|
|
597
|
+
}
|
|
598
|
+
function permissionBadge(label, allowed) {
|
|
599
|
+
const badge = document.createElement('span');
|
|
600
|
+
badge.className = allowed ? 'is-allowed' : 'is-denied';
|
|
601
|
+
badge.textContent = `${label} ${allowed ? 'allowed' : 'unavailable'}`;
|
|
602
|
+
return badge;
|
|
603
|
+
}
|
|
604
|
+
function permissionSummary(permissions) {
|
|
605
|
+
const target = (label, value) => {
|
|
606
|
+
const capabilities = [
|
|
607
|
+
value.canWrite ? 'write' : '',
|
|
608
|
+
value.canRun ? 'run' : '',
|
|
609
|
+
].filter(Boolean);
|
|
610
|
+
return `${label} ${capabilities.join('/') || 'unavailable'}`;
|
|
611
|
+
};
|
|
612
|
+
return [
|
|
613
|
+
target('SERVER', permissions.SERVER),
|
|
614
|
+
target('CLIENT', permissions.CLIENT),
|
|
615
|
+
].join(' · ');
|
|
616
|
+
}
|
|
617
|
+
function formatChunk(chunk) {
|
|
618
|
+
return `${chunk.x}, ${chunk.y}, ${chunk.z}`;
|
|
619
|
+
}
|
|
620
|
+
function focusableElements(root) {
|
|
621
|
+
return Array.from(root.querySelectorAll('button:not([disabled]), a[href], input:not([disabled]), ' +
|
|
622
|
+
'select:not([disabled]), textarea:not([disabled]), ' +
|
|
623
|
+
'[contenteditable="true"], [tabindex]:not([tabindex="-1"])')).filter((element) => !element.hidden &&
|
|
624
|
+
element.getAttribute('aria-hidden') !== 'true' &&
|
|
625
|
+
element.closest('.hidden') === null);
|
|
626
|
+
}
|
|
627
|
+
function isTextEntryTarget(target) {
|
|
628
|
+
if (!(target instanceof Element))
|
|
629
|
+
return false;
|
|
630
|
+
return (target instanceof HTMLInputElement ||
|
|
631
|
+
target instanceof HTMLTextAreaElement ||
|
|
632
|
+
target instanceof HTMLSelectElement ||
|
|
633
|
+
(target instanceof HTMLElement && target.isContentEditable) ||
|
|
634
|
+
target.closest('[contenteditable="true"], [role="textbox"], .monaco-editor, ' +
|
|
635
|
+
'.ck-crowdy-studio-editor') !== null);
|
|
636
|
+
}
|
|
637
|
+
function errorMessage(error) {
|
|
638
|
+
return error instanceof Error ? error.message : String(error);
|
|
639
|
+
}
|
|
640
|
+
function stopEventPropagation(event) {
|
|
641
|
+
event.stopPropagation();
|
|
642
|
+
}
|
|
@@ -8,6 +8,9 @@ export { EMBEDDED_PLATFORM_INDEX, MAX_PLATFORM_CRATES, MAX_PLATFORM_CRATE_FIELD_
|
|
|
8
8
|
export { DEFAULT_VFS_LIMITS, VfsLimitError, VirtualFileSystem, offsetAt, type VirtualDocument, type VirtualFileSystemLimits, } from '../live-coding/vfs.js';
|
|
9
9
|
export { WorkerLanguageClient, WorkerMessageReader, WorkerMessageWriter, createDefaultRustLanguageWorker, type LanguageWorkerLike, type WorkerLanguageClientOptions, } from '../live-coding/worker-transport.js';
|
|
10
10
|
export { CrowdyStudioAgentDomShell, type CrowdyStudioAgentDomShellOptions, } from './agent-dom-shell.js';
|
|
11
|
+
export { STUDIO_LAYOUT_STORAGE_KEY, STUDIO_PANE_IDS, StudioLayoutController, clampStudioPaneSize, studioPaneSizeRange, type StudioLayoutControllerOptions, type StudioLayoutListener, type StudioLayoutState, type StudioLayoutStorage, type StudioPaneId, type StudioPaneSizeRange, } from './layout.js';
|
|
12
|
+
export { createPaneSplitter, type PaneSplitterHandle, type PaneSplitterOptions, type PaneSplitterRange, } from './splitter.js';
|
|
13
|
+
export * from './embed/index.js';
|
|
11
14
|
export * from '../crowdy-agent/index.js';
|
|
12
15
|
export * from '../player-host/index.js';
|
|
13
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crowdy-studio/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,KAAK,kBAAkB,EACvB,KAAK,4BAA4B,EACjC,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,eAAe,EACpB,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC5B,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,GAChC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,GAC9B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,wBAAwB,EACxB,iCAAiC,EACjC,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,cAAc,EACd,KAAK,8BAA8B,EACnC,KAAK,oCAAoC,EACzC,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,6BAA6B,EAClC,KAAK,0BAA0B,EAC/B,KAAK,8BAA8B,EACnC,KAAK,kCAAkC,EACvC,KAAK,mCAAmC,EACxC,KAAK,mBAAmB,EACxB,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,mCAAmC,EACxC,KAAK,kCAAkC,EACvC,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,EACvB,KAAK,gCAAgC,EACrC,KAAK,4BAA4B,GAClC,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gCAAgC,EAChC,KAAK,6BAA6B,GACnC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,qBAAqB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,GAClC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,0BAA0B,EAC1B,KAAK,+BAA+B,GACrC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,+BAA+B,EAC/B,wBAAwB,EACxB,+BAA+B,EAC/B,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,kBAAkB,GACxB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,QAAQ,EACR,KAAK,eAAe,EACpB,KAAK,uBAAuB,GAC7B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,+BAA+B,EAC/B,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,GACjC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,yBAAyB,EACzB,KAAK,gCAAgC,GACtC,MAAM,sBAAsB,CAAC;AAC9B,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crowdy-studio/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,5 +8,8 @@ export { EMBEDDED_PLATFORM_INDEX, MAX_PLATFORM_CRATES, MAX_PLATFORM_CRATE_FIELD_
|
|
|
8
8
|
export { DEFAULT_VFS_LIMITS, VfsLimitError, VirtualFileSystem, offsetAt, } from '../live-coding/vfs.js';
|
|
9
9
|
export { WorkerLanguageClient, WorkerMessageReader, WorkerMessageWriter, createDefaultRustLanguageWorker, } from '../live-coding/worker-transport.js';
|
|
10
10
|
export { CrowdyStudioAgentDomShell, } from './agent-dom-shell.js';
|
|
11
|
+
export { STUDIO_LAYOUT_STORAGE_KEY, STUDIO_PANE_IDS, StudioLayoutController, clampStudioPaneSize, studioPaneSizeRange, } from './layout.js';
|
|
12
|
+
export { createPaneSplitter, } from './splitter.js';
|
|
13
|
+
export * from './embed/index.js';
|
|
11
14
|
export * from '../crowdy-agent/index.js';
|
|
12
15
|
export * from '../player-host/index.js';
|