@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.
- package/README.md +7 -12
- package/dist/components/scroll-view.js +1 -1
- package/dist/index.js +5 -2
- package/dist/lib/accordion/accordion-content/accordion-content.js +1 -1
- package/dist/lib/button/button.js +3 -3
- package/dist/lib/button/helpers.js +3 -3
- package/dist/lib/cascader/cascader-floating-content.js +5 -5
- package/dist/lib/chip/chip.js +3 -3
- package/dist/lib/chip/helpers.d.ts +1 -1
- package/dist/lib/chip/helpers.js +4 -4
- package/dist/lib/count-up/count-up.js +1 -1
- package/dist/lib/date-picker/date-picker.js +3 -3
- package/dist/lib/drawer/drawer/drawer.js +1 -1
- package/dist/lib/floating/floating-content/floating-content.js +1 -1
- package/dist/lib/icon-button/icon-button.js +2 -2
- package/dist/lib/input/input.js +3 -3
- package/dist/lib/input-mask/input-mask.js +5 -5
- package/dist/lib/input-range/input-range.js +8 -8
- package/dist/lib/lightbox/lightbox.js +1 -1
- package/dist/lib/loading/image-skeleton/image-skeleton.js +1 -1
- package/dist/lib/notifications/notifications.js +1 -1
- package/dist/lib/star-rating/star-rating.js +1 -1
- package/dist/lib/swiper/swiper-dots-paging/swiper-dots-paging.js +1 -1
- package/dist/lib/tabs/README.md +92 -25
- package/dist/lib/tabs/tab/README.md +134 -0
- package/dist/lib/tabs/tab/helpers.d.ts +2 -0
- package/dist/lib/tabs/tab/helpers.js +17 -0
- package/dist/lib/tabs/tab/tab.js +51 -14
- package/dist/lib/tabs/tab/types.d.ts +12 -13
- package/dist/lib/tabs/tab-content/README.md +90 -0
- package/dist/lib/tabs/tab-content/tab-content.d.ts +1 -1
- package/dist/lib/tabs/tab-content/tab-content.js +2 -11
- package/dist/lib/tabs/tab-content/types.d.ts +3 -4
- package/dist/lib/tabs/tab-indicator/README.md +94 -0
- package/dist/lib/tabs/tab-indicator/index.d.ts +0 -1
- package/dist/lib/tabs/tab-indicator/tab-indicator.d.ts +2 -1
- package/dist/lib/tabs/tab-indicator/tab-indicator.js +72 -41
- package/dist/lib/tabs/tab-indicator/types.d.ts +5 -2
- package/dist/lib/tabs/tab-list/README.md +164 -0
- package/dist/lib/tabs/tab-list/helpers.d.ts +6 -1
- package/dist/lib/tabs/tab-list/helpers.js +46 -3
- package/dist/lib/tabs/tab-list/tab-list.js +59 -22
- package/dist/lib/tabs/tab-list/types.d.ts +11 -1
- package/dist/lib/tabs/tab-panel/README.md +86 -0
- package/dist/lib/tabs/tab-panel/helpers.d.ts +1 -1
- package/dist/lib/tabs/tab-panel/tab-panel.js +3 -5
- package/dist/lib/tabs/tab-panel/types.d.ts +1 -2
- package/dist/lib/tabs/tabs/helpers.d.ts +1 -5
- package/dist/lib/tabs/tabs/helpers.js +1 -20
- package/dist/lib/tabs/tabs/tabs.js +18 -22
- package/dist/lib/tabs/tabs/types.d.ts +1 -7
- package/dist/lib/textarea/textarea.js +3 -3
- package/dist/utils/common.d.ts +1 -0
- package/dist/utils/common.js +2 -0
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +6 -5
- package/dist/utils/stylesheet.d.ts +1 -1
- package/dist/utils/stylesheet.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -140,12 +140,7 @@ export const Button = ({ ref, ..._props }: ButtonProps) => {
|
|
|
140
140
|
const { size, variant, color, children, ...rest } = getButtonProps(_props);
|
|
141
141
|
|
|
142
142
|
// 2. Build CSS từ helpers
|
|
143
|
-
const css = [
|
|
144
|
-
getButtonCssBySize(size),
|
|
145
|
-
getButtonCssByVariant(variant),
|
|
146
|
-
getButtonCssByColor(color),
|
|
147
|
-
createSxInterpolation(sx),
|
|
148
|
-
];
|
|
143
|
+
const css = [getButtonCssBySize(size), getButtonCssByVariant(variant), getButtonCssByColor(color), createSxStyle(sx)];
|
|
149
144
|
|
|
150
145
|
// 3. Render với Primitive hoặc native element
|
|
151
146
|
return (
|
|
@@ -287,12 +282,12 @@ Hầu hết components hỗ trợ 4 size variants:
|
|
|
287
282
|
|
|
288
283
|
**Size mapping:**
|
|
289
284
|
|
|
290
|
-
| size | iconSize | inputSize |
|
|
291
|
-
| ---- | -------- | --------- |
|
|
292
|
-
| `xs` | 20px | 24px | 8px
|
|
293
|
-
| `sm` | 20px | 32px | 12px
|
|
294
|
-
| `md` | 24px | 40px | 12px
|
|
295
|
-
| `lg` | 24px | 48px | 16px
|
|
285
|
+
| size | iconSize | inputSize | inputPaddingInline | textVariant |
|
|
286
|
+
| ---- | -------- | --------- | ------------------ | ----------- |
|
|
287
|
+
| `xs` | 20px | 24px | 8px | `xs` |
|
|
288
|
+
| `sm` | 20px | 32px | 12px | `sm` |
|
|
289
|
+
| `md` | 24px | 40px | 12px | `sm` |
|
|
290
|
+
| `lg` | 24px | 48px | 16px | `base` |
|
|
296
291
|
|
|
297
292
|
### Color Variants
|
|
298
293
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Stylesheet } from "../lib/stylesheet/stylesheet.js";
|
|
3
2
|
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
|
|
3
|
+
import { Stylesheet } from "../lib/stylesheet/stylesheet.js";
|
|
4
4
|
const ScrollView = ({ children, options, sx, ...props }) => {
|
|
5
5
|
return /* @__PURE__ */ jsx(Stylesheet, { children: ({ cx, css }) => /* @__PURE__ */ jsx(
|
|
6
6
|
OverlayScrollbarsComponent,
|
package/dist/index.js
CHANGED
|
@@ -89,8 +89,9 @@ import { SwiperSlide } from "./lib/swiper/swiper-slide/swiper-slide.js";
|
|
|
89
89
|
import { Switch } from "./lib/switch/switch.js";
|
|
90
90
|
import { Tab } from "./lib/tabs/tab/tab.js";
|
|
91
91
|
import { TabContent } from "./lib/tabs/tab-content/tab-content.js";
|
|
92
|
-
import { TabIndexContext, useTabIndexContext } from "./lib/tabs/tab/helpers.js";
|
|
92
|
+
import { TabIndexContext, useGetTabProps, useTabIndexContext } from "./lib/tabs/tab/helpers.js";
|
|
93
93
|
import { TabList } from "./lib/tabs/tab-list/tab-list.js";
|
|
94
|
+
import { TabListContext, getTabListProps, useTabListContext } from "./lib/tabs/tab-list/helpers.js";
|
|
94
95
|
import { TabPanel } from "./lib/tabs/tab-panel/tab-panel.js";
|
|
95
96
|
import { Table } from "./lib/table/table/table.js";
|
|
96
97
|
import { TableBody } from "./lib/table/table-body/table-body.js";
|
|
@@ -135,7 +136,6 @@ import { getPriceLabelProps } from "./lib/price-label/helpers.js";
|
|
|
135
136
|
import { getRadioButtonProps } from "./lib/radio-button/helpers.js";
|
|
136
137
|
import { getStarRatingProps } from "./lib/star-rating/helpers.js";
|
|
137
138
|
import { getSwiperProps } from "./lib/swiper/swiper/helpers.js";
|
|
138
|
-
import { getTabListProps } from "./lib/tabs/tab-list/helpers.js";
|
|
139
139
|
import { getTabPanelProps } from "./lib/tabs/tab-panel/helpers.js";
|
|
140
140
|
import { getTextCssByVariant, getTextProps } from "./lib/text/helpers.js";
|
|
141
141
|
import { getTextareaProps } from "./lib/textarea/helpers.js";
|
|
@@ -241,6 +241,7 @@ export {
|
|
|
241
241
|
TabContent,
|
|
242
242
|
TabIndexContext,
|
|
243
243
|
TabList,
|
|
244
|
+
TabListContext,
|
|
244
245
|
TabPanel,
|
|
245
246
|
Table,
|
|
246
247
|
TableBody,
|
|
@@ -308,8 +309,10 @@ export {
|
|
|
308
309
|
useDialogContext,
|
|
309
310
|
useDrawerContext,
|
|
310
311
|
useFloatingContext,
|
|
312
|
+
useGetTabProps,
|
|
311
313
|
useNotifications,
|
|
312
314
|
usePopoverContext,
|
|
313
315
|
useTabIndexContext,
|
|
316
|
+
useTabListContext,
|
|
314
317
|
useTabsContext
|
|
315
318
|
};
|
|
@@ -3,8 +3,8 @@ import { useRef } from "react";
|
|
|
3
3
|
import { motion } from "motion/react";
|
|
4
4
|
import { getAccordionContentProps } from "./helpers.js";
|
|
5
5
|
import { useAccordionContext } from "../accordion/helpers.js";
|
|
6
|
-
import { Stylesheet } from "../../stylesheet/stylesheet.js";
|
|
7
6
|
import { useAccordionGroupContext } from "../accordion-group/helpers.js";
|
|
7
|
+
import { Stylesheet } from "../../stylesheet/stylesheet.js";
|
|
8
8
|
import { Primitive } from "../../primitive/primitive.js";
|
|
9
9
|
const AccordionContent = ({ children, ref, ..._props }) => {
|
|
10
10
|
const { accordionContentProps: accordionContentPropsByGroup = {} } = useAccordionGroupContext();
|
|
@@ -8,7 +8,7 @@ import LoadingIcon from "../../assets/svg/loading-waiting.svg.js";
|
|
|
8
8
|
import { mediaQuery } from "../../theme/screens.js";
|
|
9
9
|
import { getColorVar } from "../../theme/palette.js";
|
|
10
10
|
import { getColorShadesByVariant, getSizeVariantState } from "../../utils/index.js";
|
|
11
|
-
import {
|
|
11
|
+
import { createSxStyle } from "../../utils/stylesheet.js";
|
|
12
12
|
import { RippleEffect } from "../ripple-effect/ripple-effect.js";
|
|
13
13
|
import { Icon } from "../icon/icon.js";
|
|
14
14
|
import { Primitive } from "../primitive/primitive.js";
|
|
@@ -114,7 +114,7 @@ const Button = ({ children, ref, ..._props }) => {
|
|
|
114
114
|
[mediaQuery("md")]: createStyle(md),
|
|
115
115
|
[mediaQuery("lg")]: createStyle(lg)
|
|
116
116
|
},
|
|
117
|
-
|
|
117
|
+
createSxStyle(sx)
|
|
118
118
|
];
|
|
119
119
|
const onClick = (e) => {
|
|
120
120
|
var _a;
|
|
@@ -133,7 +133,7 @@ const Button = ({ children, ref, ..._props }) => {
|
|
|
133
133
|
try {
|
|
134
134
|
const url = new URL(href);
|
|
135
135
|
window.location.href = url.toString();
|
|
136
|
-
} catch (
|
|
136
|
+
} catch (_error) {
|
|
137
137
|
navigate(href, otherOptions);
|
|
138
138
|
}
|
|
139
139
|
}
|
|
@@ -16,10 +16,10 @@ const defaultProps = {
|
|
|
16
16
|
type: "button"
|
|
17
17
|
};
|
|
18
18
|
const getButtonCssBySize = (size) => {
|
|
19
|
-
const { inputSize,
|
|
19
|
+
const { inputSize, inputPaddingInline } = getSizeVariantState(size);
|
|
20
20
|
const css = {
|
|
21
|
-
paddingLeft:
|
|
22
|
-
paddingRight:
|
|
21
|
+
paddingLeft: inputPaddingInline,
|
|
22
|
+
paddingRight: inputPaddingInline,
|
|
23
23
|
minHeight: inputSize
|
|
24
24
|
};
|
|
25
25
|
switch (size) {
|
|
@@ -160,7 +160,7 @@ const CascaderFloatingContent = ({
|
|
|
160
160
|
});
|
|
161
161
|
}, [inputValue, currentOptions]);
|
|
162
162
|
const responsiveSize = isNil(windowScreen.name) ? void 0 : getResponsiveProp({ sm, md, lg }, "size", windowScreen.name) ?? size;
|
|
163
|
-
const { inputSize: rowMinHeight = 0,
|
|
163
|
+
const { inputSize: rowMinHeight = 0, inputPaddingInline } = getSizeVariantState(responsiveSize);
|
|
164
164
|
const onInputChange = (e) => {
|
|
165
165
|
var _a;
|
|
166
166
|
e.target.value = trimStart(e.target.value);
|
|
@@ -193,8 +193,8 @@ const CascaderFloatingContent = ({
|
|
|
193
193
|
Primitive,
|
|
194
194
|
{
|
|
195
195
|
sx: {
|
|
196
|
-
paddingLeft:
|
|
197
|
-
paddingRight:
|
|
196
|
+
paddingLeft: inputPaddingInline,
|
|
197
|
+
paddingRight: inputPaddingInline,
|
|
198
198
|
minHeight: rowMinHeight,
|
|
199
199
|
borderTop: `1px solid ${getColorVar("neutral.200")}`,
|
|
200
200
|
display: "flex",
|
|
@@ -292,8 +292,8 @@ const CascaderFloatingContent = ({
|
|
|
292
292
|
onClick: handleSelect,
|
|
293
293
|
sx: {
|
|
294
294
|
minHeight: rowMinHeight,
|
|
295
|
-
paddingLeft:
|
|
296
|
-
paddingRight:
|
|
295
|
+
paddingLeft: inputPaddingInline,
|
|
296
|
+
paddingRight: inputPaddingInline,
|
|
297
297
|
paddingBlock: 4,
|
|
298
298
|
display: "flex",
|
|
299
299
|
alignItems: "center",
|
package/dist/lib/chip/chip.js
CHANGED
|
@@ -42,10 +42,10 @@ const Chip = ({ children, ..._props }) => {
|
|
|
42
42
|
);
|
|
43
43
|
};
|
|
44
44
|
const createStyle = ({ size } = {}) => {
|
|
45
|
-
const { inputSize,
|
|
45
|
+
const { inputSize, paddingInline, textVariant, rounded } = getChipSizeState(size);
|
|
46
46
|
return {
|
|
47
|
-
paddingLeft:
|
|
48
|
-
paddingRight:
|
|
47
|
+
paddingLeft: paddingInline,
|
|
48
|
+
paddingRight: paddingInline,
|
|
49
49
|
minHeight: inputSize,
|
|
50
50
|
fontSize: textVariant ? getTypographyVar(textVariant).fontSize : void 0,
|
|
51
51
|
lineHeight: textVariant ? getTypographyVar(textVariant).lineHeight : void 0,
|
|
@@ -3,7 +3,7 @@ import { TypographySizeVariant } from '../../theme';
|
|
|
3
3
|
import { ChipProps } from './types';
|
|
4
4
|
export declare const getChipSizeState: (size?: SizeVariant) => Partial<{
|
|
5
5
|
inputSize: number;
|
|
6
|
-
|
|
6
|
+
paddingInline: number;
|
|
7
7
|
textVariant: TypographySizeVariant;
|
|
8
8
|
rounded: number;
|
|
9
9
|
}>;
|
package/dist/lib/chip/helpers.js
CHANGED
|
@@ -6,13 +6,13 @@ const defaultProps = {
|
|
|
6
6
|
const getChipSizeState = (size) => {
|
|
7
7
|
switch (size) {
|
|
8
8
|
case "xs":
|
|
9
|
-
return { inputSize: 20,
|
|
9
|
+
return { inputSize: 20, paddingInline: 6, textVariant: "xs", rounded: 4 };
|
|
10
10
|
case "sm":
|
|
11
|
-
return { inputSize: 24,
|
|
11
|
+
return { inputSize: 24, paddingInline: 8, textVariant: "xs", rounded: 6 };
|
|
12
12
|
case "md":
|
|
13
|
-
return { inputSize: 28,
|
|
13
|
+
return { inputSize: 28, paddingInline: 10, textVariant: "sm", rounded: 8 };
|
|
14
14
|
case "lg":
|
|
15
|
-
return { inputSize: 32,
|
|
15
|
+
return { inputSize: 32, paddingInline: 12, textVariant: "sm", rounded: 8 };
|
|
16
16
|
default:
|
|
17
17
|
return {};
|
|
18
18
|
}
|
|
@@ -7,9 +7,9 @@ import { useTranslation } from "../../i18n/index.js";
|
|
|
7
7
|
import "lodash-es";
|
|
8
8
|
import "../../theme/palette.js";
|
|
9
9
|
import { getTypographyVar } from "../../theme/typography.js";
|
|
10
|
-
import { Stylesheet } from "../stylesheet/stylesheet.js";
|
|
11
10
|
import { getCountUpProps } from "./helpers.js";
|
|
12
11
|
import { getDecimalDigits } from "../../utils/common.js";
|
|
12
|
+
import { Stylesheet } from "../stylesheet/stylesheet.js";
|
|
13
13
|
const CountUp = ({ ref, ..._props }) => {
|
|
14
14
|
const {
|
|
15
15
|
from = 0,
|
|
@@ -11,7 +11,7 @@ import "lodash-es";
|
|
|
11
11
|
import { getColorVar } from "../../theme/palette.js";
|
|
12
12
|
import { getTypographyVar } from "../../theme/typography.js";
|
|
13
13
|
import CloseIcon from "../../assets/svg/times-close-delete.svg.js";
|
|
14
|
-
import {
|
|
14
|
+
import { createSxStyle } from "../../utils/stylesheet.js";
|
|
15
15
|
import { TimePicker } from "../time-picker/time-picker.js";
|
|
16
16
|
import { Floating } from "../floating/floating/floating.js";
|
|
17
17
|
import { FloatingTrigger } from "../floating/floating-trigger/floating-trigger.js";
|
|
@@ -193,8 +193,8 @@ const DatePicker = (_props, ref) => {
|
|
|
193
193
|
flexDirection: "column",
|
|
194
194
|
width: "100%"
|
|
195
195
|
},
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
createSxStyle(sx),
|
|
197
|
+
createSxStyle(containerSx)
|
|
198
198
|
],
|
|
199
199
|
children: [
|
|
200
200
|
/* @__PURE__ */ jsxs(
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo } from "react";
|
|
3
3
|
import { motion } from "motion/react";
|
|
4
|
-
import { Stylesheet } from "../../stylesheet/stylesheet.js";
|
|
5
4
|
import { Floating } from "../../floating/floating/floating.js";
|
|
6
5
|
import { FloatingContent } from "../../floating/floating-content/floating-content.js";
|
|
7
6
|
import { Primitive } from "../../primitive/primitive.js";
|
|
7
|
+
import { Stylesheet } from "../../stylesheet/stylesheet.js";
|
|
8
8
|
const Drawer = ({ children, placement = "left", ...props }) => {
|
|
9
9
|
const initial = useMemo(() => {
|
|
10
10
|
switch (placement) {
|
|
@@ -4,8 +4,8 @@ import { motion, AnimatePresence } from "motion/react";
|
|
|
4
4
|
import { useFloatingContext } from "../floating/helpers.js";
|
|
5
5
|
import { FLOATING_Z_INDEX } from "../../../theme/index.js";
|
|
6
6
|
import { useIsHydrated } from "../../../hooks/use-is-hydrated/index.js";
|
|
7
|
-
import { Stylesheet } from "../../stylesheet/stylesheet.js";
|
|
8
7
|
import { usePortalContainer } from "../../../theme/provider.js";
|
|
8
|
+
import { Stylesheet } from "../../stylesheet/stylesheet.js";
|
|
9
9
|
const FloatingContent = ({ preserveTabOrder, focus, overlay, sx, ref, ...props }) => {
|
|
10
10
|
const { getFloatingProps, context } = useFloatingContext();
|
|
11
11
|
const mergedRefs = useMergeRefs([context.refs.setFloating, ref]);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx } from "@emotion/react/jsx-runtime";
|
|
2
2
|
import { getIconButtonProps } from "./helpers.js";
|
|
3
|
-
import {
|
|
3
|
+
import { createSxStyle } from "../../utils/stylesheet.js";
|
|
4
4
|
import LoadingIcon from "../../assets/svg/loading-waiting.svg.js";
|
|
5
5
|
import { mediaQuery } from "../../theme/screens.js";
|
|
6
6
|
import { getColorVar } from "../../theme/palette.js";
|
|
@@ -92,7 +92,7 @@ const IconButton = ({ children, ref, ..._props }) => {
|
|
|
92
92
|
[mediaQuery("md")]: createStyle(md),
|
|
93
93
|
[mediaQuery("lg")]: createStyle(lg)
|
|
94
94
|
},
|
|
95
|
-
|
|
95
|
+
createSxStyle(sx)
|
|
96
96
|
];
|
|
97
97
|
const onClick = (e) => {
|
|
98
98
|
var _a;
|
package/dist/lib/input/input.js
CHANGED
|
@@ -252,10 +252,10 @@ const Input = ({ ref, ..._props }) => {
|
|
|
252
252
|
);
|
|
253
253
|
};
|
|
254
254
|
const createStyle = ({ size } = {}) => {
|
|
255
|
-
const {
|
|
255
|
+
const { inputPaddingInline, inputSize, textVariant } = getSizeVariantState(size);
|
|
256
256
|
return {
|
|
257
|
-
paddingLeft:
|
|
258
|
-
paddingRight:
|
|
257
|
+
paddingLeft: inputPaddingInline,
|
|
258
|
+
paddingRight: inputPaddingInline,
|
|
259
259
|
height: inputSize,
|
|
260
260
|
fontSize: textVariant ? getTypographyVar(textVariant).fontSize : void 0,
|
|
261
261
|
lineHeight: textVariant ? getTypographyVar(textVariant).lineHeight : void 0
|
|
@@ -4,7 +4,7 @@ import { getInputMaskProps } from "./helpers.js";
|
|
|
4
4
|
import { mediaQuery } from "../../theme/screens.js";
|
|
5
5
|
import { getColorVar } from "../../theme/palette.js";
|
|
6
6
|
import { getSizeVariantState } from "../../utils/index.js";
|
|
7
|
-
import {
|
|
7
|
+
import { createSxStyle } from "../../utils/stylesheet.js";
|
|
8
8
|
import { Primitive } from "../primitive/primitive.js";
|
|
9
9
|
import { Icon } from "../icon/icon.js";
|
|
10
10
|
const InputMask = (_props, ref) => {
|
|
@@ -37,7 +37,7 @@ const InputMask = (_props, ref) => {
|
|
|
37
37
|
[mediaQuery("md")]: createStyle(md),
|
|
38
38
|
[mediaQuery("lg")]: createStyle(lg)
|
|
39
39
|
},
|
|
40
|
-
|
|
40
|
+
createSxStyle(sx)
|
|
41
41
|
];
|
|
42
42
|
return /* @__PURE__ */ jsxs(Primitive, { css, ...props, ref, children: [
|
|
43
43
|
prefix,
|
|
@@ -85,12 +85,12 @@ const InputMask = (_props, ref) => {
|
|
|
85
85
|
};
|
|
86
86
|
const ForwardRefInputMask = forwardRef(InputMask);
|
|
87
87
|
const createStyle = ({ size, outline } = {}) => {
|
|
88
|
-
const { inputSize,
|
|
88
|
+
const { inputSize, inputPaddingInline } = getSizeVariantState(size);
|
|
89
89
|
return [
|
|
90
90
|
{
|
|
91
91
|
minHeight: inputSize,
|
|
92
|
-
paddingLeft:
|
|
93
|
-
paddingRight:
|
|
92
|
+
paddingLeft: inputPaddingInline,
|
|
93
|
+
paddingRight: inputPaddingInline,
|
|
94
94
|
":after": {
|
|
95
95
|
borderTopWidth: outline == null ? void 0 : outline.top,
|
|
96
96
|
borderRightWidth: outline == null ? void 0 : outline.right,
|
|
@@ -64,8 +64,8 @@ const InputRange = ({ ref: _ref, ..._props }) => {
|
|
|
64
64
|
borderStyle: "solid",
|
|
65
65
|
borderRadius: "0.5rem",
|
|
66
66
|
gap: "0.5rem",
|
|
67
|
-
paddingLeft: getSizeVariantState(size).
|
|
68
|
-
paddingRight: getSizeVariantState(size).
|
|
67
|
+
paddingLeft: getSizeVariantState(size).inputPaddingInline,
|
|
68
|
+
paddingRight: getSizeVariantState(size).inputPaddingInline,
|
|
69
69
|
"&:has(input:focus)": {
|
|
70
70
|
borderColor: getColorVar("primary.600"),
|
|
71
71
|
boxShadow: `0 1px 3px 0 ${getColorVar("primary.300")}, 0 1px 2px -1px ${getColorVar("primary.300")}`
|
|
@@ -74,16 +74,16 @@ const InputRange = ({ ref: _ref, ..._props }) => {
|
|
|
74
74
|
borderColor: getColorVar("primary.300")
|
|
75
75
|
},
|
|
76
76
|
sm: {
|
|
77
|
-
paddingLeft: getSizeVariantState(sm == null ? void 0 : sm.size).
|
|
78
|
-
paddingRight: getSizeVariantState(sm == null ? void 0 : sm.size).
|
|
77
|
+
paddingLeft: getSizeVariantState(sm == null ? void 0 : sm.size).inputPaddingInline,
|
|
78
|
+
paddingRight: getSizeVariantState(sm == null ? void 0 : sm.size).inputPaddingInline
|
|
79
79
|
},
|
|
80
80
|
md: {
|
|
81
|
-
paddingLeft: getSizeVariantState(md == null ? void 0 : md.size).
|
|
82
|
-
paddingRight: getSizeVariantState(md == null ? void 0 : md.size).
|
|
81
|
+
paddingLeft: getSizeVariantState(md == null ? void 0 : md.size).inputPaddingInline,
|
|
82
|
+
paddingRight: getSizeVariantState(md == null ? void 0 : md.size).inputPaddingInline
|
|
83
83
|
},
|
|
84
84
|
lg: {
|
|
85
|
-
paddingLeft: getSizeVariantState(lg == null ? void 0 : lg.size).
|
|
86
|
-
paddingRight: getSizeVariantState(lg == null ? void 0 : lg.size).
|
|
85
|
+
paddingLeft: getSizeVariantState(lg == null ? void 0 : lg.size).inputPaddingInline,
|
|
86
|
+
paddingRight: getSizeVariantState(lg == null ? void 0 : lg.size).inputPaddingInline
|
|
87
87
|
}
|
|
88
88
|
},
|
|
89
89
|
children: [
|
|
@@ -10,12 +10,12 @@ import ZoomPlusIcon from "../../assets/svg/search-add-plus-middle.svg.js";
|
|
|
10
10
|
import ZoomMinusIcon from "../../assets/svg/search-minus.svg.js";
|
|
11
11
|
import CloseIcon from "../../assets/svg/times-close-delete.svg.js";
|
|
12
12
|
import { FLOATING_Z_INDEX } from "../../theme/index.js";
|
|
13
|
-
import { Stylesheet } from "../stylesheet/stylesheet.js";
|
|
14
13
|
import { Swiper } from "../swiper/swiper/swiper.js";
|
|
15
14
|
import { SwiperSlide } from "../swiper/swiper-slide/swiper-slide.js";
|
|
16
15
|
import { Floating } from "../floating/floating/floating.js";
|
|
17
16
|
import { FloatingContent } from "../floating/floating-content/floating-content.js";
|
|
18
17
|
import { Primitive } from "../primitive/primitive.js";
|
|
18
|
+
import { Stylesheet } from "../stylesheet/stylesheet.js";
|
|
19
19
|
import { Image } from "../image/image.js";
|
|
20
20
|
import { FloatingClose } from "../floating/floating-close/floating-close.js";
|
|
21
21
|
import { IconButton } from "../icon-button/icon-button.js";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { animatePulseStyle } from "../../../constants/emotion.js";
|
|
3
|
-
import { Stylesheet } from "../../stylesheet/stylesheet.js";
|
|
4
3
|
import "lodash-es";
|
|
5
4
|
import { getColorVar } from "../../../theme/palette.js";
|
|
6
5
|
import { Primitive } from "../../primitive/primitive.js";
|
|
6
|
+
import { Stylesheet } from "../../stylesheet/stylesheet.js";
|
|
7
7
|
const ImageSkeleton = (props) => {
|
|
8
8
|
return /* @__PURE__ */ jsx(
|
|
9
9
|
Primitive,
|
|
@@ -7,9 +7,9 @@ import { notificationStore } from "./helpers.js";
|
|
|
7
7
|
import { getColorShadesByVariant } from "../../utils/index.js";
|
|
8
8
|
import { FLOATING_Z_INDEX } from "../../theme/index.js";
|
|
9
9
|
import CloseIcon from "../../assets/svg/times-close-delete.svg.js";
|
|
10
|
-
import { Stylesheet } from "../stylesheet/stylesheet.js";
|
|
11
10
|
import { usePortalContainer } from "../../theme/provider.js";
|
|
12
11
|
import { Primitive } from "../primitive/primitive.js";
|
|
12
|
+
import { Stylesheet } from "../stylesheet/stylesheet.js";
|
|
13
13
|
import { getTypographyVar } from "../../theme/typography.js";
|
|
14
14
|
import { IconButton } from "../icon-button/icon-button.js";
|
|
15
15
|
const Notifications = () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useId } from "react";
|
|
3
|
-
import { Stylesheet } from "../stylesheet/stylesheet.js";
|
|
4
3
|
import { getStarRatingProps } from "./helpers.js";
|
|
4
|
+
import { Stylesheet } from "../stylesheet/stylesheet.js";
|
|
5
5
|
const StarRating = (_props) => {
|
|
6
6
|
const { rating, maxRating, size, sm, md, lg, ref, color, sx } = getStarRatingProps(_props);
|
|
7
7
|
const id = useId();
|
|
@@ -6,8 +6,8 @@ import { motion } from "motion/react";
|
|
|
6
6
|
import { getColorVar } from "../../../theme/palette.js";
|
|
7
7
|
import { usePortalContainer } from "../../../theme/provider.js";
|
|
8
8
|
import { useIsHydrated } from "../../../hooks/use-is-hydrated/index.js";
|
|
9
|
-
import { Stylesheet } from "../../stylesheet/stylesheet.js";
|
|
10
9
|
import { Primitive } from "../../primitive/primitive.js";
|
|
10
|
+
import { Stylesheet } from "../../stylesheet/stylesheet.js";
|
|
11
11
|
const SWIPER_DOTS_SIZE_VAR = "--swiper-dots-size";
|
|
12
12
|
const SWIPER_DOTS_OFFSET_VAR = "--swiper-dots-offset";
|
|
13
13
|
const SWIPER_DOTS_SPACING_VAR = "--swiper-dots-spacing";
|
package/dist/lib/tabs/README.md
CHANGED
|
@@ -1,35 +1,48 @@
|
|
|
1
1
|
# Tabs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Compound component để chuyển đổi giữa các panel nội dung. `Tabs` quản lý active tab index (controlled hoặc uncontrolled) và cung cấp `activeIndex` + hàm `focusTab` xuống sub-components qua context: `TabList`, `Tab`, `TabContent`, `TabPanel`, `TabIndicator`.
|
|
4
|
+
|
|
5
|
+
Việc styling các tab được cấu hình ở `TabList` (`tabConfig`, `indicator`, `align`, `overflowBehavior`), không phải ở `Tabs`.
|
|
4
6
|
|
|
5
7
|
## Import
|
|
6
8
|
|
|
7
9
|
```tsx
|
|
8
|
-
import { Tabs } from '@janbox/storefront-ui';
|
|
10
|
+
import { Tabs, TabList, Tab, TabContent, TabPanel } from '@janbox/storefront-ui';
|
|
9
11
|
```
|
|
10
12
|
|
|
11
13
|
## Props
|
|
12
14
|
|
|
13
15
|
| Prop | Type | Default | Description |
|
|
14
|
-
|
|
15
|
-
| `activeIndex` | `number` | - | Controlled active tab index.
|
|
16
|
-
| `defaultActiveIndex` | `number` | `0` |
|
|
17
|
-
| `onTabChange` | `(
|
|
18
|
-
| `tabProps` | `Partial<TabProps>` | `{ color: 'neutral', variant: 'text', states: { active: { color: 'primary', variant: 'text' } } }` | Default props applied to every Tab child. Inactive tabs default to `color='neutral'`, active tab overrides to `color='primary'`. |
|
|
19
|
-
| `tabIndicatorProps` | `TabIndicatorProps` | `{ sx: { height: 2, backgroundColor: 'var(--color-primary-600)' } }` | Props forwarded to the TabIndicator element, cho phép custom `sx` styles trên thanh gạch chân của tab đang active. |
|
|
20
|
-
| `tabPanelProps` | `Partial<TabPanelProps>` | - | Default props applied to every TabPanel child. |
|
|
16
|
+
| ------ | ------ | ------- | ----------- |
|
|
17
|
+
| `activeIndex` | `number` | - | Controlled active tab index. Khi được cung cấp, component chuyển sang controlled mode và state nội bộ không tự đổi. |
|
|
18
|
+
| `defaultActiveIndex` | `number` | `0` | Active tab index ban đầu cho uncontrolled usage. |
|
|
19
|
+
| `onTabChange` | `(nextIndex: number) => void` | - | Callback được gọi khi active tab thay đổi, nhận index mới. |
|
|
21
20
|
| `preventActiveTabChange` | `boolean` | `true` | Khi `true`, click vào tab đang active sẽ không re-fire `onTabChange`. |
|
|
22
21
|
| `sx` | `ToResponsiveProps<StyledCSS>` | - | Responsive Emotion CSS overrides cho root wrapper `div`. |
|
|
23
22
|
| `children` * | `React.ReactNode` | - | Phải là composition của `TabList` (chứa các `Tab`) và `TabContent` (chứa các `TabPanel`). |
|
|
23
|
+
| `ref` | `React.Ref<HTMLDivElement>` | - | Forwarded ref tới root `div`. |
|
|
24
|
+
|
|
25
|
+
Kế thừa toàn bộ `JSX.IntrinsicElements['div']` attributes.
|
|
24
26
|
|
|
25
27
|
*Required props
|
|
26
28
|
|
|
29
|
+
## Cách hoạt động
|
|
30
|
+
|
|
31
|
+
- **Index của mỗi Tab**: `TabList` flatten children và bọc mỗi child trong `TabIndexContext.Provider` với index tương ứng. `Tab` đọc index này để so với `activeIndex` từ `TabsContext`.
|
|
32
|
+
- **Click handling**: mỗi `Tab` tự gắn `onClick` và gọi `focusTab(tabIndex)` lấy từ `TabsContext`. `focusTab` kiểm tra `preventActiveTabChange` rồi cập nhật state và gọi `onTabChange`. `onClick` bạn truyền vào `Tab` vẫn được gọi sau đó.
|
|
33
|
+
- **Styling**: `TabList` truyền `tabConfig` xuống mọi `Tab` con qua `TabListContext`. Mỗi `Tab` merge theo thứ tự `defaultProps` → `tabConfig` → props của chính nó, nên prop trực tiếp trên `Tab` luôn thắng.
|
|
34
|
+
- **Panel rendering**: `TabContent` chỉ render đúng một child tại `activeIndex` — các `TabPanel` khác bị unmount, state nội bộ của chúng không được giữ lại.
|
|
35
|
+
|
|
36
|
+
> ⚠️ `Tab` phải nằm trong cả `Tabs` và `TabList`. Ngoài `Tabs` thì `focusTab` là `undefined` và click sẽ throw; ngoài `TabList` thì index luôn là `-1` nên không tab nào active được.
|
|
37
|
+
>
|
|
38
|
+
> ⚠️ Ở controlled mode (`activeIndex` được truyền), state nội bộ không tự đổi — bạn phải cập nhật `activeIndex` trong `onTabChange`, nếu không tab sẽ không chuyển.
|
|
39
|
+
|
|
27
40
|
## Examples
|
|
28
41
|
|
|
29
42
|
### Basic uncontrolled tabs
|
|
30
43
|
|
|
31
44
|
```tsx
|
|
32
|
-
<Tabs defaultActiveIndex={0} onTabChange={(i) => console.log(i)}
|
|
45
|
+
<Tabs defaultActiveIndex={0} onTabChange={(i) => console.log(i)} sx={{ width: 500 }}>
|
|
33
46
|
<TabList>
|
|
34
47
|
<Tab>Tab 1</Tab>
|
|
35
48
|
<Tab>Tab 2</Tab>
|
|
@@ -43,12 +56,12 @@ import { Tabs } from '@janbox/storefront-ui';
|
|
|
43
56
|
</Tabs>
|
|
44
57
|
```
|
|
45
58
|
|
|
46
|
-
### Controlled tabs
|
|
59
|
+
### Controlled tabs
|
|
47
60
|
|
|
48
61
|
```tsx
|
|
49
62
|
const [active, setActive] = useState(1);
|
|
50
63
|
|
|
51
|
-
<Tabs activeIndex={active} onTabChange={setActive}
|
|
64
|
+
<Tabs activeIndex={active} onTabChange={setActive} sx={{ width: 500 }}>
|
|
52
65
|
<TabList>
|
|
53
66
|
<Tab>Overview</Tab>
|
|
54
67
|
<Tab>Details</Tab>
|
|
@@ -62,15 +75,23 @@ const [active, setActive] = useState(1);
|
|
|
62
75
|
</Tabs>
|
|
63
76
|
```
|
|
64
77
|
|
|
65
|
-
### Custom
|
|
78
|
+
### Custom styling qua TabList
|
|
66
79
|
|
|
67
80
|
```tsx
|
|
68
|
-
<Tabs
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
81
|
+
<Tabs defaultActiveIndex={0} sx={{ width: 500 }}>
|
|
82
|
+
<TabList
|
|
83
|
+
align="center"
|
|
84
|
+
tabConfig={{
|
|
85
|
+
sx: {
|
|
86
|
+
color: getColorVar('neutral.500'),
|
|
87
|
+
sm: { height: 48 },
|
|
88
|
+
},
|
|
89
|
+
states: {
|
|
90
|
+
active: { sx: { color: getColorVar('green.600') } },
|
|
91
|
+
},
|
|
92
|
+
}}
|
|
93
|
+
indicator={{ size: 3, sx: { backgroundColor: getColorVar('green.600') } }}
|
|
94
|
+
>
|
|
74
95
|
<Tab>Home</Tab>
|
|
75
96
|
<Tab>Profile</Tab>
|
|
76
97
|
<Tab>Settings</Tab>
|
|
@@ -83,17 +104,63 @@ const [active, setActive] = useState(1);
|
|
|
83
104
|
</Tabs>
|
|
84
105
|
```
|
|
85
106
|
|
|
107
|
+
### Tab wrap thay vì scroll ngang
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
<Tabs sx={{ width: 300 }}>
|
|
111
|
+
<TabList overflowBehavior="wrap">
|
|
112
|
+
<Tab>Tab 1</Tab>
|
|
113
|
+
<Tab>Tab 2</Tab>
|
|
114
|
+
<Tab>Tab 3</Tab>
|
|
115
|
+
<Tab>Tab 4</Tab>
|
|
116
|
+
<Tab>Tab 5</Tab>
|
|
117
|
+
</TabList>
|
|
118
|
+
<TabContent>{/* … */}</TabContent>
|
|
119
|
+
</Tabs>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Tab với icon
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
import HomeIcon from '@/assets/svg/home.svg?raw';
|
|
126
|
+
|
|
127
|
+
<Tabs defaultActiveIndex={0}>
|
|
128
|
+
<TabList>
|
|
129
|
+
<Tab startIcon={{ source: HomeIcon, size: 20 }}>Home</Tab>
|
|
130
|
+
<Tab endIcon={{ source: HomeIcon, size: 20 }}>Settings</Tab>
|
|
131
|
+
</TabList>
|
|
132
|
+
<TabContent>{/* … */}</TabContent>
|
|
133
|
+
</Tabs>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Ẩn indicator
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
<Tabs defaultActiveIndex={0}>
|
|
140
|
+
<TabList indicator={false}>
|
|
141
|
+
<Tab>Tab 1</Tab>
|
|
142
|
+
<Tab>Tab 2</Tab>
|
|
143
|
+
</TabList>
|
|
144
|
+
<TabContent>{/* … */}</TabContent>
|
|
145
|
+
</Tabs>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Sub-components
|
|
149
|
+
|
|
150
|
+
- [TabList](./tab-list/README.md)
|
|
151
|
+
- [Tab](./tab/README.md)
|
|
152
|
+
- [TabContent](./tab-content/README.md)
|
|
153
|
+
- [TabPanel](./tab-panel/README.md)
|
|
154
|
+
- [TabIndicator](./tab-indicator/README.md)
|
|
155
|
+
|
|
86
156
|
## Related Components
|
|
87
157
|
|
|
88
|
-
- [
|
|
89
|
-
- [
|
|
90
|
-
- [TabContent](../tabcontent/README.md)
|
|
91
|
-
- [TabPanel](../tabpanel/README.md)
|
|
92
|
-
- [TabIndicator](../tabindicator/README.md)
|
|
93
|
-
- [Button](../button/README.md)
|
|
158
|
+
- [Icon](../icon/README.md)
|
|
159
|
+
- [Primitive](../primitive/README.md)
|
|
94
160
|
|
|
95
161
|
## Dependencies
|
|
96
162
|
|
|
163
|
+
- motion/react
|
|
97
164
|
- @emotion/react
|
|
98
165
|
|
|
99
166
|
## See Also
|