@janbox/storefront-ui 4.0.17 → 5.0.1

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 (59) hide show
  1. package/README.md +7 -12
  2. package/dist/components/scroll-view.js +1 -1
  3. package/dist/index.js +5 -2
  4. package/dist/lib/accordion/accordion-content/accordion-content.js +1 -1
  5. package/dist/lib/button/button.js +3 -3
  6. package/dist/lib/button/helpers.js +3 -3
  7. package/dist/lib/cascader/cascader-floating-content.js +5 -5
  8. package/dist/lib/chip/chip.js +3 -3
  9. package/dist/lib/chip/helpers.d.ts +1 -1
  10. package/dist/lib/chip/helpers.js +4 -4
  11. package/dist/lib/count-up/count-up.js +1 -1
  12. package/dist/lib/date-picker/date-picker.js +3 -3
  13. package/dist/lib/drawer/drawer/drawer.js +1 -1
  14. package/dist/lib/floating/floating-content/floating-content.js +1 -1
  15. package/dist/lib/icon-button/icon-button.js +2 -2
  16. package/dist/lib/input/input.js +3 -3
  17. package/dist/lib/input-mask/input-mask.js +5 -5
  18. package/dist/lib/input-range/input-range.js +8 -8
  19. package/dist/lib/lightbox/lightbox.js +1 -1
  20. package/dist/lib/loading/image-skeleton/image-skeleton.js +1 -1
  21. package/dist/lib/notifications/notifications.js +1 -1
  22. package/dist/lib/star-rating/star-rating.js +1 -1
  23. package/dist/lib/swiper/swiper-dots-paging/swiper-dots-paging.js +1 -1
  24. package/dist/lib/tabs/README.md +92 -25
  25. package/dist/lib/tabs/tab/README.md +134 -0
  26. package/dist/lib/tabs/tab/helpers.d.ts +2 -0
  27. package/dist/lib/tabs/tab/helpers.js +17 -0
  28. package/dist/lib/tabs/tab/tab.js +51 -14
  29. package/dist/lib/tabs/tab/types.d.ts +12 -13
  30. package/dist/lib/tabs/tab-content/README.md +90 -0
  31. package/dist/lib/tabs/tab-content/tab-content.d.ts +1 -1
  32. package/dist/lib/tabs/tab-content/tab-content.js +2 -11
  33. package/dist/lib/tabs/tab-content/types.d.ts +3 -4
  34. package/dist/lib/tabs/tab-indicator/README.md +94 -0
  35. package/dist/lib/tabs/tab-indicator/index.d.ts +0 -1
  36. package/dist/lib/tabs/tab-indicator/tab-indicator.d.ts +2 -1
  37. package/dist/lib/tabs/tab-indicator/tab-indicator.js +72 -41
  38. package/dist/lib/tabs/tab-indicator/types.d.ts +5 -2
  39. package/dist/lib/tabs/tab-list/README.md +164 -0
  40. package/dist/lib/tabs/tab-list/helpers.d.ts +6 -1
  41. package/dist/lib/tabs/tab-list/helpers.js +46 -3
  42. package/dist/lib/tabs/tab-list/tab-list.js +59 -22
  43. package/dist/lib/tabs/tab-list/types.d.ts +11 -1
  44. package/dist/lib/tabs/tab-panel/README.md +86 -0
  45. package/dist/lib/tabs/tab-panel/helpers.d.ts +1 -1
  46. package/dist/lib/tabs/tab-panel/tab-panel.js +3 -5
  47. package/dist/lib/tabs/tab-panel/types.d.ts +1 -2
  48. package/dist/lib/tabs/tabs/helpers.d.ts +1 -5
  49. package/dist/lib/tabs/tabs/helpers.js +1 -20
  50. package/dist/lib/tabs/tabs/tabs.js +18 -22
  51. package/dist/lib/tabs/tabs/types.d.ts +1 -7
  52. package/dist/lib/textarea/textarea.js +3 -3
  53. package/dist/utils/common.d.ts +1 -0
  54. package/dist/utils/common.js +2 -0
  55. package/dist/utils/index.d.ts +1 -1
  56. package/dist/utils/index.js +6 -5
  57. package/dist/utils/stylesheet.d.ts +1 -1
  58. package/dist/utils/stylesheet.js +2 -2
  59. package/package.json +1 -1
@@ -0,0 +1,164 @@
1
+ # TabList
2
+
3
+ Container ngang chứa các `Tab`, đồng thời là nơi cấu hình style và hành vi overflow của tab bar. `TabList` gán index cho từng `Tab` con qua `TabIndexContext`, phân phối `tabConfig` xuống mọi `Tab` qua `TabListContext`, và render `TabIndicator` ở cuối.
4
+
5
+ Phải được dùng bên trong [Tabs](../README.md).
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { TabList } from '@janbox/storefront-ui';
11
+ ```
12
+
13
+ ## Props
14
+
15
+ | Prop | Type | Default | Description |
16
+ | ------ | ------ | ------- | ----------- |
17
+ | `overflowBehavior` | `'scroll' \| 'wrap'` | `'scroll'` | `'scroll'` cho phép scroll ngang và ẩn scrollbar; `'wrap'` cho tab xuống dòng (`flex-wrap: wrap`). Apply trên inner element. |
18
+ | `align` | `'start' \| 'center' \| 'end'` | `'start'` | Căn tab bar trong outer element qua `justify-content`. Khi tab bar hẹp hơn container, `'center'` sẽ đưa nó vào giữa. |
19
+ | `tabConfig` | `Pick<TabProps, 'sx' \| 'states'>` | Xem [Default tabConfig](#default-tabconfig) | `sx` áp dụng cho mọi `Tab` con. `states.active.sx` override cho tab đang active (match qua `[aria-selected=true]`). |
20
+ | `indicator` | `false \| TabIndicatorProps` | `{ size: 2, sx: { backgroundColor: getColorVar('primary.600') } }` | Cấu hình [TabIndicator](../tab-indicator/README.md). Truyền `false` để không render indicator. |
21
+ | `sx` | `ToResponsiveProps<StyledCSS>` | - | Responsive Emotion CSS overrides cho **inner** element. Merge sau style mặc định nên override được `display`, `width`, v.v. |
22
+ | `as` | `HTMLElementType` | `'div'` | Tag HTML của inner element. |
23
+ | `children` * | `React.ReactNode` | - | Các `Tab`. Fragment được flatten nên index vẫn đúng khi bọc trong `<>…</>`. |
24
+ | `ref` | `React.Ref<HTMLDivElement>` | - | Forwarded ref tới inner element (element chứa các `Tab`). |
25
+
26
+ Kế thừa toàn bộ `JSX.IntrinsicElements['div']` attributes — tất cả được truyền vào **inner** element, không phải outer.
27
+
28
+ *Required props
29
+
30
+ ### Cấu trúc DOM
31
+
32
+ `TabList` render hai element lồng nhau:
33
+
34
+ ```html
35
+ <!-- outer: role=tablist, nhận `align` -->
36
+ <div role="tablist" style="display: flex; justify-content: …">
37
+ <!-- inner: nhận `sx`, `ref`, `as` và mọi div attribute khác -->
38
+ <div style="display: flex; width: fit-content; max-width: 100%; position: relative">
39
+ <button aria-selected="true">…</button>
40
+ <!-- các Tab -->
41
+ <div><!-- TabIndicator --></div>
42
+ </div>
43
+ </div>
44
+ ```
45
+
46
+ Inner element có `width: fit-content` để tab bar chỉ rộng bằng tổng các tab — nhờ đó `align` trên outer mới có tác dụng. Nó cũng có `position: relative` vì `TabIndicator` định vị absolute theo element này.
47
+
48
+ ### Default tabConfig
49
+
50
+ Định nghĩa trong `tab-list/helpers.ts`, dựa trên `getSizeVariantState('md')`:
51
+
52
+ ```ts
53
+ {
54
+ sx: {
55
+ columnGap: 8,
56
+ paddingLeft: 12,
57
+ paddingRight: 12,
58
+ color: getColorVar('neutral.600'),
59
+ height: 40,
60
+ borderTopLeftRadius: 8,
61
+ borderTopRightRadius: 8,
62
+ ':hover': { backgroundColor: getColorVar('neutral.100') },
63
+ },
64
+ states: {
65
+ active: {
66
+ sx: {
67
+ color: getColorVar('primary.600'),
68
+ ':hover': { backgroundColor: getColorVar('primary.100') },
69
+ },
70
+ },
71
+ },
72
+ }
73
+ ```
74
+
75
+ `tabConfig` bạn truyền vào được **deep merge** với default trên, nên chỉ cần khai báo phần muốn đổi. Muốn xoá hoàn toàn một style mặc định, override nó bằng giá trị khác (vd: `backgroundColor: 'transparent'`) chứ không xoá key được.
76
+
77
+ ## Cách hoạt động
78
+
79
+ - Mỗi child được bọc trong `TabIndexContext.Provider value={index}` — index dựa trên thứ tự sau khi `flattenChildren`.
80
+ - `TabIndicator` được render như child **cuối cùng** của inner element. Vì `TabIndicator` tìm tab đang active bằng `parentElement.children.item(activeIndex)`, đừng chèn element không phải `Tab` vào giữa các `Tab` — index sẽ lệch.
81
+ - `role="tablist"` được set trên outer element. Nếu bạn truyền `role` qua props, nó vào inner element và **không** override được `role="tablist"` của outer.
82
+
83
+ > ⚠️ Cả hai element đang có `border` debug (`red 1px solid` ở outer, `blue 1px solid` ở inner) hardcode trong `tab-list.tsx`. Đây là style tạm khi phát triển, cần xoá trước khi release.
84
+
85
+ ## Examples
86
+
87
+ ### Căn giữa và cho tab xuống dòng
88
+
89
+ ```tsx
90
+ <Tabs sx={{ width: 300 }}>
91
+ <TabList align="center" overflowBehavior="wrap">
92
+ <Tab>Tab 1</Tab>
93
+ <Tab>Tab 2</Tab>
94
+ <Tab>Tab 3</Tab>
95
+ <Tab>Tab 4</Tab>
96
+ </TabList>
97
+ <TabContent>{/* … */}</TabContent>
98
+ </Tabs>
99
+ ```
100
+
101
+ ### Custom style cho toàn bộ Tab
102
+
103
+ ```tsx
104
+ <TabList
105
+ tabConfig={{
106
+ sx: {
107
+ height: 36,
108
+ borderRadius: 999,
109
+ ':hover': { backgroundColor: getColorVar('neutral.100') },
110
+ },
111
+ states: {
112
+ active: {
113
+ sx: {
114
+ color: getColorVar('primary.contrast'),
115
+ backgroundColor: getColorVar('primary.600'),
116
+ ':hover': { backgroundColor: getColorVar('primary.700') },
117
+ },
118
+ },
119
+ },
120
+ }}
121
+ indicator={false}
122
+ >
123
+ <Tab>All</Tab>
124
+ <Tab>Active</Tab>
125
+ <Tab>Archived</Tab>
126
+ </TabList>
127
+ ```
128
+
129
+ ### Indicator dày hơn, màu khác
130
+
131
+ ```tsx
132
+ <TabList indicator={{ size: 3, sx: { backgroundColor: getColorVar('green.600'), borderRadius: 2 } }}>
133
+ <Tab>Tab 1</Tab>
134
+ <Tab>Tab 2</Tab>
135
+ </TabList>
136
+ ```
137
+
138
+ ### Tab bar full-width, mỗi tab chia đều
139
+
140
+ `sx` apply lên inner element nên `width: '100%'` sẽ override `width: fit-content` mặc định:
141
+
142
+ ```tsx
143
+ <TabList sx={{ width: '100%' }} tabConfig={{ sx: { flex: 1, flexShrink: 1 } }}>
144
+ <Tab>Left</Tab>
145
+ <Tab>Right</Tab>
146
+ </TabList>
147
+ ```
148
+
149
+ ## Related Components
150
+
151
+ - [Tabs](../README.md)
152
+ - [Tab](../tab/README.md)
153
+ - [TabIndicator](../tab-indicator/README.md)
154
+ - [Primitive](../../primitive/README.md)
155
+
156
+ ## Dependencies
157
+
158
+ - @emotion/react
159
+
160
+ ## See Also
161
+
162
+ - [Component Source](./tab-list.tsx)
163
+ - [Storybook Stories](../tabs.stories.tsx)
164
+ - [Main README](../../../README.md)
@@ -1,2 +1,7 @@
1
- import { TabListProps } from './types';
1
+ import { TabConfig, TabListProps } from './types';
2
2
  export declare const getTabListProps: (extended: TabListProps) => TabListProps;
3
+ export type TabListContextValue = {
4
+ tabConfig?: TabConfig;
5
+ };
6
+ export declare const TabListContext: import('react').Context<TabListContextValue>;
7
+ export declare const useTabListContext: () => TabListContextValue;
@@ -1,8 +1,51 @@
1
- import { mergeComponentProps } from "../../../utils/index.js";
2
- const defaultProps = {};
1
+ import { mergeComponentProps, getSizeVariantState } from "../../../utils/index.js";
2
+ import "lodash-es";
3
+ import { getColorVar } from "../../../theme/palette.js";
4
+ import { createContext, useContext } from "react";
5
+ const { inputPaddingInline, inputSize } = getSizeVariantState("md");
6
+ const defaultProps = {
7
+ indicator: {
8
+ size: 2,
9
+ sx: {
10
+ backgroundColor: getColorVar("primary.600")
11
+ }
12
+ },
13
+ overflowBehavior: "scroll",
14
+ align: "start",
15
+ tabConfig: {
16
+ sx: {
17
+ columnGap: 8,
18
+ paddingLeft: inputPaddingInline,
19
+ paddingRight: inputPaddingInline,
20
+ color: getColorVar("neutral.600"),
21
+ height: inputSize,
22
+ borderTopLeftRadius: 8,
23
+ borderTopRightRadius: 8,
24
+ ":hover": {
25
+ backgroundColor: getColorVar("neutral.100")
26
+ }
27
+ },
28
+ states: {
29
+ active: {
30
+ sx: {
31
+ color: getColorVar("primary.600"),
32
+ ":hover": {
33
+ backgroundColor: getColorVar("primary.100")
34
+ }
35
+ }
36
+ }
37
+ }
38
+ }
39
+ };
3
40
  const getTabListProps = (extended) => {
4
41
  return mergeComponentProps(defaultProps, extended);
5
42
  };
43
+ const TabListContext = createContext({});
44
+ const useTabListContext = () => {
45
+ return useContext(TabListContext);
46
+ };
6
47
  export {
7
- getTabListProps
48
+ TabListContext,
49
+ getTabListProps,
50
+ useTabListContext
8
51
  };
@@ -1,37 +1,74 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
2
- import { getTabListProps } from "./helpers.js";
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { getTabListProps, TabListContext } from "./helpers.js";
3
3
  import { TabIndexContext } from "../tab/helpers.js";
4
4
  import { flattenChildren } from "../../../utils/index.js";
5
5
  import { scrollbarNoneStyle } from "../../../constants/emotion.js";
6
+ import { useMemo } from "react";
6
7
  import { TabIndicator } from "../tab-indicator/tab-indicator.js";
7
8
  import { Primitive } from "../../primitive/primitive.js";
8
9
  const TabList = ({ ref, children, ..._props }) => {
9
- const { sx, ...props } = getTabListProps(_props);
10
- return /* @__PURE__ */ jsxs(
10
+ const { tabConfig, overflowBehavior, indicator, align, containerProps, ...props } = getTabListProps(_props);
11
+ const alignStyle = (() => {
12
+ switch (align) {
13
+ case "end":
14
+ return {
15
+ justifyContent: "flex-end"
16
+ };
17
+ case "start":
18
+ return {
19
+ justifyContent: "flex-start"
20
+ };
21
+ case "center":
22
+ return {
23
+ justifyContent: "center"
24
+ };
25
+ default:
26
+ return {};
27
+ }
28
+ })();
29
+ const contextValue = useMemo(
30
+ () => ({
31
+ tabConfig
32
+ }),
33
+ [tabConfig]
34
+ );
35
+ return /* @__PURE__ */ jsx(TabListContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
11
36
  Primitive,
12
37
  {
38
+ ...containerProps,
13
39
  sx: {
14
40
  display: "flex",
15
- width: "fit-content",
16
- maxWidth: "100%",
17
- alignItems: "center",
18
- gap: 16,
19
- position: "relative",
20
- overflow: "auto",
21
- "& > *": {
22
- flexShrink: 0
23
- },
24
- ...scrollbarNoneStyle,
25
- ...sx
41
+ ...alignStyle,
42
+ ...containerProps == null ? void 0 : containerProps.sx
26
43
  },
27
- ...props,
28
- ref,
29
- children: [
30
- flattenChildren(children).map((child, index) => /* @__PURE__ */ jsx(TabIndexContext.Provider, { value: index, children: child }, index)),
31
- /* @__PURE__ */ jsx(TabIndicator, {})
32
- ]
44
+ children: /* @__PURE__ */ jsxs(
45
+ Primitive,
46
+ {
47
+ ...props,
48
+ role: "tablist",
49
+ sx: {
50
+ display: "flex",
51
+ width: "fit-content",
52
+ maxWidth: "100%",
53
+ alignItems: "center",
54
+ position: "relative",
55
+ ...overflowBehavior === "scroll" ? {
56
+ overflow: "auto",
57
+ ...scrollbarNoneStyle
58
+ } : {
59
+ flexWrap: "wrap"
60
+ },
61
+ ...props.sx
62
+ },
63
+ ref,
64
+ children: [
65
+ flattenChildren(children).map((child, index) => /* @__PURE__ */ jsx(TabIndexContext.Provider, { value: index, children: child }, index)),
66
+ indicator && /* @__PURE__ */ jsx(TabIndicator, { ...indicator })
67
+ ]
68
+ }
69
+ )
33
70
  }
34
- );
71
+ ) });
35
72
  };
36
73
  export {
37
74
  TabList
@@ -1,3 +1,13 @@
1
1
  import { PrimitiveProps } from '../../primitive';
2
+ import { ShallowMerge } from '../../../types';
2
3
  import { JSX } from 'react';
3
- export type TabListProps = PrimitiveProps<JSX.IntrinsicElements['div']>;
4
+ import { TabIndicatorProps } from '../tab-indicator/types';
5
+ import { TabProps } from '../tab/types';
6
+ export type TabConfig = Pick<TabProps, 'sx' | 'states'>;
7
+ export type TabListProps = PrimitiveProps<ShallowMerge<JSX.IntrinsicElements['div'], {
8
+ overflowBehavior?: 'scroll' | 'wrap';
9
+ indicator?: false | TabIndicatorProps;
10
+ align?: 'start' | 'center' | 'end';
11
+ tabConfig?: TabConfig;
12
+ containerProps?: PrimitiveProps<JSX.IntrinsicElements['div'], 'div'>;
13
+ }>, 'div'>;
@@ -0,0 +1,86 @@
1
+ # TabPanel
2
+
3
+ Wrapper cho nội dung của một tab. Là child trực tiếp của [TabContent](../tab-content/README.md), và chỉ được render khi index của nó khớp `activeIndex`.
4
+
5
+ `TabPanel` không chứa logic — nó chỉ render một `div` với các props bạn truyền vào. Việc chọn panel nào hiển thị do `TabContent` quyết định.
6
+
7
+ ## Import
8
+
9
+ ```tsx
10
+ import { TabPanel } from '@janbox/storefront-ui';
11
+ ```
12
+
13
+ ## Props
14
+
15
+ | Prop | Type | Default | Description |
16
+ | ------ | ------ | ------- | ----------- |
17
+ | `children` | `React.ReactNode` | - | Nội dung của panel. |
18
+ | `className` | `string` | - | Class cho `div`. |
19
+ | `ref` | `React.Ref<HTMLDivElement>` | - | Forwarded ref tới `div`. |
20
+
21
+ 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 panel.
22
+
23
+ ## Examples
24
+
25
+ ### Cơ bản
26
+
27
+ ```tsx
28
+ <TabContent>
29
+ <TabPanel>Content for Tab 1</TabPanel>
30
+ <TabPanel>Content for Tab 2</TabPanel>
31
+ </TabContent>
32
+ ```
33
+
34
+ ### Panel với nội dung phức tạp
35
+
36
+ ```tsx
37
+ <TabContent>
38
+ <TabPanel style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
39
+ <h3>Overview</h3>
40
+ <p>Mô tả sản phẩm…</p>
41
+ </TabPanel>
42
+ <TabPanel>
43
+ <ul>
44
+ <li>Review 1</li>
45
+ <li>Review 2</li>
46
+ </ul>
47
+ </TabPanel>
48
+ </TabContent>
49
+ ```
50
+
51
+ ### Panel kèm ARIA attributes
52
+
53
+ ```tsx
54
+ <Tabs>
55
+ <TabList>
56
+ <Tab role="tab" aria-controls="panel-overview">Overview</Tab>
57
+ <Tab role="tab" aria-controls="panel-reviews">Reviews</Tab>
58
+ </TabList>
59
+ <TabContent>
60
+ <TabPanel id="panel-overview" role="tabpanel">Overview content</TabPanel>
61
+ <TabPanel id="panel-reviews" role="tabpanel">Reviews content</TabPanel>
62
+ </TabContent>
63
+ </Tabs>
64
+ ```
65
+
66
+ > ⚠️ Panel không active bị unmount, không phải ẩn bằng CSS. Mọi state nội bộ (form input, scroll position, data đã fetch) sẽ mất khi đổi tab. Nếu cần giữ, lift state lên component cha của `Tabs`.
67
+
68
+ ## Accessibility
69
+
70
+ `TabPanel` không tự set `role="tabpanel"` hay `aria-labelledby`. Nếu cần đầy đủ ARIA tabs pattern, truyền các attribute này thủ công và ghép với `id`/`aria-controls` trên [Tab](../tab/README.md) tương ứng.
71
+
72
+ ## Related Components
73
+
74
+ - [Tabs](../README.md)
75
+ - [TabContent](../tab-content/README.md)
76
+ - [Primitive](../../primitive/README.md)
77
+
78
+ ## Dependencies
79
+
80
+ - @emotion/react
81
+
82
+ ## See Also
83
+
84
+ - [Component Source](./tab-panel.tsx)
85
+ - [Storybook Stories](../tabs.stories.tsx)
86
+ - [Main README](../../../README.md)
@@ -1,2 +1,2 @@
1
1
  import { TabPanelProps } from './types';
2
- export declare const getTabPanelProps: (extended: TabPanelProps) => TabPanelProps;
2
+ export declare const getTabPanelProps: (extended: TabPanelProps) => import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
@@ -1,11 +1,9 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { mergeComponentProps } from "../../../utils/index.js";
3
- import { useTabsContext } from "../tabs/helpers.js";
2
+ import { getTabPanelProps } from "./helpers.js";
4
3
  import { Primitive } from "../../primitive/primitive.js";
5
4
  const TabPanel = ({ children, ref, ..._props }) => {
6
- const { tabPanelProps: defaultTabPanelProps = {} } = useTabsContext();
7
- const { ...props } = mergeComponentProps(defaultTabPanelProps, _props);
8
- return /* @__PURE__ */ jsx(Primitive, { ...props, ref, children });
5
+ const { ...props } = getTabPanelProps(_props);
6
+ return /* @__PURE__ */ jsx(Primitive, { ...props, role: "tabpanel", ref, children });
9
7
  };
10
8
  export {
11
9
  TabPanel
@@ -1,3 +1,2 @@
1
1
  import { JSX } from 'react';
2
- import { PrimitiveProps } from '../../primitive';
3
- export type TabPanelProps = PrimitiveProps<JSX.IntrinsicElements['div']>;
2
+ export type TabPanelProps = JSX.IntrinsicElements['div'];
@@ -2,11 +2,7 @@ import { TabsProps } from './types';
2
2
  export declare const getTabsProps: (extended: TabsProps) => TabsProps;
3
3
  export type TabsContextValue = {
4
4
  activeIndex: number;
5
- focusTab: (index: number) => void;
6
- tabProps?: TabsProps['tabProps'];
7
- tabIndicatorProps?: TabsProps['tabIndicatorProps'];
8
- tabPanelProps?: TabsProps['tabPanelProps'];
9
- preventActiveTabChange: TabsProps['preventActiveTabChange'];
5
+ focusTab: (nextIndex: number) => void;
10
6
  };
11
7
  export declare const TabsContext: import('react').Context<TabsContextValue>;
12
8
  export declare const useTabsContext: () => TabsContextValue;
@@ -1,25 +1,6 @@
1
1
  import { createContext, useContext } from "react";
2
- import "lodash-es";
3
- import { getColorVar } from "../../../theme/palette.js";
4
2
  import { mergeComponentProps } from "../../../utils/index.js";
5
- const defaultProps = {
6
- tabProps: {
7
- color: "neutral",
8
- variant: "text",
9
- states: {
10
- active: {
11
- color: "primary",
12
- variant: "text"
13
- }
14
- }
15
- },
16
- tabIndicatorProps: {
17
- sx: {
18
- height: 2,
19
- backgroundColor: getColorVar("primary.600")
20
- }
21
- }
22
- };
3
+ const defaultProps = {};
23
4
  const getTabsProps = (extended) => {
24
5
  return mergeComponentProps(defaultProps, extended);
25
6
  };
@@ -1,39 +1,35 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { useRef, useMemo } from "react";
2
+ import { useRef, useEffect, useCallback, useMemo } from "react";
3
3
  import { getTabsProps, TabsContext } from "./helpers.js";
4
4
  import { useControllableState } from "../../../hooks/use-controllable-state.js";
5
5
  import { Primitive } from "../../primitive/primitive.js";
6
6
  const Tabs = ({ ref, children, ..._props }) => {
7
- const {
8
- defaultActiveIndex,
9
- activeIndex,
10
- onTabChange,
11
- tabProps,
12
- tabIndicatorProps,
13
- tabPanelProps,
14
- preventActiveTabChange = true,
15
- ...rest
16
- } = getTabsProps(_props);
7
+ const { defaultActiveIndex, activeIndex, onTabChange, preventActiveTabChange = true, ...rest } = getTabsProps(_props);
17
8
  const [activeTabIndex, setActiveTabIndex] = useControllableState({
18
9
  defaultValue: defaultActiveIndex ?? 0,
19
10
  value: activeIndex
20
11
  });
21
12
  const onTabChangeRef = useRef(onTabChange);
22
- onTabChangeRef.current = onTabChange;
13
+ useEffect(() => {
14
+ onTabChangeRef.current = onTabChange;
15
+ }, [onTabChange]);
16
+ const focusTab = useCallback(
17
+ (nextIndex) => {
18
+ var _a;
19
+ const isChanged = preventActiveTabChange ? nextIndex !== activeTabIndex : true;
20
+ if (isChanged) {
21
+ setActiveTabIndex(nextIndex);
22
+ (_a = onTabChangeRef.current) == null ? void 0 : _a.call(onTabChangeRef, nextIndex);
23
+ }
24
+ },
25
+ [activeTabIndex, preventActiveTabChange, setActiveTabIndex]
26
+ );
23
27
  const contextValue = useMemo(() => {
24
28
  return {
25
29
  activeIndex: activeTabIndex,
26
- focusTab: (tabIndex) => {
27
- var _a;
28
- setActiveTabIndex(tabIndex);
29
- (_a = onTabChangeRef.current) == null ? void 0 : _a.call(onTabChangeRef, tabIndex);
30
- },
31
- tabProps,
32
- tabIndicatorProps,
33
- tabPanelProps,
34
- preventActiveTabChange
30
+ focusTab
35
31
  };
36
- }, [activeTabIndex, tabProps, tabIndicatorProps, tabPanelProps, preventActiveTabChange, setActiveTabIndex]);
32
+ }, [activeTabIndex, focusTab]);
37
33
  return /* @__PURE__ */ jsx(TabsContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(Primitive, { ...rest, ref, children }) });
38
34
  };
39
35
  export {
@@ -1,15 +1,9 @@
1
1
  import { JSX } from 'react';
2
- import { TabProps } from '../tab';
3
- import { TabIndicatorProps } from '../tab-indicator';
4
- import { TabPanelProps } from '../tab-panel';
5
2
  import { PropsWithSx, ShallowMerge } from '../../../types';
6
3
  export type TabsExtendedProps = PropsWithSx<{
7
4
  activeIndex?: number;
8
5
  defaultActiveIndex?: number;
9
- onTabChange?: (tabIndex: number) => void;
10
- tabProps?: Partial<TabProps>;
11
- tabIndicatorProps?: TabIndicatorProps;
12
- tabPanelProps?: Partial<TabPanelProps>;
6
+ onTabChange?: (nextIndex: number) => void;
13
7
  preventActiveTabChange?: boolean;
14
8
  }>;
15
9
  export type TabsProps = ShallowMerge<JSX.IntrinsicElements['div'], TabsExtendedProps>;
@@ -162,10 +162,10 @@ const Textarea = ({ ref, ..._props }) => {
162
162
  );
163
163
  };
164
164
  const createStyle = ({ size } = {}) => {
165
- const { inputPaddingX, textVariant } = getSizeVariantState(size);
165
+ const { inputPaddingInline, textVariant } = getSizeVariantState(size);
166
166
  return {
167
- paddingLeft: inputPaddingX,
168
- paddingRight: inputPaddingX,
167
+ paddingLeft: inputPaddingInline,
168
+ paddingRight: inputPaddingInline,
169
169
  fontSize: textVariant ? getTypographyVar(textVariant).fontSize : void 0,
170
170
  lineHeight: textVariant ? getTypographyVar(textVariant).lineHeight : void 0
171
171
  };
@@ -16,3 +16,4 @@ export declare const parseNumber: (text?: string | number, type?: "int" | "float
16
16
  export declare function omitEmpty<T extends object>(obj?: T): T;
17
17
  export declare const getEnumValues: <T extends Dict<string | number>>(enumObject: T) => Array<T[keyof T]>;
18
18
  export declare function parseSvgString(source: string, uniqueId: string): ReactElement<import('react').SVGProps<SVGSVGElement>, "svg"> | null;
19
+ export declare const isNumber: (value: any) => value is number;
@@ -108,11 +108,13 @@ function parseSvgString(source, uniqueId) {
108
108
  const validType = "svg";
109
109
  return isValidElement(parsed) && parsed.type === validType ? parsed : null;
110
110
  }
111
+ const isNumber = (value) => typeof value === "number";
111
112
  export {
112
113
  ensureArray,
113
114
  ensureBoolean,
114
115
  getDecimalDigits,
115
116
  getEnumValues,
117
+ isNumber,
116
118
  matchSearch,
117
119
  normalizeSearchText,
118
120
  omitEmpty,
@@ -31,7 +31,7 @@ export declare const flattenChildren: (children: React.ReactNode) => ReactElemen
31
31
  export type SizeVariantState = Partial<{
32
32
  iconSize: number;
33
33
  inputSize: number;
34
- inputPaddingX: number;
34
+ inputPaddingInline: number;
35
35
  textVariant: TypographySizeVariant;
36
36
  }>;
37
37
  export declare const getSizeVariantState: (size?: SizeVariant) => SizeVariantState;
@@ -2,7 +2,7 @@ import { Children, isValidElement, Fragment } from "react";
2
2
  import { isString, isNumber, isUndefined, mergeWith, get } from "lodash-es";
3
3
  import { getSmallerScreens } from "../theme/screens.js";
4
4
  import { getColorVar } from "../theme/palette.js";
5
- import { ensureArray, ensureBoolean, getDecimalDigits, getEnumValues, matchSearch, normalizeSearchText, omitEmpty, parseNumber, parseSvgString } from "./common.js";
5
+ import { ensureArray, ensureBoolean, getDecimalDigits, getEnumValues, isNumber as isNumber2, matchSearch, normalizeSearchText, omitEmpty, parseNumber, parseSvgString } from "./common.js";
6
6
  import { ArrayParamParser, BooleanParamParser, DateParamParser, EnumParamParser, NumberParamParser, StringParamParser, simplifyQueryParams } from "./query-params.js";
7
7
  import { createUnderlineEffect } from "./stylesheet.js";
8
8
  const getColorShadesByVariant = (variant) => {
@@ -127,28 +127,28 @@ const getSizeVariantState = (size) => {
127
127
  return {
128
128
  iconSize: 20,
129
129
  inputSize: 24,
130
- inputPaddingX: 8,
130
+ inputPaddingInline: 8,
131
131
  textVariant: "xs"
132
132
  };
133
133
  case "sm":
134
134
  return {
135
135
  iconSize: 20,
136
136
  inputSize: 32,
137
- inputPaddingX: 12,
137
+ inputPaddingInline: 12,
138
138
  textVariant: "sm"
139
139
  };
140
140
  case "md":
141
141
  return {
142
142
  iconSize: 24,
143
143
  inputSize: 40,
144
- inputPaddingX: 12,
144
+ inputPaddingInline: 12,
145
145
  textVariant: "sm"
146
146
  };
147
147
  case "lg":
148
148
  return {
149
149
  iconSize: 24,
150
150
  inputSize: 48,
151
- inputPaddingX: 16,
151
+ inputPaddingInline: 16,
152
152
  textVariant: "base"
153
153
  };
154
154
  default:
@@ -253,6 +253,7 @@ export {
253
253
  getLanguageDisplayName,
254
254
  getResponsiveProp,
255
255
  getSizeVariantState,
256
+ isNumber2 as isNumber,
256
257
  matchSearch,
257
258
  mergeComponentProps,
258
259
  normalizeSearchText,