@pactor-app/ui 1.47.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.
@@ -415,7 +415,7 @@ function ButtonGroup({ className, ...props }) {
415
415
  role: "group",
416
416
  "data-slot": "button-group",
417
417
  className: cn(
418
- "flex w-fit items-stretch [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 [&>[data-slot=button]]:rounded-none [&>[data-slot=button]]:first:rounded-l-md [&>[data-slot=button]]:last:rounded-r-md [&>[data-slot=button]:not(:first-child)]:-ml-px",
418
+ "flex w-fit items-stretch [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 [&>[data-slot=button]]:rounded-none [&>[data-slot=button]]:first:rounded-l-md [&>[data-slot=button]]:last:rounded-r-md [&>[data-slot=button]:not(:first-child)]:-ml-px [&>[data-slot=dropdown-menu-trigger]]:rounded-none [&>[data-slot=dropdown-menu-trigger]:not(:first-child)]:-ml-px [&>[data-slot=dropdown-menu-trigger]]:last:rounded-r-md",
419
419
  className
420
420
  ),
421
421
  ...props
@@ -134,7 +134,7 @@ import {
134
134
  Typography,
135
135
  navigationMenuTriggerStyle,
136
136
  toast
137
- } from "./chunk-F7GQYNTG.js";
137
+ } from "./chunk-5FQ5SDIZ.js";
138
138
  import {
139
139
  Dialog,
140
140
  DialogContent,
@@ -775,6 +775,7 @@ import { X } from "lucide-react";
775
775
  import { jsx as jsx17 } from "react/jsx-runtime";
776
776
  var CLEARABLE_GROUP = "group";
777
777
  var CLEARABLE_ICON_HIDE = "group-hover:hidden";
778
+ var CLEARABLE_OVERLAY_HIDE = "pactor-clearable-ghost";
778
779
  function ClearHoverButton({ label, onClear, className }) {
779
780
  return /* @__PURE__ */ jsx17(
780
781
  "span",
@@ -782,7 +783,7 @@ function ClearHoverButton({ label, onClear, className }) {
782
783
  role: "button",
783
784
  "aria-label": label,
784
785
  className: cn(
785
- "hidden shrink-0 cursor-pointer items-center justify-center text-muted-foreground group-hover:inline-flex hover:text-foreground",
786
+ "pactor-clearable shrink-0 cursor-pointer items-center justify-center text-muted-foreground hover:text-foreground",
786
787
  className
787
788
  ),
788
789
  onClick: (event) => {
@@ -949,12 +950,12 @@ function FieldShell({
949
950
  // 星号为 label 的同级 aria-hidden 兄弟(而非伪元素 / label 子节点):
950
951
  // 不占 label 文本内容与可访问名,视觉仍在 label 前
951
952
  /* @__PURE__ */ jsxs12("span", { className: "flex items-center", children: [
952
- required ? /* @__PURE__ */ jsx19("span", { "aria-hidden": true, className: "mr-0.5 text-destructive", children: "*" }) : null,
953
+ required ? /* @__PURE__ */ jsx19("span", { "aria-hidden": true, className: "mr-0.5 text-sm leading-normal text-destructive", children: "*" }) : null,
953
954
  /* @__PURE__ */ jsx19(
954
955
  "label",
955
956
  {
956
957
  htmlFor,
957
- className: "shrink-0 text-sm leading-none font-medium whitespace-nowrap",
958
+ className: "shrink-0 text-sm leading-normal font-medium whitespace-nowrap",
958
959
  children: label
959
960
  }
960
961
  )
@@ -4894,7 +4895,7 @@ function NumberInput({
4894
4895
  {
4895
4896
  className: cn(
4896
4897
  "absolute inset-y-0 right-0 flex w-7 flex-col divide-y divide-input border-l border-input",
4897
- showClear && CLEARABLE_ICON_HIDE
4898
+ showClear && CLEARABLE_OVERLAY_HIDE
4898
4899
  ),
4899
4900
  children: [
4900
4901
  /* @__PURE__ */ jsx70(
@@ -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 = () => {
@@ -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,
@@ -581,6 +609,7 @@ function PageOverlayBody({
581
609
  http: host.http,
582
610
  route: { params: entry.params ?? {} }
583
611
  });
612
+ created.context.parentRuntime = host;
584
613
  setChild(created);
585
614
  onRuntime?.(created);
586
615
  } catch (cause) {
@@ -1362,7 +1362,7 @@ function ButtonGroup({ className, ...props }) {
1362
1362
  role: "group",
1363
1363
  "data-slot": "button-group",
1364
1364
  className: cn(
1365
- "flex w-fit items-stretch [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 [&>[data-slot=button]]:rounded-none [&>[data-slot=button]]:first:rounded-l-md [&>[data-slot=button]]:last:rounded-r-md [&>[data-slot=button]:not(:first-child)]:-ml-px",
1365
+ "flex w-fit items-stretch [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 [&>[data-slot=button]]:rounded-none [&>[data-slot=button]]:first:rounded-l-md [&>[data-slot=button]]:last:rounded-r-md [&>[data-slot=button]:not(:first-child)]:-ml-px [&>[data-slot=dropdown-menu-trigger]]:rounded-none [&>[data-slot=dropdown-menu-trigger]:not(:first-child)]:-ml-px [&>[data-slot=dropdown-menu-trigger]]:last:rounded-r-md",
1366
1366
  className
1367
1367
  ),
1368
1368
  ...props
@@ -1947,6 +1947,7 @@ var import_lucide_react7 = require("lucide-react");
1947
1947
  var import_jsx_runtime34 = require("react/jsx-runtime");
1948
1948
  var CLEARABLE_GROUP = "group";
1949
1949
  var CLEARABLE_ICON_HIDE = "group-hover:hidden";
1950
+ var CLEARABLE_OVERLAY_HIDE = "pactor-clearable-ghost";
1950
1951
  function ClearHoverButton({ label, onClear, className }) {
1951
1952
  return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1952
1953
  "span",
@@ -1954,7 +1955,7 @@ function ClearHoverButton({ label, onClear, className }) {
1954
1955
  role: "button",
1955
1956
  "aria-label": label,
1956
1957
  className: cn(
1957
- "hidden shrink-0 cursor-pointer items-center justify-center text-muted-foreground group-hover:inline-flex hover:text-foreground",
1958
+ "pactor-clearable shrink-0 cursor-pointer items-center justify-center text-muted-foreground hover:text-foreground",
1958
1959
  className
1959
1960
  ),
1960
1961
  onClick: (event) => {
@@ -2166,12 +2167,12 @@ function FieldShell({
2166
2167
  style,
2167
2168
  children: [
2168
2169
  label ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "flex items-center", children: [
2169
- required ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { "aria-hidden": true, className: "mr-0.5 text-destructive", children: "*" }) : null,
2170
+ required ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { "aria-hidden": true, className: "mr-0.5 text-sm leading-normal text-destructive", children: "*" }) : null,
2170
2171
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
2171
2172
  "label",
2172
2173
  {
2173
2174
  htmlFor,
2174
- className: "shrink-0 text-sm leading-none font-medium whitespace-nowrap",
2175
+ className: "shrink-0 text-sm leading-normal font-medium whitespace-nowrap",
2175
2176
  children: label
2176
2177
  }
2177
2178
  )
@@ -8572,7 +8573,7 @@ function NumberInput({
8572
8573
  {
8573
8574
  className: cn(
8574
8575
  "absolute inset-y-0 right-0 flex w-7 flex-col divide-y divide-input border-l border-input",
8575
- showClear && CLEARABLE_ICON_HIDE
8576
+ showClear && CLEARABLE_OVERLAY_HIDE
8576
8577
  ),
8577
8578
  children: [
8578
8579
  /* @__PURE__ */ (0, import_jsx_runtime118.jsx)(
@@ -125,7 +125,7 @@ import {
125
125
  registerBuiltinComponents,
126
126
  useFormContext,
127
127
  useOptionalRenderer
128
- } from "../chunk-7VDIDB3K.js";
128
+ } from "../chunk-PF2FHU2X.js";
129
129
  import {
130
130
  DropdownMenu,
131
131
  ICONS,
@@ -137,7 +137,7 @@ import {
137
137
  normalizeIconName,
138
138
  useSidebarDrawer
139
139
  } from "../chunk-B2Y6JC36.js";
140
- import "../chunk-F7GQYNTG.js";
140
+ import "../chunk-5FQ5SDIZ.js";
141
141
  import "../chunk-YVHPJHW3.js";
142
142
  import "../chunk-YHTRCBKF.js";
143
143
  import "../chunk-WKJUCGV4.js";
package/dist/index.cjs CHANGED
@@ -1378,7 +1378,7 @@ function ButtonGroup({ className, ...props }) {
1378
1378
  role: "group",
1379
1379
  "data-slot": "button-group",
1380
1380
  className: cn(
1381
- "flex w-fit items-stretch [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 [&>[data-slot=button]]:rounded-none [&>[data-slot=button]]:first:rounded-l-md [&>[data-slot=button]]:last:rounded-r-md [&>[data-slot=button]:not(:first-child)]:-ml-px",
1381
+ "flex w-fit items-stretch [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 [&>[data-slot=button]]:rounded-none [&>[data-slot=button]]:first:rounded-l-md [&>[data-slot=button]]:last:rounded-r-md [&>[data-slot=button]:not(:first-child)]:-ml-px [&>[data-slot=dropdown-menu-trigger]]:rounded-none [&>[data-slot=dropdown-menu-trigger]:not(:first-child)]:-ml-px [&>[data-slot=dropdown-menu-trigger]]:last:rounded-r-md",
1382
1382
  className
1383
1383
  ),
1384
1384
  ...props
@@ -1963,6 +1963,7 @@ var import_lucide_react7 = require("lucide-react");
1963
1963
  var import_jsx_runtime34 = require("react/jsx-runtime");
1964
1964
  var CLEARABLE_GROUP = "group";
1965
1965
  var CLEARABLE_ICON_HIDE = "group-hover:hidden";
1966
+ var CLEARABLE_OVERLAY_HIDE = "pactor-clearable-ghost";
1966
1967
  function ClearHoverButton({ label, onClear, className }) {
1967
1968
  return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1968
1969
  "span",
@@ -1970,7 +1971,7 @@ function ClearHoverButton({ label, onClear, className }) {
1970
1971
  role: "button",
1971
1972
  "aria-label": label,
1972
1973
  className: cn(
1973
- "hidden shrink-0 cursor-pointer items-center justify-center text-muted-foreground group-hover:inline-flex hover:text-foreground",
1974
+ "pactor-clearable shrink-0 cursor-pointer items-center justify-center text-muted-foreground hover:text-foreground",
1974
1975
  className
1975
1976
  ),
1976
1977
  onClick: (event) => {
@@ -2182,12 +2183,12 @@ function FieldShell({
2182
2183
  style,
2183
2184
  children: [
2184
2185
  label ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "flex items-center", children: [
2185
- required ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { "aria-hidden": true, className: "mr-0.5 text-destructive", children: "*" }) : null,
2186
+ required ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { "aria-hidden": true, className: "mr-0.5 text-sm leading-normal text-destructive", children: "*" }) : null,
2186
2187
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
2187
2188
  "label",
2188
2189
  {
2189
2190
  htmlFor,
2190
- className: "shrink-0 text-sm leading-none font-medium whitespace-nowrap",
2191
+ className: "shrink-0 text-sm leading-normal font-medium whitespace-nowrap",
2191
2192
  children: label
2192
2193
  }
2193
2194
  )
@@ -8611,7 +8612,7 @@ function NumberInput({
8611
8612
  {
8612
8613
  className: cn(
8613
8614
  "absolute inset-y-0 right-0 flex w-7 flex-col divide-y divide-input border-l border-input",
8614
- showClear && CLEARABLE_ICON_HIDE
8615
+ showClear && CLEARABLE_OVERLAY_HIDE
8615
8616
  ),
8616
8617
  children: [
8617
8618
  /* @__PURE__ */ (0, import_jsx_runtime118.jsx)(
@@ -14128,7 +14129,11 @@ var OverlayManager = class {
14128
14129
  );
14129
14130
  }
14130
14131
  this.counter += 1;
14131
- const entry = { ...config, id: `overlay-${this.counter}` };
14132
+ const entry = {
14133
+ ...config,
14134
+ id: `overlay-${this.counter}`,
14135
+ owner: options.owner
14136
+ };
14132
14137
  return new Promise((resolve) => {
14133
14138
  this.pending.push({
14134
14139
  entry,
@@ -14211,8 +14216,13 @@ function registerInteractionActions(actions, manager, ui) {
14211
14216
  const { content, ...rest } = overlay;
14212
14217
  const resolved = (0, import_runtime51.resolveDeep)(rest, ctx.scope);
14213
14218
  const config = { ...resolved, content };
14219
+ let owner = ctx.context;
14220
+ while (owner.parentRuntime !== void 0) {
14221
+ owner = owner.parentRuntime;
14222
+ }
14214
14223
  const data = await manager.open(config, {
14215
- parentScope: { ...ctx.scope }
14224
+ parentScope: { ...ctx.scope },
14225
+ owner
14216
14226
  });
14217
14227
  return { ok: true, data };
14218
14228
  });
@@ -14283,6 +14293,7 @@ var toastTypeClass = {
14283
14293
  info: "border-l-4 border-l-info",
14284
14294
  warning: "border-l-4 border-l-warning"
14285
14295
  };
14296
+ var bridgeStacks = /* @__PURE__ */ new WeakMap();
14286
14297
  function InteractionProvider({
14287
14298
  bridge,
14288
14299
  children
@@ -14314,11 +14325,27 @@ function InteractionProvider({
14314
14325
  return { modal: modalImpl, message: messageImpl };
14315
14326
  }, []);
14316
14327
  (0, import_react66.useEffect)(() => {
14328
+ let stack = bridgeStacks.get(bridge);
14329
+ if (stack === void 0) {
14330
+ stack = [];
14331
+ bridgeStacks.set(bridge, stack);
14332
+ }
14333
+ const impl = { modal, message };
14334
+ stack.push(impl);
14317
14335
  bridge.modal = modal;
14318
14336
  bridge.message = message;
14319
14337
  return () => {
14320
- bridge.modal = void 0;
14321
- bridge.message = void 0;
14338
+ const list = bridgeStacks.get(bridge);
14339
+ if (list === void 0) {
14340
+ return;
14341
+ }
14342
+ const index = list.indexOf(impl);
14343
+ if (index !== -1) {
14344
+ list.splice(index, 1);
14345
+ }
14346
+ const top = list[list.length - 1];
14347
+ bridge.modal = top?.modal;
14348
+ bridge.message = top?.message;
14322
14349
  };
14323
14350
  }, [bridge, modal, message]);
14324
14351
  const handleOk = () => {
@@ -14421,7 +14448,9 @@ function OverlayHost({ manager, resolvePage }) {
14421
14448
  },
14422
14449
  () => `${renderer.context.state.getVersion()}:${renderer.context.data.getVersion()}`
14423
14450
  );
14424
- return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(import_jsx_runtime180.Fragment, { children: stack.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
14451
+ return /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(import_jsx_runtime180.Fragment, { children: stack.filter(
14452
+ (entry) => entry.owner === void 0 || entry.owner === renderer.context
14453
+ ).map((entry) => /* @__PURE__ */ (0, import_jsx_runtime180.jsx)(
14425
14454
  OverlayEntryView,
14426
14455
  {
14427
14456
  entry,
@@ -14663,6 +14692,7 @@ function PageOverlayBody({
14663
14692
  http: host.http,
14664
14693
  route: { params: entry.params ?? {} }
14665
14694
  });
14695
+ created.context.parentRuntime = host;
14666
14696
  setChild(created);
14667
14697
  onRuntime?.(created);
14668
14698
  } catch (cause) {
package/dist/index.js CHANGED
@@ -125,7 +125,7 @@ import {
125
125
  registerBuiltinComponents,
126
126
  useFormContext,
127
127
  useOptionalRenderer
128
- } from "./chunk-7VDIDB3K.js";
128
+ } from "./chunk-PF2FHU2X.js";
129
129
  import {
130
130
  InteractionProvider,
131
131
  OVERLAY_CANCEL_PAYLOAD,
@@ -133,7 +133,7 @@ import {
133
133
  OverlayManager,
134
134
  createUiBridge,
135
135
  registerInteractionActions
136
- } from "./chunk-OBSD66BK.js";
136
+ } from "./chunk-PSEMK4AY.js";
137
137
  import {
138
138
  AdminLayout,
139
139
  BlankLayout,
@@ -157,7 +157,7 @@ import {
157
157
  normalizeIconName,
158
158
  useSidebarDrawer
159
159
  } from "./chunk-B2Y6JC36.js";
160
- import "./chunk-F7GQYNTG.js";
160
+ import "./chunk-5FQ5SDIZ.js";
161
161
  import "./chunk-YVHPJHW3.js";
162
162
  import "./chunk-YHTRCBKF.js";
163
163
  import "./chunk-WKJUCGV4.js";
@@ -63,7 +63,11 @@ var OverlayManager = class {
63
63
  );
64
64
  }
65
65
  this.counter += 1;
66
- const entry = { ...config, id: `overlay-${this.counter}` };
66
+ const entry = {
67
+ ...config,
68
+ id: `overlay-${this.counter}`,
69
+ owner: options.owner
70
+ };
67
71
  return new Promise((resolve) => {
68
72
  this.pending.push({
69
73
  entry,
@@ -146,8 +150,13 @@ function registerInteractionActions(actions, manager, ui) {
146
150
  const { content, ...rest } = overlay;
147
151
  const resolved = (0, import_runtime.resolveDeep)(rest, ctx.scope);
148
152
  const config = { ...resolved, content };
153
+ let owner = ctx.context;
154
+ while (owner.parentRuntime !== void 0) {
155
+ owner = owner.parentRuntime;
156
+ }
149
157
  const data = await manager.open(config, {
150
- parentScope: { ...ctx.scope }
158
+ parentScope: { ...ctx.scope },
159
+ owner
151
160
  });
152
161
  return { ok: true, data };
153
162
  });
@@ -417,6 +426,7 @@ var toastTypeClass = {
417
426
  info: "border-l-4 border-l-info",
418
427
  warning: "border-l-4 border-l-warning"
419
428
  };
429
+ var bridgeStacks = /* @__PURE__ */ new WeakMap();
420
430
  function InteractionProvider({
421
431
  bridge,
422
432
  children
@@ -448,11 +458,27 @@ function InteractionProvider({
448
458
  return { modal: modalImpl, message: messageImpl };
449
459
  }, []);
450
460
  (0, import_react.useEffect)(() => {
461
+ let stack = bridgeStacks.get(bridge);
462
+ if (stack === void 0) {
463
+ stack = [];
464
+ bridgeStacks.set(bridge, stack);
465
+ }
466
+ const impl = { modal, message };
467
+ stack.push(impl);
451
468
  bridge.modal = modal;
452
469
  bridge.message = message;
453
470
  return () => {
454
- bridge.modal = void 0;
455
- bridge.message = void 0;
471
+ const list = bridgeStacks.get(bridge);
472
+ if (list === void 0) {
473
+ return;
474
+ }
475
+ const index = list.indexOf(impl);
476
+ if (index !== -1) {
477
+ list.splice(index, 1);
478
+ }
479
+ const top = list[list.length - 1];
480
+ bridge.modal = top?.modal;
481
+ bridge.message = top?.message;
456
482
  };
457
483
  }, [bridge, modal, message]);
458
484
  const handleOk = () => {
@@ -638,7 +664,9 @@ function OverlayHost({ manager, resolvePage }) {
638
664
  },
639
665
  () => `${renderer.context.state.getVersion()}:${renderer.context.data.getVersion()}`
640
666
  );
641
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: stack.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
667
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: stack.filter(
668
+ (entry) => entry.owner === void 0 || entry.owner === renderer.context
669
+ ).map((entry) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
642
670
  OverlayEntryView,
643
671
  {
644
672
  entry,
@@ -880,6 +908,7 @@ function PageOverlayBody({
880
908
  http: host.http,
881
909
  route: { params: entry.params ?? {} }
882
910
  });
911
+ created.context.parentRuntime = host;
883
912
  setChild(created);
884
913
  onRuntime?.(created);
885
914
  } catch (cause) {
@@ -54,6 +54,12 @@ interface OverlayConfig {
54
54
  /** 堆栈条目:配置 + 生成的 id */
55
55
  interface OverlayEntry extends OverlayConfig {
56
56
  id: string;
57
+ /**
58
+ * 打开方身份(缺省为发起 overlay.open 的运行时上下文根):多运行时
59
+ * 共享同一 OverlayManager(如布局嵌套链共用装配单例)时,OverlayHost
60
+ * 只渲染 owner 匹配所在运行时的条目;缺省(程序直开)所有宿主可见
61
+ */
62
+ owner?: unknown;
57
63
  }
58
64
  /** 堆栈变化监听器:open / close 时以最新堆栈快照回调 */
59
65
  type OverlayListener = (stack: readonly OverlayEntry[]) => void;
@@ -88,6 +94,7 @@ declare class OverlayManager {
88
94
  */
89
95
  open(config: OverlayConfig, options?: {
90
96
  parentScope?: Record<string, unknown>;
97
+ owner?: unknown;
91
98
  }): Promise<unknown>;
92
99
  /**
93
100
  * 关闭 overlay 并以 payload resolve 对应的 open Promise:
@@ -174,7 +181,8 @@ interface InteractionProviderProps {
174
181
  * - `message.{success,error,info,warning}`:toast 栈(容器固定右上角,
175
182
  * 自动约 3s 消失,类型色条读语义令牌)。
176
183
  *
177
- * unmount 时清空 bridge,动作退化为受控失败。
184
+ * 多 Provider 共存时 bridge 指向最后挂载者(栈顶),卸载后回退到上一
185
+ * 实现;全部卸载后动作退化为受控失败。
178
186
  */
179
187
  declare function InteractionProvider({ bridge, children, }: InteractionProviderProps): React.JSX.Element;
180
188
 
@@ -54,6 +54,12 @@ interface OverlayConfig {
54
54
  /** 堆栈条目:配置 + 生成的 id */
55
55
  interface OverlayEntry extends OverlayConfig {
56
56
  id: string;
57
+ /**
58
+ * 打开方身份(缺省为发起 overlay.open 的运行时上下文根):多运行时
59
+ * 共享同一 OverlayManager(如布局嵌套链共用装配单例)时,OverlayHost
60
+ * 只渲染 owner 匹配所在运行时的条目;缺省(程序直开)所有宿主可见
61
+ */
62
+ owner?: unknown;
57
63
  }
58
64
  /** 堆栈变化监听器:open / close 时以最新堆栈快照回调 */
59
65
  type OverlayListener = (stack: readonly OverlayEntry[]) => void;
@@ -88,6 +94,7 @@ declare class OverlayManager {
88
94
  */
89
95
  open(config: OverlayConfig, options?: {
90
96
  parentScope?: Record<string, unknown>;
97
+ owner?: unknown;
91
98
  }): Promise<unknown>;
92
99
  /**
93
100
  * 关闭 overlay 并以 payload resolve 对应的 open Promise:
@@ -174,7 +181,8 @@ interface InteractionProviderProps {
174
181
  * - `message.{success,error,info,warning}`:toast 栈(容器固定右上角,
175
182
  * 自动约 3s 消失,类型色条读语义令牌)。
176
183
  *
177
- * unmount 时清空 bridge,动作退化为受控失败。
184
+ * 多 Provider 共存时 bridge 指向最后挂载者(栈顶),卸载后回退到上一
185
+ * 实现;全部卸载后动作退化为受控失败。
178
186
  */
179
187
  declare function InteractionProvider({ bridge, children, }: InteractionProviderProps): React.JSX.Element;
180
188
 
@@ -5,7 +5,7 @@ import {
5
5
  OverlayManager,
6
6
  createUiBridge,
7
7
  registerInteractionActions
8
- } from "../chunk-OBSD66BK.js";
8
+ } from "../chunk-PSEMK4AY.js";
9
9
  import "../chunk-YVHPJHW3.js";
10
10
  import "../chunk-WKJUCGV4.js";
11
11
  export {
package/dist/ui/index.cjs CHANGED
@@ -1144,7 +1144,7 @@ function ButtonGroup({ className, ...props }) {
1144
1144
  role: "group",
1145
1145
  "data-slot": "button-group",
1146
1146
  className: cn(
1147
- "flex w-fit items-stretch [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 [&>[data-slot=button]]:rounded-none [&>[data-slot=button]]:first:rounded-l-md [&>[data-slot=button]]:last:rounded-r-md [&>[data-slot=button]:not(:first-child)]:-ml-px",
1147
+ "flex w-fit items-stretch [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 [&>[data-slot=button]]:rounded-none [&>[data-slot=button]]:first:rounded-l-md [&>[data-slot=button]]:last:rounded-r-md [&>[data-slot=button]:not(:first-child)]:-ml-px [&>[data-slot=dropdown-menu-trigger]]:rounded-none [&>[data-slot=dropdown-menu-trigger]:not(:first-child)]:-ml-px [&>[data-slot=dropdown-menu-trigger]]:last:rounded-r-md",
1148
1148
  className
1149
1149
  ),
1150
1150
  ...props
@@ -185,6 +185,8 @@ declare function BreadcrumbEllipsis({ className, ...props }: React.ComponentProp
185
185
  /**
186
186
  * shadcn/ui ButtonGroup(vendored 源码,纯样式组合):
187
187
  * 相连按钮组——内部按钮去圆角,首尾保留外侧圆角,相邻边框重叠。
188
+ * 下拉触发钮(data-slot=dropdown-menu-trigger,如 SplitButton 的 chevron
189
+ * 触发)同为直接子元素,按相同规则并入相连表面。
188
190
  */
189
191
  declare function ButtonGroup({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
190
192
 
@@ -185,6 +185,8 @@ declare function BreadcrumbEllipsis({ className, ...props }: React.ComponentProp
185
185
  /**
186
186
  * shadcn/ui ButtonGroup(vendored 源码,纯样式组合):
187
187
  * 相连按钮组——内部按钮去圆角,首尾保留外侧圆角,相邻边框重叠。
188
+ * 下拉触发钮(data-slot=dropdown-menu-trigger,如 SplitButton 的 chevron
189
+ * 触发)同为直接子元素,按相同规则并入相连表面。
188
190
  */
189
191
  declare function ButtonGroup({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
190
192
 
package/dist/ui/index.js CHANGED
@@ -149,7 +149,7 @@ import {
149
149
  toggleVariants,
150
150
  typographyVariants,
151
151
  useCarousel
152
- } from "../chunk-F7GQYNTG.js";
152
+ } from "../chunk-5FQ5SDIZ.js";
153
153
  import {
154
154
  Dialog,
155
155
  DialogClose,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pactor-app/ui",
3
- "version": "1.47.0",
3
+ "version": "1.48.0",
4
4
  "description": "Pactor UI kit (shadcn): the single built-in UI kit — vendored shadcn/ui components (Base UI primitives + cva + tailwind-merge + lucide-react), props contracts, interaction core (OverlayManager / UiBridge) and layouts, with build-time Tailwind v4 prebuilt styles.css (zero consumer-side Tailwind config)",
5
5
  "keywords": [
6
6
  "pactor",
@@ -108,11 +108,11 @@
108
108
  "react-resizable-panels": "^4.12.3",
109
109
  "tailwind-merge": "^3.6.0",
110
110
  "vaul": "^1.1.2",
111
- "@pactor-app/core": "1.47.0",
112
- "@pactor-app/permission": "1.47.0",
113
- "@pactor-app/markdown": "1.47.0",
114
- "@pactor-app/runtime": "1.47.0",
115
- "@pactor-app/router": "1.47.0"
111
+ "@pactor-app/core": "1.48.0",
112
+ "@pactor-app/permission": "1.48.0",
113
+ "@pactor-app/runtime": "1.48.0",
114
+ "@pactor-app/router": "1.48.0",
115
+ "@pactor-app/markdown": "1.48.0"
116
116
  },
117
117
  "peerDependencies": {
118
118
  "react": ">=18",
package/styles.css CHANGED
@@ -42,6 +42,7 @@
42
42
  --font-weight-extrabold: 800;
43
43
  --tracking-tight: -0.025em;
44
44
  --leading-tight: 1.25;
45
+ --leading-normal: 1.5;
45
46
  --leading-relaxed: 1.625;
46
47
  --radius-xs: 0.125rem;
47
48
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
@@ -1821,6 +1822,10 @@
1821
1822
  --tw-leading: 1;
1822
1823
  line-height: 1;
1823
1824
  }
1825
+ .leading-normal {
1826
+ --tw-leading: var(--leading-normal);
1827
+ line-height: var(--leading-normal);
1828
+ }
1824
1829
  .leading-relaxed {
1825
1830
  --tw-leading: var(--leading-relaxed);
1826
1831
  line-height: var(--leading-relaxed);
@@ -3603,6 +3608,16 @@
3603
3608
  .\[\&\>\[data-slot\=button\]\:not\(\:first-child\)\]\:-ml-px > [data-slot=button]:not(:first-child) {
3604
3609
  margin-left: -1px;
3605
3610
  }
3611
+ .\[\&\>\[data-slot\=dropdown-menu-trigger\]\]\:rounded-none > [data-slot=dropdown-menu-trigger] {
3612
+ border-radius: 0;
3613
+ }
3614
+ .\[\&\>\[data-slot\=dropdown-menu-trigger\]\]\:last\:rounded-r-md > [data-slot=dropdown-menu-trigger]:last-child {
3615
+ border-top-right-radius: calc(var(--radius) * 0.8);
3616
+ border-bottom-right-radius: calc(var(--radius) * 0.8);
3617
+ }
3618
+ .\[\&\>\[data-slot\=dropdown-menu-trigger\]\:not\(\:first-child\)\]\:-ml-px > [data-slot=dropdown-menu-trigger]:not(:first-child) {
3619
+ margin-left: -1px;
3620
+ }
3606
3621
  .\[\&\>\[data-slot\=text\]\]\:shrink-0 > [data-slot=text] {
3607
3622
  flex-shrink: 0;
3608
3623
  }
@@ -4148,6 +4163,17 @@
4148
4163
  background-position: -200% 0;
4149
4164
  }
4150
4165
  }
4166
+ .pactor-clearable {
4167
+ display: none;
4168
+ }
4169
+ @media (hover: hover) {
4170
+ .group:hover .pactor-clearable {
4171
+ display: inline-flex;
4172
+ }
4173
+ .group:hover .pactor-clearable-ghost {
4174
+ visibility: hidden;
4175
+ }
4176
+ }
4151
4177
  @layer base {
4152
4178
  * {
4153
4179
  border-color: var(--border);