|
1 | | -import React, { ComponentProps, useCallback, useRef, useState } from 'react'; |
2 | | -import type { StoryObj, Meta } from '@storybook/react-vite'; |
3 | | -import { action } from 'storybook/actions'; |
4 | | -import { disableProps, InSpacingDecorator } from '@salutejs/plasma-sb-utils'; |
| 1 | +import React, { ComponentProps } from 'react'; |
| 2 | +import type { Meta } from '@storybook/react'; |
| 3 | +import { getCalendarStories } from '@salutejs/plasma-sb-utils'; |
5 | 4 |
|
6 | 5 | import { Tabs } from '../Tabs/Tabs'; |
7 | 6 | import { TabItem } from '../Tabs/TabItem'; |
8 | 7 | import { H3 } from '../Typography'; |
9 | 8 |
|
10 | | -import { Calendar, CalendarBase, CalendarBaseRange, CalendarDouble, CalendarDoubleRange } from '.'; |
| 9 | +import { config } from './CalendarBase.config'; |
| 10 | +import { Calendar, CalendarBase, CalendarBaseRange, CalendarDouble, CalendarDoubleRange } from './Calendar'; |
11 | 11 |
|
12 | | -const onChangeValue = action('onChangeValue'); |
| 12 | +type ButtonProps = ComponentProps<typeof Calendar>; |
13 | 13 |
|
14 | | -const meta: Meta<CalendarProps> = { |
15 | | - title: 'Data Entry/Calendar', |
16 | | - decorators: [InSpacingDecorator], |
| 14 | +const { meta: META, Default, Range } = getCalendarStories({ |
17 | 15 | component: Calendar, |
18 | | - argTypes: { |
19 | | - min: { |
20 | | - control: { |
21 | | - type: 'date', |
22 | | - }, |
23 | | - }, |
24 | | - max: { |
25 | | - control: { |
26 | | - type: 'date', |
27 | | - }, |
28 | | - }, |
29 | | - ...disableProps([ |
30 | | - 'size', |
31 | | - 'value', |
32 | | - 'onChangeValue', |
33 | | - 'date', |
34 | | - 'eventList', |
35 | | - 'disabledList', |
36 | | - 'eventMonthList', |
37 | | - 'disabledMonthList', |
38 | | - 'eventQuarterList', |
39 | | - 'disabledQuarterList', |
40 | | - 'eventYearList', |
41 | | - 'disabledYearList', |
42 | | - 'type', |
43 | | - 'view', |
44 | | - 'onChangeStartOfRange', |
45 | | - ]), |
46 | | - }, |
47 | | -}; |
48 | | - |
49 | | -export default meta; |
50 | | - |
51 | | -type CalendarProps = ComponentProps<typeof Calendar>; |
52 | | -type CalendarBaseProps = ComponentProps<typeof CalendarBase>; |
53 | | -type CalendarBaseRangeProps = ComponentProps<typeof CalendarBaseRange>; |
54 | | -const defaultMinDate = new Date(2016, 6, 1); |
55 | | -const defaultMaxDate = new Date(2030, 11, 24); |
56 | | - |
57 | | -const getBaseEvents = (type: 'days' | 'months' | 'quarters' | 'years', datesNumber = 2) => { |
58 | | - const baseDate = { |
59 | | - day: 10, |
60 | | - monthIndex: 6, |
61 | | - year: 2023, |
62 | | - }; |
63 | | - |
64 | | - const events = [...new Array(datesNumber)].map((_, index) => { |
65 | | - const eventNumber = index + 1; |
66 | | - const day = type === 'days' ? baseDate.day + index : 1; |
67 | | - const month = |
68 | | - // eslint-disable-next-line no-nested-ternary |
69 | | - type === 'months' || type === 'quarters' |
70 | | - ? baseDate.monthIndex + index |
71 | | - : type === 'days' |
72 | | - ? baseDate.monthIndex |
73 | | - : 0; |
74 | | - const year = type === 'years' ? baseDate.year + index : baseDate.year; |
75 | | - |
76 | | - return [...new Array(eventNumber)].map(() => { |
77 | | - return { date: new Date(year, month, day), color: 'var(--text-warning)' }; |
78 | | - }); |
79 | | - }); |
80 | | - |
81 | | - return events.flat(); |
82 | | -}; |
83 | | - |
84 | | -const StoryDefault = (args: CalendarProps) => { |
85 | | - const { isRange, isDouble, min, max, date, includeEdgeDates, size, ...rest } = args; |
86 | | - const [value, setValue] = useState(new Date(2023, 10, 16)); |
87 | | - const [valueRange, setValueRange] = useState<[Date, Date?]>([new Date(2023, 10, 16), new Date(2023, 10, 23)]); |
88 | | - |
89 | | - const handleOnChange = useCallback((newValue: Date) => { |
90 | | - setValue(newValue); |
91 | | - onChangeValue(newValue); |
92 | | - }, []); |
93 | | - const handleOnRangeChange = useCallback((newValue: [Date, Date?]) => { |
94 | | - setValueRange(newValue); |
95 | | - }, []); |
96 | | - |
97 | | - return ( |
98 | | - <div style={{ height: '100vh' }}> |
99 | | - <Calendar |
100 | | - size={size} |
101 | | - isRange={isRange} |
102 | | - isDouble={isDouble} |
103 | | - date={date} |
104 | | - includeEdgeDates={includeEdgeDates} |
105 | | - min={min} |
106 | | - max={max} |
107 | | - {...rest} |
108 | | - value={(isRange ? valueRange : value) as Date & [Date, Date?]} |
109 | | - onChangeValue={ |
110 | | - (isRange ? handleOnRangeChange : handleOnChange) as (value: Date | [Date, Date?]) => void |
111 | | - } |
112 | | - /> |
113 | | - </div> |
114 | | - ); |
115 | | -}; |
116 | | - |
117 | | -export const Default: StoryObj<CalendarProps> = { |
118 | | - args: { |
119 | | - min: new Date(2023, 10, 1), |
120 | | - max: new Date(2023, 11, 24), |
121 | | - isDouble: false, |
122 | | - isRange: false, |
123 | | - includeEdgeDates: false, |
124 | | - size: 's', |
125 | | - stretched: false, |
| 16 | + componentConfig: config, |
| 17 | + additionalComponents: { |
| 18 | + Tabs, |
| 19 | + TabItem, |
| 20 | + Heading: H3, |
| 21 | + CalendarBase, |
| 22 | + CalendarBaseRange, |
| 23 | + CalendarDouble, |
| 24 | + CalendarDoubleRange, |
126 | 25 | }, |
127 | | - render: (args) => <StoryDefault {...args} />, |
128 | | -}; |
129 | | - |
130 | | -const StoryBase = (args: CalendarBaseProps & { displayDouble: boolean }) => { |
131 | | - const { min, max, includeEdgeDates, size, displayDouble, ...rest } = args; |
132 | | - const [value, setValue] = useState(new Date(2023, 6, 7)); |
133 | | - const [currentState, setCurrentState] = useState('Days'); |
134 | | - |
135 | | - const handleOnChange = useCallback((newValue: Date, dateInfo?: unknown) => { |
136 | | - setValue(newValue); |
137 | | - onChangeValue(newValue, dateInfo); |
138 | | - }, []); |
139 | | - |
140 | | - const eventList = useRef(getBaseEvents('days', 5)); |
141 | | - const eventMonthList = useRef(getBaseEvents('months', 5)); |
142 | | - const eventQuarterList = useRef(getBaseEvents('quarters')); |
143 | | - const eventYearList = useRef(getBaseEvents('years')); |
| 26 | + defaultArgs: { enableEventTooltip: false, size: 's' }, |
| 27 | + disablePropsList: ['eventTooltipSize', 'enableEventTooltip'], |
| 28 | +}); |
144 | 29 |
|
145 | | - const disabledDays = [...new Array(5)].map((_, day) => ({ |
146 | | - date: new Date(2023, 6, 23 + day), |
147 | | - })); |
148 | | - |
149 | | - const getCalendarComponent = ({ type, ...rest }) => { |
150 | | - return displayDouble ? ( |
151 | | - <CalendarDouble |
152 | | - size={size} |
153 | | - value={value} |
154 | | - includeEdgeDates={includeEdgeDates} |
155 | | - type={type} |
156 | | - onChangeValue={handleOnChange} |
157 | | - min={min} |
158 | | - max={max} |
159 | | - {...rest} |
160 | | - /> |
161 | | - ) : ( |
162 | | - <CalendarBase |
163 | | - size={size} |
164 | | - value={value} |
165 | | - includeEdgeDates={includeEdgeDates} |
166 | | - type={type} |
167 | | - onChangeValue={handleOnChange} |
168 | | - min={min} |
169 | | - max={max} |
170 | | - {...rest} |
171 | | - /> |
172 | | - ); |
173 | | - }; |
174 | | - |
175 | | - const calendarMap = { |
176 | | - Days: getCalendarComponent({ type: 'Days', eventList, disabledList: disabledDays, ...rest }), |
177 | | - Months: getCalendarComponent({ type: 'Months', eventMonthList, ...rest }), |
178 | | - Quarters: getCalendarComponent({ type: 'Quarters', eventQuarterList, ...rest }), |
179 | | - Years: getCalendarComponent({ type: 'Years', eventYearList, ...rest }), |
180 | | - }; |
181 | | - |
182 | | - return ( |
183 | | - <> |
184 | | - <H3>Тип календаря</H3> |
185 | | - <Tabs view="divider" size="s" hasDivider> |
186 | | - {Object.keys(calendarMap).map((state, i) => ( |
187 | | - <TabItem |
188 | | - key={`item:${i}`} |
189 | | - view="divider" |
190 | | - selected={state === currentState} |
191 | | - onClick={() => setCurrentState(state)} |
192 | | - size="s" |
193 | | - > |
194 | | - {state} |
195 | | - </TabItem> |
196 | | - ))} |
197 | | - </Tabs> |
198 | | - <div style={{ marginTop: '1rem', height: '100vh' }}>{calendarMap[currentState]}</div> |
199 | | - </> |
200 | | - ); |
201 | | -}; |
202 | | - |
203 | | -export const Base: StoryObj<CalendarBaseProps & { displayDouble: boolean }> = { |
204 | | - argTypes: { |
205 | | - ...disableProps(['isRange', 'isDouble']), |
206 | | - }, |
207 | | - args: { |
208 | | - size: 's', |
209 | | - min: defaultMinDate, |
210 | | - max: defaultMaxDate, |
211 | | - includeEdgeDates: false, |
212 | | - displayDouble: false, |
213 | | - stretched: false, |
214 | | - }, |
215 | | - render: (args) => <StoryBase {...args} />, |
| 30 | +const meta: Meta<ButtonProps> = { |
| 31 | + ...META, |
| 32 | + title: 'Data Entry/Calendar', |
216 | 33 | }; |
217 | 34 |
|
218 | | -const StoryRange = (args: CalendarBaseRangeProps & { displayDouble: boolean }) => { |
219 | | - const { min, max, includeEdgeDates, size, displayDouble, ...rest } = args; |
220 | | - const [values, setValue] = useState<[Date, Date?]>([new Date(2023, 6, 1), new Date(2023, 6, 16)]); |
221 | | - const [currentState, setCurrentState] = useState('Days'); |
222 | | - |
223 | | - const handleOnChange = (newValue: [Date, Date?], dateInfo) => { |
224 | | - onChangeValue(newValue, dateInfo); |
225 | | - setValue(newValue); |
226 | | - }; |
227 | | - |
228 | | - const eventList = useRef(getBaseEvents('days', 5)); |
229 | | - const eventMonthList = useRef(getBaseEvents('months', 5)); |
230 | | - const eventQuarterList = useRef(getBaseEvents('quarters')); |
231 | | - const eventYearList = useRef(getBaseEvents('years')); |
232 | | - |
233 | | - const disabledDays = [...new Array(5)].map((_, day) => ({ |
234 | | - date: new Date(2023, 6, 23 + day), |
235 | | - })); |
236 | | - |
237 | | - const getCalendarComponent = ({ type, ...rest }) => { |
238 | | - return displayDouble ? ( |
239 | | - <CalendarDoubleRange |
240 | | - size={size} |
241 | | - min={min} |
242 | | - max={max} |
243 | | - includeEdgeDates={includeEdgeDates} |
244 | | - type={type} |
245 | | - {...rest} |
246 | | - value={values} |
247 | | - onChangeValue={handleOnChange} |
248 | | - /> |
249 | | - ) : ( |
250 | | - <CalendarBaseRange |
251 | | - size={size} |
252 | | - min={min} |
253 | | - max={max} |
254 | | - includeEdgeDates={includeEdgeDates} |
255 | | - type={type} |
256 | | - {...rest} |
257 | | - value={values} |
258 | | - onChangeValue={handleOnChange} |
259 | | - /> |
260 | | - ); |
261 | | - }; |
262 | | - |
263 | | - const calendarMap = { |
264 | | - Days: getCalendarComponent({ type: 'Days', eventList, disabledList: disabledDays, ...rest }), |
265 | | - Months: getCalendarComponent({ type: 'Months', eventMonthList, ...rest }), |
266 | | - Quarters: getCalendarComponent({ type: 'Quarters', eventQuarterList, ...rest }), |
267 | | - Years: getCalendarComponent({ type: 'Years', eventYearList, ...rest }), |
268 | | - }; |
269 | | - |
270 | | - return ( |
271 | | - <> |
272 | | - <H3>Тип календаря</H3> |
273 | | - <Tabs view="divider" size="s" hasDivider> |
274 | | - {Object.keys(calendarMap).map((state, i) => ( |
275 | | - <TabItem |
276 | | - key={`item:${i}`} |
277 | | - view="divider" |
278 | | - selected={state === currentState} |
279 | | - onClick={() => setCurrentState(state)} |
280 | | - size="s" |
281 | | - > |
282 | | - {state} |
283 | | - </TabItem> |
284 | | - ))} |
285 | | - </Tabs> |
286 | | - <div style={{ marginTop: '1rem', height: '100vh' }}>{calendarMap[currentState]}</div> |
287 | | - </> |
288 | | - ); |
289 | | -}; |
| 35 | +export default meta; |
290 | 36 |
|
291 | | -export const Range: StoryObj<CalendarBaseRangeProps & { displayDouble: boolean }> = { |
292 | | - argTypes: { |
293 | | - ...disableProps(['isRange', 'isDouble']), |
294 | | - }, |
295 | | - args: { |
296 | | - size: 's', |
297 | | - min: defaultMinDate, |
298 | | - max: defaultMaxDate, |
299 | | - includeEdgeDates: false, |
300 | | - displayDouble: false, |
301 | | - stretched: false, |
302 | | - }, |
303 | | - render: (args) => <StoryRange {...args} />, |
304 | | -}; |
| 37 | +export { Default, Range }; |
0 commit comments