twico-ui 1.36.1 → 1.37.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/CHANGELOG.md +7 -0
- package/dist/index.cjs +22 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.mjs +22 -10
- package/dist/index.mjs.map +1 -1
- package/llms.txt +3 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Twico UI are documented here (newest first). This file is generated automatically on each release by [semantic-release](https://semantic-release.gitbook.io/) from [Conventional Commits](https://www.conventionalcommits.org/) — do not edit it by hand. The same notes appear on each [GitHub Release](https://github.com/EncryptionL/twico-ui/releases).
|
|
4
4
|
|
|
5
|
+
# [1.37.0](https://github.com/EncryptionL/twico-ui/compare/v1.36.1...v1.37.0) (2026-09-11)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **overlay:** safer Dialog/Drawer defaults + Popover height clamp ([#371](https://github.com/EncryptionL/twico-ui/issues/371), [#372](https://github.com/EncryptionL/twico-ui/issues/372), [#373](https://github.com/EncryptionL/twico-ui/issues/373)) ([0f7a386](https://github.com/EncryptionL/twico-ui/commit/0f7a38656956bb9ef7cdd0331d2b5e6776aa7d7c))
|
|
11
|
+
|
|
5
12
|
## [1.36.1](https://github.com/EncryptionL/twico-ui/compare/v1.36.0...v1.36.1) (2026-09-09)
|
|
6
13
|
|
|
7
14
|
|
package/dist/index.cjs
CHANGED
|
@@ -15433,6 +15433,10 @@ var DIALOG_CSS = `
|
|
|
15433
15433
|
.twc-dialog__close svg { width: 18px; height: 18px; }
|
|
15434
15434
|
.twc-dialog__body { padding: var(--space-4) var(--space-5); font-size: var(--text-sm); color: var(--color-text-muted); line-height: var(--leading-normal); }
|
|
15435
15435
|
.twc-dialog__footer { display: flex; gap: var(--space-2); justify-content: flex-end; padding: 0 var(--space-5) var(--space-5); }
|
|
15436
|
+
/* #372: header/body and body/footer rules (on by default). Per-region data-divider so the rule is
|
|
15437
|
+
suppressed when the region is empty (no footer; a header with only a close button and no title/description). */
|
|
15438
|
+
.twc-dialog__header[data-divider="true"] { padding-bottom: var(--space-4); border-bottom: var(--border-thin) solid var(--color-divider); }
|
|
15439
|
+
.twc-dialog__footer[data-divider="true"] { padding-top: var(--space-4); border-top: var(--border-thin) solid var(--color-divider); }
|
|
15436
15440
|
`;
|
|
15437
15441
|
function Dialog({
|
|
15438
15442
|
open,
|
|
@@ -15442,7 +15446,8 @@ function Dialog({
|
|
|
15442
15446
|
footer,
|
|
15443
15447
|
children,
|
|
15444
15448
|
size = "md",
|
|
15445
|
-
scrollBody =
|
|
15449
|
+
scrollBody = true,
|
|
15450
|
+
dividers = true,
|
|
15446
15451
|
closeOnBackdrop = true,
|
|
15447
15452
|
className = "",
|
|
15448
15453
|
...rest
|
|
@@ -15483,7 +15488,7 @@ function Dialog({
|
|
|
15483
15488
|
}, children: [
|
|
15484
15489
|
__twcStyles,
|
|
15485
15490
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { ref: dialogRef, className: `twc-dialog ${className}`, "data-state": state, "data-size": size, "data-scroll-body": scrollBody ? "true" : void 0, role: "dialog", "aria-modal": "true", tabIndex: -1, "aria-labelledby": title ? titleId : void 0, "aria-label": !title ? "Dialog" : void 0, "aria-describedby": description ? descId : void 0, ...rest, children: [
|
|
15486
|
-
title || description || onClose ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dialog__header", children: [
|
|
15491
|
+
title || description || onClose ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dialog__header", "data-divider": dividers && (title || description) && (children || footer) ? "true" : void 0, children: [
|
|
15487
15492
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dialog__titles", children: [
|
|
15488
15493
|
title ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dialog__title", id: titleId, children: title }) : null,
|
|
15489
15494
|
description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dialog__desc", id: descId, children: description }) : null
|
|
@@ -15491,7 +15496,7 @@ function Dialog({
|
|
|
15491
15496
|
onClose ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-dialog__close", onClick: onClose, "aria-label": "Close", type: "button", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
|
|
15492
15497
|
] }) : null,
|
|
15493
15498
|
children ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dialog__body", children }) : null,
|
|
15494
|
-
footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dialog__footer", children: footer }) : null
|
|
15499
|
+
footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dialog__footer", "data-divider": dividers && children ? "true" : void 0, children: footer }) : null
|
|
15495
15500
|
] })
|
|
15496
15501
|
] });
|
|
15497
15502
|
return renderPortal(overlay);
|
|
@@ -15591,7 +15596,11 @@ var DRAWER_CSS = `
|
|
|
15591
15596
|
.twc-drawer__close:hover { background: var(--color-surface-sunken); color: var(--color-text); }
|
|
15592
15597
|
.twc-drawer__close svg { width: 18px; height: 18px; }
|
|
15593
15598
|
.twc-drawer__body { flex: 1; overflow-y: auto; padding: var(--space-2) var(--space-5) var(--space-5); font-size: var(--text-sm); color: var(--color-text-muted); line-height: var(--leading-normal); }
|
|
15594
|
-
.twc-drawer__footer { display: flex; gap: var(--space-2); justify-content: flex-end; padding: var(--space-4) var(--space-5);
|
|
15599
|
+
.twc-drawer__footer { display: flex; gap: var(--space-2); justify-content: flex-end; padding: var(--space-4) var(--space-5); }
|
|
15600
|
+
/* #372: header/footer rules (on by default), consistent with Dialog. Per-region data-divider so an empty
|
|
15601
|
+
region grows no stray line (no footer; a header with only a close button and no title/description). */
|
|
15602
|
+
.twc-drawer__header[data-divider="true"] { border-bottom: var(--border-thin) solid var(--color-divider); }
|
|
15603
|
+
.twc-drawer__footer[data-divider="true"] { border-top: var(--border-thin) solid var(--color-divider); }
|
|
15595
15604
|
@media (prefers-reduced-motion: reduce) {
|
|
15596
15605
|
.twc-drawer__overlay[data-state], .twc-drawer[data-state] { animation-duration: 1ms; }
|
|
15597
15606
|
}
|
|
@@ -15607,6 +15616,7 @@ function Drawer({
|
|
|
15607
15616
|
width,
|
|
15608
15617
|
height,
|
|
15609
15618
|
closeOnBackdrop = true,
|
|
15619
|
+
dividers = true,
|
|
15610
15620
|
children,
|
|
15611
15621
|
className = "",
|
|
15612
15622
|
style,
|
|
@@ -15652,7 +15662,7 @@ function Drawer({
|
|
|
15652
15662
|
}, children: [
|
|
15653
15663
|
__twcStyles,
|
|
15654
15664
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { ref: panelRef, className: `twc-drawer ${className}`, "data-side": side, "data-state": state, role: "dialog", "aria-modal": "true", tabIndex: -1, "aria-labelledby": title ? titleId : void 0, "aria-label": !title ? "Drawer" : void 0, "aria-describedby": description ? descId : void 0, style: { ...dim ? sizeVar : null, ...style }, ...rest, children: [
|
|
15655
|
-
title || description || onClose ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drawer__header", children: [
|
|
15665
|
+
title || description || onClose ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drawer__header", "data-divider": dividers && (title || description) ? "true" : void 0, children: [
|
|
15656
15666
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drawer__titles", children: [
|
|
15657
15667
|
title ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-drawer__title", id: titleId, children: title }) : null,
|
|
15658
15668
|
description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-drawer__desc", id: descId, children: description }) : null
|
|
@@ -15660,7 +15670,7 @@ function Drawer({
|
|
|
15660
15670
|
onClose ? /* @__PURE__ */ jsxRuntime.jsx("button", { className: "twc-drawer__close", onClick: onClose, "aria-label": "Close", type: "button", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
|
|
15661
15671
|
] }) : null,
|
|
15662
15672
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-drawer__body", children }),
|
|
15663
|
-
footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-drawer__footer", children: footer }) : null
|
|
15673
|
+
footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-drawer__footer", "data-divider": dividers ? "true" : void 0, children: footer }) : null
|
|
15664
15674
|
] })
|
|
15665
15675
|
] });
|
|
15666
15676
|
return renderPortal(overlay);
|
|
@@ -16361,7 +16371,9 @@ var POPOVER_CSS = `
|
|
|
16361
16371
|
.twc-popover__arrow { position: absolute; width: 11px; height: 11px; background: var(--color-surface-raised);
|
|
16362
16372
|
border-left: var(--border-thin) solid var(--color-border); border-top: var(--border-thin) solid var(--color-border);
|
|
16363
16373
|
transform: rotate(45deg); }
|
|
16364
|
-
|
|
16374
|
+
/* #373: cap the panel to the room place() measured and scroll INSIDE the inner (not the panel \u2014 the panel
|
|
16375
|
+
must keep overflow visible so the absolutely-positioned arrow isn't clipped) so a tall panel's footer stays reachable. */
|
|
16376
|
+
.twc-popover__inner { padding: var(--space-4); font-size: var(--text-sm); color: var(--color-text-muted); line-height: var(--leading-normal); overflow-y: auto; }
|
|
16365
16377
|
.twc-popover__title { font-size: var(--text-sm); font-weight: var(--font-bold); color: var(--color-text); margin-bottom: 4px; }
|
|
16366
16378
|
`;
|
|
16367
16379
|
function Popover({
|
|
@@ -16423,7 +16435,7 @@ function Popover({
|
|
|
16423
16435
|
l = Math.max(M, Math.min(l, vw - w - M));
|
|
16424
16436
|
left = l;
|
|
16425
16437
|
arrow = { left: Math.min(Math.max(r2.left + r2.width / 2 - l - 5.5, 10), w - 20), [flip ? "bottom" : "top"]: -6 };
|
|
16426
|
-
return setPos({ top, bottom, left, width: w, flip, arrow });
|
|
16438
|
+
return setPos({ top, bottom, left, width: w, flip, arrow, maxHeight: flip ? spaceAbove : spaceBelow });
|
|
16427
16439
|
}
|
|
16428
16440
|
const ph = popRef.current ? popRef.current.offsetHeight : 120;
|
|
16429
16441
|
let onRight = placement === "right";
|
|
@@ -16435,7 +16447,7 @@ function Popover({
|
|
|
16435
16447
|
const cy = r2.top + r2.height / 2;
|
|
16436
16448
|
top = Math.max(M, Math.min(cy - ph / 2, vh - ph - M));
|
|
16437
16449
|
arrow = { top: Math.min(Math.max(cy - top - 5.5, 8), ph - 18), [onRight ? "left" : "right"]: -6 };
|
|
16438
|
-
setPos({ top, left, width: w, flip: false, arrow });
|
|
16450
|
+
setPos({ top, left, width: w, flip: false, arrow, maxHeight: vh - 2 * M });
|
|
16439
16451
|
}, [placement, align, width]);
|
|
16440
16452
|
React51__namespace.default.useEffect(() => {
|
|
16441
16453
|
if (!open) return;
|
|
@@ -16501,7 +16513,7 @@ function Popover({
|
|
|
16501
16513
|
children: [
|
|
16502
16514
|
__twcStyles,
|
|
16503
16515
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-popover__arrow", style: pos.arrow, "aria-hidden": "true" }),
|
|
16504
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-popover__inner", children: [
|
|
16516
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-popover__inner", style: { maxHeight: pos.maxHeight }, children: [
|
|
16505
16517
|
title ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-popover__title", id: `${popId}-title`, children: title }) : null,
|
|
16506
16518
|
children
|
|
16507
16519
|
] })
|