@kungal/ui-core 2.54.0 → 2.55.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 CHANGED
@@ -1,5 +1,31 @@
1
1
  # @kungal/ui-core
2
2
 
3
+ ## 2.55.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 0bac099: New `KunSplitPane`: two panes with a divider you can drag or move with the keyboard. It suits a list beside a detail view, or a main area with an auxiliary column. KunChatLayout now switches between one and two panes by its own width, and its list pane can be made draggable.
8
+
9
+ **KunSplitPane** puts its panes in the `#start` and `#end` slots.
10
+
11
+ - **Width.** `v-model:size` is the primary pane's width in px (default 360). It is a prop the server knows, so the server-rendered HTML already has the layout and the divider's `aria-valuenow`/`min`/`max`.
12
+ - **Persisting the width.** `v-model:size` updates on every pointer move. Save from `resize-end`, which fires once per drag or key press, for example to a cookie your server reads back into `size`.
13
+ - **Limits and snapping.** `min-size` and `max-size` default to 240 and 480. `snap-points` (e.g. `[360, 412]`) pull the divider in once it comes within `snap-threshold` px (default 8), and any width in between stays reachable. A keyboard step that ends within the threshold snaps too, but a snap never cancels or reverses a step, so a small `step` cannot get stuck on a snap point.
14
+ - **Which pane is sized.** `primary="end"` gives the width to the right pane, for an auxiliary column.
15
+ - **Keyboard** (WAI-ARIA window splitter pattern):
16
+ - ← and → move the divider by `step` (default 10px); Shift moves five steps.
17
+ - Home and End jump to the minimum and maximum.
18
+ - **The divider** is a 1px line. Its grab area is 9px wide with a mouse and 21px on a touch screen, and it sits above the panes' content. A drag follows the pointer that started it; a second finger or the mouse cannot take it over. While you drag, the page keeps a col-resize cursor, no text gets selected, and the panes ignore the pointer, so an iframe can't swallow the drag.
19
+ - **Narrow layouts.** Below `stack-below` (`md` = 48rem by default, `lg` = 64rem, or `false`), it shows one pane at a time, chosen by `show-pane`. This is a container query on the component's own width, not a media query on the window: a split nested beside a side rail or inside another pane stacks based on the room it actually has.
20
+ - **Flutter port.** The snapping rule is a pure `resolveKunSplitSize` in `@kungal/ui-core`, with tests.
21
+
22
+ **KunChatLayout** now shows two panes once the layout itself is 48rem (768px) wide, rather than once the window is.
23
+
24
+ - **Why:** a chat beside an app's side rail used to switch to two panes in a 768px window that left it 679px, and the conversation was squeezed to 327px.
25
+ - **What might change for you:** pages that give the chat less than 48rem (for example, a window of about 768–800px minus page padding) now show one pane.
26
+ - **KunChatHeader's `back="mobile"`** follows the KunChatLayout around it. Outside a KunChatLayout it still uses the window's `md` width.
27
+ - **New props:** `resizable`, `v-model:sidebar-size` (px), `sidebar-min-size` and `sidebar-max-size` make the list draggable through KunSplitPane. The `sidebar-resize-end` event is the one to persist from. Without `resizable`, `sidebar-width` works as before.
28
+
3
29
  ## 2.54.0
4
30
 
5
31
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -541,6 +541,9 @@ var zh_CN_default = {
541
541
  clear: "清除",
542
542
  removeOption: "移除 {label}"
543
543
  },
544
+ splitPane: {
545
+ handle: "调整分栏宽度"
546
+ },
544
547
  spoiler: {
545
548
  copyCode: "复制代码",
546
549
  reveal: "剧透内容,点击或按回车显示"
@@ -684,6 +687,25 @@ var normalizeKunMenuSeparators = (entries) => {
684
687
  return out;
685
688
  };
686
689
 
690
+ // src/splitPane.ts
691
+ var resolveKunSplitSize = (raw, { min, max, snapPoints = [], snapThreshold = 8, from }) => {
692
+ const lo = Math.min(min, max);
693
+ const hi = Math.max(min, max);
694
+ const clamped = Math.min(Math.max(raw, lo), hi);
695
+ let best = clamped;
696
+ let bestDistance = Infinity;
697
+ for (const point of snapPoints) {
698
+ if (point < lo || point > hi) continue;
699
+ const distance = Math.abs(point - clamped);
700
+ if (distance <= snapThreshold && distance < bestDistance) {
701
+ best = point;
702
+ bestDistance = distance;
703
+ }
704
+ }
705
+ if (from !== void 0 && Math.sign(best - from) !== Math.sign(clamped - from)) best = clamped;
706
+ return Math.round(best);
707
+ };
708
+
687
709
  // src/random.ts
688
710
  var randomNum = (lowerValue, upperValue) => Math.floor(Math.random() * (upperValue - lowerValue + 1) + lowerValue);
689
711
 
@@ -1749,6 +1771,7 @@ exports.randomNum = randomNum;
1749
1771
  exports.registerKunIcon = registerKunIcon;
1750
1772
  exports.registerKunIcons = registerKunIcons;
1751
1773
  exports.resolveKunShortcut = resolveKunShortcut;
1774
+ exports.resolveKunSplitSize = resolveKunSplitSize;
1752
1775
  exports.resolveRounded = resolveRounded;
1753
1776
  exports.sliceKunChatEntities = sliceKunChatEntities;
1754
1777
  exports.speakKunShortcut = speakKunShortcut;