@recursica/mui-adapter 0.4.0 → 0.6.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/CHANGELOG.md +15 -0
- package/dist/mui-adapter.cjs +74 -1
- package/dist/mui-adapter.cjs.map +1 -1
- package/dist/mui-adapter.css +1 -1
- package/dist/mui-adapter.js +6651 -201
- package/dist/mui-adapter.js.map +1 -1
- package/dist/src/components/Accordion/Accordion.d.ts +63 -2
- package/dist/src/components/AssistiveElement/AssistiveElement.d.ts +9 -2
- package/dist/src/components/Autocomplete/Autocomplete.d.ts +17 -0
- package/dist/src/components/Autocomplete/index.d.ts +1 -0
- package/dist/src/components/Avatar/Avatar.d.ts +14 -2
- package/dist/src/components/Badge/Badge.d.ts +13 -3
- package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +10 -3
- package/dist/src/components/Button/Button.d.ts +1 -1
- package/dist/src/components/Card/Card.d.ts +40 -3
- package/dist/src/components/Checkbox/Checkbox.d.ts +15 -2
- package/dist/src/components/Checkbox/CheckboxGroup.d.ts +16 -0
- package/dist/src/components/Checkbox/index.d.ts +5 -1
- package/dist/src/components/Chip/Chip.d.ts +18 -2
- package/dist/src/components/Dropdown/Dropdown.d.ts +23 -3
- package/dist/src/components/FormControlLayout/FormControlLayout.d.ts +10 -2
- package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +24 -2
- package/dist/src/components/HoverCard/HoverCard.d.ts +55 -3
- package/dist/src/components/Label/Label.d.ts +13 -2
- package/dist/src/components/Link/Link.d.ts +1 -1
- package/dist/src/components/Menu/Menu.d.ts +99 -3
- package/dist/src/components/Modal/Modal.d.ts +36 -2
- package/dist/src/components/NumberInput/NumberInput.d.ts +14 -2
- package/dist/src/components/Pagination/Pagination.d.ts +44 -2
- package/dist/src/components/Pagination/Pagination.icons.d.ts +8 -0
- package/dist/src/components/Panel/Panel.d.ts +65 -3
- package/dist/src/components/Radio/Radio.d.ts +13 -3
- package/dist/src/components/Radio/RadioGroup.d.ts +13 -0
- package/dist/src/components/ReadOnlyField/ReadOnlyBooleanField.d.ts +5 -0
- package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +7 -2
- package/dist/src/components/ReadOnlyField/ReadOnlySwitchField.d.ts +5 -0
- package/dist/src/components/ReadOnlyField/ReadOnlyTextField.d.ts +8 -0
- package/dist/src/components/ReadOnlyField/WithReadOnlyWrapper.d.ts +28 -0
- package/dist/src/components/ReadOnlyField/index.d.ts +1 -0
- package/dist/src/components/SegmentedControl/SegmentedControl.d.ts +31 -3
- package/dist/src/components/Slider/Slider.d.ts +28 -2
- package/dist/src/components/Stepper/Stepper.d.ts +21 -2
- package/dist/src/components/Switch/Switch.d.ts +10 -3
- package/dist/src/components/Switch/SwitchGroup.d.ts +13 -0
- package/dist/src/components/Tabs/Tabs.d.ts +35 -3
- package/dist/src/components/Text/Text.d.ts +1 -1
- package/dist/src/components/TextArea/TextArea.d.ts +18 -2
- package/dist/src/components/TextField/TextField.d.ts +16 -2
- package/dist/src/components/Timeline/Timeline.d.ts +14 -2
- package/dist/src/components/Timeline/TimelineItem.d.ts +29 -0
- package/dist/src/components/Title/Title.d.ts +1 -1
- package/dist/src/components/Toast/Toast.d.ts +25 -2
- package/dist/src/components/Tooltip/Tooltip.d.ts +42 -3
- package/dist/src/components/Typography/Typography.d.ts +1 -1
- package/dist/src/components/index.d.ts +1 -0
- package/package.json +12 -2
- package/src/GlobalExemptions.modules.css +13 -0
- package/src/components/Accordion/Accordion.module.css +295 -0
- package/src/components/Accordion/Accordion.stories.tsx +149 -21
- package/src/components/Accordion/Accordion.tsx +264 -4
- package/src/components/AssistiveElement/AssistiveElement.module.css +111 -0
- package/src/components/AssistiveElement/AssistiveElement.stories.tsx +76 -19
- package/src/components/AssistiveElement/AssistiveElement.tsx +85 -4
- package/src/components/Autocomplete/Autocomplete.module.css +325 -0
- package/src/components/Autocomplete/Autocomplete.stories.tsx +196 -0
- package/src/components/Autocomplete/Autocomplete.tsx +201 -0
- package/src/components/Autocomplete/index.ts +1 -0
- package/src/components/Avatar/Avatar.module.css +344 -0
- package/src/components/Avatar/Avatar.stories.tsx +94 -22
- package/src/components/Avatar/Avatar.tsx +110 -5
- package/src/components/Badge/Badge.module.css +127 -0
- package/src/components/Badge/Badge.stories.tsx +65 -22
- package/src/components/Badge/Badge.tsx +70 -5
- package/src/components/Breadcrumb/Breadcrumb.module.css +26 -0
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +57 -22
- package/src/components/Breadcrumb/Breadcrumb.tsx +62 -5
- package/src/components/Button/Button.module.css +113 -20
- package/src/components/Button/Button.stories.tsx +3 -0
- package/src/components/Button/Button.tsx +10 -3
- package/src/components/Card/Card.module.css +118 -0
- package/src/components/Card/Card.stories.tsx +117 -19
- package/src/components/Card/Card.tsx +179 -4
- package/src/components/Checkbox/Checkbox.module.css +232 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +81 -19
- package/src/components/Checkbox/Checkbox.tsx +146 -4
- package/src/components/Checkbox/CheckboxGroup.tsx +117 -0
- package/src/components/Checkbox/index.ts +6 -1
- package/src/components/Chip/Chip.module.css +236 -0
- package/src/components/Chip/Chip.stories.tsx +101 -21
- package/src/components/Chip/Chip.tsx +138 -5
- package/src/components/DatePicker/DatePicker.module.css +42 -0
- package/src/components/DatePicker/DatePicker.tsx +1 -0
- package/src/components/Dropdown/Dropdown.module.css +296 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +80 -21
- package/src/components/Dropdown/Dropdown.tsx +182 -5
- package/src/components/FileInput/FileInput.module.css +47 -0
- package/src/components/FileInput/FileInput.tsx +1 -0
- package/src/components/FileUpload/FileUpload.module.css +40 -0
- package/src/components/FileUpload/FileUpload.tsx +1 -0
- package/src/components/FormControlLayout/FormControlLayout.module.css +92 -0
- package/src/components/FormControlLayout/FormControlLayout.stories.tsx +74 -19
- package/src/components/FormControlLayout/FormControlLayout.tsx +58 -4
- package/src/components/FormControlWrapper/FormControlWrapper.module.css +96 -0
- package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +122 -19
- package/src/components/FormControlWrapper/FormControlWrapper.tsx +145 -6
- package/src/components/HoverCard/HoverCard.module.css +91 -0
- package/src/components/HoverCard/HoverCard.stories.tsx +158 -21
- package/src/components/HoverCard/HoverCard.tsx +150 -4
- package/src/components/Label/Label.module.css +136 -0
- package/src/components/Label/Label.stories.tsx +98 -17
- package/src/components/Label/Label.tsx +88 -4
- package/src/components/Link/Link.module.css +8 -0
- package/src/components/Menu/Menu.module.css +287 -0
- package/src/components/Menu/Menu.stories.tsx +307 -21
- package/src/components/Menu/Menu.tsx +318 -4
- package/src/components/Modal/Modal.module.css +172 -0
- package/src/components/Modal/Modal.stories.tsx +66 -22
- package/src/components/Modal/Modal.tsx +216 -3
- package/src/components/NumberInput/NumberInput.module.css +281 -0
- package/src/components/NumberInput/NumberInput.stories.tsx +83 -20
- package/src/components/NumberInput/NumberInput.tsx +148 -5
- package/src/components/Pagination/Pagination.icons.tsx +66 -0
- package/src/components/Pagination/Pagination.module.css +307 -0
- package/src/components/Pagination/Pagination.stories.tsx +42 -21
- package/src/components/Pagination/Pagination.tsx +193 -4
- package/src/components/Panel/Panel.module.css +206 -0
- package/src/components/Panel/Panel.stories.tsx +214 -22
- package/src/components/Panel/Panel.tsx +153 -4
- package/src/components/Radio/Radio.module.css +220 -0
- package/src/components/Radio/Radio.stories.tsx +77 -19
- package/src/components/Radio/Radio.tsx +178 -4
- package/src/components/Radio/RadioGroup.tsx +111 -0
- package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
- package/src/components/ReadOnlyField/ReadOnlyField.module.css +54 -0
- package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +175 -16
- package/src/components/ReadOnlyField/ReadOnlyField.tsx +109 -4
- package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
- package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +48 -0
- package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +93 -0
- package/src/components/ReadOnlyField/index.ts +1 -0
- package/src/components/SegmentedControl/SegmentedControl.module.css +203 -0
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +102 -20
- package/src/components/SegmentedControl/SegmentedControl.tsx +110 -5
- package/src/components/Slider/Slider.module.css +542 -0
- package/src/components/Slider/Slider.stories.tsx +157 -19
- package/src/components/Slider/Slider.tsx +282 -4
- package/src/components/Stepper/Stepper.module.css +410 -0
- package/src/components/Stepper/Stepper.stories.tsx +132 -19
- package/src/components/Stepper/Stepper.tsx +145 -5
- package/src/components/Switch/Switch.module.css +238 -0
- package/src/components/Switch/Switch.stories.tsx +98 -19
- package/src/components/Switch/Switch.tsx +153 -5
- package/src/components/Switch/SwitchGroup.tsx +111 -0
- package/src/components/Tabs/Tabs.module.css +422 -0
- package/src/components/Tabs/Tabs.stories.tsx +138 -19
- package/src/components/Tabs/Tabs.tsx +103 -5
- package/src/components/TextArea/TextArea.module.css +160 -0
- package/src/components/TextArea/TextArea.stories.tsx +80 -21
- package/src/components/TextArea/TextArea.tsx +156 -5
- package/src/components/TextField/TextField.module.css +266 -0
- package/src/components/TextField/TextField.stories.tsx +168 -15
- package/src/components/TextField/TextField.tsx +171 -5
- package/src/components/TimePicker/TimePicker.module.css +41 -0
- package/src/components/TimePicker/TimePicker.tsx +1 -0
- package/src/components/Timeline/Timeline.module.css +367 -0
- package/src/components/Timeline/Timeline.stories.tsx +114 -21
- package/src/components/Timeline/Timeline.tsx +80 -4
- package/src/components/Timeline/TimelineItem.tsx +101 -0
- package/src/components/Toast/Toast.module.css +170 -0
- package/src/components/Toast/Toast.stories.tsx +54 -22
- package/src/components/Toast/Toast.tsx +90 -4
- package/src/components/Tooltip/Tooltip.module.css +90 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +152 -22
- package/src/components/Tooltip/Tooltip.tsx +114 -4
- package/src/components/TransferList/TransferList.module.css +38 -0
- package/src/components/TransferList/TransferList.tsx +1 -0
- package/src/components/index.ts +1 -0
|
@@ -1,7 +1,267 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { forwardRef, createContext, useContext, useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Accordion as MuiAccordion,
|
|
4
|
+
AccordionSummary as MuiAccordionSummary,
|
|
5
|
+
AccordionDetails as MuiAccordionDetails,
|
|
6
|
+
type AccordionProps as MuiAccordionProps,
|
|
7
|
+
type AccordionSummaryProps as MuiAccordionSummaryProps,
|
|
8
|
+
type AccordionDetailsProps as MuiAccordionDetailsProps,
|
|
9
|
+
} from "@mui/material";
|
|
10
|
+
import {
|
|
11
|
+
filterStylingProps,
|
|
12
|
+
type RecursicaOverStyled,
|
|
13
|
+
} from "../../utils/filterStylingProps";
|
|
14
|
+
import styles from "./Accordion.module.css";
|
|
2
15
|
|
|
3
|
-
|
|
16
|
+
const ChevronIcon = () => (
|
|
17
|
+
<svg
|
|
18
|
+
viewBox="0 0 24 24"
|
|
19
|
+
fill="none"
|
|
20
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
21
|
+
stroke="currentColor"
|
|
22
|
+
strokeWidth="2"
|
|
23
|
+
strokeLinecap="round"
|
|
24
|
+
strokeLinejoin="round"
|
|
25
|
+
style={{ width: "100%", height: "100%" }}
|
|
26
|
+
>
|
|
27
|
+
<polyline points="6 9 12 15 18 9"></polyline>
|
|
28
|
+
</svg>
|
|
29
|
+
);
|
|
4
30
|
|
|
5
|
-
|
|
6
|
-
|
|
31
|
+
const AccordionContext = createContext<{
|
|
32
|
+
value: string | string[] | null;
|
|
33
|
+
onChange: (val: string) => void;
|
|
34
|
+
} | null>(null);
|
|
35
|
+
|
|
36
|
+
// ==== ACCORDION CONTAINER ====
|
|
37
|
+
export type AccordionProps = RecursicaOverStyled<
|
|
38
|
+
React.HTMLAttributes<HTMLDivElement> & {
|
|
39
|
+
variant?: string;
|
|
40
|
+
value?: string | string[];
|
|
41
|
+
defaultValue?: string | string[];
|
|
42
|
+
onChange?: (value: string | string[] | null) => void;
|
|
43
|
+
multiple?: boolean;
|
|
44
|
+
}
|
|
45
|
+
>;
|
|
46
|
+
|
|
47
|
+
const AccordionBase = forwardRef<HTMLDivElement, AccordionProps>(
|
|
48
|
+
function Accordion(
|
|
49
|
+
{
|
|
50
|
+
variant = "unstyled",
|
|
51
|
+
overStyled = false,
|
|
52
|
+
value,
|
|
53
|
+
defaultValue,
|
|
54
|
+
onChange,
|
|
55
|
+
multiple = false,
|
|
56
|
+
children,
|
|
57
|
+
...rest
|
|
58
|
+
},
|
|
59
|
+
ref,
|
|
60
|
+
) {
|
|
61
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
62
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
63
|
+
.className as string | undefined;
|
|
64
|
+
|
|
65
|
+
const finalClass =
|
|
66
|
+
[styles.root, classNameProp].filter(Boolean).join(" ") || undefined;
|
|
67
|
+
|
|
68
|
+
const [uncontrolledValue, setUncontrolledValue] = useState<
|
|
69
|
+
string | string[] | null
|
|
70
|
+
>(defaultValue !== undefined ? defaultValue : multiple ? [] : null);
|
|
71
|
+
const activeValue = value !== undefined ? value : uncontrolledValue;
|
|
72
|
+
|
|
73
|
+
const handleItemChange = (itemValue: string) => {
|
|
74
|
+
let newValue: string | string[] | null;
|
|
75
|
+
if (multiple) {
|
|
76
|
+
const arr = Array.isArray(activeValue)
|
|
77
|
+
? activeValue
|
|
78
|
+
: activeValue
|
|
79
|
+
? [activeValue as string]
|
|
80
|
+
: [];
|
|
81
|
+
newValue = arr.includes(itemValue)
|
|
82
|
+
? arr.filter((v) => v !== itemValue)
|
|
83
|
+
: [...arr, itemValue];
|
|
84
|
+
} else {
|
|
85
|
+
newValue = activeValue === itemValue ? null : itemValue;
|
|
86
|
+
}
|
|
87
|
+
setUncontrolledValue(newValue);
|
|
88
|
+
onChange?.(newValue);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<AccordionContext.Provider
|
|
93
|
+
value={{ value: activeValue, onChange: handleItemChange }}
|
|
94
|
+
>
|
|
95
|
+
<div
|
|
96
|
+
ref={ref}
|
|
97
|
+
className={finalClass}
|
|
98
|
+
data-variant={variant}
|
|
99
|
+
{...(sanitizedProps as React.HTMLAttributes<HTMLDivElement>)}
|
|
100
|
+
>
|
|
101
|
+
{children}
|
|
102
|
+
</div>
|
|
103
|
+
</AccordionContext.Provider>
|
|
104
|
+
);
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
AccordionBase.displayName = "Accordion";
|
|
108
|
+
|
|
109
|
+
// ==== ACCORDION ITEM ====
|
|
110
|
+
export type AccordionItemWrapperProps = RecursicaOverStyled<
|
|
111
|
+
Omit<MuiAccordionProps, "children" | "value"> & {
|
|
112
|
+
children?: React.ReactNode;
|
|
113
|
+
title?: React.ReactNode;
|
|
114
|
+
leftIcon?: React.ReactNode;
|
|
115
|
+
divider?: boolean;
|
|
116
|
+
value: string;
|
|
117
|
+
}
|
|
118
|
+
>;
|
|
119
|
+
|
|
120
|
+
export const AccordionItem = forwardRef<
|
|
121
|
+
HTMLDivElement,
|
|
122
|
+
AccordionItemWrapperProps
|
|
123
|
+
>(function AccordionItem(
|
|
124
|
+
{
|
|
125
|
+
title,
|
|
126
|
+
leftIcon,
|
|
127
|
+
divider = true,
|
|
128
|
+
children,
|
|
129
|
+
value,
|
|
130
|
+
overStyled = false,
|
|
131
|
+
style,
|
|
132
|
+
...rest
|
|
133
|
+
},
|
|
134
|
+
ref,
|
|
135
|
+
) {
|
|
136
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
137
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
138
|
+
.className as string | undefined;
|
|
139
|
+
|
|
140
|
+
const finalClass =
|
|
141
|
+
[styles.item, divider ? undefined : styles.noDivider, classNameProp]
|
|
142
|
+
.filter(Boolean)
|
|
143
|
+
.join(" ") || undefined;
|
|
144
|
+
|
|
145
|
+
const ctx = useContext(AccordionContext);
|
|
146
|
+
const isExpanded = ctx
|
|
147
|
+
? Array.isArray(ctx.value)
|
|
148
|
+
? ctx.value.includes(value)
|
|
149
|
+
: ctx.value === value
|
|
150
|
+
: undefined;
|
|
151
|
+
|
|
152
|
+
const handleChange = () => {
|
|
153
|
+
ctx?.onChange(value);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// background-color: transparent allows Layer overrides to naturally penetrate
|
|
157
|
+
const mergedStyle = { backgroundColor: "transparent", ...style };
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<MuiAccordion
|
|
161
|
+
ref={ref}
|
|
162
|
+
className={finalClass}
|
|
163
|
+
disableGutters
|
|
164
|
+
elevation={0}
|
|
165
|
+
square
|
|
166
|
+
expanded={isExpanded}
|
|
167
|
+
onChange={handleChange}
|
|
168
|
+
style={mergedStyle}
|
|
169
|
+
{...(sanitizedProps as unknown as Omit<
|
|
170
|
+
MuiAccordionProps,
|
|
171
|
+
"expanded" | "onChange"
|
|
172
|
+
>)}
|
|
173
|
+
>
|
|
174
|
+
{title ? (
|
|
175
|
+
<>
|
|
176
|
+
<AccordionControl leftIcon={leftIcon}>{title}</AccordionControl>
|
|
177
|
+
<AccordionPanel>{children}</AccordionPanel>
|
|
178
|
+
</>
|
|
179
|
+
) : (
|
|
180
|
+
children
|
|
181
|
+
)}
|
|
182
|
+
</MuiAccordion>
|
|
183
|
+
);
|
|
184
|
+
});
|
|
185
|
+
AccordionItem.displayName = "AccordionItem";
|
|
186
|
+
|
|
187
|
+
// ==== ACCORDION CONTROL ====
|
|
188
|
+
export type AccordionControlWrapperProps = RecursicaOverStyled<
|
|
189
|
+
MuiAccordionSummaryProps & {
|
|
190
|
+
leftIcon?: React.ReactNode;
|
|
191
|
+
}
|
|
192
|
+
>;
|
|
193
|
+
|
|
194
|
+
export const AccordionControl = forwardRef<
|
|
195
|
+
HTMLDivElement,
|
|
196
|
+
AccordionControlWrapperProps
|
|
197
|
+
>(function AccordionControl(
|
|
198
|
+
{ leftIcon, children, overStyled = false, ...rest },
|
|
199
|
+
ref,
|
|
200
|
+
) {
|
|
201
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
202
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
203
|
+
.className as string | undefined;
|
|
204
|
+
|
|
205
|
+
const finalClass =
|
|
206
|
+
[styles.control, classNameProp].filter(Boolean).join(" ") || undefined;
|
|
207
|
+
|
|
208
|
+
return (
|
|
209
|
+
<MuiAccordionSummary
|
|
210
|
+
ref={ref}
|
|
211
|
+
className={finalClass}
|
|
212
|
+
expandIcon={
|
|
213
|
+
<span className={styles.chevron}>
|
|
214
|
+
<ChevronIcon />
|
|
215
|
+
</span>
|
|
216
|
+
}
|
|
217
|
+
{...(sanitizedProps as unknown as MuiAccordionSummaryProps)}
|
|
218
|
+
>
|
|
219
|
+
{leftIcon && (
|
|
220
|
+
<span className={styles.iconLeftWrapper} aria-hidden>
|
|
221
|
+
{leftIcon}
|
|
222
|
+
</span>
|
|
223
|
+
)}
|
|
224
|
+
<div className={styles.label}>{children}</div>
|
|
225
|
+
</MuiAccordionSummary>
|
|
226
|
+
);
|
|
227
|
+
});
|
|
228
|
+
AccordionControl.displayName = "AccordionControl";
|
|
229
|
+
|
|
230
|
+
// ==== ACCORDION PANEL ====
|
|
231
|
+
export type AccordionPanelWrapperProps =
|
|
232
|
+
RecursicaOverStyled<MuiAccordionDetailsProps>;
|
|
233
|
+
|
|
234
|
+
export const AccordionPanel = forwardRef<
|
|
235
|
+
HTMLDivElement,
|
|
236
|
+
AccordionPanelWrapperProps
|
|
237
|
+
>(function AccordionPanel({ overStyled = false, children, ...rest }, ref) {
|
|
238
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
239
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
240
|
+
.className as string | undefined;
|
|
241
|
+
|
|
242
|
+
const finalClass =
|
|
243
|
+
[styles.panel, classNameProp].filter(Boolean).join(" ") || undefined;
|
|
244
|
+
|
|
245
|
+
return (
|
|
246
|
+
<MuiAccordionDetails
|
|
247
|
+
ref={ref}
|
|
248
|
+
className={finalClass}
|
|
249
|
+
{...(sanitizedProps as unknown as MuiAccordionDetailsProps)}
|
|
250
|
+
>
|
|
251
|
+
<div className={styles.content}>{children}</div>
|
|
252
|
+
</MuiAccordionDetails>
|
|
253
|
+
);
|
|
254
|
+
});
|
|
255
|
+
AccordionPanel.displayName = "AccordionPanel";
|
|
256
|
+
|
|
257
|
+
// ==== DOT NOTATION EXPORT ====
|
|
258
|
+
type AccordionComponent = typeof AccordionBase & {
|
|
259
|
+
Item: typeof AccordionItem;
|
|
260
|
+
Control: typeof AccordionControl;
|
|
261
|
+
Panel: typeof AccordionPanel;
|
|
7
262
|
};
|
|
263
|
+
|
|
264
|
+
export const Accordion = AccordionBase as AccordionComponent;
|
|
265
|
+
Accordion.Item = AccordionItem;
|
|
266
|
+
Accordion.Control = AccordionControl;
|
|
267
|
+
Accordion.Panel = AccordionPanel;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/*
|
|
2
|
+
ASSISTIVE ELEMENT ARCHITECTURE
|
|
3
|
+
This component strictly standardizes FormHelperText logic dynamically natively decoupled from the overarching input blocks.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
.root {
|
|
7
|
+
/* Override MUI FormHelperText native resets structurally safely */
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: flex-start; /* Forces the icon to align with the first line of text */
|
|
10
|
+
margin: 0; /* HARDCODE: structural reset */
|
|
11
|
+
padding: 0; /* HARDCODE: structural reset */
|
|
12
|
+
width: 100%;
|
|
13
|
+
|
|
14
|
+
gap: var(
|
|
15
|
+
--recursica_ui-kit_components_assistive-element_properties_icon-text-gap
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
font-family: var(
|
|
19
|
+
--recursica_ui-kit_components_assistive-element_properties_text_font-family
|
|
20
|
+
);
|
|
21
|
+
font-size: var(
|
|
22
|
+
--recursica_ui-kit_components_assistive-element_properties_text_font-size
|
|
23
|
+
);
|
|
24
|
+
font-style: var(
|
|
25
|
+
--recursica_ui-kit_components_assistive-element_properties_text_font-style
|
|
26
|
+
);
|
|
27
|
+
font-weight: var(
|
|
28
|
+
--recursica_ui-kit_components_assistive-element_properties_text_font-weight
|
|
29
|
+
);
|
|
30
|
+
letter-spacing: var(
|
|
31
|
+
--recursica_ui-kit_components_assistive-element_properties_text_letter-spacing
|
|
32
|
+
);
|
|
33
|
+
line-height: var(
|
|
34
|
+
--recursica_ui-kit_components_assistive-element_properties_text_line-height
|
|
35
|
+
);
|
|
36
|
+
text-decoration: var(
|
|
37
|
+
--recursica_ui-kit_components_assistive-element_properties_text_text-decoration
|
|
38
|
+
);
|
|
39
|
+
text-transform: var(
|
|
40
|
+
--recursica_ui-kit_components_assistive-element_properties_text_text-transform
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.text {
|
|
45
|
+
flex: 1; /* Consume remaining space causing native flex wrap */
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* Base Icon Architecture */
|
|
49
|
+
.icon {
|
|
50
|
+
flex-shrink: 0; /* Prevent squishing */
|
|
51
|
+
display: flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
justify-content: center;
|
|
54
|
+
width: var(
|
|
55
|
+
--recursica_ui-kit_components_assistive-element_properties_icon-size
|
|
56
|
+
);
|
|
57
|
+
height: var(
|
|
58
|
+
--recursica_ui-kit_components_assistive-element_properties_icon-size
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
/* Mathematical vertical centering bounds to the first line of typography explicitly */
|
|
62
|
+
margin-top: calc(
|
|
63
|
+
(
|
|
64
|
+
var(
|
|
65
|
+
--recursica_ui-kit_components_assistive-element_properties_text_line-height
|
|
66
|
+
) -
|
|
67
|
+
var(
|
|
68
|
+
--recursica_ui-kit_components_assistive-element_properties_icon-size
|
|
69
|
+
)
|
|
70
|
+
) /
|
|
71
|
+
2
|
|
72
|
+
); /* Forces exact centering bounds within the first text line vertically */
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.icon :global(svg) {
|
|
76
|
+
width: 100%;
|
|
77
|
+
height: 100%;
|
|
78
|
+
stroke-width: 2px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* =========================================
|
|
82
|
+
VARIANTS: Default / Help
|
|
83
|
+
========================================= */
|
|
84
|
+
|
|
85
|
+
.root[data-variant="help"] {
|
|
86
|
+
color: var(
|
|
87
|
+
--recursica_ui-kit_components_assistive-element_variants_types_help_properties_colors_text-color
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.root[data-variant="help"] .icon {
|
|
92
|
+
color: var(
|
|
93
|
+
--recursica_ui-kit_components_assistive-element_variants_types_help_properties_colors_icon-color
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* =========================================
|
|
98
|
+
VARIANTS: Error
|
|
99
|
+
========================================= */
|
|
100
|
+
|
|
101
|
+
.root[data-variant="error"] {
|
|
102
|
+
color: var(
|
|
103
|
+
--recursica_ui-kit_components_assistive-element_variants_types_error_properties_colors_text-color
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.root[data-variant="error"] .icon {
|
|
108
|
+
color: var(
|
|
109
|
+
--recursica_ui-kit_components_assistive-element_variants_types_error_properties_colors_icon-color
|
|
110
|
+
);
|
|
111
|
+
}
|
|
@@ -1,35 +1,92 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
3
|
import { AssistiveElement } from "./AssistiveElement";
|
|
3
|
-
import { ComingSoon } from "@recursica/storybook-template";
|
|
4
4
|
|
|
5
5
|
const meta: Meta<typeof AssistiveElement> = {
|
|
6
|
-
title: "UI-Kit
|
|
6
|
+
title: "UI-Kit/AssistiveElement",
|
|
7
7
|
component: AssistiveElement,
|
|
8
8
|
tags: ["autodocs"],
|
|
9
9
|
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component:
|
|
13
|
+
"The `AssistiveElement` is a semantic structural primitive designed to standardize Helper and Error descriptive blocks natively beneath form components globally. By explicitly wiring to the `--recursica_ui-kit_components_assistive-element` layout tokens, this component safely injects custom SVGs (Alerts vs Info circles) alongside constrained flex-wrapping typography strings, preserving flawless line-height and alignment logic entirely decoupled from underlying input engine frameworks.",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
10
16
|
controls: {
|
|
11
|
-
include: [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"onClick",
|
|
22
|
-
"onChange",
|
|
23
|
-
"value",
|
|
24
|
-
"checked",
|
|
25
|
-
],
|
|
17
|
+
include: ["assistiveVariant", "assistiveWithIcon", "children"],
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
argTypes: {
|
|
21
|
+
assistiveVariant: {
|
|
22
|
+
control: "radio",
|
|
23
|
+
options: ["help", "error"],
|
|
24
|
+
},
|
|
25
|
+
assistiveWithIcon: {
|
|
26
|
+
control: "boolean",
|
|
26
27
|
},
|
|
27
28
|
},
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
export default meta;
|
|
32
|
+
|
|
31
33
|
type Story = StoryObj<typeof AssistiveElement>;
|
|
32
34
|
|
|
33
|
-
export const
|
|
34
|
-
|
|
35
|
+
export const DefaultHelp: Story = {
|
|
36
|
+
args: {
|
|
37
|
+
children:
|
|
38
|
+
"This is a standard assistive layout explaining specific configurations.",
|
|
39
|
+
assistiveVariant: "help",
|
|
40
|
+
assistiveWithIcon: true,
|
|
41
|
+
},
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
43
|
+
render: ({ ...args }: any) => (
|
|
44
|
+
<div style={{ padding: "48px" }}>
|
|
45
|
+
<AssistiveElement {...args} />
|
|
46
|
+
</div>
|
|
47
|
+
),
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const ErrorState: Story = {
|
|
51
|
+
args: {
|
|
52
|
+
children:
|
|
53
|
+
"Invalid property. You must satisfy the constraints outlined above.",
|
|
54
|
+
assistiveVariant: "error",
|
|
55
|
+
assistiveWithIcon: true,
|
|
56
|
+
},
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
58
|
+
render: ({ ...args }: any) => (
|
|
59
|
+
<div style={{ padding: "48px" }}>
|
|
60
|
+
<AssistiveElement {...args} />
|
|
61
|
+
</div>
|
|
62
|
+
),
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const NoIconHelp: Story = {
|
|
66
|
+
args: {
|
|
67
|
+
children:
|
|
68
|
+
"Fallback textual representation without visual injection targets.",
|
|
69
|
+
assistiveVariant: "help",
|
|
70
|
+
assistiveWithIcon: false,
|
|
71
|
+
},
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
73
|
+
render: ({ ...args }: any) => (
|
|
74
|
+
<div style={{ padding: "48px" }}>
|
|
75
|
+
<AssistiveElement {...args} />
|
|
76
|
+
</div>
|
|
77
|
+
),
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const Docs: Story = {
|
|
81
|
+
args: {
|
|
82
|
+
children: "Docs explicitly mapped configuration.",
|
|
83
|
+
assistiveVariant: "help",
|
|
84
|
+
assistiveWithIcon: true,
|
|
85
|
+
},
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
87
|
+
render: ({ ...args }: any) => (
|
|
88
|
+
<div style={{ padding: "48px" }}>
|
|
89
|
+
<AssistiveElement {...args} />
|
|
90
|
+
</div>
|
|
91
|
+
),
|
|
35
92
|
};
|
|
@@ -1,7 +1,88 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { FormHelperText, type FormHelperTextProps } from "@mui/material";
|
|
3
|
+
import { filterStylingProps } from "../../utils/filterStylingProps";
|
|
4
|
+
import styles from "./AssistiveElement.module.css";
|
|
2
5
|
|
|
3
|
-
export
|
|
6
|
+
export interface AssistiveElementProps extends FormHelperTextProps {
|
|
7
|
+
/** Governs the semantic rendering block (changes icon and CSS structural hooks natively). */
|
|
8
|
+
assistiveVariant?: "help" | "error";
|
|
9
|
+
/** Renders the structural mapping icon inline beside the text natively. */
|
|
10
|
+
assistiveWithIcon?: boolean;
|
|
11
|
+
overStyled?: boolean;
|
|
12
|
+
}
|
|
4
13
|
|
|
5
|
-
export const AssistiveElement
|
|
6
|
-
|
|
7
|
-
|
|
14
|
+
export const AssistiveElement = React.forwardRef<
|
|
15
|
+
HTMLParagraphElement,
|
|
16
|
+
AssistiveElementProps
|
|
17
|
+
>(function AssistiveElement(props, ref) {
|
|
18
|
+
const {
|
|
19
|
+
assistiveVariant = "help",
|
|
20
|
+
assistiveWithIcon = true,
|
|
21
|
+
overStyled = false,
|
|
22
|
+
className,
|
|
23
|
+
children,
|
|
24
|
+
...rest
|
|
25
|
+
} = props;
|
|
26
|
+
|
|
27
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
28
|
+
|
|
29
|
+
const HelpIcon = () => (
|
|
30
|
+
<svg
|
|
31
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
32
|
+
width="24"
|
|
33
|
+
height="24"
|
|
34
|
+
viewBox="0 0 24 24"
|
|
35
|
+
fill="none"
|
|
36
|
+
stroke="currentColor"
|
|
37
|
+
strokeWidth="2"
|
|
38
|
+
strokeLinecap="round"
|
|
39
|
+
strokeLinejoin="round"
|
|
40
|
+
>
|
|
41
|
+
<circle cx="12" cy="12" r="10"></circle>
|
|
42
|
+
<line x1="12" y1="16" x2="12" y2="12"></line>
|
|
43
|
+
<line x1="12" y1="8" x2="12.01" y2="8"></line>
|
|
44
|
+
</svg>
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const ErrorIcon = () => (
|
|
48
|
+
<svg
|
|
49
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
50
|
+
width="24"
|
|
51
|
+
height="24"
|
|
52
|
+
viewBox="0 0 24 24"
|
|
53
|
+
fill="none"
|
|
54
|
+
stroke="currentColor"
|
|
55
|
+
strokeWidth="2"
|
|
56
|
+
strokeLinecap="round"
|
|
57
|
+
strokeLinejoin="round"
|
|
58
|
+
>
|
|
59
|
+
<circle cx="12" cy="12" r="10"></circle>
|
|
60
|
+
<line x1="12" y1="8" x2="12" y2="12"></line>
|
|
61
|
+
<line x1="12" y1="16" x2="12.01" y2="16"></line>
|
|
62
|
+
</svg>
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// Map to MUI's native error prop if it's explicitly an error state
|
|
66
|
+
const isError = assistiveVariant === "error";
|
|
67
|
+
|
|
68
|
+
// Force component = "div" so flex layouts execute correctly inside HelperText
|
|
69
|
+
return (
|
|
70
|
+
<FormHelperText
|
|
71
|
+
ref={ref}
|
|
72
|
+
component="div"
|
|
73
|
+
error={isError}
|
|
74
|
+
data-variant={assistiveVariant}
|
|
75
|
+
className={className ? `${styles.root} ${className}` : styles.root}
|
|
76
|
+
{...(sanitizedProps as FormHelperTextProps)}
|
|
77
|
+
>
|
|
78
|
+
{assistiveWithIcon && (
|
|
79
|
+
<div className={styles.icon}>
|
|
80
|
+
{assistiveVariant === "error" ? <ErrorIcon /> : <HelpIcon />}
|
|
81
|
+
</div>
|
|
82
|
+
)}
|
|
83
|
+
<div className={styles.text}>{children}</div>
|
|
84
|
+
</FormHelperText>
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
AssistiveElement.displayName = "AssistiveElement";
|