@recursica/mantine-adapter 0.7.0 → 0.9.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 +12 -0
- package/dist/mantine-adapter.cjs +1 -1
- package/dist/mantine-adapter.cjs.map +1 -1
- package/dist/mantine-adapter.css +1 -1
- package/dist/mantine-adapter.js +963 -639
- package/dist/mantine-adapter.js.map +1 -1
- package/dist/src/components/Container/Container.d.ts +14 -0
- package/dist/src/components/Dropdown/Dropdown.d.ts +10 -2
- package/dist/src/components/Flex/Flex.d.ts +17 -0
- package/dist/src/components/Group/Group.d.ts +17 -0
- package/dist/src/components/Stack/Stack.d.ts +15 -0
- package/dist/src/components/TextArea/TextArea.d.ts +14 -2
- package/dist/src/components/index.d.ts +6 -0
- package/package.json +1 -1
- package/src/components/Accordion/Accordion.module.css +29 -8
- package/src/components/Checkbox/CheckboxGroup.tsx +1 -1
- package/src/components/Container/CONTAINER_IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Container/Container.module.css +7 -0
- package/src/components/Container/Container.stories.tsx +102 -0
- package/src/components/Container/Container.tsx +63 -0
- package/src/components/Dropdown/DROPDOWN_IMPLEMENTATION_NOTES.md +7 -0
- package/src/components/Dropdown/Dropdown.module.css +272 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +77 -5
- package/src/components/Dropdown/Dropdown.tsx +171 -5
- package/src/components/Flex/FLEX_IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Flex/Flex.module.css +7 -0
- package/src/components/Flex/Flex.stories.tsx +125 -0
- package/src/components/Flex/Flex.tsx +68 -0
- package/src/components/Group/GROUP_IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Group/Group.module.css +7 -0
- package/src/components/Group/Group.stories.tsx +117 -0
- package/src/components/Group/Group.tsx +68 -0
- package/src/components/Stack/STACK_IMPLEMENTATION_NOTES.md +4 -0
- package/src/components/Stack/Stack.module.css +7 -0
- package/src/components/Stack/Stack.stories.tsx +105 -0
- package/src/components/Stack/Stack.tsx +66 -0
- package/src/components/TextArea/TEXTAREA_IMPLEMENTATION_NOTES.md +7 -0
- package/src/components/TextArea/TextArea.module.css +225 -0
- package/src/components/TextArea/TextArea.stories.tsx +77 -5
- package/src/components/TextArea/TextArea.tsx +149 -5
- package/src/components/index.ts +6 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/* HARDCODED VALUES:
|
|
2
|
+
- border-width: 1px. Native geometric boundary for the input box.
|
|
3
|
+
- border-style: solid. Native structural rendering rule.
|
|
4
|
+
- outline: none. Bypassing browser focus rings to rely strictly on Recursica focus states natively.
|
|
5
|
+
- flex/layout: display: flex on the root wrapper safely encapsulating internal section rendering.
|
|
6
|
+
- placeholder opacity: 0.5. The dropdown parameters currently lack a dedicated placeholder-opacity variable.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
.root {
|
|
10
|
+
display: flex;
|
|
11
|
+
position: relative;
|
|
12
|
+
width: 100%;
|
|
13
|
+
min-height: var(--recursica_ui-kit_components_dropdown_properties_min-height);
|
|
14
|
+
|
|
15
|
+
/* Override Mantine native Input variables governing section spacing padding mathematics safely */
|
|
16
|
+
--input-left-section-size: calc(
|
|
17
|
+
var(--recursica_ui-kit_components_dropdown_properties_icon-size) +
|
|
18
|
+
(
|
|
19
|
+
var(
|
|
20
|
+
--recursica_ui-kit_components_dropdown_properties_horizontal-padding
|
|
21
|
+
) *
|
|
22
|
+
2
|
|
23
|
+
)
|
|
24
|
+
);
|
|
25
|
+
--input-right-section-size: calc(
|
|
26
|
+
var(--recursica_ui-kit_components_dropdown_properties_icon-size) +
|
|
27
|
+
(
|
|
28
|
+
var(
|
|
29
|
+
--recursica_ui-kit_components_dropdown_properties_horizontal-padding
|
|
30
|
+
) *
|
|
31
|
+
2
|
|
32
|
+
)
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.input {
|
|
37
|
+
/* Structural Overrides */
|
|
38
|
+
width: 100%;
|
|
39
|
+
box-sizing: border-box;
|
|
40
|
+
margin: 0;
|
|
41
|
+
|
|
42
|
+
/* Box Geometry */
|
|
43
|
+
min-height: var(--recursica_ui-kit_components_dropdown_properties_min-height);
|
|
44
|
+
padding-top: var(
|
|
45
|
+
--recursica_ui-kit_components_dropdown_properties_vertical-padding
|
|
46
|
+
);
|
|
47
|
+
padding-bottom: var(
|
|
48
|
+
--recursica_ui-kit_components_dropdown_properties_vertical-padding
|
|
49
|
+
);
|
|
50
|
+
padding-left: var(
|
|
51
|
+
--recursica_ui-kit_components_dropdown_properties_horizontal-padding
|
|
52
|
+
);
|
|
53
|
+
padding-right: var(
|
|
54
|
+
--recursica_ui-kit_components_dropdown_properties_horizontal-padding
|
|
55
|
+
);
|
|
56
|
+
border-radius: var(
|
|
57
|
+
--recursica_ui-kit_components_dropdown_properties_border-radius
|
|
58
|
+
);
|
|
59
|
+
border-width: 1px;
|
|
60
|
+
border-style: solid;
|
|
61
|
+
|
|
62
|
+
/* Strict Typography Unification */
|
|
63
|
+
font-family: var(
|
|
64
|
+
--recursica_ui-kit_components_dropdown_properties_text_font-family
|
|
65
|
+
);
|
|
66
|
+
font-size: var(
|
|
67
|
+
--recursica_ui-kit_components_dropdown_properties_text_font-size
|
|
68
|
+
);
|
|
69
|
+
font-style: var(
|
|
70
|
+
--recursica_ui-kit_components_dropdown_properties_text_font-style
|
|
71
|
+
);
|
|
72
|
+
font-weight: var(
|
|
73
|
+
--recursica_ui-kit_components_dropdown_properties_text_font-weight
|
|
74
|
+
);
|
|
75
|
+
letter-spacing: var(
|
|
76
|
+
--recursica_ui-kit_components_dropdown_properties_text_letter-spacing
|
|
77
|
+
);
|
|
78
|
+
line-height: var(
|
|
79
|
+
--recursica_ui-kit_components_dropdown_properties_text_line-height
|
|
80
|
+
);
|
|
81
|
+
text-decoration: var(
|
|
82
|
+
--recursica_ui-kit_components_dropdown_properties_text_text-decoration
|
|
83
|
+
);
|
|
84
|
+
text-transform: var(
|
|
85
|
+
--recursica_ui-kit_components_dropdown_properties_text_text-transform
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
/* Base State Default Execution */
|
|
89
|
+
background-color: var(
|
|
90
|
+
--recursica_ui-kit_components_dropdown_variants_states_default_properties_colors_background
|
|
91
|
+
);
|
|
92
|
+
border-color: var(
|
|
93
|
+
--recursica_ui-kit_components_dropdown_variants_states_default_properties_colors_border-color
|
|
94
|
+
);
|
|
95
|
+
color: var(
|
|
96
|
+
--recursica_ui-kit_components_dropdown_variants_states_default_properties_colors_text
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
outline: none;
|
|
100
|
+
transition:
|
|
101
|
+
border-color 0.15s ease,
|
|
102
|
+
background-color 0.15s ease;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.input::placeholder {
|
|
106
|
+
/* HARDCODE: Dropdown properties currently missing placeholder-opacity tokens from Figma JSON */
|
|
107
|
+
opacity: 0.5;
|
|
108
|
+
color: inherit;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* Dynamic Padding Overrides */
|
|
112
|
+
.root[data-with-left-section] .input {
|
|
113
|
+
padding-left: var(--input-left-section-size);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.root[data-with-right-section] .input {
|
|
117
|
+
padding-right: var(--input-right-section-size);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* Flexible End-Caps (Icons, actions) */
|
|
121
|
+
.section {
|
|
122
|
+
display: flex;
|
|
123
|
+
align-items: center;
|
|
124
|
+
justify-content: center;
|
|
125
|
+
height: 100%;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.section :global(svg) {
|
|
129
|
+
width: var(--recursica_ui-kit_components_dropdown_properties_icon-size);
|
|
130
|
+
height: var(--recursica_ui-kit_components_dropdown_properties_icon-size);
|
|
131
|
+
color: var(
|
|
132
|
+
--recursica_ui-kit_components_dropdown_variants_states_default_properties_colors_leading-icon
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.section[data-position="right"] :global(svg) {
|
|
137
|
+
color: var(
|
|
138
|
+
--recursica_ui-kit_components_dropdown_variants_states_default_properties_colors_trailing-icon
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* -------------------------------------
|
|
143
|
+
STATE CASCADE ARCHITECTURE
|
|
144
|
+
-------------------------------------- */
|
|
145
|
+
|
|
146
|
+
/* Focus State Mapping (Triggered internally via browser pseudo-pseudo-class) */
|
|
147
|
+
.input:focus-within,
|
|
148
|
+
.input:focus {
|
|
149
|
+
border-color: var(
|
|
150
|
+
--recursica_ui-kit_components_dropdown_variants_states_focus_properties_colors_border-color
|
|
151
|
+
);
|
|
152
|
+
background-color: var(
|
|
153
|
+
--recursica_ui-kit_components_dropdown_variants_states_focus_properties_colors_background
|
|
154
|
+
);
|
|
155
|
+
color: var(
|
|
156
|
+
--recursica_ui-kit_components_dropdown_variants_states_focus_properties_colors_text
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.root:focus-within .section[data-position="left"] :global(svg) {
|
|
161
|
+
color: var(
|
|
162
|
+
--recursica_ui-kit_components_dropdown_variants_states_focus_properties_colors_leading-icon
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.root:focus-within .section[data-position="right"] :global(svg) {
|
|
167
|
+
color: var(
|
|
168
|
+
--recursica_ui-kit_components_dropdown_variants_states_focus_properties_colors_trailing-icon
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/* Error State Mapping (Propagated strictly down from the wrapper DOM context) */
|
|
173
|
+
.root[data-error] .input {
|
|
174
|
+
border-color: var(
|
|
175
|
+
--recursica_ui-kit_components_dropdown_variants_states_error_properties_colors_border-color
|
|
176
|
+
) !important;
|
|
177
|
+
background-color: var(
|
|
178
|
+
--recursica_ui-kit_components_dropdown_variants_states_error_properties_colors_background
|
|
179
|
+
) !important;
|
|
180
|
+
color: var(
|
|
181
|
+
--recursica_ui-kit_components_dropdown_variants_states_error_properties_colors_text
|
|
182
|
+
) !important;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.root[data-error] .section[data-position="left"] :global(svg) {
|
|
186
|
+
color: var(
|
|
187
|
+
--recursica_ui-kit_components_dropdown_variants_states_error_properties_colors_leading-icon
|
|
188
|
+
) !important;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.root[data-error] .section[data-position="right"] :global(svg) {
|
|
192
|
+
color: var(
|
|
193
|
+
--recursica_ui-kit_components_dropdown_variants_states_error_properties_colors_trailing-icon
|
|
194
|
+
) !important;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* Disabled State Mapping (Propagated strictly down from the wrapper DOM context) */
|
|
198
|
+
.root[data-disabled] .input {
|
|
199
|
+
border-color: var(
|
|
200
|
+
--recursica_ui-kit_components_dropdown_variants_states_disabled_properties_colors_border-color
|
|
201
|
+
) !important;
|
|
202
|
+
background-color: var(
|
|
203
|
+
--recursica_ui-kit_components_dropdown_variants_states_disabled_properties_colors_background
|
|
204
|
+
) !important;
|
|
205
|
+
color: var(
|
|
206
|
+
--recursica_ui-kit_components_dropdown_variants_states_disabled_properties_colors_text
|
|
207
|
+
) !important;
|
|
208
|
+
cursor: not-allowed;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.root[data-disabled] .section[data-position="left"] :global(svg) {
|
|
212
|
+
color: var(
|
|
213
|
+
--recursica_ui-kit_components_dropdown_variants_states_disabled_properties_colors_leading-icon
|
|
214
|
+
) !important;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.root[data-disabled] .section[data-position="right"] :global(svg) {
|
|
218
|
+
color: var(
|
|
219
|
+
--recursica_ui-kit_components_dropdown_variants_states_disabled_properties_colors_trailing-icon
|
|
220
|
+
) !important;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* -------------------------------------
|
|
224
|
+
DROPDOWN & OPTIONS ARCHITECTURE
|
|
225
|
+
-------------------------------------- */
|
|
226
|
+
|
|
227
|
+
.dropdown {
|
|
228
|
+
background-color: var(
|
|
229
|
+
--recursica_ui-kit_components_dropdown_variants_states_default_properties_colors_background
|
|
230
|
+
);
|
|
231
|
+
border: 1px solid
|
|
232
|
+
var(
|
|
233
|
+
--recursica_ui-kit_components_dropdown_variants_states_default_properties_colors_border-color
|
|
234
|
+
);
|
|
235
|
+
border-radius: var(
|
|
236
|
+
--recursica_ui-kit_components_dropdown_properties_border-radius
|
|
237
|
+
);
|
|
238
|
+
overflow: hidden;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.option {
|
|
242
|
+
font-family: var(
|
|
243
|
+
--recursica_ui-kit_components_dropdown_properties_text_font-family
|
|
244
|
+
);
|
|
245
|
+
font-size: var(
|
|
246
|
+
--recursica_ui-kit_components_dropdown_properties_text_font-size
|
|
247
|
+
);
|
|
248
|
+
font-weight: var(
|
|
249
|
+
--recursica_ui-kit_components_dropdown_properties_text_font-weight
|
|
250
|
+
);
|
|
251
|
+
color: var(
|
|
252
|
+
--recursica_ui-kit_components_dropdown_variants_states_default_properties_colors_text
|
|
253
|
+
);
|
|
254
|
+
padding: calc(
|
|
255
|
+
var(--recursica_ui-kit_components_dropdown_properties_vertical-padding) *
|
|
256
|
+
0.75
|
|
257
|
+
)
|
|
258
|
+
var(--recursica_ui-kit_components_dropdown_properties_horizontal-padding);
|
|
259
|
+
cursor: pointer;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.option[data-selected="true"],
|
|
263
|
+
.option[data-combobox-selected="true"],
|
|
264
|
+
.option[data-hovered="true"],
|
|
265
|
+
.option:hover {
|
|
266
|
+
background-color: var(
|
|
267
|
+
--recursica_ui-kit_components_dropdown_variants_states_focus_properties_colors_background
|
|
268
|
+
);
|
|
269
|
+
color: var(
|
|
270
|
+
--recursica_ui-kit_components_dropdown_variants_states_focus_properties_colors_text
|
|
271
|
+
);
|
|
272
|
+
}
|
|
@@ -1,22 +1,94 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
3
|
import { Dropdown } from "./Dropdown";
|
|
3
|
-
import {
|
|
4
|
+
import { formControlArgTypes } from "../../../.storybook/commonArgTypes";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
type DropdownStoryProps = React.ComponentProps<typeof Dropdown>;
|
|
7
|
+
|
|
8
|
+
const meta: Meta<DropdownStoryProps> = {
|
|
9
|
+
title: "UI-Kit/Dropdown",
|
|
7
10
|
component: Dropdown,
|
|
8
11
|
tags: ["autodocs"],
|
|
12
|
+
parameters: {
|
|
13
|
+
docs: {
|
|
14
|
+
description: {
|
|
15
|
+
component:
|
|
16
|
+
"Dropdown provides a selectable list of options, mapping natively over Mantine's Select component encapsulated within the standardized FormControlWrapper.",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
args: {
|
|
21
|
+
label: "Country Selection",
|
|
22
|
+
assistiveText: "Select your country of origin.",
|
|
23
|
+
placeholder: "Pick value",
|
|
24
|
+
data: ["United States", "Canada", "Mexico", "United Kingdom", "France"],
|
|
25
|
+
disabled: false,
|
|
26
|
+
required: false,
|
|
27
|
+
readOnly: false,
|
|
28
|
+
searchable: false,
|
|
29
|
+
clearable: false,
|
|
30
|
+
},
|
|
9
31
|
argTypes: {
|
|
32
|
+
...formControlArgTypes,
|
|
10
33
|
disabled: {
|
|
11
34
|
control: "boolean",
|
|
12
35
|
},
|
|
36
|
+
readOnly: {
|
|
37
|
+
control: "boolean",
|
|
38
|
+
},
|
|
39
|
+
searchable: {
|
|
40
|
+
control: "boolean",
|
|
41
|
+
},
|
|
42
|
+
clearable: {
|
|
43
|
+
control: "boolean",
|
|
44
|
+
},
|
|
45
|
+
checked: {
|
|
46
|
+
table: { disable: true },
|
|
47
|
+
},
|
|
48
|
+
defaultChecked: {
|
|
49
|
+
table: { disable: true },
|
|
50
|
+
},
|
|
51
|
+
containerWidth: {
|
|
52
|
+
table: { disable: true },
|
|
53
|
+
},
|
|
13
54
|
},
|
|
14
55
|
};
|
|
15
56
|
|
|
16
57
|
export default meta;
|
|
17
58
|
|
|
18
|
-
type Story = StoryObj<
|
|
59
|
+
type Story = StoryObj<DropdownStoryProps>;
|
|
19
60
|
|
|
20
61
|
export const Default: Story = {
|
|
21
|
-
|
|
62
|
+
args: {},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const SearchableClearable: Story = {
|
|
66
|
+
args: {
|
|
67
|
+
label: "Search & Clear Options",
|
|
68
|
+
searchable: true,
|
|
69
|
+
clearable: true,
|
|
70
|
+
placeholder: "Start typing...",
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const StaticError: Story = {
|
|
75
|
+
args: {
|
|
76
|
+
error: "You must choose a valid destination.",
|
|
77
|
+
value: "Invalid Island",
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const StaticDisabled: Story = {
|
|
82
|
+
args: {
|
|
83
|
+
disabled: true,
|
|
84
|
+
value: "United States",
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export const StaticReadOnly: Story = {
|
|
89
|
+
args: {
|
|
90
|
+
label: "Read Only View",
|
|
91
|
+
readOnly: true,
|
|
92
|
+
value: "Canada",
|
|
93
|
+
},
|
|
22
94
|
};
|
|
@@ -1,7 +1,173 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Select as MantineSelect,
|
|
4
|
+
type SelectProps as MantineSelectProps,
|
|
5
|
+
} from "@mantine/core";
|
|
6
|
+
import { type ReadOnlyControlProps } from "@recursica/adapter-common";
|
|
7
|
+
import {
|
|
8
|
+
filterStylingProps,
|
|
9
|
+
type RecursicaOverStyled,
|
|
10
|
+
} from "../../utils/filterStylingProps";
|
|
11
|
+
import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
|
|
12
|
+
import { WithReadOnlyWrapper } from "../ReadOnlyField/WithReadOnlyWrapper";
|
|
13
|
+
import styles from "./Dropdown.module.css";
|
|
2
14
|
|
|
3
|
-
export
|
|
15
|
+
export interface RecursicaDropdownProps
|
|
16
|
+
extends Omit<
|
|
17
|
+
MantineSelectProps,
|
|
18
|
+
"size" | "variant" | "radius" | "wrapperProps"
|
|
19
|
+
>,
|
|
20
|
+
Pick<
|
|
21
|
+
RecursicaFormControlWrapperProps,
|
|
22
|
+
| "assistiveText"
|
|
23
|
+
| "assistiveWithIcon"
|
|
24
|
+
| "formLayout"
|
|
25
|
+
| "labelSize"
|
|
26
|
+
| "labelAlignment"
|
|
27
|
+
| "labelOptionalText"
|
|
28
|
+
| "labelWithEditIcon"
|
|
29
|
+
| "onLabelEditClick"
|
|
30
|
+
>,
|
|
31
|
+
ReadOnlyControlProps {
|
|
32
|
+
/** Internal hook for Selects to override raw layout width properties when necessary */
|
|
33
|
+
containerWidth?: React.CSSProperties["width"];
|
|
34
|
+
}
|
|
4
35
|
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
36
|
+
export type DropdownProps = RecursicaOverStyled<RecursicaDropdownProps>;
|
|
37
|
+
|
|
38
|
+
export const Dropdown = forwardRef<HTMLInputElement, DropdownProps>(
|
|
39
|
+
function Dropdown(
|
|
40
|
+
{
|
|
41
|
+
overStyled = false,
|
|
42
|
+
formLayout = "stacked",
|
|
43
|
+
containerWidth,
|
|
44
|
+
|
|
45
|
+
// Label & Wrapper Maps
|
|
46
|
+
labelSize,
|
|
47
|
+
labelAlignment,
|
|
48
|
+
labelOptionalText,
|
|
49
|
+
labelWithEditIcon,
|
|
50
|
+
onLabelEditClick,
|
|
51
|
+
|
|
52
|
+
label,
|
|
53
|
+
assistiveText,
|
|
54
|
+
assistiveWithIcon,
|
|
55
|
+
error,
|
|
56
|
+
required,
|
|
57
|
+
withAsterisk,
|
|
58
|
+
id,
|
|
59
|
+
className,
|
|
60
|
+
style,
|
|
61
|
+
disabled,
|
|
62
|
+
readOnly,
|
|
63
|
+
readOnlyComponent,
|
|
64
|
+
value,
|
|
65
|
+
defaultValue,
|
|
66
|
+
data,
|
|
67
|
+
...rest
|
|
68
|
+
},
|
|
69
|
+
ref,
|
|
70
|
+
) {
|
|
71
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
72
|
+
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
73
|
+
|
|
74
|
+
// Delete prohibited sizing hooks from bypassing variables natively
|
|
75
|
+
delete restRecord["size"];
|
|
76
|
+
delete restRecord["variant"];
|
|
77
|
+
delete restRecord["radius"];
|
|
78
|
+
|
|
79
|
+
// Securely map core native blocks down ensuring nested CSS modules map precisely
|
|
80
|
+
const mergedClassNames: Partial<Record<string, string>> = {
|
|
81
|
+
wrapper: styles.root, // The nested Input internal relative wrapper bounding box
|
|
82
|
+
input: styles.input,
|
|
83
|
+
section: styles.section,
|
|
84
|
+
dropdown: styles.dropdown,
|
|
85
|
+
option: styles.option,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const classNamesProp = restRecord.classNames;
|
|
89
|
+
if (
|
|
90
|
+
classNamesProp &&
|
|
91
|
+
typeof classNamesProp === "object" &&
|
|
92
|
+
!Array.isArray(classNamesProp)
|
|
93
|
+
) {
|
|
94
|
+
const o = classNamesProp as Partial<Record<string, string>>;
|
|
95
|
+
mergedClassNames.wrapper = o.wrapper
|
|
96
|
+
? `${styles.root} ${o.wrapper}`
|
|
97
|
+
: styles.root;
|
|
98
|
+
mergedClassNames.input = o.input
|
|
99
|
+
? `${styles.input} ${o.input}`
|
|
100
|
+
: styles.input;
|
|
101
|
+
mergedClassNames.section = o.section
|
|
102
|
+
? `${styles.section} ${o.section}`
|
|
103
|
+
: styles.section;
|
|
104
|
+
mergedClassNames.dropdown = o.dropdown
|
|
105
|
+
? `${styles.dropdown} ${o.dropdown}`
|
|
106
|
+
: styles.dropdown;
|
|
107
|
+
mergedClassNames.option = o.option
|
|
108
|
+
? `${styles.option} ${o.option}`
|
|
109
|
+
: styles.option;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const injectedStyles = {
|
|
113
|
+
...((style as React.CSSProperties) || {}),
|
|
114
|
+
width: containerWidth || "100%",
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<WithReadOnlyWrapper
|
|
119
|
+
className={className}
|
|
120
|
+
style={injectedStyles}
|
|
121
|
+
controlMaxWidth="var(--recursica_ui-kit_components_dropdown_properties_max-width)"
|
|
122
|
+
controlMinWidth="var(--recursica_ui-kit_components_dropdown_properties_min-width)"
|
|
123
|
+
overStyled={overStyled as true}
|
|
124
|
+
formLayout={formLayout}
|
|
125
|
+
labelSize={labelSize}
|
|
126
|
+
labelAlignment={labelAlignment}
|
|
127
|
+
labelOptionalText={labelOptionalText}
|
|
128
|
+
labelWithEditIcon={labelWithEditIcon}
|
|
129
|
+
onLabelEditClick={onLabelEditClick}
|
|
130
|
+
label={label}
|
|
131
|
+
assistiveText={assistiveText}
|
|
132
|
+
assistiveWithIcon={assistiveWithIcon}
|
|
133
|
+
error={error}
|
|
134
|
+
required={required}
|
|
135
|
+
withAsterisk={withAsterisk}
|
|
136
|
+
id={id}
|
|
137
|
+
readOnly={readOnly}
|
|
138
|
+
readOnlyComponent={readOnlyComponent}
|
|
139
|
+
readOnlyType="text"
|
|
140
|
+
readOnlyValue={
|
|
141
|
+
value !== undefined
|
|
142
|
+
? String(value)
|
|
143
|
+
: defaultValue
|
|
144
|
+
? String(defaultValue)
|
|
145
|
+
: undefined
|
|
146
|
+
}
|
|
147
|
+
activeComponent={
|
|
148
|
+
/* Naked Select execution safely decoupled from Mantine's macro Input.Wrapper DOM hooks */
|
|
149
|
+
<MantineSelect
|
|
150
|
+
ref={ref}
|
|
151
|
+
classNames={mergedClassNames}
|
|
152
|
+
disabled={disabled}
|
|
153
|
+
value={value}
|
|
154
|
+
defaultValue={defaultValue}
|
|
155
|
+
data={data || []}
|
|
156
|
+
label={undefined}
|
|
157
|
+
description={undefined}
|
|
158
|
+
error={undefined}
|
|
159
|
+
required={undefined}
|
|
160
|
+
withAsterisk={undefined}
|
|
161
|
+
wrapperProps={{
|
|
162
|
+
"data-disabled": disabled ? "true" : undefined,
|
|
163
|
+
"data-error": error ? "true" : undefined,
|
|
164
|
+
}}
|
|
165
|
+
{...(sanitizedProps as unknown as MantineSelectProps)}
|
|
166
|
+
/>
|
|
167
|
+
}
|
|
168
|
+
/>
|
|
169
|
+
);
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
Dropdown.displayName = "Dropdown";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# Flex Implementation Notes
|
|
2
|
+
|
|
3
|
+
The `Flex` component is a generic unopinionated flex layout wrapper mapped directly to Mantine's `Flex`.
|
|
4
|
+
It currently does not require any custom logical layouts or CSS workarounds since it serves only to provide absolute, raw manipulation of standard CSS flex properties. All spacing props (gap, align, justify, direction, wrap) pass safely through via the `filterStylingProps` layout-property allowance, with `rec-` dimension tokens scaling transparently mapped to standard gap limits.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Flex } from "./Flex";
|
|
4
|
+
import { Button } from "../Button";
|
|
5
|
+
import { Text } from "../Text/Text";
|
|
6
|
+
|
|
7
|
+
type FlexStoryProps = React.ComponentProps<typeof Flex>;
|
|
8
|
+
|
|
9
|
+
const meta: Meta<FlexStoryProps> = {
|
|
10
|
+
title: "UI-Kit/Flex",
|
|
11
|
+
component: Flex,
|
|
12
|
+
tags: ["autodocs"],
|
|
13
|
+
parameters: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component:
|
|
17
|
+
"Flex is a bare-metal flex container that maps directly to Mantine's Flex component, providing unopinionated control over direction, alignment, and wrapping.",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
args: {
|
|
22
|
+
gap: "rec-default",
|
|
23
|
+
align: "center",
|
|
24
|
+
justify: "flex-start",
|
|
25
|
+
direction: "row",
|
|
26
|
+
wrap: "wrap",
|
|
27
|
+
},
|
|
28
|
+
argTypes: {
|
|
29
|
+
gap: {
|
|
30
|
+
control: "select",
|
|
31
|
+
options: [
|
|
32
|
+
"rec-none",
|
|
33
|
+
"rec-sm",
|
|
34
|
+
"rec-default",
|
|
35
|
+
"rec-md",
|
|
36
|
+
"rec-lg",
|
|
37
|
+
"rec-xl",
|
|
38
|
+
"rec-2xl",
|
|
39
|
+
"xs",
|
|
40
|
+
"sm",
|
|
41
|
+
"md",
|
|
42
|
+
"lg",
|
|
43
|
+
"xl",
|
|
44
|
+
],
|
|
45
|
+
description: "Gap between elements",
|
|
46
|
+
},
|
|
47
|
+
direction: {
|
|
48
|
+
control: "select",
|
|
49
|
+
options: ["row", "column", "row-reverse", "column-reverse"],
|
|
50
|
+
description: "Flex-direction property",
|
|
51
|
+
},
|
|
52
|
+
align: {
|
|
53
|
+
control: "select",
|
|
54
|
+
options: ["flex-start", "center", "flex-end", "stretch"],
|
|
55
|
+
description: "Align-items property",
|
|
56
|
+
},
|
|
57
|
+
justify: {
|
|
58
|
+
control: "select",
|
|
59
|
+
options: [
|
|
60
|
+
"flex-start",
|
|
61
|
+
"center",
|
|
62
|
+
"flex-end",
|
|
63
|
+
"space-between",
|
|
64
|
+
"space-around",
|
|
65
|
+
],
|
|
66
|
+
description: "Justify-content property",
|
|
67
|
+
},
|
|
68
|
+
wrap: {
|
|
69
|
+
control: "select",
|
|
70
|
+
options: ["wrap", "nowrap", "wrap-reverse"],
|
|
71
|
+
description: "Flex-wrap property",
|
|
72
|
+
},
|
|
73
|
+
defaultChecked: {
|
|
74
|
+
table: { disable: true },
|
|
75
|
+
},
|
|
76
|
+
rowGap: {
|
|
77
|
+
table: { disable: true },
|
|
78
|
+
},
|
|
79
|
+
columnGap: {
|
|
80
|
+
table: { disable: true },
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export default meta;
|
|
86
|
+
|
|
87
|
+
type Story = StoryObj<FlexStoryProps>;
|
|
88
|
+
|
|
89
|
+
export const Default: Story = {
|
|
90
|
+
render: (args) => (
|
|
91
|
+
<Flex {...args}>
|
|
92
|
+
<Button variant="solid">Block A</Button>
|
|
93
|
+
<Button variant="outline">Block B</Button>
|
|
94
|
+
<Text>Text inside Flex</Text>
|
|
95
|
+
</Flex>
|
|
96
|
+
),
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const StaticGapSmallColumn: Story = {
|
|
100
|
+
args: {
|
|
101
|
+
gap: "rec-sm",
|
|
102
|
+
direction: "column",
|
|
103
|
+
},
|
|
104
|
+
render: (args) => (
|
|
105
|
+
<Flex {...args}>
|
|
106
|
+
<Button variant="solid">Item 1</Button>
|
|
107
|
+
<Button variant="solid">Item 2</Button>
|
|
108
|
+
<Button variant="solid">Item 3</Button>
|
|
109
|
+
</Flex>
|
|
110
|
+
),
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export const StaticGapLargeRow: Story = {
|
|
114
|
+
args: {
|
|
115
|
+
gap: "rec-xl",
|
|
116
|
+
direction: "row",
|
|
117
|
+
},
|
|
118
|
+
render: (args) => (
|
|
119
|
+
<Flex {...args}>
|
|
120
|
+
<Button variant="solid">Item 1</Button>
|
|
121
|
+
<Button variant="solid">Item 2</Button>
|
|
122
|
+
<Button variant="solid">Item 3</Button>
|
|
123
|
+
</Flex>
|
|
124
|
+
),
|
|
125
|
+
};
|