@janbox/storefront-ui 5.0.0 → 5.0.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.
@@ -14,10 +14,13 @@ import { TabContent } from '@janbox/storefront-ui';
14
14
  | ------ | ------ | ------- | ----------- |
15
15
  | `children` * | `React.ReactNode` | - | Danh sách `TabPanel`, thứ tự phải khớp với thứ tự các `Tab` trong `TabList`. |
16
16
  | `className` | `string` | - | Class cho container `div`. |
17
+ | `as` | `HTMLElementType` | `'div'` | Tag HTML của container. |
18
+ | `sx` | `ToResponsiveProps<StyledCSS>` | - | Style responsive cho container. |
19
+ | `ref` | `React.Ref<HTMLElement>` | - | Trỏ tới DOM node của container. |
17
20
 
18
- Kiểu prop là `JSX.IntrinsicElements['div']` — kế thừa toàn bộ div attributes. Component **không** nhận `sx`; dùng `className` hoặc `style` nếu cần style container.
21
+ Kiểu prop là `PrimitiveProps<JSX.IntrinsicElements['div'], 'div'>` — kế thừa toàn bộ div attributes cùng `as` và `sx` từ [Primitive](../../primitive/README.md).
19
22
 
20
- > ⚠️ `TabContent` **không** forward `ref`. `ref` trong props sẽ bị truyền vào `Primitive` như prop thường và không trỏ tới DOM node.
23
+ > React 19 coi `ref` là prop thường, nên `ref` được `Primitive` spread thẳng vào DOM node của container.
21
24
 
22
25
  *Required props
23
26
 
@@ -1,2 +1,3 @@
1
1
  import { JSX } from 'react';
2
- export type TabContentProps = JSX.IntrinsicElements['div'];
2
+ import { PrimitiveProps } from '../../primitive';
3
+ export type TabContentProps = PrimitiveProps<JSX.IntrinsicElements['div'], 'div'>;
@@ -31,7 +31,9 @@ Truyền `indicator={false}` để không render indicator.
31
31
  - Tab đang active được tìm bằng `parentElement.children.item(activeIndex)` — tức là **theo thứ tự DOM**, không qua index từ context. Vì vậy đừng chèn element không phải `Tab` vào giữa các `Tab`, nếu không indicator sẽ trỏ sai.
32
32
  - Vị trí (`left`, `top`, `width`) được tính từ `getBoundingClientRect()` của tab active so với container, có bù `scrollLeft`/`scrollTop` để đúng khi tab bar scroll ngang.
33
33
  - Một `MutationObserver` theo dõi `childList` của `TabList` để cập nhật khi số lượng `Tab` thay đổi (thêm/bớt tab động).
34
- - Một `ResizeObserver` observe cả tab active **và** container: resize container không đổi kích thước từng tab nhưng có thể làm tab xuống dòng khác khi `overflowBehavior="wrap"`, nên phải theo dõi cả hai để cập nhật vị trí dòng.
34
+ - Một `ResizeObserver` observe tab active, container **và** chính indicator:
35
+ - Container: resize container không đổi kích thước từng tab nhưng có thể làm tab xuống dòng khác khi `overflowBehavior="wrap"`, nên phải theo dõi để cập nhật vị trí dòng.
36
+ - Chính indicator: `top` phụ thuộc `offsetHeight` của nó, nên khi `size` đổi (qua prop hoặc breakpoint) vị trí phải được tính lại. Indicator là `position: absolute` nên đổi height không làm tab/container resize.
35
37
  - `top` được tính là mép dưới của tab trừ đi chiều cao indicator, nên indicator luôn nằm sát đáy tab active — kể cả khi tab wrap sang dòng thứ hai.
36
38
 
37
39
  ## Examples
@@ -1 +1,2 @@
1
- export * from './tab-indicator';
1
+ export { TabIndicator } from './tab-indicator';
2
+ export { type TabIndicatorProps } from './types';
@@ -51,15 +51,18 @@ const TabIndicator = ({ size, sm, md, lg, ...props }) => {
51
51
  });
52
52
  }, [activeTabElement]);
53
53
  useEffect(() => {
54
- var _a;
55
54
  const resizeObserver = new ResizeObserver(syncIndicatorRect);
56
- const parentElement = (_a = indicatorEl.current) == null ? void 0 : _a.parentElement;
55
+ const indicator = indicatorEl.current;
56
+ const parentElement = indicator == null ? void 0 : indicator.parentElement;
57
57
  if (activeTabElement) {
58
58
  resizeObserver.observe(activeTabElement);
59
59
  }
60
60
  if (parentElement) {
61
61
  resizeObserver.observe(parentElement);
62
62
  }
63
+ if (indicator) {
64
+ resizeObserver.observe(indicator);
65
+ }
63
66
  return () => {
64
67
  resizeObserver.disconnect();
65
68
  };
@@ -1,5 +1,5 @@
1
1
  import { flatten } from "flat";
2
- import { isNil, trim, isString, isNumber, isDate, isBoolean, isArray, isPlainObject } from "lodash-es";
2
+ import { isNil, isString, isNumber, isDate, isBoolean, isArray, isPlainObject } from "lodash-es";
3
3
  import { getEnumValues } from "./common.js";
4
4
  class QueryParamParser {
5
5
  constructor(value) {
@@ -55,7 +55,7 @@ class ArrayParamParser extends QueryParamParser {
55
55
  if (isNil(value)) {
56
56
  return void 0;
57
57
  }
58
- const parsedValue = value.split(",").map(trim).filter(Boolean);
58
+ const parsedValue = value.split(",").map((part) => part.trim()).filter(Boolean);
59
59
  return parsedValue.length ? parsedValue : void 0;
60
60
  }
61
61
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@janbox/storefront-ui",
3
- "version": "5.0.0",
3
+ "version": "5.0.2",
4
4
  "description": "Storefront UI component library for Janbox",
5
5
  "author": "Janbox",
6
6
  "keywords": [