@12-apps/ui 1.5.0 → 1.5.2
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/package.json +17 -9
- package/src/button/index.ts +1 -0
- package/src/social-login-button/index.ts +1 -0
- package/src/{social-login-button.tsx → social-login-button/social-login-button.tsx} +5 -5
- package/src/user-avatar/index.ts +1 -0
- package/src/{user-avatar.tsx → user-avatar/user-avatar.tsx} +4 -4
- package/eslint.config.js +0 -89
- package/src/__tests__/data-grid.test.tsx +0 -125
- package/src/__tests__/package-wiring.test.ts +0 -41
- package/src/__tests__/setup.ts +0 -1
- package/src/__tests__/social-login-button.test.tsx +0 -186
- package/src/__tests__/user-avatar.test.tsx +0 -195
- package/src/__tests__/viewport.test.ts +0 -50
- package/src/components/command/__tests__/command.test.tsx +0 -112
- package/src/components/data-display/Alert/Alert.stories.tsx +0 -559
- package/src/components/data-display/Alert/Alert.test.stories.tsx +0 -707
- package/src/components/data-display/AlertDialog/AlertDialog.stories.tsx +0 -362
- package/src/components/data-display/AlertDialog/AlertDialog.test.stories.tsx +0 -763
- package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.stories.tsx +0 -230
- package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.test.stories.tsx +0 -270
- package/src/components/data-display/Avatar/Avatar.stories.tsx +0 -721
- package/src/components/data-display/Avatar/Avatar.test.stories.tsx +0 -822
- package/src/components/data-display/Badge/Badge.stories.tsx +0 -1134
- package/src/components/data-display/Badge/Badge.test.stories.tsx +0 -1194
- package/src/components/data-display/Banner/Banner.stories.tsx +0 -528
- package/src/components/data-display/Banner/Banner.test.stories.tsx +0 -511
- package/src/components/data-display/Carousel/Carousel.stories.tsx +0 -607
- package/src/components/data-display/Carousel/Carousel.test.stories.tsx +0 -701
- package/src/components/data-display/Chart/Chart.stories.tsx +0 -568
- package/src/components/data-display/Chart/Chart.test.stories.tsx +0 -174
- package/src/components/data-display/Chart/SpecChart.stories.tsx +0 -150
- package/src/components/data-display/Chart/SpecChart.test.stories.tsx +0 -56
- package/src/components/data-display/Chart/__tests__/SpecChart.test.tsx +0 -60
- package/src/components/data-display/Chart/__tests__/chart-format.test.ts +0 -43
- package/src/components/data-display/Chart/__tests__/chart-spec.test.ts +0 -119
- package/src/components/data-display/Chip/Chip.stories.tsx +0 -252
- package/src/components/data-display/Chip/Chip.test.stories.tsx +0 -266
- package/src/components/data-display/DataGrid/DataGrid.stories.tsx +0 -515
- package/src/components/data-display/DataGrid/DataGrid.test.stories.tsx +0 -653
- package/src/components/data-display/DataViews/__tests__/DataViewsGrid.test.tsx +0 -271
- package/src/components/data-display/DataViews/__tests__/DataViewsTableBase.test.tsx +0 -134
- package/src/components/data-display/DataViews/__tests__/SaveViewModal.test.tsx +0 -83
- package/src/components/data-display/DataViews/__tests__/data-views-filter.test.ts +0 -115
- package/src/components/data-display/DataViews/__tests__/data-views-preview.test.ts +0 -53
- package/src/components/data-display/DataViews/__tests__/range-pill.test.tsx +0 -114
- package/src/components/data-display/DataViews/base-card.stories.tsx +0 -136
- package/src/components/data-display/DescriptionItem/DescriptionItem.stories.tsx +0 -254
- package/src/components/data-display/EmptyState/EmptyState.stories.tsx +0 -282
- package/src/components/data-display/EmptyState/EmptyState.test.stories.tsx +0 -441
- package/src/components/data-display/ErrorState/ErrorState.stories.tsx +0 -110
- package/src/components/data-display/ErrorState/ErrorState.test.stories.tsx +0 -133
- package/src/components/data-display/HoverCard/HoverCard.stories.tsx +0 -650
- package/src/components/data-display/HoverCard/HoverCard.test.stories.tsx +0 -929
- package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.stories.tsx +0 -411
- package/src/components/data-display/LazyImage/LazyImage.stories.tsx +0 -387
- package/src/components/data-display/Lightbox/Lightbox.stories.tsx +0 -315
- package/src/components/data-display/Lightbox/Lightbox.test.stories.tsx +0 -598
- package/src/components/data-display/LoadingState/LoadingState.stories.tsx +0 -124
- package/src/components/data-display/LoadingState/LoadingState.test.stories.tsx +0 -99
- package/src/components/data-display/MapPreview/MapPreview.stories.tsx +0 -458
- package/src/components/data-display/MapPreview/MapPreview.test.stories.tsx +0 -394
- package/src/components/data-display/Popover/Popover.stories.tsx +0 -295
- package/src/components/data-display/Popover/Popover.test.stories.tsx +0 -1162
- package/src/components/data-display/Progress/Progress.stories.tsx +0 -481
- package/src/components/data-display/Progress/Progress.test.stories.tsx +0 -2070
- package/src/components/data-display/SectionOnboarding/SectionOnboarding.stories.tsx +0 -160
- package/src/components/data-display/SectionOnboarding/SectionOnboarding.test.stories.tsx +0 -190
- package/src/components/data-display/Sheet/Sheet.stories.tsx +0 -883
- package/src/components/data-display/Sheet/Sheet.test.stories.tsx +0 -1105
- package/src/components/data-display/StatCard/StatCard.stories.tsx +0 -167
- package/src/components/data-display/StatCard/StatCard.test.stories.tsx +0 -240
- package/src/components/data-display/Stepper/Stepper.stories.tsx +0 -540
- package/src/components/data-display/Stepper/Stepper.test.stories.tsx +0 -600
- package/src/components/data-display/Table/Table.stories.tsx +0 -803
- package/src/components/data-display/Table/Table.test.stories.tsx +0 -369
- package/src/components/data-display/Timeline/Timeline.stories.tsx +0 -442
- package/src/components/data-display/Timeline/Timeline.test.stories.tsx +0 -930
- package/src/components/data-display/TimingDiagram/TimingDiagram.stories.tsx +0 -475
- package/src/components/data-display/TimingDiagram/TimingDiagram.test.stories.tsx +0 -734
- package/src/components/data-display/Tooltip/Tooltip.stories.tsx +0 -468
- package/src/components/data-display/Tooltip/Tooltip.test.stories.tsx +0 -1154
- package/src/components/feedback/ConfirmAction/ConfirmAction.stories.tsx +0 -146
- package/src/components/feedback/ConfirmAction/ConfirmAction.test.stories.tsx +0 -114
- package/src/components/feedback/ConfirmAction/__tests__/confirm-action.test.tsx +0 -288
- package/src/components/feedback/Dialog/Dialog.stories.tsx +0 -833
- package/src/components/feedback/Dialog/Dialog.test.stories.tsx +0 -964
- package/src/components/feedback/Dialog/__tests__/dialog-content-spacing.test.tsx +0 -66
- package/src/components/feedback/Modal/Modal.stories.tsx +0 -765
- package/src/components/feedback/Modal/Modal.test.stories.tsx +0 -251
- package/src/components/feedback/Sonner/Sonner.stories.tsx +0 -698
- package/src/components/feedback/Sonner/Sonner.test.stories.tsx +0 -896
- package/src/components/feedback/StackedModal/StackedModal.stories.tsx +0 -1783
- package/src/components/feedback/StackedModal/StackedModal.test.stories.tsx +0 -973
- package/src/components/feedback/StackedModal/__tests__/stacked-modal-viewport.test.tsx +0 -104
- package/src/components/feedback/Toast/Toast.stories.tsx +0 -548
- package/src/components/feedback/Toast/Toast.test.stories.tsx +0 -834
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.stories.tsx +0 -691
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.test.stories.tsx +0 -634
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.stories.tsx +0 -665
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.test.stories.tsx +0 -727
- package/src/components/form/Autocomplete/Autocomplete.stories.tsx +0 -715
- package/src/components/form/Autocomplete/Autocomplete.test.stories.tsx +0 -825
- package/src/components/form/Button/Button.stories.tsx +0 -365
- package/src/components/form/Button/Button.test.stories.tsx +0 -607
- package/src/components/form/Calendar/Calendar.stories.tsx +0 -349
- package/src/components/form/Calendar/Calendar.test.stories.tsx +0 -464
- package/src/components/form/CepField/CepField.stories.tsx +0 -138
- package/src/components/form/CepField/CepField.test.stories.tsx +0 -281
- package/src/components/form/Checkbox/Checkbox.stories.tsx +0 -265
- package/src/components/form/Checkbox/Checkbox.test.stories.tsx +0 -181
- package/src/components/form/CodeEditor/CodeEditor.stories.tsx +0 -871
- package/src/components/form/CodeEditor/CodeEditor.test.stories.tsx +0 -574
- package/src/components/form/Command/Command.stories.tsx +0 -580
- package/src/components/form/Command/Command.test.stories.tsx +0 -215
- package/src/components/form/CreatableSelect/CreatableSelect.stories.tsx +0 -112
- package/src/components/form/CreatableSelect/CreatableSelect.test.stories.tsx +0 -134
- package/src/components/form/Form/Form.stories.tsx +0 -687
- package/src/components/form/Form/Form.test.stories.tsx +0 -601
- package/src/components/form/Input/Input.stories.tsx +0 -260
- package/src/components/form/Input/Input.test.stories.tsx +0 -1191
- package/src/components/form/InputOTP/InputOTP.stories.tsx +0 -774
- package/src/components/form/InputOTP/InputOTP.test.stories.tsx +0 -588
- package/src/components/form/Label/Label.stories.tsx +0 -473
- package/src/components/form/Label/Label.test.stories.tsx +0 -915
- package/src/components/form/Menubar/Menubar.stories.tsx +0 -472
- package/src/components/form/Menubar/Menubar.test.stories.tsx +0 -584
- package/src/components/form/PasswordStrength/PasswordStrength.stories.tsx +0 -562
- package/src/components/form/PasswordStrength/PasswordStrength.test.stories.tsx +0 -327
- package/src/components/form/PhoneInput/PhoneInput.stories.tsx +0 -495
- package/src/components/form/PhoneInput/PhoneInput.test.stories.tsx +0 -666
- package/src/components/form/RadioGroup/RadioGroup.stories.tsx +0 -518
- package/src/components/form/RadioGroup/RadioGroup.test.stories.tsx +0 -685
- package/src/components/form/RichTextEditor/RichTextEditor.stories.tsx +0 -261
- package/src/components/form/RichTextEditor/RichTextEditor.test.stories.tsx +0 -491
- package/src/components/form/SearchPalette/SearchPalette.stories.tsx +0 -135
- package/src/components/form/Select/Select.stories.tsx +0 -364
- package/src/components/form/Select/Select.test.stories.tsx +0 -985
- package/src/components/form/Slider/Slider.stories.tsx +0 -418
- package/src/components/form/Slider/Slider.test.stories.tsx +0 -1042
- package/src/components/form/Switch/Switch.stories.tsx +0 -697
- package/src/components/form/Switch/Switch.test.stories.tsx +0 -597
- package/src/components/form/Textarea/Textarea.stories.tsx +0 -473
- package/src/components/form/Textarea/Textarea.test.stories.tsx +0 -702
- package/src/components/form/Toggle/Toggle.stories.tsx +0 -638
- package/src/components/form/Toggle/Toggle.test.stories.tsx +0 -1159
- package/src/components/form/ToggleGroup/ToggleGroup.stories.tsx +0 -617
- package/src/components/form/ToggleGroup/ToggleGroup.test.stories.tsx +0 -915
- package/src/components/form/UploadButton/UploadButton.stories.tsx +0 -367
- package/src/components/form/UploadButton/UploadButton.test.stories.tsx +0 -573
- package/src/components/form/total-form/total-form.test.tsx +0 -214
- package/src/components/layout/Accordion/Accordion.stories.tsx +0 -694
- package/src/components/layout/Accordion/Accordion.test.stories.tsx +0 -1344
- package/src/components/layout/Card/Card.stories.tsx +0 -591
- package/src/components/layout/Card/Card.test.stories.tsx +0 -1134
- package/src/components/layout/CardGrid/__tests__/CardGrid.test.tsx +0 -92
- package/src/components/layout/Collapsible/Collapsible.stories.tsx +0 -180
- package/src/components/layout/Collapsible/Collapsible.test.stories.tsx +0 -308
- package/src/components/layout/Container/Container.stories.tsx +0 -557
- package/src/components/layout/Container/Container.test.stories.tsx +0 -745
- package/src/components/layout/ContentToolbar/ContentToolbar.stories.tsx +0 -129
- package/src/components/layout/ContentToolbar/ContentToolbar.test.stories.tsx +0 -251
- package/src/components/layout/ContentToolbar/__tests__/ColumnsMenu.test.tsx +0 -39
- package/src/components/layout/ContentToolbar/__tests__/MultiSelectDropdown.test.tsx +0 -131
- package/src/components/layout/ContentToolbar/__tests__/SavedViewsMenu.test.tsx +0 -99
- package/src/components/layout/Dashboard/Dashboard.stories.tsx +0 -104
- package/src/components/layout/Dashboard/Dashboard.test.stories.tsx +0 -190
- package/src/components/layout/Drawer/Drawer.stories.tsx +0 -658
- package/src/components/layout/Drawer/Drawer.test.stories.tsx +0 -1343
- package/src/components/layout/Resizable/Resizable.stories.tsx +0 -1039
- package/src/components/layout/Resizable/Resizable.test.stories.tsx +0 -754
- package/src/components/layout/ScrollArea/ScrollArea.stories.tsx +0 -651
- package/src/components/layout/ScrollArea/ScrollArea.test.stories.tsx +0 -619
- package/src/components/layout/Separator/Separator.stories.tsx +0 -563
- package/src/components/layout/Separator/Separator.test.stories.tsx +0 -518
- package/src/components/layout/SettingsLayout/SettingsLayout.stories.tsx +0 -192
- package/src/components/layout/SettingsLayout/SettingsLayout.test.stories.tsx +0 -175
- package/src/components/layout/Sidebar/Sidebar.stories.tsx +0 -609
- package/src/components/layout/Sidebar/Sidebar.test.stories.tsx +0 -1324
- package/src/components/layout/Skeleton/Skeleton.stories.tsx +0 -689
- package/src/components/layout/Skeleton/Skeleton.test.stories.tsx +0 -521
- package/src/components/layout/Spacer/Spacer.stories.tsx +0 -502
- package/src/components/layout/Spacer/Spacer.test.stories.tsx +0 -474
- package/src/components/layout/TableFilter/TableFilter.stories.tsx +0 -82
- package/src/components/layout/TableFilter/TableFilter.test.stories.tsx +0 -87
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.stories.tsx +0 -638
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.test.stories.tsx +0 -1008
- package/src/components/navigation/CommandPalette/CommandPalette.stories.tsx +0 -386
- package/src/components/navigation/CommandPalette/CommandPalette.test.stories.tsx +0 -435
- package/src/components/navigation/ContextMenu/ContextMenu.stories.tsx +0 -614
- package/src/components/navigation/ContextMenu/ContextMenu.test.stories.tsx +0 -845
- package/src/components/navigation/DropdownMenu/DropdownMenu.stories.tsx +0 -578
- package/src/components/navigation/DropdownMenu/DropdownMenu.test.stories.tsx +0 -660
- package/src/components/navigation/NavigationMenu/stories/NavigationMenu.stories.tsx +0 -516
- package/src/components/navigation/NavigationMenu/stories/NavigationMenu.test.stories.tsx +0 -935
- package/src/components/navigation/NavigationMenu/stories/NavigationMenuHorizontal.stories.tsx +0 -501
- package/src/components/navigation/NavigationMenu/stories/NavigationMenuVertical.stories.tsx +0 -453
- package/src/components/navigation/Pagination/Pagination.stories.tsx +0 -602
- package/src/components/navigation/Pagination/Pagination.test.stories.tsx +0 -520
- package/src/components/navigation/Tabs/Tabs.stories.tsx +0 -1004
- package/src/components/navigation/Tabs/Tabs.test.stories.tsx +0 -1225
- package/src/components/typography/Blockquote/Blockquote.stories.tsx +0 -359
- package/src/components/typography/Blockquote/Blockquote.test.stories.tsx +0 -432
- package/src/components/typography/Code/Code.stories.tsx +0 -686
- package/src/components/typography/Code/Code.test.stories.tsx +0 -703
- package/src/components/typography/Heading/Heading.stories.tsx +0 -451
- package/src/components/typography/Heading/Heading.test.stories.tsx +0 -830
- package/src/components/typography/Paragraph/Paragraph.stories.tsx +0 -280
- package/src/components/typography/Paragraph/Paragraph.test.stories.tsx +0 -231
- package/src/components/typography/Text/Text.stories.tsx +0 -359
- package/src/components/typography/Text/Text.test.stories.tsx +0 -759
- package/src/components/utility/AnimatedIcon/AnimatedIcon.stories.tsx +0 -945
- package/src/components/utility/AnimatedIcon/AnimatedIcon.test.stories.tsx +0 -603
- package/src/components/utility/AspectRatio/AspectRatio.stories.tsx +0 -414
- package/src/components/utility/AspectRatio/AspectRatio.test.stories.tsx +0 -859
- package/src/components/utility/InfiniteScroll/InfiniteScroll.stories.tsx +0 -620
- package/src/components/utility/InfiniteScroll/InfiniteScroll.test.stories.tsx +0 -361
- package/src/components/utility/InstallPrompt/InstallPrompt.stories.tsx +0 -118
- package/src/components/utility/InstallPrompt/InstallPrompt.test.stories.tsx +0 -83
- package/src/components/utility/InstallPrompt/__tests__/InstallPrompt.ios.test.tsx +0 -65
- package/src/components/utility/InstallPrompt/__tests__/usePwaInstall.test.tsx +0 -271
- package/src/components/utility/Portal/Portal.stories.tsx +0 -340
- package/src/components/utility/Portal/Portal.test.stories.tsx +0 -2086
- package/src/components/utility/Transition/Transition.stories.tsx +0 -493
- package/src/components/utility/Transition/Transition.test.stories.tsx +0 -854
- package/src/components/utility/VirtualList/VirtualList.stories.tsx +0 -1073
- package/src/components/utility/VirtualList/VirtualList.test.stories.tsx +0 -1085
- package/src/components/utility/WorkflowStep/WorkflowStep.stories.tsx +0 -431
- package/src/components/utility/WorkflowStep/WorkflowStep.test.stories.tsx +0 -364
- /package/src/{button.tsx → button/button.tsx} +0 -0
|
@@ -1,464 +0,0 @@
|
|
|
1
|
-
import { Box } from '@mui/material';
|
|
2
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
import { expect, fn,userEvent, waitFor, within } from 'storybook/test';
|
|
5
|
-
|
|
6
|
-
import { Calendar } from './Calendar';
|
|
7
|
-
import type { DateRange } from './Calendar.types';
|
|
8
|
-
|
|
9
|
-
const meta: Meta<typeof Calendar> = {
|
|
10
|
-
title: 'Form/Calendar/Tests',
|
|
11
|
-
component: Calendar,
|
|
12
|
-
parameters: {
|
|
13
|
-
layout: 'centered',
|
|
14
|
-
chromatic: { disableSnapshot: false },
|
|
15
|
-
},
|
|
16
|
-
tags: ['autodocs', 'test', 'component:Calendar'],
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export default meta;
|
|
20
|
-
type Story = StoryObj<typeof meta>;
|
|
21
|
-
|
|
22
|
-
// Pinned so the min/max assertions describe the same calendar whatever day the
|
|
23
|
-
// suite runs on.
|
|
24
|
-
const REFERENCE_DATE = new Date(2025, 5, 15); // 15 June 2025
|
|
25
|
-
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
26
|
-
const daysFromReference = (days: number): Date =>
|
|
27
|
-
new Date(REFERENCE_DATE.getTime() + days * DAY_MS);
|
|
28
|
-
|
|
29
|
-
// Test wrapper component for controlled state
|
|
30
|
-
interface TestWrapperProps {
|
|
31
|
-
selectionMode?: 'single' | 'range';
|
|
32
|
-
onChangeCallback?: (value: Date | null) => void;
|
|
33
|
-
onRangeChangeCallback?: (range: Required<DateRange>) => void;
|
|
34
|
-
[key: string]: unknown;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const TestWrapper = ({
|
|
38
|
-
selectionMode = 'single',
|
|
39
|
-
onChangeCallback = fn(),
|
|
40
|
-
onRangeChangeCallback = fn(),
|
|
41
|
-
...props
|
|
42
|
-
}: TestWrapperProps) => {
|
|
43
|
-
const [value, setValue] = useState<Date | null>(null);
|
|
44
|
-
const [range, setRange] = useState<DateRange>({ start: null, end: null });
|
|
45
|
-
|
|
46
|
-
const handleChange = (newValue: Date | null) => {
|
|
47
|
-
setValue(newValue);
|
|
48
|
-
onChangeCallback(newValue);
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const handleRangeChange = (newRange: Required<DateRange>) => {
|
|
52
|
-
setRange(newRange);
|
|
53
|
-
onRangeChangeCallback(newRange);
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
if (selectionMode === 'range') {
|
|
57
|
-
return (
|
|
58
|
-
<Calendar {...props} selectionMode="range" range={range} onRangeChange={handleRangeChange} />
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return <Calendar {...props} selectionMode="single" value={value} onChange={handleChange} />;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export const BasicInteraction: Story = {
|
|
66
|
-
render: () => <TestWrapper onChangeCallback={fn()} />,
|
|
67
|
-
play: async ({ canvasElement }) => {
|
|
68
|
-
const canvas = within(canvasElement);
|
|
69
|
-
|
|
70
|
-
// Find calendar container
|
|
71
|
-
const calendar = canvas.getByRole('application', { name: 'Calendar' });
|
|
72
|
-
expect(calendar).toBeInTheDocument();
|
|
73
|
-
|
|
74
|
-
// Find and click a date (day 15 if available)
|
|
75
|
-
const dateButtons = canvas.getAllByRole('gridcell');
|
|
76
|
-
expect(dateButtons.length).toBeGreaterThan(0);
|
|
77
|
-
|
|
78
|
-
// Find a clickable date in current month
|
|
79
|
-
const clickableDate = dateButtons.find(
|
|
80
|
-
(button) =>
|
|
81
|
-
!button.getAttribute('aria-disabled') &&
|
|
82
|
-
button.textContent &&
|
|
83
|
-
button.textContent.trim() !== '',
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
if (clickableDate) {
|
|
87
|
-
await userEvent.click(clickableDate);
|
|
88
|
-
|
|
89
|
-
// Verify date is selected
|
|
90
|
-
await waitFor(() => {
|
|
91
|
-
expect(clickableDate).toHaveAttribute('aria-selected', 'true');
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
export const RangeInteractionTest: Story = {
|
|
98
|
-
render: () => <TestWrapper selectionMode="range" onRangeChangeCallback={fn()} />,
|
|
99
|
-
play: async ({ canvasElement }) => {
|
|
100
|
-
const canvas = within(canvasElement);
|
|
101
|
-
|
|
102
|
-
// Find calendar container
|
|
103
|
-
const calendar = canvas.getByRole('application', { name: 'Calendar' });
|
|
104
|
-
expect(calendar).toBeInTheDocument();
|
|
105
|
-
|
|
106
|
-
const dateButtons = canvas.getAllByRole('gridcell');
|
|
107
|
-
const clickableDates = dateButtons.filter(
|
|
108
|
-
(button) =>
|
|
109
|
-
!button.getAttribute('aria-disabled') &&
|
|
110
|
-
button.textContent &&
|
|
111
|
-
button.textContent.trim() !== '',
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
if (clickableDates.length >= 2) {
|
|
115
|
-
// Click first date (start)
|
|
116
|
-
await userEvent.click(clickableDates[5]);
|
|
117
|
-
|
|
118
|
-
// Hover over second date to see preview
|
|
119
|
-
await userEvent.hover(clickableDates[10]);
|
|
120
|
-
|
|
121
|
-
// Click second date (end)
|
|
122
|
-
await userEvent.click(clickableDates[10]);
|
|
123
|
-
|
|
124
|
-
// Verify range selection
|
|
125
|
-
await waitFor(() => {
|
|
126
|
-
expect(clickableDates[5]).toHaveAttribute('aria-selected', 'true');
|
|
127
|
-
expect(clickableDates[10]).toHaveAttribute('aria-selected', 'true');
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
export const KeyboardNavigation: Story = {
|
|
134
|
-
render: () => <TestWrapper autoFocus />,
|
|
135
|
-
play: async ({ canvasElement }) => {
|
|
136
|
-
const canvas = within(canvasElement);
|
|
137
|
-
|
|
138
|
-
// Find calendar container
|
|
139
|
-
const calendar = canvas.getByRole('application', { name: 'Calendar' });
|
|
140
|
-
expect(calendar).toBeInTheDocument();
|
|
141
|
-
|
|
142
|
-
// Focus the calendar the way a user would, and confirm it took — the keyboard
|
|
143
|
-
// assertions below are meaningless if the container never held focus.
|
|
144
|
-
await userEvent.click(calendar);
|
|
145
|
-
await waitFor(() => expect(calendar).toHaveFocus());
|
|
146
|
-
|
|
147
|
-
// Test arrow key navigation
|
|
148
|
-
await userEvent.keyboard('{ArrowRight}');
|
|
149
|
-
await userEvent.keyboard('{ArrowDown}');
|
|
150
|
-
await userEvent.keyboard('{ArrowLeft}');
|
|
151
|
-
await userEvent.keyboard('{ArrowUp}');
|
|
152
|
-
|
|
153
|
-
// Test home/end navigation
|
|
154
|
-
await userEvent.keyboard('{Home}');
|
|
155
|
-
await userEvent.keyboard('{End}');
|
|
156
|
-
|
|
157
|
-
// Test page navigation
|
|
158
|
-
await userEvent.keyboard('{PageDown}');
|
|
159
|
-
await userEvent.keyboard('{PageUp}');
|
|
160
|
-
|
|
161
|
-
// Test selection with Enter
|
|
162
|
-
await userEvent.keyboard('{Enter}');
|
|
163
|
-
|
|
164
|
-
// Verify focused element exists
|
|
165
|
-
const focusedCell = document.activeElement;
|
|
166
|
-
expect(focusedCell).toBeTruthy();
|
|
167
|
-
},
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
export const ScreenReaderTest: Story = {
|
|
171
|
-
render: () => <TestWrapper />,
|
|
172
|
-
play: async ({ canvasElement }) => {
|
|
173
|
-
const canvas = within(canvasElement);
|
|
174
|
-
|
|
175
|
-
// Verify ARIA attributes
|
|
176
|
-
const calendar = canvas.getByRole('application', { name: 'Calendar' });
|
|
177
|
-
expect(calendar).toBeInTheDocument();
|
|
178
|
-
|
|
179
|
-
// Check grid role
|
|
180
|
-
const grids = canvas.getAllByRole('grid');
|
|
181
|
-
expect(grids.length).toBeGreaterThan(0);
|
|
182
|
-
|
|
183
|
-
// Check column headers (weekdays)
|
|
184
|
-
const columnHeaders = canvas.getAllByRole('columnheader');
|
|
185
|
-
expect(columnHeaders).toHaveLength(7); // 7 days of week
|
|
186
|
-
|
|
187
|
-
// Check grid cells
|
|
188
|
-
const gridCells = canvas.getAllByRole('gridcell');
|
|
189
|
-
expect(gridCells.length).toBeGreaterThan(0);
|
|
190
|
-
|
|
191
|
-
// Verify each cell has proper attributes
|
|
192
|
-
gridCells.forEach((cell) => {
|
|
193
|
-
expect(cell).toHaveAttribute('aria-selected');
|
|
194
|
-
if (cell.textContent === 'disabled') {
|
|
195
|
-
expect(cell).toHaveAttribute('aria-disabled', 'true');
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
},
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
export const FocusManagement: Story = {
|
|
202
|
-
render: () => <TestWrapper autoFocus />,
|
|
203
|
-
play: async ({ canvasElement }) => {
|
|
204
|
-
const canvas = within(canvasElement);
|
|
205
|
-
|
|
206
|
-
// Find calendar container
|
|
207
|
-
const calendar = canvas.getByRole('application', { name: 'Calendar' });
|
|
208
|
-
|
|
209
|
-
// Focus should be managed properly
|
|
210
|
-
await userEvent.click(calendar);
|
|
211
|
-
await waitFor(() => expect(calendar).toHaveFocus());
|
|
212
|
-
|
|
213
|
-
// Navigate and verify focus moves correctly
|
|
214
|
-
await userEvent.keyboard('{ArrowRight}');
|
|
215
|
-
|
|
216
|
-
// Check that only one cell has tabIndex 0
|
|
217
|
-
const dateButtons = canvas.getAllByRole('gridcell');
|
|
218
|
-
const focusableCells = dateButtons.filter((cell) => cell.getAttribute('tabindex') === '0');
|
|
219
|
-
expect(focusableCells).toHaveLength(1);
|
|
220
|
-
|
|
221
|
-
// Test Tab navigation out of calendar
|
|
222
|
-
await userEvent.keyboard('{Tab}');
|
|
223
|
-
|
|
224
|
-
// Focus should move to next element (navigation buttons)
|
|
225
|
-
const focusedElement = document.activeElement;
|
|
226
|
-
expect(focusedElement).toBeTruthy();
|
|
227
|
-
},
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
export const ResponsiveDesign: Story = {
|
|
231
|
-
parameters: {
|
|
232
|
-
viewport: { defaultViewport: 'mobile1' },
|
|
233
|
-
},
|
|
234
|
-
render: () => (
|
|
235
|
-
<Box sx={{ width: '100%', maxWidth: 320 }}>
|
|
236
|
-
<TestWrapper />
|
|
237
|
-
</Box>
|
|
238
|
-
),
|
|
239
|
-
play: async ({ canvasElement }) => {
|
|
240
|
-
const canvas = within(canvasElement);
|
|
241
|
-
|
|
242
|
-
// Verify calendar renders in mobile viewport
|
|
243
|
-
const calendar = canvas.getByRole('application', { name: 'Calendar' });
|
|
244
|
-
expect(calendar).toBeInTheDocument();
|
|
245
|
-
|
|
246
|
-
// Check that calendar adapts to container width
|
|
247
|
-
const calendarRect = calendar.getBoundingClientRect();
|
|
248
|
-
expect(calendarRect.width).toBeLessThanOrEqual(320);
|
|
249
|
-
|
|
250
|
-
// Verify interactions still work on mobile
|
|
251
|
-
const dateButtons = canvas.getAllByRole('gridcell');
|
|
252
|
-
const clickableDate = dateButtons.find(
|
|
253
|
-
(button) =>
|
|
254
|
-
!button.getAttribute('aria-disabled') &&
|
|
255
|
-
button.textContent &&
|
|
256
|
-
button.textContent.trim() !== '',
|
|
257
|
-
);
|
|
258
|
-
|
|
259
|
-
if (clickableDate) {
|
|
260
|
-
await userEvent.click(clickableDate);
|
|
261
|
-
|
|
262
|
-
await waitFor(() => {
|
|
263
|
-
expect(clickableDate).toHaveAttribute('aria-selected', 'true');
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
},
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
export const ThemeVariations: Story = {
|
|
270
|
-
render: () => <TestWrapper />,
|
|
271
|
-
play: async ({ canvasElement }) => {
|
|
272
|
-
const canvas = within(canvasElement);
|
|
273
|
-
|
|
274
|
-
// Find calendar and verify theme application
|
|
275
|
-
const calendar = canvas.getByRole('application', { name: 'Calendar' });
|
|
276
|
-
expect(calendar).toBeInTheDocument();
|
|
277
|
-
|
|
278
|
-
// Check that theme styles are applied
|
|
279
|
-
const computedStyle = window.getComputedStyle(calendar);
|
|
280
|
-
expect(computedStyle.padding).toBeTruthy();
|
|
281
|
-
|
|
282
|
-
// Find date buttons and check their styling
|
|
283
|
-
const dateButtons = canvas.getAllByRole('gridcell');
|
|
284
|
-
dateButtons.forEach((button) => {
|
|
285
|
-
const buttonStyle = window.getComputedStyle(button);
|
|
286
|
-
expect(buttonStyle.display).toBe('flex');
|
|
287
|
-
});
|
|
288
|
-
},
|
|
289
|
-
};
|
|
290
|
-
|
|
291
|
-
export const VisualStates: Story = {
|
|
292
|
-
render: () => (
|
|
293
|
-
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
|
|
294
|
-
<TestWrapper
|
|
295
|
-
value={REFERENCE_DATE}
|
|
296
|
-
minDate={daysFromReference(-7)}
|
|
297
|
-
maxDate={daysFromReference(7)}
|
|
298
|
-
/>
|
|
299
|
-
</Box>
|
|
300
|
-
),
|
|
301
|
-
play: async ({ canvasElement }) => {
|
|
302
|
-
const canvas = within(canvasElement);
|
|
303
|
-
|
|
304
|
-
// Verify different visual states
|
|
305
|
-
const calendar = canvas.getByRole('application', { name: 'Calendar' });
|
|
306
|
-
expect(calendar).toBeInTheDocument();
|
|
307
|
-
|
|
308
|
-
const dateButtons = canvas.getAllByRole('gridcell');
|
|
309
|
-
|
|
310
|
-
// The selected day carries its own marker. (Today's styling is not asserted
|
|
311
|
-
// here: the pinned reference date is not today, so no cell is aria-current.)
|
|
312
|
-
const selectedMarkers = canvas.getAllByTestId('calendar-selected-date');
|
|
313
|
-
expect(selectedMarkers.length).toBeGreaterThan(0);
|
|
314
|
-
|
|
315
|
-
// Everything more than a week either side of the reference date is out of
|
|
316
|
-
// bounds, so June has disabled cells at both ends.
|
|
317
|
-
const disabledButtons = dateButtons.filter(
|
|
318
|
-
(button) => button.getAttribute('aria-disabled') === 'true',
|
|
319
|
-
);
|
|
320
|
-
expect(disabledButtons.length).toBeGreaterThan(0);
|
|
321
|
-
},
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
// Multi-month rendering and navigation. This previously bracketed the queries
|
|
325
|
-
// below with Date.now() and asserted wall-clock budgets, which measured the
|
|
326
|
-
// machine rather than the component and could not meaningfully fail.
|
|
327
|
-
export const PerformanceTest: Story = {
|
|
328
|
-
render: () => <TestWrapper numberOfMonths={3} />,
|
|
329
|
-
play: async ({ canvasElement }) => {
|
|
330
|
-
const canvas = within(canvasElement);
|
|
331
|
-
|
|
332
|
-
const calendar = canvas.getByRole('application', { name: 'Calendar' });
|
|
333
|
-
expect(calendar).toBeInTheDocument();
|
|
334
|
-
|
|
335
|
-
// Check all months are rendered
|
|
336
|
-
const grids = canvas.getAllByRole('grid');
|
|
337
|
-
expect(grids).toHaveLength(3);
|
|
338
|
-
|
|
339
|
-
// Advancing moves every visible month along. The old lookup searched for an
|
|
340
|
-
// aria-label the buttons never had, so this branch never ran.
|
|
341
|
-
const headingBefore = canvas.getAllByTestId('calendar-header')[0]?.textContent;
|
|
342
|
-
await userEvent.click(canvas.getByTestId('calendar-next-month'));
|
|
343
|
-
|
|
344
|
-
await waitFor(() => {
|
|
345
|
-
const headingAfter = canvas.getAllByTestId('calendar-header')[0]?.textContent;
|
|
346
|
-
expect(headingAfter).not.toBe(headingBefore);
|
|
347
|
-
});
|
|
348
|
-
},
|
|
349
|
-
};
|
|
350
|
-
|
|
351
|
-
export const EdgeCases: Story = {
|
|
352
|
-
render: () => (
|
|
353
|
-
<TestWrapper
|
|
354
|
-
minRangeLength={3}
|
|
355
|
-
maxRangeLength={10}
|
|
356
|
-
allowSameDayRange={false}
|
|
357
|
-
selectionMode="range"
|
|
358
|
-
/>
|
|
359
|
-
),
|
|
360
|
-
play: async ({ canvasElement }) => {
|
|
361
|
-
const canvas = within(canvasElement);
|
|
362
|
-
|
|
363
|
-
const calendar = canvas.getByRole('application', { name: 'Calendar' });
|
|
364
|
-
expect(calendar).toBeInTheDocument();
|
|
365
|
-
|
|
366
|
-
const dateButtons = canvas.getAllByRole('gridcell');
|
|
367
|
-
const clickableDates = dateButtons.filter(
|
|
368
|
-
(button) =>
|
|
369
|
-
!button.getAttribute('aria-disabled') &&
|
|
370
|
-
button.textContent &&
|
|
371
|
-
button.textContent.trim() !== '',
|
|
372
|
-
);
|
|
373
|
-
|
|
374
|
-
if (clickableDates.length >= 3) {
|
|
375
|
-
// Try to select same day range (should be prevented)
|
|
376
|
-
await userEvent.click(clickableDates[5]);
|
|
377
|
-
await userEvent.click(clickableDates[5]);
|
|
378
|
-
|
|
379
|
-
// Verify same day range is not allowed
|
|
380
|
-
// (implementation should prevent this selection)
|
|
381
|
-
|
|
382
|
-
// Test minimum range length constraint
|
|
383
|
-
await userEvent.click(clickableDates[5]);
|
|
384
|
-
await userEvent.click(clickableDates[6]); // Only 1 day gap, should be invalid
|
|
385
|
-
|
|
386
|
-
// Test valid range
|
|
387
|
-
await userEvent.click(clickableDates[5]);
|
|
388
|
-
await userEvent.click(clickableDates[8]); // 3+ days, should be valid
|
|
389
|
-
|
|
390
|
-
await waitFor(() => {
|
|
391
|
-
expect(clickableDates[5]).toHaveAttribute('aria-selected', 'true');
|
|
392
|
-
expect(clickableDates[8]).toHaveAttribute('aria-selected', 'true');
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
},
|
|
396
|
-
};
|
|
397
|
-
|
|
398
|
-
const IntegrationTestComponent = () => {
|
|
399
|
-
const [singleDate, setSingleDate] = useState<Date | null>(null);
|
|
400
|
-
const [rangeDate, setRangeDate] = useState<DateRange>({ start: null, end: null });
|
|
401
|
-
|
|
402
|
-
return (
|
|
403
|
-
<Box sx={{ display: 'flex', gap: 4 }}>
|
|
404
|
-
<Calendar
|
|
405
|
-
selectionMode="single"
|
|
406
|
-
value={singleDate}
|
|
407
|
-
onChange={setSingleDate}
|
|
408
|
-
data-testid="single-calendar"
|
|
409
|
-
/>
|
|
410
|
-
<Calendar
|
|
411
|
-
selectionMode="range"
|
|
412
|
-
range={rangeDate}
|
|
413
|
-
onRangeChange={setRangeDate}
|
|
414
|
-
data-testid="range-calendar"
|
|
415
|
-
/>
|
|
416
|
-
</Box>
|
|
417
|
-
);
|
|
418
|
-
};
|
|
419
|
-
|
|
420
|
-
export const IntegrationTest: Story = {
|
|
421
|
-
render: () => <IntegrationTestComponent />,
|
|
422
|
-
play: async ({ canvasElement }) => {
|
|
423
|
-
const canvas = within(canvasElement);
|
|
424
|
-
|
|
425
|
-
// Test multiple calendars working independently
|
|
426
|
-
const calendars = canvas.getAllByRole('application', { name: 'Calendar' });
|
|
427
|
-
expect(calendars).toHaveLength(2);
|
|
428
|
-
|
|
429
|
-
// Test interaction with first calendar
|
|
430
|
-
const firstCalendarButtons = within(calendars[0]).getAllByRole('gridcell');
|
|
431
|
-
const firstClickable = firstCalendarButtons.find(
|
|
432
|
-
(button) =>
|
|
433
|
-
!button.getAttribute('aria-disabled') &&
|
|
434
|
-
button.textContent &&
|
|
435
|
-
button.textContent.trim() !== '',
|
|
436
|
-
);
|
|
437
|
-
|
|
438
|
-
if (firstClickable) {
|
|
439
|
-
await userEvent.click(firstClickable);
|
|
440
|
-
await waitFor(() => {
|
|
441
|
-
expect(firstClickable).toHaveAttribute('aria-selected', 'true');
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// Test interaction with second calendar
|
|
446
|
-
const secondCalendarButtons = within(calendars[1]).getAllByRole('gridcell');
|
|
447
|
-
const secondClickables = secondCalendarButtons.filter(
|
|
448
|
-
(button) =>
|
|
449
|
-
!button.getAttribute('aria-disabled') &&
|
|
450
|
-
button.textContent &&
|
|
451
|
-
button.textContent.trim() !== '',
|
|
452
|
-
);
|
|
453
|
-
|
|
454
|
-
if (secondClickables.length >= 2) {
|
|
455
|
-
await userEvent.click(secondClickables[5]);
|
|
456
|
-
await userEvent.click(secondClickables[10]);
|
|
457
|
-
|
|
458
|
-
await waitFor(() => {
|
|
459
|
-
expect(secondClickables[5]).toHaveAttribute('aria-selected', 'true');
|
|
460
|
-
expect(secondClickables[10]).toHaveAttribute('aria-selected', 'true');
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
},
|
|
464
|
-
};
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { Paper, Stack, Typography } from '@mui/material';
|
|
2
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
|
-
import React, { useState } from 'react';
|
|
4
|
-
|
|
5
|
-
import { CepField } from './CepField';
|
|
6
|
-
import type { CepAddress } from './CepField.types';
|
|
7
|
-
|
|
8
|
-
const meta: Meta<typeof CepField> = {
|
|
9
|
-
title: 'Form/CepField',
|
|
10
|
-
component: CepField,
|
|
11
|
-
parameters: {
|
|
12
|
-
layout: 'padded',
|
|
13
|
-
docs: {
|
|
14
|
-
description: {
|
|
15
|
-
component:
|
|
16
|
-
'A CEP input that fills the rest of the address in. Masks to `#####-###`, waits for a complete CEP, then calls the injected `onLookup` and hands the result to `onResolved`. The lookup is injected, so the component works with any backend — or none.',
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
tags: ['autodocs', 'component:CepField'],
|
|
21
|
-
argTypes: {
|
|
22
|
-
value: { control: 'text', description: 'Current value (masked or bare)' },
|
|
23
|
-
label: { control: 'text', description: 'Visible label' },
|
|
24
|
-
placeholder: { control: 'text', description: 'Placeholder text' },
|
|
25
|
-
error: { control: 'text', description: 'Validation error from the caller' },
|
|
26
|
-
disabled: { control: 'boolean', description: 'Disable input and lookups' },
|
|
27
|
-
debounceMs: { control: 'number', description: 'Delay before looking up' },
|
|
28
|
-
name: { control: 'text', description: 'Field name / input id' },
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export default meta;
|
|
33
|
-
type Story = StoryObj<typeof meta>;
|
|
34
|
-
|
|
35
|
-
/** Stand-in for a real provider — resolves one CEP, rejects everything else. */
|
|
36
|
-
const FIXTURES: Record<string, CepAddress> = {
|
|
37
|
-
'01310100': {
|
|
38
|
-
cep: '01310100',
|
|
39
|
-
street: 'Avenida Paulista',
|
|
40
|
-
neighborhood: 'Bela Vista',
|
|
41
|
-
city: 'São Paulo',
|
|
42
|
-
state: 'SP',
|
|
43
|
-
},
|
|
44
|
-
'20040020': {
|
|
45
|
-
cep: '20040020',
|
|
46
|
-
street: 'Avenida Rio Branco',
|
|
47
|
-
neighborhood: 'Centro',
|
|
48
|
-
city: 'Rio de Janeiro',
|
|
49
|
-
state: 'RJ',
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const fakeLookup = async (cep: string): Promise<CepAddress | null> => {
|
|
54
|
-
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
55
|
-
return FIXTURES[cep] ?? null;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
/** The whole point: type a CEP, watch the address fields fill themselves. */
|
|
59
|
-
function Demo({
|
|
60
|
-
lookup = fakeLookup,
|
|
61
|
-
...props
|
|
62
|
-
}: {
|
|
63
|
-
lookup?: (cep: string) => Promise<CepAddress | null>;
|
|
64
|
-
label?: string;
|
|
65
|
-
disabled?: boolean;
|
|
66
|
-
}): React.ReactElement {
|
|
67
|
-
const [cep, setCep] = useState('');
|
|
68
|
-
const [address, setAddress] = useState<CepAddress | null>(null);
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<Stack spacing={2} sx={{ maxWidth: 420 }}>
|
|
72
|
-
<CepField
|
|
73
|
-
{...props}
|
|
74
|
-
value={cep}
|
|
75
|
-
onChange={setCep}
|
|
76
|
-
onLookup={lookup}
|
|
77
|
-
onResolved={setAddress}
|
|
78
|
-
/>
|
|
79
|
-
<Paper variant="outlined" sx={{ p: 2 }}>
|
|
80
|
-
<Typography variant="caption" color="text.secondary">
|
|
81
|
-
Endereço resolvido
|
|
82
|
-
</Typography>
|
|
83
|
-
<Typography variant="body2">{address?.street ?? '—'}</Typography>
|
|
84
|
-
<Typography variant="body2">{address?.neighborhood ?? '—'}</Typography>
|
|
85
|
-
<Typography variant="body2">
|
|
86
|
-
{address ? `${address.city ?? '—'} / ${address.state ?? '—'}` : '—'}
|
|
87
|
-
</Typography>
|
|
88
|
-
</Paper>
|
|
89
|
-
<Typography variant="caption" color="text.secondary">
|
|
90
|
-
Try 01310-100 or 20040-020. Anything else resolves to “não encontrado”.
|
|
91
|
-
</Typography>
|
|
92
|
-
</Stack>
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export const Default: Story = {
|
|
97
|
-
render: () => <Demo />,
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
export const CustomLabel: Story = {
|
|
101
|
-
render: () => <Demo label="CEP do fornecedor" />,
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
export const Disabled: Story = {
|
|
105
|
-
render: () => <Demo disabled />,
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
/** Every provider is down. The field degrades to a plain masked input. */
|
|
109
|
-
export const LookupUnavailable: Story = {
|
|
110
|
-
render: () => <Demo lookup={async () => null} />,
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
/** No `onLookup` at all — just the mask and validation. */
|
|
114
|
-
export const MaskOnly: Story = {
|
|
115
|
-
render: function MaskOnlyStory() {
|
|
116
|
-
const [cep, setCep] = useState('');
|
|
117
|
-
return (
|
|
118
|
-
<Stack sx={{ maxWidth: 420 }}>
|
|
119
|
-
<CepField value={cep} onChange={setCep} />
|
|
120
|
-
</Stack>
|
|
121
|
-
);
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
export const WithError: Story = {
|
|
126
|
-
render: function WithErrorStory() {
|
|
127
|
-
const [cep, setCep] = useState('123');
|
|
128
|
-
return (
|
|
129
|
-
<Stack sx={{ maxWidth: 420 }}>
|
|
130
|
-
<CepField
|
|
131
|
-
value={cep}
|
|
132
|
-
onChange={setCep}
|
|
133
|
-
error="CEP inválido — use o formato 00000-000."
|
|
134
|
-
/>
|
|
135
|
-
</Stack>
|
|
136
|
-
);
|
|
137
|
-
},
|
|
138
|
-
};
|