@pactor-app/ui 1.46.0 → 1.48.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.
@@ -41,7 +41,11 @@ var OverlayManager = class {
41
41
  );
42
42
  }
43
43
  this.counter += 1;
44
- const entry = { ...config, id: `overlay-${this.counter}` };
44
+ const entry = {
45
+ ...config,
46
+ id: `overlay-${this.counter}`,
47
+ owner: options.owner
48
+ };
45
49
  return new Promise((resolve) => {
46
50
  this.pending.push({
47
51
  entry,
@@ -124,8 +128,13 @@ function registerInteractionActions(actions, manager, ui) {
124
128
  const { content, ...rest } = overlay;
125
129
  const resolved = resolveDeep(rest, ctx.scope);
126
130
  const config = { ...resolved, content };
131
+ let owner = ctx.context;
132
+ while (owner.parentRuntime !== void 0) {
133
+ owner = owner.parentRuntime;
134
+ }
127
135
  const data = await manager.open(config, {
128
- parentScope: { ...ctx.scope }
136
+ parentScope: { ...ctx.scope },
137
+ owner
129
138
  });
130
139
  return { ok: true, data };
131
140
  });
@@ -196,6 +205,7 @@ var toastTypeClass = {
196
205
  info: "border-l-4 border-l-info",
197
206
  warning: "border-l-4 border-l-warning"
198
207
  };
208
+ var bridgeStacks = /* @__PURE__ */ new WeakMap();
199
209
  function InteractionProvider({
200
210
  bridge,
201
211
  children
@@ -227,11 +237,27 @@ function InteractionProvider({
227
237
  return { modal: modalImpl, message: messageImpl };
228
238
  }, []);
229
239
  useEffect(() => {
240
+ let stack = bridgeStacks.get(bridge);
241
+ if (stack === void 0) {
242
+ stack = [];
243
+ bridgeStacks.set(bridge, stack);
244
+ }
245
+ const impl = { modal, message };
246
+ stack.push(impl);
230
247
  bridge.modal = modal;
231
248
  bridge.message = message;
232
249
  return () => {
233
- bridge.modal = void 0;
234
- bridge.message = void 0;
250
+ const list = bridgeStacks.get(bridge);
251
+ if (list === void 0) {
252
+ return;
253
+ }
254
+ const index = list.indexOf(impl);
255
+ if (index !== -1) {
256
+ list.splice(index, 1);
257
+ }
258
+ const top = list[list.length - 1];
259
+ bridge.modal = top?.modal;
260
+ bridge.message = top?.message;
235
261
  };
236
262
  }, [bridge, modal, message]);
237
263
  const handleOk = () => {
@@ -307,14 +333,14 @@ function InteractionProvider({
307
333
  }
308
334
 
309
335
  // src/interaction/host.tsx
310
- import { XIcon } from "lucide-react";
336
+ import { Loader2, XIcon } from "lucide-react";
311
337
  import {
312
338
  createPageRuntime,
313
339
  PageRuntimeView,
314
340
  useI18n as useI18n2,
315
341
  useRenderer
316
342
  } from "@pactor-app/runtime";
317
- import { useEffect as useEffect2, useState as useState2, useSyncExternalStore } from "react";
343
+ import { useEffect as useEffect2, useRef, useState as useState2, useSyncExternalStore } from "react";
318
344
  import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
319
345
  function toCssWidth(width) {
320
346
  if (width === void 0) {
@@ -339,7 +365,9 @@ function OverlayHost({ manager, resolvePage }) {
339
365
  },
340
366
  () => `${renderer.context.state.getVersion()}:${renderer.context.data.getVersion()}`
341
367
  );
342
- return /* @__PURE__ */ jsx2(Fragment2, { children: stack.map((entry) => /* @__PURE__ */ jsx2(
368
+ return /* @__PURE__ */ jsx2(Fragment2, { children: stack.filter(
369
+ (entry) => entry.owner === void 0 || entry.owner === renderer.context
370
+ ).map((entry) => /* @__PURE__ */ jsx2(
343
371
  OverlayEntryView,
344
372
  {
345
373
  entry,
@@ -357,7 +385,18 @@ function OverlayEntryView({
357
385
  resolvePage
358
386
  }) {
359
387
  const { t } = useI18n2();
388
+ const childRuntimeRef = useRef(null);
360
389
  const handleCancel = () => manager.close(entry.id);
390
+ const handleConfirm = () => {
391
+ const footer2 = entry.footer ?? {};
392
+ const forms = entry.page ? childRuntimeRef.current?.context.forms : renderer.context.forms;
393
+ const handle = forms?.get(footer2.confirmForm ?? "default");
394
+ if (handle?.submit) {
395
+ handle.submit();
396
+ return;
397
+ }
398
+ manager.close(entry.id, { success: true });
399
+ };
361
400
  let body = null;
362
401
  if (entry.content) {
363
402
  body = renderer.renderChildren([entry.content], {
@@ -370,12 +409,24 @@ function OverlayEntryView({
370
409
  {
371
410
  entry,
372
411
  renderer,
373
- resolvePage
412
+ resolvePage,
413
+ onRuntime: (runtime) => {
414
+ childRuntimeRef.current = runtime;
415
+ }
374
416
  }
375
417
  );
376
418
  }
419
+ const footer = entry.footer ? /* @__PURE__ */ jsx2(
420
+ OverlayFooter,
421
+ {
422
+ footer: entry.footer,
423
+ slot: entry.type === "drawer" ? "drawer-footer" : "overlay-modal-footer",
424
+ onCancel: handleCancel,
425
+ onConfirm: handleConfirm
426
+ }
427
+ ) : null;
377
428
  if (entry.type === "drawer") {
378
- return /* @__PURE__ */ jsx2(ShadcnDrawerView, { entry, onCancel: handleCancel, children: body });
429
+ return /* @__PURE__ */ jsx2(ShadcnDrawerView, { entry, onCancel: handleCancel, footer, children: body });
379
430
  }
380
431
  return /* @__PURE__ */ jsx2(
381
432
  Dialog,
@@ -412,16 +463,64 @@ function OverlayEntryView({
412
463
  }
413
464
  )
414
465
  ] }),
415
- /* @__PURE__ */ jsx2("div", { "data-slot": "overlay-modal-body", children: body })
466
+ /* @__PURE__ */ jsx2("div", { "data-slot": "overlay-modal-body", children: body }),
467
+ footer
416
468
  ]
417
469
  }
418
470
  )
419
471
  }
420
472
  );
421
473
  }
474
+ function OverlayFooter({
475
+ footer,
476
+ slot,
477
+ onCancel,
478
+ onConfirm
479
+ }) {
480
+ const { t } = useI18n2();
481
+ if (footer.hideCancel && footer.hideConfirm) {
482
+ return null;
483
+ }
484
+ const confirmBusy = footer.confirmLoading === true;
485
+ return /* @__PURE__ */ jsxs2(
486
+ "div",
487
+ {
488
+ "data-slot": slot,
489
+ className: cn(
490
+ "flex items-center justify-end gap-2",
491
+ slot === "drawer-footer" && "border-t border-border px-6 py-4"
492
+ ),
493
+ children: [
494
+ footer.hideCancel ? null : /* @__PURE__ */ jsx2(
495
+ Button,
496
+ {
497
+ variant: "outline",
498
+ disabled: confirmBusy,
499
+ onClick: onCancel,
500
+ "data-slot": "overlay-cancel",
501
+ children: footer.cancelText ?? t("pactor.overlay.cancel")
502
+ }
503
+ ),
504
+ footer.hideConfirm ? null : /* @__PURE__ */ jsxs2(
505
+ Button,
506
+ {
507
+ disabled: footer.confirmDisabled === true || confirmBusy,
508
+ onClick: onConfirm,
509
+ "data-slot": "overlay-confirm",
510
+ children: [
511
+ confirmBusy ? /* @__PURE__ */ jsx2(Loader2, { className: "animate-spin" }) : null,
512
+ footer.confirmText ?? t("pactor.overlay.confirm")
513
+ ]
514
+ }
515
+ )
516
+ ]
517
+ }
518
+ );
519
+ }
422
520
  function ShadcnDrawerView({
423
521
  entry,
424
522
  onCancel,
523
+ footer,
425
524
  children
426
525
  }) {
427
526
  const { t } = useI18n2();
@@ -465,7 +564,8 @@ function ShadcnDrawerView({
465
564
  ]
466
565
  }
467
566
  ),
468
- /* @__PURE__ */ jsx2("div", { "data-slot": "drawer-body", className: "flex-1 overflow-auto p-6", children })
567
+ /* @__PURE__ */ jsx2("div", { "data-slot": "drawer-body", className: "flex-1 overflow-auto p-6", children }),
568
+ footer
469
569
  ]
470
570
  }
471
571
  )
@@ -475,7 +575,8 @@ function ShadcnDrawerView({
475
575
  function PageOverlayBody({
476
576
  entry,
477
577
  renderer,
478
- resolvePage
578
+ resolvePage,
579
+ onRuntime
479
580
  }) {
480
581
  const [child, setChild] = useState2(null);
481
582
  const [error, setError] = useState2(null);
@@ -508,7 +609,9 @@ function PageOverlayBody({
508
609
  http: host.http,
509
610
  route: { params: entry.params ?? {} }
510
611
  });
612
+ created.context.parentRuntime = host;
511
613
  setChild(created);
614
+ onRuntime?.(created);
512
615
  } catch (cause) {
513
616
  if (!cancelled) {
514
617
  setError(cause instanceof Error ? cause : new Error(String(cause)));
@@ -517,6 +620,7 @@ function PageOverlayBody({
517
620
  })();
518
621
  return () => {
519
622
  cancelled = true;
623
+ onRuntime?.(null);
520
624
  void created?.destroy();
521
625
  };
522
626
  }, [entry.id]);
@@ -2,7 +2,7 @@ import {
2
2
  Icon,
3
3
  Menu,
4
4
  Sidebar
5
- } from "./chunk-FU4P7CAM.js";
5
+ } from "./chunk-B2Y6JC36.js";
6
6
  import {
7
7
  Accordion,
8
8
  AccordionContent,
@@ -15,7 +15,7 @@ import {
15
15
  Popover,
16
16
  PopoverContent,
17
17
  PopoverTrigger
18
- } from "./chunk-7OBUSV5S.js";
18
+ } from "./chunk-YHTRCBKF.js";
19
19
  import {
20
20
  cn
21
21
  } from "./chunk-WKJUCGV4.js";