@suphark/ui 0.45.1 → 0.45.2

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
@@ -2,7 +2,13 @@
2
2
 
3
3
  รูปแบบตาม [Keep a Changelog](https://keepachangelog.com/) · semver: patch = หน้าตา/บั๊ก, minor = component/prop ใหม่, major = เปลี่ยน/ลบ props
4
4
 
5
- ## [0.45.1] — 2026-10-08
5
+ ## [0.45.2] — 2026-10-08
6
+
7
+ ### Fixed
8
+
9
+ - `@suphark/ui/sortable`: ลากรายการเข้ากลุ่มอื่นไปวาง "ใต้" แถวหนึ่ง ระหว่างลากอยู่ถูกที่ แต่ปล่อยแล้วกระโดดไปอยู่ "เหนือ" แถวนั้น (เจ้าของเจอในตัวอย่างโครง `<tbody>`) — ตอนข้ามกลุ่มจัดตำแหน่งก่อน/หลังไว้แล้ว แต่ตอนปล่อย `reorderItems` ย้ายไปแทนที่แถวที่ชี้ซ้ำอีกรอบ · ตอนนี้ถ้าปล่อยตอนยังชี้แถวเดิมที่ข้ามกลุ่มเข้ามา ใช้ตำแหน่งที่จัดไว้เลย
10
+ - showcase: `/components/sortable-list` **เอาตัวอย่างโครง `<tbody>` ต่อกลุ่มออก** — เจ้าของเลือกให้มีรูปแบบเดียว (หัวกลุ่ม + แถวรายการเป็น `<tr>` ใน `<tbody>` เดียวกัน) เพื่อดูแลง่าย
11
+
6
12
 
7
13
  ### Fixed
8
14
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suphark/ui",
3
- "version": "0.45.1",
3
+ "version": "0.45.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Design system กลางของ Suphark apps: shadcn/ui (base-nova, Base UI, Tailwind v4) + shared components + token/ฟอนต์ Noto Sans Thai Looped — ส่งเป็น source ให้แอป Next transpile เอง",
@@ -319,6 +319,9 @@ export function SortableProvider({
319
319
  // กันกระพริบตอนย้ายข้ามกลุ่ม: จำเป้าหมายล่าสุดไว้ใช้ตอนที่ layout กำลังขยับแล้วหาเป้าหมายไม่เจอ
320
320
  const lastOverId = useRef<UniqueIdentifier | null>(null);
321
321
  const movedAcross = useRef(false);
322
+ // เป้าหมายตอนย้ายข้ามกลุ่มครั้งล่าสุด — ตำแหน่งถูกจัดไว้แล้ว (ก่อน/หลังตามครึ่งแถว) ถ้าปล่อยตอนยังชี้ตัวเดิม
323
+ // ห้าม reorderItems ซ้ำ (arrayMove ไปแทนที่ตัวนั้น = วาง "หลัง" กลายเป็น "ก่อน")
324
+ const crossedAt = useRef<UniqueIdentifier | null>(null);
322
325
  const beforeDrag = useRef<SortableOrder | null>(null);
323
326
  // อ่านลำดับล่าสุดตอนปล่อย (onDragOver เปลี่ยนไปหลายรอบแล้ว prop ยังไม่ทัน)
324
327
  const latest = useRef(order);
@@ -626,6 +629,7 @@ export function SortableProvider({
626
629
 
627
630
  function onDragStart({ active }: DragStartEvent) {
628
631
  beforeDrag.current = latest.current;
632
+ crossedAt.current = null;
629
633
  lastOverId.current = null;
630
634
  const kind: SortableKind = kindOf(active.id) === "g" ? "group" : "item";
631
635
  const raw = rawOf(active.id);
@@ -679,6 +683,7 @@ export function SortableProvider({
679
683
  const raw = rawOf(active.id);
680
684
  const apply = (next: SortableOrder) => {
681
685
  if (next === current) return;
686
+ crossedAt.current = over.id;
682
687
  movedAcross.current = true;
683
688
  latest.current = next;
684
689
  onOrderChange(next);
@@ -694,6 +699,8 @@ export function SortableProvider({
694
699
  const from = containerOf(active.id, current);
695
700
  const to = containerOf(over.id, current);
696
701
  if (!from || !to || from === to) {
702
+ // ชี้ตัวอื่นในกลุ่มเดียวกันแล้ว = เรียงต่อแบบปกติ (ไม่ใช่ตำแหน่งที่จัดไว้ตอนข้ามกลุ่ม)
703
+ if (over.id !== crossedAt.current) crossedAt.current = null;
697
704
  updateTarget(active, over, keyboard, pointerY);
698
705
  return;
699
706
  }
@@ -778,7 +785,12 @@ export function SortableProvider({
778
785
  index,
779
786
  );
780
787
  }
781
- } else if (over && kindOf(active.id) === "i" && kindOf(over.id) === "i") {
788
+ } else if (
789
+ over &&
790
+ kindOf(active.id) === "i" &&
791
+ kindOf(over.id) === "i" &&
792
+ over.id !== crossedAt.current
793
+ ) {
782
794
  next = reorderItems(current, rawOf(active.id), rawOf(over.id));
783
795
  }
784
796
  // bulk: ตัวที่เลือกไว้ตัวอื่นตามมารวมที่จุดวางของตัวที่จับ (เรียงตามลำดับเดิม)