@thangph2146/nextjs-editor 1.0.5 → 1.0.6

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/README.md CHANGED
@@ -26,7 +26,7 @@ Trong `app/layout.tsx` hoặc `_app.tsx`:
26
26
  import "@thangph2146/nextjs-editor/styles.css"
27
27
  ```
28
28
 
29
- **Lưu ý:** Chỉ cần import file trên. Bạn **không** cần thêm `@source` hay cấu hình nào trong `globals.css`. Style editor được đóng gói sẵn, scope trong `#editor-x` nằm trong layer `nextjs-editor` nếu app dùng CSS layer cho SCSS/global (xem bên dưới), style editor sẽ không bị ghi đè.
29
+ **Lưu ý:** Chỉ cần import file trên. Bạn **không** cần thêm `@source` hay cấu hình nào trong `globals.css`. Style editor được đóng gói sẵn, scope trong `#editor-x`, nằm trong layer `nextjs-editor`, **mọi declaration đều `!important`** dự án app (tuyen-sinh, tuyen-sinh-admin, v.v.) **không ghi đè được** style editor.
30
30
 
31
31
  ### 2. Dùng component Editor (Client Component)
32
32
 
@@ -66,11 +66,11 @@ export function MyEditor() {
66
66
 
67
67
  ## Tránh SCSS/CSS của app ghi đè editor
68
68
 
69
- Style editor được bọc trong **`@layer nextjs-editor`**. Trong CSS, rule **không nằm trong layer** (unlayered) độ ưu tiên cao hơn rule trong layer, nên nếu SCSS/global của app là unlayered thìthể ghi đè list, spacing, typography… bên trong `#editor-x`.
69
+ Style editor được build với **`!important`** trên mọi declaration (dùng [postcss-safe-important](https://github.com/Crimx/postcss-safe-important); keyframes animation được loại trừ theo mặc định). Do đó **các dự án app (tuyen-sinh, tuyen-sinh-admin, v.v.) không ghi đè được** style bên trong `#editor-x`, kể cả khi SCSS/global của app là unlayered hoặcspecificity cao hơn.
70
70
 
71
- **Cách làm:** Đưa toàn bộ SCSS/global của app vào một layer (ví dụ `app`) và khai báo thứ tự layer sao cho `nextjs-editor` đứng **sau** — khi đó style editor sẽ thắng khi specificity tương đương.
71
+ Style vẫn được bọc trong **`@layer nextjs-editor`**. Nếu bạn muốn thêm một lớp bảo vệ theo thứ tự layer (ví dụ đảm bảo SCSS app không bao giờ thắng khi specificity ngang nhau), có thể đưa SCSS/global của app vào layer `app` và khai báo thứ tự layer sao cho `nextjs-editor` đứng **sau**.
72
72
 
73
- ### Bước 1: Khai báo thứ tự layer trong app
73
+ ### Bước 1 (tùy chọn): Khai báo thứ tự layer trong app
74
74
 
75
75
  Trong `globals.css` (hoặc file CSS chính), **dòng đầu tiên** khai báo thứ tự layer, thêm `app` và `nextjs-editor` (layer xuất hiện sau có ưu tiên cao hơn):
76
76
 
@@ -78,26 +78,27 @@ Trong `globals.css` (hoặc file CSS chính), **dòng đầu tiên** khai báo t
78
78
  @layer legacy, base, components, utilities, app, nextjs-editor;
79
79
  ```
80
80
 
81
- ### Bước 2: Đưa SCSS/global vào layer `app`
81
+ ### Bước 2 (tùy chọn): Đưa SCSS/global vào layer `app`
82
82
 
83
- Mọi style global/SCSS không nằm trong Tailwind (base, typography, components từ SCSS…) cần nằm trong `@layer app`.
83
+ Mọi style global/SCSS không nằm trong Tailwind cần nằm trong `@layer app`. **Lưu ý:** Trong Sass, `@use` không được phép bên trong `@layer`, nên không bọc trực tiếp nội dung có `@use` trong một block `@layer app { }`.
84
84
 
85
- **Cách ABọc toàn bộ file SCSS chính:**
85
+ **Cách khuyến nghị File wrapper dùng `@import`:**
86
86
 
87
- Trong file SCSS chính (ví dụ `src/styles/main.scss`), bọc toàn bộ nội dung trong `@layer app`:
87
+ Tạo file SCSS mới (ví dụ `src/styles/app-layer.scss`) chỉ dùng `@import` (Sass cho phép `@import` trong `@layer`):
88
88
 
89
89
  ```scss
90
90
  @layer app {
91
- @use "abstracts/variables" as *;
92
- @use "abstracts/mixins" as *;
93
- @use "base/base";
94
- @use "base/typography";
95
- @use "components/header";
96
- /* ... các @use khác ... */
91
+ @import "main";
97
92
  }
98
93
  ```
99
94
 
100
- **Cách B Import SCSS từ một file CSS layer:**
95
+ Trong `layout.tsx` (hoặc nơi đang import file SCSS chính), đổi sang import file wrapper:
96
+
97
+ ```tsx
98
+ import "../styles/app-layer.scss";
99
+ ```
100
+
101
+ **Cách khác — File CSS import SCSS (nếu bundler hỗ trợ):**
101
102
 
102
103
  Tạo file `src/app/globals-app.css`:
103
104
 
@@ -107,9 +108,9 @@ Tạo file `src/app/globals-app.css`:
107
108
  }
108
109
  ```
109
110
 
110
- Rồi trong `layout.tsx` import sau `globals.css`: `import "./globals-app.css"`.
111
+ Rồi trong `layout.tsx` import sau `globals.css`: `import "./globals-app.css"`. (Một số bundler có thể không compile `.scss` khi import từ `.css`.)
111
112
 
112
- Sau khi cấu hình, style trong layer `nextjs-editor` (đã load khi import `@thangph2146/nextjs-editor/styles.css`) sẽưu tiên cao hơn layer `app`, nên cấu trúc Tailwind và theme của editor trong `#editor-x` không còn bị SCSS của app ghi đè.
113
+ Sau khi cấu hình (nếu dùng), style trong layer `nextjs-editor` (đã load khi import `@thangph2146/nextjs-editor/styles.css`) `!important` sẽ luôn thắng so với SCSS của app; cấu trúc Tailwind và theme của editor trong `#editor-x` không bị ghi đè.
113
114
 
114
115
  ## Cấu hình API thư viện ảnh
115
116
 
@@ -591,6 +591,9 @@
591
591
  .h-\[var\(--radix-select-trigger-height\)\] {
592
592
  height: var(--radix-select-trigger-height);
593
593
  }
594
+ .h-auto {
595
+ height: auto;
596
+ }
594
597
  .h-full {
595
598
  height: 100%;
596
599
  }
@@ -648,9 +651,6 @@
648
651
  .min-h-\[54px\] {
649
652
  min-height: 54px;
650
653
  }
651
- .min-h-\[70vh\] {
652
- min-height: 70vh;
653
- }
654
654
  .min-h-\[300px\] {
655
655
  min-height: 300px;
656
656
  }
@@ -1135,6 +1135,10 @@
1135
1135
  border-start-end-radius: 0;
1136
1136
  border-end-end-radius: 0;
1137
1137
  }
1138
+ .rounded-t-xl {
1139
+ border-top-left-radius: var(--radius-xl);
1140
+ border-top-right-radius: var(--radius-xl);
1141
+ }
1138
1142
  .rounded-b-xl {
1139
1143
  border-bottom-right-radius: var(--radius-xl);
1140
1144
  border-bottom-left-radius: var(--radius-xl);
@@ -1262,10 +1266,10 @@
1262
1266
  background-color: color-mix(in oklab, var(--background) 95%, transparent);
1263
1267
  }
1264
1268
  }
1265
- .bg-black\/20 {
1266
- background-color: color-mix(in srgb, #000 20%, transparent);
1269
+ .bg-black\/10 {
1270
+ background-color: color-mix(in srgb, #000 10%, transparent);
1267
1271
  @supports (color: color-mix(in lab, red, red)) {
1268
- background-color: color-mix(in oklab, var(--color-black) 20%, transparent);
1272
+ background-color: color-mix(in oklab, var(--color-black) 10%, transparent);
1269
1273
  }
1270
1274
  }
1271
1275
  .bg-black\/60 {
@@ -1328,12 +1332,6 @@
1328
1332
  background-color: color-mix(in oklab, var(--muted) 20%, transparent);
1329
1333
  }
1330
1334
  }
1331
- .bg-muted\/30 {
1332
- background-color: var(--muted);
1333
- @supports (color: color-mix(in lab, red, red)) {
1334
- background-color: color-mix(in oklab, var(--muted) 30%, transparent);
1335
- }
1336
- }
1337
1335
  .bg-muted\/40 {
1338
1336
  background-color: var(--muted);
1339
1337
  @supports (color: color-mix(in lab, red, red)) {
@@ -1527,12 +1525,12 @@
1527
1525
  .pt-0 {
1528
1526
  padding-top: calc(var(--spacing) * 0);
1529
1527
  }
1528
+ .pt-3 {
1529
+ padding-top: calc(var(--spacing) * 3);
1530
+ }
1530
1531
  .pt-4 {
1531
1532
  padding-top: calc(var(--spacing) * 4);
1532
1533
  }
1533
- .pt-5 {
1534
- padding-top: calc(var(--spacing) * 5);
1535
- }
1536
1534
  .pt-6 {
1537
1535
  padding-top: calc(var(--spacing) * 6);
1538
1536
  }
@@ -1542,6 +1540,9 @@
1542
1540
  .pr-10 {
1543
1541
  padding-right: calc(var(--spacing) * 10);
1544
1542
  }
1543
+ .pr-12 {
1544
+ padding-right: calc(var(--spacing) * 12);
1545
+ }
1545
1546
  .pb-2 {
1546
1547
  padding-bottom: calc(var(--spacing) * 2);
1547
1548
  }
@@ -3879,4 +3880,4 @@
3879
3880
  --tw-content: "";
3880
3881
  }
3881
3882
  }
3882
- }
3883
+ }
@@ -591,6 +591,9 @@
591
591
  #editor-x .h-\[var\(--radix-select-trigger-height\)\] {
592
592
  height: var(--radix-select-trigger-height);
593
593
  }
594
+ #editor-x .h-auto {
595
+ height: auto;
596
+ }
594
597
  #editor-x .h-full {
595
598
  height: 100%;
596
599
  }
@@ -648,9 +651,6 @@
648
651
  #editor-x .min-h-\[54px\] {
649
652
  min-height: 54px;
650
653
  }
651
- #editor-x .min-h-\[70vh\] {
652
- min-height: 70vh;
653
- }
654
654
  #editor-x .min-h-\[300px\] {
655
655
  min-height: 300px;
656
656
  }
@@ -1135,6 +1135,10 @@
1135
1135
  border-start-end-radius: 0;
1136
1136
  border-end-end-radius: 0;
1137
1137
  }
1138
+ #editor-x .rounded-t-xl {
1139
+ border-top-left-radius: var(--radius-xl);
1140
+ border-top-right-radius: var(--radius-xl);
1141
+ }
1138
1142
  #editor-x .rounded-b-xl {
1139
1143
  border-bottom-right-radius: var(--radius-xl);
1140
1144
  border-bottom-left-radius: var(--radius-xl);
@@ -1262,10 +1266,10 @@
1262
1266
  background-color: color-mix(in oklab, var(--background) 95%, transparent);
1263
1267
  }
1264
1268
  }
1265
- #editor-x .bg-black\/20 {
1266
- background-color: color-mix(in srgb, #000 20%, transparent);
1269
+ #editor-x .bg-black\/10 {
1270
+ background-color: color-mix(in srgb, #000 10%, transparent);
1267
1271
  @supports (color: color-mix(in lab, red, red)) {
1268
- background-color: color-mix(in oklab, var(--color-black) 20%, transparent);
1272
+ background-color: color-mix(in oklab, var(--color-black) 10%, transparent);
1269
1273
  }
1270
1274
  }
1271
1275
  #editor-x .bg-black\/60 {
@@ -1328,12 +1332,6 @@
1328
1332
  background-color: color-mix(in oklab, var(--muted) 20%, transparent);
1329
1333
  }
1330
1334
  }
1331
- #editor-x .bg-muted\/30 {
1332
- background-color: var(--muted);
1333
- @supports (color: color-mix(in lab, red, red)) {
1334
- background-color: color-mix(in oklab, var(--muted) 30%, transparent);
1335
- }
1336
- }
1337
1335
  #editor-x .bg-muted\/40 {
1338
1336
  background-color: var(--muted);
1339
1337
  @supports (color: color-mix(in lab, red, red)) {
@@ -1527,12 +1525,12 @@
1527
1525
  #editor-x .pt-0 {
1528
1526
  padding-top: calc(var(--spacing) * 0);
1529
1527
  }
1528
+ #editor-x .pt-3 {
1529
+ padding-top: calc(var(--spacing) * 3);
1530
+ }
1530
1531
  #editor-x .pt-4 {
1531
1532
  padding-top: calc(var(--spacing) * 4);
1532
1533
  }
1533
- #editor-x .pt-5 {
1534
- padding-top: calc(var(--spacing) * 5);
1535
- }
1536
1534
  #editor-x .pt-6 {
1537
1535
  padding-top: calc(var(--spacing) * 6);
1538
1536
  }
@@ -1542,6 +1540,9 @@
1542
1540
  #editor-x .pr-10 {
1543
1541
  padding-right: calc(var(--spacing) * 10);
1544
1542
  }
1543
+ #editor-x .pr-12 {
1544
+ padding-right: calc(var(--spacing) * 12);
1545
+ }
1545
1546
  #editor-x .pb-2 {
1546
1547
  padding-bottom: calc(var(--spacing) * 2);
1547
1548
  }
@@ -3879,4 +3880,4 @@
3879
3880
  --tw-content: "";
3880
3881
  }
3881
3882
  }
3882
- }
3883
+ }
package/dist/index.cjs CHANGED
@@ -2698,29 +2698,29 @@ function ImageComponent({
2698
2698
  className: "max-w-[96vw] max-h-[96vh] w-[96vw] h-[96vh] overflow-hidden flex flex-col p-0 gap-0 rounded-xl border shadow-2xl",
2699
2699
  "aria-describedby": "view-original-image-desc",
2700
2700
  children: [
2701
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogHeader, { className: "shrink-0 px-6 pt-5 pb-2 border-b bg-muted/30", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogTitle, { className: "text-base font-semibold", children: "Xem h\xECnh g\u1ED1c" }) }),
2701
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogHeader, { className: "shrink-0 px-4 pt-3 pb-3 pr-12 border-b border-border/50 bg-muted/20 rounded-t-xl", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogTitle, { className: "text-sm font-semibold", children: "Xem h\xECnh g\u1ED1c" }) }),
2702
2702
  /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2703
2703
  "div",
2704
2704
  {
2705
2705
  id: "view-original-image-desc",
2706
- className: "flex-1 min-h-[70vh] overflow-auto flex items-center justify-center p-4 bg-black/20",
2706
+ className: "flex-1 min-h-0 overflow-auto flex items-center justify-center p-4 bg-black/10",
2707
2707
  children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2708
2708
  "img",
2709
2709
  {
2710
2710
  src,
2711
2711
  alt: altText || "H\xECnh g\u1ED1c",
2712
- className: "flex-1 min-w-0 min-h-0 w-full h-full max-w-full max-h-full object-contain rounded-lg"
2712
+ className: "max-w-full max-h-full w-auto h-auto object-contain rounded-lg select-none"
2713
2713
  }
2714
2714
  )
2715
2715
  }
2716
2716
  ),
2717
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogFooter, { className: "shrink-0 flex-row justify-center gap-2 px-6 py-4 border-t bg-muted/20 rounded-b-xl", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2717
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogFooter, { className: "shrink-0 flex-row justify-center gap-2 px-4 py-3 border-t border-border/50 bg-muted/20 rounded-b-xl", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2718
2718
  Button,
2719
2719
  {
2720
2720
  variant: "outline",
2721
- size: "default",
2721
+ size: "sm",
2722
2722
  asChild: true,
2723
- className: "gap-2 text-base",
2723
+ className: "gap-2",
2724
2724
  children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
2725
2725
  "a",
2726
2726
  {