@recursica/mantine-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/.storybook/commonArgTypes.ts +148 -0
- package/CHANGELOG.md +69 -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 +660 -586
- package/dist/mantine-adapter.js.map +1 -1
- package/dist/src/components/Checkbox/CheckboxGroup.d.ts +1 -1
- package/dist/src/components/Chip/Chip.d.ts +14 -2
- package/package.json +5 -2
- package/src/OverStyling.stories.tsx +174 -0
- package/src/Version.stories.tsx +56 -0
- package/src/components/Accordion/ACCORDION_IMPLEMENTATION_NOTES.md +48 -0
- package/src/components/Accordion/Accordion.module.css +261 -0
- package/src/components/Accordion/Accordion.stories.tsx +145 -0
- package/src/components/Accordion/Accordion.tsx +200 -0
- package/src/components/Accordion/index.ts +1 -0
- package/src/components/AssistiveElement/AssistiveElement.module.css +111 -0
- package/src/components/AssistiveElement/AssistiveElement.stories.tsx +73 -0
- package/src/components/AssistiveElement/AssistiveElement.tsx +91 -0
- package/src/components/Avatar/AVATAR_IMPLEMENTATION_NOTES.md +24 -0
- package/src/components/Avatar/Avatar.module.css +340 -0
- package/src/components/Avatar/Avatar.stories.tsx +102 -0
- package/src/components/Avatar/Avatar.tsx +100 -0
- package/src/components/Avatar/index.ts +1 -0
- package/src/components/Badge/BADGE_IMPLEMENTATION_NOTES.md +18 -0
- package/src/components/Badge/Badge.module.css +124 -0
- package/src/components/Badge/Badge.stories.tsx +77 -0
- package/src/components/Badge/Badge.tsx +66 -0
- package/src/components/Breadcrumb/BREADCRUMB_IMPLEMENTATION_NOTES.md +14 -0
- package/src/components/Breadcrumb/Breadcrumb.module.css +26 -0
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +77 -0
- package/src/components/Breadcrumb/Breadcrumb.tsx +64 -0
- package/src/components/Button/Button.module.css +275 -0
- package/src/components/Button/Button.stories.tsx +105 -0
- package/src/components/Button/Button.tsx +122 -0
- package/src/components/Button/IMPLEMENTATION_NOTES.md +45 -0
- package/src/components/Button/index.ts +1 -0
- package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +10 -0
- package/src/components/Card/Card.module.css +60 -0
- package/src/components/Card/Card.stories.tsx +141 -0
- package/src/components/Card/Card.tsx +176 -0
- package/src/components/Checkbox/CHECKBOX_IMPLEMENTATION_NOTES.md +25 -0
- package/src/components/Checkbox/Checkbox.module.css +204 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +73 -0
- package/src/components/Checkbox/Checkbox.tsx +111 -0
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +138 -0
- package/src/components/Checkbox/CheckboxGroup.tsx +140 -0
- package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +35 -0
- package/src/components/Chip/Chip.module.css +218 -0
- package/src/components/Chip/Chip.stories.tsx +115 -0
- package/src/components/Chip/Chip.tsx +143 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +22 -0
- package/src/components/DatePicker/DatePicker.tsx +7 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +22 -0
- package/src/components/Dropdown/Dropdown.tsx +7 -0
- package/src/components/FileInput/FileInput.stories.tsx +22 -0
- package/src/components/FileInput/FileInput.tsx +7 -0
- package/src/components/FileUpload/FileUpload.stories.tsx +22 -0
- package/src/components/FileUpload/FileUpload.tsx +7 -0
- package/src/components/FormControlWrapper/FORMCONTROLWRAPPER_IMPLEMENTATION_NOTES.md +32 -0
- package/src/components/FormControlWrapper/FormControlWrapper.module.css +46 -0
- package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +116 -0
- package/src/components/FormControlWrapper/FormControlWrapper.tsx +170 -0
- package/src/components/HoverCard/HoverCard.stories.tsx +17 -0
- package/src/components/HoverCard/HoverCard.tsx +7 -0
- package/src/components/Label/LABEL_IMPLEMENTATION_NOTES.md +48 -0
- package/src/components/Label/Label.module.css +177 -0
- package/src/components/Label/Label.stories.tsx +123 -0
- package/src/components/Label/Label.tsx +132 -0
- package/src/components/Label/index.ts +1 -0
- package/src/components/Link/Link.stories.tsx +17 -0
- package/src/components/Link/Link.tsx +7 -0
- package/src/components/Loader/Loader.stories.tsx +17 -0
- package/src/components/Loader/Loader.tsx +7 -0
- package/src/components/Menu/Menu.stories.tsx +17 -0
- package/src/components/Menu/Menu.tsx +7 -0
- package/src/components/Modal/Modal.stories.tsx +17 -0
- package/src/components/Modal/Modal.tsx +7 -0
- package/src/components/NumberInput/NumberInput.stories.tsx +22 -0
- package/src/components/NumberInput/NumberInput.tsx +7 -0
- package/src/components/Pagination/Pagination.stories.tsx +17 -0
- package/src/components/Pagination/Pagination.tsx +7 -0
- package/src/components/Panel/Panel.stories.tsx +17 -0
- package/src/components/Panel/Panel.tsx +7 -0
- package/src/components/Popover/Popover.stories.tsx +17 -0
- package/src/components/Popover/Popover.tsx +7 -0
- package/src/components/Radio/Radio.stories.tsx +22 -0
- package/src/components/Radio/Radio.tsx +7 -0
- package/src/components/ReadOnlyField/READ_ONLY_FIELD_IMPLEMENTATION_NOTES.md +15 -0
- package/src/components/ReadOnlyField/ReadOnlyField.module.css +49 -0
- package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +120 -0
- package/src/components/ReadOnlyField/ReadOnlyField.tsx +75 -0
- package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +46 -0
- package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +85 -0
- package/src/components/ReadOnlyField/index.ts +3 -0
- package/src/components/Search/Search.stories.tsx +17 -0
- package/src/components/Search/Search.tsx +7 -0
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +22 -0
- package/src/components/SegmentedControl/SegmentedControl.tsx +7 -0
- package/src/components/Slider/Slider.stories.tsx +22 -0
- package/src/components/Slider/Slider.tsx +7 -0
- package/src/components/Stepper/Stepper.stories.tsx +17 -0
- package/src/components/Stepper/Stepper.tsx +7 -0
- package/src/components/Switch/Switch.stories.tsx +22 -0
- package/src/components/Switch/Switch.tsx +7 -0
- package/src/components/Table/Table.stories.tsx +17 -0
- package/src/components/Table/Table.tsx +7 -0
- package/src/components/Tabs/Tabs.stories.tsx +17 -0
- package/src/components/Tabs/Tabs.tsx +7 -0
- package/src/components/Text/Text.stories.tsx +88 -0
- package/src/components/Text/Text.tsx +54 -0
- package/src/components/TextArea/TextArea.stories.tsx +22 -0
- package/src/components/TextArea/TextArea.tsx +7 -0
- package/src/components/TextField/TEXTFIELD_IMPLEMENTATION_NOTES.md +19 -0
- package/src/components/TextField/TextField.module.css +225 -0
- package/src/components/TextField/TextField.stories.tsx +162 -0
- package/src/components/TextField/TextField.tsx +138 -0
- package/src/components/TimePicker/TimePicker.stories.tsx +22 -0
- package/src/components/TimePicker/TimePicker.tsx +7 -0
- package/src/components/Timeline/Timeline.stories.tsx +17 -0
- package/src/components/Timeline/Timeline.tsx +7 -0
- package/src/components/Title/Title.stories.tsx +63 -0
- package/src/components/Title/Title.tsx +45 -0
- package/src/components/Toast/Toast.stories.tsx +17 -0
- package/src/components/Toast/Toast.tsx +7 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +17 -0
- package/src/components/Tooltip/Tooltip.tsx +7 -0
- package/src/components/TransferList/TransferList.stories.tsx +17 -0
- package/src/components/TransferList/TransferList.tsx +7 -0
- package/src/components/index.ts +39 -0
- package/src/env.d.ts +7 -0
- package/src/index.ts +3 -0
- package/src/types/index.ts +9 -0
- package/src/types/mantine.d.ts +7 -0
- package/src/types/scss-modules.d.ts +9 -0
- package/src/utils/ColorSchemeWrapper.tsx +27 -0
- package/src/utils/copyToClipboard.ts +36 -0
- package/src/utils/filterStylingProps.ts +139 -0
- package/src/utils/index.ts +1 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { ReadOnlyField } from "./ReadOnlyField";
|
|
4
|
+
import { EmptyValueRenderer } from "@recursica/adapter-common";
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof ReadOnlyField> = {
|
|
7
|
+
title: "UI Kit/ReadOnlyField",
|
|
8
|
+
component: ReadOnlyField,
|
|
9
|
+
tags: ["autodocs"],
|
|
10
|
+
parameters: {
|
|
11
|
+
docs: {
|
|
12
|
+
description: {
|
|
13
|
+
component:
|
|
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.",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
args: {
|
|
19
|
+
label: "Read Only Label",
|
|
20
|
+
value: "Fixed Data Set Value",
|
|
21
|
+
assistiveText: "Helper description text beneath the node.",
|
|
22
|
+
type: "text",
|
|
23
|
+
},
|
|
24
|
+
argTypes: {
|
|
25
|
+
type: {
|
|
26
|
+
control: "select",
|
|
27
|
+
options: ["text", "number"], // Add more as we support them
|
|
28
|
+
},
|
|
29
|
+
labelWithEditIcon: {
|
|
30
|
+
control: "boolean",
|
|
31
|
+
},
|
|
32
|
+
// We cannot natively control a React.ElementType through standard primitive storybook panels.
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default meta;
|
|
37
|
+
|
|
38
|
+
type Story = StoryObj<typeof ReadOnlyField>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Playground story demonstrating standard structural blocks of the ReadOnlyField module dynamically.
|
|
42
|
+
*/
|
|
43
|
+
export const Default: Story = {
|
|
44
|
+
args: {},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Shows the default handler replacing missing mapping data directly with 'N/A'.
|
|
49
|
+
*/
|
|
50
|
+
export const EmptyValue: Story = {
|
|
51
|
+
args: {
|
|
52
|
+
value: "",
|
|
53
|
+
label: "Empty String Evaluated Automatically (Default 'N/A')",
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const CustomEmptyTextRenderer: React.FC<{ value?: any }> & {
|
|
58
|
+
check?: (v: any) => boolean;
|
|
59
|
+
} = (props) => <EmptyValueRenderer {...props} emptyText="No Data Found" />;
|
|
60
|
+
CustomEmptyTextRenderer.check = EmptyValueRenderer.check;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Demonstrates overriding the baseline verbiage internally utilizing the exported `EmptyValueRenderer` while inheriting default evaluation checks.
|
|
64
|
+
*/
|
|
65
|
+
export const CustomEmptyText: Story = {
|
|
66
|
+
args: {
|
|
67
|
+
value: null,
|
|
68
|
+
label: "Custom Empty Text Default",
|
|
69
|
+
emptyValueComponent: CustomEmptyTextRenderer,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const CustomEmptyCheckRenderer: React.FC<{ value?: any }> & {
|
|
74
|
+
check?: (v: any) => boolean;
|
|
75
|
+
} = () => {
|
|
76
|
+
return <i>Custom HTML Markup Provided</i>;
|
|
77
|
+
};
|
|
78
|
+
CustomEmptyCheckRenderer.check = (val) => val === "EMPTY_MOCK";
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Validates a fully overridden emptyValueComponent injecting custom rendering boundaries alongside explicitly tailored validation rules evaluating datasets dynamically.
|
|
82
|
+
*/
|
|
83
|
+
export const CustomEmptyRenderer: Story = {
|
|
84
|
+
args: {
|
|
85
|
+
value: "EMPTY_MOCK",
|
|
86
|
+
label: "Custom Logic Evaluation Binding",
|
|
87
|
+
emptyValueComponent: CustomEmptyCheckRenderer,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Validates the core read-only label execution and base default spacing bindings globally.
|
|
93
|
+
*/
|
|
94
|
+
export const StackedDefault: Story = {
|
|
95
|
+
args: {
|
|
96
|
+
formLayout: "stacked",
|
|
97
|
+
value: "Some fixed readable text",
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Binds side-by-side structures globally maintaining correct inline gutter layouts.
|
|
103
|
+
*/
|
|
104
|
+
export const SideBySide: Story = {
|
|
105
|
+
args: {
|
|
106
|
+
formLayout: "side-by-side",
|
|
107
|
+
value: "Some fixed readable text mapping horizontally",
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Tests the fallback structural logic when Edit icon natively overrides required bindings.
|
|
113
|
+
*/
|
|
114
|
+
export const WithEditIcon: Story = {
|
|
115
|
+
args: {
|
|
116
|
+
labelWithEditIcon: true,
|
|
117
|
+
required: true,
|
|
118
|
+
value: "Editable fixed structure",
|
|
119
|
+
},
|
|
120
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import React, { forwardRef } from "react";
|
|
3
|
+
import {
|
|
4
|
+
ReadOnlyFieldType,
|
|
5
|
+
EmptyValueRenderer,
|
|
6
|
+
} from "@recursica/adapter-common";
|
|
7
|
+
import {
|
|
8
|
+
filterStylingProps,
|
|
9
|
+
type RecursicaOverStyled,
|
|
10
|
+
} from "../../utils/filterStylingProps";
|
|
11
|
+
import {
|
|
12
|
+
type FormControlWrapperProps,
|
|
13
|
+
FormControlWrapper,
|
|
14
|
+
} from "../FormControlWrapper/FormControlWrapper";
|
|
15
|
+
import { ReadOnlyTextField } from "./ReadOnlyTextField";
|
|
16
|
+
|
|
17
|
+
export interface RecursicaReadOnlyFieldProps
|
|
18
|
+
extends Omit<FormControlWrapperProps, "children" | "overStyled"> {
|
|
19
|
+
/** The specific value to be rendered in read-only mode explicitly matching the original field input */
|
|
20
|
+
value?: any;
|
|
21
|
+
/** The data type formatting rules bounding how the string is presented to the user */
|
|
22
|
+
type?: ReadOnlyFieldType;
|
|
23
|
+
/** Custom renderer explicitly responsible for formatting missing/empty value mappings (overriding default 'N/A') */
|
|
24
|
+
emptyValueComponent?: React.ElementType<{ value?: any }>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type ReadOnlyFieldProps =
|
|
28
|
+
RecursicaOverStyled<RecursicaReadOnlyFieldProps>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A native generic form control wrapper exclusively responsible for displaying fixed data.
|
|
32
|
+
* Internally maps to structural ReadOnly primitive blocks bridging standard `FormControlWrapper` layouts natively.
|
|
33
|
+
*/
|
|
34
|
+
export const ReadOnlyField = forwardRef<HTMLDivElement, ReadOnlyFieldProps>(
|
|
35
|
+
function ReadOnlyField(
|
|
36
|
+
{ value, type = "text", emptyValueComponent, overStyled = false, ...rest },
|
|
37
|
+
ref,
|
|
38
|
+
) {
|
|
39
|
+
let content: React.ReactNode = null;
|
|
40
|
+
|
|
41
|
+
// We still pass sanitized properties (like className/style/etc) strictly down.
|
|
42
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
43
|
+
|
|
44
|
+
const Renderer = emptyValueComponent || EmptyValueRenderer;
|
|
45
|
+
const isValueEmpty = (Renderer as any).check
|
|
46
|
+
? (Renderer as any).check(value)
|
|
47
|
+
: EmptyValueRenderer.check(value);
|
|
48
|
+
|
|
49
|
+
const displayValue = isValueEmpty ? <Renderer value={value} /> : value;
|
|
50
|
+
|
|
51
|
+
switch (type) {
|
|
52
|
+
case "text":
|
|
53
|
+
default:
|
|
54
|
+
content = (
|
|
55
|
+
<ReadOnlyTextField
|
|
56
|
+
value={displayValue}
|
|
57
|
+
overStyled={overStyled as true}
|
|
58
|
+
/>
|
|
59
|
+
);
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<FormControlWrapper
|
|
65
|
+
ref={ref}
|
|
66
|
+
overStyled={overStyled as true}
|
|
67
|
+
{...(sanitizedProps as any)}
|
|
68
|
+
>
|
|
69
|
+
{content}
|
|
70
|
+
</FormControlWrapper>
|
|
71
|
+
);
|
|
72
|
+
},
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
ReadOnlyField.displayName = "ReadOnlyField";
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Box } from "@mantine/core";
|
|
4
|
+
import {
|
|
5
|
+
filterStylingProps,
|
|
6
|
+
type RecursicaOverStyled,
|
|
7
|
+
} from "../../utils/filterStylingProps";
|
|
8
|
+
import styles from "./ReadOnlyField.module.css";
|
|
9
|
+
|
|
10
|
+
export interface RecursicaReadOnlyTextFieldProps {
|
|
11
|
+
/** The value strictly rendered as text output */
|
|
12
|
+
value?: any;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type ReadOnlyTextFieldProps =
|
|
16
|
+
RecursicaOverStyled<RecursicaReadOnlyTextFieldProps>;
|
|
17
|
+
|
|
18
|
+
export const ReadOnlyTextField: React.FC<ReadOnlyTextFieldProps> = ({
|
|
19
|
+
value,
|
|
20
|
+
overStyled = false,
|
|
21
|
+
...rest
|
|
22
|
+
}) => {
|
|
23
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
24
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
25
|
+
.className as string | undefined;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Box
|
|
29
|
+
component="p"
|
|
30
|
+
className={
|
|
31
|
+
classNameProp
|
|
32
|
+
? `${styles.textField} ${classNameProp}`
|
|
33
|
+
: styles.textField
|
|
34
|
+
}
|
|
35
|
+
{...sanitizedProps}
|
|
36
|
+
>
|
|
37
|
+
{value != null
|
|
38
|
+
? React.isValidElement(value)
|
|
39
|
+
? value
|
|
40
|
+
: String(value)
|
|
41
|
+
: ""}
|
|
42
|
+
</Box>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
ReadOnlyTextField.displayName = "ReadOnlyTextField";
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import React, { forwardRef } from "react";
|
|
3
|
+
import { type ReadOnlyFieldType } from "@recursica/adapter-common";
|
|
4
|
+
import {
|
|
5
|
+
FormControlWrapper,
|
|
6
|
+
type FormControlWrapperProps,
|
|
7
|
+
} from "../FormControlWrapper/FormControlWrapper";
|
|
8
|
+
import { ReadOnlyField } from "./ReadOnlyField";
|
|
9
|
+
|
|
10
|
+
export interface WithReadOnlyWrapperProps
|
|
11
|
+
extends Omit<FormControlWrapperProps, "children" | "overStyled"> {
|
|
12
|
+
/** Injects whether the field defaults to reading mode natively */
|
|
13
|
+
readOnly?: boolean;
|
|
14
|
+
/** Explicit React component directly overtaking the baseline text renderer when read-only mode is active */
|
|
15
|
+
readOnlyComponent?: React.ReactNode;
|
|
16
|
+
/** Instructs the underlying generic ReadOnlyField which raw visual structure to bridge automatically */
|
|
17
|
+
readOnlyType?: ReadOnlyFieldType;
|
|
18
|
+
/** The isolated raw data value intercepted explicitly into the ReadOnly formatters */
|
|
19
|
+
readOnlyValue?: any;
|
|
20
|
+
/** Safely enables deep Mantine overrides transparently bypassing block filters */
|
|
21
|
+
overStyled?: boolean;
|
|
22
|
+
/** The nested active node dynamically exposed exclusively when read-only bounds are disabled */
|
|
23
|
+
activeComponent: React.ReactNode;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Universal execution barrier trapping readOnly states globally.
|
|
28
|
+
* Natively delegates active logic down avoiding duplicative internal component bindings dynamically.
|
|
29
|
+
*/
|
|
30
|
+
export const WithReadOnlyWrapper = forwardRef<
|
|
31
|
+
HTMLDivElement,
|
|
32
|
+
WithReadOnlyWrapperProps
|
|
33
|
+
>(function WithReadOnlyWrapper(
|
|
34
|
+
{
|
|
35
|
+
readOnly,
|
|
36
|
+
readOnlyComponent,
|
|
37
|
+
readOnlyType = "text",
|
|
38
|
+
readOnlyValue,
|
|
39
|
+
activeComponent,
|
|
40
|
+
overStyled,
|
|
41
|
+
onLabelEditClick,
|
|
42
|
+
...wrapperProps
|
|
43
|
+
},
|
|
44
|
+
ref,
|
|
45
|
+
) {
|
|
46
|
+
if (readOnly) {
|
|
47
|
+
if (readOnlyComponent) {
|
|
48
|
+
return (
|
|
49
|
+
<FormControlWrapper
|
|
50
|
+
ref={ref}
|
|
51
|
+
{...wrapperProps}
|
|
52
|
+
onLabelEditClick={onLabelEditClick}
|
|
53
|
+
overStyled={overStyled as true}
|
|
54
|
+
>
|
|
55
|
+
{readOnlyComponent}
|
|
56
|
+
</FormControlWrapper>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<ReadOnlyField
|
|
62
|
+
ref={ref}
|
|
63
|
+
type={readOnlyType}
|
|
64
|
+
value={readOnlyValue}
|
|
65
|
+
onLabelEditClick={onLabelEditClick}
|
|
66
|
+
overStyled={overStyled as true}
|
|
67
|
+
{...wrapperProps}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Active Standard Execution natively forwarding bound children implicitly
|
|
73
|
+
return (
|
|
74
|
+
<FormControlWrapper
|
|
75
|
+
ref={ref}
|
|
76
|
+
{...wrapperProps}
|
|
77
|
+
onLabelEditClick={onLabelEditClick}
|
|
78
|
+
overStyled={overStyled as true}
|
|
79
|
+
>
|
|
80
|
+
{activeComponent}
|
|
81
|
+
</FormControlWrapper>
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
WithReadOnlyWrapper.displayName = "WithReadOnlyWrapper";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Search } from "./Search";
|
|
3
|
+
import { ComingSoon } from "@recursica/storybook-template";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Search> = {
|
|
6
|
+
title: "UI-Kit/🚧 Search",
|
|
7
|
+
component: Search,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default meta;
|
|
12
|
+
|
|
13
|
+
type Story = StoryObj<typeof Search>;
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
render: () => <ComingSoon componentName="Search" />,
|
|
17
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { SegmentedControl } from "./SegmentedControl";
|
|
3
|
+
import { ComingSoon } from "@recursica/storybook-template";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof SegmentedControl> = {
|
|
6
|
+
title: "UI-Kit/🚧 SegmentedControl",
|
|
7
|
+
component: SegmentedControl,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
argTypes: {
|
|
10
|
+
disabled: {
|
|
11
|
+
control: "boolean",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default meta;
|
|
17
|
+
|
|
18
|
+
type Story = StoryObj<typeof SegmentedControl>;
|
|
19
|
+
|
|
20
|
+
export const Default: Story = {
|
|
21
|
+
render: () => <ComingSoon componentName="SegmentedControl" />,
|
|
22
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Slider } from "./Slider";
|
|
3
|
+
import { ComingSoon } from "@recursica/storybook-template";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Slider> = {
|
|
6
|
+
title: "UI-Kit/🚧 Slider",
|
|
7
|
+
component: Slider,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
argTypes: {
|
|
10
|
+
disabled: {
|
|
11
|
+
control: "boolean",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default meta;
|
|
17
|
+
|
|
18
|
+
type Story = StoryObj<typeof Slider>;
|
|
19
|
+
|
|
20
|
+
export const Default: Story = {
|
|
21
|
+
render: () => <ComingSoon componentName="Slider" />,
|
|
22
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Stepper } from "./Stepper";
|
|
3
|
+
import { ComingSoon } from "@recursica/storybook-template";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Stepper> = {
|
|
6
|
+
title: "UI-Kit/🚧 Stepper",
|
|
7
|
+
component: Stepper,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default meta;
|
|
12
|
+
|
|
13
|
+
type Story = StoryObj<typeof Stepper>;
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
render: () => <ComingSoon componentName="Stepper" />,
|
|
17
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Switch } from "./Switch";
|
|
3
|
+
import { ComingSoon } from "@recursica/storybook-template";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Switch> = {
|
|
6
|
+
title: "UI-Kit/🚧 Switch",
|
|
7
|
+
component: Switch,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
argTypes: {
|
|
10
|
+
disabled: {
|
|
11
|
+
control: "boolean",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default meta;
|
|
17
|
+
|
|
18
|
+
type Story = StoryObj<typeof Switch>;
|
|
19
|
+
|
|
20
|
+
export const Default: Story = {
|
|
21
|
+
render: () => <ComingSoon componentName="Switch" />,
|
|
22
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Table } from "./Table";
|
|
3
|
+
import { ComingSoon } from "@recursica/storybook-template";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Table> = {
|
|
6
|
+
title: "UI-Kit/🚧 Table",
|
|
7
|
+
component: Table,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default meta;
|
|
12
|
+
|
|
13
|
+
type Story = StoryObj<typeof Table>;
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
render: () => <ComingSoon componentName="Table" />,
|
|
17
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Tabs } from "./Tabs";
|
|
3
|
+
import { ComingSoon } from "@recursica/storybook-template";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Tabs> = {
|
|
6
|
+
title: "UI-Kit/🚧 Tabs",
|
|
7
|
+
component: Tabs,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default meta;
|
|
12
|
+
|
|
13
|
+
type Story = StoryObj<typeof Tabs>;
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
render: () => <ComingSoon componentName="Tabs" />,
|
|
17
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Text } from "./Text";
|
|
3
|
+
import { Layer } from "@recursica/adapter-common";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Text> = {
|
|
6
|
+
title: "UI-Kit/Text",
|
|
7
|
+
component: Text,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component:
|
|
13
|
+
"The standard `<Text>` component controls common body sizing scales and implicit paragraphs governed by the active theme layer. For semantic headings (`h1` through `h6`), use `<Title>` instead.",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
argTypes: {
|
|
18
|
+
variant: {
|
|
19
|
+
control: "select",
|
|
20
|
+
options: [
|
|
21
|
+
"body",
|
|
22
|
+
"body-small",
|
|
23
|
+
"caption",
|
|
24
|
+
"overline",
|
|
25
|
+
"subtitle",
|
|
26
|
+
"subtitle-small",
|
|
27
|
+
],
|
|
28
|
+
description:
|
|
29
|
+
"Controls the standard logical boundary definitions natively extracted from Figma.",
|
|
30
|
+
},
|
|
31
|
+
c: {
|
|
32
|
+
control: "text",
|
|
33
|
+
description:
|
|
34
|
+
"Standard Mantine color string mapped via internal boundaries. Example: `dimmed`",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default meta;
|
|
40
|
+
|
|
41
|
+
type Story = StoryObj<typeof Text>;
|
|
42
|
+
|
|
43
|
+
export const Default: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
variant: "body",
|
|
46
|
+
children:
|
|
47
|
+
"This is standard body typography controlled by the central UI-kit boundaries exclusively.",
|
|
48
|
+
},
|
|
49
|
+
render: ({ ...args }) => (
|
|
50
|
+
<Layer layer={0} style={{ padding: "48px" }}>
|
|
51
|
+
<Text {...args} />
|
|
52
|
+
</Layer>
|
|
53
|
+
),
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const StaticVariations: Story = {
|
|
57
|
+
args: {},
|
|
58
|
+
render: () => (
|
|
59
|
+
<Layer
|
|
60
|
+
layer={0}
|
|
61
|
+
style={{
|
|
62
|
+
padding: "48px",
|
|
63
|
+
display: "flex",
|
|
64
|
+
flexDirection: "column",
|
|
65
|
+
gap: "16px",
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
<Text variant="body">
|
|
69
|
+
Body (Base paragraph and generic information flow)
|
|
70
|
+
</Text>
|
|
71
|
+
<Text variant="body-small">
|
|
72
|
+
Body Small (Compacted list items and helper blocks)
|
|
73
|
+
</Text>
|
|
74
|
+
<Text variant="caption">
|
|
75
|
+
Caption (Data table descriptions or micro-labels)
|
|
76
|
+
</Text>
|
|
77
|
+
<Text variant="overline">
|
|
78
|
+
Overline (Card contextual pre-headers and categorical tags)
|
|
79
|
+
</Text>
|
|
80
|
+
<Text variant="subtitle">
|
|
81
|
+
Subtitle (Minor sub-headers avoiding heavy display weights)
|
|
82
|
+
</Text>
|
|
83
|
+
<Text variant="subtitle-small">
|
|
84
|
+
Subtitle Small (Section anchors deep in hierarchy)
|
|
85
|
+
</Text>
|
|
86
|
+
</Layer>
|
|
87
|
+
),
|
|
88
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { forwardRef, type ReactNode } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Text as MantineText,
|
|
4
|
+
type TextProps as MantineTextProps,
|
|
5
|
+
} from "@mantine/core";
|
|
6
|
+
import {
|
|
7
|
+
filterStylingProps,
|
|
8
|
+
type RecursicaOverStyled,
|
|
9
|
+
} from "../../utils/filterStylingProps";
|
|
10
|
+
|
|
11
|
+
export type TextVariant =
|
|
12
|
+
| "body"
|
|
13
|
+
| "body-small"
|
|
14
|
+
| "caption"
|
|
15
|
+
| "overline"
|
|
16
|
+
| "subtitle"
|
|
17
|
+
| "subtitle-small";
|
|
18
|
+
|
|
19
|
+
export type RecursicaTextProps = Omit<MantineTextProps, "variant"> & {
|
|
20
|
+
/**
|
|
21
|
+
* The explicit typography hierarchy dictated by Recursica's global design tokens.
|
|
22
|
+
*/
|
|
23
|
+
variant?: TextVariant;
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type TextProps = RecursicaOverStyled<RecursicaTextProps>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* A generalized typographical wrapper limiting text properties to bounded Recursica UI-kit tokens inherently.
|
|
31
|
+
* Do not use for semantic headings; use the explicit `<Title>` component for `<h1>` - `<h6>`.
|
|
32
|
+
*/
|
|
33
|
+
export const Text = forwardRef<HTMLDivElement, TextProps>(function Text(
|
|
34
|
+
{ overStyled = false, variant = "body", ...rest },
|
|
35
|
+
ref,
|
|
36
|
+
) {
|
|
37
|
+
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
38
|
+
const classNameProp = (sanitizedProps as Record<string, unknown>)
|
|
39
|
+
.className as string | undefined;
|
|
40
|
+
|
|
41
|
+
const typographyClass = `recursica_brand_typography_${variant}`;
|
|
42
|
+
const mergedClassName = classNameProp
|
|
43
|
+
? `${typographyClass} ${classNameProp}`
|
|
44
|
+
: typographyClass;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<MantineText
|
|
48
|
+
ref={ref}
|
|
49
|
+
className={mergedClassName}
|
|
50
|
+
{...(sanitizedProps as unknown as MantineTextProps)}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
Text.displayName = "Text";
|