@godxjp/ui 23.4.1 → 23.4.3

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.
Files changed (40) hide show
  1. package/README.md +17 -2
  2. package/dist/components/data-display/badge.d.ts +14 -1
  3. package/dist/components/data-display/badge.js +21 -1
  4. package/dist/components/data-display/data-table.d.ts +4 -2
  5. package/dist/components/data-display/data-table.js +14 -2
  6. package/dist/components/data-entry/date-picker.js +4 -16
  7. package/dist/components/layout/draggable-panel.d.ts +3 -2
  8. package/dist/components/layout/draggable-panel.js +11 -2
  9. package/dist/components/layout/index.d.ts +1 -1
  10. package/dist/components/navigation/filter-bar.js +11 -16
  11. package/dist/components/ui/segmented.d.ts +19 -1
  12. package/dist/components/ui/segmented.js +34 -2
  13. package/dist/props/components/data-display.prop.d.ts +5 -0
  14. package/dist/props/components/index.d.ts +1 -1
  15. package/dist/props/components/layout.prop.d.ts +13 -2
  16. package/dist/props/registry.d.ts +5 -1
  17. package/dist/props/registry.js +6 -1
  18. package/dist/props/vocabulary/data.prop.d.ts +11 -0
  19. package/dist/styles/badge-layout.css +25 -0
  20. package/dist/styles/control.css +37 -0
  21. package/dist/styles/core-with-fallbacks.css +3 -0
  22. package/dist/styles/focus-ring.css +2 -0
  23. package/dist/styles/font-fallbacks.css +83 -0
  24. package/dist/styles/fonts.css +1 -82
  25. package/dist/styles/layout.css +17 -5
  26. package/dist/tokens/components/badge.css +6 -0
  27. package/dist/tokens/components/draggable-panel.css +4 -0
  28. package/dist/tokens/components/segmented.css +8 -0
  29. package/docs/CONSUMER-RULES.md +1 -1
  30. package/docs/CUSTOMER-THEMING.md +16 -2
  31. package/docs/DESIGN-AUTHORITY.md +15 -0
  32. package/docs/data-entry/segmented-in-filter-row.tsx +2 -19
  33. package/docs/data-entry/segmented.tsx +2 -19
  34. package/package.json +4 -2
  35. package/scripts/_agent-setup.mjs +90 -17
  36. package/scripts/cli.mjs +6 -2
  37. package/scripts/consumer-rule.md +76 -18
  38. package/scripts/guinea-pig-skill.md +38 -9
  39. package/scripts/postinstall.mjs +1 -1
  40. package/scripts/ui-audit.mjs +1 -1
@@ -1,6 +1,9 @@
1
1
  # @godxjp/ui
2
2
 
3
- > **Tệp này do gói `@godxjp/ui` sở hữu bị GHI ĐÈ mỗi lần nâng cấp.**
3
+ > **Tệp này do gói `@godxjp/ui` sở hữu.** Nội dung được ghi lại khi luật trong gói đổi (thường
4
+ > qua postinstall sau `npm i`, trừ khi `.npmrc` có `ignore-scripts=true`). Khi đó chạy
5
+ > `npx @godxjp/ui sync-rules`. Dấu `<!-- godxjp-ui:version -->` luôn được đồng bộ với phiên bản
6
+ > gói đang cài — kể cả khi thân tệp không đổi giữa hai bản.
4
7
  > Đừng sửa ở đây — luật của riêng kho thuộc về một tệp khác trong `.ai/rules/`,
5
8
  > và index sẽ nạp cả hai. (Khác với `.claude/skills/.../SKILL.md`, nơi mục §8
6
9
  > trở đi là của kho và được giữ lại.)
@@ -9,11 +12,12 @@
9
12
  `docs/CONSUMER-RULES.md` (10 luật) và, với kho chuột bạch, ở
10
13
  `.claude/skills/godx-ui-guinea-pig/SKILL.md`.
11
14
 
12
- ## Nạp style: HAI lối vào, và lối thứ hai không chở font
15
+ ## Nạp style: BA lối vào, và hai lối sau không chở font
13
16
 
14
17
  ```css
15
- @import "@godxjp/ui/styles"; /* mọi layer + Noto Sans JP / M PLUS 2 đóng gói sẵn */
18
+ @import "@godxjp/ui/styles"; /* mọi layer + Noto Sans JP / M PLUS 2 đóng gói sẵn */
16
19
  @import "@godxjp/ui/styles/core"; /* CÙNG các layer ấy, KHÔNG một @font-face nào */
20
+ @import "@godxjp/ui/styles/core-with-fallbacks"; /* core + 6 khối local()-only, vẫn 0 byte mạng */
17
21
  ```
18
22
 
19
23
  Chọn `core` khi kho tự lo mặt chữ, hoặc khi không muốn chở font: `@fontsource` cắt
@@ -21,9 +25,18 @@ Noto Sans JP thành hàng trăm lát `unicode-range`, và trình duyệt chỉ b
21
25
  SAU khi đã dựng bố cục — một consumer đo được **737 lát / 13 MB**, gấp bảy lần toàn bộ
22
26
  JavaScript của họ, cộng ~8 vòng tải mỗi lần chuyển màn.
23
27
 
24
- `core` không phải cherry-pick: một trong hai lối vào được hỗ trợ, thứ tự layer
25
- vẫn nguyên vẹn. Cherry-pick từng layer riêng lẻ thì vẫn cấm đó là thứ làm vỡ hợp đồng
26
- thứ tự, không phải việc chọn lối vào.
28
+ Lối thứ ba dành cho kho **tự cấp Noto Sans JP** (next/font, self-host) vẫn muốn cửa
29
+ sổ swap không đội hình: chở đúng 6 `@font-face` metric-matched, `src` toàn `local()`
30
+ nên **không tải byte nào**. Nhớ tự xếp tên họ chữ ngay sau mặt chữ của bạn:
31
+ `--font-sans-base: "Noto Sans JP", "Noto Sans JP Fallback", system-ui, sans-serif;`
32
+
33
+ `core` giữ `@font-face` = **0** và đó là lời hứa đo được —
34
+ `grep -c '@font-face' node_modules/@godxjp/ui/dist/styles/core.css` → `0`. Vì vậy các
35
+ fallback nằm ở entry riêng chứ không nhét vào `core`.
36
+
37
+ Không lối nào trong ba là cherry-pick: cả ba đều được hỗ trợ và thứ tự layer vẫn nguyên
38
+ vẹn. Cherry-pick từng layer riêng lẻ thì vẫn cấm — đó là thứ làm vỡ hợp đồng thứ tự,
39
+ không phải việc chọn lối vào.
27
40
 
28
41
  ## Bố cục chuẩn của platform: BA CỘT, và ba cột là BA PHẠM VI
29
42
 
@@ -66,24 +79,69 @@ Slack thì đặt lại **một dòng**, không fork `.app-nav-rail`.
66
79
  Hỏi MCP `godxjp-ui` (`search_components`, `get_component`). Đo được trong một
67
80
  ngày: năm thứ cần đều ĐÃ CÓ và vẫn bị dựng lại bằng thứ khác —
68
81
 
69
- | Cần | Đã có |
70
- | ---------------------------------------- | --------------------- |
71
- | đường kẻ chạm mép Card | `<CardContent flush>` |
72
- | header có kẻ khi thân là danh sách flush | `<CardHeader banded>` |
73
- | một hàng LÀ liên kết (thay cho nút rời) | `<ListRow asChild>` |
74
- | kẻ ô từng ngày trong lịch | `<Calendar bordered>` |
75
- | dải giữa hai vùng, tự kẻ theo VỊ TRÍ | `<CardBar>` |
82
+ | Cần | Đã có |
83
+ | ----------------------------------------------- | ---------------------------------------------------------------------------------- |
84
+ | đường kẻ chạm mép Card | `<CardContent flush>` |
85
+ | header có kẻ khi thân là danh sách flush | `<CardHeader banded>` |
86
+ | một hàng LÀ liên kết (thay cho nút rời) | `<ListRow asChild>` |
87
+ | kẻ ô từng ngày trong lịch | `<Calendar bordered>` |
88
+ | dải giữa hai vùng, tự kẻ theo VỊ TRÍ | `<CardBar>` (`border` để ép khi xếp chồng) |
89
+ | chip "điều kiện đang bật" có dấu × để bỏ | `<Badge onRemove>` — KHÔNG phải `TagInput` |
90
+ | dải tab nằm TRONG đầu Card | `<Card tabList activeTabKey onTabChange>` |
91
+ | tiêu đề / đoạn văn / liên kết trong văn bản | `<Title>` · `<Paragraph>` · `<Link>` (`Text` 33 prop) |
92
+ | nút nổi góc màn (quay lên đầu, hành động nhanh) | `<FloatButton>` |
93
+ | khung xương của một FORM khi đang tải | `<SkeletonForm>` |
94
+ | ô màu chỉ để xem, màu do NGƯỜI DÙNG chọn | `<Swatch>` |
95
+ | ảnh đại diện của một tệp / bản xem trước | `<Thumbnail>` |
96
+ | danh sách "có gì trong gói này" | `<FeatureList>` |
97
+ | panel kéo giãn được (chia đôi màn) | `<DraggablePanel>` |
98
+ | màn hội thoại AI | `<Welcome>` · `<Conversations>` · `<Attachments>` · `<ThoughtChain>` · `<Actions>` |
76
99
 
77
100
  Lỗi không phải "đoán sai tên prop" mà là **cho rằng nó không tồn tại nên không
78
101
  hỏi**.
79
102
 
80
- ## Catalog chở PROP, không chở LUẬT BỐ CỤC
103
+ ## Dialog AlertDialog MỘT họ `variant` là lối chuẩn
81
104
 
82
- `CardBar` trong manifest đúng một prop (`extra`) không dòng nào nói tự
83
- kẻ theo vị trí (đầu: kẻ dưới · cuối: kẻ trên · giữa: cả hai). Luật ấy chỉ nằm
84
- trong chú thích `node_modules/@godxjp/ui/src/styles/card-layout.css`.
105
+ Đừng với tay sang 12 export `AlertDialog*` nữa. Chúng **vẫn chạy y như cũ** (gỡ
106
+ breaking change) nhưng **LỐI CŨ**: đo được 26 export với **12 cặp trùng
107
+ tên** **0** phần chỉ `AlertDialog` mới có. antd — thẩm quyền bề mặt prop của
108
+ gói này — chỉ có MỘT `Modal`, và mức nguy hiểm ở đó là một PROP.
109
+
110
+ ```tsx
111
+ <DialogContent variant="destructive"> {/* thay cho <AlertDialogContent> */}
112
+ ```
85
113
 
86
- **Làm bố cục trong một component của DS mở tệp `*-layout.css` của ra đọc.**
114
+ Một prop ấy quyết định ba thứ đi cùng nhau: `role="alertdialog"`, click ra ngoài
115
+ KHÔNG đóng, nút chính nhấn mạnh destructive (và ✕ mặc định tắt). Esc VẪN đóng —
116
+ y như `AlertDialogContent` trước nay. Đặt `variant` ở `DialogRoot` thì cả cây kế
117
+ thừa.
118
+
119
+ ## antd là CHUẨN — thiếu gì thì port 100%, đừng tự thiết kế
120
+
121
+ `docs/DESIGN-AUTHORITY.md` của gói: **nơi antd đặt tên cho một năng lực, gói này
122
+ lấy nguyên tên và nguyên ngữ nghĩa của antd.** Một năng lực còn thiếu được port
123
+ từ antd **100% TRƯỚC** — tên, prop, ngữ nghĩa — rồi mới cải tiến. Không thiết kế
124
+ lại trước, không port một nửa.
125
+
126
+ Nghĩa là với consumer: thấy thiếu prop thì **mở issue kèm tên antd của nó**
127
+ (`sorter`, `closable`, `okType`…), đừng đề xuất một cái tên mới và đừng tự vẽ
128
+ lại bằng class tiện ích. Ba trục cố ý lệch khỏi antd đều đã ghi lý do trong
129
+ DESIGN-AUTHORITY (logical thay cho `left/right`, từ vựng giá trị của gói này,
130
+ `density` thay cho `size`) — lệch thêm thì phải viết ra ở đó.
131
+
132
+ ## Catalog giờ chở CẢ luật bố cục — nhưng phải hỏi mới có
133
+
134
+ Mục này từng nói "catalog chở PROP, không chở LUẬT BỐ CỤC", với `CardBar` làm
135
+ bằng chứng: một prop (`extra`), không dòng nào nói nó tự kẻ theo vị trí. **Bằng
136
+ chứng ấy đã hết đúng.** `CardBar` nay có 6 prop, trong đó `border` (`"none" |
137
+ "block-start" | "block-end" | "both"`) ép được đường kẻ khi xếp chồng, và cả
138
+ `Card` lẫn `CardBar` trong catalog đều nói ra luật vị trí (đầu: kẻ dưới · cuối:
139
+ kẻ trên · giữa: cả hai).
140
+
141
+ Nên luật hiện hành là: **hỏi `get_component` trước** — nay nó thường trả lời cả
142
+ hình dạng lẫn luật. Còn khi `usage`/`description` im lặng về bố cục thì mới mở
143
+ `node_modules/@godxjp/ui/src/styles/*-layout.css` của component ấy ra đọc; chú
144
+ thích trong đó vẫn là bản đầy đủ nhất.
87
145
 
88
146
  ## Card không lồng Card
89
147
 
@@ -101,6 +101,28 @@ Thứ tự ưu tiên, chỉ tiến khi bước trước thật sự không diễ
101
101
  **dùng → ghép → thêm prop vào component đã có → tạo component mới.**
102
102
  Một prop nữa hơn một component nữa.
103
103
 
104
+ **Và TÊN không phải của bạn — nó là của antd.** `docs/DESIGN-AUTHORITY.md` (mục
105
+ "The PROP SURFACE of a component is antd's too"): **nơi antd đặt tên cho một năng
106
+ lực, kho này lấy nguyên tên và nguyên ngữ nghĩa của antd. Một năng lực còn thiếu
107
+ được port từ antd 100% TRƯỚC — tên, prop, ngữ nghĩa — rồi mới cải tiến. Không
108
+ thiết kế lại trước, và không port một nửa.**
109
+
110
+ Đây là luật mới nhất và là luật hay bị bỏ qua nhất, vì nó nghe như lời khuyên.
111
+ Cái giá của việc bỏ qua đã đo được: `DataTable` mọc `pin: "end"` nơi antd có
112
+ `fixed`, `sortable: true` nơi antd có `sorter`, và không có câu trả lời nào cho
113
+ filter/expandable — mỗi lần một người quyết một kiểu. Cùng hình dạng lỗi:
114
+ `Dialog` + `AlertDialog` từng là 26 export với **12 cặp trùng tên** và **0** phần
115
+ chỉ `AlertDialog` mới có, trong khi antd chỉ có MỘT `Modal` (nguy hiểm là một
116
+ PROP, `okType`). Nay là một họ, `variant` là lối chuẩn, 12 export cũ ở lại vì gỡ
117
+ là breaking. Và cả họ Ant Design X từng tới nửa vời — thiếu `Conversations`,
118
+ `Attachments`, `ThoughtChain`, `Welcome`, `Actions`, nay đã đủ.
119
+
120
+ Ba chỗ cố ý lệch khỏi antd (logical thay `left/right`, từ vựng giá trị của kho
121
+ này, `density` thay `size`) đều **ghi lý do trong DESIGN-AUTHORITY**. Lệch thêm
122
+ thì phải viết vào đó, không lệch lặng lẽ. Và đọc bề mặt antd từ **type đã cài ở
123
+ một checkout khác**, không từ trí nhớ — `antd` đã bị gỡ khỏi devDependencies của
124
+ kho này từ 20.0.0 và `check:no-antd-runtime` canh cho nó không quay lại.
125
+
104
126
  ### Bước 4 — Kiểm bằng tarball TRƯỚC khi phát hành
105
127
 
106
128
  Đây là bước làm cho "vừa làm vừa trải nghiệm" thành thật. Đừng phát hành rồi
@@ -303,15 +325,22 @@ không tồn tại nên không hỏi**.
303
325
  Trước khi viết bất kỳ bố cục nào: `search_components` + `get_component`. Rẻ hơn
304
326
  mọi lần sửa sau.
305
327
 
306
- **Nhưng catalog chở PROP, không chở LUẬT BỐ CỤC** — và đó một khoảng trống
307
- thật của catalog, không chỉ lỗi của người dùng nó. Ví dụ đo được: `CardBar`
308
- trong manifest có đúng một prop (`extra`), không dòng nào nói nó **tự lấy đường
309
- kẻ theo VỊ TRÍ** đầu thì kẻ dưới, cuối thì kẻ trên, ở giữa thì cả hai. Luật ấy
310
- chỉ nằm trong chú thích của `src/styles/card-layout.css`, cùng chỗ định nghĩa hai
311
- nhịp `section` (header phẳng) `band` (header có kẻ).
312
-
313
- Nên khi làm bố cục bên trong một component của DS: **mở tệp `*-layout.css` của
314
- ra đọc**. Một agent hỏi MCP đúng cách vẫn sẽ không biết những luật này.
328
+ **Catalog từng chở PROP không chở LUẬT BỐ CỤC — và dụ ấy nay đã được vá,
329
+ nên đừng trích nữa.** Bản trước của mục này viết: `CardBar` trong manifest có
330
+ đúng một prop (`extra`), không dòng nào nói nó tự lấy đường kẻ theo VỊ TRÍ. Đo
331
+ lại hôm nay: `CardBar` **6 prop**, trong đó `border` (`"none" | "block-start"
332
+ | "block-end" | "both"`) ép được đường kẻ khi xếp chồng, và luật vị trí (đầu: kẻ
333
+ dưới · cuối: kẻ trên · giữa: cả hai) nằm **trong chính catalog** — ở `usage` của
334
+ `CardBar` lẫn `description` của `Card`.
335
+
336
+ Bài học còn lại vẫn thật, chỉ đổi hình: một luật bố cục **có thể** chỉ sống
337
+ trong chú thích CSS, và không có cổng nào bắt nó phải lên catalog. Nên:
338
+
339
+ 1. Hỏi `get_component` trước — nay nó thường trả lời cả hình dạng lẫn luật.
340
+ 2. `usage`/`description` im lặng về bố cục → mở `src/styles/*-layout.css` của
341
+ component ấy ra đọc (chỗ định nghĩa hai nhịp `section` và `band` chẳng hạn).
342
+ 3. Là chuột bạch, khi bước 2 phải dùng tới, đó là **khoảng trống catalog** — đưa
343
+ luật ấy lên `usage` trong cùng PR, theo §4. Đó là cách `CardBar` được vá.
315
344
 
316
345
  ## 6. Thứ KHÔNG đẩy lên DS
317
346
 
@@ -22,7 +22,7 @@ try {
22
22
  const r = ensureMcpJson(root);
23
23
  // A refusal is a full sentence, not one of the three status words — say it on its own line
24
24
  // rather than folding it into "MCP in .mcp.json (…)", where it would read as a success.
25
- if (r.startsWith("left untouched")) {
25
+ if (r.startsWith("left untouched") || r.startsWith("present (custom godx-ui")) {
26
26
  console.log(`\n @godxjp/ui → .mcp.json ${r}\n`);
27
27
  }
28
28
  // The mandate is plain text the agent reads every turn (CLAUDE.md block + workflow file). It
@@ -1006,7 +1006,7 @@ function staleOwnedRules() {
1006
1006
  `This file is written by @godxjp/ui and says version ${stamped}, but the installed package ` +
1007
1007
  `is ${installed}. Its rules describe a different library than the one you are building ` +
1008
1008
  "against — most likely because `ignore-scripts=true` kept our postinstall from running.",
1009
- replacement: 'INIT_CWD="$PWD" node node_modules/@godxjp/ui/scripts/postinstall.mjs',
1009
+ replacement: "npx @godxjp/ui sync-rules",
1010
1010
  snippet: `<!-- godxjp-ui:version ${stamped} --> vs installed ${installed}`,
1011
1011
  };
1012
1012
  }