@janbox/storefront-ui 2.0.29 → 2.0.30

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 (76) hide show
  1. package/README.md +681 -0
  2. package/dist/lib/accordion/README.md +81 -0
  3. package/dist/lib/avatar/README.md +74 -0
  4. package/dist/lib/badge/README.md +58 -0
  5. package/dist/lib/box/README.md +69 -0
  6. package/dist/lib/breadcrumbs/README.md +70 -0
  7. package/dist/lib/button/README.md +115 -0
  8. package/dist/lib/cascader/README.md +128 -0
  9. package/dist/lib/checkbox/README.md +74 -0
  10. package/dist/lib/checkbox/checkbox.js +107 -12
  11. package/dist/lib/checkbox/types.d.ts +2 -2
  12. package/dist/lib/chip/README.md +72 -0
  13. package/dist/lib/collapse/README.md +78 -0
  14. package/dist/lib/container/README.md +59 -0
  15. package/dist/lib/count-up/README.md +52 -0
  16. package/dist/lib/countdown-timer/README.md +77 -0
  17. package/dist/lib/date-picker/README.md +94 -0
  18. package/dist/lib/date-picker/date-picker.js +2 -1
  19. package/dist/lib/dialog/README.md +109 -0
  20. package/dist/lib/drawer/README.md +97 -0
  21. package/dist/lib/filter-panel/README.md +146 -0
  22. package/dist/lib/flag/README.md +58 -0
  23. package/dist/lib/flexbox/README.md +59 -0
  24. package/dist/lib/floating/README.md +109 -0
  25. package/dist/lib/form-helper-text/README.md +54 -0
  26. package/dist/lib/form-label/README.md +50 -0
  27. package/dist/lib/grid/README.md +72 -0
  28. package/dist/lib/highlight-words/README.md +64 -0
  29. package/dist/lib/highlight-words/highlight-words.js +1 -2
  30. package/dist/lib/icon/README.md +69 -0
  31. package/dist/lib/icon-button/README.md +92 -0
  32. package/dist/lib/image/README.md +80 -0
  33. package/dist/lib/input/README.md +118 -0
  34. package/dist/lib/input-mask/README.md +88 -0
  35. package/dist/lib/input-number/README.md +92 -0
  36. package/dist/lib/input-range/README.md +85 -0
  37. package/dist/lib/lightbox/README.md +107 -0
  38. package/dist/lib/linear-progress/README.md +54 -0
  39. package/dist/lib/link/README.md +67 -0
  40. package/dist/lib/loading/README.md +65 -0
  41. package/dist/lib/marquee/README.md +83 -0
  42. package/dist/lib/menu/README.md +92 -0
  43. package/dist/lib/multiple-select/README.md +108 -0
  44. package/dist/lib/nav-link/README.md +61 -0
  45. package/dist/lib/notifications/README.md +103 -0
  46. package/dist/lib/otp-input/README.md +71 -0
  47. package/dist/lib/pagination/README.md +84 -0
  48. package/dist/lib/phone-input/README.md +80 -0
  49. package/dist/lib/popover/README.md +93 -0
  50. package/dist/lib/price-label/README.md +78 -0
  51. package/dist/lib/primitive/README.md +80 -0
  52. package/dist/lib/progress/README.md +50 -0
  53. package/dist/lib/radio-button/README.md +89 -0
  54. package/dist/lib/radio-button/radio-button.js +98 -7
  55. package/dist/lib/ripple-effect/README.md +66 -0
  56. package/dist/lib/select/README.md +124 -0
  57. package/dist/lib/star-rating/README.md +67 -0
  58. package/dist/lib/stepper/README.md +99 -0
  59. package/dist/lib/suspense-query/README.md +78 -0
  60. package/dist/lib/swiper/README.md +99 -0
  61. package/dist/lib/switch/README.md +73 -0
  62. package/dist/lib/switch/switch.d.ts +1 -1
  63. package/dist/lib/switch/switch.js +110 -11
  64. package/dist/lib/table/README.md +115 -0
  65. package/dist/lib/tabs/README.md +103 -0
  66. package/dist/lib/text/README.md +59 -0
  67. package/dist/lib/textarea/README.md +76 -0
  68. package/dist/lib/time-picker/README.md +100 -0
  69. package/dist/lib/tooltip/README.md +106 -0
  70. package/dist/lib/unordered-list/README.md +85 -0
  71. package/dist/lib/video/README.md +88 -0
  72. package/package.json +5 -5
  73. package/dist/lib/checkbox/checkbox.module.scss.js +0 -23
  74. package/dist/lib/radio-button/radio-button.module.scss.js +0 -17
  75. package/dist/lib/switch/switch.module.scss.js +0 -14
  76. package/dist/style.css +0 -823
@@ -0,0 +1,72 @@
1
+ # Grid
2
+
3
+ A CSS Grid layout component that renders a responsive grid container with configurable column counts. It works in tandem with the Cell component, which supports colSpan for spanning multiple columns.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Grid } from '@janbox/storefront-ui';
9
+ ```
10
+
11
+ ## Props
12
+
13
+ | Prop | Type | Default | Description |
14
+ |------|------|---------|-------------|
15
+ | `cols` | `number` | 1 | Number of equal-width columns in the grid. Generates `grid-template-columns: repeat(cols, minmax(0, 1fr))`. Supports responsive variants via sm/md/lg. |
16
+ | `sm` | `GridResponsiveProps` | - | Responsive overrides applied at the sm breakpoint (≥768px). Accepts `{ cols?: number }`. |
17
+ | `md` | `GridResponsiveProps` | - | Responsive overrides applied at the md breakpoint (≥1280px). Accepts `{ cols?: number }`. |
18
+ | `lg` | `GridResponsiveProps` | - | Responsive overrides applied at the lg breakpoint (≥1680px). Accepts `{ cols?: number }`. |
19
+ | `container` | `boolean` | false | When true, applies the shared responsive container styles (padding and max-width) from `containerStyle`. |
20
+ | `sx` | `ToResponsiveProps<StyledCSS>` | - | Escape-hatch for inline Emotion styles. Supports responsive keys (sm, md, lg) alongside base styles. |
21
+ | `children` | `React.ReactNode` | - | Grid children, typically Cell components. |
22
+ | `ref` | `React.Ref<HTMLDivElement>` | - | Forwarded ref to the underlying div element. |
23
+
24
+ ## Examples
25
+
26
+ ### Two-column grid
27
+
28
+ ```tsx
29
+ <Grid cols={2} style={{ width: 600 }}>
30
+ <Cell style={{ padding: 8, background: '#e0f0ff' }}>Cell 1</Cell>
31
+ <Cell style={{ padding: 8, background: '#f0ffe0' }}>Cell 2</Cell>
32
+ <Cell style={{ padding: 8, background: '#fff0e0' }}>Cell 3</Cell>
33
+ <Cell style={{ padding: 8, background: '#f0e0ff' }}>Cell 4</Cell>
34
+ </Grid>
35
+ ```
36
+
37
+ ### Three-column grid with colSpan
38
+
39
+ ```tsx
40
+ <Grid cols={3} style={{ width: 600 }}>
41
+ <Cell colSpan={2} style={{ padding: 8, background: '#e0f0ff' }}>Span 2 columns</Cell>
42
+ <Cell style={{ padding: 8, background: '#f0ffe0' }}>Cell 2</Cell>
43
+ <Cell style={{ padding: 8, background: '#fff0e0' }}>Cell 3</Cell>
44
+ <Cell style={{ padding: 8, background: '#f0e0ff' }}>Cell 4</Cell>
45
+ </Grid>
46
+ ```
47
+
48
+ ### Responsive columns (1 on mobile, 2 on tablet, 4 on desktop)
49
+
50
+ ```tsx
51
+ <Grid cols={1} sm={{ cols: 2 }} md={{ cols: 4 }} container>
52
+ <Cell>Item 1</Cell>
53
+ <Cell>Item 2</Cell>
54
+ <Cell>Item 3</Cell>
55
+ <Cell>Item 4</Cell>
56
+ </Grid>
57
+ ```
58
+
59
+ ## Related Components
60
+
61
+ - [Cell](./cell/README.md)
62
+ - [Primitive](../primitive/README.md)
63
+
64
+ ## Dependencies
65
+
66
+ - lodash-es
67
+
68
+ ## See Also
69
+
70
+ - [Component Source](./index.ts)
71
+ - [Storybook Stories](./grid.stories.tsx)
72
+ - [Main README](../../README.md)
@@ -0,0 +1,64 @@
1
+ # HighlightWords
2
+
3
+ Renders a text string with specified search words highlighted using bold font weight. Built on top of `highlight-words-core`, it is useful for search result UIs where matched terms need to be visually distinguished within a body of text.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { HighlightWords } from '@janbox/storefront-ui';
9
+ ```
10
+
11
+ ## Props
12
+
13
+ | Prop | Type | Default | Description |
14
+ |------|------|---------|-------------|
15
+ | `textToHighlight*` | `string` | - | The full text string to display and search within. |
16
+ | `searchWords*` | `string[]` | - | Array of words or phrases to highlight within the text. |
17
+ | `highlightClassName` | `string` | - | Optional CSS class name(s) applied to the highlighted `<span>` elements. Useful for custom highlight styling (e.g. background color). |
18
+ | `caseSensitive` | `boolean` | `false` | Whether the search matching should be case-sensitive. Defaults to false (case-insensitive). |
19
+ | `autoEscape` | `boolean` | `false` | Whether to escape special regex characters in the search words before matching. |
20
+ | `sanitize` | `(text: string) => string` | - | Optional function to sanitize/normalize text before matching (e.g. removing diacritics). |
21
+ | `findChunks` | `(args: FindChunksArgs) => Chunk[]` | - | Custom chunk-finding function to override the default highlight-words-core matching logic. |
22
+
23
+ *Required props
24
+
25
+ ## Examples
26
+
27
+ ### Basic usage
28
+
29
+ ```tsx
30
+ <HighlightWords
31
+ textToHighlight="The quick brown fox jumps over the lazy dog"
32
+ searchWords={["fox", "dog"]}
33
+ />
34
+ ```
35
+
36
+ ### Case-sensitive matching
37
+
38
+ ```tsx
39
+ <HighlightWords
40
+ textToHighlight="Hello World hello world"
41
+ searchWords={["Hello"]}
42
+ caseSensitive
43
+ />
44
+ ```
45
+
46
+ ### Custom highlight class
47
+
48
+ ```tsx
49
+ <HighlightWords
50
+ textToHighlight="React is a JavaScript library for building user interfaces"
51
+ searchWords={["React", "JavaScript"]}
52
+ highlightClassName="bg-yellow-200 font-bold"
53
+ />
54
+ ```
55
+
56
+ ## Dependencies
57
+
58
+ - highlight-words-core
59
+
60
+ ## See Also
61
+
62
+ - [Component Source](./index.ts)
63
+ - [Storybook Stories](./highlightwords.stories.tsx)
64
+ - [Main README](../../README.md)
@@ -1,13 +1,12 @@
1
1
  import { jsx } from "@emotion/react/jsx-runtime";
2
2
  import { Fragment } from "react";
3
3
  import { findAll } from "highlight-words-core";
4
- import { clsx } from "clsx";
5
4
  const HighlightWords = ({ highlightClassName, ...props }) => {
6
5
  const chunks = findAll(props);
7
6
  return /* @__PURE__ */ jsx(Fragment, { children: chunks.map((chunk, index) => {
8
7
  const { end, highlight, start } = chunk;
9
8
  const text = props.textToHighlight.substring(start, end);
10
- return /* @__PURE__ */ jsx(Fragment, { children: highlight ? /* @__PURE__ */ jsx("span", { css: { fontWeight: 500 }, className: clsx(highlightClassName), children: text }) : text }, index);
9
+ return /* @__PURE__ */ jsx(Fragment, { children: highlight ? /* @__PURE__ */ jsx("span", { css: { fontWeight: 500 }, className: highlightClassName, children: text }) : text }, index);
11
10
  }) });
12
11
  };
13
12
  export {
@@ -0,0 +1,69 @@
1
+ # Icon
2
+
3
+ A responsive SVG icon component that renders raw SVG strings via the SvgLoader component. Supports numeric size control with responsive breakpoint overrides (sm/md/lg) and the sx prop for custom styling.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Icon } from '@janbox/storefront-ui';
9
+ ```
10
+
11
+ ## Props
12
+
13
+ | Prop | Type | Default | Description |
14
+ |------|------|---------|-------------|
15
+ | `source*` | `string` | - | Raw SVG string to render. Typically imported via Vite's ?raw query (e.g. import MyIcon from '@/assets/svg/my-icon.svg?raw'). |
16
+ | `size` | `number` | 24 | Width and height of the icon in pixels. Applied as the base (mobile-first) size. |
17
+ | `sm` | `{ size?: number }` | - | Responsive overrides applied at the sm breakpoint (≥768px). Accepts an object with the same responsive props. |
18
+ | `md` | `{ size?: number }` | - | Responsive overrides applied at the md breakpoint (≥1280px). Accepts an object with the same responsive props. |
19
+ | `lg` | `{ size?: number }` | - | Responsive overrides applied at the lg breakpoint (≥1680px). Accepts an object with the same responsive props. |
20
+ | `sx` | `ToResponsiveProps<StyledCSS>` | - | Escape hatch for custom Emotion CSS. Supports responsive keys (sm/md/lg) for breakpoint-scoped styles. |
21
+ | `...svgProps` | `JSX.IntrinsicElements['svg']` | - | All native SVG element attributes (e.g. className, style, aria-label, onClick) are forwarded to the underlying svg element. |
22
+
23
+ *Required props
24
+
25
+ ## Examples
26
+
27
+ ### Default icon at 24px
28
+
29
+ ```tsx
30
+ import HomeIcon from '@/assets/svg/home.svg?raw';
31
+
32
+ <Icon source={HomeIcon} />
33
+ ```
34
+
35
+ ### Custom size with accessible label
36
+
37
+ ```tsx
38
+ import StarIcon from '@/assets/svg/star.svg?raw';
39
+
40
+ <Icon source={StarIcon} size={32} aria-label="Favourite" />
41
+ ```
42
+
43
+ ### Responsive size across breakpoints
44
+
45
+ ```tsx
46
+ import SearchIcon from '@/assets/svg/search.svg?raw';
47
+
48
+ <Icon
49
+ source={SearchIcon}
50
+ size={20}
51
+ sm={{ size: 20 }}
52
+ md={{ size: 24 }}
53
+ lg={{ size: 28 }}
54
+ />
55
+ ```
56
+
57
+ ## Related Components
58
+
59
+ - [SvgLoader](../svgloader/README.md)
60
+
61
+ ## Dependencies
62
+
63
+ - @emotion/react
64
+
65
+ ## See Also
66
+
67
+ - [Component Source](./index.ts)
68
+ - [Storybook Stories](./icon.stories.tsx)
69
+ - [Main README](../../README.md)
@@ -0,0 +1,92 @@
1
+ # IconButton
2
+
3
+ A button component that renders an icon (and optionally children) with support for contained, outlined, and text variants. Designed for icon-only or icon-with-label actions, with built-in loading state, ripple effect, and responsive sizing.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { IconButton } from '@janbox/storefront-ui';
9
+ ```
10
+
11
+ ## Props
12
+
13
+ | Prop | Type | Default | Description |
14
+ |------|------|---------|-------------|
15
+ | `icon` | `IconProps` | - | Icon to render inside the button. Accepts an SVG raw string via `source` plus any Icon component props (size, sx, responsive breakpoints). |
16
+ | `variant` | `'contained' \| 'outlined' \| 'text'` | `'text'` | Visual style of the button. |
17
+ | `color` | `'primary' \| 'secondary' \| 'green' \| 'red' \| 'orange' \| 'blue' \| 'neutral'` | `'primary'` | Color variant that controls background, border, and icon color based on the design token palette. |
18
+ | `size` | `'xs' \| 'sm' \| 'md' \| 'lg'` | `'md'` | Controls the minimum width/height of the button and icon size. |
19
+ | `isLoading` | `boolean` | `false` | When true, hides the icon and shows a spinning loading indicator. Disables pointer events. |
20
+ | `sx` | `ToResponsiveProps<StyledCSS>` | - | Escape hatch for custom Emotion CSS styles, including responsive overrides at sm/md/lg breakpoints. |
21
+ | `sm` | `IconButtonResponsiveProps` | - | Responsive size override applied at the sm breakpoint (≥768px). |
22
+ | `md` | `IconButtonResponsiveProps` | - | Responsive size override applied at the md breakpoint (≥1280px). |
23
+ | `lg` | `IconButtonResponsiveProps` | - | Responsive size override applied at the lg breakpoint (≥1680px). |
24
+ | `disabled` | `boolean` | `false` | Native HTML disabled attribute. Disables pointer events and applies neutral disabled colors. |
25
+ | `aria-disabled` | `boolean \| 'true' \| 'false'` | - | Aria-disabled state. Applies disabled styling without removing the element from the tab order. |
26
+ | `children` | `React.ReactNode` | - | Optional content rendered alongside the icon (e.g. a label). |
27
+ | `onClick` | `React.MouseEventHandler<HTMLButtonElement>` | - | Click handler forwarded from native button props. |
28
+
29
+ ## Examples
30
+
31
+ ### Text variant (default) with a star icon
32
+
33
+ ```tsx
34
+ <IconButton icon={{ source: starSvg }} onClick={handleClick} />
35
+ ```
36
+
37
+ ### Contained primary button with loading state
38
+
39
+ ```tsx
40
+ <IconButton
41
+ icon={{ source: searchSvg }}
42
+ variant="contained"
43
+ color="primary"
44
+ isLoading={isFetching}
45
+ />
46
+ ```
47
+
48
+ ### Outlined small close button with aria-disabled
49
+
50
+ ```tsx
51
+ <IconButton
52
+ icon={{ source: closeSvg }}
53
+ variant="outlined"
54
+ color="red"
55
+ size="sm"
56
+ aria-disabled={!canClose}
57
+ />
58
+ ```
59
+
60
+ ### Responsive size — nhỏ trên mobile, lớn hơn trên desktop
61
+
62
+ ```tsx
63
+ <IconButton
64
+ icon={{ source: filterSvg }}
65
+ variant="outlined"
66
+ size="sm"
67
+ md={{ size: 'md' }}
68
+ />
69
+ ```
70
+
71
+ ### Icon button với label
72
+
73
+ ```tsx
74
+ <IconButton icon={{ source: editSvg }} variant="text" color="primary">
75
+ Chỉnh sửa
76
+ </IconButton>
77
+ ```
78
+
79
+ ## Related Components
80
+
81
+ - [Icon](../icon/README.md)
82
+ - [RippleEffect](../ripple-effect/README.md)
83
+
84
+ ## Dependencies
85
+
86
+ - `@emotion/react`
87
+
88
+ ## See Also
89
+
90
+ - [Component Source](./index.ts)
91
+ - [Storybook Stories](./icon-button.stories.tsx)
92
+ - [Main README](../../README.md)
@@ -0,0 +1,80 @@
1
+ # Image
2
+
3
+ A polymorphic image component that wraps the native `<img>` element with built-in fallback support and sensible defaults. It automatically handles broken image sources by swapping in a fallback URL or a default placeholder, and applies `loading="lazy"` and `object-fit: cover` out of the box.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Image } from '@janbox/storefront-ui';
9
+ ```
10
+
11
+ ## Props
12
+
13
+ | Prop | Type | Default | Description |
14
+ |------|------|---------|-------------|
15
+ | `src` | `string` | - | The URL of the image to display. If empty or undefined, the fallback source is used instead. |
16
+ | `alt` | `string` | "" | Alternative text for the image. Defaults to an empty string if not provided. |
17
+ | `fallback` | `string \| boolean` | true | Controls fallback behavior when the image fails to load. Pass `true` to use the built-in IMAGE_PLACEHOLDER constant, a string URL to use a custom fallback image, or `false` to disable fallback entirely. |
18
+ | `loading` | `"lazy" \| "eager"` | "lazy" | Native img loading attribute. Defaults to 'lazy' for performance. |
19
+ | `sx` | `ToResponsiveProps<StyledCSS>` | { objectFit: 'cover' } | Responsive style overrides via the Emotion sx prop. Base styles apply `objectFit: 'cover'` and `maxHeight: '100%'`. |
20
+ | `width` | `number \| string` | - | Native img width attribute. |
21
+ | `height` | `number \| string` | - | Native img height attribute. |
22
+ | `onError` | `React.ReactEventHandler<HTMLImageElement>` | - | Called after the fallback logic runs when the image fails to load. The component handles src replacement internally before invoking this callback. |
23
+ | `as` | `React.ElementType` | "img" | Polymorphic tag override inherited from Primitive. Defaults to 'img'. |
24
+ | `ref` | `React.Ref<HTMLImageElement>` | - | Forwarded ref to the underlying img element. |
25
+
26
+ ## Examples
27
+
28
+ ### Default usage
29
+
30
+ ```tsx
31
+ <Image
32
+ src="https://via.placeholder.com/300x200"
33
+ alt="Placeholder image"
34
+ width={300}
35
+ height={200}
36
+ />
37
+ ```
38
+
39
+ ### Custom fallback URL on error
40
+
41
+ ```tsx
42
+ <Image
43
+ src="https://invalid-url.example.com/image.jpg"
44
+ alt="Image with fallback"
45
+ fallback="https://via.placeholder.com/300x200?text=Fallback"
46
+ width={300}
47
+ height={200}
48
+ />
49
+ ```
50
+
51
+ ### Built-in placeholder fallback with responsive sx
52
+
53
+ ```tsx
54
+ <Image
55
+ src="https://cdn.example.com/product.jpg"
56
+ alt="Product thumbnail"
57
+ fallback={true}
58
+ width={120}
59
+ height={120}
60
+ sx={{
61
+ borderRadius: 8,
62
+ objectFit: 'contain',
63
+ md: { width: 160, height: 160 },
64
+ }}
65
+ />
66
+ ```
67
+
68
+ ## Related Components
69
+
70
+ - [Primitive](../primitive/README.md)
71
+
72
+ ## Dependencies
73
+
74
+ - lodash-es
75
+
76
+ ## See Also
77
+
78
+ - [Component Source](./index.ts)
79
+ - [Storybook Stories](./image.stories.tsx)
80
+ - [Main README](../../README.md)
@@ -0,0 +1,118 @@
1
+ # Input
2
+
3
+ A flexible text input component with support for prefix/suffix slots, start/end icons, password visibility toggle, error state, helper text, debounced onChange, and responsive sizing. Designed for form fields across all sizes of the design system.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { Input } from '@janbox/storefront-ui';
9
+ ```
10
+
11
+ ## Props
12
+
13
+ | Prop | Type | Default | Description |
14
+ |------|------|---------|-------------|
15
+ | `size` | `SizeVariant ('xs' \| 'sm' \| 'md' \| 'lg')` | `md` | Controls height, padding, and font size of the input via the size variant scale. |
16
+ | `sm` | `InputResponsiveProps ({ size?: SizeVariant })` | - | Responsive overrides applied at the sm breakpoint (≥768px). |
17
+ | `md` | `InputResponsiveProps ({ size?: SizeVariant })` | - | Responsive overrides applied at the md breakpoint (≥1280px). |
18
+ | `lg` | `InputResponsiveProps ({ size?: SizeVariant })` | - | Responsive overrides applied at the lg breakpoint (≥1680px). |
19
+ | `sx` | `ToResponsiveProps<StyledCSS>` | - | Escape-hatch for custom Emotion CSS styles, passed to the container element. |
20
+ | `error` | `boolean` | `false` | Puts the input into an error state, showing a red border and applying error styling to the helper text. |
21
+ | `helperText` | `string` | - | Descriptive or validation text rendered below the input via FormHelperText. Color changes when `error` is `true`. |
22
+ | `prefix` | `React.ReactNode` | - | Arbitrary node rendered at the far-left of the input wrapper, outside the icon slots (e.g. a country code badge). |
23
+ | `suffix` | `React.ReactNode` | - | Arbitrary node rendered at the far-right of the input wrapper, outside the icon slots. |
24
+ | `startIcon` | `IconProps` | - | Icon displayed on the left side of the input field, inside the wrapper. Size tracks the current size variant automatically. |
25
+ | `endIcon` | `IconProps` | - | Icon displayed on the right side of the input field, inside the wrapper. Size tracks the current size variant automatically. |
26
+ | `containerProps` | `PrimitiveProps<JSX.IntrinsicElements['div']>` | - | Props forwarded to the outermost wrapper div (position: relative, flex column container). |
27
+ | `mainProps` | `PrimitiveProps<JSX.IntrinsicElements['div']>` | - | Props forwarded to the inner wrapper div that renders the border, background, and layout for the input row. |
28
+ | `value` | `string` | - | Controlled value of the input. When provided alongside `debounce` or `mode='onBlur'`, the component buffers the typing value internally. |
29
+ | `defaultValue` | `string` | - | Uncontrolled default value for the input. |
30
+ | `transform` | `(value: string) => string` | - | Optional function applied to the raw input value on every change event before propagating it (e.g. uppercase, numeric-only filter). |
31
+ | `mode` | `'onChange' \| 'onBlur'` | `onChange` | Determines when `onChange` fires. `'onBlur'` defers the call until the user leaves the field; `'onChange'` fires on every keystroke (subject to `debounce`). |
32
+ | `debounce` | `number` | `0` | Milliseconds to debounce the `onChange` callback. Set to `0` to disable debouncing. |
33
+ | `type` | `string (HTML input type)` | - | Standard HTML input type. When set to `'password'`, a visibility toggle icon is automatically appended. |
34
+ | `disabled` | `boolean` | - | Disables the input and applies a neutral muted style to the wrapper via CSS `:has` selector. |
35
+ | `placeholder` | `string` | - | Placeholder text shown when the input is empty. |
36
+ | `onChange` | `React.ChangeEventHandler<HTMLInputElement>` | - | Change handler. May be deferred depending on `mode` and `debounce` settings. |
37
+
38
+ ## Examples
39
+
40
+ ### Default input with placeholder
41
+
42
+ ```tsx
43
+ <Input placeholder="Enter text..." onChange={handleChange} />
44
+ ```
45
+
46
+ ### Error state with helper text
47
+
48
+ ```tsx
49
+ <Input
50
+ placeholder="Enter email..."
51
+ error={true}
52
+ helperText="Invalid email address"
53
+ onChange={handleChange}
54
+ />
55
+ ```
56
+
57
+ ### Password input with debounced onChange
58
+
59
+ ```tsx
60
+ <Input
61
+ type="password"
62
+ placeholder="Enter password..."
63
+ mode="onChange"
64
+ debounce={300}
65
+ value={password}
66
+ onChange={(e) => setPassword(e.target.value)}
67
+ />
68
+ ```
69
+
70
+ ### Input với icon và prefix/suffix
71
+
72
+ ```tsx
73
+ <Input
74
+ placeholder="Tìm kiếm..."
75
+ startIcon={{ source: SearchIcon }}
76
+ suffix={<span>VND</span>}
77
+ size="lg"
78
+ />
79
+ ```
80
+
81
+ ### Responsive sizing
82
+
83
+ ```tsx
84
+ <Input
85
+ size="sm"
86
+ sm={{ size: 'md' }}
87
+ md={{ size: 'lg' }}
88
+ placeholder="Responsive input"
89
+ />
90
+ ```
91
+
92
+ ### onBlur mode với transform
93
+
94
+ ```tsx
95
+ <Input
96
+ mode="onBlur"
97
+ transform={(val) => val.toUpperCase()}
98
+ placeholder="Uppercase on blur"
99
+ onChange={(e) => console.log(e.target.value)}
100
+ />
101
+ ```
102
+
103
+ ## Related Components
104
+
105
+ - [Icon](../icon/README.md)
106
+ - [FormHelperText](../formhelpertext/README.md)
107
+ - [Primitive](../primitive/README.md)
108
+
109
+ ## Dependencies
110
+
111
+ - `@floating-ui/react`
112
+ - `lodash-es`
113
+
114
+ ## See Also
115
+
116
+ - [Component Source](./index.ts)
117
+ - [Storybook Stories](./input.stories.tsx)
118
+ - [Main README](../../README.md)
@@ -0,0 +1,88 @@
1
+ # InputMask
2
+
3
+ Wrapper component cung cấp container input có style với hỗ trợ icons, prefix/suffix slots, trạng thái lỗi, và responsive sizing. Được dùng làm visual shell cho các custom input component cần layout bordered, padded nhất quán với icon placement.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { InputMask } from '@janbox/storefront-ui';
9
+ ```
10
+
11
+ ## Props
12
+
13
+ | Prop | Type | Default | Description |
14
+ |------|------|---------|-------------|
15
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Kiểm soát chiều cao và horizontal padding của container. Loại trừ `'xs'` khỏi SizeVariant. |
16
+ | `outline` | `{ top?: number; right?: number; bottom?: number; left?: number }` | - | Override border width riêng lẻ trên pseudo-element outline. Hữu ích khi cần bỏ một cạnh cụ thể (ví dụ: chỉ hiện border bottom). |
17
+ | `prefix` | `React.ReactNode` | - | Nội dung render trước startIcon và children. Thường dùng cho text label hoặc ký hiệu tiền tệ đặt ngoài inner flow. |
18
+ | `suffix` | `React.ReactNode` | - | Nội dung render sau children và endIcon. Thường dùng cho đơn vị hoặc trailing label. |
19
+ | `startIcon` | `IconProps` | - | Icon hiển thị bên trái, trước children. Nhận raw SVG qua IconProps. Size tự động lấy từ size variant hiện tại. |
20
+ | `endIcon` | `IconProps` | - | Icon hiển thị bên phải, sau children. Nhận raw SVG qua IconProps. Size tự động lấy từ size variant hiện tại. |
21
+ | `error` | `boolean` | `false` | Khi `true`, render border outline màu đỏ (`--color-red-600`) để báo lỗi validation. |
22
+ | `sm` | `InputMaskResponsiveProps` | - | Responsive overrides tại breakpoint sm (≥768px). Nhận `size` và `outline`. |
23
+ | `md` | `InputMaskResponsiveProps` | - | Responsive overrides tại breakpoint md (≥1280px). Nhận `size` và `outline`. |
24
+ | `lg` | `InputMaskResponsiveProps` | - | Responsive overrides tại breakpoint lg (≥1680px). Nhận `size` và `outline`. |
25
+ | `sx` | `ToResponsiveProps<StyledCSS>` | - | Escape hatch cho custom Emotion CSS styles, hỗ trợ responsive keys (`sm`, `md`, `lg`). |
26
+ | `children` | `React.ReactNode` | - | Inner input element hoặc nội dung render giữa startIcon và endIcon. |
27
+ | `as` | `React.ElementType` | - | Polymorphic prop kế thừa từ PrimitiveProps. Cho phép render thành HTML element hoặc component khác. |
28
+
29
+ ## Examples
30
+
31
+ ### Mặc định
32
+
33
+ ```tsx
34
+ <InputMask placeholder="Input mask..." />
35
+ ```
36
+
37
+ ### Trạng thái lỗi với size nhỏ
38
+
39
+ ```tsx
40
+ <InputMask size="sm" error placeholder="Enter value..." />
41
+ ```
42
+
43
+ ### Với start icon, suffix, và responsive sizing
44
+
45
+ ```tsx
46
+ <InputMask
47
+ size="md"
48
+ sm={{ size: 'lg' }}
49
+ startIcon={{ source: SearchIcon }}
50
+ suffix={<span>.00</span>}
51
+ >
52
+ <input placeholder="Search..." />
53
+ </InputMask>
54
+ ```
55
+
56
+ ### Bottom-only border (outline override)
57
+
58
+ ```tsx
59
+ <InputMask outline={{ top: 0, left: 0, right: 0 }}>
60
+ <input placeholder="Underline style..." />
61
+ </InputMask>
62
+ ```
63
+
64
+ ### Prefix và suffix label
65
+
66
+ ```tsx
67
+ <InputMask
68
+ prefix={<span>USD</span>}
69
+ suffix={<span>/month</span>}
70
+ >
71
+ <input type="number" placeholder="0" />
72
+ </InputMask>
73
+ ```
74
+
75
+ ## Related Components
76
+
77
+ - [Icon](../icon/README.md)
78
+ - [Primitive](../primitive/README.md)
79
+
80
+ ## Dependencies
81
+
82
+ - @emotion/react
83
+
84
+ ## See Also
85
+
86
+ - [Component Source](./index.ts)
87
+ - [Storybook Stories](./inputmask.stories.tsx)
88
+ - [Main README](../../README.md)