@janbox/storefront-ui 2.0.29 → 2.0.31
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 +692 -0
- package/dist/lib/accordion/README.md +81 -0
- package/dist/lib/avatar/README.md +74 -0
- package/dist/lib/badge/README.md +58 -0
- package/dist/lib/box/README.md +69 -0
- package/dist/lib/breadcrumbs/README.md +70 -0
- package/dist/lib/button/README.md +115 -0
- package/dist/lib/cascader/README.md +128 -0
- package/dist/lib/checkbox/README.md +74 -0
- package/dist/lib/checkbox/checkbox.js +107 -12
- package/dist/lib/checkbox/types.d.ts +2 -2
- package/dist/lib/chip/README.md +72 -0
- package/dist/lib/collapse/README.md +78 -0
- package/dist/lib/container/README.md +59 -0
- package/dist/lib/count-up/README.md +52 -0
- package/dist/lib/countdown-timer/README.md +77 -0
- package/dist/lib/date-picker/README.md +94 -0
- package/dist/lib/dialog/README.md +109 -0
- package/dist/lib/drawer/README.md +97 -0
- package/dist/lib/filter-panel/README.md +146 -0
- package/dist/lib/flag/README.md +58 -0
- package/dist/lib/flexbox/README.md +59 -0
- package/dist/lib/floating/README.md +109 -0
- package/dist/lib/form-helper-text/README.md +54 -0
- package/dist/lib/form-label/README.md +50 -0
- package/dist/lib/grid/README.md +72 -0
- package/dist/lib/highlight-words/README.md +64 -0
- package/dist/lib/highlight-words/highlight-words.js +1 -2
- package/dist/lib/icon/README.md +69 -0
- package/dist/lib/icon-button/README.md +92 -0
- package/dist/lib/image/README.md +80 -0
- package/dist/lib/input/README.md +118 -0
- package/dist/lib/input-mask/README.md +88 -0
- package/dist/lib/input-number/README.md +92 -0
- package/dist/lib/input-range/README.md +85 -0
- package/dist/lib/lightbox/README.md +107 -0
- package/dist/lib/linear-progress/README.md +54 -0
- package/dist/lib/link/README.md +67 -0
- package/dist/lib/loading/README.md +65 -0
- package/dist/lib/marquee/README.md +83 -0
- package/dist/lib/marquee/marquee/marquee.js +1 -1
- package/dist/lib/menu/README.md +92 -0
- package/dist/lib/multiple-select/README.md +108 -0
- package/dist/lib/nav-link/README.md +61 -0
- package/dist/lib/notifications/README.md +103 -0
- package/dist/lib/otp-input/README.md +71 -0
- package/dist/lib/pagination/README.md +84 -0
- package/dist/lib/phone-input/README.md +80 -0
- package/dist/lib/popover/README.md +93 -0
- package/dist/lib/price-label/README.md +78 -0
- package/dist/lib/primitive/README.md +80 -0
- package/dist/lib/progress/README.md +50 -0
- package/dist/lib/radio-button/README.md +89 -0
- package/dist/lib/radio-button/radio-button.js +98 -7
- package/dist/lib/ripple-effect/README.md +66 -0
- package/dist/lib/select/README.md +124 -0
- package/dist/lib/star-rating/README.md +67 -0
- package/dist/lib/stepper/README.md +99 -0
- package/dist/lib/suspense-query/README.md +78 -0
- package/dist/lib/swiper/README.md +99 -0
- package/dist/lib/switch/README.md +73 -0
- package/dist/lib/switch/switch.d.ts +1 -1
- package/dist/lib/switch/switch.js +110 -11
- package/dist/lib/table/README.md +115 -0
- package/dist/lib/tabs/README.md +103 -0
- package/dist/lib/text/README.md +59 -0
- package/dist/lib/textarea/README.md +76 -0
- package/dist/lib/time-picker/README.md +100 -0
- package/dist/lib/tooltip/README.md +106 -0
- package/dist/lib/unordered-list/README.md +85 -0
- package/dist/lib/video/README.md +88 -0
- package/dist/style.css +1 -244
- package/package.json +5 -5
- package/dist/lib/checkbox/checkbox.module.scss.js +0 -23
- package/dist/lib/radio-button/radio-button.module.scss.js +0 -17
- package/dist/lib/switch/switch.module.scss.js +0 -14
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# MultipleSelect
|
|
2
|
+
|
|
3
|
+
A generic multi-select dropdown component that renders selected values as tags inside an input trigger. It supports search filtering, virtualized option lists, controlled/uncontrolled state, and responsive sizing.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { MultipleSelect } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `options*` | `O[]` | - | Array of option objects to display in the dropdown list. |
|
|
16
|
+
| `value` | `Array<Partial<O> \| MultipleSelectOptionValue>` | - | Controlled selected values. Can be full option objects or primitive values (string \| number). |
|
|
17
|
+
| `defaultValue` | `Array<Partial<O> \| MultipleSelectOptionValue>` | - | Initial selected values for uncontrolled usage. |
|
|
18
|
+
| `onChange` | `(value: O[]) => void` | - | Callback fired when the selection changes, receiving the full array of selected option objects. |
|
|
19
|
+
| `optionValue` | `keyof O \| ((option: O) => MultipleSelectOptionValue)` | `'value'` | Key or function to derive the unique value from an option object. |
|
|
20
|
+
| `optionLabel` | `keyof O \| ((option: O) => React.ReactNode)` | `'label'` | Key or function to derive the display label from an option object. |
|
|
21
|
+
| `tagLabel` | `keyof O \| ((option: O) => React.ReactNode)` | - | Key or function to derive the label shown inside the selected tag chip. Falls back to `optionLabel` if not set. |
|
|
22
|
+
| `optionSearchLabel` | `keyof O \| Array<keyof O> \| ((option: O) => string \| string[])` | - | Field(s) or function used when filtering options by the search input. Defaults to `optionLabel`. |
|
|
23
|
+
| `searchable` | `boolean` | `true` | Whether to show a search input inside the dropdown for filtering options. |
|
|
24
|
+
| `displayCount` | `number` | `1` | Maximum number of tag chips shown in the trigger before collapsing into a `+N` badge. Use `Infinity` to show all. |
|
|
25
|
+
| `placeholder` | `string` | - | Placeholder text shown in the trigger when no values are selected. |
|
|
26
|
+
| `open` | `boolean` | - | Controlled open state of the dropdown. |
|
|
27
|
+
| `onOpenChange` | `UseFloatingOptions['onOpenChange']` | - | Callback fired when the open state changes. |
|
|
28
|
+
| `placement` | `Placement` | `'bottom-start'` | Floating UI placement for the dropdown panel. |
|
|
29
|
+
| `error` | `boolean` | - | When true, renders the trigger in an error/invalid visual state. |
|
|
30
|
+
| `helperText` | `string` | - | Helper or validation message rendered below the trigger via `FormHelperText`. |
|
|
31
|
+
| `containerProps` | `PrimitiveProps<JSX.IntrinsicElements['div']>` | - | Props forwarded to the outer container `Primitive` wrapper. |
|
|
32
|
+
| `inputProps` | `InputProps` | - | Props forwarded to the search `Input` rendered inside the dropdown panel. |
|
|
33
|
+
| `listProps` | `PropsWithoutRef<HTMLProps<HTMLDivElement>>` | - | Props forwarded to the `VirtualizedList` container element. |
|
|
34
|
+
| `size` | `'xs' \| 'sm' \| 'md' \| 'lg'` | `'md'` | Size variant controlling height, padding, and font size of the trigger and option rows. |
|
|
35
|
+
|
|
36
|
+
*Required props
|
|
37
|
+
|
|
38
|
+
## Examples
|
|
39
|
+
|
|
40
|
+
### Basic usage
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
type Option = { label: string; value: string };
|
|
44
|
+
|
|
45
|
+
const fruits: Option[] = [
|
|
46
|
+
{ label: 'Apple', value: 'apple' },
|
|
47
|
+
{ label: 'Banana', value: 'banana' },
|
|
48
|
+
{ label: 'Cherry', value: 'cherry' },
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
<MultipleSelect<Option>
|
|
52
|
+
options={fruits}
|
|
53
|
+
placeholder="Select fruits..."
|
|
54
|
+
onChange={(selected) => console.log(selected)}
|
|
55
|
+
/>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Controlled with error state
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
const [selected, setSelected] = useState<string[]>([]);
|
|
62
|
+
|
|
63
|
+
<MultipleSelect
|
|
64
|
+
options={fruits}
|
|
65
|
+
value={selected}
|
|
66
|
+
onChange={(opts) => setSelected(opts.map((o) => o.value))}
|
|
67
|
+
error={selected.length === 0}
|
|
68
|
+
helperText={selected.length === 0 ? 'Please select at least one option' : undefined}
|
|
69
|
+
placeholder="Select fruits..."
|
|
70
|
+
/>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Display multiple tags with overflow badge
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
// Shows up to 2 tag chips, remaining selections collapse into '+N' badge
|
|
77
|
+
<MultipleSelect<Option>
|
|
78
|
+
options={fruits}
|
|
79
|
+
value={['apple', 'banana', 'cherry']}
|
|
80
|
+
displayCount={2}
|
|
81
|
+
placeholder="Select fruits..."
|
|
82
|
+
onChange={handleChange}
|
|
83
|
+
/>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Related Components
|
|
87
|
+
|
|
88
|
+
- [Input](../input/README.md)
|
|
89
|
+
- [InputMask](../inputmask/README.md)
|
|
90
|
+
- [Checkbox](../checkbox/README.md)
|
|
91
|
+
- [Floating](../floating/README.md)
|
|
92
|
+
- [FloatingTrigger](../floatingtrigger/README.md)
|
|
93
|
+
- [FloatingContent](../floatingcontent/README.md)
|
|
94
|
+
- [FormHelperText](../formhelpertext/README.md)
|
|
95
|
+
- [VirtualizedList](../virtualizedlist/README.md)
|
|
96
|
+
- [Primitive](../primitive/README.md)
|
|
97
|
+
|
|
98
|
+
## Dependencies
|
|
99
|
+
|
|
100
|
+
- @floating-ui/react
|
|
101
|
+
- @tanstack/react-virtual
|
|
102
|
+
- lodash-es
|
|
103
|
+
|
|
104
|
+
## See Also
|
|
105
|
+
|
|
106
|
+
- [Component Source](./index.ts)
|
|
107
|
+
- [Storybook Stories](./multipleselect.stories.tsx)
|
|
108
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# NavLink
|
|
2
|
+
|
|
3
|
+
A wrapper around React Router's NavLink component that adds safe handling for undefined `to` prop. When `to` is nil, the link prevents navigation and treats itself as inactive, making it safe to render navigation items that may not yet have a destination.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { NavLink } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `to` | `ReactRouterNavLinkProps['to'] \| undefined` | - | Đường dẫn hoặc location object. Khi `undefined` hoặc `null`, link sẽ ngăn navigation và được coi là inactive (`isActive = false`). |
|
|
16
|
+
| `children` | `React.ReactNode \| ((props: NavLinkRenderProps) => React.ReactNode)` | - | Nội dung bên trong link. Có thể là render function nhận NavLink render props gồm `isActive`, `isPending`, `isTransitioning`. Khi `to` là nil, `isActive` luôn là `false`. |
|
|
17
|
+
| `className` | `string \| ((props: NavLinkRenderProps) => string \| undefined)` | - | Class name hoặc function nhận render props để tính class động. `isActive` trong render props tuân theo nil-to override. |
|
|
18
|
+
| `style` | `React.CSSProperties \| ((props: NavLinkRenderProps) => React.CSSProperties \| undefined)` | - | Inline styles hoặc function nhận render props để tính styles động. `isActive` trong render props tuân theo nil-to override. |
|
|
19
|
+
| `end` | `boolean` | - | Khi `true`, active class/style chỉ được áp dụng khi URL hiện tại khớp chính xác với `to` (không partial matching). |
|
|
20
|
+
| `ref` | `Ref<HTMLAnchorElement>` | - | Forwarded ref đến anchor element bên dưới. |
|
|
21
|
+
| `onClick` | `(event: React.MouseEvent<HTMLAnchorElement>) => void` | - | Click handler. Navigation tự động bị ngăn khi `to` là nil hoặc khi `aria-disabled` là `true`. |
|
|
22
|
+
|
|
23
|
+
## Examples
|
|
24
|
+
|
|
25
|
+
### Basic navigation link
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
<NavLink to="/home">Home</NavLink>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Active state with exact match and dynamic class
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<NavLink
|
|
35
|
+
to="/dashboard"
|
|
36
|
+
end
|
|
37
|
+
className={({ isActive }) => isActive ? 'nav-item nav-item--active' : 'nav-item'}
|
|
38
|
+
>
|
|
39
|
+
Dashboard
|
|
40
|
+
</NavLink>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Placeholder link with no destination (disabled navigation)
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
<NavLink to={undefined} aria-disabled="true">
|
|
47
|
+
{({ isActive }) => (
|
|
48
|
+
<span style={{ opacity: isActive ? 1 : 0.5 }}>Coming Soon</span>
|
|
49
|
+
)}
|
|
50
|
+
</NavLink>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Dependencies
|
|
54
|
+
|
|
55
|
+
- react-router
|
|
56
|
+
|
|
57
|
+
## See Also
|
|
58
|
+
|
|
59
|
+
- [Component Source](./index.ts)
|
|
60
|
+
- [Storybook Stories](./navlink.stories.tsx)
|
|
61
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Notifications
|
|
2
|
+
|
|
3
|
+
A toast notification system that renders dismissible notification cards in a fixed portal overlay at the top-right of the screen. It uses an external store (`notificationStore`) and the `useNotifications` hook to push notifications imperatively from anywhere in the app.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Notifications } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
|
|
16
|
+
## Examples
|
|
17
|
+
|
|
18
|
+
### Basic usage — mount Notifications once and push via hook
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { Notifications, useNotifications } from '@janbox/storefront-ui';
|
|
22
|
+
|
|
23
|
+
const App = () => (
|
|
24
|
+
<>
|
|
25
|
+
{/* Mount once at the root level */}
|
|
26
|
+
<Notifications />
|
|
27
|
+
<MyPage />
|
|
28
|
+
</>
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const MyPage = () => {
|
|
32
|
+
const { pushNotifications } = useNotifications();
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<button
|
|
36
|
+
onClick={() =>
|
|
37
|
+
pushNotifications({
|
|
38
|
+
title: 'Success',
|
|
39
|
+
message: 'Your changes have been saved.',
|
|
40
|
+
color: 'green',
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
>
|
|
44
|
+
Save
|
|
45
|
+
</button>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Push multiple notifications with custom duration
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
const { pushNotifications } = useNotifications();
|
|
54
|
+
|
|
55
|
+
pushNotifications([
|
|
56
|
+
{
|
|
57
|
+
title: 'Item added',
|
|
58
|
+
message: 'Product has been added to your cart.',
|
|
59
|
+
color: 'primary',
|
|
60
|
+
duration: 4000,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
title: 'Stock low',
|
|
64
|
+
message: 'Only 2 items left in stock.',
|
|
65
|
+
color: 'orange',
|
|
66
|
+
duration: 6000,
|
|
67
|
+
},
|
|
68
|
+
]);
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Error notification on API failure
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
const { pushNotifications } = useNotifications();
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
await submitOrder();
|
|
78
|
+
} catch (err) {
|
|
79
|
+
pushNotifications({
|
|
80
|
+
title: 'Order failed',
|
|
81
|
+
message: 'Something went wrong. Please try again.',
|
|
82
|
+
color: 'red',
|
|
83
|
+
duration: 5000,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Related Components
|
|
89
|
+
|
|
90
|
+
- [IconButton](../icon-button/README.md)
|
|
91
|
+
- [Primitive](../primitive/README.md)
|
|
92
|
+
|
|
93
|
+
## Dependencies
|
|
94
|
+
|
|
95
|
+
- @floating-ui/react
|
|
96
|
+
- lodash-es
|
|
97
|
+
- motion/react
|
|
98
|
+
|
|
99
|
+
## See Also
|
|
100
|
+
|
|
101
|
+
- [Component Source](./index.ts)
|
|
102
|
+
- [Storybook Stories](./notifications.stories.tsx)
|
|
103
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# OtpInput
|
|
2
|
+
|
|
3
|
+
A one-time password input component that renders multiple individual input fields for entering verification codes. Supports auto-focus, paste handling, keyboard navigation, and automatic progression between fields.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { OtpInput } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `length` | `number` | 6 | Number of OTP input fields to render |
|
|
16
|
+
| `onChange` | `(otp: string) => void` | - | Callback fired when any digit changes, receives the complete OTP string |
|
|
17
|
+
| `onFullfilled` | `(otp: string) => void` | - | Callback fired when all digits are filled, receives the complete OTP string |
|
|
18
|
+
| `disabled` | `boolean` | - | Disables all input fields |
|
|
19
|
+
| `autoFocus` | `boolean` | - | Auto-focuses the first input field on mount |
|
|
20
|
+
| `isLoading` | `boolean` | - | Makes all input fields read-only during loading state |
|
|
21
|
+
| `defaultValue` | `string` | - | Default OTP value (uncontrolled) |
|
|
22
|
+
| `value` | `string` | - | Controlled OTP value |
|
|
23
|
+
| `error` | `boolean` | - | Shows error state styling on all input fields |
|
|
24
|
+
| `size` | `InputSizeVariant` | - | Size variant for all input fields |
|
|
25
|
+
| `sm` | `InputResponsiveProps` | - | Responsive props for small breakpoint (768px+) |
|
|
26
|
+
| `md` | `InputResponsiveProps` | - | Responsive props for medium breakpoint (1280px+) |
|
|
27
|
+
| `lg` | `InputResponsiveProps` | - | Responsive props for large breakpoint (1680px+) |
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
30
|
+
|
|
31
|
+
### Basic 6-digit OTP
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<OtpInput length={6} onChange={(otp) => console.log(otp)} />
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 4-digit PIN with auto-submit
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
<OtpInput
|
|
41
|
+
length={4}
|
|
42
|
+
autoFocus
|
|
43
|
+
onFullfilled={(otp) => handleVerify(otp)}
|
|
44
|
+
/>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Controlled with error state
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<OtpInput
|
|
51
|
+
length={6}
|
|
52
|
+
value={otpValue}
|
|
53
|
+
onChange={setOtpValue}
|
|
54
|
+
error={hasError}
|
|
55
|
+
disabled={isSubmitting}
|
|
56
|
+
/>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Related Components
|
|
60
|
+
|
|
61
|
+
- [Input](../input/README.md)
|
|
62
|
+
|
|
63
|
+
## Dependencies
|
|
64
|
+
|
|
65
|
+
- lodash-es
|
|
66
|
+
|
|
67
|
+
## See Also
|
|
68
|
+
|
|
69
|
+
- [Component Source](./index.ts)
|
|
70
|
+
- [Storybook Stories](./otpinput.stories.tsx)
|
|
71
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Pagination
|
|
2
|
+
|
|
3
|
+
A pagination component for navigating through multiple pages of content. Displays page numbers with ellipsis for large page counts, supports customizable navigation buttons, and provides responsive sizing.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Pagination } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `page` | `number` | 1 | Current active page number |
|
|
16
|
+
| `totalPages` | `number` | 1 | Total number of pages available |
|
|
17
|
+
| `onChange` | `(page: number) => void` | - | Callback function triggered when page changes |
|
|
18
|
+
| `disabled` | `boolean` | - | Disables all pagination interactions |
|
|
19
|
+
| `size` | `'xs' \| 'sm' \| 'md' \| 'lg'` | `sm` | Size variant for pagination buttons and text |
|
|
20
|
+
| `showPrevPageButton` | `boolean` | `true` | Show/hide the previous page navigation button |
|
|
21
|
+
| `showNextPageButton` | `boolean` | `true` | Show/hide the next page navigation button |
|
|
22
|
+
| `showFirstPageButton` | `boolean` | `false` | Show/hide the first page navigation button |
|
|
23
|
+
| `showLastPageButton` | `boolean` | `false` | Show/hide the last page navigation button |
|
|
24
|
+
| `siblingCount` | `number` | `2` | Number of pages to show on each side of the current page |
|
|
25
|
+
| `states` | `Partial<Record<'normal' \| 'active', { color?: IconButtonProps['color']; variant?: IconButtonProps['variant']; }>>` | `{ normal: { color: 'neutral', variant: 'outlined' }, active: { color: 'primary', variant: 'outlined' } }` | Customize color and variant for normal and active pagination button states |
|
|
26
|
+
| `sm` | `{ size?: SizeVariant }` | - | Responsive props for small breakpoint (768px) |
|
|
27
|
+
| `md` | `{ size?: SizeVariant }` | - | Responsive props for medium breakpoint (1280px) |
|
|
28
|
+
| `lg` | `{ size?: SizeVariant }` | - | Responsive props for large breakpoint (1680px) |
|
|
29
|
+
|
|
30
|
+
## Examples
|
|
31
|
+
|
|
32
|
+
### Basic pagination with 10 pages
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
<Pagination
|
|
36
|
+
page={5}
|
|
37
|
+
totalPages={10}
|
|
38
|
+
onChange={(page) => console.log('Navigate to page:', page)}
|
|
39
|
+
/>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Pagination with first/last buttons and custom sibling count
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
<Pagination
|
|
46
|
+
page={7}
|
|
47
|
+
totalPages={50}
|
|
48
|
+
siblingCount={2}
|
|
49
|
+
showFirstPageButton
|
|
50
|
+
showLastPageButton
|
|
51
|
+
onChange={(page) => setCurrentPage(page)}
|
|
52
|
+
/>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Disabled pagination with custom button states
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
<Pagination
|
|
59
|
+
page={3}
|
|
60
|
+
totalPages={10}
|
|
61
|
+
disabled
|
|
62
|
+
states={{
|
|
63
|
+
normal: { color: 'neutral', variant: 'outlined' },
|
|
64
|
+
active: { color: 'blue', variant: 'contained' }
|
|
65
|
+
}}
|
|
66
|
+
onChange={(page) => handlePageChange(page)}
|
|
67
|
+
/>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Related Components
|
|
71
|
+
|
|
72
|
+
- [IconButton](../iconbutton/README.md)
|
|
73
|
+
- [Icon](../icon/README.md)
|
|
74
|
+
- [Text](../text/README.md)
|
|
75
|
+
|
|
76
|
+
## Dependencies
|
|
77
|
+
|
|
78
|
+
- @emotion/react
|
|
79
|
+
|
|
80
|
+
## See Also
|
|
81
|
+
|
|
82
|
+
- [Component Source](./index.ts)
|
|
83
|
+
- [Storybook Stories](./pagination.stories.tsx)
|
|
84
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# PhoneInput
|
|
2
|
+
|
|
3
|
+
A phone number input component that combines a country dial code selector with a national number text field. It supports controlled and uncontrolled usage, auto-parses country codes from dial codes, and displays formatted phone numbers when not focused.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { PhoneInput } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `value` | `PhoneInputValue` | - | Controlled value object containing countryCode, dialCode, and nationalNumber. |
|
|
16
|
+
| `defaultValue` | `PhoneInputValue` | - | Uncontrolled default value. Defaults to the first country in the countries list if not provided. |
|
|
17
|
+
| `onChange` | `(value: PhoneInputValue) => void` | - | Callback fired when either the country dial code or the national number changes. Receives a PhoneInputValue object. |
|
|
18
|
+
| `error` | `boolean` | `false` | Puts the input into an error state, rendering the border in red. |
|
|
19
|
+
| `helperText` | `string` | - | Helper or error message displayed below the input via FormHelperText. |
|
|
20
|
+
| `disabled` | `boolean` | `false` | Disables both the country select and the number input, applying a disabled surface color. |
|
|
21
|
+
| `containerProps` | `PrimitiveProps<JSX.IntrinsicElements['div']>` | - | Props forwarded to the outer container Primitive div, useful for layout overrides via sx. |
|
|
22
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size variant for the input. xs is excluded. Supports responsive values via sm/md/lg breakpoint keys. |
|
|
23
|
+
| `css` | `Interpolation` | - | Emotion CSS interpolation applied directly to the InputMask wrapper element. |
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### Default (uncontrolled)
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
<div style={{ width: 300 }}>
|
|
31
|
+
<PhoneInput onChange={(value) => console.log(value)} />
|
|
32
|
+
</div>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Controlled with initial value
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
const [phone, setPhone] = useState<PhoneInputValue>({
|
|
39
|
+
countryCode: 'JP',
|
|
40
|
+
dialCode: '+81',
|
|
41
|
+
nationalNumber: '9012345678',
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
<PhoneInput
|
|
45
|
+
value={phone}
|
|
46
|
+
onChange={setPhone}
|
|
47
|
+
/>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Error state with helper text
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<PhoneInput
|
|
54
|
+
error
|
|
55
|
+
helperText="Please enter a valid phone number."
|
|
56
|
+
defaultValue={{ countryCode: 'VN' }}
|
|
57
|
+
onChange={(value) => console.log(value)}
|
|
58
|
+
/>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Related Components
|
|
62
|
+
|
|
63
|
+
- [Input](../input/README.md)
|
|
64
|
+
- [InputMask](../inputmask/README.md)
|
|
65
|
+
- [Select](../select/README.md)
|
|
66
|
+
- [Flag](../flag/README.md)
|
|
67
|
+
- [FormHelperText](../formhelpertext/README.md)
|
|
68
|
+
- [Primitive](../primitive/README.md)
|
|
69
|
+
|
|
70
|
+
## Dependencies
|
|
71
|
+
|
|
72
|
+
- phone
|
|
73
|
+
- @floating-ui/react
|
|
74
|
+
- lodash-es
|
|
75
|
+
|
|
76
|
+
## See Also
|
|
77
|
+
|
|
78
|
+
- [Component Source](./index.ts)
|
|
79
|
+
- [Storybook Stories](./phoneinput.stories.tsx)
|
|
80
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Popover
|
|
2
|
+
|
|
3
|
+
A floating overlay component for displaying contextual content anchored to a trigger element. Built on top of @floating-ui/react, it supports click-to-open, dismiss-on-outside-click, and controlled/uncontrolled open state — composed via Popover, PopoverTrigger, PopoverContent, and PopoverClose sub-components.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Popover } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `open` | `boolean` | - | Controlled open state of the popover. |
|
|
16
|
+
| `onOpenChange` | `UseFloatingOptions['onOpenChange']` | - | Callback fired when the open state changes. Receives (open: boolean, event: Event | undefined, reason: OpenChangeReason | undefined). |
|
|
17
|
+
| `placement` | `Placement` | `bottom` | Preferred placement of the floating content relative to the trigger. Accepts all @floating-ui/react Placement values (e.g. `'top'`, `'bottom'`, `'left'`, `'right'` and their `'-start'`/`'-end'` variants). |
|
|
18
|
+
| `clickProps` | `UseClickProps` | `{ enabled: true }` | Options forwarded to @floating-ui/react useClick interaction hook. Enabled by default in Popover. |
|
|
19
|
+
| `dismissProps` | `UseDismissProps` | `{ enabled: true }` | Options forwarded to @floating-ui/react useDismiss interaction hook (close on outside click / Escape key). Enabled by default in Popover. |
|
|
20
|
+
| `hoverProps` | `UseHoverProps` | - | Options forwarded to @floating-ui/react useHover interaction hook. |
|
|
21
|
+
| `focusProps` | `UseFocusProps` | - | Options forwarded to @floating-ui/react useFocus interaction hook. |
|
|
22
|
+
| `offsetOptions` | `OffsetOptions` | - | Distance (in px) between the trigger and the floating content. |
|
|
23
|
+
| `sizeOptions` | `SizeOptions` | - | Options for the @floating-ui/react size middleware — constrain the floating element dimensions. |
|
|
24
|
+
| `autoUpdateOptions` | `AutoUpdateOptions` | - | Options passed to @floating-ui/react autoUpdate to control when the position recalculates. |
|
|
25
|
+
| `elements` | `UseFloatingOptions['elements']` | - | Override the reference or floating elements used by floating-ui. |
|
|
26
|
+
| `ref` | `React.Ref<FloatingRef>` | - | Ref forwarded to the underlying UseFloatingReturn object, exposing the full floating-ui context. |
|
|
27
|
+
| `children` | `React.ReactNode` | - | Should contain PopoverTrigger and PopoverContent (and optionally PopoverClose inside content). |
|
|
28
|
+
|
|
29
|
+
## Examples
|
|
30
|
+
|
|
31
|
+
### Default (click to open, dismiss on outside click)
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<Popover>
|
|
35
|
+
<PopoverTrigger>
|
|
36
|
+
<button>Open Popover</button>
|
|
37
|
+
</PopoverTrigger>
|
|
38
|
+
<PopoverContent>
|
|
39
|
+
<p>Popover content here</p>
|
|
40
|
+
<PopoverClose>
|
|
41
|
+
<button>Close</button>
|
|
42
|
+
</PopoverClose>
|
|
43
|
+
</PopoverContent>
|
|
44
|
+
</Popover>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Top placement
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
<Popover placement="top">
|
|
51
|
+
<PopoverTrigger>
|
|
52
|
+
<button>Open Top</button>
|
|
53
|
+
</PopoverTrigger>
|
|
54
|
+
<PopoverContent>
|
|
55
|
+
<p>Popover anchored above the trigger</p>
|
|
56
|
+
</PopoverContent>
|
|
57
|
+
</Popover>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Controlled open state
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
const [open, setOpen] = useState(false);
|
|
64
|
+
|
|
65
|
+
<Popover open={open} onOpenChange={(next) => setOpen(next)}>
|
|
66
|
+
<PopoverTrigger>
|
|
67
|
+
<button>Toggle</button>
|
|
68
|
+
</PopoverTrigger>
|
|
69
|
+
<PopoverContent>
|
|
70
|
+
<p>Controlled popover</p>
|
|
71
|
+
<PopoverClose>
|
|
72
|
+
<button onClick={() => setOpen(false)}>Close</button>
|
|
73
|
+
</PopoverClose>
|
|
74
|
+
</PopoverContent>
|
|
75
|
+
</Popover>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Related Components
|
|
79
|
+
|
|
80
|
+
- [Floating](../floating/README.md)
|
|
81
|
+
- [FloatingTrigger](../floating-trigger/README.md)
|
|
82
|
+
- [FloatingContent](../floating-content/README.md)
|
|
83
|
+
- [FloatingClose](../floating-close/README.md)
|
|
84
|
+
|
|
85
|
+
## Dependencies
|
|
86
|
+
|
|
87
|
+
- @floating-ui/react
|
|
88
|
+
|
|
89
|
+
## See Also
|
|
90
|
+
|
|
91
|
+
- [Component Source](./index.ts)
|
|
92
|
+
- [Storybook Stories](./popover.stories.tsx)
|
|
93
|
+
- [Main README](../../README.md)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# PriceLabel
|
|
2
|
+
|
|
3
|
+
A component for displaying a primary price alongside an optional exchange/secondary price. Supports currency formatting, pending states, skeleton placeholders, responsive typography sizing, and both vertical and horizontal layout orientations.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { PriceLabel } from '@janbox/storefront-ui';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Props
|
|
12
|
+
|
|
13
|
+
| Prop | Type | Default | Description |
|
|
14
|
+
|------|------|---------|-------------|
|
|
15
|
+
| `price*` | `PriceLabelEntry` | - | Primary price data. Contains currency, value, isPending, placeholder, prefix, and suffix fields. |
|
|
16
|
+
| `price.currency` | `string` | - | ISO currency code (e.g. 'USD', 'VND'). When combined with value, renders a formatted price string. |
|
|
17
|
+
| `price.value` | `number` | - | Numeric price value to format and display. |
|
|
18
|
+
| `price.isPending` | `boolean` | - | When true and no value is set, renders an 'updating' label. |
|
|
19
|
+
| `price.placeholder` | `boolean` | - | When true and no value or pending state, renders a skeleton placeholder. Defaults to true on the primary price. |
|
|
20
|
+
| `price.prefix` | `string` | - | String prepended to the formatted price. |
|
|
21
|
+
| `price.suffix` | `string` | - | String appended to the formatted price. |
|
|
22
|
+
| `exchangePrice` | `PriceLabelEntry` | - | Optional secondary/exchange price displayed below (vertical) or beside (horizontal) the primary price. |
|
|
23
|
+
| `priceProps` | `PrimitiveProps<JSX.IntrinsicElements['span']>` | - | Additional props forwarded to the primary price span element, including sx for style overrides. |
|
|
24
|
+
| `exchangePriceProps` | `PrimitiveProps<JSX.IntrinsicElements['span']>` | - | Additional props forwarded to the exchange price span element, including sx for style overrides. |
|
|
25
|
+
| `color` | `ColorVariant` | `neutral` | Color variant used for the price text. Primary price uses the 600 shade, exchange price uses the 500 shade. |
|
|
26
|
+
| `orientation` | `'horizontal' \| 'vertical'` | `vertical` | Layout direction of the primary and exchange prices. Vertical stacks them with a line break; horizontal places them side by side. |
|
|
27
|
+
| `showEqual` | `boolean` | `false` | When true, shows the exchange price even if it is equal to the primary price (same currency and value). |
|
|
28
|
+
| `size` | `TypographySizeVariant` | `sm` | Typography size for the primary price. Accepts responsive values via sm/md/lg breakpoint props. Exchange price automatically uses one size smaller. |
|
|
29
|
+
|
|
30
|
+
*Required props
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
### Basic price with exchange rate
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<PriceLabel
|
|
38
|
+
price={{ value: 100, currency: 'USD' }}
|
|
39
|
+
exchangePrice={{ value: 2000000, currency: 'VND' }}
|
|
40
|
+
/>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Horizontal layout with color variant and larger size
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
<PriceLabel
|
|
47
|
+
price={{ value: 49.99, currency: 'USD' }}
|
|
48
|
+
exchangePrice={{ value: 999000, currency: 'VND' }}
|
|
49
|
+
orientation="horizontal"
|
|
50
|
+
color="primary"
|
|
51
|
+
size="lg"
|
|
52
|
+
/>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Pending state while price is loading
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
<PriceLabel
|
|
59
|
+
price={{ isPending: true }}
|
|
60
|
+
exchangePrice={{ isPending: true }}
|
|
61
|
+
color="neutral"
|
|
62
|
+
/>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Related Components
|
|
66
|
+
|
|
67
|
+
- [TextSkeleton](../loading/README.md)
|
|
68
|
+
- [Primitive](../primitive/README.md)
|
|
69
|
+
|
|
70
|
+
## Dependencies
|
|
71
|
+
|
|
72
|
+
- lodash-es
|
|
73
|
+
|
|
74
|
+
## See Also
|
|
75
|
+
|
|
76
|
+
- [Component Source](./index.ts)
|
|
77
|
+
- [Storybook Stories](./pricelabel.stories.tsx)
|
|
78
|
+
- [Main README](../../README.md)
|