@recursica/mui-adapter 0.6.0 → 0.7.0
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/ARCHITECTURE.md +15 -0
- package/CHANGELOG.md +6 -0
- package/SETUP.md +77 -0
- package/USAGE.md +55 -0
- package/dist/mui-adapter.cjs +26 -26
- package/dist/mui-adapter.cjs.map +1 -1
- package/dist/mui-adapter.css +1 -1
- package/dist/mui-adapter.js +3721 -3511
- package/dist/mui-adapter.js.map +1 -1
- package/dist/src/components/Accordion/Accordion.d.ts +9 -29
- package/dist/src/components/AssistiveElement/AssistiveElement.d.ts +2 -5
- package/dist/src/components/Autocomplete/Autocomplete.d.ts +4 -8
- package/dist/src/components/Avatar/Avatar.d.ts +1 -6
- package/dist/src/components/Badge/Badge.d.ts +1 -4
- package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +2 -3
- package/dist/src/components/Button/Button.d.ts +2 -17
- package/dist/src/components/Card/Card.d.ts +2 -4
- package/dist/src/components/Checkbox/Checkbox.d.ts +4 -6
- package/dist/src/components/Checkbox/CheckboxGroup.d.ts +8 -6
- package/dist/src/components/Chip/Chip.d.ts +2 -11
- package/dist/src/components/Container/Container.d.ts +1 -5
- package/dist/src/components/DatePicker/DatePicker.d.ts +2 -1
- package/dist/src/components/Dropdown/Dropdown.d.ts +4 -14
- package/dist/src/components/Flex/Flex.d.ts +2 -22
- package/dist/src/components/FormControlLayout/FormControlLayout.d.ts +2 -7
- package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +3 -18
- package/dist/src/components/Group/Group.d.ts +2 -7
- package/dist/src/components/HoverCard/HoverCard.d.ts +13 -39
- package/dist/src/components/Label/Label.d.ts +2 -9
- package/dist/src/components/Link/Link.d.ts +2 -6
- package/dist/src/components/Loader/Loader.d.ts +2 -7
- package/dist/src/components/Menu/Menu.d.ts +24 -98
- package/dist/src/components/Modal/Modal.d.ts +32 -31
- package/dist/src/components/NumberInput/NumberInput.d.ts +3 -5
- package/dist/src/components/Pagination/Pagination.d.ts +8 -41
- package/dist/src/components/Panel/Panel.d.ts +5 -18
- package/dist/src/components/Radio/Radio.d.ts +4 -4
- package/dist/src/components/Radio/RadioGroup.d.ts +3 -7
- package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +2 -5
- package/dist/src/components/SegmentedControl/SegmentedControl.d.ts +5 -15
- package/dist/src/components/Slider/Slider.d.ts +4 -14
- package/dist/src/components/Stack/Stack.d.ts +2 -5
- package/dist/src/components/Stepper/Stepper.d.ts +36 -16
- package/dist/src/components/Switch/Switch.d.ts +4 -4
- package/dist/src/components/Switch/SwitchGroup.d.ts +4 -4
- package/dist/src/components/Table/Table.d.ts +2 -1
- package/dist/src/components/Tabs/Tabs.d.ts +11 -26
- package/dist/src/components/Text/Text.d.ts +2 -16
- package/dist/src/components/TextArea/TextArea.d.ts +3 -9
- package/dist/src/components/TextField/TextField.d.ts +3 -7
- package/dist/src/components/TimePicker/TimePicker.d.ts +2 -1
- package/dist/src/components/Timeline/Timeline.d.ts +2 -1
- package/dist/src/components/Timeline/TimelineItem.d.ts +2 -13
- package/dist/src/components/Title/Title.d.ts +2 -15
- package/dist/src/components/Toast/Toast.d.ts +11 -16
- package/dist/src/components/Tooltip/Tooltip.d.ts +7 -21
- package/dist/src/components/TransferList/TransferList.d.ts +2 -1
- package/dist/src/components/Typography/Typography.d.ts +1 -1
- package/dist/src/utils/RequireAccessibleLabel.d.ts +1 -18
- package/dist/src/utils/filterStylingProps.d.ts +1 -11
- package/llms.txt +16 -0
- package/package.json +6 -2
- package/src/components/Accordion/Accordion.module.css +1 -2
- package/src/components/Accordion/Accordion.stories.tsx +0 -18
- package/src/components/Accordion/Accordion.tsx +19 -23
- package/src/components/AssistiveElement/AssistiveElement.module.css +32 -29
- package/src/components/AssistiveElement/AssistiveElement.stories.tsx +10 -27
- package/src/components/AssistiveElement/AssistiveElement.tsx +11 -15
- package/src/components/Autocomplete/Autocomplete.module.css +17 -18
- package/src/components/Autocomplete/Autocomplete.stories.tsx +7 -16
- package/src/components/Autocomplete/Autocomplete.tsx +27 -45
- package/src/components/Avatar/Avatar.tsx +2 -13
- package/src/components/Badge/Badge.tsx +2 -5
- package/src/components/Breadcrumb/Breadcrumb.tsx +1 -4
- package/src/components/Button/Button.module.css +19 -61
- package/src/components/Button/Button.stories.tsx +24 -23
- package/src/components/Button/Button.tsx +7 -18
- package/src/components/Card/Card.module.css +36 -0
- package/src/components/Card/Card.tsx +6 -4
- package/src/components/Checkbox/Checkbox.module.css +27 -10
- package/src/components/Checkbox/Checkbox.tsx +124 -24
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +43 -23
- package/src/components/Chip/Chip.module.css +52 -34
- package/src/components/Chip/Chip.tsx +45 -47
- package/src/components/Container/Container.stories.tsx +103 -20
- package/src/components/Container/Container.tsx +1 -13
- package/src/components/DatePicker/DatePicker.stories.tsx +125 -19
- package/src/components/DatePicker/DatePicker.tsx +3 -1
- package/src/components/Dropdown/Dropdown.tsx +7 -9
- package/src/components/FileInput/FileInput.stories.tsx +2 -19
- package/src/components/FileUpload/FileUpload.stories.tsx +2 -19
- package/src/components/Flex/Flex.stories.tsx +113 -20
- package/src/components/Flex/Flex.tsx +16 -26
- package/src/components/FormControlLayout/FormControlLayout.stories.tsx +0 -8
- package/src/components/FormControlLayout/FormControlLayout.tsx +18 -7
- package/src/components/FormControlWrapper/FormControlWrapper.module.css +1 -10
- package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +12 -21
- package/src/components/FormControlWrapper/FormControlWrapper.tsx +11 -30
- package/src/components/Group/Group.stories.tsx +6 -30
- package/src/components/Group/Group.tsx +14 -9
- package/src/components/HoverCard/HoverCard.tsx +72 -75
- package/src/components/Label/Label.module.css +4 -0
- package/src/components/Label/Label.stories.tsx +18 -12
- package/src/components/Label/Label.tsx +3 -9
- package/src/components/Link/Link.module.css +4 -3
- package/src/components/Link/Link.stories.tsx +2 -8
- package/src/components/Link/Link.tsx +1 -5
- package/src/components/Loader/Loader.module.css +1 -2
- package/src/components/Loader/Loader.tsx +1 -7
- package/src/components/Menu/IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Menu/Menu.stories.tsx +106 -188
- package/src/components/Menu/Menu.tsx +34 -280
- package/src/components/Modal/Modal.tsx +158 -160
- package/src/components/NumberInput/NumberInput.tsx +6 -18
- package/src/components/Pagination/IMPLEMENTATION_NOTES.md +3 -0
- package/src/components/Pagination/Pagination.module.css +12 -24
- package/src/components/Pagination/Pagination.stories.tsx +0 -8
- package/src/components/Pagination/Pagination.tsx +20 -140
- package/src/components/Panel/Panel.tsx +7 -30
- package/src/components/Radio/Radio.module.css +25 -10
- package/src/components/Radio/Radio.tsx +51 -19
- package/src/components/Radio/RadioGroup.stories.tsx +117 -0
- package/src/components/Radio/RadioGroup.tsx +26 -12
- package/src/components/ReadOnlyField/ReadOnlyField.module.css +6 -6
- package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +5 -36
- package/src/components/ReadOnlyField/ReadOnlyField.tsx +9 -13
- package/src/components/SegmentedControl/SegmentedControl.module.css +23 -47
- package/src/components/SegmentedControl/SegmentedControl.tsx +44 -14
- package/src/components/Slider/Slider.module.css +1 -4
- package/src/components/Slider/Slider.stories.tsx +3 -3
- package/src/components/Slider/Slider.tsx +26 -25
- package/src/components/Stack/Stack.stories.tsx +4 -25
- package/src/components/Stack/Stack.tsx +1 -5
- package/src/components/Stepper/IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Stepper/Stepper.stories.tsx +56 -43
- package/src/components/Stepper/Stepper.tsx +89 -87
- package/src/components/Switch/Switch.module.css +21 -0
- package/src/components/Switch/Switch.tsx +63 -16
- package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
- package/src/components/Switch/SwitchGroup.tsx +27 -18
- package/src/components/Table/Table.stories.tsx +1 -19
- package/src/components/Table/Table.tsx +3 -1
- package/src/components/Tabs/IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Tabs/Tabs.stories.tsx +41 -24
- package/src/components/Tabs/Tabs.tsx +49 -66
- package/src/components/Text/Text.stories.tsx +5 -17
- package/src/components/Text/Text.tsx +1 -15
- package/src/components/TextArea/TextArea.tsx +7 -17
- package/src/components/TextField/TextField.stories.tsx +1 -27
- package/src/components/TextField/TextField.tsx +4 -6
- package/src/components/TimePicker/TimePicker.stories.tsx +2 -19
- package/src/components/TimePicker/TimePicker.tsx +3 -1
- package/src/components/Timeline/Timeline.tsx +4 -1
- package/src/components/Timeline/TimelineItem.tsx +1 -12
- package/src/components/Title/Title.stories.tsx +0 -18
- package/src/components/Title/Title.tsx +1 -7
- package/src/components/Toast/Toast.stories.tsx +1 -1
- package/src/components/Toast/Toast.tsx +62 -28
- package/src/components/Tooltip/Tooltip.tsx +11 -37
- package/src/components/TransferList/TransferList.stories.tsx +1 -19
- package/src/components/TransferList/TransferList.tsx +3 -1
- package/src/utils/RequireAccessibleLabel.ts +1 -12
- package/src/utils/filterStylingProps.ts +7 -20
|
@@ -13,6 +13,8 @@ import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/For
|
|
|
13
13
|
import { WithReadOnlyWrapper } from "../ReadOnlyField/WithReadOnlyWrapper";
|
|
14
14
|
import styles from "./Dropdown.module.css";
|
|
15
15
|
|
|
16
|
+
import { type RecursicaDropdownProps as BaseRecursicaDropdownProps } from "@recursica/adapter-common";
|
|
17
|
+
|
|
16
18
|
export interface RecursicaDropdownProps
|
|
17
19
|
extends Omit<
|
|
18
20
|
MuiSelectProps,
|
|
@@ -29,14 +31,8 @@ export interface RecursicaDropdownProps
|
|
|
29
31
|
| "labelWithEditIcon"
|
|
30
32
|
| "onLabelEditClick"
|
|
31
33
|
>,
|
|
32
|
-
ReadOnlyControlProps
|
|
33
|
-
|
|
34
|
-
containerWidth?: React.CSSProperties["width"];
|
|
35
|
-
data?: (string | { value: string; label: ReactNode; disabled?: boolean })[];
|
|
36
|
-
searchable?: boolean;
|
|
37
|
-
clearable?: boolean;
|
|
38
|
-
withAsterisk?: boolean;
|
|
39
|
-
}
|
|
34
|
+
ReadOnlyControlProps,
|
|
35
|
+
BaseRecursicaDropdownProps {}
|
|
40
36
|
|
|
41
37
|
export type DropdownProps = RecursicaOverStyled<RecursicaDropdownProps>;
|
|
42
38
|
|
|
@@ -59,6 +55,7 @@ export const Dropdown = forwardRef<HTMLInputElement, DropdownProps>(
|
|
|
59
55
|
assistiveWithIcon,
|
|
60
56
|
error,
|
|
61
57
|
required,
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
62
59
|
withAsterisk,
|
|
63
60
|
id,
|
|
64
61
|
className,
|
|
@@ -70,7 +67,9 @@ export const Dropdown = forwardRef<HTMLInputElement, DropdownProps>(
|
|
|
70
67
|
value,
|
|
71
68
|
defaultValue,
|
|
72
69
|
data,
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
73
71
|
searchable, // Not natively supported by basic MUI Select, stubbed
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
74
73
|
clearable, // Not natively supported by basic MUI Select, stubbed
|
|
75
74
|
...rest
|
|
76
75
|
} = props;
|
|
@@ -135,7 +134,6 @@ export const Dropdown = forwardRef<HTMLInputElement, DropdownProps>(
|
|
|
135
134
|
assistiveWithIcon={assistiveWithIcon}
|
|
136
135
|
error={!!error}
|
|
137
136
|
required={required}
|
|
138
|
-
withAsterisk={withAsterisk}
|
|
139
137
|
id={id}
|
|
140
138
|
readOnly={readOnly}
|
|
141
139
|
readOnlyComponent={readOnlyComponent}
|
|
@@ -6,28 +6,11 @@ const meta: Meta<typeof FileInput> = {
|
|
|
6
6
|
title: "UI-Kit/🚧 FileInput",
|
|
7
7
|
component: FileInput,
|
|
8
8
|
tags: ["autodocs"],
|
|
9
|
-
|
|
10
|
-
controls: {
|
|
11
|
-
include: [
|
|
12
|
-
"layer",
|
|
13
|
-
"withLayer",
|
|
14
|
-
"children",
|
|
15
|
-
"component",
|
|
16
|
-
"variant",
|
|
17
|
-
"size",
|
|
18
|
-
"icon",
|
|
19
|
-
"disabled",
|
|
20
|
-
"href",
|
|
21
|
-
"onClick",
|
|
22
|
-
"onChange",
|
|
23
|
-
"value",
|
|
24
|
-
"checked",
|
|
25
|
-
],
|
|
26
|
-
},
|
|
27
|
-
},
|
|
9
|
+
argTypes: {},
|
|
28
10
|
};
|
|
29
11
|
|
|
30
12
|
export default meta;
|
|
13
|
+
|
|
31
14
|
type Story = StoryObj<typeof FileInput>;
|
|
32
15
|
|
|
33
16
|
export const Default: Story = {
|
|
@@ -6,28 +6,11 @@ const meta: Meta<typeof FileUpload> = {
|
|
|
6
6
|
title: "UI-Kit/🚧 FileUpload",
|
|
7
7
|
component: FileUpload,
|
|
8
8
|
tags: ["autodocs"],
|
|
9
|
-
|
|
10
|
-
controls: {
|
|
11
|
-
include: [
|
|
12
|
-
"layer",
|
|
13
|
-
"withLayer",
|
|
14
|
-
"children",
|
|
15
|
-
"component",
|
|
16
|
-
"variant",
|
|
17
|
-
"size",
|
|
18
|
-
"icon",
|
|
19
|
-
"disabled",
|
|
20
|
-
"href",
|
|
21
|
-
"onClick",
|
|
22
|
-
"onChange",
|
|
23
|
-
"value",
|
|
24
|
-
"checked",
|
|
25
|
-
],
|
|
26
|
-
},
|
|
27
|
-
},
|
|
9
|
+
argTypes: {},
|
|
28
10
|
};
|
|
29
11
|
|
|
30
12
|
export default meta;
|
|
13
|
+
|
|
31
14
|
type Story = StoryObj<typeof FileUpload>;
|
|
32
15
|
|
|
33
16
|
export const Default: Story = {
|
|
@@ -1,35 +1,128 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
3
|
import { Flex } from "./Flex";
|
|
3
|
-
import {
|
|
4
|
+
import { Button } from "../Button";
|
|
5
|
+
import { Text } from "../Text/Text";
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
type FlexStoryProps = React.ComponentProps<typeof Flex>;
|
|
8
|
+
|
|
9
|
+
const meta: Meta<FlexStoryProps> = {
|
|
10
|
+
title: "UI-Kit/Flex",
|
|
7
11
|
component: Flex,
|
|
8
12
|
tags: ["autodocs"],
|
|
9
13
|
parameters: {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component:
|
|
17
|
+
"Flex is a bare-metal flex container that maps directly to Mantine's Flex component, providing unopinionated control over direction, alignment, and wrapping.",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
args: {
|
|
22
|
+
gap: "rec-default",
|
|
23
|
+
align: "center",
|
|
24
|
+
justify: "flex-start",
|
|
25
|
+
direction: "row",
|
|
26
|
+
wrap: "wrap",
|
|
27
|
+
},
|
|
28
|
+
argTypes: {
|
|
29
|
+
gap: {
|
|
30
|
+
control: "select",
|
|
31
|
+
options: [
|
|
32
|
+
"rec-none",
|
|
33
|
+
"rec-sm",
|
|
34
|
+
"rec-default",
|
|
35
|
+
"rec-md",
|
|
36
|
+
"rec-lg",
|
|
37
|
+
"rec-xl",
|
|
38
|
+
"rec-2xl",
|
|
39
|
+
"xs",
|
|
40
|
+
"sm",
|
|
41
|
+
"md",
|
|
42
|
+
"lg",
|
|
43
|
+
"xl",
|
|
44
|
+
],
|
|
45
|
+
description: "Gap between elements",
|
|
46
|
+
},
|
|
47
|
+
direction: {
|
|
48
|
+
control: "select",
|
|
49
|
+
options: ["row", "column", "row-reverse", "column-reverse"],
|
|
50
|
+
description: "Flex-direction property",
|
|
51
|
+
},
|
|
52
|
+
align: {
|
|
53
|
+
control: "select",
|
|
54
|
+
options: ["flex-start", "center", "flex-end", "stretch"],
|
|
55
|
+
description: "Align-items property",
|
|
56
|
+
},
|
|
57
|
+
justify: {
|
|
58
|
+
control: "select",
|
|
59
|
+
options: [
|
|
60
|
+
"flex-start",
|
|
61
|
+
"center",
|
|
62
|
+
"flex-end",
|
|
63
|
+
"space-between",
|
|
64
|
+
"space-around",
|
|
25
65
|
],
|
|
66
|
+
description: "Justify-content property",
|
|
67
|
+
},
|
|
68
|
+
wrap: {
|
|
69
|
+
control: "select",
|
|
70
|
+
options: ["wrap", "nowrap", "wrap-reverse"],
|
|
71
|
+
description: "Flex-wrap property",
|
|
72
|
+
},
|
|
73
|
+
defaultChecked: {
|
|
74
|
+
table: { disable: true },
|
|
75
|
+
},
|
|
76
|
+
rowGap: {
|
|
77
|
+
table: { disable: true },
|
|
78
|
+
},
|
|
79
|
+
columnGap: {
|
|
80
|
+
table: { disable: true },
|
|
26
81
|
},
|
|
27
82
|
},
|
|
28
83
|
};
|
|
29
84
|
|
|
30
85
|
export default meta;
|
|
31
|
-
|
|
86
|
+
|
|
87
|
+
type Story = StoryObj<FlexStoryProps>;
|
|
32
88
|
|
|
33
89
|
export const Default: Story = {
|
|
34
|
-
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
91
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
92
|
+
<Flex {...args}>
|
|
93
|
+
<Button variant="solid">Block A</Button>
|
|
94
|
+
<Button variant="outline">Block B</Button>
|
|
95
|
+
<Text>Text inside Flex</Text>
|
|
96
|
+
</Flex>
|
|
97
|
+
),
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const StaticGapSmallColumn: Story = {
|
|
101
|
+
args: {
|
|
102
|
+
gap: "rec-sm",
|
|
103
|
+
direction: "column",
|
|
104
|
+
},
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
106
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
107
|
+
<Flex {...args}>
|
|
108
|
+
<Button variant="solid">Item 1</Button>
|
|
109
|
+
<Button variant="solid">Item 2</Button>
|
|
110
|
+
<Button variant="solid">Item 3</Button>
|
|
111
|
+
</Flex>
|
|
112
|
+
),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const StaticGapLargeRow: Story = {
|
|
116
|
+
args: {
|
|
117
|
+
gap: "rec-xl",
|
|
118
|
+
direction: "row",
|
|
119
|
+
},
|
|
120
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
121
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
122
|
+
<Flex {...args}>
|
|
123
|
+
<Button variant="solid">Item 1</Button>
|
|
124
|
+
<Button variant="solid">Item 2</Button>
|
|
125
|
+
<Button variant="solid">Item 3</Button>
|
|
126
|
+
</Flex>
|
|
127
|
+
),
|
|
35
128
|
};
|
|
@@ -11,41 +11,27 @@
|
|
|
11
11
|
import React, { forwardRef } from "react";
|
|
12
12
|
import { Box as MUIBox, type BoxProps as MUIBoxProps } from "@mui/material";
|
|
13
13
|
import {
|
|
14
|
-
type RecursicaSpacing,
|
|
15
14
|
SPACING_MAP,
|
|
16
15
|
type OmitSx,
|
|
17
16
|
filterSxProp,
|
|
18
17
|
} from "../../utils/filterStylingProps";
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Content to render inside the flex container.
|
|
23
|
-
*/
|
|
24
|
-
children?: React.ReactNode;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The gap between flex items. Accepts standard MUI spacing or Recursica gap tokens
|
|
28
|
-
* (e.g. "rec-md").
|
|
29
|
-
*/
|
|
30
|
-
gap?: string | number | RecursicaSpacing;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* The vertical gap between flex items when wrapping. Accepts standard MUI spacing
|
|
34
|
-
* or Recursica gap tokens.
|
|
35
|
-
*/
|
|
36
|
-
rowGap?: string | number | RecursicaSpacing;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* The horizontal gap between flex items when wrapping. Accepts standard MUI spacing
|
|
40
|
-
* or Recursica gap tokens.
|
|
41
|
-
*/
|
|
42
|
-
columnGap?: string | number | RecursicaSpacing;
|
|
43
|
-
}
|
|
19
|
+
import { type RecursicaFlexProps } from "@recursica/adapter-common";
|
|
44
20
|
|
|
45
21
|
export type FlexProps = OmitSx<MUIBoxProps & RecursicaFlexProps>;
|
|
46
22
|
|
|
47
23
|
export const Flex = forwardRef<HTMLDivElement, FlexProps>(function Flex(
|
|
48
|
-
{
|
|
24
|
+
{
|
|
25
|
+
children,
|
|
26
|
+
gap = "rec-default",
|
|
27
|
+
rowGap,
|
|
28
|
+
columnGap,
|
|
29
|
+
direction,
|
|
30
|
+
align,
|
|
31
|
+
justify,
|
|
32
|
+
wrap,
|
|
33
|
+
...rest
|
|
34
|
+
},
|
|
49
35
|
ref,
|
|
50
36
|
) {
|
|
51
37
|
const safeProps = filterSxProp(rest as Record<string, unknown>);
|
|
@@ -70,6 +56,10 @@ export const Flex = forwardRef<HTMLDivElement, FlexProps>(function Flex(
|
|
|
70
56
|
gap={resolvedGap}
|
|
71
57
|
rowGap={resolvedRowGap}
|
|
72
58
|
columnGap={resolvedColumnGap}
|
|
59
|
+
flexDirection={direction}
|
|
60
|
+
alignItems={align}
|
|
61
|
+
justifyContent={justify}
|
|
62
|
+
flexWrap={wrap}
|
|
73
63
|
>
|
|
74
64
|
{children}
|
|
75
65
|
</MUIBox>
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import React from "react";
|
|
3
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
4
2
|
import { FormControlLayout } from "./FormControlLayout";
|
|
5
3
|
import { Switch } from "../Switch/Switch";
|
|
@@ -15,9 +13,6 @@ const meta: Meta<typeof FormControlLayout> = {
|
|
|
15
13
|
"A layout component used to correctly position form inputs alongside their labels.\n\n**When to use this:**\nTypically, you should use `FormControlWrapper` instead, which uses this component under the hood to handle layout automatically.\n\nHowever, this component is useful when you need to align standalone inputs (like a `Switch` or `Checkbox` without a label) so they perfectly match the spacing and alignment of your other form fields in a `side-by-side` layout.",
|
|
16
14
|
},
|
|
17
15
|
},
|
|
18
|
-
controls: {
|
|
19
|
-
include: ["formLayout", "labelSize"],
|
|
20
|
-
},
|
|
21
16
|
},
|
|
22
17
|
tags: ["autodocs"],
|
|
23
18
|
argTypes: {
|
|
@@ -59,7 +54,6 @@ export const Default: Story = {
|
|
|
59
54
|
),
|
|
60
55
|
children: <Switch label="Input area content" />,
|
|
61
56
|
},
|
|
62
|
-
render: ({ ...args }: any) => <FormControlLayout {...args} />,
|
|
63
57
|
};
|
|
64
58
|
|
|
65
59
|
/**
|
|
@@ -72,7 +66,6 @@ export const StackedLayout: Story = {
|
|
|
72
66
|
labelSize: "default",
|
|
73
67
|
children: <Switch label="Flush stacked switch" />,
|
|
74
68
|
},
|
|
75
|
-
render: ({ ...args }: any) => <FormControlLayout {...args} />,
|
|
76
69
|
};
|
|
77
70
|
|
|
78
71
|
/**
|
|
@@ -86,5 +79,4 @@ export const SideBySideLayout: Story = {
|
|
|
86
79
|
labelSize: "default",
|
|
87
80
|
children: <Switch label="Offset switch aligning with grid" />,
|
|
88
81
|
},
|
|
89
|
-
render: ({ ...args }: any) => <FormControlLayout {...args} />,
|
|
90
82
|
};
|
|
@@ -2,15 +2,12 @@ import React from "react";
|
|
|
2
2
|
import { filterStylingProps } from "../../utils/filterStylingProps";
|
|
3
3
|
import styles from "./FormControlLayout.module.css";
|
|
4
4
|
|
|
5
|
+
import { type RecursicaFormControlLayoutProps } from "@recursica/adapter-common";
|
|
6
|
+
|
|
5
7
|
export interface FormControlLayoutProps
|
|
6
|
-
extends React.HTMLAttributes<HTMLDivElement
|
|
8
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
9
|
+
RecursicaFormControlLayoutProps {
|
|
7
10
|
overStyled?: boolean;
|
|
8
|
-
formLayout?: "stacked" | "side-by-side";
|
|
9
|
-
labelSize?: "small" | "default" | "md";
|
|
10
|
-
controlMaxWidth?: string;
|
|
11
|
-
controlMinWidth?: string;
|
|
12
|
-
leftSection?: React.ReactNode;
|
|
13
|
-
children: React.ReactNode;
|
|
14
11
|
}
|
|
15
12
|
|
|
16
13
|
export const FormControlLayout = React.forwardRef<
|
|
@@ -21,9 +18,12 @@ export const FormControlLayout = React.forwardRef<
|
|
|
21
18
|
overStyled = false,
|
|
22
19
|
formLayout = "stacked",
|
|
23
20
|
labelSize = "default",
|
|
21
|
+
controlMaxWidth,
|
|
22
|
+
controlMinWidth,
|
|
24
23
|
leftSection,
|
|
25
24
|
className,
|
|
26
25
|
children,
|
|
26
|
+
style,
|
|
27
27
|
...rest
|
|
28
28
|
} = props;
|
|
29
29
|
|
|
@@ -34,6 +34,17 @@ export const FormControlLayout = React.forwardRef<
|
|
|
34
34
|
ref={ref}
|
|
35
35
|
className={className ? `${styles.root} ${className}` : styles.root}
|
|
36
36
|
data-form-layout={formLayout}
|
|
37
|
+
style={
|
|
38
|
+
{
|
|
39
|
+
...style,
|
|
40
|
+
...(controlMaxWidth
|
|
41
|
+
? { "--form-control-max-width": controlMaxWidth }
|
|
42
|
+
: {}),
|
|
43
|
+
...(controlMinWidth
|
|
44
|
+
? { "--form-control-min-width": controlMinWidth }
|
|
45
|
+
: {}),
|
|
46
|
+
} as React.CSSProperties
|
|
47
|
+
}
|
|
37
48
|
{...sanitizedProps}
|
|
38
49
|
>
|
|
39
50
|
{/*
|
|
@@ -74,21 +74,12 @@
|
|
|
74
74
|
color: var(--form-field-text-valued);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
.
|
|
77
|
+
.inputSection {
|
|
78
78
|
display: flex;
|
|
79
79
|
flex-direction: column;
|
|
80
80
|
flex: 1;
|
|
81
81
|
min-width: 0;
|
|
82
|
-
|
|
83
|
-
/* Constrain the input natively to custom properties */
|
|
84
|
-
max-width: var(--form-control-max-width);
|
|
85
|
-
min-width: var(--form-control-min-width);
|
|
86
|
-
|
|
87
|
-
/* Hook to allow child components to add margin below themselves dynamically
|
|
88
|
-
via CSS variables (e.g. padding beneath TextField before AssistiveText renders) */
|
|
89
|
-
margin-bottom: var(--form-control-margin-bottom);
|
|
90
82
|
}
|
|
91
|
-
|
|
92
83
|
.assistive {
|
|
93
84
|
margin-top: var(
|
|
94
85
|
--recursica_ui-kit_globals_form_properties_label-field-gap-vertical
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import React from "react";
|
|
3
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
4
2
|
import {
|
|
5
3
|
FormControlWrapper,
|
|
@@ -18,23 +16,9 @@ const meta: Meta<WrapperStoryProps> = {
|
|
|
18
16
|
docs: {
|
|
19
17
|
description: {
|
|
20
18
|
component:
|
|
21
|
-
"The `FormControlWrapper` is the ultimate structural replacement for built-in
|
|
19
|
+
"The `FormControlWrapper` is the ultimate structural replacement for Mantine's built-in `Input.Wrapper`. By abandoning Mantine's opinionated wrappers entirely, we centralize all label tracking, error rendering, ARIA generation, and grid layouts natively inside this single component.\n\n### Usage with Naked Primitives\nThis component wraps 'naked' elements like `<Input>` directly. The demonstration stories below utilize `<TextField>` as a native display vehicle, since `<TextField>` natively pipes all its properties structurally back into this wrapper.",
|
|
22
20
|
},
|
|
23
21
|
},
|
|
24
|
-
controls: {
|
|
25
|
-
include: [
|
|
26
|
-
"error",
|
|
27
|
-
"assistiveText",
|
|
28
|
-
"assistiveWithIcon",
|
|
29
|
-
"required",
|
|
30
|
-
"formLayout",
|
|
31
|
-
"labelSize",
|
|
32
|
-
"labelAlignment",
|
|
33
|
-
"labelOptionalText",
|
|
34
|
-
"labelWithEditIcon",
|
|
35
|
-
"labelActionArea",
|
|
36
|
-
],
|
|
37
|
-
},
|
|
38
22
|
},
|
|
39
23
|
argTypes: {
|
|
40
24
|
...formControlArgTypes,
|
|
@@ -61,10 +45,15 @@ export default meta;
|
|
|
61
45
|
|
|
62
46
|
type Story = StoryObj<WrapperStoryProps>;
|
|
63
47
|
|
|
64
|
-
const renderWithTextField = (
|
|
65
|
-
// We explicitly cast args to 'any' here because
|
|
48
|
+
const renderWithTextField = (args: WrapperStoryProps) => (
|
|
49
|
+
// We explicitly cast args to 'any' here because Mantine enforces strict anatomy types for
|
|
50
|
+
// 'classNames', 'styles', and 'attributes'. WrapperStoryProps defines these for the Wrapper anatomy,
|
|
66
51
|
// but TextField expects them for the full TextInput anatomy, causing a TS intersection mismatch.
|
|
67
|
-
<TextField
|
|
52
|
+
<TextField
|
|
53
|
+
placeholder="Form Control primitive mapped..."
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
+
{...(args as any)}
|
|
56
|
+
/>
|
|
68
57
|
);
|
|
69
58
|
|
|
70
59
|
export const Default: Story = {
|
|
@@ -119,7 +108,8 @@ export const NativeChildrenDirectly: Story = {
|
|
|
119
108
|
formLayout: "side-by-side",
|
|
120
109
|
assistiveText: "This wraps a raw HTML input tag mapping correctly.",
|
|
121
110
|
},
|
|
122
|
-
|
|
111
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
112
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
123
113
|
<div
|
|
124
114
|
style={{
|
|
125
115
|
display: "flex",
|
|
@@ -127,6 +117,7 @@ export const NativeChildrenDirectly: Story = {
|
|
|
127
117
|
alignItems: "center",
|
|
128
118
|
}}
|
|
129
119
|
>
|
|
120
|
+
{/* We can cleanly wrap even un-styled HTML primitives! */}
|
|
130
121
|
<FormControlWrapper {...args}>
|
|
131
122
|
<input
|
|
132
123
|
type="checkbox"
|
|
@@ -6,29 +6,14 @@ import { AssistiveElement } from "../AssistiveElement/AssistiveElement";
|
|
|
6
6
|
import { FormControlLayout } from "../FormControlLayout/FormControlLayout";
|
|
7
7
|
import styles from "./FormControlWrapper.module.css";
|
|
8
8
|
|
|
9
|
+
import { type RecursicaFormControlWrapperProps as BaseRecursicaFormControlWrapperProps } from "@recursica/adapter-common";
|
|
10
|
+
|
|
9
11
|
export interface RecursicaFormControlWrapperProps
|
|
10
|
-
extends Omit<FormControlProps, "margin" | "variant" | "size" | "color"
|
|
12
|
+
extends Omit<FormControlProps, "margin" | "variant" | "size" | "color">,
|
|
13
|
+
BaseRecursicaFormControlWrapperProps {
|
|
11
14
|
overStyled?: boolean;
|
|
12
15
|
label?: React.ReactNode;
|
|
13
|
-
|
|
14
|
-
assistiveText?: React.ReactNode;
|
|
15
|
-
/** Secondary parameter fallback identical to assistiveText to match MUI / Mantine native APIs safely. */
|
|
16
|
-
description?: React.ReactNode;
|
|
17
|
-
/** Fallback mapping for MUI's native helperText */
|
|
18
|
-
helperText?: React.ReactNode;
|
|
19
|
-
assistiveWithIcon?: boolean;
|
|
20
|
-
|
|
21
|
-
formLayout?: "stacked" | "side-by-side";
|
|
22
|
-
labelSize?: "small" | "default" | "md";
|
|
23
|
-
labelAlignment?: "left" | "right"; // Currently functionally maps to left automatically natively
|
|
24
|
-
labelOptionalText?: React.ReactNode | true;
|
|
25
|
-
labelWithEditIcon?: boolean;
|
|
26
|
-
onLabelEditClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
27
|
-
labelActionArea?: React.ReactNode;
|
|
28
|
-
|
|
29
|
-
/** Allows layout mapping to limit the input's bounding box without impacting the label */
|
|
30
|
-
controlMaxWidth?: string;
|
|
31
|
-
controlMinWidth?: string;
|
|
16
|
+
focused?: boolean;
|
|
32
17
|
}
|
|
33
18
|
|
|
34
19
|
export type FormControlWrapperProps = RecursicaFormControlWrapperProps;
|
|
@@ -95,11 +80,16 @@ export const FormControlWrapper = React.forwardRef<
|
|
|
95
80
|
focused={focused}
|
|
96
81
|
className={className ? `${styles.root} ${className}` : styles.root}
|
|
97
82
|
style={style}
|
|
83
|
+
data-error={error ? "true" : undefined}
|
|
84
|
+
data-disabled={disabled ? "true" : undefined}
|
|
85
|
+
data-focused={focused ? "true" : undefined}
|
|
98
86
|
{...(sanitizedProps as FormControlProps)}
|
|
99
87
|
>
|
|
100
88
|
<FormControlLayout
|
|
101
89
|
formLayout={formLayout}
|
|
102
90
|
labelSize={labelSize}
|
|
91
|
+
controlMaxWidth={controlMaxWidth}
|
|
92
|
+
controlMinWidth={controlMinWidth}
|
|
103
93
|
leftSection={
|
|
104
94
|
label && (
|
|
105
95
|
<Label
|
|
@@ -116,15 +106,7 @@ export const FormControlWrapper = React.forwardRef<
|
|
|
116
106
|
)
|
|
117
107
|
}
|
|
118
108
|
>
|
|
119
|
-
<div
|
|
120
|
-
className={styles.inputContainer}
|
|
121
|
-
style={
|
|
122
|
-
{
|
|
123
|
-
"--form-control-max-width": controlMaxWidth,
|
|
124
|
-
"--form-control-min-width": controlMinWidth,
|
|
125
|
-
} as React.CSSProperties
|
|
126
|
-
}
|
|
127
|
-
>
|
|
109
|
+
<div className={styles.inputSection}>
|
|
128
110
|
{/* Natively wrap children into flex box */}
|
|
129
111
|
{mappedChildren}
|
|
130
112
|
|
|
@@ -134,7 +116,6 @@ export const FormControlWrapper = React.forwardRef<
|
|
|
134
116
|
id={descriptionId}
|
|
135
117
|
assistiveVariant={error ? "error" : "help"}
|
|
136
118
|
assistiveWithIcon={assistiveWithIcon}
|
|
137
|
-
className={styles.assistive}
|
|
138
119
|
>
|
|
139
120
|
{error && typeof error === "string" ? error : finalAssistiveText}
|
|
140
121
|
</AssistiveElement>
|
|
@@ -17,36 +17,12 @@ const meta: Meta<GroupStoryProps> = {
|
|
|
17
17
|
"Group is a flex horizontal layout container that maps directly to Mantine's Group component allowing safe layout property passing.",
|
|
18
18
|
},
|
|
19
19
|
},
|
|
20
|
-
controls: {
|
|
21
|
-
include: [
|
|
22
|
-
"layer",
|
|
23
|
-
"withLayer",
|
|
24
|
-
"gap",
|
|
25
|
-
"alignItems",
|
|
26
|
-
"justifyContent",
|
|
27
|
-
"flexWrap",
|
|
28
|
-
"defaultChecked",
|
|
29
|
-
"rowGap",
|
|
30
|
-
"columnGap",
|
|
31
|
-
"children",
|
|
32
|
-
"component",
|
|
33
|
-
"variant",
|
|
34
|
-
"size",
|
|
35
|
-
"icon",
|
|
36
|
-
"disabled",
|
|
37
|
-
"href",
|
|
38
|
-
"onClick",
|
|
39
|
-
"onChange",
|
|
40
|
-
"value",
|
|
41
|
-
"checked",
|
|
42
|
-
],
|
|
43
|
-
},
|
|
44
20
|
},
|
|
45
21
|
args: {
|
|
46
22
|
gap: "rec-default",
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
23
|
+
align: "center",
|
|
24
|
+
justify: "flex-start",
|
|
25
|
+
wrap: "wrap",
|
|
50
26
|
},
|
|
51
27
|
argTypes: {
|
|
52
28
|
gap: {
|
|
@@ -67,12 +43,12 @@ const meta: Meta<GroupStoryProps> = {
|
|
|
67
43
|
],
|
|
68
44
|
description: "Gap between elements",
|
|
69
45
|
},
|
|
70
|
-
|
|
46
|
+
align: {
|
|
71
47
|
control: "select",
|
|
72
48
|
options: ["flex-start", "center", "flex-end", "stretch"],
|
|
73
49
|
description: "Align-items property",
|
|
74
50
|
},
|
|
75
|
-
|
|
51
|
+
justify: {
|
|
76
52
|
control: "select",
|
|
77
53
|
options: [
|
|
78
54
|
"flex-start",
|
|
@@ -83,7 +59,7 @@ const meta: Meta<GroupStoryProps> = {
|
|
|
83
59
|
],
|
|
84
60
|
description: "Justify-content property",
|
|
85
61
|
},
|
|
86
|
-
|
|
62
|
+
wrap: {
|
|
87
63
|
control: "select",
|
|
88
64
|
options: ["wrap", "nowrap", "wrap-reverse"],
|
|
89
65
|
description: "Flex-wrap property",
|