@comitor/ui 1.3.0 → 1.3.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.
@@ -5,18 +5,18 @@ import { useId } from "react";
5
5
  import { cn } from "../../lib/cn.js";
6
6
  import { Field, FieldContent, FieldDescription, FieldError, FieldLabel } from "../ui/field.js";
7
7
  const colSpanClasses = {
8
- 1: "col-span-12 md:col-span-1",
9
- 2: "col-span-12 md:col-span-2",
10
- 3: "col-span-12 sm:col-span-6 md:col-span-3",
11
- 4: "col-span-12 sm:col-span-6 md:col-span-4",
12
- 5: "col-span-12 sm:col-span-6 md:col-span-5",
13
- 6: "col-span-12 sm:col-span-6",
14
- 7: "col-span-12 md:col-span-7",
15
- 8: "col-span-12 md:col-span-8",
16
- 9: "col-span-12 md:col-span-9",
17
- 10: "col-span-12 md:col-span-10",
18
- 11: "col-span-12 md:col-span-11",
19
- 12: "col-span-12"
8
+ 1: "col-span-full md:col-span-1",
9
+ 2: "col-span-full md:col-span-2",
10
+ 3: "col-span-full sm:col-span-6 md:col-span-3",
11
+ 4: "col-span-full sm:col-span-6 md:col-span-4",
12
+ 5: "col-span-full sm:col-span-6 md:col-span-5",
13
+ 6: "col-span-full sm:col-span-6",
14
+ 7: "col-span-full md:col-span-7",
15
+ 8: "col-span-full md:col-span-8",
16
+ 9: "col-span-full md:col-span-9",
17
+ 10: "col-span-full md:col-span-10",
18
+ 11: "col-span-full md:col-span-11",
19
+ 12: "col-span-full"
20
20
  };
21
21
  function FormField({
22
22
  label,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/composite/form-field.tsx"],"sourcesContent":["\"use client\";\n\nimport { AlertCircle } from \"lucide-react\";\nimport { type ReactNode, useId } from \"react\";\nimport { cn } from \"../../lib/cn.js\";\nimport { Field, FieldContent, FieldDescription, FieldError, FieldLabel } from \"../ui/field.js\";\n\nexport type FormFieldColSpan = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;\n\n/**\n * Thuộc tính a11y mà `FormField` tiêm xuống control con.\n *\n * Trải nguyên cụm này vào `<Input>`/`<Combobox>`/`<Select>` là control tự có id khớp nhãn,\n * tự báo lỗi và trạng thái bắt buộc — không phải nhớ từng thuộc tính ở mỗi trang.\n */\nexport interface FormFieldControlProps {\n id: string;\n \"aria-invalid\"?: true;\n \"aria-required\"?: true;\n \"aria-describedby\"?: string;\n}\n\nexport interface FormFieldProps {\n label?: ReactNode;\n /** Đánh dấu bắt buộc: vẽ dấu * và phát `aria-required` xuống control */\n required?: boolean;\n /** Mô tả/gợi ý dưới trường — bị ẩn khi có lỗi để không đọc chồng lời */\n description?: ReactNode;\n /** Thông báo lỗi; có giá trị là trường vào trạng thái invalid */\n error?: ReactNode;\n /** id của control — bỏ trống thì tự sinh bằng useId */\n htmlFor?: string;\n /** Số cột chiếm trong lưới 12 cột của `FormSection` (mặc định 12 = cả hàng) */\n colSpan?: FormFieldColSpan;\n orientation?: \"vertical\" | \"horizontal\" | \"responsive\";\n className?: string;\n /**\n * Control của trường. Dạng hàm sẽ nhận `FormFieldControlProps` để trải xuống —\n * dạng node thì app tự lo id/aria (dùng khi control đã tự quản, vd Checkbox có nhãn riêng).\n */\n children: ReactNode | ((control: FormFieldControlProps) => ReactNode);\n}\n\nconst colSpanClasses: Record<FormFieldColSpan, string> = {\n 1: \"col-span-12 md:col-span-1\",\n 2: \"col-span-12 md:col-span-2\",\n 3: \"col-span-12 sm:col-span-6 md:col-span-3\",\n 4: \"col-span-12 sm:col-span-6 md:col-span-4\",\n 5: \"col-span-12 sm:col-span-6 md:col-span-5\",\n 6: \"col-span-12 sm:col-span-6\",\n 7: \"col-span-12 md:col-span-7\",\n 8: \"col-span-12 md:col-span-8\",\n 9: \"col-span-12 md:col-span-9\",\n 10: \"col-span-12 md:col-span-10\",\n 11: \"col-span-12 md:col-span-11\",\n 12: \"col-span-12\"\n};\n\n/**\n * Một trường form: nhãn + control + mô tả/lỗi, đặt trong lưới 12 cột của `FormSection`.\n *\n * KHÔNG tự vẽ input. Nhãn và lỗi uỷ quyền xuống primitive `Field`, còn control do app chọn —\n * nếu composite tự dựng input thì mỗi kiểu control mới (combobox, date range, editor) lại phải\n * mở lại file này — một FormField \"đa năng\" ôm hết mọi loại control sẽ phình ra không có điểm dừng.\n */\nexport function FormField({\n label,\n required = false,\n description,\n error,\n htmlFor,\n colSpan = 12,\n orientation = \"vertical\",\n className,\n children\n}: FormFieldProps) {\n const generatedId = useId();\n const id = htmlFor ?? generatedId;\n const hasError = Boolean(error);\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n const control: FormFieldControlProps = {\n id,\n \"aria-invalid\": hasError ? true : undefined,\n \"aria-required\": required ? true : undefined,\n \"aria-describedby\": hasError ? errorId : description ? descriptionId : undefined\n };\n\n return (\n <Field\n data-slot=\"form-field\"\n data-invalid={hasError || undefined}\n orientation={orientation}\n className={cn(colSpanClasses[colSpan], className)}\n >\n {/*\n Nhãn KHÔNG truyền `className=\"text-sm\"`: `Label` bên dưới đã đặt sẵn `text-sm` nên chuỗi đó\n không mua được gì — mà lại làm mất HAI chiều cao dòng. `cn()` chạy qua tailwind-merge, ở đó\n một utility CỠ CHỮ xoá mọi `leading-*` đứng TRƯỚC nó: `text-sm` nằm cuối chuỗi cắt\n `leading-snug` của `FieldLabel`, rồi cắt tiếp `leading-none` trong base của `Label`. Kết quả\n là thẻ <label> không còn `leading-*` nào.\n */}\n {label && (\n <FieldLabel htmlFor={id}>\n {label}\n {required && (\n // Dấu * chỉ là tín hiệu thị giác — trạng thái bắt buộc đã nằm ở aria-required trên\n // control, để trình đọc màn hình khỏi đọc thừa \"sao\".\n // Bậc ink (7,15:1 light / 6,42:1 dark trên `--card`) chứ không `text-destructive`\n // (bậc NỀN, chỉ 3,53:1 trên `--card` ở dark ✗).\n <span aria-hidden=\"true\" className=\"text-destructive-ink\">\n *\n </span>\n )}\n </FieldLabel>\n )}\n\n <FieldContent>\n {typeof children === \"function\" ? children(control) : children}\n\n {hasError ? (\n <FieldError id={errorId} className=\"flex items-center gap-1.5 text-xs animate-in fade-in slide-in-from-top-1\">\n <AlertCircle aria-hidden=\"true\" className=\"size-3.5 shrink-0\" />\n {error}\n </FieldError>\n ) : (\n description && (\n // `leading-normal` phải VIẾT LẠI sau `text-xs`: cùng cái bẫy tailwind-merge ở nhãn phía\n // trên — `text-xs` xoá `leading-normal` trong base của `FieldDescription` và kéo dòng\n // mô tả từ 1.5 xuống 1rem. Cỡ chữ nhỏ hơn base là CÓ Ý, chiều cao dòng thì không.\n <FieldDescription id={descriptionId} className=\"text-xs leading-normal\">\n {description}\n </FieldDescription>\n )\n )}\n </FieldContent>\n </Field>\n );\n}\n"],"mappings":";AAwGQ,SAOI,KAPJ;AAtGR,SAAS,mBAAmB;AAC5B,SAAyB,aAAa;AACtC,SAAS,UAAU;AACnB,SAAS,OAAO,cAAc,kBAAkB,YAAY,kBAAkB;AAsC9E,MAAM,iBAAmD;AAAA,EACvD,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AASO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAAmB;AACjB,QAAM,cAAc,MAAM;AAC1B,QAAM,KAAK,WAAW;AACtB,QAAM,WAAW,QAAQ,KAAK;AAC9B,QAAM,UAAU,GAAG,EAAE;AACrB,QAAM,gBAAgB,GAAG,EAAE;AAE3B,QAAM,UAAiC;AAAA,IACrC;AAAA,IACA,gBAAgB,WAAW,OAAO;AAAA,IAClC,iBAAiB,WAAW,OAAO;AAAA,IACnC,oBAAoB,WAAW,UAAU,cAAc,gBAAgB;AAAA,EACzE;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,gBAAc,YAAY;AAAA,MAC1B;AAAA,MACA,WAAW,GAAG,eAAe,OAAO,GAAG,SAAS;AAAA,MAS/C;AAAA,iBACC,qBAAC,cAAW,SAAS,IAClB;AAAA;AAAA,UACA;AAAA;AAAA;AAAA;AAAA,UAKC,oBAAC,UAAK,eAAY,QAAO,WAAU,wBAAuB,eAE1D;AAAA,WAEJ;AAAA,QAGF,qBAAC,gBACE;AAAA,iBAAO,aAAa,aAAa,SAAS,OAAO,IAAI;AAAA,UAErD,WACC,qBAAC,cAAW,IAAI,SAAS,WAAU,4EACjC;AAAA,gCAAC,eAAY,eAAY,QAAO,WAAU,qBAAoB;AAAA,YAC7D;AAAA,aACH,IAEA;AAAA;AAAA;AAAA,UAIE,oBAAC,oBAAiB,IAAI,eAAe,WAAU,0BAC5C,uBACH;AAAA,WAGN;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/composite/form-field.tsx"],"sourcesContent":["\"use client\";\n\nimport { AlertCircle } from \"lucide-react\";\nimport { type ReactNode, useId } from \"react\";\nimport { cn } from \"../../lib/cn.js\";\nimport { Field, FieldContent, FieldDescription, FieldError, FieldLabel } from \"../ui/field.js\";\n\nexport type FormFieldColSpan = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;\n\n/**\n * Thuộc tính a11y mà `FormField` tiêm xuống control con.\n *\n * Trải nguyên cụm này vào `<Input>`/`<Combobox>`/`<Select>` là control tự có id khớp nhãn,\n * tự báo lỗi và trạng thái bắt buộc — không phải nhớ từng thuộc tính ở mỗi trang.\n */\nexport interface FormFieldControlProps {\n id: string;\n \"aria-invalid\"?: true;\n \"aria-required\"?: true;\n \"aria-describedby\"?: string;\n}\n\nexport interface FormFieldProps {\n label?: ReactNode;\n /** Đánh dấu bắt buộc: vẽ dấu * và phát `aria-required` xuống control */\n required?: boolean;\n /** Mô tả/gợi ý dưới trường — bị ẩn khi có lỗi để không đọc chồng lời */\n description?: ReactNode;\n /** Thông báo lỗi; có giá trị là trường vào trạng thái invalid */\n error?: ReactNode;\n /** id của control — bỏ trống thì tự sinh bằng useId */\n htmlFor?: string;\n /** Số cột chiếm trong lưới 12 cột của `FormSection` (mặc định 12 = cả hàng) */\n colSpan?: FormFieldColSpan;\n orientation?: \"vertical\" | \"horizontal\" | \"responsive\";\n className?: string;\n /**\n * Control của trường. Dạng hàm sẽ nhận `FormFieldControlProps` để trải xuống —\n * dạng node thì app tự lo id/aria (dùng khi control đã tự quản, vd Checkbox có nhãn riêng).\n */\n children: ReactNode | ((control: FormFieldControlProps) => ReactNode);\n}\n\n/*\n * ⚠ BẬC BASE PHẢI LÀ `col-span-full`, KHÔNG PHẢI `col-span-12`.\n *\n * Hai class này trông tương đương trong lưới 12 cột của `FormSection` — và đúng là tương đương\n * Ở ĐÓ (đo được: cả hai cho trường rộng đủ một hàng). Nhưng chúng biên dịch ra hai thứ KHÁC HẲN:\n * col-span-12 → grid-column: span 12 / span 12 (một phép ĐẾM tương đối)\n * col-span-full → grid-column: 1 / -1 (từ MÉP tới MÉP của lưới)\n *\n * `span 12` trong một `display:grid` KHÔNG khai `grid-cols-*` buộc trình duyệt ĐẺ 11 track NGẦM\n * để chứa cho đủ. `DialogContent` của gói chính là một grid như vậy (`grid ... gap-4 p-6`), nên\n * một `FormField` đặt thẳng trong hộp thoại làm cả hộp vỡ theo HAI cách cùng lúc:\n * - trường THÒ RA ngoài mép hộp: nó rộng bằng (track 1 + 11 khe);\n * - MỌI anh em không span — `DialogHeader`, `DialogFooter` — bị bóp về track 1, nên mô tả\n * xuống dòng sớm và các nút dồn lại.\n * Đo trên bản thật (hộp 432px, vùng nội dung 378px, gap 18px): 12 track `217.43px 0px ×11`,\n * trường 415.43px, thò 37.43px, header co còn 217.43px.\n *\n * `1 / -1` không đếm gì cả nên nó KHÔNG đẻ track: cùng phép đo cho 1 track, cả ba con đều 378px.\n * Và trong `grid-cols-12` thật thì `1 / -1` = cả 12 cột, tức KHÔNG đổi một pixel nào ở đường\n * dùng đúng. Vì vậy đây là bản vá không phá vỡ tương thích, không phải một đánh đổi.\n *\n * ⚠ Các bậc `sm:`/`md:` thì PHẢI giữ `col-span-<số>` — chúng là phép đếm thật trong lưới 12 cột,\n * và `1 / -1` sẽ biến `colSpan={6}` thành cả hàng. Đổi lại, một app khai `colSpan` tường minh\n * BÊN TRONG một grid không phải 12 cột vẫn đẻ track ngầm từ breakpoint đó trở lên — nhưng đó là\n * lựa chọn tường minh của chỗ gọi, không phải cái bẫy im lặng mà mặc định `12` từng giăng ra.\n *\n * `scripts/check-grid-contract.mjs` khoá luật này lại.\n */\nconst colSpanClasses: Record<FormFieldColSpan, string> = {\n 1: \"col-span-full md:col-span-1\",\n 2: \"col-span-full md:col-span-2\",\n 3: \"col-span-full sm:col-span-6 md:col-span-3\",\n 4: \"col-span-full sm:col-span-6 md:col-span-4\",\n 5: \"col-span-full sm:col-span-6 md:col-span-5\",\n 6: \"col-span-full sm:col-span-6\",\n 7: \"col-span-full md:col-span-7\",\n 8: \"col-span-full md:col-span-8\",\n 9: \"col-span-full md:col-span-9\",\n 10: \"col-span-full md:col-span-10\",\n 11: \"col-span-full md:col-span-11\",\n 12: \"col-span-full\"\n};\n\n/**\n * Một trường form: nhãn + control + mô tả/lỗi, đặt trong lưới 12 cột của `FormSection`.\n *\n * KHÔNG tự vẽ input. Nhãn và lỗi uỷ quyền xuống primitive `Field`, còn control do app chọn —\n * nếu composite tự dựng input thì mỗi kiểu control mới (combobox, date range, editor) lại phải\n * mở lại file này — một FormField \"đa năng\" ôm hết mọi loại control sẽ phình ra không có điểm dừng.\n */\nexport function FormField({\n label,\n required = false,\n description,\n error,\n htmlFor,\n colSpan = 12,\n orientation = \"vertical\",\n className,\n children\n}: FormFieldProps) {\n const generatedId = useId();\n const id = htmlFor ?? generatedId;\n const hasError = Boolean(error);\n const errorId = `${id}-error`;\n const descriptionId = `${id}-description`;\n\n const control: FormFieldControlProps = {\n id,\n \"aria-invalid\": hasError ? true : undefined,\n \"aria-required\": required ? true : undefined,\n \"aria-describedby\": hasError ? errorId : description ? descriptionId : undefined\n };\n\n return (\n <Field\n data-slot=\"form-field\"\n data-invalid={hasError || undefined}\n orientation={orientation}\n className={cn(colSpanClasses[colSpan], className)}\n >\n {/*\n Nhãn KHÔNG truyền `className=\"text-sm\"`: `Label` bên dưới đã đặt sẵn `text-sm` nên chuỗi đó\n không mua được gì — mà lại làm mất HAI chiều cao dòng. `cn()` chạy qua tailwind-merge, ở đó\n một utility CỠ CHỮ xoá mọi `leading-*` đứng TRƯỚC nó: `text-sm` nằm cuối chuỗi cắt\n `leading-snug` của `FieldLabel`, rồi cắt tiếp `leading-none` trong base của `Label`. Kết quả\n là thẻ <label> không còn `leading-*` nào.\n */}\n {label && (\n <FieldLabel htmlFor={id}>\n {label}\n {required && (\n // Dấu * chỉ là tín hiệu thị giác — trạng thái bắt buộc đã nằm ở aria-required trên\n // control, để trình đọc màn hình khỏi đọc thừa \"sao\".\n // Bậc ink (7,15:1 light / 6,42:1 dark trên `--card`) chứ không `text-destructive`\n // (bậc NỀN, chỉ 3,53:1 trên `--card` ở dark ✗).\n <span aria-hidden=\"true\" className=\"text-destructive-ink\">\n *\n </span>\n )}\n </FieldLabel>\n )}\n\n <FieldContent>\n {typeof children === \"function\" ? children(control) : children}\n\n {hasError ? (\n <FieldError id={errorId} className=\"flex items-center gap-1.5 text-xs animate-in fade-in slide-in-from-top-1\">\n <AlertCircle aria-hidden=\"true\" className=\"size-3.5 shrink-0\" />\n {error}\n </FieldError>\n ) : (\n description && (\n // `leading-normal` phải VIẾT LẠI sau `text-xs`: cùng cái bẫy tailwind-merge ở nhãn phía\n // trên — `text-xs` xoá `leading-normal` trong base của `FieldDescription` và kéo dòng\n // mô tả từ 1.5 xuống 1rem. Cỡ chữ nhỏ hơn base là CÓ Ý, chiều cao dòng thì không.\n <FieldDescription id={descriptionId} className=\"text-xs leading-normal\">\n {description}\n </FieldDescription>\n )\n )}\n </FieldContent>\n </Field>\n );\n}\n"],"mappings":";AAoIQ,SAOI,KAPJ;AAlIR,SAAS,mBAAmB;AAC5B,SAAyB,aAAa;AACtC,SAAS,UAAU;AACnB,SAAS,OAAO,cAAc,kBAAkB,YAAY,kBAAkB;AAkE9E,MAAM,iBAAmD;AAAA,EACvD,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AASO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,cAAc;AAAA,EACd;AAAA,EACA;AACF,GAAmB;AACjB,QAAM,cAAc,MAAM;AAC1B,QAAM,KAAK,WAAW;AACtB,QAAM,WAAW,QAAQ,KAAK;AAC9B,QAAM,UAAU,GAAG,EAAE;AACrB,QAAM,gBAAgB,GAAG,EAAE;AAE3B,QAAM,UAAiC;AAAA,IACrC;AAAA,IACA,gBAAgB,WAAW,OAAO;AAAA,IAClC,iBAAiB,WAAW,OAAO;AAAA,IACnC,oBAAoB,WAAW,UAAU,cAAc,gBAAgB;AAAA,EACzE;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,gBAAc,YAAY;AAAA,MAC1B;AAAA,MACA,WAAW,GAAG,eAAe,OAAO,GAAG,SAAS;AAAA,MAS/C;AAAA,iBACC,qBAAC,cAAW,SAAS,IAClB;AAAA;AAAA,UACA;AAAA;AAAA;AAAA;AAAA,UAKC,oBAAC,UAAK,eAAY,QAAO,WAAU,wBAAuB,eAE1D;AAAA,WAEJ;AAAA,QAGF,qBAAC,gBACE;AAAA,iBAAO,aAAa,aAAa,SAAS,OAAO,IAAI;AAAA,UAErD,WACC,qBAAC,cAAW,IAAI,SAAS,WAAU,4EACjC;AAAA,gCAAC,eAAY,eAAY,QAAO,WAAU,qBAAoB;AAAA,YAC7D;AAAA,aACH,IAEA;AAAA;AAAA;AAAA,UAIE,oBAAC,oBAAiB,IAAI,eAAe,WAAU,0BAC5C,uBACH;AAAA,WAGN;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -35,6 +35,19 @@ type DialogContentProps = React.ComponentProps<typeof DialogPrimitive.Content> &
35
35
  };
36
36
  declare function DialogContent({ className, children, showCloseButton, size, closeLabel, ...props }: DialogContentProps): React.JSX.Element;
37
37
  type DialogBodyProps = React.ComponentProps<"div">;
38
+ /**
39
+ * Vùng nội dung CUỘN của hộp thoại, giữa header và footer.
40
+ *
41
+ * ⚠ Trước 1.3.2 component này render `<div className={cn(className)} />` — tức KHÔNG LÀM GÌ CẢ,
42
+ * trong khi chính tài liệu của nó (và của `Dialog`) nói nó "tách vùng nội dung cuộn khỏi
43
+ * header/footer". Một component không làm điều nó tự nhận là loại lỗi tệ nhất trong một gói dùng
44
+ * chung: chỗ gọi đã làm ĐÚNG rồi mà vẫn hỏng, nên người ta đi tìm nguyên nhân ở app.
45
+ *
46
+ * ⚠ `flex-auto` chứ không `flex-1`: `flex-1` là `flex: 1 1 0%`, tức lấy 0 làm cỡ cơ sở. `flex-auto`
47
+ * (`1 1 auto`) lấy cỡ NỘI DUNG làm cơ sở, nên hộp thoại ngắn vẫn ôm sát nội dung thay vì bị kéo
48
+ * giãn. `min-h-0` là mảnh bắt buộc còn lại — thiếu nó, `min-height: auto` mặc định của flex item
49
+ * giữ nguyên chiều cao nội dung và không gì cuộn được.
50
+ */
38
51
  declare function DialogBody({ className, ...props }: DialogBodyProps): React.JSX.Element;
39
52
  type DialogHeaderProps = React.ComponentProps<"div">;
40
53
  declare function DialogHeader({ className, ...props }: DialogHeaderProps): React.JSX.Element;
@@ -49,7 +49,23 @@ function DialogContent({
49
49
  {
50
50
  "data-slot": "dialog-content",
51
51
  className: cn(
52
- "bg-card data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl border border-border p-6 shadow-overlay duration-200",
52
+ /*
53
+ * ⚠ `max-h` + `overflow-y-auto` là BẮT BUỘC, không phải trang trí.
54
+ *
55
+ * Hộp thoại là `position: fixed` căn giữa bằng `translate-y-[-50%]`. Không có trần
56
+ * chiều cao thì một biểu mẫu dài tràn ra CẢ HAI phía màn hình — và vì nó `fixed` nên
57
+ * trang không cuộn nó được: phần đầu và phần cuối (kể cả nút Gửi) trở nên KHÔNG THỂ
58
+ * chạm tới. Đo được ở hộp "Mời thành viên": nội dung 812px trong khung nhìn 613px.
59
+ *
60
+ * ⚠ `flex flex-col` chứ KHÔNG phải `grid`. Với `grid`, mọi hàng là `auto` nên không
61
+ * hàng nào chịu co lại — muốn `DialogBody` cuộn thì phải khai `grid-template-rows`,
62
+ * mà làm vậy là ghim thứ tự con (header phải là con thứ nhất). Flex cho `DialogBody`
63
+ * co lại theo `min-h-0` bất kể nó nằm ở đâu.
64
+ *
65
+ * `overflow-y-auto` ở đây là LƯỚI AN TOÀN cho hộp thoại KHÔNG dùng `DialogBody`:
66
+ * có `DialogBody` thì chính nó cuộn và thanh cuộn ngoài này không bao giờ xuất hiện.
67
+ */
68
+ "bg-card data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 flex max-h-[calc(100dvh-2rem)] w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] flex-col gap-4 overflow-y-auto rounded-xl border border-border p-6 shadow-overlay duration-200",
53
69
  dialogSizeStyles[size],
54
70
  className
55
71
  ),
@@ -73,7 +89,7 @@ function DialogContent({
73
89
  ] });
74
90
  }
75
91
  function DialogBody({ className, ...props }) {
76
- return /* @__PURE__ */ jsx("div", { "data-slot": "dialog-body", className: cn(className), ...props });
92
+ return /* @__PURE__ */ jsx("div", { "data-slot": "dialog-body", className: cn("min-h-0 flex-auto overflow-y-auto", className), ...props });
77
93
  }
78
94
  function DialogHeader({ className, ...props }) {
79
95
  return /* @__PURE__ */ jsx(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ui/dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { XIcon } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * Dialog — hộp thoại modal (Radix Dialog), style new-york + token Comitor.\n *\n * Khác bản shadcn gốc: có prop `size` (sm/md/lg/xl) và `DialogBody` để tách vùng\n * nội dung cuộn khỏi header/footer.\n */\n\nexport type DialogProps = React.ComponentProps<typeof DialogPrimitive.Root>;\n\nfunction Dialog({ ...props }: DialogProps) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nexport type DialogTriggerProps = React.ComponentProps<typeof DialogPrimitive.Trigger>;\n\nfunction DialogTrigger({ ...props }: DialogTriggerProps) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nexport type DialogPortalProps = React.ComponentProps<typeof DialogPrimitive.Portal>;\n\nfunction DialogPortal({ ...props }: DialogPortalProps) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nexport type DialogCloseProps = React.ComponentProps<typeof DialogPrimitive.Close>;\n\nfunction DialogClose({ ...props }: DialogCloseProps) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nexport type DialogOverlayProps = React.ComponentProps<typeof DialogPrimitive.Overlay>;\n\nfunction DialogOverlay({ className, ...props }: DialogOverlayProps) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-ink/60 dark:bg-ink/80 backdrop-blur-sm\",\n className\n )}\n {...props}\n />\n );\n}\n\n/** Bề ngang tối đa theo cỡ — khai tĩnh để Tailwind quét được (không sinh class động). */\nconst dialogSizeStyles = {\n sm: \"sm:max-w-sm\",\n md: \"sm:max-w-md\",\n lg: \"sm:max-w-lg\",\n xl: \"sm:max-w-xl\"\n} as const;\n\nexport type DialogSize = keyof typeof dialogSizeStyles;\n\nexport type DialogContentProps = React.ComponentProps<typeof DialogPrimitive.Content> & {\n /** Hiện nút đóng ở góc phải trên. Mặc định true. */\n showCloseButton?: boolean;\n /** Cỡ hộp thoại theo breakpoint sm trở lên. Mặc định \"md\". */\n size?: DialogSize;\n /** Nhãn cho trình đọc màn hình của nút đóng. Mặc định \"Đóng\". */\n closeLabel?: string;\n};\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n size = \"md\",\n closeLabel = \"Đóng\",\n ...props\n}: DialogContentProps) {\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n \"bg-card data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl border border-border p-6 shadow-overlay duration-200\",\n dialogSizeStyles[size],\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className=\"absolute top-4 right-4 rounded-md p-1 text-muted-foreground transition-colors duration-150 ease-out hover:text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\"\n >\n <XIcon />\n <span className=\"sr-only\">{closeLabel}</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n );\n}\n\nexport type DialogBodyProps = React.ComponentProps<\"div\">;\n\nfunction DialogBody({ className, ...props }: DialogBodyProps) {\n return <div data-slot=\"dialog-body\" className={cn(className)} {...props} />;\n}\n\nexport type DialogHeaderProps = React.ComponentProps<\"div\">;\n\nfunction DialogHeader({ className, ...props }: DialogHeaderProps) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogFooterProps = React.ComponentProps<\"div\">;\n\nfunction DialogFooter({ className, ...props }: DialogFooterProps) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogTitleProps = React.ComponentProps<typeof DialogPrimitive.Title>;\n\nfunction DialogTitle({ className, ...props }: DialogTitleProps) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg font-semibold text-foreground\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogDescriptionProps = React.ComponentProps<typeof DialogPrimitive.Description>;\n\nfunction DialogDescription({ className, ...props }: DialogDescriptionProps) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogBody,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger\n};\n"],"mappings":";AAiBS,cA6EC,YA7ED;AAfT,YAAY,qBAAqB;AACjC,SAAS,aAAa;AAEtB,SAAS,UAAU;AAWnB,SAAS,OAAO,EAAE,GAAG,MAAM,GAAgB;AACzC,SAAO,oBAAC,gBAAgB,MAAhB,EAAqB,aAAU,UAAU,GAAG,OAAO;AAC7D;AAIA,SAAS,cAAc,EAAE,GAAG,MAAM,GAAuB;AACvD,SAAO,oBAAC,gBAAgB,SAAhB,EAAwB,aAAU,kBAAkB,GAAG,OAAO;AACxE;AAIA,SAAS,aAAa,EAAE,GAAG,MAAM,GAAsB;AACrD,SAAO,oBAAC,gBAAgB,QAAhB,EAAuB,aAAU,iBAAiB,GAAG,OAAO;AACtE;AAIA,SAAS,YAAY,EAAE,GAAG,MAAM,GAAqB;AACnD,SAAO,oBAAC,gBAAgB,OAAhB,EAAsB,aAAU,gBAAgB,GAAG,OAAO;AACpE;AAIA,SAAS,cAAc,EAAE,WAAW,GAAG,MAAM,GAAuB;AAClE,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAGA,MAAM,mBAAmB;AAAA,EACvB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAaA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB,OAAO;AAAA,EACP,aAAa;AAAA,EACb,GAAG;AACL,GAAuB;AACrB,SACE,qBAAC,gBAAa,aAAU,iBACtB;AAAA,wBAAC,iBAAc;AAAA,IACf;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,aAAU;AAAA,QACV,WAAW;AAAA,UACT;AAAA,UACA,iBAAiB,IAAI;AAAA,UACrB;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,UACA,mBACC;AAAA,YAAC,gBAAgB;AAAA,YAAhB;AAAA,cACC,aAAU;AAAA,cACV,WAAU;AAAA,cAEV;AAAA,oCAAC,SAAM;AAAA,gBACP,oBAAC,UAAK,WAAU,WAAW,sBAAW;AAAA;AAAA;AAAA,UACxC;AAAA;AAAA;AAAA,IAEJ;AAAA,KACF;AAEJ;AAIA,SAAS,WAAW,EAAE,WAAW,GAAG,MAAM,GAAoB;AAC5D,SAAO,oBAAC,SAAI,aAAU,eAAc,WAAW,GAAG,SAAS,GAAI,GAAG,OAAO;AAC3E;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,gDAAgD,SAAS;AAAA,MACtE,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,0DAA0D,SAAS;AAAA,MAChF,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,yCAAyC,SAAS;AAAA,MAC/D,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,kBAAkB,EAAE,WAAW,GAAG,MAAM,GAA2B;AAC1E,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/ui/dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport { XIcon } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * Dialog — hộp thoại modal (Radix Dialog), style new-york + token Comitor.\n *\n * Khác bản shadcn gốc: có prop `size` (sm/md/lg/xl) và `DialogBody` để tách vùng\n * nội dung cuộn khỏi header/footer.\n */\n\nexport type DialogProps = React.ComponentProps<typeof DialogPrimitive.Root>;\n\nfunction Dialog({ ...props }: DialogProps) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nexport type DialogTriggerProps = React.ComponentProps<typeof DialogPrimitive.Trigger>;\n\nfunction DialogTrigger({ ...props }: DialogTriggerProps) {\n return <DialogPrimitive.Trigger data-slot=\"dialog-trigger\" {...props} />;\n}\n\nexport type DialogPortalProps = React.ComponentProps<typeof DialogPrimitive.Portal>;\n\nfunction DialogPortal({ ...props }: DialogPortalProps) {\n return <DialogPrimitive.Portal data-slot=\"dialog-portal\" {...props} />;\n}\n\nexport type DialogCloseProps = React.ComponentProps<typeof DialogPrimitive.Close>;\n\nfunction DialogClose({ ...props }: DialogCloseProps) {\n return <DialogPrimitive.Close data-slot=\"dialog-close\" {...props} />;\n}\n\nexport type DialogOverlayProps = React.ComponentProps<typeof DialogPrimitive.Overlay>;\n\nfunction DialogOverlay({ className, ...props }: DialogOverlayProps) {\n return (\n <DialogPrimitive.Overlay\n data-slot=\"dialog-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-ink/60 dark:bg-ink/80 backdrop-blur-sm\",\n className\n )}\n {...props}\n />\n );\n}\n\n/** Bề ngang tối đa theo cỡ — khai tĩnh để Tailwind quét được (không sinh class động). */\nconst dialogSizeStyles = {\n sm: \"sm:max-w-sm\",\n md: \"sm:max-w-md\",\n lg: \"sm:max-w-lg\",\n xl: \"sm:max-w-xl\"\n} as const;\n\nexport type DialogSize = keyof typeof dialogSizeStyles;\n\nexport type DialogContentProps = React.ComponentProps<typeof DialogPrimitive.Content> & {\n /** Hiện nút đóng ở góc phải trên. Mặc định true. */\n showCloseButton?: boolean;\n /** Cỡ hộp thoại theo breakpoint sm trở lên. Mặc định \"md\". */\n size?: DialogSize;\n /** Nhãn cho trình đọc màn hình của nút đóng. Mặc định \"Đóng\". */\n closeLabel?: string;\n};\n\nfunction DialogContent({\n className,\n children,\n showCloseButton = true,\n size = \"md\",\n closeLabel = \"Đóng\",\n ...props\n}: DialogContentProps) {\n return (\n <DialogPortal data-slot=\"dialog-portal\">\n <DialogOverlay />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n /*\n * ⚠ `max-h` + `overflow-y-auto` là BẮT BUỘC, không phải trang trí.\n *\n * Hộp thoại là `position: fixed` căn giữa bằng `translate-y-[-50%]`. Không có trần\n * chiều cao thì một biểu mẫu dài tràn ra CẢ HAI phía màn hình — và vì nó `fixed` nên\n * trang không cuộn nó được: phần đầu và phần cuối (kể cả nút Gửi) trở nên KHÔNG THỂ\n * chạm tới. Đo được ở hộp \"Mời thành viên\": nội dung 812px trong khung nhìn 613px.\n *\n * ⚠ `flex flex-col` chứ KHÔNG phải `grid`. Với `grid`, mọi hàng là `auto` nên không\n * hàng nào chịu co lại — muốn `DialogBody` cuộn thì phải khai `grid-template-rows`,\n * mà làm vậy là ghim thứ tự con (header phải là con thứ nhất). Flex cho `DialogBody`\n * co lại theo `min-h-0` bất kể nó nằm ở đâu.\n *\n * `overflow-y-auto` ở đây là LƯỚI AN TOÀN cho hộp thoại KHÔNG dùng `DialogBody`:\n * có `DialogBody` thì chính nó cuộn và thanh cuộn ngoài này không bao giờ xuất hiện.\n */\n \"bg-card data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 flex max-h-[calc(100dvh-2rem)] w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] flex-col gap-4 overflow-y-auto rounded-xl border border-border p-6 shadow-overlay duration-200\",\n dialogSizeStyles[size],\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close\n data-slot=\"dialog-close\"\n className=\"absolute top-4 right-4 rounded-md p-1 text-muted-foreground transition-colors duration-150 ease-out hover:text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\"\n >\n <XIcon />\n <span className=\"sr-only\">{closeLabel}</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPortal>\n );\n}\n\nexport type DialogBodyProps = React.ComponentProps<\"div\">;\n\n/**\n * Vùng nội dung CUỘN của hộp thoại, giữa header và footer.\n *\n * ⚠ Trước 1.3.2 component này render `<div className={cn(className)} />` — tức KHÔNG LÀM GÌ CẢ,\n * trong khi chính tài liệu của nó (và của `Dialog`) nói nó \"tách vùng nội dung cuộn khỏi\n * header/footer\". Một component không làm điều nó tự nhận là loại lỗi tệ nhất trong một gói dùng\n * chung: chỗ gọi đã làm ĐÚNG rồi mà vẫn hỏng, nên người ta đi tìm nguyên nhân ở app.\n *\n * ⚠ `flex-auto` chứ không `flex-1`: `flex-1` là `flex: 1 1 0%`, tức lấy 0 làm cỡ cơ sở. `flex-auto`\n * (`1 1 auto`) lấy cỡ NỘI DUNG làm cơ sở, nên hộp thoại ngắn vẫn ôm sát nội dung thay vì bị kéo\n * giãn. `min-h-0` là mảnh bắt buộc còn lại — thiếu nó, `min-height: auto` mặc định của flex item\n * giữ nguyên chiều cao nội dung và không gì cuộn được.\n */\nfunction DialogBody({ className, ...props }: DialogBodyProps) {\n return <div data-slot=\"dialog-body\" className={cn(\"min-h-0 flex-auto overflow-y-auto\", className)} {...props} />;\n}\n\nexport type DialogHeaderProps = React.ComponentProps<\"div\">;\n\nfunction DialogHeader({ className, ...props }: DialogHeaderProps) {\n return (\n <div\n data-slot=\"dialog-header\"\n className={cn(\"flex flex-col gap-2 text-center sm:text-left\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogFooterProps = React.ComponentProps<\"div\">;\n\nfunction DialogFooter({ className, ...props }: DialogFooterProps) {\n return (\n <div\n data-slot=\"dialog-footer\"\n className={cn(\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogTitleProps = React.ComponentProps<typeof DialogPrimitive.Title>;\n\nfunction DialogTitle({ className, ...props }: DialogTitleProps) {\n return (\n <DialogPrimitive.Title\n data-slot=\"dialog-title\"\n className={cn(\"text-lg font-semibold text-foreground\", className)}\n {...props}\n />\n );\n}\n\nexport type DialogDescriptionProps = React.ComponentProps<typeof DialogPrimitive.Description>;\n\nfunction DialogDescription({ className, ...props }: DialogDescriptionProps) {\n return (\n <DialogPrimitive.Description\n data-slot=\"dialog-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Dialog,\n DialogBody,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger\n};\n"],"mappings":";AAiBS,cA6FC,YA7FD;AAfT,YAAY,qBAAqB;AACjC,SAAS,aAAa;AAEtB,SAAS,UAAU;AAWnB,SAAS,OAAO,EAAE,GAAG,MAAM,GAAgB;AACzC,SAAO,oBAAC,gBAAgB,MAAhB,EAAqB,aAAU,UAAU,GAAG,OAAO;AAC7D;AAIA,SAAS,cAAc,EAAE,GAAG,MAAM,GAAuB;AACvD,SAAO,oBAAC,gBAAgB,SAAhB,EAAwB,aAAU,kBAAkB,GAAG,OAAO;AACxE;AAIA,SAAS,aAAa,EAAE,GAAG,MAAM,GAAsB;AACrD,SAAO,oBAAC,gBAAgB,QAAhB,EAAuB,aAAU,iBAAiB,GAAG,OAAO;AACtE;AAIA,SAAS,YAAY,EAAE,GAAG,MAAM,GAAqB;AACnD,SAAO,oBAAC,gBAAgB,OAAhB,EAAsB,aAAU,gBAAgB,GAAG,OAAO;AACpE;AAIA,SAAS,cAAc,EAAE,WAAW,GAAG,MAAM,GAAuB;AAClE,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAGA,MAAM,mBAAmB;AAAA,EACvB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAaA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA,kBAAkB;AAAA,EAClB,OAAO;AAAA,EACP,aAAa;AAAA,EACb,GAAG;AACL,GAAuB;AACrB,SACE,qBAAC,gBAAa,aAAU,iBACtB;AAAA,wBAAC,iBAAc;AAAA,IACf;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,aAAU;AAAA,QACV,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAiBT;AAAA,UACA,iBAAiB,IAAI;AAAA,UACrB;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,UACA,mBACC;AAAA,YAAC,gBAAgB;AAAA,YAAhB;AAAA,cACC,aAAU;AAAA,cACV,WAAU;AAAA,cAEV;AAAA,oCAAC,SAAM;AAAA,gBACP,oBAAC,UAAK,WAAU,WAAW,sBAAW;AAAA;AAAA;AAAA,UACxC;AAAA;AAAA;AAAA,IAEJ;AAAA,KACF;AAEJ;AAiBA,SAAS,WAAW,EAAE,WAAW,GAAG,MAAM,GAAoB;AAC5D,SAAO,oBAAC,SAAI,aAAU,eAAc,WAAW,GAAG,qCAAqC,SAAS,GAAI,GAAG,OAAO;AAChH;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,gDAAgD,SAAS;AAAA,MACtE,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,0DAA0D,SAAS;AAAA,MAChF,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,yCAAyC,SAAS;AAAA,MAC/D,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,kBAAkB,EAAE,WAAW,GAAG,MAAM,GAA2B;AAC1E,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
@@ -35,7 +35,12 @@ function DrawerContent({ className, children, ...props }) {
35
35
  {
36
36
  "data-slot": "drawer-content",
37
37
  className: cn(
38
- "group/drawer-content bg-background fixed z-50 flex h-auto flex-col",
38
+ /*
39
+ * `overflow-y-auto`: `max-h-[80vh]` ở hai hướng trên/dưới đặt trần chiều cao nhưng
40
+ * KHÔNG có gì cuộn phần vượt trần — nội dung dài bị cắt im lặng. Cùng lỗi với
41
+ * `DialogContent` trước 1.3.2.
42
+ */
43
+ "group/drawer-content bg-background fixed z-50 flex h-auto flex-col overflow-y-auto",
39
44
  "data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b",
40
45
  "data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t",
41
46
  "data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ui/drawer.tsx"],"sourcesContent":["\"use client\";\n\nimport type * as React from \"react\";\nimport { Drawer as DrawerPrimitive } from \"vaul\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * Drawer — panel kéo-thả (vaul), có quán tính và tay cầm kéo như app di động.\n *\n * Khác `Sheet` (Radix Dialog, trượt cứng): Drawer cho phép người dùng vuốt để đóng,\n * hợp với màn hình cảm ứng. Hướng đặt bằng prop `direction` của vaul —\n * style bám theo thuộc tính `data-vaul-drawer-direction` mà vaul tự gắn.\n */\n\nexport type DrawerProps = React.ComponentProps<typeof DrawerPrimitive.Root>;\n\nfunction Drawer({ ...props }: DrawerProps) {\n return <DrawerPrimitive.Root data-slot=\"drawer\" {...props} />;\n}\n\nexport type DrawerTriggerProps = React.ComponentProps<typeof DrawerPrimitive.Trigger>;\n\nfunction DrawerTrigger({ ...props }: DrawerTriggerProps) {\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />;\n}\n\nexport type DrawerPortalProps = React.ComponentProps<typeof DrawerPrimitive.Portal>;\n\nfunction DrawerPortal({ ...props }: DrawerPortalProps) {\n return <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props} />;\n}\n\nexport type DrawerCloseProps = React.ComponentProps<typeof DrawerPrimitive.Close>;\n\nfunction DrawerClose({ ...props }: DrawerCloseProps) {\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />;\n}\n\nexport type DrawerOverlayProps = React.ComponentProps<typeof DrawerPrimitive.Overlay>;\n\nfunction DrawerOverlay({ className, ...props }: DrawerOverlayProps) {\n return (\n <DrawerPrimitive.Overlay\n data-slot=\"drawer-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-ink/60 dark:bg-ink/80 backdrop-blur-sm\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type DrawerContentProps = React.ComponentProps<typeof DrawerPrimitive.Content>;\n\nfunction DrawerContent({ className, children, ...props }: DrawerContentProps) {\n return (\n <DrawerPortal data-slot=\"drawer-portal\">\n <DrawerOverlay />\n <DrawerPrimitive.Content\n data-slot=\"drawer-content\"\n className={cn(\n \"group/drawer-content bg-background fixed z-50 flex h-auto flex-col\",\n \"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b\",\n \"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t\",\n \"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm\",\n \"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm\",\n className\n )}\n {...props}\n >\n {/*\n Tay cầm kéo — chỉ hiện khi drawer trượt từ đáy lên.\n Màu `--control-edge`, KHÔNG phải `--muted`: mảng `bg-*` này CHÍNH LÀ hình dạng của dấu\n duy nhất nói \"kéo ở đây\", nên nó chịu ngưỡng 3:1 (WCAG 1.4.11) chứ không phải là một\n bề mặt. `bg-muted` trên `bg-background` của DrawerContent chỉ 1,07:1 (light) · 1,17:1\n (dark) — coi như không hiện. `bg-control-edge`: 3,83:1 (light) · 4,94:1 (dark) ✓\n */}\n <div className=\"bg-control-edge mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block\" />\n {children}\n </DrawerPrimitive.Content>\n </DrawerPortal>\n );\n}\n\nexport type DrawerHeaderProps = React.ComponentProps<\"div\">;\n\nfunction DrawerHeader({ className, ...props }: DrawerHeaderProps) {\n return (\n <div\n data-slot=\"drawer-header\"\n className={cn(\n \"flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type DrawerFooterProps = React.ComponentProps<\"div\">;\n\nfunction DrawerFooter({ className, ...props }: DrawerFooterProps) {\n return <div data-slot=\"drawer-footer\" className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)} {...props} />;\n}\n\nexport type DrawerTitleProps = React.ComponentProps<typeof DrawerPrimitive.Title>;\n\nfunction DrawerTitle({ className, ...props }: DrawerTitleProps) {\n return (\n <DrawerPrimitive.Title\n data-slot=\"drawer-title\"\n className={cn(\"text-foreground font-semibold\", className)}\n {...props}\n />\n );\n}\n\nexport type DrawerDescriptionProps = React.ComponentProps<typeof DrawerPrimitive.Description>;\n\nfunction DrawerDescription({ className, ...props }: DrawerDescriptionProps) {\n return (\n <DrawerPrimitive.Description\n data-slot=\"drawer-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Drawer,\n DrawerClose,\n DrawerContent,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerOverlay,\n DrawerPortal,\n DrawerTitle,\n DrawerTrigger\n};\n"],"mappings":";AAiBS,cA0CH,YA1CG;AAdT,SAAS,UAAU,uBAAuB;AAC1C,SAAS,UAAU;AAYnB,SAAS,OAAO,EAAE,GAAG,MAAM,GAAgB;AACzC,SAAO,oBAAC,gBAAgB,MAAhB,EAAqB,aAAU,UAAU,GAAG,OAAO;AAC7D;AAIA,SAAS,cAAc,EAAE,GAAG,MAAM,GAAuB;AACvD,SAAO,oBAAC,gBAAgB,SAAhB,EAAwB,aAAU,kBAAkB,GAAG,OAAO;AACxE;AAIA,SAAS,aAAa,EAAE,GAAG,MAAM,GAAsB;AACrD,SAAO,oBAAC,gBAAgB,QAAhB,EAAuB,aAAU,iBAAiB,GAAG,OAAO;AACtE;AAIA,SAAS,YAAY,EAAE,GAAG,MAAM,GAAqB;AACnD,SAAO,oBAAC,gBAAgB,OAAhB,EAAsB,aAAU,gBAAgB,GAAG,OAAO;AACpE;AAIA,SAAS,cAAc,EAAE,WAAW,GAAG,MAAM,GAAuB;AAClE,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,cAAc,EAAE,WAAW,UAAU,GAAG,MAAM,GAAuB;AAC5E,SACE,qBAAC,gBAAa,aAAU,iBACtB;AAAA,wBAAC,iBAAc;AAAA,IACf;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,aAAU;AAAA,QACV,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QASJ;AAAA,8BAAC,SAAI,WAAU,0IAAyI;AAAA,UACvJ;AAAA;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SAAO,oBAAC,SAAI,aAAU,iBAAgB,WAAW,GAAG,mCAAmC,SAAS,GAAI,GAAG,OAAO;AAChH;AAIA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,kBAAkB,EAAE,WAAW,GAAG,MAAM,GAA2B;AAC1E,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/ui/drawer.tsx"],"sourcesContent":["\"use client\";\n\nimport type * as React from \"react\";\nimport { Drawer as DrawerPrimitive } from \"vaul\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * Drawer — panel kéo-thả (vaul), có quán tính và tay cầm kéo như app di động.\n *\n * Khác `Sheet` (Radix Dialog, trượt cứng): Drawer cho phép người dùng vuốt để đóng,\n * hợp với màn hình cảm ứng. Hướng đặt bằng prop `direction` của vaul —\n * style bám theo thuộc tính `data-vaul-drawer-direction` mà vaul tự gắn.\n */\n\nexport type DrawerProps = React.ComponentProps<typeof DrawerPrimitive.Root>;\n\nfunction Drawer({ ...props }: DrawerProps) {\n return <DrawerPrimitive.Root data-slot=\"drawer\" {...props} />;\n}\n\nexport type DrawerTriggerProps = React.ComponentProps<typeof DrawerPrimitive.Trigger>;\n\nfunction DrawerTrigger({ ...props }: DrawerTriggerProps) {\n return <DrawerPrimitive.Trigger data-slot=\"drawer-trigger\" {...props} />;\n}\n\nexport type DrawerPortalProps = React.ComponentProps<typeof DrawerPrimitive.Portal>;\n\nfunction DrawerPortal({ ...props }: DrawerPortalProps) {\n return <DrawerPrimitive.Portal data-slot=\"drawer-portal\" {...props} />;\n}\n\nexport type DrawerCloseProps = React.ComponentProps<typeof DrawerPrimitive.Close>;\n\nfunction DrawerClose({ ...props }: DrawerCloseProps) {\n return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />;\n}\n\nexport type DrawerOverlayProps = React.ComponentProps<typeof DrawerPrimitive.Overlay>;\n\nfunction DrawerOverlay({ className, ...props }: DrawerOverlayProps) {\n return (\n <DrawerPrimitive.Overlay\n data-slot=\"drawer-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-ink/60 dark:bg-ink/80 backdrop-blur-sm\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type DrawerContentProps = React.ComponentProps<typeof DrawerPrimitive.Content>;\n\nfunction DrawerContent({ className, children, ...props }: DrawerContentProps) {\n return (\n <DrawerPortal data-slot=\"drawer-portal\">\n <DrawerOverlay />\n <DrawerPrimitive.Content\n data-slot=\"drawer-content\"\n className={cn(\n /*\n * `overflow-y-auto`: `max-h-[80vh]` ở hai hướng trên/dưới đặt trần chiều cao nhưng\n * KHÔNG có gì cuộn phần vượt trần — nội dung dài bị cắt im lặng. Cùng lỗi với\n * `DialogContent` trước 1.3.2.\n */\n \"group/drawer-content bg-background fixed z-50 flex h-auto flex-col overflow-y-auto\",\n \"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b\",\n \"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t\",\n \"data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm\",\n \"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=left]:sm:max-w-sm\",\n className\n )}\n {...props}\n >\n {/*\n Tay cầm kéo — chỉ hiện khi drawer trượt từ đáy lên.\n Màu `--control-edge`, KHÔNG phải `--muted`: mảng `bg-*` này CHÍNH LÀ hình dạng của dấu\n duy nhất nói \"kéo ở đây\", nên nó chịu ngưỡng 3:1 (WCAG 1.4.11) chứ không phải là một\n bề mặt. `bg-muted` trên `bg-background` của DrawerContent chỉ 1,07:1 (light) · 1,17:1\n (dark) — coi như không hiện. `bg-control-edge`: 3,83:1 (light) · 4,94:1 (dark) ✓\n */}\n <div className=\"bg-control-edge mx-auto mt-4 hidden h-2 w-[100px] shrink-0 rounded-full group-data-[vaul-drawer-direction=bottom]/drawer-content:block\" />\n {children}\n </DrawerPrimitive.Content>\n </DrawerPortal>\n );\n}\n\nexport type DrawerHeaderProps = React.ComponentProps<\"div\">;\n\nfunction DrawerHeader({ className, ...props }: DrawerHeaderProps) {\n return (\n <div\n data-slot=\"drawer-header\"\n className={cn(\n \"flex flex-col gap-0.5 p-4 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:gap-1.5 md:text-left\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type DrawerFooterProps = React.ComponentProps<\"div\">;\n\nfunction DrawerFooter({ className, ...props }: DrawerFooterProps) {\n return <div data-slot=\"drawer-footer\" className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)} {...props} />;\n}\n\nexport type DrawerTitleProps = React.ComponentProps<typeof DrawerPrimitive.Title>;\n\nfunction DrawerTitle({ className, ...props }: DrawerTitleProps) {\n return (\n <DrawerPrimitive.Title\n data-slot=\"drawer-title\"\n className={cn(\"text-foreground font-semibold\", className)}\n {...props}\n />\n );\n}\n\nexport type DrawerDescriptionProps = React.ComponentProps<typeof DrawerPrimitive.Description>;\n\nfunction DrawerDescription({ className, ...props }: DrawerDescriptionProps) {\n return (\n <DrawerPrimitive.Description\n data-slot=\"drawer-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Drawer,\n DrawerClose,\n DrawerContent,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerOverlay,\n DrawerPortal,\n DrawerTitle,\n DrawerTrigger\n};\n"],"mappings":";AAiBS,cA0CH,YA1CG;AAdT,SAAS,UAAU,uBAAuB;AAC1C,SAAS,UAAU;AAYnB,SAAS,OAAO,EAAE,GAAG,MAAM,GAAgB;AACzC,SAAO,oBAAC,gBAAgB,MAAhB,EAAqB,aAAU,UAAU,GAAG,OAAO;AAC7D;AAIA,SAAS,cAAc,EAAE,GAAG,MAAM,GAAuB;AACvD,SAAO,oBAAC,gBAAgB,SAAhB,EAAwB,aAAU,kBAAkB,GAAG,OAAO;AACxE;AAIA,SAAS,aAAa,EAAE,GAAG,MAAM,GAAsB;AACrD,SAAO,oBAAC,gBAAgB,QAAhB,EAAuB,aAAU,iBAAiB,GAAG,OAAO;AACtE;AAIA,SAAS,YAAY,EAAE,GAAG,MAAM,GAAqB;AACnD,SAAO,oBAAC,gBAAgB,OAAhB,EAAsB,aAAU,gBAAgB,GAAG,OAAO;AACpE;AAIA,SAAS,cAAc,EAAE,WAAW,GAAG,MAAM,GAAuB;AAClE,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,cAAc,EAAE,WAAW,UAAU,GAAG,MAAM,GAAuB;AAC5E,SACE,qBAAC,gBAAa,aAAU,iBACtB;AAAA,wBAAC,iBAAc;AAAA,IACf;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,aAAU;AAAA,QACV,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAMT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QASJ;AAAA,8BAAC,SAAI,WAAU,0IAAyI;AAAA,UACvJ;AAAA;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SAAO,oBAAC,SAAI,aAAU,iBAAgB,WAAW,GAAG,mCAAmC,SAAS,GAAI,GAAG,OAAO;AAChH;AAIA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,kBAAkB,EAAE,WAAW,GAAG,MAAM,GAA2B;AAC1E,SACE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
@@ -36,7 +36,12 @@ function SheetContent({ className, children, side = "right", closeLabel = "\u011
36
36
  {
37
37
  "data-slot": "sheet-content",
38
38
  className: cn(
39
- "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-overlay transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
39
+ /*
40
+ * `overflow-y-auto`: cùng lỗi với `DialogContent` trước 1.3.2 — `position: fixed`,
41
+ * `h-full`, mà không có `overflow` nào, nên nội dung dài hơn khung nhìn bị CẮT và
42
+ * không cuộn được. `SheetFooter` mang `mt-auto` nên nó vẫn dính đáy khi nội dung ngắn.
43
+ */
44
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 overflow-y-auto shadow-overlay transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
40
45
  side === "right" && "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
41
46
  side === "left" && "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
42
47
  side === "top" && "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ui/sheet.tsx"],"sourcesContent":["\"use client\";\n\nimport * as SheetPrimitive from \"@radix-ui/react-dialog\";\nimport { XIcon } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * Sheet — panel trượt từ cạnh màn hình (dựng trên Radix Dialog).\n *\n * Dùng cho menu di động, bộ lọc, panel chi tiết. Shell Tier 3 dùng `side=\"left\"`\n * cho MobileMenu. Với panel kéo-thả kiểu mobile (có tay cầm, kéo để đóng) thì\n * dùng `Drawer` (vaul) thay vì Sheet.\n */\n\nexport type SheetProps = React.ComponentProps<typeof SheetPrimitive.Root>;\n\nfunction Sheet({ ...props }: SheetProps) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />;\n}\n\nexport type SheetTriggerProps = React.ComponentProps<typeof SheetPrimitive.Trigger>;\n\nfunction SheetTrigger({ ...props }: SheetTriggerProps) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />;\n}\n\nexport type SheetCloseProps = React.ComponentProps<typeof SheetPrimitive.Close>;\n\nfunction SheetClose({ ...props }: SheetCloseProps) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />;\n}\n\nexport type SheetPortalProps = React.ComponentProps<typeof SheetPrimitive.Portal>;\n\nfunction SheetPortal({ ...props }: SheetPortalProps) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />;\n}\n\nexport type SheetOverlayProps = React.ComponentProps<typeof SheetPrimitive.Overlay>;\n\nfunction SheetOverlay({ className, ...props }: SheetOverlayProps) {\n return (\n <SheetPrimitive.Overlay\n data-slot=\"sheet-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-ink/60 dark:bg-ink/80 backdrop-blur-sm\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type SheetSide = \"top\" | \"right\" | \"bottom\" | \"left\";\n\nexport type SheetContentProps = React.ComponentProps<typeof SheetPrimitive.Content> & {\n /** Cạnh màn hình mà panel trượt ra. Mặc định \"right\". */\n side?: SheetSide;\n /** Nhãn cho trình đọc màn hình của nút đóng. Mặc định \"Đóng\". */\n closeLabel?: string;\n};\n\nfunction SheetContent({ className, children, side = \"right\", closeLabel = \"Đóng\", ...props }: SheetContentProps) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Content\n data-slot=\"sheet-content\"\n className={cn(\n \"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-overlay transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500\",\n side === \"right\" &&\n \"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm\",\n side === \"left\" &&\n \"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm\",\n side === \"top\" &&\n \"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b\",\n side === \"bottom\" &&\n \"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t\",\n className\n )}\n {...props}\n >\n {children}\n <SheetPrimitive.Close className=\"absolute top-4 right-4 rounded-md p-1 text-muted-foreground transition-colors duration-150 ease-out hover:text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none\">\n <XIcon className=\"size-4\" />\n <span className=\"sr-only\">{closeLabel}</span>\n </SheetPrimitive.Close>\n </SheetPrimitive.Content>\n </SheetPortal>\n );\n}\n\nexport type SheetHeaderProps = React.ComponentProps<\"div\">;\n\nfunction SheetHeader({ className, ...props }: SheetHeaderProps) {\n return <div data-slot=\"sheet-header\" className={cn(\"flex flex-col gap-1.5 p-4\", className)} {...props} />;\n}\n\nexport type SheetFooterProps = React.ComponentProps<\"div\">;\n\nfunction SheetFooter({ className, ...props }: SheetFooterProps) {\n return <div data-slot=\"sheet-footer\" className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)} {...props} />;\n}\n\nexport type SheetTitleProps = React.ComponentProps<typeof SheetPrimitive.Title>;\n\nfunction SheetTitle({ className, ...props }: SheetTitleProps) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\"text-foreground font-semibold\", className)}\n {...props}\n />\n );\n}\n\nexport type SheetDescriptionProps = React.ComponentProps<typeof SheetPrimitive.Description>;\n\nfunction SheetDescription({ className, ...props }: SheetDescriptionProps) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Sheet,\n SheetClose,\n SheetContent,\n SheetDescription,\n SheetFooter,\n SheetHeader,\n SheetOverlay,\n SheetPortal,\n SheetTitle,\n SheetTrigger\n};\n"],"mappings":";AAkBS,cAkED,YAlEC;AAhBT,YAAY,oBAAoB;AAChC,SAAS,aAAa;AAEtB,SAAS,UAAU;AAYnB,SAAS,MAAM,EAAE,GAAG,MAAM,GAAe;AACvC,SAAO,oBAAC,eAAe,MAAf,EAAoB,aAAU,SAAS,GAAG,OAAO;AAC3D;AAIA,SAAS,aAAa,EAAE,GAAG,MAAM,GAAsB;AACrD,SAAO,oBAAC,eAAe,SAAf,EAAuB,aAAU,iBAAiB,GAAG,OAAO;AACtE;AAIA,SAAS,WAAW,EAAE,GAAG,MAAM,GAAoB;AACjD,SAAO,oBAAC,eAAe,OAAf,EAAqB,aAAU,eAAe,GAAG,OAAO;AAClE;AAIA,SAAS,YAAY,EAAE,GAAG,MAAM,GAAqB;AACnD,SAAO,oBAAC,eAAe,QAAf,EAAsB,aAAU,gBAAgB,GAAG,OAAO;AACpE;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC,eAAe;AAAA,IAAf;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAWA,SAAS,aAAa,EAAE,WAAW,UAAU,OAAO,SAAS,aAAa,gBAAQ,GAAG,MAAM,GAAsB;AAC/G,SACE,qBAAC,eACC;AAAA,wBAAC,gBAAa;AAAA,IACd;AAAA,MAAC,eAAe;AAAA,MAAf;AAAA,QACC,aAAU;AAAA,QACV,WAAW;AAAA,UACT;AAAA,UACA,SAAS,WACP;AAAA,UACF,SAAS,UACP;AAAA,UACF,SAAS,SACP;AAAA,UACF,SAAS,YACP;AAAA,UACF;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,UACD,qBAAC,eAAe,OAAf,EAAqB,WAAU,qTAC9B;AAAA,gCAAC,SAAM,WAAU,UAAS;AAAA,YAC1B,oBAAC,UAAK,WAAU,WAAW,sBAAW;AAAA,aACxC;AAAA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;AAIA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SAAO,oBAAC,SAAI,aAAU,gBAAe,WAAW,GAAG,6BAA6B,SAAS,GAAI,GAAG,OAAO;AACzG;AAIA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SAAO,oBAAC,SAAI,aAAU,gBAAe,WAAW,GAAG,mCAAmC,SAAS,GAAI,GAAG,OAAO;AAC/G;AAIA,SAAS,WAAW,EAAE,WAAW,GAAG,MAAM,GAAoB;AAC5D,SACE;AAAA,IAAC,eAAe;AAAA,IAAf;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,iBAAiB,EAAE,WAAW,GAAG,MAAM,GAA0B;AACxE,SACE;AAAA,IAAC,eAAe;AAAA,IAAf;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/ui/sheet.tsx"],"sourcesContent":["\"use client\";\n\nimport * as SheetPrimitive from \"@radix-ui/react-dialog\";\nimport { XIcon } from \"lucide-react\";\nimport type * as React from \"react\";\nimport { cn } from \"../../lib/cn.js\";\n\n/**\n * Sheet — panel trượt từ cạnh màn hình (dựng trên Radix Dialog).\n *\n * Dùng cho menu di động, bộ lọc, panel chi tiết. Shell Tier 3 dùng `side=\"left\"`\n * cho MobileMenu. Với panel kéo-thả kiểu mobile (có tay cầm, kéo để đóng) thì\n * dùng `Drawer` (vaul) thay vì Sheet.\n */\n\nexport type SheetProps = React.ComponentProps<typeof SheetPrimitive.Root>;\n\nfunction Sheet({ ...props }: SheetProps) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />;\n}\n\nexport type SheetTriggerProps = React.ComponentProps<typeof SheetPrimitive.Trigger>;\n\nfunction SheetTrigger({ ...props }: SheetTriggerProps) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />;\n}\n\nexport type SheetCloseProps = React.ComponentProps<typeof SheetPrimitive.Close>;\n\nfunction SheetClose({ ...props }: SheetCloseProps) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />;\n}\n\nexport type SheetPortalProps = React.ComponentProps<typeof SheetPrimitive.Portal>;\n\nfunction SheetPortal({ ...props }: SheetPortalProps) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />;\n}\n\nexport type SheetOverlayProps = React.ComponentProps<typeof SheetPrimitive.Overlay>;\n\nfunction SheetOverlay({ className, ...props }: SheetOverlayProps) {\n return (\n <SheetPrimitive.Overlay\n data-slot=\"sheet-overlay\"\n className={cn(\n \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-ink/60 dark:bg-ink/80 backdrop-blur-sm\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport type SheetSide = \"top\" | \"right\" | \"bottom\" | \"left\";\n\nexport type SheetContentProps = React.ComponentProps<typeof SheetPrimitive.Content> & {\n /** Cạnh màn hình mà panel trượt ra. Mặc định \"right\". */\n side?: SheetSide;\n /** Nhãn cho trình đọc màn hình của nút đóng. Mặc định \"Đóng\". */\n closeLabel?: string;\n};\n\nfunction SheetContent({ className, children, side = \"right\", closeLabel = \"Đóng\", ...props }: SheetContentProps) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Content\n data-slot=\"sheet-content\"\n className={cn(\n /*\n * `overflow-y-auto`: cùng lỗi với `DialogContent` trước 1.3.2 — `position: fixed`,\n * `h-full`, mà không có `overflow` nào, nên nội dung dài hơn khung nhìn bị CẮT và\n * không cuộn được. `SheetFooter` mang `mt-auto` nên nó vẫn dính đáy khi nội dung ngắn.\n */\n \"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 overflow-y-auto shadow-overlay transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500\",\n side === \"right\" &&\n \"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm\",\n side === \"left\" &&\n \"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm\",\n side === \"top\" &&\n \"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b\",\n side === \"bottom\" &&\n \"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t\",\n className\n )}\n {...props}\n >\n {children}\n <SheetPrimitive.Close className=\"absolute top-4 right-4 rounded-md p-1 text-muted-foreground transition-colors duration-150 ease-out hover:text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none\">\n <XIcon className=\"size-4\" />\n <span className=\"sr-only\">{closeLabel}</span>\n </SheetPrimitive.Close>\n </SheetPrimitive.Content>\n </SheetPortal>\n );\n}\n\nexport type SheetHeaderProps = React.ComponentProps<\"div\">;\n\nfunction SheetHeader({ className, ...props }: SheetHeaderProps) {\n return <div data-slot=\"sheet-header\" className={cn(\"flex flex-col gap-1.5 p-4\", className)} {...props} />;\n}\n\nexport type SheetFooterProps = React.ComponentProps<\"div\">;\n\nfunction SheetFooter({ className, ...props }: SheetFooterProps) {\n return <div data-slot=\"sheet-footer\" className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)} {...props} />;\n}\n\nexport type SheetTitleProps = React.ComponentProps<typeof SheetPrimitive.Title>;\n\nfunction SheetTitle({ className, ...props }: SheetTitleProps) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\"text-foreground font-semibold\", className)}\n {...props}\n />\n );\n}\n\nexport type SheetDescriptionProps = React.ComponentProps<typeof SheetPrimitive.Description>;\n\nfunction SheetDescription({ className, ...props }: SheetDescriptionProps) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-muted-foreground text-sm\", className)}\n {...props}\n />\n );\n}\n\nexport {\n Sheet,\n SheetClose,\n SheetContent,\n SheetDescription,\n SheetFooter,\n SheetHeader,\n SheetOverlay,\n SheetPortal,\n SheetTitle,\n SheetTrigger\n};\n"],"mappings":";AAkBS,cAuED,YAvEC;AAhBT,YAAY,oBAAoB;AAChC,SAAS,aAAa;AAEtB,SAAS,UAAU;AAYnB,SAAS,MAAM,EAAE,GAAG,MAAM,GAAe;AACvC,SAAO,oBAAC,eAAe,MAAf,EAAoB,aAAU,SAAS,GAAG,OAAO;AAC3D;AAIA,SAAS,aAAa,EAAE,GAAG,MAAM,GAAsB;AACrD,SAAO,oBAAC,eAAe,SAAf,EAAuB,aAAU,iBAAiB,GAAG,OAAO;AACtE;AAIA,SAAS,WAAW,EAAE,GAAG,MAAM,GAAoB;AACjD,SAAO,oBAAC,eAAe,OAAf,EAAqB,aAAU,eAAe,GAAG,OAAO;AAClE;AAIA,SAAS,YAAY,EAAE,GAAG,MAAM,GAAqB;AACnD,SAAO,oBAAC,eAAe,QAAf,EAAsB,aAAU,gBAAgB,GAAG,OAAO;AACpE;AAIA,SAAS,aAAa,EAAE,WAAW,GAAG,MAAM,GAAsB;AAChE,SACE;AAAA,IAAC,eAAe;AAAA,IAAf;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAWA,SAAS,aAAa,EAAE,WAAW,UAAU,OAAO,SAAS,aAAa,gBAAQ,GAAG,MAAM,GAAsB;AAC/G,SACE,qBAAC,eACC;AAAA,wBAAC,gBAAa;AAAA,IACd;AAAA,MAAC,eAAe;AAAA,MAAf;AAAA,QACC,aAAU;AAAA,QACV,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAMT;AAAA,UACA,SAAS,WACP;AAAA,UACF,SAAS,UACP;AAAA,UACF,SAAS,SACP;AAAA,UACF,SAAS,YACP;AAAA,UACF;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEH;AAAA;AAAA,UACD,qBAAC,eAAe,OAAf,EAAqB,WAAU,qTAC9B;AAAA,gCAAC,SAAM,WAAU,UAAS;AAAA,YAC1B,oBAAC,UAAK,WAAU,WAAW,sBAAW;AAAA,aACxC;AAAA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;AAIA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SAAO,oBAAC,SAAI,aAAU,gBAAe,WAAW,GAAG,6BAA6B,SAAS,GAAI,GAAG,OAAO;AACzG;AAIA,SAAS,YAAY,EAAE,WAAW,GAAG,MAAM,GAAqB;AAC9D,SAAO,oBAAC,SAAI,aAAU,gBAAe,WAAW,GAAG,mCAAmC,SAAS,GAAI,GAAG,OAAO;AAC/G;AAIA,SAAS,WAAW,EAAE,WAAW,GAAG,MAAM,GAAoB;AAC5D,SACE;AAAA,IAAC,eAAe;AAAA,IAAf;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;AAIA,SAAS,iBAAiB,EAAE,WAAW,GAAG,MAAM,GAA0B;AACxE,SACE;AAAA,IAAC,eAAe;AAAA,IAAf;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,iCAAiC,SAAS;AAAA,MACvD,GAAG;AAAA;AAAA,EACN;AAEJ;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comitor/ui",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Comitor design system — Shadcn/UI tùy biến theo brand Comitor + component dùng chung cho hệ sinh thái SaaS (Tasks, Chat, CRM, HR…)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -68,7 +68,8 @@
68
68
  "verify:directives": "node scripts/verify-directives.mjs",
69
69
  "smoke:entries": "node scripts/smoke-entries.mjs",
70
70
  "check:exports": "publint --strict && attw --pack . --profile esm-only --exclude-entrypoints styles.css",
71
- "prepublishOnly": "pnpm run typecheck && pnpm run build && pnpm run verify:directives && pnpm run smoke:entries && pnpm run check:exports && pnpm run test:nav-active && pnpm run test:a11y-gate && pnpm run lint:a11y"
71
+ "prepublishOnly": "pnpm run typecheck && pnpm run build && pnpm run verify:directives && pnpm run smoke:entries && pnpm run check:exports && pnpm run test:nav-active && pnpm run test:grid-contract && pnpm run test:a11y-gate && pnpm run lint:a11y",
72
+ "test:grid-contract": "node scripts/check-grid-contract.mjs"
72
73
  },
73
74
  "peerDependencies": {
74
75
  "@uppy/core": "^6.0.0",