1- // Button.stories.ts|tsx
2- import DynamicUnitInputNumber , {
1+ import BAIDynamicUnitInputNumber , {
32 BAIDynamicUnitInputNumberProps ,
43} from './BAIDynamicUnitInputNumber' ;
54import type { Meta , StoryObj } from '@storybook/react-vite' ;
65import { Form } from 'antd' ;
76
8- const meta : Meta < typeof DynamicUnitInputNumber > = {
7+ /**
8+ * BAIDynamicUnitInputNumber is a specialized input for handling memory/storage values with unit conversion.
9+ *
10+ * Key features:
11+ * - Automatic unit conversion between MiB, GiB, TiB, PiB
12+ * - Dynamic step increments based on current unit
13+ * - Configurable unit restrictions (e.g., GiB only)
14+ * - Min/max validation with unit support
15+ * - Integration with Ant Design Form
16+ *
17+ * @see BAIDynamicUnitInputNumber.tsx for implementation details
18+ */
19+ const meta : Meta < typeof BAIDynamicUnitInputNumber > = {
920 title : 'Input/BAIDynamicUnitInputNumber' ,
10- component : DynamicUnitInputNumber ,
21+ component : BAIDynamicUnitInputNumber ,
22+ tags : [ 'autodocs' ] ,
1123 parameters : {
12- // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
1324 layout : 'centered' ,
25+ docs : {
26+ description : {
27+ component : `
28+ **BAIDynamicUnitInputNumber** is a specialized input component for handling memory and storage values with automatic unit conversion.
29+
30+ ## Features
31+ - Automatic unit conversion between MiB, GiB, TiB, PiB
32+ - Dynamic step increments that adapt to the current unit
33+ - Configurable min/max values with unit support (e.g., '256m', '45g')
34+ - Unit restriction (allow only specific units)
35+ - Seamless integration with Ant Design Form
36+ - Optional auto-unit switching based on value magnitude
37+
38+ ## Props
39+ | Name | Type | Default | Description |
40+ |------|------|---------|-------------|
41+ | \`min\` | \`string\` | \`'0m'\` | Minimum value with unit (e.g., '100m', '2g') |
42+ | \`max\` | \`string\` | \`'300p'\` | Maximum value with unit |
43+ | \`value\` | \`string \\| null \\| undefined\` | - | Current value with unit (controlled) |
44+ | \`units\` | \`string[]\` | \`['m', 'g', 't', 'p']\` | Allowed units (m=MiB, g=GiB, t=TiB, p=PiB) |
45+ | \`dynamicSteps\` | \`number[]\` | \`[1, 2, 4, 8, ...]\` | Step increments for input |
46+ | \`roundStep\` | \`number\` | - | Round input value to nearest step |
47+ | \`disableAutoUnit\` | \`boolean\` | \`false\` | Disable automatic unit switching |
48+ | \`addonPrefix\` | \`ReactNode\` | - | Content before input |
49+ | \`addonSuffix\` | \`ReactNode\` | - | Content after input |
50+ | \`onChange\` | \`(value: string) => void\` | - | Callback when value changes |
51+
52+ For all other props, refer to [Ant Design InputNumber](https://ant.design/components/input-number).
53+
54+ ## Unit Abbreviations
55+ - \`m\` - MiB (Mebibyte)
56+ - \`g\` - GiB (Gibibyte)
57+ - \`t\` - TiB (Tebibyte)
58+ - \`p\` - PiB (Pebibyte)
59+ ` ,
60+ } ,
61+ } ,
62+ } ,
63+ argTypes : {
64+ min : {
65+ control : false ,
66+ description :
67+ 'Minimum value with unit (e.g., "100m", "2g"). Requires format: number + unit (m/g/t/p)' ,
68+ table : {
69+ type : { summary : 'string' } ,
70+ defaultValue : { summary : '0m' } ,
71+ } ,
72+ } ,
73+ max : {
74+ control : false ,
75+ description :
76+ 'Maximum value with unit. Requires format: number + unit (m/g/t/p)' ,
77+ table : {
78+ type : { summary : 'string' } ,
79+ defaultValue : { summary : '300p' } ,
80+ } ,
81+ } ,
82+ value : {
83+ control : false ,
84+ description :
85+ 'Current value with unit (controlled). Requires format: number + unit (m/g/t/p)' ,
86+ table : {
87+ type : { summary : 'string | null | undefined' } ,
88+ } ,
89+ } ,
90+ units : {
91+ control : { type : 'object' } ,
92+ description : 'Allowed units array (m=MiB, g=GiB, t=TiB, p=PiB)' ,
93+ table : {
94+ type : { summary : 'string[]' } ,
95+ defaultValue : { summary : "['m', 'g', 't', 'p']" } ,
96+ } ,
97+ } ,
98+ dynamicSteps : {
99+ control : { type : 'object' } ,
100+ description : 'Array of step increments for the input' ,
101+ table : {
102+ type : { summary : 'number[]' } ,
103+ defaultValue : { summary : '[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]' } ,
104+ } ,
105+ } ,
106+ roundStep : {
107+ control : { type : 'number' } ,
108+ description : 'Round input value to nearest step' ,
109+ table : {
110+ type : { summary : 'number' } ,
111+ } ,
112+ } ,
113+ disableAutoUnit : {
114+ control : { type : 'boolean' } ,
115+ description : 'Disable automatic unit switching based on value magnitude' ,
116+ table : {
117+ type : { summary : 'boolean' } ,
118+ defaultValue : { summary : 'false' } ,
119+ } ,
120+ } ,
121+ addonPrefix : {
122+ control : false ,
123+ description : 'Content to display before the input' ,
124+ table : {
125+ type : { summary : 'ReactNode' } ,
126+ } ,
127+ } ,
128+ addonSuffix : {
129+ control : false ,
130+ description : 'Content to display after the input' ,
131+ table : {
132+ type : { summary : 'ReactNode' } ,
133+ } ,
134+ } ,
135+ onChange : {
136+ action : 'changed' ,
137+ description : 'Callback fired when value changes' ,
138+ table : {
139+ type : { summary : '(value: string) => void' } ,
140+ } ,
141+ } ,
142+ disabled : {
143+ control : { type : 'boolean' } ,
144+ description : 'Disable the input' ,
145+ table : {
146+ type : { summary : 'boolean' } ,
147+ defaultValue : { summary : 'false' } ,
148+ } ,
149+ } ,
150+ size : {
151+ control : { type : 'select' } ,
152+ options : [ 'small' , 'middle' , 'large' ] ,
153+ description : 'Input size' ,
154+ table : {
155+ type : { summary : "'small' | 'middle' | 'large'" } ,
156+ } ,
157+ } ,
14158 } ,
15159} ;
16160
17161export default meta ;
18162
19- type Story = StoryObj < typeof DynamicUnitInputNumber > ;
20-
163+ type Story = StoryObj < typeof BAIDynamicUnitInputNumber > ;
21164const renderWithFormItem = ( {
22165 value,
23166 ...args
@@ -29,42 +172,83 @@ const renderWithFormItem = ({
29172 } }
30173 >
31174 < Form . Item name = "mem" >
32- < DynamicUnitInputNumber { ...args } />
175+ < BAIDynamicUnitInputNumber { ...args } />
33176 </ Form . Item >
34177 </ Form >
35178 ) ;
36179} ;
37180
181+ export const Default : Story = {
182+ name : 'Basic' ,
183+ parameters : {
184+ docs : {
185+ description : {
186+ story :
187+ 'Basic uncontrolled usage with default settings. Allows all units (MiB, GiB, TiB, PiB).' ,
188+ } ,
189+ } ,
190+ } ,
191+ } ;
192+
38193export const WithFormItem : Story = {
39- name : 'Controlled by Form.Item' ,
194+ name : 'FormIntegration' ,
195+ parameters : {
196+ docs : {
197+ description : {
198+ story :
199+ 'Controlled by Ant Design Form.Item. The component syncs with form state automatically.' ,
200+ } ,
201+ } ,
202+ } ,
40203 render : renderWithFormItem ,
41204 args : {
42205 value : '1.3g' ,
43206 } ,
44207} ;
45208
46- export const Default : Story = {
47- name : 'Uncontrolled' ,
48- } ;
49-
50- export const WithMin : Story = {
51- name : 'With min/max' ,
209+ export const WithMinMax : Story = {
210+ name : 'MinMaxRange' ,
211+ parameters : {
212+ docs : {
213+ description : {
214+ story :
215+ 'Custom min/max range. Input validates against these boundaries.' ,
216+ } ,
217+ } ,
218+ } ,
52219 args : {
53220 min : '256m' ,
54221 max : '45g' ,
55222 } ,
56223} ;
57224
58- export const AllowOlnyMiBandGiB : Story = {
59- name : 'unit: MiB, GiB' ,
225+ export const AllowOnlyMiBandGiB : Story = {
226+ name : 'MiBGiBUnits' ,
227+ parameters : {
228+ docs : {
229+ description : {
230+ story :
231+ 'Restrict units to MiB and GiB only. User can switch between these two units.' ,
232+ } ,
233+ } ,
234+ } ,
60235 args : {
61236 min : '256m' ,
62237 max : '45g' ,
63238 units : [ 'm' , 'g' ] ,
64239 } ,
65240} ;
66- export const AllowOlnyGiB : Story = {
67- name : 'unit: GiB' ,
241+
242+ export const AllowOnlyGiB : Story = {
243+ name : 'GiBOnly' ,
244+ parameters : {
245+ docs : {
246+ description : {
247+ story :
248+ 'Restrict to GiB unit only. Useful when fractional GiB values are needed.' ,
249+ } ,
250+ } ,
251+ } ,
68252 args : {
69253 min : '100m' ,
70254 max : '45g' ,
0 commit comments