@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
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import React from "react";
|
|
3
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
4
3
|
import { ReadOnlyField } from "./ReadOnlyField";
|
|
5
4
|
import { EmptyValueRenderer } from "@recursica/adapter-common";
|
|
6
|
-
import { formControlArgTypes } from "../../../.storybook/commonArgTypes";
|
|
7
5
|
|
|
8
6
|
const meta: Meta<typeof ReadOnlyField> = {
|
|
9
|
-
title: "UI
|
|
7
|
+
title: "UI Kit/ReadOnlyField",
|
|
10
8
|
component: ReadOnlyField,
|
|
11
9
|
tags: ["autodocs"],
|
|
12
10
|
parameters: {
|
|
@@ -16,17 +14,6 @@ const meta: Meta<typeof ReadOnlyField> = {
|
|
|
16
14
|
"The ReadOnlyField safely natively wraps data sets bypassing active HTML interaction hooks while natively retaining exact bounding visual layouts defined by internal Design System Tokens. Useful for creating strict data-review profiles or conditional form read-overs.",
|
|
17
15
|
},
|
|
18
16
|
},
|
|
19
|
-
controls: {
|
|
20
|
-
include: [
|
|
21
|
-
"type",
|
|
22
|
-
"labelWithEditIcon",
|
|
23
|
-
"formLayout",
|
|
24
|
-
"labelSize",
|
|
25
|
-
"labelAlignment",
|
|
26
|
-
"labelOptionalText",
|
|
27
|
-
"required",
|
|
28
|
-
],
|
|
29
|
-
},
|
|
30
17
|
},
|
|
31
18
|
args: {
|
|
32
19
|
label: "Read Only Label",
|
|
@@ -35,14 +22,14 @@ const meta: Meta<typeof ReadOnlyField> = {
|
|
|
35
22
|
type: "text",
|
|
36
23
|
},
|
|
37
24
|
argTypes: {
|
|
38
|
-
...formControlArgTypes,
|
|
39
25
|
type: {
|
|
40
26
|
control: "select",
|
|
41
|
-
options: ["text", "number"
|
|
27
|
+
options: ["text", "number"], // Add more as we support them
|
|
42
28
|
},
|
|
43
29
|
labelWithEditIcon: {
|
|
44
30
|
control: "boolean",
|
|
45
31
|
},
|
|
32
|
+
// We cannot natively control a React.ElementType through standard primitive storybook panels.
|
|
46
33
|
},
|
|
47
34
|
};
|
|
48
35
|
|
|
@@ -55,7 +42,6 @@ type Story = StoryObj<typeof ReadOnlyField>;
|
|
|
55
42
|
*/
|
|
56
43
|
export const Default: Story = {
|
|
57
44
|
args: {},
|
|
58
|
-
render: ({ ...args }: any) => <ReadOnlyField {...args} />,
|
|
59
45
|
};
|
|
60
46
|
|
|
61
47
|
/**
|
|
@@ -66,7 +52,6 @@ export const EmptyValue: Story = {
|
|
|
66
52
|
value: "",
|
|
67
53
|
label: "Empty String Evaluated Automatically (Default 'N/A')",
|
|
68
54
|
},
|
|
69
|
-
render: ({ ...args }: any) => <ReadOnlyField {...args} />,
|
|
70
55
|
};
|
|
71
56
|
|
|
72
57
|
const CustomEmptyTextRenderer: React.FC<{ value?: any }> & {
|
|
@@ -83,7 +68,6 @@ export const CustomEmptyText: Story = {
|
|
|
83
68
|
label: "Custom Empty Text Default",
|
|
84
69
|
emptyValueComponent: CustomEmptyTextRenderer,
|
|
85
70
|
},
|
|
86
|
-
render: ({ ...args }: any) => <ReadOnlyField {...args} />,
|
|
87
71
|
};
|
|
88
72
|
|
|
89
73
|
const CustomEmptyCheckRenderer: React.FC<{ value?: any }> & {
|
|
@@ -102,7 +86,6 @@ export const CustomEmptyRenderer: Story = {
|
|
|
102
86
|
label: "Custom Logic Evaluation Binding",
|
|
103
87
|
emptyValueComponent: CustomEmptyCheckRenderer,
|
|
104
88
|
},
|
|
105
|
-
render: ({ ...args }: any) => <ReadOnlyField {...args} />,
|
|
106
89
|
};
|
|
107
90
|
|
|
108
91
|
/**
|
|
@@ -113,7 +96,6 @@ export const StackedDefault: Story = {
|
|
|
113
96
|
formLayout: "stacked",
|
|
114
97
|
value: "Some fixed readable text",
|
|
115
98
|
},
|
|
116
|
-
render: ({ ...args }: any) => <ReadOnlyField {...args} />,
|
|
117
99
|
};
|
|
118
100
|
|
|
119
101
|
/**
|
|
@@ -124,7 +106,6 @@ export const SideBySide: Story = {
|
|
|
124
106
|
formLayout: "side-by-side",
|
|
125
107
|
value: "Some fixed readable text mapping horizontally",
|
|
126
108
|
},
|
|
127
|
-
render: ({ ...args }: any) => <ReadOnlyField {...args} />,
|
|
128
109
|
};
|
|
129
110
|
|
|
130
111
|
/**
|
|
@@ -136,7 +117,6 @@ export const WithEditIcon: Story = {
|
|
|
136
117
|
required: true,
|
|
137
118
|
value: "Editable fixed structure",
|
|
138
119
|
},
|
|
139
|
-
render: ({ ...args }: any) => <ReadOnlyField {...args} />,
|
|
140
120
|
};
|
|
141
121
|
|
|
142
122
|
/**
|
|
@@ -145,46 +125,35 @@ export const WithEditIcon: Story = {
|
|
|
145
125
|
*/
|
|
146
126
|
export const DataTypes: Story = {
|
|
147
127
|
args: {},
|
|
148
|
-
render: (
|
|
128
|
+
render: () => (
|
|
149
129
|
<div style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
|
|
150
130
|
<ReadOnlyField
|
|
151
|
-
{...args}
|
|
152
131
|
label="Text Mapping"
|
|
153
132
|
type="text"
|
|
154
133
|
value="Standard string output"
|
|
155
134
|
/>
|
|
135
|
+
<ReadOnlyField label="Number Mapping" type="number" value={1234567.89} />
|
|
156
136
|
<ReadOnlyField
|
|
157
|
-
{...args}
|
|
158
|
-
label="Number Mapping"
|
|
159
|
-
type="number"
|
|
160
|
-
value={1234567.89}
|
|
161
|
-
/>
|
|
162
|
-
<ReadOnlyField
|
|
163
|
-
{...args}
|
|
164
137
|
label="Date Mapping"
|
|
165
138
|
type="date"
|
|
166
139
|
value={new Date("2026-04-28T12:00:00Z").toLocaleDateString()}
|
|
167
140
|
/>
|
|
168
141
|
<ReadOnlyField
|
|
169
|
-
{...args}
|
|
170
142
|
label="Boolean Mapping (True)"
|
|
171
143
|
type="boolean"
|
|
172
144
|
value={true}
|
|
173
145
|
/>
|
|
174
146
|
<ReadOnlyField
|
|
175
|
-
{...args}
|
|
176
147
|
label="Boolean Mapping (False)"
|
|
177
148
|
type="boolean"
|
|
178
149
|
value={false}
|
|
179
150
|
/>
|
|
180
151
|
<ReadOnlyField
|
|
181
|
-
{...args}
|
|
182
152
|
label="Switch Mapping (True -> On)"
|
|
183
153
|
type="switch"
|
|
184
154
|
value={true}
|
|
185
155
|
/>
|
|
186
156
|
<ReadOnlyField
|
|
187
|
-
{...args}
|
|
188
157
|
label="Switch Mapping (False -> Off)"
|
|
189
158
|
type="switch"
|
|
190
159
|
value={false}
|
|
@@ -7,14 +7,14 @@ import {
|
|
|
7
7
|
} from "../FormControlWrapper/FormControlWrapper";
|
|
8
8
|
import styles from "./ReadOnlyField.module.css";
|
|
9
9
|
|
|
10
|
+
import { type RecursicaReadOnlyFieldProps as BaseRecursicaReadOnlyFieldProps } from "@recursica/adapter-common";
|
|
11
|
+
|
|
10
12
|
export type ReadOnlyFieldProps = Omit<
|
|
11
13
|
RecursicaFormControlWrapperProps,
|
|
12
|
-
"error" | "focused"
|
|
14
|
+
"error" | "focused" | "controlMaxWidth" | "controlMinWidth"
|
|
13
15
|
> &
|
|
14
|
-
ReadOnlyControlProps &
|
|
15
|
-
|
|
16
|
-
type?: "text" | "boolean" | "number" | "switch" | "date";
|
|
17
|
-
};
|
|
16
|
+
ReadOnlyControlProps &
|
|
17
|
+
BaseRecursicaReadOnlyFieldProps;
|
|
18
18
|
|
|
19
19
|
export const ReadOnlyField = React.forwardRef<
|
|
20
20
|
HTMLDivElement,
|
|
@@ -61,7 +61,7 @@ export const ReadOnlyField = React.forwardRef<
|
|
|
61
61
|
className={`${styles.root} ${className || ""}`}
|
|
62
62
|
{...wrapperProps}
|
|
63
63
|
>
|
|
64
|
-
<
|
|
64
|
+
<p className={styles.text}>N/A</p>
|
|
65
65
|
</FormControlWrapper>
|
|
66
66
|
);
|
|
67
67
|
}
|
|
@@ -88,12 +88,8 @@ export const ReadOnlyField = React.forwardRef<
|
|
|
88
88
|
if (type === "switch") {
|
|
89
89
|
displayValue = value ? "On" : "Off";
|
|
90
90
|
}
|
|
91
|
-
} else if (
|
|
92
|
-
|
|
93
|
-
displayValue = JSON.stringify(value);
|
|
94
|
-
} catch {
|
|
95
|
-
displayValue = String(value);
|
|
96
|
-
}
|
|
91
|
+
} else if (Array.isArray(value)) {
|
|
92
|
+
displayValue = value.join(", ");
|
|
97
93
|
} else {
|
|
98
94
|
displayValue = String(value);
|
|
99
95
|
}
|
|
@@ -104,7 +100,7 @@ export const ReadOnlyField = React.forwardRef<
|
|
|
104
100
|
className={`${styles.root} ${className || ""}`}
|
|
105
101
|
{...wrapperProps}
|
|
106
102
|
>
|
|
107
|
-
<
|
|
103
|
+
<p className={styles.text}>{displayValue}</p>
|
|
108
104
|
</FormControlWrapper>
|
|
109
105
|
);
|
|
110
106
|
});
|
|
@@ -25,8 +25,7 @@
|
|
|
25
25
|
--recursica_ui-kit_components_segmented-control_properties_padding-horizontal
|
|
26
26
|
);
|
|
27
27
|
box-shadow: var(
|
|
28
|
-
--recursica_ui-kit_components_segmented-control_properties_elevation
|
|
29
|
-
none
|
|
28
|
+
--recursica_ui-kit_components_segmented-control_properties_elevation
|
|
30
29
|
);
|
|
31
30
|
gap: var(--recursica_ui-kit_components_segmented-control_properties_item-gap);
|
|
32
31
|
}
|
|
@@ -42,10 +41,7 @@
|
|
|
42
41
|
--recursica_ui-kit_components_segmented-control-item_properties_item_height
|
|
43
42
|
);
|
|
44
43
|
border-radius: var(
|
|
45
|
-
--recursica_ui-kit_components_segmented-control-item_properties_unselected_border-radius
|
|
46
|
-
var(
|
|
47
|
-
--recursica_ui-kit_components_segmented-control-item_properties_item_border-radius
|
|
48
|
-
)
|
|
44
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected_border-radius
|
|
49
45
|
);
|
|
50
46
|
|
|
51
47
|
border: var(
|
|
@@ -63,41 +59,32 @@
|
|
|
63
59
|
);
|
|
64
60
|
|
|
65
61
|
font-family: var(
|
|
66
|
-
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_font-family
|
|
67
|
-
inherit
|
|
62
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_font-family
|
|
68
63
|
);
|
|
69
64
|
font-size: var(
|
|
70
|
-
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_font-size
|
|
71
|
-
inherit
|
|
65
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_font-size
|
|
72
66
|
);
|
|
73
67
|
font-style: var(
|
|
74
|
-
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_font-style
|
|
75
|
-
inherit
|
|
68
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_font-style
|
|
76
69
|
);
|
|
77
70
|
font-weight: var(
|
|
78
|
-
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_font-weight
|
|
79
|
-
inherit
|
|
71
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_font-weight
|
|
80
72
|
);
|
|
81
73
|
letter-spacing: var(
|
|
82
|
-
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_letter-spacing
|
|
83
|
-
inherit
|
|
74
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_letter-spacing
|
|
84
75
|
);
|
|
85
76
|
line-height: var(
|
|
86
|
-
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_line-height
|
|
87
|
-
inherit
|
|
77
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_line-height
|
|
88
78
|
);
|
|
89
79
|
text-decoration: var(
|
|
90
|
-
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_text-decoration
|
|
91
|
-
inherit
|
|
80
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_text-decoration
|
|
92
81
|
);
|
|
93
82
|
text-transform: var(
|
|
94
|
-
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_text-transform
|
|
95
|
-
inherit
|
|
83
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected-text_text-transform
|
|
96
84
|
);
|
|
97
85
|
|
|
98
86
|
color: var(
|
|
99
|
-
--recursica_ui-kit_components_segmented-control-item_properties_unselected_colors_text-color
|
|
100
|
-
inherit
|
|
87
|
+
--recursica_ui-kit_components_segmented-control-item_properties_unselected_colors_text-color
|
|
101
88
|
);
|
|
102
89
|
|
|
103
90
|
display: flex;
|
|
@@ -140,8 +127,8 @@
|
|
|
140
127
|
);
|
|
141
128
|
}
|
|
142
129
|
|
|
143
|
-
/* Indicator (
|
|
144
|
-
.root .
|
|
130
|
+
/* Indicator mapping (MUI ToggleButton applies .Mui-selected to the button instead of rendering a sliding indicator) */
|
|
131
|
+
.root .control.Mui-selected {
|
|
145
132
|
background-color: var(
|
|
146
133
|
--recursica_ui-kit_components_segmented-control-item_properties_selected_colors_background
|
|
147
134
|
);
|
|
@@ -156,48 +143,37 @@
|
|
|
156
143
|
--recursica_ui-kit_components_segmented-control-item_properties_selected_elevation
|
|
157
144
|
);
|
|
158
145
|
border-radius: var(
|
|
159
|
-
--recursica_ui-kit_components_segmented-control-item_properties_selected_border-radius
|
|
160
|
-
var(
|
|
161
|
-
--recursica_ui-kit_components_segmented-control-item_properties_item_border-radius
|
|
162
|
-
)
|
|
146
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected_border-radius
|
|
163
147
|
);
|
|
164
148
|
}
|
|
165
149
|
|
|
166
150
|
/* Selected label text color override */
|
|
167
|
-
.root .control
|
|
151
|
+
.root .control.Mui-selected .label {
|
|
168
152
|
color: var(
|
|
169
153
|
--recursica_ui-kit_components_segmented-control-item_properties_selected_colors_text-color
|
|
170
154
|
);
|
|
171
155
|
font-family: var(
|
|
172
|
-
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_font-family
|
|
173
|
-
inherit
|
|
156
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_font-family
|
|
174
157
|
);
|
|
175
158
|
font-size: var(
|
|
176
|
-
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_font-size
|
|
177
|
-
inherit
|
|
159
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_font-size
|
|
178
160
|
);
|
|
179
161
|
font-style: var(
|
|
180
|
-
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_font-style
|
|
181
|
-
inherit
|
|
162
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_font-style
|
|
182
163
|
);
|
|
183
164
|
font-weight: var(
|
|
184
|
-
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_font-weight
|
|
185
|
-
inherit
|
|
165
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_font-weight
|
|
186
166
|
);
|
|
187
167
|
letter-spacing: var(
|
|
188
|
-
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_letter-spacing
|
|
189
|
-
inherit
|
|
168
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_letter-spacing
|
|
190
169
|
);
|
|
191
170
|
line-height: var(
|
|
192
|
-
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_line-height
|
|
193
|
-
inherit
|
|
171
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_line-height
|
|
194
172
|
);
|
|
195
173
|
text-decoration: var(
|
|
196
|
-
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_text-decoration
|
|
197
|
-
inherit
|
|
174
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_text-decoration
|
|
198
175
|
);
|
|
199
176
|
text-transform: var(
|
|
200
|
-
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_text-transform
|
|
201
|
-
inherit
|
|
177
|
+
--recursica_ui-kit_components_segmented-control-item_properties_selected-text_text-transform
|
|
202
178
|
);
|
|
203
179
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { forwardRef } from "react";
|
|
2
2
|
import {
|
|
3
3
|
ToggleButtonGroup as MuiSegmentedControl,
|
|
4
|
+
ToggleButton,
|
|
4
5
|
type ToggleButtonGroupProps as MuiSegmentedControlProps,
|
|
5
6
|
} from "@mui/material";
|
|
6
7
|
import {
|
|
@@ -9,17 +10,7 @@ import {
|
|
|
9
10
|
} from "../../utils/filterStylingProps";
|
|
10
11
|
import styles from "./SegmentedControl.module.css";
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
/** The orientation of the control */
|
|
14
|
-
orientation?: "horizontal" | "vertical";
|
|
15
|
-
/** If true, the control will take up the full width of its container */
|
|
16
|
-
fullWidth?: boolean;
|
|
17
|
-
/**
|
|
18
|
-
* SegmentedControl should NOT be allowed to be disabled by design.
|
|
19
|
-
* This component explicitly disables the `disabled` prop.
|
|
20
|
-
*/
|
|
21
|
-
disabled?: never;
|
|
22
|
-
}
|
|
13
|
+
import { type RecursicaSegmentedControlProps } from "@recursica/adapter-common";
|
|
23
14
|
|
|
24
15
|
export type SegmentedControlProps = RecursicaOverStyled<
|
|
25
16
|
Omit<
|
|
@@ -31,6 +22,8 @@ export type SegmentedControlProps = RecursicaOverStyled<
|
|
|
31
22
|
| "classNames"
|
|
32
23
|
| "className"
|
|
33
24
|
| "disabled"
|
|
25
|
+
| "value"
|
|
26
|
+
| "onChange"
|
|
34
27
|
> & {
|
|
35
28
|
className?: string;
|
|
36
29
|
classNames?: Partial<Record<string, string>>;
|
|
@@ -77,7 +70,15 @@ function useSegmentedControlClassNames(restRecord: Record<string, unknown>): {
|
|
|
77
70
|
|
|
78
71
|
const _SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
|
|
79
72
|
function SegmentedControl(
|
|
80
|
-
{
|
|
73
|
+
{
|
|
74
|
+
overStyled = false,
|
|
75
|
+
orientation = "horizontal",
|
|
76
|
+
fullWidth,
|
|
77
|
+
data = [],
|
|
78
|
+
value,
|
|
79
|
+
onChange,
|
|
80
|
+
...rest
|
|
81
|
+
},
|
|
81
82
|
ref,
|
|
82
83
|
) {
|
|
83
84
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
@@ -88,6 +89,15 @@ const _SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
|
|
|
88
89
|
|
|
89
90
|
const stylingParams = useSegmentedControlClassNames(restRecord);
|
|
90
91
|
|
|
92
|
+
const handleChange = (
|
|
93
|
+
_event: React.MouseEvent<HTMLElement>,
|
|
94
|
+
newValue: string | null,
|
|
95
|
+
) => {
|
|
96
|
+
if (newValue !== null && onChange) {
|
|
97
|
+
onChange(newValue);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
91
101
|
return (
|
|
92
102
|
<MuiSegmentedControl
|
|
93
103
|
ref={ref}
|
|
@@ -96,11 +106,31 @@ const _SegmentedControl = forwardRef<HTMLDivElement, SegmentedControlProps>(
|
|
|
96
106
|
orientation={orientation}
|
|
97
107
|
fullWidth={fullWidth}
|
|
98
108
|
data-orientation={orientation}
|
|
109
|
+
exclusive
|
|
110
|
+
value={value}
|
|
111
|
+
onChange={handleChange as any}
|
|
99
112
|
{...(sanitizedProps as Omit<
|
|
100
113
|
MuiSegmentedControlProps,
|
|
101
|
-
"variant" | "size"
|
|
114
|
+
"variant" | "size" | "value" | "onChange"
|
|
102
115
|
>)}
|
|
103
|
-
|
|
116
|
+
>
|
|
117
|
+
{data.map((item) => {
|
|
118
|
+
const itemValue = typeof item === "string" ? item : item.value;
|
|
119
|
+
const itemLabel = typeof item === "string" ? item : item.label;
|
|
120
|
+
const itemDisabled = typeof item === "string" ? false : item.disabled;
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<ToggleButton
|
|
124
|
+
key={itemValue}
|
|
125
|
+
value={itemValue}
|
|
126
|
+
disabled={itemDisabled}
|
|
127
|
+
className={stylingParams.classNames.control}
|
|
128
|
+
>
|
|
129
|
+
<div className={stylingParams.classNames.label}>{itemLabel}</div>
|
|
130
|
+
</ToggleButton>
|
|
131
|
+
);
|
|
132
|
+
})}
|
|
133
|
+
</MuiSegmentedControl>
|
|
104
134
|
);
|
|
105
135
|
},
|
|
106
136
|
);
|
|
@@ -233,10 +233,7 @@
|
|
|
233
233
|
position: absolute;
|
|
234
234
|
bottom: calc(
|
|
235
235
|
100% +
|
|
236
|
-
var(
|
|
237
|
-
--recursica_ui-kit_globals_form_properties_label-field-gap-vertical,
|
|
238
|
-
8px
|
|
239
|
-
)
|
|
236
|
+
var(--recursica_ui-kit_globals_form_properties_label-field-gap-vertical)
|
|
240
237
|
);
|
|
241
238
|
right: 0;
|
|
242
239
|
white-space: nowrap;
|
|
@@ -65,8 +65,8 @@ export const Default: Story = {
|
|
|
65
65
|
args: {
|
|
66
66
|
label: "Auditory Threshold",
|
|
67
67
|
assistiveText: "Specify the maximum decibel frequency boundary.",
|
|
68
|
-
defaultValue:
|
|
69
|
-
min:
|
|
68
|
+
defaultValue: 60,
|
|
69
|
+
min: 10,
|
|
70
70
|
max: 100,
|
|
71
71
|
step: 1,
|
|
72
72
|
showMinMaxLabels: true,
|
|
@@ -92,7 +92,7 @@ export const Disabled: Story = {
|
|
|
92
92
|
label: "Decommissioned Server Node",
|
|
93
93
|
assistiveText: "Modifications to this environment are frozen.",
|
|
94
94
|
defaultValue: 35,
|
|
95
|
-
disabled:
|
|
95
|
+
disabled: false,
|
|
96
96
|
},
|
|
97
97
|
};
|
|
98
98
|
|
|
@@ -2,7 +2,6 @@ import React, { forwardRef, useState, useEffect } from "react";
|
|
|
2
2
|
import {
|
|
3
3
|
Slider as MuiSlider,
|
|
4
4
|
type SliderProps as MuiSliderProps,
|
|
5
|
-
type InputWrapperProps,
|
|
6
5
|
} from "@mui/material";
|
|
7
6
|
import { type ReadOnlyControlProps } from "@recursica/adapter-common";
|
|
8
7
|
import {
|
|
@@ -14,28 +13,24 @@ import { WithReadOnlyWrapper } from "../ReadOnlyField/WithReadOnlyWrapper";
|
|
|
14
13
|
|
|
15
14
|
import styles from "./Slider.module.css";
|
|
16
15
|
|
|
16
|
+
import { type RecursicaSliderProps as BaseRecursicaSliderProps } from "@recursica/adapter-common";
|
|
17
|
+
|
|
17
18
|
export interface RecursicaSliderProps
|
|
18
19
|
extends Omit<
|
|
19
|
-
|
|
20
|
-
"
|
|
20
|
+
MuiSliderProps,
|
|
21
|
+
"size" | "color" | "classes" | "onChange" | "onChangeCommitted"
|
|
21
22
|
>,
|
|
22
23
|
Omit<
|
|
23
24
|
RecursicaFormControlWrapperProps,
|
|
24
|
-
|
|
25
|
+
| "controlMaxWidth"
|
|
26
|
+
| "controlMinWidth"
|
|
27
|
+
| "error"
|
|
28
|
+
| "required"
|
|
29
|
+
| "withAsterisk"
|
|
30
|
+
| keyof MuiSliderProps
|
|
25
31
|
>,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
/** The form control label displayed above or beside the slider track. */
|
|
29
|
-
label?: React.ReactNode;
|
|
30
|
-
/** Floating tooltip shown above the thumb when dragging. Replaces Mui's `label`. */
|
|
31
|
-
tooltipLabel?: MuiSliderProps["label"];
|
|
32
|
-
/** An optional icon rendered to the left of the slider track. */
|
|
33
|
-
icon?: React.ReactNode;
|
|
34
|
-
/** Whether to render a numeric input field side-by-side or stacked with the track. Defaults to false. */
|
|
35
|
-
showInput?: boolean;
|
|
36
|
-
/** Whether to render min and max labels below the track. Defaults to true. */
|
|
37
|
-
showMinMaxLabels?: boolean;
|
|
38
|
-
}
|
|
32
|
+
ReadOnlyControlProps,
|
|
33
|
+
BaseRecursicaSliderProps {}
|
|
39
34
|
|
|
40
35
|
export type SliderProps = RecursicaOverStyled<RecursicaSliderProps>;
|
|
41
36
|
|
|
@@ -73,6 +68,7 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(
|
|
|
73
68
|
assistiveWithIcon,
|
|
74
69
|
error,
|
|
75
70
|
required,
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
76
72
|
withAsterisk,
|
|
77
73
|
id,
|
|
78
74
|
className,
|
|
@@ -96,12 +92,18 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(
|
|
|
96
92
|
|
|
97
93
|
// Bidirectional state linking the slider track value to the input field string representation
|
|
98
94
|
const [internalValue, setInternalValue] = useState<number>(() => {
|
|
99
|
-
if (value !== undefined) return value;
|
|
100
|
-
if (defaultValue !== undefined)
|
|
95
|
+
if (value !== undefined) return Array.isArray(value) ? value[0] : value;
|
|
96
|
+
if (defaultValue !== undefined)
|
|
97
|
+
return Array.isArray(defaultValue) ? defaultValue[0] : defaultValue;
|
|
101
98
|
return min;
|
|
102
99
|
});
|
|
103
100
|
|
|
104
|
-
const resolvedValue =
|
|
101
|
+
const resolvedValue =
|
|
102
|
+
value !== undefined
|
|
103
|
+
? Array.isArray(value)
|
|
104
|
+
? value[0]
|
|
105
|
+
: value
|
|
106
|
+
: internalValue;
|
|
105
107
|
const [inputValue, setInputValue] = useState<string>(
|
|
106
108
|
resolvedValue.toString(),
|
|
107
109
|
);
|
|
@@ -111,12 +113,12 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(
|
|
|
111
113
|
setInputValue(resolvedValue.toString());
|
|
112
114
|
}, [resolvedValue]);
|
|
113
115
|
|
|
114
|
-
const handleValueChange = (
|
|
116
|
+
const handleValueChange = (_e: Event, val: number | number[]) => {
|
|
115
117
|
const singleVal = Array.isArray(val) ? val[0] : val;
|
|
116
118
|
if (value === undefined) {
|
|
117
119
|
setInternalValue(singleVal);
|
|
118
120
|
}
|
|
119
|
-
onChange?.(singleVal
|
|
121
|
+
onChange?.(singleVal);
|
|
120
122
|
};
|
|
121
123
|
|
|
122
124
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
@@ -209,9 +211,8 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(
|
|
|
209
211
|
label={label}
|
|
210
212
|
assistiveText={assistiveText}
|
|
211
213
|
assistiveWithIcon={assistiveWithIcon}
|
|
212
|
-
error={error}
|
|
214
|
+
error={error as any}
|
|
213
215
|
required={required}
|
|
214
|
-
withAsterisk={withAsterisk}
|
|
215
216
|
id={id}
|
|
216
217
|
readOnly={readOnly}
|
|
217
218
|
readOnlyComponent={readOnlyComponent || SliderReadOnlyValue}
|
|
@@ -270,7 +271,7 @@ export const Slider = forwardRef<HTMLDivElement, SliderProps>(
|
|
|
270
271
|
onBlur={handleInputBlur}
|
|
271
272
|
min={min}
|
|
272
273
|
max={max}
|
|
273
|
-
step={step}
|
|
274
|
+
step={step ?? undefined}
|
|
274
275
|
disabled={disabled}
|
|
275
276
|
data-error={error ? "true" : undefined}
|
|
276
277
|
/>
|
|
@@ -17,32 +17,11 @@ const meta: Meta<StackStoryProps> = {
|
|
|
17
17
|
"Stack is a flex vertical layout container that maps directly to Mantine's Stack 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
|
-
"defaultChecked",
|
|
28
|
-
"children",
|
|
29
|
-
"component",
|
|
30
|
-
"variant",
|
|
31
|
-
"size",
|
|
32
|
-
"icon",
|
|
33
|
-
"disabled",
|
|
34
|
-
"href",
|
|
35
|
-
"onClick",
|
|
36
|
-
"onChange",
|
|
37
|
-
"value",
|
|
38
|
-
"checked",
|
|
39
|
-
],
|
|
40
|
-
},
|
|
41
20
|
},
|
|
42
21
|
args: {
|
|
43
22
|
gap: "rec-default",
|
|
44
|
-
|
|
45
|
-
|
|
23
|
+
align: "stretch",
|
|
24
|
+
justify: "flex-start",
|
|
46
25
|
},
|
|
47
26
|
argTypes: {
|
|
48
27
|
gap: {
|
|
@@ -63,12 +42,12 @@ const meta: Meta<StackStoryProps> = {
|
|
|
63
42
|
],
|
|
64
43
|
description: "Gap between elements",
|
|
65
44
|
},
|
|
66
|
-
|
|
45
|
+
align: {
|
|
67
46
|
control: "select",
|
|
68
47
|
options: ["flex-start", "center", "flex-end", "stretch"],
|
|
69
48
|
description: "Align-items property",
|
|
70
49
|
},
|
|
71
|
-
|
|
50
|
+
justify: {
|
|
72
51
|
control: "select",
|
|
73
52
|
options: [
|
|
74
53
|
"flex-start",
|
|
@@ -4,16 +4,12 @@ import {
|
|
|
4
4
|
type StackProps as MUIStackProps,
|
|
5
5
|
} from "@mui/material";
|
|
6
6
|
import {
|
|
7
|
-
type RecursicaSpacing,
|
|
8
7
|
SPACING_MAP,
|
|
9
8
|
type OmitSx,
|
|
10
9
|
filterSxProp,
|
|
11
10
|
} from "../../utils/filterStylingProps";
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
children?: React.ReactNode;
|
|
15
|
-
gap?: MUIStackProps["spacing"] | RecursicaSpacing;
|
|
16
|
-
}
|
|
12
|
+
import { type RecursicaStackProps } from "@recursica/adapter-common";
|
|
17
13
|
|
|
18
14
|
export type StackProps = OmitSx<
|
|
19
15
|
Omit<MUIStackProps, "spacing"> & RecursicaStackProps
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# Stepper Implementation Notes
|
|
2
|
+
|
|
3
|
+
- **Compositional API Dropped:** Mantine manages stepper state and content via `<Stepper.Step>` and `<Stepper.Completed>`. MUI delegates content rendering to the developer and focuses purely on the stepper visual layout using `<Step>`, `<StepLabel>`, etc.
|
|
4
|
+
- **Monolithic API Adopted:** Following architectural review, we have abandoned the fabricated context wrappers for `mui-adapter`. We now natively export `Stepper`, `Step`, `StepLabel`, `StepButton`, and `StepConnector` wrapping their `@mui/material` counterparts. Developers are expected to manage the active step logic and content rendering outside the `Stepper` component, consistent with MUI patterns. Storybook tests have been updated to reflect this divergence while retaining core visual compatibility.
|