@recursica/mantine-adapter 0.10.0 → 0.12.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 +16 -0
- package/README.md +6 -28
- 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 +1650 -1344
- package/dist/mantine-adapter.js.map +1 -1
- package/dist/src/components/Checkbox/Checkbox.d.ts +3 -1
- package/dist/src/components/FormControlLayout/FormControlLayout.d.ts +21 -0
- package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +2 -0
- package/dist/src/components/Label/Label.d.ts +1 -3
- package/dist/src/components/Menu/Menu.d.ts +85 -3
- package/dist/src/components/Radio/Radio.d.ts +3 -1
- package/dist/src/components/ReadOnlyField/ReadOnlyBooleanField.d.ts +5 -0
- package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +6 -6
- package/dist/src/components/ReadOnlyField/ReadOnlySwitchField.d.ts +5 -0
- package/dist/src/components/ReadOnlyField/WithReadOnlyWrapper.d.ts +7 -1
- package/dist/src/components/ReadOnlyField/index.d.ts +2 -0
- package/dist/src/components/Switch/Switch.d.ts +3 -1
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/utils/RequireAccessibleLabel.d.ts +18 -0
- package/package.json +1 -1
- package/src/components/AssistiveElement/AssistiveElement.stories.tsx +6 -4
- package/src/components/Avatar/Avatar.stories.tsx +10 -5
- package/src/components/Badge/Badge.stories.tsx +2 -1
- package/src/components/Button/Button.stories.tsx +2 -4
- package/src/components/Checkbox/Checkbox.module.css +1 -1
- package/src/components/Checkbox/Checkbox.stories.tsx +24 -3
- package/src/components/Checkbox/Checkbox.tsx +72 -15
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +26 -25
- package/src/components/Checkbox/CheckboxGroup.tsx +38 -58
- package/src/components/Container/Container.stories.tsx +6 -3
- package/src/components/DatePicker/DatePicker.stories.tsx +1 -5
- package/src/components/Dropdown/Dropdown.stories.tsx +0 -3
- package/src/components/Dropdown/Dropdown.tsx +6 -5
- package/src/components/FileInput/FileInput.stories.tsx +1 -5
- package/src/components/FileUpload/FileUpload.stories.tsx +1 -5
- package/src/components/Flex/Flex.stories.tsx +6 -3
- package/src/components/FormControlLayout/FormControlLayout.module.css +80 -0
- package/src/components/FormControlLayout/FormControlLayout.stories.tsx +82 -0
- package/src/components/FormControlLayout/FormControlLayout.tsx +78 -0
- package/src/components/FormControlWrapper/FormControlWrapper.module.css +3 -41
- package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +18 -5
- package/src/components/FormControlWrapper/FormControlWrapper.tsx +28 -41
- package/src/components/Group/Group.stories.tsx +6 -3
- package/src/components/Label/Label.module.css +0 -37
- package/src/components/Label/Label.stories.tsx +8 -9
- package/src/components/Label/Label.tsx +2 -7
- package/src/components/Loader/Loader.stories.tsx +10 -5
- package/src/components/Menu/MENU_IMPLEMENTATION_NOTES.md +78 -0
- package/src/components/Menu/Menu.module.css +244 -0
- package/src/components/Menu/Menu.stories.tsx +309 -5
- package/src/components/Menu/Menu.tsx +317 -4
- package/src/components/NumberInput/NumberInput.stories.tsx +1 -5
- package/src/components/Radio/Radio.stories.tsx +22 -8
- package/src/components/Radio/Radio.tsx +134 -75
- package/src/components/Radio/RadioGroup.stories.tsx +26 -7
- package/src/components/Radio/RadioGroup.tsx +37 -57
- package/src/components/ReadOnlyField/ReadOnlyBooleanField.tsx +21 -0
- package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +43 -0
- package/src/components/ReadOnlyField/ReadOnlyField.tsx +30 -3
- package/src/components/ReadOnlyField/ReadOnlySwitchField.tsx +21 -0
- package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +3 -1
- package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +10 -2
- package/src/components/ReadOnlyField/index.ts +2 -0
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +1 -5
- package/src/components/Slider/Slider.stories.tsx +1 -5
- package/src/components/Stack/Stack.stories.tsx +6 -3
- package/src/components/Switch/Switch.module.css +2 -10
- package/src/components/Switch/Switch.stories.tsx +42 -27
- package/src/components/Switch/Switch.tsx +138 -89
- package/src/components/Switch/SwitchGroup.stories.tsx +28 -8
- package/src/components/Switch/SwitchGroup.tsx +37 -57
- package/src/components/TextArea/TextArea.stories.tsx +0 -3
- package/src/components/TextArea/TextArea.tsx +6 -5
- package/src/components/TextField/TextField.tsx +6 -5
- package/src/components/TimePicker/TimePicker.stories.tsx +1 -5
- package/src/components/index.ts +1 -0
- package/src/utils/RequireAccessibleLabel.ts +12 -0
|
@@ -2,7 +2,9 @@ import { CheckboxProps as MantineCheckboxProps } from '@mantine/core';
|
|
|
2
2
|
import { ReadOnlyControlProps } from '@recursica/adapter-common';
|
|
3
3
|
import { CheckboxGroup } from './CheckboxGroup';
|
|
4
4
|
import { RecursicaOverStyled } from '../../utils/filterStylingProps';
|
|
5
|
-
|
|
5
|
+
import { RequireAccessibleLabel } from '../../utils/RequireAccessibleLabel';
|
|
6
|
+
import { FormControlLayoutProps } from '../FormControlLayout/FormControlLayout';
|
|
7
|
+
export type RecursicaCheckboxProps = RequireAccessibleLabel<Omit<MantineCheckboxProps, "size" | "color" | "radius" | "iconColor" | "variant"> & ReadOnlyControlProps & Pick<FormControlLayoutProps, "formLayout" | "labelSize" | "controlMaxWidth" | "controlMinWidth">>;
|
|
6
8
|
export type CheckboxProps = RecursicaOverStyled<RecursicaCheckboxProps>;
|
|
7
9
|
type CheckboxComponent = React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>> & {
|
|
8
10
|
Group: typeof CheckboxGroup;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export interface FormControlLayoutProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
formLayout?: "stacked" | "side-by-side";
|
|
4
|
+
labelSize?: "default" | "small" | "md";
|
|
5
|
+
controlMaxWidth?: string;
|
|
6
|
+
controlMinWidth?: string;
|
|
7
|
+
leftSection?: React.ReactNode;
|
|
8
|
+
children?: React.ReactNode;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A layout component used to correctly position form inputs alongside their labels.
|
|
12
|
+
*
|
|
13
|
+
* **When to use this:**
|
|
14
|
+
* Typically, you should use `FormControlWrapper` instead, which uses this component
|
|
15
|
+
* under the hood to handle layout automatically.
|
|
16
|
+
*
|
|
17
|
+
* However, this component is useful when you need to align standalone inputs
|
|
18
|
+
* (like a `Switch` or `Checkbox` without a label) so they perfectly match the spacing
|
|
19
|
+
* and alignment of your other form fields in a `side-by-side` layout.
|
|
20
|
+
*/
|
|
21
|
+
export declare const FormControlLayout: React.ForwardRefExoticComponent<FormControlLayoutProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -3,6 +3,8 @@ import { InputWrapperProps } from '@mantine/core';
|
|
|
3
3
|
import { RecursicaOverStyled } from '../../utils/filterStylingProps';
|
|
4
4
|
import { RecursicaLabelProps } from '../Label/Label';
|
|
5
5
|
export interface RecursicaFormControlWrapperProps extends RecursicaLabelProps {
|
|
6
|
+
/** Overall structural flow mapping the Form Control natively cascading down to Label and Input logic. */
|
|
7
|
+
formLayout?: "stacked" | "side-by-side";
|
|
6
8
|
/** Securely replaces standard Mantine descriptions safely providing standard Assistive properties. */
|
|
7
9
|
assistiveText?: React.ReactNode;
|
|
8
10
|
/** Explicit toggle to suppress the Info icon rendering natively alongside the assistiveText. Defaults to true. */
|
|
@@ -2,10 +2,8 @@ import { default as React } from 'react';
|
|
|
2
2
|
import { InputLabelProps } from '@mantine/core';
|
|
3
3
|
import { RecursicaOverStyled } from '../../utils/filterStylingProps';
|
|
4
4
|
export interface RecursicaLabelProps {
|
|
5
|
-
/** Overall structural flow mapping the Form Control natively cascading down to Label and Input logic. */
|
|
6
|
-
formLayout?: "stacked" | "side-by-side";
|
|
7
5
|
/** Specifies the sizing metrics natively mapping the Label boundaries. */
|
|
8
|
-
labelSize?: "default" | "small";
|
|
6
|
+
labelSize?: "default" | "small" | "md";
|
|
9
7
|
/** Overall alignment directive for the label strings natively forcing Left/Right justification. */
|
|
10
8
|
labelAlignment?: "left" | "right";
|
|
11
9
|
/** Injects an indicator text block alongside the label. Can be boolean (`true` maps to '(Optional)') or custom React nodes. */
|
|
@@ -1,3 +1,85 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { MenuProps as MantineMenuProps, MenuTargetProps as MantineMenuTargetProps, MenuDropdownProps as MantineMenuDropdownProps, MenuItemProps as MantineMenuItemProps, MenuDividerProps as MantineMenuDividerProps, MenuLabelProps as MantineMenuLabelProps, MenuSubProps as MantineMenuSubProps, MenuSubTargetProps as MantineMenuSubTargetProps, MenuSubDropdownProps as MantineMenuSubDropdownProps } from '@mantine/core';
|
|
2
|
+
import { RecursicaOverStyled } from '../../utils/filterStylingProps';
|
|
3
|
+
/**
|
|
4
|
+
* Recursica Menu component wrapping Mantine's composable Menu.
|
|
5
|
+
*
|
|
6
|
+
* Usage follows the composable dot-notation pattern:
|
|
7
|
+
* ```tsx
|
|
8
|
+
* <Menu>
|
|
9
|
+
* <Menu.Target><Button>Open</Button></Menu.Target>
|
|
10
|
+
* <Menu.Dropdown>
|
|
11
|
+
* <Menu.Label>Section</Menu.Label>
|
|
12
|
+
* <Menu.Item>Action</Menu.Item>
|
|
13
|
+
* <Menu.Divider />
|
|
14
|
+
* <Menu.Item>Another action</Menu.Item>
|
|
15
|
+
* </Menu.Dropdown>
|
|
16
|
+
* </Menu>
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export type MenuProps = RecursicaOverStyled<MantineMenuProps>;
|
|
20
|
+
declare const MenuBase: {
|
|
21
|
+
({ overStyled, ...rest }: MenuProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
displayName: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Wrapper for the element that triggers the menu.
|
|
26
|
+
* Requires a single child element that supports ref forwarding.
|
|
27
|
+
*/
|
|
28
|
+
export type MenuTargetProps = MantineMenuTargetProps;
|
|
29
|
+
declare const MenuTarget: {
|
|
30
|
+
(props: MenuTargetProps): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
displayName: string;
|
|
32
|
+
};
|
|
33
|
+
/** The dropdown panel containing menu items, dividers, and labels. */
|
|
34
|
+
export type MenuDropdownProps = RecursicaOverStyled<MantineMenuDropdownProps>;
|
|
35
|
+
declare const MenuDropdown: import('react').ForwardRefExoticComponent<MenuDropdownProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
36
|
+
/**
|
|
37
|
+
* An individual actionable item within the menu dropdown.
|
|
38
|
+
*
|
|
39
|
+
* **Note:** Mantine's `color` prop is stripped in strict mode to enforce
|
|
40
|
+
* design token adherence. Use `overStyled={true}` if you need to bypass.
|
|
41
|
+
*/
|
|
42
|
+
export type MenuItemProps = RecursicaOverStyled<Omit<MantineMenuItemProps, "color">>;
|
|
43
|
+
declare const MenuItem: import('react').ForwardRefExoticComponent<MenuItemProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
44
|
+
/** A visual separator between groups of menu items. */
|
|
45
|
+
export type MenuDividerProps = RecursicaOverStyled<MantineMenuDividerProps>;
|
|
46
|
+
declare const MenuDivider: import('react').ForwardRefExoticComponent<MenuDividerProps & import('react').RefAttributes<HTMLHRElement>>;
|
|
47
|
+
/** A non-interactive section label used to categorize groups of menu items. */
|
|
48
|
+
export type MenuLabelProps = RecursicaOverStyled<MantineMenuLabelProps>;
|
|
49
|
+
declare const MenuLabel: import('react').ForwardRefExoticComponent<MenuLabelProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
50
|
+
/** Container for a submenu, wrapping Menu.Sub.Target and Menu.Sub.Dropdown. */
|
|
51
|
+
export type MenuSubProps = MantineMenuSubProps;
|
|
52
|
+
declare const MenuSubBase: {
|
|
53
|
+
(props: MenuSubProps): import("react/jsx-runtime").JSX.Element;
|
|
54
|
+
displayName: string;
|
|
55
|
+
};
|
|
56
|
+
/** Wrapper for the element that triggers the submenu. */
|
|
57
|
+
export type MenuSubTargetProps = MantineMenuSubTargetProps;
|
|
58
|
+
declare const MenuSubTarget: {
|
|
59
|
+
(props: MenuSubTargetProps): import("react/jsx-runtime").JSX.Element;
|
|
60
|
+
displayName: string;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* A menu item that acts as a submenu trigger.
|
|
64
|
+
* Renders within Menu.Sub.Target and displays a chevron indicator.
|
|
65
|
+
*/
|
|
66
|
+
export type MenuSubItemProps = RecursicaOverStyled<Omit<MantineMenuItemProps, "color">>;
|
|
67
|
+
declare const MenuSubItem: import('react').ForwardRefExoticComponent<MenuSubItemProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
68
|
+
/** The dropdown panel for a submenu. */
|
|
69
|
+
export type MenuSubDropdownProps = RecursicaOverStyled<MantineMenuSubDropdownProps>;
|
|
70
|
+
declare const MenuSubDropdown: import('react').ForwardRefExoticComponent<MenuSubDropdownProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
71
|
+
type MenuSubComponent = typeof MenuSubBase & {
|
|
72
|
+
Target: typeof MenuSubTarget;
|
|
73
|
+
Item: typeof MenuSubItem;
|
|
74
|
+
Dropdown: typeof MenuSubDropdown;
|
|
75
|
+
};
|
|
76
|
+
type MenuComponent = typeof MenuBase & {
|
|
77
|
+
Target: typeof MenuTarget;
|
|
78
|
+
Dropdown: typeof MenuDropdown;
|
|
79
|
+
Item: typeof MenuItem;
|
|
80
|
+
Divider: typeof MenuDivider;
|
|
81
|
+
Label: typeof MenuLabel;
|
|
82
|
+
Sub: MenuSubComponent;
|
|
83
|
+
};
|
|
84
|
+
export declare const Menu: MenuComponent;
|
|
85
|
+
export {};
|
|
@@ -2,7 +2,9 @@ import { RadioProps as MantineRadioProps } from '@mantine/core';
|
|
|
2
2
|
import { ReadOnlyControlProps } from '@recursica/adapter-common';
|
|
3
3
|
import { RadioGroup } from './RadioGroup';
|
|
4
4
|
import { RecursicaOverStyled } from '../../utils/filterStylingProps';
|
|
5
|
-
|
|
5
|
+
import { RequireAccessibleLabel } from '../../utils/RequireAccessibleLabel';
|
|
6
|
+
import { FormControlLayoutProps } from '../FormControlLayout/FormControlLayout';
|
|
7
|
+
export type RecursicaRadioProps = RequireAccessibleLabel<Omit<MantineRadioProps, "size" | "color" | "radius" | "iconColor" | "variant"> & ReadOnlyControlProps & Pick<FormControlLayoutProps, "formLayout" | "labelSize" | "controlMaxWidth" | "controlMinWidth">>;
|
|
6
8
|
export type RadioProps = RecursicaOverStyled<RecursicaRadioProps>;
|
|
7
9
|
type RadioComponent = React.ForwardRefExoticComponent<RadioProps & React.RefAttributes<HTMLInputElement>> & {
|
|
8
10
|
Group: typeof RadioGroup;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
import { ReadOnlyFieldType } from '@recursica/adapter-common';
|
|
2
|
+
import { ReadOnlyFieldType, ReadOnlyControlProps } from '@recursica/adapter-common';
|
|
3
3
|
import { RecursicaOverStyled } from '../../utils/filterStylingProps';
|
|
4
4
|
import { FormControlWrapperProps } from '../FormControlWrapper/FormControlWrapper';
|
|
5
|
-
export interface RecursicaReadOnlyFieldProps extends Omit<FormControlWrapperProps, "children" | "overStyled"> {
|
|
5
|
+
export interface RecursicaReadOnlyFieldProps extends Omit<FormControlWrapperProps, "children" | "overStyled" | "controlMaxWidth" | "controlMinWidth">, Pick<ReadOnlyControlProps, "emptyValueComponent"> {
|
|
6
6
|
/** The specific value to be rendered in read-only mode explicitly matching the original field input */
|
|
7
7
|
value?: any;
|
|
8
8
|
/** The data type formatting rules bounding how the string is presented to the user */
|
|
9
9
|
type?: ReadOnlyFieldType;
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
/** Pass the native maximum width design variable dynamically bounding the specific wrapper width exclusively. */
|
|
11
|
+
controlMaxWidth?: string | undefined;
|
|
12
|
+
/** Pass the native minimum width design variable dynamically bounding the specific wrapper width exclusively. */
|
|
13
|
+
controlMinWidth?: string | undefined;
|
|
14
14
|
}
|
|
15
15
|
export type ReadOnlyFieldProps = RecursicaOverStyled<RecursicaReadOnlyFieldProps>;
|
|
16
16
|
/**
|
|
@@ -5,7 +5,13 @@ export interface WithReadOnlyWrapperProps extends Omit<FormControlWrapperProps,
|
|
|
5
5
|
/** Injects whether the field defaults to reading mode natively */
|
|
6
6
|
readOnly?: boolean;
|
|
7
7
|
/** Explicit React component directly overtaking the baseline text renderer when read-only mode is active */
|
|
8
|
-
readOnlyComponent?: React.
|
|
8
|
+
readOnlyComponent?: React.ElementType<any>;
|
|
9
|
+
/** Custom renderer explicitly responsible for formatting missing/empty value mappings (overriding default 'N/A') */
|
|
10
|
+
emptyValueComponent?: React.ElementType<{
|
|
11
|
+
value?: any;
|
|
12
|
+
}>;
|
|
13
|
+
/** The full native props dictionary securely forwarded into the custom readOnlyComponent if active */
|
|
14
|
+
readOnlyNativeProps?: any;
|
|
9
15
|
/** Instructs the underlying generic ReadOnlyField which raw visual structure to bridge automatically */
|
|
10
16
|
readOnlyType?: ReadOnlyFieldType;
|
|
11
17
|
/** The isolated raw data value intercepted explicitly into the ReadOnly formatters */
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { SwitchProps as MantineSwitchProps } from '@mantine/core';
|
|
2
2
|
import { ReadOnlyControlProps } from '@recursica/adapter-common';
|
|
3
3
|
import { RecursicaOverStyled } from '../../utils/filterStylingProps';
|
|
4
|
+
import { RequireAccessibleLabel } from '../../utils/RequireAccessibleLabel';
|
|
5
|
+
import { FormControlLayoutProps } from '../FormControlLayout/FormControlLayout';
|
|
4
6
|
import { SwitchGroup } from './SwitchGroup';
|
|
5
|
-
export type RecursicaSwitchProps = Omit<MantineSwitchProps, "size" | "color" | "radius" | "variant"> & ReadOnlyControlProps
|
|
7
|
+
export type RecursicaSwitchProps = RequireAccessibleLabel<Omit<MantineSwitchProps, "size" | "color" | "radius" | "variant"> & ReadOnlyControlProps & Pick<FormControlLayoutProps, "formLayout" | "labelSize" | "controlMaxWidth" | "controlMinWidth">>;
|
|
6
8
|
export type SwitchProps = RecursicaOverStyled<RecursicaSwitchProps>;
|
|
7
9
|
type SwitchComponent = React.ForwardRefExoticComponent<SwitchProps & React.RefAttributes<HTMLInputElement>> & {
|
|
8
10
|
Group: typeof SwitchGroup;
|
|
@@ -13,6 +13,7 @@ export * from './Dropdown/Dropdown';
|
|
|
13
13
|
export * from './FileInput/FileInput';
|
|
14
14
|
export * from './FileUpload/FileUpload';
|
|
15
15
|
export * from './Flex/Flex';
|
|
16
|
+
export * from './FormControlLayout/FormControlLayout';
|
|
16
17
|
export * from './Group/Group';
|
|
17
18
|
export * from './HoverCard/HoverCard';
|
|
18
19
|
export * from './Link/Link';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Enforces accessibility by strictly requiring at least one form of labeling:
|
|
4
|
+
* either a visual \`label\`, an \`aria-label\`, or an \`aria-labelledby\`.
|
|
5
|
+
*/
|
|
6
|
+
export type RequireAccessibleLabel<T> = T & ({
|
|
7
|
+
label: ReactNode;
|
|
8
|
+
"aria-label"?: string;
|
|
9
|
+
"aria-labelledby"?: string;
|
|
10
|
+
} | {
|
|
11
|
+
label?: ReactNode;
|
|
12
|
+
"aria-label": string;
|
|
13
|
+
"aria-labelledby"?: string;
|
|
14
|
+
} | {
|
|
15
|
+
label?: ReactNode;
|
|
16
|
+
"aria-label"?: string;
|
|
17
|
+
"aria-labelledby": string;
|
|
18
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
2
|
import { AssistiveElement } from "./AssistiveElement";
|
|
3
3
|
import { Layer } from "@recursica/adapter-common";
|
|
4
|
-
import React from "react";
|
|
5
4
|
|
|
6
5
|
const meta: Meta<typeof AssistiveElement> = {
|
|
7
6
|
title: "UI-Kit/AssistiveElement",
|
|
@@ -37,7 +36,8 @@ export const DefaultHelp: Story = {
|
|
|
37
36
|
assistiveVariant: "help",
|
|
38
37
|
assistiveWithIcon: true,
|
|
39
38
|
},
|
|
40
|
-
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
40
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
41
41
|
<Layer layer={0} style={{ padding: "48px" }}>
|
|
42
42
|
<AssistiveElement {...args} />
|
|
43
43
|
</Layer>
|
|
@@ -51,7 +51,8 @@ export const ErrorState: Story = {
|
|
|
51
51
|
assistiveVariant: "error",
|
|
52
52
|
assistiveWithIcon: true,
|
|
53
53
|
},
|
|
54
|
-
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
55
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
55
56
|
<Layer layer={0} style={{ padding: "48px" }}>
|
|
56
57
|
<AssistiveElement {...args} />
|
|
57
58
|
</Layer>
|
|
@@ -65,7 +66,8 @@ export const NoIconHelp: Story = {
|
|
|
65
66
|
assistiveVariant: "help",
|
|
66
67
|
assistiveWithIcon: false,
|
|
67
68
|
},
|
|
68
|
-
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
70
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
69
71
|
<Layer layer={0} style={{ padding: "48px" }}>
|
|
70
72
|
<AssistiveElement {...args} />
|
|
71
73
|
</Layer>
|
|
@@ -42,7 +42,8 @@ export const Default: Story = {
|
|
|
42
42
|
size: "default",
|
|
43
43
|
variant: "solid",
|
|
44
44
|
},
|
|
45
|
-
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
46
|
+
render: ({ withLayer, layer, ...args }: any) => {
|
|
46
47
|
return <Avatar {...args} />;
|
|
47
48
|
},
|
|
48
49
|
};
|
|
@@ -53,7 +54,8 @@ export const TextSolidDefault: Story = {
|
|
|
53
54
|
variant: "solid",
|
|
54
55
|
size: "default",
|
|
55
56
|
},
|
|
56
|
-
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
58
|
+
render: ({ withLayer, layer, ...args }: any) => <Avatar {...args} />,
|
|
57
59
|
};
|
|
58
60
|
|
|
59
61
|
export const ImageLarge: Story = {
|
|
@@ -61,7 +63,8 @@ export const ImageLarge: Story = {
|
|
|
61
63
|
src: "https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=250&q=80",
|
|
62
64
|
size: "large",
|
|
63
65
|
},
|
|
64
|
-
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
67
|
+
render: ({ withLayer, layer, ...args }: any) => <Avatar {...args} />,
|
|
65
68
|
};
|
|
66
69
|
|
|
67
70
|
export const IconSmallGhost: Story = {
|
|
@@ -85,7 +88,8 @@ export const IconSmallGhost: Story = {
|
|
|
85
88
|
</svg>
|
|
86
89
|
),
|
|
87
90
|
},
|
|
88
|
-
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
92
|
+
render: ({ withLayer, layer, ...args }: any) => <Avatar {...args} />,
|
|
89
93
|
};
|
|
90
94
|
|
|
91
95
|
export const LayerOneOutline: Story = {
|
|
@@ -94,7 +98,8 @@ export const LayerOneOutline: Story = {
|
|
|
94
98
|
variant: "outline",
|
|
95
99
|
size: "default",
|
|
96
100
|
},
|
|
97
|
-
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
102
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
98
103
|
<Layer layer={1} style={{ padding: "24px", display: "inline-block" }}>
|
|
99
104
|
<Avatar {...args} />
|
|
100
105
|
</Layer>
|
|
@@ -27,7 +27,8 @@ export const Default: Story = {
|
|
|
27
27
|
children: "Badge Label",
|
|
28
28
|
variant: "primary-color",
|
|
29
29
|
},
|
|
30
|
-
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
31
|
+
render: ({ withLayer, layer, ...args }: any) => {
|
|
31
32
|
return <Badge {...args} />;
|
|
32
33
|
},
|
|
33
34
|
};
|
|
@@ -20,9 +20,6 @@ const meta: Meta<ButtonStoryProps> = {
|
|
|
20
20
|
options: ["default", "small"],
|
|
21
21
|
description: "The size of the button",
|
|
22
22
|
},
|
|
23
|
-
disabled: {
|
|
24
|
-
control: "boolean",
|
|
25
|
-
},
|
|
26
23
|
},
|
|
27
24
|
};
|
|
28
25
|
|
|
@@ -37,7 +34,8 @@ export const Default: Story = {
|
|
|
37
34
|
size: "default",
|
|
38
35
|
disabled: false,
|
|
39
36
|
},
|
|
40
|
-
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
38
|
+
render: ({ withLayer, layer, ...args }: any) => {
|
|
41
39
|
return <Button {...args} />;
|
|
42
40
|
},
|
|
43
41
|
};
|
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
--recursica_ui-kit_components_checkbox_properties_colors_icon-color
|
|
162
162
|
) !important;
|
|
163
163
|
}
|
|
164
|
-
.input:disabled + .
|
|
164
|
+
.input:disabled + .icon {
|
|
165
165
|
color: var(
|
|
166
166
|
--recursica_ui-kit_components_checkbox_properties_colors_disabled-icon
|
|
167
167
|
) !important;
|
|
@@ -24,14 +24,13 @@ To render a solitary component natively:
|
|
|
24
24
|
},
|
|
25
25
|
},
|
|
26
26
|
argTypes: {
|
|
27
|
-
disabled: {
|
|
28
|
-
control: "boolean",
|
|
29
|
-
},
|
|
30
27
|
readOnly: {
|
|
31
28
|
control: "boolean",
|
|
32
29
|
description:
|
|
33
30
|
"Toggles structural read-only data presentation bypassing interaction boundaries completely.",
|
|
34
31
|
},
|
|
32
|
+
controlMaxWidth: { table: { disable: true } },
|
|
33
|
+
controlMinWidth: { table: { disable: true } },
|
|
35
34
|
},
|
|
36
35
|
};
|
|
37
36
|
|
|
@@ -46,6 +45,13 @@ export const Default: Story = {
|
|
|
46
45
|
},
|
|
47
46
|
};
|
|
48
47
|
|
|
48
|
+
export const SideBySideLayout: Story = {
|
|
49
|
+
args: {
|
|
50
|
+
label: "Opt-in form alignment",
|
|
51
|
+
formLayout: "side-by-side",
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
49
55
|
export const LongLabelWrap: Story = {
|
|
50
56
|
args: {
|
|
51
57
|
label:
|
|
@@ -71,3 +77,18 @@ export const StaticVariations: Story = {
|
|
|
71
77
|
</div>
|
|
72
78
|
),
|
|
73
79
|
};
|
|
80
|
+
|
|
81
|
+
export const ReadOnly: Story = {
|
|
82
|
+
args: {},
|
|
83
|
+
render: () => (
|
|
84
|
+
<div
|
|
85
|
+
style={{
|
|
86
|
+
display: "flex",
|
|
87
|
+
flexDirection: "column",
|
|
88
|
+
gap: "24px",
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
<Checkbox label="Accept Terms & Conditions" defaultChecked readOnly />
|
|
92
|
+
</div>
|
|
93
|
+
),
|
|
94
|
+
};
|
|
@@ -9,13 +9,25 @@ import {
|
|
|
9
9
|
filterStylingProps,
|
|
10
10
|
type RecursicaOverStyled,
|
|
11
11
|
} from "../../utils/filterStylingProps";
|
|
12
|
+
import { type RequireAccessibleLabel } from "../../utils/RequireAccessibleLabel";
|
|
13
|
+
import {
|
|
14
|
+
FormControlLayout,
|
|
15
|
+
type FormControlLayoutProps,
|
|
16
|
+
} from "../FormControlLayout/FormControlLayout";
|
|
17
|
+
|
|
12
18
|
import styles from "./Checkbox.module.css";
|
|
13
19
|
|
|
14
|
-
export type RecursicaCheckboxProps =
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
export type RecursicaCheckboxProps = RequireAccessibleLabel<
|
|
21
|
+
Omit<
|
|
22
|
+
MantineCheckboxProps,
|
|
23
|
+
"size" | "color" | "radius" | "iconColor" | "variant"
|
|
24
|
+
> &
|
|
25
|
+
ReadOnlyControlProps &
|
|
26
|
+
Pick<
|
|
27
|
+
FormControlLayoutProps,
|
|
28
|
+
"formLayout" | "labelSize" | "controlMaxWidth" | "controlMinWidth"
|
|
29
|
+
>
|
|
30
|
+
>;
|
|
19
31
|
|
|
20
32
|
export type CheckboxProps = RecursicaOverStyled<RecursicaCheckboxProps>;
|
|
21
33
|
|
|
@@ -26,10 +38,18 @@ type CheckboxComponent = React.ForwardRefExoticComponent<
|
|
|
26
38
|
};
|
|
27
39
|
|
|
28
40
|
export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
|
|
29
|
-
function Checkbox(
|
|
30
|
-
{
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
function Checkbox(props, ref) {
|
|
42
|
+
const {
|
|
43
|
+
overStyled = false,
|
|
44
|
+
readOnly,
|
|
45
|
+
readOnlyComponent,
|
|
46
|
+
disabled,
|
|
47
|
+
formLayout,
|
|
48
|
+
labelSize,
|
|
49
|
+
controlMaxWidth,
|
|
50
|
+
controlMinWidth,
|
|
51
|
+
...rest
|
|
52
|
+
} = props;
|
|
33
53
|
// Checkbox doesn't use Label onLabelEditClick natively since it isn't mapped inside FormControlWrapper intrinsically.
|
|
34
54
|
const sanitizedProps = filterStylingProps(rest, overStyled);
|
|
35
55
|
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
@@ -41,11 +61,6 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
|
|
|
41
61
|
delete restRecord["variant"];
|
|
42
62
|
delete restRecord["iconColor"];
|
|
43
63
|
|
|
44
|
-
if (readOnly && readOnlyComponent) {
|
|
45
|
-
// Safely fallback explicitly returning mapped elements natively without macro wrappers
|
|
46
|
-
return <>{readOnlyComponent}</>;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
64
|
const mergedClassNames: Partial<Record<string, string>> = {
|
|
50
65
|
root: styles.root,
|
|
51
66
|
body: styles.body,
|
|
@@ -85,8 +100,35 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
|
|
|
85
100
|
? `${styles.root} ${classNameProp}`
|
|
86
101
|
: styles.root;
|
|
87
102
|
|
|
103
|
+
if (readOnly && !!readOnlyComponent) {
|
|
104
|
+
const isChecked = !!(restRecord.checked ?? restRecord.defaultChecked);
|
|
105
|
+
const ReadOnlyComp = readOnlyComponent;
|
|
106
|
+
const roNode = (
|
|
107
|
+
<ReadOnlyComp
|
|
108
|
+
{...props}
|
|
109
|
+
checked={isChecked}
|
|
110
|
+
label={restRecord.label as React.ReactNode}
|
|
111
|
+
/>
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
if (formLayout) {
|
|
115
|
+
return (
|
|
116
|
+
<FormControlLayout
|
|
117
|
+
formLayout={formLayout}
|
|
118
|
+
labelSize={labelSize}
|
|
119
|
+
controlMaxWidth={controlMaxWidth}
|
|
120
|
+
controlMinWidth={controlMinWidth}
|
|
121
|
+
>
|
|
122
|
+
{roNode}
|
|
123
|
+
</FormControlLayout>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return <>{roNode}</>;
|
|
128
|
+
}
|
|
129
|
+
|
|
88
130
|
// We omit Mantine's sizing/coloring so we rely strictly on variables from Checkbox.module.css
|
|
89
|
-
|
|
131
|
+
const checkboxNode = (
|
|
90
132
|
<MantineCheckbox
|
|
91
133
|
ref={ref}
|
|
92
134
|
className={finalClass}
|
|
@@ -95,6 +137,21 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
|
|
|
95
137
|
{...(sanitizedProps as unknown as MantineCheckboxProps)}
|
|
96
138
|
/>
|
|
97
139
|
);
|
|
140
|
+
|
|
141
|
+
if (formLayout) {
|
|
142
|
+
return (
|
|
143
|
+
<FormControlLayout
|
|
144
|
+
formLayout={formLayout}
|
|
145
|
+
labelSize={labelSize}
|
|
146
|
+
controlMaxWidth={controlMaxWidth}
|
|
147
|
+
controlMinWidth={controlMinWidth}
|
|
148
|
+
>
|
|
149
|
+
{checkboxNode}
|
|
150
|
+
</FormControlLayout>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return checkboxNode;
|
|
98
155
|
},
|
|
99
156
|
) as CheckboxComponent;
|
|
100
157
|
|