@octane-xplat/macos-renderer 0.0.1 → 0.10.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/LICENSE +21 -0
- package/README.md +232 -3
- package/package.json +38 -3
- package/src/appkit.d.ts +199 -0
- package/src/fonts.ts +100 -0
- package/src/image.ts +23 -0
- package/src/index.d.ts +18 -0
- package/src/index.ts +4652 -0
- package/src/intrinsics.d.ts +53 -0
- package/src/jsx-runtime.d.ts +7 -0
- package/src/layer.d.mts +17 -0
- package/src/layer.mjs +221 -0
- package/src/native-core-shim.ts +47 -0
- package/src/native-escape-props.ts +30 -0
- package/src/presentation.mjs +501 -0
- package/src/webview.ts +252 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
// Shared surfaces live in the declaring window, independently of its layout.
|
|
2
|
+
// Kept separate from NSPopover and platform-authentic window sheets.
|
|
3
|
+
export function installPresentationBridge(bridge, createRoot, fontFamilyForView) {
|
|
4
|
+
const entries = []
|
|
5
|
+
const layers = new WeakMap()
|
|
6
|
+
class PresentationLayer extends NSView {
|
|
7
|
+
static {
|
|
8
|
+
NativeClass(this)
|
|
9
|
+
}
|
|
10
|
+
acceptsFirstResponder() {
|
|
11
|
+
return true
|
|
12
|
+
}
|
|
13
|
+
hitTest(point) {
|
|
14
|
+
const hit = super.hitTest(point)
|
|
15
|
+
const entry = layers.get(this)
|
|
16
|
+
return (hit === this || hit?.isEqual?.(this)) && !entry?.options.modal ? null : hit
|
|
17
|
+
}
|
|
18
|
+
layout() {
|
|
19
|
+
super.layout()
|
|
20
|
+
layers.get(this)?.layout()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const children = (view) => {
|
|
25
|
+
const result = []
|
|
26
|
+
const list = view?.subviews
|
|
27
|
+
for (let i = 0; i < Number(list?.count ?? 0); i++) {
|
|
28
|
+
result.push(list.objectAtIndex(i))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return result
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const truth = (view, key) => (typeof view?.[key] === 'function' ? view[key]() : view?.[key])
|
|
35
|
+
const focusables = (view) => {
|
|
36
|
+
if (!view || truth(view, 'hidden')) {
|
|
37
|
+
return []
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const own = truth(view, 'acceptsFirstResponder') && view.enabled !== false ? [view] : []
|
|
41
|
+
return [...own, ...children(view).flatMap(focusables)]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const inside = (view, panel) => {
|
|
45
|
+
for (let current = view; current; current = current.superview) {
|
|
46
|
+
if (current === panel || current.isEqual?.(panel)) {
|
|
47
|
+
return true
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const length = (value, budget, fallback) => {
|
|
55
|
+
if (typeof value === 'number') {
|
|
56
|
+
return Math.max(0, value)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (typeof value !== 'string') {
|
|
60
|
+
return fallback
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const match = value.trim().match(/^([\d.]+)(%|px|dip|dvh|vh)?$/)
|
|
64
|
+
return match
|
|
65
|
+
? Number(match[1]) * (['%', 'dvh', 'vh'].includes(match[2]) ? budget / 100 : 1)
|
|
66
|
+
: fallback
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
bridge.setSurfaceAppearance = (view, dark) => {
|
|
70
|
+
const entry = entries.find((entry) => inside(view, entry.panel))
|
|
71
|
+
if (!entry) {
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
entry.options.dark = dark
|
|
76
|
+
entry.layout()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
bridge.presentSurface = (initial) => {
|
|
80
|
+
const owner = initial.owner?.native ?? initial.owner
|
|
81
|
+
const nativeWindow = owner?.window ?? NSApplication.sharedApplication.keyWindow
|
|
82
|
+
const host = nativeWindow?.contentView
|
|
83
|
+
if (!host || typeof initial.component !== 'function') {
|
|
84
|
+
throw new Error('AppKit presentation requires a mounted window and component')
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const layer = PresentationLayer.alloc().initWithFrame(host.bounds)
|
|
88
|
+
layer.autoresizingMask = 18 // width + height
|
|
89
|
+
layer.wantsLayer = true
|
|
90
|
+
const panel = NSView.alloc().initWithFrame(host.bounds)
|
|
91
|
+
panel.wantsLayer = true
|
|
92
|
+
layer.addSubview(panel)
|
|
93
|
+
const root = createRoot(panel, { fontFamily: fontFamilyForView(owner ?? host) })
|
|
94
|
+
let resolveClosed
|
|
95
|
+
const responder = nativeWindow.firstResponder
|
|
96
|
+
const previousFocus = truth(responder, 'isFieldEditor') ? responder.delegate : responder
|
|
97
|
+
const entry = {
|
|
98
|
+
options: initial,
|
|
99
|
+
parent: [...entries]
|
|
100
|
+
.reverse()
|
|
101
|
+
.find(
|
|
102
|
+
(entry) =>
|
|
103
|
+
entry.window === nativeWindow &&
|
|
104
|
+
(owner ? inside(owner, entry.panel) : entry.options.modal),
|
|
105
|
+
),
|
|
106
|
+
panel,
|
|
107
|
+
layer,
|
|
108
|
+
window: nativeWindow,
|
|
109
|
+
closed: false,
|
|
110
|
+
observers: [],
|
|
111
|
+
monitor: null,
|
|
112
|
+
closedPromise: new Promise((resolve) => {
|
|
113
|
+
resolveClosed = resolve
|
|
114
|
+
}),
|
|
115
|
+
layout() {
|
|
116
|
+
if (entry.closed) {
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const options = entry.options
|
|
121
|
+
const bounds = layer.bounds.size
|
|
122
|
+
const w = Number(bounds.width),
|
|
123
|
+
h = Number(bounds.height)
|
|
124
|
+
|
|
125
|
+
const content = panel.subviews?.objectAtIndex?.(0)
|
|
126
|
+
const fit = content?.documentView?.fittingSize ?? content?.fittingSize ?? panel.fittingSize
|
|
127
|
+
const full = options.kind === 'lightbox' || options.fullscreen
|
|
128
|
+
const width = full
|
|
129
|
+
? w
|
|
130
|
+
: Math.min(w, length(options.width, w, options.kind === 'sheet' ? w : 400))
|
|
131
|
+
|
|
132
|
+
let height = full
|
|
133
|
+
? h
|
|
134
|
+
: Math.min(
|
|
135
|
+
h,
|
|
136
|
+
length(options.maxHeight, h, h * 0.75),
|
|
137
|
+
Math.max(80, Number(fit?.height ?? 160)),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
if (options.kind === 'sheet') {
|
|
141
|
+
const budget =
|
|
142
|
+
options.height === 'tall'
|
|
143
|
+
? h * 0.92
|
|
144
|
+
: options.height === 'hug'
|
|
145
|
+
? height
|
|
146
|
+
: length(options.height, h, h * 0.62)
|
|
147
|
+
|
|
148
|
+
const stops = (options.snapPoints ?? [])
|
|
149
|
+
.map((p) => (typeof p === 'number' && p <= 1 ? p * h : length(p, h, 0)))
|
|
150
|
+
.filter((p) => p > 0)
|
|
151
|
+
.map((p) => Math.min(p, h))
|
|
152
|
+
.sort((a, b) => a - b)
|
|
153
|
+
|
|
154
|
+
entry.stops = [...new Set(stops)]
|
|
155
|
+
height = entry.stops.length
|
|
156
|
+
? entry.stops[Math.min(entry.stop ?? 0, entry.stops.length - 1)]
|
|
157
|
+
: Math.min(h * 0.92, budget)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
let x = (w - width) / 2,
|
|
161
|
+
y = (h - height) / 2
|
|
162
|
+
|
|
163
|
+
if (options.kind === 'sheet') {
|
|
164
|
+
y = 0
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (options.kind === 'toast') {
|
|
168
|
+
const edge = options.position ?? 'bottomEnd',
|
|
169
|
+
inset = options.inset ?? {}
|
|
170
|
+
|
|
171
|
+
x = edge.endsWith('Start') ? 16 + (inset.start ?? 0) : w - width - 16 - (inset.end ?? 0)
|
|
172
|
+
y = edge.startsWith('top') ? h - height - 16 - (inset.top ?? 0) : 16 + (inset.bottom ?? 0)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const pos =
|
|
176
|
+
!full && options.position && typeof options.position === 'object' ? options.position : {}
|
|
177
|
+
|
|
178
|
+
if (pos.start != null) {
|
|
179
|
+
x = length(pos.start, w, 0)
|
|
180
|
+
} else if (pos.end != null) {
|
|
181
|
+
x = w - width - length(pos.end, w, 0)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (pos.top != null) {
|
|
185
|
+
y = h - height - length(pos.top, h, 0)
|
|
186
|
+
} else if (pos.bottom != null) {
|
|
187
|
+
y = length(pos.bottom, h, 0)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
panel.frame = { origin: { x: Math.max(0, x), y: Math.max(0, y) }, size: { width, height } }
|
|
191
|
+
layer.layer.backgroundColor = NSColor.colorWithRedGreenBlueAlpha(
|
|
192
|
+
0,
|
|
193
|
+
0,
|
|
194
|
+
0,
|
|
195
|
+
options.modal ? 0.35 : 0,
|
|
196
|
+
).CGColor
|
|
197
|
+
|
|
198
|
+
const surfaceColor = options.dark ? 10 / 255 : 1
|
|
199
|
+
panel.layer.backgroundColor = NSColor.colorWithRedGreenBlueAlpha(
|
|
200
|
+
surfaceColor,
|
|
201
|
+
surfaceColor,
|
|
202
|
+
surfaceColor,
|
|
203
|
+
1,
|
|
204
|
+
).CGColor
|
|
205
|
+
|
|
206
|
+
panel.layer.cornerRadius = full ? 0 : 12
|
|
207
|
+
panel.layer.masksToBounds = true
|
|
208
|
+
if (typeof NSAppearance !== 'undefined' && options.dark != null) {
|
|
209
|
+
panel.appearance = NSAppearance.appearanceNamed(
|
|
210
|
+
options.dark ? 'NSAppearanceNameDarkAqua' : 'NSAppearanceNameAqua',
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
panel.accessibilityLabel = options.label ?? (options.kind === 'sheet' ? 'Sheet' : 'Dialog')
|
|
215
|
+
|
|
216
|
+
panel.accessibilityRole = 'AXGroup'
|
|
217
|
+
},
|
|
218
|
+
update(options) {
|
|
219
|
+
if (entry.closed) {
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const transition =
|
|
224
|
+
entry.didRender &&
|
|
225
|
+
entry.options.kind === 'sheet' &&
|
|
226
|
+
options.transitionKey !== entry.options.transitionKey
|
|
227
|
+
|
|
228
|
+
const hadFocus =
|
|
229
|
+
inside(nativeWindow.firstResponder, panel) ||
|
|
230
|
+
inside(nativeWindow.firstResponder?.delegate, panel) ||
|
|
231
|
+
nativeWindow.firstResponder === layer
|
|
232
|
+
|
|
233
|
+
entry.options = { ...entry.options, ...options }
|
|
234
|
+
root.render(entry.options.component, entry.options.props ?? {})
|
|
235
|
+
entry.layout()
|
|
236
|
+
entry.didRender = true
|
|
237
|
+
if (hadFocus && entry.options.modal) {
|
|
238
|
+
queueMicrotask(() => {
|
|
239
|
+
const top = [...entries]
|
|
240
|
+
.reverse()
|
|
241
|
+
.find((e) => e.window === nativeWindow && e.options.modal && !e.closed)
|
|
242
|
+
|
|
243
|
+
if (
|
|
244
|
+
top === entry &&
|
|
245
|
+
!inside(nativeWindow.firstResponder, panel) &&
|
|
246
|
+
!inside(nativeWindow.firstResponder?.delegate, panel)
|
|
247
|
+
) {
|
|
248
|
+
nativeWindow.makeFirstResponder(focusables(panel)[0] ?? layer)
|
|
249
|
+
}
|
|
250
|
+
})
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (transition && typeof CABasicAnimation !== 'undefined') {
|
|
254
|
+
const animation = CABasicAnimation.animationWithKeyPath('opacity')
|
|
255
|
+
animation.fromValue = NSNumber.numberWithDouble(0.65)
|
|
256
|
+
animation.toValue = NSNumber.numberWithDouble(1)
|
|
257
|
+
animation.duration = 0.18
|
|
258
|
+
panel.layer.addAnimationForKey(animation, 'xplat-sheet-switch')
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (entry.options.kind === 'lightbox') {
|
|
262
|
+
const visit = (view) => {
|
|
263
|
+
if ('allowsMagnification' in view) {
|
|
264
|
+
view.allowsMagnification = entry.options.zoom !== false
|
|
265
|
+
view.minMagnification = 1
|
|
266
|
+
view.maxMagnification = 4
|
|
267
|
+
} else {
|
|
268
|
+
for (const child of children(view)) {
|
|
269
|
+
visit(child)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
visit(panel)
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
close(reason) {
|
|
278
|
+
if (entry.closed) {
|
|
279
|
+
return
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
entry.closed = true
|
|
283
|
+
const owns = (candidate) => {
|
|
284
|
+
for (let current = candidate; current; current = current.parent) {
|
|
285
|
+
if (current === entry) {
|
|
286
|
+
return true
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return false
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const hadFocus = entries
|
|
294
|
+
.filter(owns)
|
|
295
|
+
.some(
|
|
296
|
+
(candidate) =>
|
|
297
|
+
nativeWindow.firstResponder === candidate.layer ||
|
|
298
|
+
nativeWindow.firstResponder?.isEqual?.(candidate.layer) ||
|
|
299
|
+
inside(nativeWindow.firstResponder, candidate.panel) ||
|
|
300
|
+
inside(nativeWindow.firstResponder?.delegate, candidate.panel),
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
for (const child of [...entries].reverse()) {
|
|
304
|
+
if (child.parent === entry) {
|
|
305
|
+
child.close(reason === 'owner' ? 'owner' : 'ancestor')
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
entries.splice(entries.indexOf(entry), 1)
|
|
310
|
+
if (entry.monitor) {
|
|
311
|
+
NSEvent.removeMonitor(entry.monitor)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
for (const observer of entry.observers) {
|
|
315
|
+
NSNotificationCenter.defaultCenter.removeObserver(observer)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
try {
|
|
319
|
+
root.unmount()
|
|
320
|
+
} finally {
|
|
321
|
+
layer.removeFromSuperview()
|
|
322
|
+
layers.delete(layer)
|
|
323
|
+
const target = entry.options.finalFocusRef?.current
|
|
324
|
+
if (hadFocus && reason !== 'owner' && reason !== 'ancestor') {
|
|
325
|
+
if (typeof target?.focus === 'function') {
|
|
326
|
+
target.focus()
|
|
327
|
+
} else if (
|
|
328
|
+
nativeWindow.makeFirstResponder(target?.native ?? target ?? previousFocus ?? host) ===
|
|
329
|
+
false
|
|
330
|
+
) {
|
|
331
|
+
nativeWindow.makeFirstResponder(null)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
resolveClosed(reason)
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (reason === 'user') {
|
|
339
|
+
entry.options.onDismiss?.()
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
requestDismiss(path) {
|
|
343
|
+
const purpose = entry.options.purpose ?? 'info'
|
|
344
|
+
if (purpose === 'required' || (path === 'outside' && purpose !== 'info')) {
|
|
345
|
+
return
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (entry.options.canDismiss?.(path) === false) {
|
|
349
|
+
return
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
entry.close('user')
|
|
353
|
+
},
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
layers.set(layer, entry)
|
|
357
|
+
entries.push(entry)
|
|
358
|
+
try {
|
|
359
|
+
host.addSubview(layer)
|
|
360
|
+
entry.update(initial)
|
|
361
|
+
entry.observers.push(
|
|
362
|
+
NSNotificationCenter.defaultCenter.addObserverForNameObjectQueueUsingBlock(
|
|
363
|
+
'NSWindowWillCloseNotification',
|
|
364
|
+
nativeWindow,
|
|
365
|
+
null,
|
|
366
|
+
() => entry.close('owner'),
|
|
367
|
+
),
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
entry.monitor = NSEvent.addLocalMonitorForEventsMatchingMaskHandler(
|
|
371
|
+
1024 | 2 | 8 | 64 | 4,
|
|
372
|
+
(event) => {
|
|
373
|
+
if (
|
|
374
|
+
entry.closed ||
|
|
375
|
+
!(event.window === nativeWindow || event.window?.isEqual?.(nativeWindow))
|
|
376
|
+
) {
|
|
377
|
+
return event
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const top = [...entries]
|
|
381
|
+
.reverse()
|
|
382
|
+
.find((e) => e.window === nativeWindow && e.options.modal && !e.closed)
|
|
383
|
+
|
|
384
|
+
if (top && top !== entry) {
|
|
385
|
+
return event
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const type = Number(event.type)
|
|
389
|
+
if (type === 10) {
|
|
390
|
+
if (!entry.options.modal && !inside(nativeWindow.firstResponder, panel)) {
|
|
391
|
+
return event
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const code = Number(event.keyCode)
|
|
395
|
+
if (code === 53) {
|
|
396
|
+
entry.requestDismiss('escape')
|
|
397
|
+
return null
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (code === 48 && entry.options.modal) {
|
|
401
|
+
const controls = focusables(panel),
|
|
402
|
+
current = nativeWindow.firstResponder
|
|
403
|
+
|
|
404
|
+
const i = controls.findIndex(
|
|
405
|
+
(v) =>
|
|
406
|
+
v === current ||
|
|
407
|
+
v === current?.delegate ||
|
|
408
|
+
v.isEqual?.(current?.delegate ?? current),
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
const next =
|
|
412
|
+
controls[
|
|
413
|
+
(i + (Number(event.modifierFlags) & 131072 ? -1 : 1) + controls.length) %
|
|
414
|
+
controls.length
|
|
415
|
+
]
|
|
416
|
+
|
|
417
|
+
nativeWindow.makeFirstResponder(next ?? layer)
|
|
418
|
+
return null
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (entry.options.onKey?.(code) === true) {
|
|
422
|
+
return null
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return event
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const point = panel.convertPointFromView(event.locationInWindow, null)
|
|
429
|
+
const bounds = panel.bounds.size
|
|
430
|
+
const within =
|
|
431
|
+
point.x >= 0 && point.y >= 0 && point.x <= bounds.width && point.y <= bounds.height
|
|
432
|
+
|
|
433
|
+
if (
|
|
434
|
+
type === 1 &&
|
|
435
|
+
within &&
|
|
436
|
+
entry.options.kind === 'sheet' &&
|
|
437
|
+
point.y >= bounds.height - 24
|
|
438
|
+
) {
|
|
439
|
+
entry.drag = { y: event.locationInWindow.y, height: panel.frame.size.height }
|
|
440
|
+
return null
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (entry.drag && type === 6) {
|
|
444
|
+
const height = Math.max(
|
|
445
|
+
24,
|
|
446
|
+
Math.min(
|
|
447
|
+
entry.stops?.at(-1) ?? layer.bounds.size.height * 0.92,
|
|
448
|
+
entry.drag.height + event.locationInWindow.y - entry.drag.y,
|
|
449
|
+
),
|
|
450
|
+
)
|
|
451
|
+
|
|
452
|
+
panel.frame = { origin: panel.frame.origin, size: { width: bounds.width, height } }
|
|
453
|
+
return null
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if (entry.drag && type === 2) {
|
|
457
|
+
entry.drag = null
|
|
458
|
+
const height = panel.frame.size.height
|
|
459
|
+
if (height < (entry.stops?.[0] ?? 120) * 0.5) {
|
|
460
|
+
entry.requestDismiss('drag')
|
|
461
|
+
} else if (entry.stops?.length) {
|
|
462
|
+
entry.stop = entry.stops.reduce(
|
|
463
|
+
(best, stop, i, stops) =>
|
|
464
|
+
Math.abs(stop - height) < Math.abs(stops[best] - height) ? i : best,
|
|
465
|
+
0,
|
|
466
|
+
)
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
entry.layout()
|
|
470
|
+
return null
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (!within && entry.options.modal && (type === 1 || type === 3)) {
|
|
474
|
+
entry.requestDismiss('outside')
|
|
475
|
+
return null
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
return event
|
|
479
|
+
},
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
if (initial.modal) {
|
|
483
|
+
nativeWindow.makeFirstResponder(focusables(panel)[0] ?? layer)
|
|
484
|
+
}
|
|
485
|
+
} catch (error) {
|
|
486
|
+
entry.close()
|
|
487
|
+
throw error
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return {
|
|
491
|
+
update: entry.update,
|
|
492
|
+
close: entry.close,
|
|
493
|
+
get closed() {
|
|
494
|
+
return entry.closed
|
|
495
|
+
},
|
|
496
|
+
closedPromise: entry.closedPromise,
|
|
497
|
+
panel,
|
|
498
|
+
layer,
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|