@recursica/mui-adapter 0.5.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 +15 -0
- package/SETUP.md +77 -0
- package/USAGE.md +55 -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 +6863 -205
- package/dist/mui-adapter.js.map +1 -1
- package/dist/src/components/Accordion/Accordion.d.ts +43 -2
- package/dist/src/components/AssistiveElement/AssistiveElement.d.ts +6 -2
- package/dist/src/components/Autocomplete/Autocomplete.d.ts +12 -2
- package/dist/src/components/Avatar/Avatar.d.ts +10 -3
- package/dist/src/components/Badge/Badge.d.ts +10 -3
- package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +9 -3
- package/dist/src/components/Button/Button.d.ts +2 -17
- package/dist/src/components/Card/Card.d.ts +38 -3
- package/dist/src/components/Checkbox/Checkbox.d.ts +13 -2
- package/dist/src/components/Checkbox/CheckboxGroup.d.ts +18 -0
- package/dist/src/components/Checkbox/index.d.ts +5 -1
- package/dist/src/components/Chip/Chip.d.ts +9 -2
- 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 +12 -2
- package/dist/src/components/Flex/Flex.d.ts +2 -22
- package/dist/src/components/FormControlLayout/FormControlLayout.d.ts +5 -2
- package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +9 -2
- package/dist/src/components/Group/Group.d.ts +2 -7
- package/dist/src/components/HoverCard/HoverCard.d.ts +28 -2
- package/dist/src/components/Label/Label.d.ts +6 -2
- 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 +25 -3
- package/dist/src/components/Modal/Modal.d.ts +37 -2
- package/dist/src/components/NumberInput/NumberInput.d.ts +12 -2
- package/dist/src/components/Pagination/Pagination.d.ts +12 -3
- package/dist/src/components/Pagination/Pagination.icons.d.ts +8 -0
- package/dist/src/components/Panel/Panel.d.ts +52 -3
- package/dist/src/components/Radio/Radio.d.ts +13 -3
- package/dist/src/components/Radio/RadioGroup.d.ts +9 -0
- package/dist/src/components/ReadOnlyField/ReadOnlyBooleanField.d.ts +5 -0
- package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +4 -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 +21 -3
- package/dist/src/components/Slider/Slider.d.ts +18 -2
- package/dist/src/components/Stack/Stack.d.ts +2 -5
- package/dist/src/components/Stepper/Stepper.d.ts +41 -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/Table/Table.d.ts +2 -1
- package/dist/src/components/Tabs/Tabs.d.ts +20 -3
- package/dist/src/components/Text/Text.d.ts +2 -16
- package/dist/src/components/TextArea/TextArea.d.ts +12 -2
- package/dist/src/components/TextField/TextField.d.ts +12 -2
- package/dist/src/components/TimePicker/TimePicker.d.ts +2 -1
- package/dist/src/components/Timeline/Timeline.d.ts +15 -2
- package/dist/src/components/Timeline/TimelineItem.d.ts +18 -0
- package/dist/src/components/Title/Title.d.ts +2 -15
- package/dist/src/components/Toast/Toast.d.ts +20 -2
- package/dist/src/components/Tooltip/Tooltip.d.ts +28 -3
- 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 +14 -3
- package/src/components/Accordion/Accordion.module.css +294 -56
- package/src/components/Accordion/Accordion.stories.tsx +131 -21
- package/src/components/Accordion/Accordion.tsx +260 -5
- package/src/components/AssistiveElement/AssistiveElement.module.css +114 -20
- package/src/components/AssistiveElement/AssistiveElement.stories.tsx +60 -20
- package/src/components/AssistiveElement/AssistiveElement.tsx +81 -5
- package/src/components/Autocomplete/Autocomplete.module.css +319 -42
- package/src/components/Autocomplete/Autocomplete.stories.tsx +175 -23
- package/src/components/Autocomplete/Autocomplete.tsx +181 -6
- package/src/components/Avatar/Avatar.module.css +343 -73
- package/src/components/Avatar/Avatar.stories.tsx +94 -22
- package/src/components/Avatar/Avatar.tsx +99 -6
- package/src/components/Badge/Badge.module.css +127 -29
- package/src/components/Badge/Badge.stories.tsx +65 -22
- package/src/components/Badge/Badge.tsx +67 -6
- package/src/components/Breadcrumb/Breadcrumb.module.css +25 -5
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +57 -22
- package/src/components/Breadcrumb/Breadcrumb.tsx +59 -6
- 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 +154 -38
- package/src/components/Card/Card.stories.tsx +117 -19
- package/src/components/Card/Card.tsx +181 -5
- package/src/components/Checkbox/Checkbox.module.css +249 -39
- package/src/components/Checkbox/Checkbox.stories.tsx +81 -19
- package/src/components/Checkbox/Checkbox.tsx +246 -5
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +137 -0
- package/src/components/Checkbox/index.ts +6 -1
- package/src/components/Chip/Chip.module.css +246 -43
- package/src/components/Chip/Chip.stories.tsx +101 -21
- package/src/components/Chip/Chip.tsx +136 -6
- 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.module.css +291 -41
- package/src/components/Dropdown/Dropdown.stories.tsx +80 -21
- package/src/components/Dropdown/Dropdown.tsx +180 -6
- 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.module.css +92 -0
- package/src/components/FormControlLayout/FormControlLayout.stories.tsx +67 -20
- package/src/components/FormControlLayout/FormControlLayout.tsx +69 -4
- package/src/components/FormControlWrapper/FormControlWrapper.module.css +87 -0
- package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +116 -22
- package/src/components/FormControlWrapper/FormControlWrapper.tsx +126 -6
- package/src/components/Group/Group.stories.tsx +6 -30
- package/src/components/Group/Group.tsx +14 -9
- package/src/components/HoverCard/HoverCard.module.css +90 -22
- package/src/components/HoverCard/HoverCard.stories.tsx +158 -21
- package/src/components/HoverCard/HoverCard.tsx +147 -5
- package/src/components/Label/Label.module.css +140 -35
- package/src/components/Label/Label.stories.tsx +108 -21
- package/src/components/Label/Label.tsx +82 -5
- 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.module.css +285 -51
- package/src/components/Menu/Menu.stories.tsx +229 -25
- package/src/components/Menu/Menu.tsx +73 -6
- package/src/components/Modal/Modal.module.css +171 -35
- package/src/components/Modal/Modal.stories.tsx +66 -22
- package/src/components/Modal/Modal.tsx +215 -5
- package/src/components/NumberInput/NumberInput.module.css +276 -42
- package/src/components/NumberInput/NumberInput.stories.tsx +83 -20
- package/src/components/NumberInput/NumberInput.tsx +136 -6
- package/src/components/Pagination/IMPLEMENTATION_NOTES.md +3 -0
- package/src/components/Pagination/Pagination.icons.tsx +66 -0
- package/src/components/Pagination/Pagination.module.css +234 -20
- package/src/components/Pagination/Pagination.stories.tsx +34 -21
- package/src/components/Pagination/Pagination.tsx +74 -6
- package/src/components/Panel/Panel.module.css +206 -38
- package/src/components/Panel/Panel.stories.tsx +214 -22
- package/src/components/Panel/Panel.tsx +130 -5
- package/src/components/Radio/Radio.module.css +235 -37
- package/src/components/Radio/Radio.stories.tsx +77 -19
- package/src/components/Radio/Radio.tsx +210 -5
- package/src/components/Radio/RadioGroup.stories.tsx +117 -0
- package/src/components/Radio/RadioGroup.tsx +125 -0
- package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
- package/src/components/ReadOnlyField/ReadOnlyField.module.css +53 -15
- package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +147 -19
- package/src/components/ReadOnlyField/ReadOnlyField.tsx +105 -5
- 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 +179 -47
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +102 -20
- package/src/components/SegmentedControl/SegmentedControl.tsx +140 -6
- package/src/components/Slider/Slider.module.css +539 -86
- package/src/components/Slider/Slider.stories.tsx +157 -19
- package/src/components/Slider/Slider.tsx +283 -5
- 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.module.css +410 -71
- package/src/components/Stepper/Stepper.stories.tsx +146 -20
- package/src/components/Stepper/Stepper.tsx +147 -6
- package/src/components/Switch/Switch.module.css +259 -39
- package/src/components/Switch/Switch.stories.tsx +98 -19
- package/src/components/Switch/Switch.tsx +200 -6
- package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
- package/src/components/Switch/SwitchGroup.tsx +120 -0
- 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.module.css +422 -79
- package/src/components/Tabs/Tabs.stories.tsx +156 -20
- package/src/components/Tabs/Tabs.tsx +86 -6
- package/src/components/Text/Text.stories.tsx +5 -17
- package/src/components/Text/Text.tsx +1 -15
- package/src/components/TextArea/TextArea.module.css +155 -32
- package/src/components/TextArea/TextArea.stories.tsx +80 -21
- package/src/components/TextArea/TextArea.tsx +146 -6
- package/src/components/TextField/TextField.module.css +261 -42
- package/src/components/TextField/TextField.stories.tsx +147 -20
- package/src/components/TextField/TextField.tsx +169 -6
- package/src/components/TimePicker/TimePicker.stories.tsx +2 -19
- package/src/components/TimePicker/TimePicker.tsx +3 -1
- package/src/components/Timeline/Timeline.module.css +365 -76
- package/src/components/Timeline/Timeline.stories.tsx +114 -21
- package/src/components/Timeline/Timeline.tsx +83 -5
- package/src/components/Timeline/TimelineItem.tsx +90 -0
- package/src/components/Title/Title.stories.tsx +0 -18
- package/src/components/Title/Title.tsx +1 -7
- package/src/components/Toast/Toast.module.css +166 -28
- package/src/components/Toast/Toast.stories.tsx +54 -22
- package/src/components/Toast/Toast.tsx +124 -5
- package/src/components/Tooltip/Tooltip.module.css +89 -24
- package/src/components/Tooltip/Tooltip.stories.tsx +152 -22
- package/src/components/Tooltip/Tooltip.tsx +88 -5
- 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
|
@@ -1,8 +1,263 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import
|
|
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";
|
|
3
15
|
|
|
4
|
-
|
|
16
|
+
import {
|
|
17
|
+
type RecursicaAccordionProps,
|
|
18
|
+
type RecursicaAccordionItemProps,
|
|
19
|
+
type RecursicaAccordionControlProps,
|
|
20
|
+
} from "@recursica/adapter-common";
|
|
5
21
|
|
|
6
|
-
|
|
7
|
-
|
|
22
|
+
const ChevronIcon = () => (
|
|
23
|
+
<svg
|
|
24
|
+
viewBox="0 0 24 24"
|
|
25
|
+
fill="none"
|
|
26
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
27
|
+
stroke="currentColor"
|
|
28
|
+
strokeWidth="2"
|
|
29
|
+
strokeLinecap="round"
|
|
30
|
+
strokeLinejoin="round"
|
|
31
|
+
style={{ width: "100%", height: "100%" }}
|
|
32
|
+
>
|
|
33
|
+
<polyline points="6 9 12 15 18 9"></polyline>
|
|
34
|
+
</svg>
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const AccordionContext = createContext<{
|
|
38
|
+
value: string | string[] | null;
|
|
39
|
+
onChange: (val: string) => void;
|
|
40
|
+
} | null>(null);
|
|
41
|
+
|
|
42
|
+
// ==== ACCORDION CONTAINER ====
|
|
43
|
+
export type AccordionProps = RecursicaOverStyled<
|
|
44
|
+
React.HTMLAttributes<HTMLDivElement> & RecursicaAccordionProps
|
|
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
|
+
export type AccordionItemWrapperProps = RecursicaOverStyled<
|
|
110
|
+
Omit<MuiAccordionProps, "children" | "value"> & {
|
|
111
|
+
children?: React.ReactNode;
|
|
112
|
+
value: string;
|
|
113
|
+
} & RecursicaAccordionItemProps
|
|
114
|
+
>;
|
|
115
|
+
|
|
116
|
+
export const AccordionItem = forwardRef<
|
|
117
|
+
HTMLDivElement,
|
|
118
|
+
AccordionItemWrapperProps
|
|
119
|
+
>(function AccordionItem(
|
|
120
|
+
{
|
|
121
|
+
title,
|
|
122
|
+
leftIcon,
|
|
123
|
+
divider = true,
|
|
124
|
+
children,
|
|
125
|
+
value,
|
|
126
|
+
overStyled = false,
|
|
127
|
+
style,
|
|
128
|
+
...rest
|
|
129
|
+
},
|
|
130
|
+
ref,
|
|
131
|
+
) {
|
|
132
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
133
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
134
|
+
.className as string | undefined;
|
|
135
|
+
|
|
136
|
+
const finalClass =
|
|
137
|
+
[styles.item, divider ? undefined : styles.noDivider, classNameProp]
|
|
138
|
+
.filter(Boolean)
|
|
139
|
+
.join(" ") || undefined;
|
|
140
|
+
|
|
141
|
+
const ctx = useContext(AccordionContext);
|
|
142
|
+
const isExpanded = ctx
|
|
143
|
+
? Array.isArray(ctx.value)
|
|
144
|
+
? ctx.value.includes(value)
|
|
145
|
+
: ctx.value === value
|
|
146
|
+
: undefined;
|
|
147
|
+
|
|
148
|
+
const handleChange = () => {
|
|
149
|
+
ctx?.onChange(value);
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// background-color: transparent allows Layer overrides to naturally penetrate
|
|
153
|
+
const mergedStyle = { backgroundColor: "transparent", ...style };
|
|
154
|
+
|
|
155
|
+
return (
|
|
156
|
+
<MuiAccordion
|
|
157
|
+
ref={ref}
|
|
158
|
+
className={finalClass}
|
|
159
|
+
disableGutters
|
|
160
|
+
elevation={0}
|
|
161
|
+
square
|
|
162
|
+
expanded={isExpanded}
|
|
163
|
+
onChange={handleChange}
|
|
164
|
+
style={mergedStyle}
|
|
165
|
+
{...(sanitizedProps as unknown as Omit<
|
|
166
|
+
MuiAccordionProps,
|
|
167
|
+
"expanded" | "onChange"
|
|
168
|
+
>)}
|
|
169
|
+
>
|
|
170
|
+
{
|
|
171
|
+
(title ? (
|
|
172
|
+
<>
|
|
173
|
+
<AccordionControl leftIcon={leftIcon}>{title}</AccordionControl>
|
|
174
|
+
<AccordionPanel>{children}</AccordionPanel>
|
|
175
|
+
</>
|
|
176
|
+
) : (
|
|
177
|
+
children
|
|
178
|
+
)) as any
|
|
179
|
+
}
|
|
180
|
+
</MuiAccordion>
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
AccordionItem.displayName = "AccordionItem";
|
|
184
|
+
|
|
185
|
+
// ==== ACCORDION CONTROL ====
|
|
186
|
+
export type AccordionControlWrapperProps = RecursicaOverStyled<
|
|
187
|
+
MuiAccordionSummaryProps & RecursicaAccordionControlProps
|
|
188
|
+
>;
|
|
189
|
+
|
|
190
|
+
export const AccordionControl = forwardRef<
|
|
191
|
+
HTMLDivElement,
|
|
192
|
+
AccordionControlWrapperProps
|
|
193
|
+
>(function AccordionControl(
|
|
194
|
+
{ leftIcon, children, overStyled = false, ...rest },
|
|
195
|
+
ref,
|
|
196
|
+
) {
|
|
197
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
198
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
199
|
+
.className as string | undefined;
|
|
200
|
+
|
|
201
|
+
const finalClass =
|
|
202
|
+
[styles.control, classNameProp].filter(Boolean).join(" ") || undefined;
|
|
203
|
+
|
|
204
|
+
return (
|
|
205
|
+
<MuiAccordionSummary
|
|
206
|
+
ref={ref}
|
|
207
|
+
className={finalClass}
|
|
208
|
+
expandIcon={
|
|
209
|
+
<span className={styles.chevron}>
|
|
210
|
+
<ChevronIcon />
|
|
211
|
+
</span>
|
|
212
|
+
}
|
|
213
|
+
{...(sanitizedProps as unknown as MuiAccordionSummaryProps)}
|
|
214
|
+
>
|
|
215
|
+
{leftIcon && (
|
|
216
|
+
<span className={styles.iconLeftWrapper} aria-hidden>
|
|
217
|
+
{leftIcon}
|
|
218
|
+
</span>
|
|
219
|
+
)}
|
|
220
|
+
<div className={styles.label}>{children}</div>
|
|
221
|
+
</MuiAccordionSummary>
|
|
222
|
+
);
|
|
223
|
+
});
|
|
224
|
+
AccordionControl.displayName = "AccordionControl";
|
|
225
|
+
|
|
226
|
+
// ==== ACCORDION PANEL ====
|
|
227
|
+
export type AccordionPanelWrapperProps =
|
|
228
|
+
RecursicaOverStyled<MuiAccordionDetailsProps>;
|
|
229
|
+
|
|
230
|
+
export const AccordionPanel = forwardRef<
|
|
231
|
+
HTMLDivElement,
|
|
232
|
+
AccordionPanelWrapperProps
|
|
233
|
+
>(function AccordionPanel({ overStyled = false, children, ...rest }, ref) {
|
|
234
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
235
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
236
|
+
.className as string | undefined;
|
|
237
|
+
|
|
238
|
+
const finalClass =
|
|
239
|
+
[styles.panel, classNameProp].filter(Boolean).join(" ") || undefined;
|
|
240
|
+
|
|
241
|
+
return (
|
|
242
|
+
<MuiAccordionDetails
|
|
243
|
+
ref={ref}
|
|
244
|
+
className={finalClass}
|
|
245
|
+
{...(sanitizedProps as unknown as MuiAccordionDetailsProps)}
|
|
246
|
+
>
|
|
247
|
+
<div className={styles.content}>{children}</div>
|
|
248
|
+
</MuiAccordionDetails>
|
|
249
|
+
);
|
|
250
|
+
});
|
|
251
|
+
AccordionPanel.displayName = "AccordionPanel";
|
|
252
|
+
|
|
253
|
+
// ==== DOT NOTATION EXPORT ====
|
|
254
|
+
type AccordionComponent = typeof AccordionBase & {
|
|
255
|
+
Item: typeof AccordionItem;
|
|
256
|
+
Control: typeof AccordionControl;
|
|
257
|
+
Panel: typeof AccordionPanel;
|
|
8
258
|
};
|
|
259
|
+
|
|
260
|
+
export const Accordion = AccordionBase as AccordionComponent;
|
|
261
|
+
Accordion.Item = AccordionItem;
|
|
262
|
+
Accordion.Control = AccordionControl;
|
|
263
|
+
Accordion.Panel = AccordionPanel;
|
|
@@ -1,20 +1,114 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
/*
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/*
|
|
11
|
-
/*
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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 !important;
|
|
9
|
+
align-items: flex-start !important; /* Forces the icon to align with the first line of text */
|
|
10
|
+
margin: 0 !important; /* HARDCODE: structural reset */
|
|
11
|
+
padding: 0 !important; /* HARDCODE: structural reset */
|
|
12
|
+
width: 100%;
|
|
13
|
+
|
|
14
|
+
gap: var(
|
|
15
|
+
--recursica_ui-kit_components_assistive-element_properties_icon-text-gap
|
|
16
|
+
);
|
|
17
|
+
margin-top: var(
|
|
18
|
+
--recursica_ui-kit_components_assistive-element_properties_top-margin
|
|
19
|
+
) !important;
|
|
20
|
+
max-width: var(
|
|
21
|
+
--recursica_ui-kit_components_assistive-element_properties_max-width
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
font-family: var(
|
|
25
|
+
--recursica_ui-kit_components_assistive-element_properties_text_font-family
|
|
26
|
+
);
|
|
27
|
+
font-size: var(
|
|
28
|
+
--recursica_ui-kit_components_assistive-element_properties_text_font-size
|
|
29
|
+
);
|
|
30
|
+
font-style: var(
|
|
31
|
+
--recursica_ui-kit_components_assistive-element_properties_text_font-style
|
|
32
|
+
);
|
|
33
|
+
font-weight: var(
|
|
34
|
+
--recursica_ui-kit_components_assistive-element_properties_text_font-weight
|
|
35
|
+
);
|
|
36
|
+
letter-spacing: var(
|
|
37
|
+
--recursica_ui-kit_components_assistive-element_properties_text_letter-spacing
|
|
38
|
+
);
|
|
39
|
+
line-height: var(
|
|
40
|
+
--recursica_ui-kit_components_assistive-element_properties_text_line-height
|
|
41
|
+
);
|
|
42
|
+
text-decoration: var(
|
|
43
|
+
--recursica_ui-kit_components_assistive-element_properties_text_text-decoration
|
|
44
|
+
);
|
|
45
|
+
text-transform: var(
|
|
46
|
+
--recursica_ui-kit_components_assistive-element_properties_text_text-transform
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.text {
|
|
51
|
+
overflow-wrap: break-word;
|
|
52
|
+
white-space: normal;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* Base Icon Architecture */
|
|
56
|
+
.icon {
|
|
57
|
+
flex-shrink: 0 !important; /* Prevent squishing */
|
|
58
|
+
display: flex !important;
|
|
59
|
+
align-items: center !important;
|
|
60
|
+
justify-content: center !important;
|
|
61
|
+
|
|
62
|
+
width: var(
|
|
63
|
+
--recursica_ui-kit_components_assistive-element_properties_icon-size
|
|
64
|
+
) !important;
|
|
65
|
+
height: calc(
|
|
66
|
+
var(
|
|
67
|
+
--recursica_ui-kit_components_assistive-element_properties_text_line-height
|
|
68
|
+
) *
|
|
69
|
+
var(
|
|
70
|
+
--recursica_ui-kit_components_assistive-element_properties_text_font-size
|
|
71
|
+
)
|
|
72
|
+
) !important; /* Forces exact centering bounds within the first text line vertically */
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.icon :global(svg) {
|
|
76
|
+
width: var(
|
|
77
|
+
--recursica_ui-kit_components_assistive-element_properties_icon-size
|
|
78
|
+
) !important;
|
|
79
|
+
height: var(
|
|
80
|
+
--recursica_ui-kit_components_assistive-element_properties_icon-size
|
|
81
|
+
) !important;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* =========================================
|
|
85
|
+
VARIANTS: Default / Help
|
|
86
|
+
========================================= */
|
|
87
|
+
|
|
88
|
+
.root[data-variant="help"] {
|
|
89
|
+
color: var(
|
|
90
|
+
--recursica_ui-kit_components_assistive-element_variants_types_help_properties_colors_text-color
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.root[data-variant="help"] .icon {
|
|
95
|
+
color: var(
|
|
96
|
+
--recursica_ui-kit_components_assistive-element_variants_types_help_properties_colors_icon-color
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* =========================================
|
|
101
|
+
VARIANTS: Error
|
|
102
|
+
========================================= */
|
|
103
|
+
|
|
104
|
+
.root[data-variant="error"] {
|
|
105
|
+
color: var(
|
|
106
|
+
--recursica_ui-kit_components_assistive-element_variants_types_error_properties_colors_text-color
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.root[data-variant="error"] .icon {
|
|
111
|
+
color: var(
|
|
112
|
+
--recursica_ui-kit_components_assistive-element_variants_types_error_properties_colors_icon-color
|
|
113
|
+
);
|
|
114
|
+
}
|
|
@@ -1,35 +1,75 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
2
|
import { AssistiveElement } from "./AssistiveElement";
|
|
3
|
-
import {
|
|
3
|
+
import { Layer } from "@recursica/adapter-common";
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"checked",
|
|
25
|
-
],
|
|
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
|
+
},
|
|
16
|
+
},
|
|
17
|
+
argTypes: {
|
|
18
|
+
assistiveVariant: {
|
|
19
|
+
control: "radio",
|
|
20
|
+
options: ["help", "error"],
|
|
21
|
+
},
|
|
22
|
+
assistiveWithIcon: {
|
|
23
|
+
control: "boolean",
|
|
26
24
|
},
|
|
27
25
|
},
|
|
28
26
|
};
|
|
29
27
|
|
|
30
28
|
export default meta;
|
|
29
|
+
|
|
31
30
|
type Story = StoryObj<typeof AssistiveElement>;
|
|
32
31
|
|
|
33
|
-
export const
|
|
34
|
-
|
|
32
|
+
export const DefaultHelp: Story = {
|
|
33
|
+
args: {
|
|
34
|
+
children:
|
|
35
|
+
"This is a standard assistive layout explaining specific configurations.",
|
|
36
|
+
assistiveVariant: "help",
|
|
37
|
+
assistiveWithIcon: true,
|
|
38
|
+
},
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
40
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
41
|
+
<Layer layer={0} style={{ padding: "48px" }}>
|
|
42
|
+
<AssistiveElement {...args} />
|
|
43
|
+
</Layer>
|
|
44
|
+
),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const ErrorState: Story = {
|
|
48
|
+
args: {
|
|
49
|
+
children:
|
|
50
|
+
"Invalid property. You must satisfy the constraints outlined above.",
|
|
51
|
+
assistiveVariant: "error",
|
|
52
|
+
assistiveWithIcon: true,
|
|
53
|
+
},
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
55
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
56
|
+
<Layer layer={0} style={{ padding: "48px" }}>
|
|
57
|
+
<AssistiveElement {...args} />
|
|
58
|
+
</Layer>
|
|
59
|
+
),
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const NoIconHelp: Story = {
|
|
63
|
+
args: {
|
|
64
|
+
children:
|
|
65
|
+
"Fallback textual representation without visual injection targets.",
|
|
66
|
+
assistiveVariant: "help",
|
|
67
|
+
assistiveWithIcon: false,
|
|
68
|
+
},
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
70
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
71
|
+
<Layer layer={0} style={{ padding: "48px" }}>
|
|
72
|
+
<AssistiveElement {...args} />
|
|
73
|
+
</Layer>
|
|
74
|
+
),
|
|
35
75
|
};
|
|
@@ -1,8 +1,84 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import "
|
|
2
|
+
import { FormHelperText, type FormHelperTextProps } from "@mui/material";
|
|
3
|
+
import { filterStylingProps } from "../../utils/filterStylingProps";
|
|
4
|
+
import styles from "./AssistiveElement.module.css";
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
import { type RecursicaAssistiveElementProps } from "@recursica/adapter-common";
|
|
5
7
|
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
export interface AssistiveElementProps
|
|
9
|
+
extends FormHelperTextProps,
|
|
10
|
+
RecursicaAssistiveElementProps {
|
|
11
|
+
overStyled?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
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
|
+
viewBox="0 0 24 24"
|
|
33
|
+
fill="none"
|
|
34
|
+
stroke="currentColor"
|
|
35
|
+
strokeWidth="2"
|
|
36
|
+
strokeLinecap="round"
|
|
37
|
+
strokeLinejoin="round"
|
|
38
|
+
>
|
|
39
|
+
<circle cx="12" cy="12" r="10" />
|
|
40
|
+
<path d="M12 16v-4" />
|
|
41
|
+
<path d="M12 8h.01" />
|
|
42
|
+
</svg>
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const ErrorIcon = () => (
|
|
46
|
+
<svg
|
|
47
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
48
|
+
viewBox="0 0 24 24"
|
|
49
|
+
fill="none"
|
|
50
|
+
stroke="currentColor"
|
|
51
|
+
strokeWidth="2"
|
|
52
|
+
strokeLinecap="round"
|
|
53
|
+
strokeLinejoin="round"
|
|
54
|
+
>
|
|
55
|
+
<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z" />
|
|
56
|
+
<path d="M12 9v4" />
|
|
57
|
+
<path d="M12 17h.01" />
|
|
58
|
+
</svg>
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
// Map to MUI's native error prop if it's explicitly an error state
|
|
62
|
+
const isError = assistiveVariant === "error";
|
|
63
|
+
|
|
64
|
+
// Force component = "div" so flex layouts execute correctly inside HelperText
|
|
65
|
+
return (
|
|
66
|
+
<FormHelperText
|
|
67
|
+
ref={ref}
|
|
68
|
+
component="div"
|
|
69
|
+
error={isError}
|
|
70
|
+
data-variant={assistiveVariant}
|
|
71
|
+
className={className ? `${styles.root} ${className}` : styles.root}
|
|
72
|
+
{...(sanitizedProps as FormHelperTextProps)}
|
|
73
|
+
>
|
|
74
|
+
{assistiveWithIcon && (
|
|
75
|
+
<div className={styles.icon}>
|
|
76
|
+
{assistiveVariant === "error" ? <ErrorIcon /> : <HelpIcon />}
|
|
77
|
+
</div>
|
|
78
|
+
)}
|
|
79
|
+
<div className={styles.text}>{children}</div>
|
|
80
|
+
</FormHelperText>
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
AssistiveElement.displayName = "AssistiveElement";
|