@godxjp/ui 23.4.11 → 23.4.12

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.
@@ -155,9 +155,21 @@ interface DropdownMenuItemPropsOwn {
155
155
  textValue?: string;
156
156
  /** Mượn thẻ của con thay vì dựng `<div>` riêng — chỗ để nhét một `<Link>` vào một mục menu. */
157
157
  asChild?: boolean;
158
+ /**
159
+ * `id` và mọi `data-*` ĐI XUỐNG phần tử gốc của item (gh#631).
160
+ *
161
+ * Trigger của chính cụm này đã nhận cách xử lý ấy ở 20.0.0, với đúng lý do CHANGELOG ghi:
162
+ * "trước đó bị nuốt, nên selector e2e của consumer rời ra trong im lặng". Phần item thì chưa,
163
+ * nên hai nửa của cùng một component hành xử ngược nhau.
164
+ *
165
+ * TypeScript không bắt được: JSX luôn cho qua mọi thuộc tính có gạch nối, nên `data-testid`
166
+ * biên dịch sạch và chỉ hỏng lúc chạy. Với `id` còn tệ hơn — nó là thứ `aria-activedescendant`
167
+ * trỏ vào, và nó biến mất không một lời.
168
+ */
169
+ id?: string;
158
170
  }
159
- type DropdownMenuItemProps = React.PropsWithChildren<DropdownMenuItemPropsOwn>;
160
- export declare function DropdownMenuItem({ children, className, inset, variant, disabled, onSelect, textValue, asChild, }: DropdownMenuItemProps): React.JSX.Element;
171
+ type DropdownMenuItemProps = React.PropsWithChildren<DropdownMenuItemPropsOwn> & Record<`data-${string}`, unknown>;
172
+ export declare function DropdownMenuItem({ children, className, inset, variant, disabled, onSelect, textValue, asChild, ...forwarded }: DropdownMenuItemProps): React.JSX.Element;
161
173
  interface DropdownMenuLabelPropsOwn {
162
174
  className?: string;
163
175
  inset?: boolean;
@@ -267,22 +267,30 @@ function DropdownMenuRadioGroup({
267
267
  value,
268
268
  onValueChange
269
269
  }) {
270
- return /* @__PURE__ */ jsx(
271
- MenuSection,
272
- {
273
- "data-slot": "dropdown-menu-radio-group",
274
- className,
275
- selectionMode: "single",
276
- disallowEmptySelection: true,
277
- selectedKeys: value == null ? [] : [value],
278
- onSelectionChange: (keys) => {
279
- if (keys === "all") return;
280
- const [first] = [...keys];
281
- if (first != null) onValueChange?.(String(first));
282
- },
283
- children
270
+ const selection = {
271
+ className,
272
+ selectionMode: "single",
273
+ disallowEmptySelection: true,
274
+ selectedKeys: value == null ? [] : [value],
275
+ onSelectionChange: (keys) => {
276
+ if (keys === "all") return;
277
+ const [first] = [...keys];
278
+ if (first != null) onValueChange?.(String(first));
284
279
  }
285
- );
280
+ };
281
+ const runs = [{ label: null, items: [] }];
282
+ for (const child of React.Children.toArray(children)) {
283
+ if (React.isValidElement(child) && child.type === DropdownMenuLabel) {
284
+ runs.push({ label: child, items: [] });
285
+ } else {
286
+ runs[runs.length - 1].items.push(child);
287
+ }
288
+ }
289
+ const sections = runs.filter((run) => run.label != null || run.items.length > 0);
290
+ return /* @__PURE__ */ jsx(Fragment, { children: sections.map((run, index) => /* @__PURE__ */ jsxs(MenuSection, { "data-slot": "dropdown-menu-radio-group", ...selection, children: [
291
+ run.label,
292
+ run.items
293
+ ] }, index)) });
286
294
  }
287
295
  function DropdownMenuSub({ children }) {
288
296
  const parts = React.Children.toArray(children).filter(React.isValidElement);
@@ -372,7 +380,8 @@ function DropdownMenuItem({
372
380
  disabled,
373
381
  onSelect,
374
382
  textValue,
375
- asChild
383
+ asChild,
384
+ ...forwarded
376
385
  }) {
377
386
  const tag = borrowedTag(children, asChild);
378
387
  return /* @__PURE__ */ jsx(
@@ -394,7 +403,10 @@ function DropdownMenuItem({
394
403
  "data-slot": "dropdown-menu-item",
395
404
  "data-inset": inset,
396
405
  "data-variant": variant,
397
- ...radixItemState(state)
406
+ ...radixItemState(state),
407
+ // LAST, so a consumer's own `id`/`data-*` wins over ours rather than being
408
+ // overwritten by the slot bookkeeping above (gh#631).
409
+ ...forwarded
398
410
  },
399
411
  content
400
412
  );
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$comment": "AUTO-GENERATED by scripts/gen-measurement-contract.mjs — do not edit. Read this instead of guessing: docs/MEASUREMENT-CONTRACT.md.",
3
- "version": "23.4.11",
3
+ "version": "23.4.12",
4
4
  "targetSize": {
5
5
  "standard": "WCAG 2.2 SC 2.5.8 Target Size (Minimum), level AA — 24×24 CSS px",
6
6
  "min": 24,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@godxjp/ui",
3
- "version": "23.4.11",
4
- "godxUiMcp": "23.4.11",
3
+ "version": "23.4.12",
4
+ "godxUiMcp": "23.4.12",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",