klun-ui 0.1.8 → 0.1.9

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 CHANGED
@@ -5,6 +5,17 @@ All notable changes to **klun-ui** are documented here. The format follows
5
5
  [Semantic Versioning](https://semver.org/) (pre-1.0: minor/patch bumps may carry
6
6
  small breaking changes).
7
7
 
8
+ ## [0.1.9] — 2026-06-21
9
+
10
+ ### Fixed
11
+ - **`Popconfirm` bubble is no longer clipped by scroll containers.** The bubble
12
+ rendered as an `absolute` child of the trigger, so when the trigger sat inside
13
+ a scrollable/`overflow` pane (e.g. an app content area) the bubble was clipped
14
+ at that pane's edge — near the left edge its title/description got cut off. It
15
+ is now portaled to `<body>`, positioned with fixed viewport coordinates, and
16
+ clamped to stay fully on-screen (recomputed on scroll/resize). Outside-click
17
+ and Escape dismissal still work across the portal boundary.
18
+
8
19
  ## [0.1.8] — 2026-06-21
9
20
 
10
21
  ### Fixed
@@ -10099,6 +10099,8 @@ var Modal = forwardRef(function Modal2({
10099
10099
  );
10100
10100
  });
10101
10101
  Modal.displayName = "Modal";
10102
+ var GAP2 = 8;
10103
+ var MARGIN = 8;
10102
10104
  var Popconfirm = forwardRef(function Popconfirm2({
10103
10105
  title: titleProp,
10104
10106
  description,
@@ -10121,11 +10123,15 @@ var Popconfirm = forwardRef(function Popconfirm2({
10121
10123
  const cancelText = cancelTextProp ?? popconfirm.cancel;
10122
10124
  const [open, setOpen] = useState(false);
10123
10125
  const [busy, setBusy] = useState(false);
10126
+ const [pos, setPos] = useState(null);
10124
10127
  const innerRef = useRef(null);
10128
+ const bubbleRef = useRef(null);
10125
10129
  useEffect(() => {
10126
10130
  if (!open) return;
10127
10131
  const h = (e) => {
10128
- if (innerRef.current && !innerRef.current.contains(e.target)) setOpen(false);
10132
+ const t = e.target;
10133
+ if (innerRef.current?.contains(t) || bubbleRef.current?.contains(t)) return;
10134
+ setOpen(false);
10129
10135
  };
10130
10136
  const k = (e) => {
10131
10137
  if (e.key === "Escape") setOpen(false);
@@ -10137,6 +10143,51 @@ var Popconfirm = forwardRef(function Popconfirm2({
10137
10143
  document.removeEventListener("keydown", k);
10138
10144
  };
10139
10145
  }, [open]);
10146
+ useLayoutEffect(() => {
10147
+ if (!open) {
10148
+ setPos(null);
10149
+ return;
10150
+ }
10151
+ const place = () => {
10152
+ const trigger = innerRef.current;
10153
+ const bubble = bubbleRef.current;
10154
+ if (!trigger || !bubble) return;
10155
+ const tr = trigger.getBoundingClientRect();
10156
+ const bw = bubble.offsetWidth;
10157
+ const bh = bubble.offsetHeight;
10158
+ const vw = document.documentElement.clientWidth;
10159
+ const vh = document.documentElement.clientHeight;
10160
+ let top;
10161
+ let left;
10162
+ switch (placement) {
10163
+ case "bottom":
10164
+ top = tr.bottom + GAP2;
10165
+ left = tr.left + tr.width / 2 - bw / 2;
10166
+ break;
10167
+ case "left":
10168
+ left = tr.left - bw - GAP2;
10169
+ top = tr.top + tr.height / 2 - bh / 2;
10170
+ break;
10171
+ case "right":
10172
+ left = tr.right + GAP2;
10173
+ top = tr.top + tr.height / 2 - bh / 2;
10174
+ break;
10175
+ default:
10176
+ top = tr.top - bh - GAP2;
10177
+ left = tr.left + tr.width / 2 - bw / 2;
10178
+ }
10179
+ left = Math.max(MARGIN, Math.min(left, vw - bw - MARGIN));
10180
+ top = Math.max(MARGIN, Math.min(top, vh - bh - MARGIN));
10181
+ setPos({ top, left });
10182
+ };
10183
+ place();
10184
+ window.addEventListener("scroll", place, true);
10185
+ window.addEventListener("resize", place);
10186
+ return () => {
10187
+ window.removeEventListener("scroll", place, true);
10188
+ window.removeEventListener("resize", place);
10189
+ };
10190
+ }, [open, placement, title, description]);
10140
10191
  const setRefs = (node) => {
10141
10192
  innerRef.current = node;
10142
10193
  if (typeof ref === "function") ref(node);
@@ -10155,6 +10206,16 @@ var Popconfirm = forwardRef(function Popconfirm2({
10155
10206
  onCancel?.();
10156
10207
  setOpen(false);
10157
10208
  };
10209
+ const bubbleStyle = {
10210
+ position: "fixed",
10211
+ top: pos ? pos.top : 0,
10212
+ left: pos ? pos.left : 0,
10213
+ right: "auto",
10214
+ bottom: "auto",
10215
+ transform: "none",
10216
+ visibility: pos ? "visible" : "hidden",
10217
+ ["--klun-popconfirm-tint"]: `var(--klun-state-${status}-base)`
10218
+ };
10158
10219
  return /* @__PURE__ */ jsxs("span", { ref: setRefs, className: cx("klun-popconfirm", className), ...props, children: [
10159
10220
  /* @__PURE__ */ jsx(
10160
10221
  "span",
@@ -10167,47 +10228,51 @@ var Popconfirm = forwardRef(function Popconfirm2({
10167
10228
  children
10168
10229
  }
10169
10230
  ),
10170
- open ? /* @__PURE__ */ jsxs(
10171
- "div",
10172
- {
10173
- role: "dialog",
10174
- className: cx("klun-popconfirm__bubble", `klun-popconfirm__bubble--${placement}`),
10175
- style: { ["--klun-popconfirm-tint"]: `var(--klun-state-${status}-base)` },
10176
- onClick: (e) => e.stopPropagation(),
10177
- children: [
10178
- /* @__PURE__ */ jsxs("div", { className: "klun-popconfirm__head", children: [
10179
- icon ? /* @__PURE__ */ jsx("i", { className: cx("klun-popconfirm__icon", icon) }) : null,
10180
- /* @__PURE__ */ jsxs("div", { className: "klun-popconfirm__body", children: [
10181
- /* @__PURE__ */ jsx("div", { className: "klun-popconfirm__title", children: title }),
10182
- description ? /* @__PURE__ */ jsx("div", { className: "klun-popconfirm__desc", children: description }) : null
10231
+ open && typeof document !== "undefined" ? createPortal(
10232
+ /* @__PURE__ */ jsxs(
10233
+ "div",
10234
+ {
10235
+ ref: bubbleRef,
10236
+ role: "dialog",
10237
+ className: cx("klun-popconfirm__bubble", `klun-popconfirm__bubble--${placement}`),
10238
+ style: bubbleStyle,
10239
+ onClick: (e) => e.stopPropagation(),
10240
+ children: [
10241
+ /* @__PURE__ */ jsxs("div", { className: "klun-popconfirm__head", children: [
10242
+ icon ? /* @__PURE__ */ jsx("i", { className: cx("klun-popconfirm__icon", icon) }) : null,
10243
+ /* @__PURE__ */ jsxs("div", { className: "klun-popconfirm__body", children: [
10244
+ /* @__PURE__ */ jsx("div", { className: "klun-popconfirm__title", children: title }),
10245
+ description ? /* @__PURE__ */ jsx("div", { className: "klun-popconfirm__desc", children: description }) : null
10246
+ ] })
10247
+ ] }),
10248
+ /* @__PURE__ */ jsxs("div", { className: "klun-popconfirm__actions", children: [
10249
+ /* @__PURE__ */ jsx("button", { type: "button", className: "klun-popconfirm__cancel", onClick: cancel, children: cancelText }),
10250
+ /* @__PURE__ */ jsxs(
10251
+ "button",
10252
+ {
10253
+ type: "button",
10254
+ className: cx(
10255
+ "klun-popconfirm__confirm",
10256
+ okDanger && "klun-popconfirm__confirm--danger"
10257
+ ),
10258
+ onClick: confirm,
10259
+ disabled: busy,
10260
+ children: [
10261
+ busy ? /* @__PURE__ */ jsx("i", { className: "ri-loader-4-line klun-popconfirm__spinner" }) : null,
10262
+ okText
10263
+ ]
10264
+ }
10265
+ )
10183
10266
  ] })
10184
- ] }),
10185
- /* @__PURE__ */ jsxs("div", { className: "klun-popconfirm__actions", children: [
10186
- /* @__PURE__ */ jsx("button", { type: "button", className: "klun-popconfirm__cancel", onClick: cancel, children: cancelText }),
10187
- /* @__PURE__ */ jsxs(
10188
- "button",
10189
- {
10190
- type: "button",
10191
- className: cx(
10192
- "klun-popconfirm__confirm",
10193
- okDanger && "klun-popconfirm__confirm--danger"
10194
- ),
10195
- onClick: confirm,
10196
- disabled: busy,
10197
- children: [
10198
- busy ? /* @__PURE__ */ jsx("i", { className: "ri-loader-4-line klun-popconfirm__spinner" }) : null,
10199
- okText
10200
- ]
10201
- }
10202
- )
10203
- ] })
10204
- ]
10205
- }
10267
+ ]
10268
+ }
10269
+ ),
10270
+ document.body
10206
10271
  ) : null
10207
10272
  ] });
10208
10273
  });
10209
10274
  Popconfirm.displayName = "Popconfirm";
10210
10275
 
10211
10276
  export { Accordion, Alert, AutoComplete, Avatar, AvatarGroup, Badge, Banner, Breadcrumb, BulkAction, BulkActionBar, Button, ButtonGroup, Card, Carousel, Cascader, CharacterCounter, ChartLegend, ChartTooltip, Checkbox, CheckboxCard, Chip, CircularProgress, CodeViewer, Col, ColorDot, ColorPicker, ColorSlider, CommandMenu, CompactSelect, CompactSelectForInput, ConfigProvider, Confirm, ContentLabel, CopyButton, CounterInput, DatePicker, DateRangePicker, DateTimePicker, Descriptions, DigitInput, Divider, Drawer, Dropdown, ExpiryCountdown, FileUpload, Flex, Form, FormItem, FormList, Format, GaugeBar, Grid, Hint, HorizontalFilter, ImageUpload, InlineInput, InlineSelect, Input, Kbd, KeyIcon, Label, Layout, LayoutContent, LayoutFooter, LayoutHeader, LayoutSider, List, ListItem, LiveDot, LogViewer, Masonry, Menu, Message, Modal, Money, Notification, Pagination, PasswordStrength, Popconfirm, Popover, ProgressBar, Radio, RadioCard, RangeSlider, Rating, RelativeTime, RichEditorToolbar, Row, SegmentedControl, SegmentedProgress, Select, SelectMenu, Skeleton, Slider, Space, Spinner2 as Spinner, Splitter2 as Splitter, SplitterPanel, Statistic, StatusBadge, StatusDot, StepIndicator, Switch, Table, Tabs, Tag, Textarea, TimePicker, Timeline, Toast, Toaster, Tooltip, Tree, Wizard, arSA, deDE, enUS, esES, fmt, frFR, idID, itIT, jaJP, koKR, locales, nlNL, plPL, primaryColorVars, ptBR, ruRU, toast, trTR, useBreakpoint, useConfig, useForm, useLocale, useMappedSize, useMessage, useNotification, useSize, viVN, zhCN, zhTW };
10212
- //# sourceMappingURL=chunk-Z2TY6K3O.js.map
10213
- //# sourceMappingURL=chunk-Z2TY6K3O.js.map
10277
+ //# sourceMappingURL=chunk-N3A4NTMY.js.map
10278
+ //# sourceMappingURL=chunk-N3A4NTMY.js.map