@recursica/mantine-adapter 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/.storybook/commonArgTypes.ts +148 -0
  2. package/CHANGELOG.md +69 -0
  3. package/dist/mantine-adapter.cjs +1 -1
  4. package/dist/mantine-adapter.cjs.map +1 -1
  5. package/dist/mantine-adapter.css +1 -1
  6. package/dist/mantine-adapter.js +1076 -266
  7. package/dist/mantine-adapter.js.map +1 -1
  8. package/dist/src/components/Accordion/Accordion.d.ts +13 -28
  9. package/dist/src/components/AssistiveElement/AssistiveElement.d.ts +10 -0
  10. package/dist/src/components/Avatar/Avatar.d.ts +1 -1
  11. package/dist/src/components/Breadcrumb/Breadcrumb.d.ts +6 -3
  12. package/dist/src/components/Button/Button.d.ts +1 -1
  13. package/dist/src/components/Card/Card.d.ts +38 -3
  14. package/dist/src/components/Checkbox/Checkbox.d.ts +11 -3
  15. package/dist/src/components/Checkbox/CheckboxGroup.d.ts +9 -0
  16. package/dist/src/components/Chip/Chip.d.ts +14 -2
  17. package/dist/src/components/FormControlWrapper/FormControlWrapper.d.ts +18 -0
  18. package/dist/src/components/Label/Label.d.ts +21 -0
  19. package/dist/src/components/Label/index.d.ts +1 -0
  20. package/dist/src/components/ReadOnlyField/ReadOnlyField.d.ts +19 -2
  21. package/dist/src/components/ReadOnlyField/ReadOnlyTextField.d.ts +8 -0
  22. package/dist/src/components/ReadOnlyField/WithReadOnlyWrapper.d.ts +22 -0
  23. package/dist/src/components/ReadOnlyField/index.d.ts +3 -0
  24. package/dist/src/components/Text/Text.d.ts +17 -0
  25. package/dist/src/components/TextField/TextField.d.ts +8 -2
  26. package/dist/src/components/Title/Title.d.ts +13 -0
  27. package/dist/src/components/index.d.ts +3 -1
  28. package/dist/src/utils/ColorSchemeWrapper.d.ts +3 -0
  29. package/dist/src/utils/filterStylingProps.d.ts +6 -2
  30. package/package.json +9 -5
  31. package/src/OverStyling.stories.tsx +174 -0
  32. package/src/Version.stories.tsx +56 -0
  33. package/src/components/Accordion/ACCORDION_IMPLEMENTATION_NOTES.md +48 -0
  34. package/src/components/Accordion/Accordion.module.css +261 -0
  35. package/src/components/Accordion/Accordion.stories.tsx +145 -0
  36. package/src/components/Accordion/Accordion.tsx +200 -0
  37. package/src/components/Accordion/index.ts +1 -0
  38. package/src/components/AssistiveElement/AssistiveElement.module.css +111 -0
  39. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +73 -0
  40. package/src/components/AssistiveElement/AssistiveElement.tsx +91 -0
  41. package/src/components/Avatar/AVATAR_IMPLEMENTATION_NOTES.md +24 -0
  42. package/src/components/Avatar/Avatar.module.css +340 -0
  43. package/src/components/Avatar/Avatar.stories.tsx +102 -0
  44. package/src/components/Avatar/Avatar.tsx +100 -0
  45. package/src/components/Avatar/index.ts +1 -0
  46. package/src/components/Badge/BADGE_IMPLEMENTATION_NOTES.md +18 -0
  47. package/src/components/Badge/Badge.module.css +124 -0
  48. package/src/components/Badge/Badge.stories.tsx +77 -0
  49. package/src/components/Badge/Badge.tsx +66 -0
  50. package/src/components/Breadcrumb/BREADCRUMB_IMPLEMENTATION_NOTES.md +14 -0
  51. package/src/components/Breadcrumb/Breadcrumb.module.css +26 -0
  52. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +77 -0
  53. package/src/components/Breadcrumb/Breadcrumb.tsx +64 -0
  54. package/src/components/Button/Button.module.css +275 -0
  55. package/src/components/Button/Button.stories.tsx +105 -0
  56. package/src/components/Button/Button.tsx +122 -0
  57. package/src/components/Button/IMPLEMENTATION_NOTES.md +45 -0
  58. package/src/components/Button/index.ts +1 -0
  59. package/src/components/Card/CARD_IMPLEMENTATION_NOTES.md +10 -0
  60. package/src/components/Card/Card.module.css +60 -0
  61. package/src/components/Card/Card.stories.tsx +141 -0
  62. package/src/components/Card/Card.tsx +176 -0
  63. package/src/components/Checkbox/CHECKBOX_IMPLEMENTATION_NOTES.md +25 -0
  64. package/src/components/Checkbox/Checkbox.module.css +204 -0
  65. package/src/components/Checkbox/Checkbox.stories.tsx +73 -0
  66. package/src/components/Checkbox/Checkbox.tsx +111 -0
  67. package/src/components/Checkbox/CheckboxGroup.stories.tsx +138 -0
  68. package/src/components/Checkbox/CheckboxGroup.tsx +140 -0
  69. package/src/components/Chip/CHIP_IMPLEMENTATION_NOTES.md +35 -0
  70. package/src/components/Chip/Chip.module.css +218 -0
  71. package/src/components/Chip/Chip.stories.tsx +115 -0
  72. package/src/components/Chip/Chip.tsx +143 -0
  73. package/src/components/DatePicker/DatePicker.stories.tsx +22 -0
  74. package/src/components/DatePicker/DatePicker.tsx +7 -0
  75. package/src/components/Dropdown/Dropdown.stories.tsx +22 -0
  76. package/src/components/Dropdown/Dropdown.tsx +7 -0
  77. package/src/components/FileInput/FileInput.stories.tsx +22 -0
  78. package/src/components/FileInput/FileInput.tsx +7 -0
  79. package/src/components/FileUpload/FileUpload.stories.tsx +22 -0
  80. package/src/components/FileUpload/FileUpload.tsx +7 -0
  81. package/src/components/FormControlWrapper/FORMCONTROLWRAPPER_IMPLEMENTATION_NOTES.md +32 -0
  82. package/src/components/FormControlWrapper/FormControlWrapper.module.css +46 -0
  83. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +116 -0
  84. package/src/components/FormControlWrapper/FormControlWrapper.tsx +170 -0
  85. package/src/components/HoverCard/HoverCard.stories.tsx +17 -0
  86. package/src/components/HoverCard/HoverCard.tsx +7 -0
  87. package/src/components/Label/LABEL_IMPLEMENTATION_NOTES.md +48 -0
  88. package/src/components/Label/Label.module.css +177 -0
  89. package/src/components/Label/Label.stories.tsx +123 -0
  90. package/src/components/Label/Label.tsx +132 -0
  91. package/src/components/Label/index.ts +1 -0
  92. package/src/components/Link/Link.stories.tsx +17 -0
  93. package/src/components/Link/Link.tsx +7 -0
  94. package/src/components/Loader/Loader.stories.tsx +17 -0
  95. package/src/components/Loader/Loader.tsx +7 -0
  96. package/src/components/Menu/Menu.stories.tsx +17 -0
  97. package/src/components/Menu/Menu.tsx +7 -0
  98. package/src/components/Modal/Modal.stories.tsx +17 -0
  99. package/src/components/Modal/Modal.tsx +7 -0
  100. package/src/components/NumberInput/NumberInput.stories.tsx +22 -0
  101. package/src/components/NumberInput/NumberInput.tsx +7 -0
  102. package/src/components/Pagination/Pagination.stories.tsx +17 -0
  103. package/src/components/Pagination/Pagination.tsx +7 -0
  104. package/src/components/Panel/Panel.stories.tsx +17 -0
  105. package/src/components/Panel/Panel.tsx +7 -0
  106. package/src/components/Popover/Popover.stories.tsx +17 -0
  107. package/src/components/Popover/Popover.tsx +7 -0
  108. package/src/components/Radio/Radio.stories.tsx +22 -0
  109. package/src/components/Radio/Radio.tsx +7 -0
  110. package/src/components/ReadOnlyField/READ_ONLY_FIELD_IMPLEMENTATION_NOTES.md +15 -0
  111. package/src/components/ReadOnlyField/ReadOnlyField.module.css +49 -0
  112. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +120 -0
  113. package/src/components/ReadOnlyField/ReadOnlyField.tsx +75 -0
  114. package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +46 -0
  115. package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +85 -0
  116. package/src/components/ReadOnlyField/index.ts +3 -0
  117. package/src/components/Search/Search.stories.tsx +17 -0
  118. package/src/components/Search/Search.tsx +7 -0
  119. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +22 -0
  120. package/src/components/SegmentedControl/SegmentedControl.tsx +7 -0
  121. package/src/components/Slider/Slider.stories.tsx +22 -0
  122. package/src/components/Slider/Slider.tsx +7 -0
  123. package/src/components/Stepper/Stepper.stories.tsx +17 -0
  124. package/src/components/Stepper/Stepper.tsx +7 -0
  125. package/src/components/Switch/Switch.stories.tsx +22 -0
  126. package/src/components/Switch/Switch.tsx +7 -0
  127. package/src/components/Table/Table.stories.tsx +17 -0
  128. package/src/components/Table/Table.tsx +7 -0
  129. package/src/components/Tabs/Tabs.stories.tsx +17 -0
  130. package/src/components/Tabs/Tabs.tsx +7 -0
  131. package/src/components/Text/Text.stories.tsx +88 -0
  132. package/src/components/Text/Text.tsx +54 -0
  133. package/src/components/TextArea/TextArea.stories.tsx +22 -0
  134. package/src/components/TextArea/TextArea.tsx +7 -0
  135. package/src/components/TextField/TEXTFIELD_IMPLEMENTATION_NOTES.md +19 -0
  136. package/src/components/TextField/TextField.module.css +225 -0
  137. package/src/components/TextField/TextField.stories.tsx +162 -0
  138. package/src/components/TextField/TextField.tsx +138 -0
  139. package/src/components/TimePicker/TimePicker.stories.tsx +22 -0
  140. package/src/components/TimePicker/TimePicker.tsx +7 -0
  141. package/src/components/Timeline/Timeline.stories.tsx +17 -0
  142. package/src/components/Timeline/Timeline.tsx +7 -0
  143. package/src/components/Title/Title.stories.tsx +63 -0
  144. package/src/components/Title/Title.tsx +45 -0
  145. package/src/components/Toast/Toast.stories.tsx +17 -0
  146. package/src/components/Toast/Toast.tsx +7 -0
  147. package/src/components/Tooltip/Tooltip.stories.tsx +17 -0
  148. package/src/components/Tooltip/Tooltip.tsx +7 -0
  149. package/src/components/TransferList/TransferList.stories.tsx +17 -0
  150. package/src/components/TransferList/TransferList.tsx +7 -0
  151. package/src/components/index.ts +39 -0
  152. package/src/env.d.ts +7 -0
  153. package/src/index.ts +3 -0
  154. package/src/types/index.ts +9 -0
  155. package/src/types/mantine.d.ts +7 -0
  156. package/src/types/scss-modules.d.ts +9 -0
  157. package/src/utils/ColorSchemeWrapper.tsx +27 -0
  158. package/src/utils/copyToClipboard.ts +36 -0
  159. package/src/utils/filterStylingProps.ts +139 -0
  160. package/src/utils/index.ts +1 -0
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Link } from "./Link";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof Link> = {
6
+ title: "UI-Kit/🚧 Link",
7
+ component: Link,
8
+ tags: ["autodocs"],
9
+ };
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof Link>;
14
+
15
+ export const Default: Story = {
16
+ render: () => <ComingSoon componentName="Link" />,
17
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type LinkProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const Link: React.FC<LinkProps> = (props) => {
6
+ return <div {...props}>Link</div>;
7
+ };
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Loader } from "./Loader";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof Loader> = {
6
+ title: "UI-Kit/🚧 Loader",
7
+ component: Loader,
8
+ tags: ["autodocs"],
9
+ };
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof Loader>;
14
+
15
+ export const Default: Story = {
16
+ render: () => <ComingSoon componentName="Loader" />,
17
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type LoaderProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const Loader: React.FC<LoaderProps> = (props) => {
6
+ return <div {...props}>Loader</div>;
7
+ };
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Menu } from "./Menu";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof Menu> = {
6
+ title: "UI-Kit/🚧 Menu",
7
+ component: Menu,
8
+ tags: ["autodocs"],
9
+ };
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof Menu>;
14
+
15
+ export const Default: Story = {
16
+ render: () => <ComingSoon componentName="Menu" />,
17
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type MenuProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const Menu: React.FC<MenuProps> = (props) => {
6
+ return <div {...props}>Menu</div>;
7
+ };
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Modal } from "./Modal";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof Modal> = {
6
+ title: "UI-Kit/🚧 Modal",
7
+ component: Modal,
8
+ tags: ["autodocs"],
9
+ };
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof Modal>;
14
+
15
+ export const Default: Story = {
16
+ render: () => <ComingSoon componentName="Modal" />,
17
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type ModalProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const Modal: React.FC<ModalProps> = (props) => {
6
+ return <div {...props}>Modal</div>;
7
+ };
@@ -0,0 +1,22 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { NumberInput } from "./NumberInput";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof NumberInput> = {
6
+ title: "UI-Kit/🚧 NumberInput",
7
+ component: NumberInput,
8
+ tags: ["autodocs"],
9
+ argTypes: {
10
+ disabled: {
11
+ control: "boolean",
12
+ },
13
+ },
14
+ };
15
+
16
+ export default meta;
17
+
18
+ type Story = StoryObj<typeof NumberInput>;
19
+
20
+ export const Default: Story = {
21
+ render: () => <ComingSoon componentName="NumberInput" />,
22
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type NumberInputProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const NumberInput: React.FC<NumberInputProps> = (props) => {
6
+ return <div {...props}>NumberInput</div>;
7
+ };
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Pagination } from "./Pagination";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof Pagination> = {
6
+ title: "UI-Kit/🚧 Pagination",
7
+ component: Pagination,
8
+ tags: ["autodocs"],
9
+ };
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof Pagination>;
14
+
15
+ export const Default: Story = {
16
+ render: () => <ComingSoon componentName="Pagination" />,
17
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type PaginationProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const Pagination: React.FC<PaginationProps> = (props) => {
6
+ return <div {...props}>Pagination</div>;
7
+ };
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Panel } from "./Panel";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof Panel> = {
6
+ title: "UI-Kit/🚧 Panel",
7
+ component: Panel,
8
+ tags: ["autodocs"],
9
+ };
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof Panel>;
14
+
15
+ export const Default: Story = {
16
+ render: () => <ComingSoon componentName="Panel" />,
17
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type PanelProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const Panel: React.FC<PanelProps> = (props) => {
6
+ return <div {...props}>Panel</div>;
7
+ };
@@ -0,0 +1,17 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Popover } from "./Popover";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof Popover> = {
6
+ title: "UI-Kit/🚧 Popover",
7
+ component: Popover,
8
+ tags: ["autodocs"],
9
+ };
10
+
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof Popover>;
14
+
15
+ export const Default: Story = {
16
+ render: () => <ComingSoon componentName="Popover" />,
17
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type PopoverProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const Popover: React.FC<PopoverProps> = (props) => {
6
+ return <div {...props}>Popover</div>;
7
+ };
@@ -0,0 +1,22 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Radio } from "./Radio";
3
+ import { ComingSoon } from "@recursica/storybook-template";
4
+
5
+ const meta: Meta<typeof Radio> = {
6
+ title: "UI-Kit/🚧 Radio",
7
+ component: Radio,
8
+ tags: ["autodocs"],
9
+ argTypes: {
10
+ disabled: {
11
+ control: "boolean",
12
+ },
13
+ },
14
+ };
15
+
16
+ export default meta;
17
+
18
+ type Story = StoryObj<typeof Radio>;
19
+
20
+ export const Default: Story = {
21
+ render: () => <ComingSoon componentName="Radio" />,
22
+ };
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+
3
+ export type RadioProps = React.HTMLAttributes<HTMLDivElement>;
4
+
5
+ export const Radio: React.FC<RadioProps> = (props) => {
6
+ return <div {...props}>Radio</div>;
7
+ };
@@ -0,0 +1,15 @@
1
+ # ReadOnlyField Implementation Notes
2
+
3
+ This document acts as a living record tracking edge cases and architectural choices made specific to the `ReadOnlyField` and its internal blocks (like `ReadOnlyTextField`).
4
+
5
+ ## 1. Stripping Mantine Assumptions
6
+
7
+ Unlike standard input variables, standard HTML output `<p>` tags inherently carry margin and spacing assumptions from core browser stylesheets. To correctly map `ReadOnlyTextField` elements gracefully inside the generic `FormControlWrapper` bounded context, we hardcode resets:
8
+
9
+ - `margin: 0` explicitly strips block flow gap so `FormControlWrapper` handles vertical rhythm.
10
+ - `min-height`: Native `Input` boxes typically have baseline padding borders. We map directly to `var(--recursica_ui-kit_components_read-only-field_properties_min-height)` to ensure a side-by-side editable `TextField` and `ReadOnlyField` perfectly share roughly identical visual heights.
11
+
12
+ ## 2. Unidirectional Editable Mode
13
+
14
+ The main wrapper intercepts `readOnly` boolean blocks, maintaining its own `isReadOnly` state. Natively, if a user clicks an exposed 'Edit' action (like our legacy SVG or custom `labelActionArea`), the context permanently switches to active.
15
+ There is intentionally no built-in reverse toggle inside typical field bindings (like input "Blur") to revert state. Parents must pass external controls to `readOnly` forcing the internal hooks to reset via standard `useEffect` propagation.
@@ -0,0 +1,49 @@
1
+ /* HARDCODED VALUES:
2
+ - margin: 0; padding: overrides native paragraph margins mapping back to form element flows.
3
+ */
4
+ .textField {
5
+ margin: 0; /* HARDCODE: Reset paragraph margin; assume wrapper controls layout */
6
+ display: flex;
7
+ align-items: center;
8
+ word-break: break-word;
9
+ padding: 0; /* HARDCODE: read-only fields have no specific padding defined by tokens, zeroing it. */
10
+ font-family: var(
11
+ --recursica_ui-kit_components_read-only-field_properties_text_font-family,
12
+ inherit
13
+ );
14
+ font-size: var(
15
+ --recursica_ui-kit_components_read-only-field_properties_text_font-size,
16
+ 1rem
17
+ );
18
+ font-weight: var(
19
+ --recursica_ui-kit_components_read-only-field_properties_text_font-weight,
20
+ normal
21
+ );
22
+ letter-spacing: var(
23
+ --recursica_ui-kit_components_read-only-field_properties_text_letter-spacing,
24
+ normal
25
+ );
26
+ line-height: var(
27
+ --recursica_ui-kit_components_read-only-field_properties_text_line-height,
28
+ 1.5
29
+ );
30
+ font-style: var(
31
+ --recursica_ui-kit_components_read-only-field_properties_text_font-style,
32
+ normal
33
+ );
34
+ text-decoration: var(
35
+ --recursica_ui-kit_components_read-only-field_properties_text_text-decoration,
36
+ none
37
+ );
38
+ text-transform: var(
39
+ --recursica_ui-kit_components_read-only-field_properties_text_text-transform,
40
+ none
41
+ );
42
+ color: var(
43
+ --recursica_ui-kit_components_read-only-field_properties_colors_text
44
+ );
45
+ min-height: var(
46
+ --recursica_ui-kit_components_read-only-field_properties_min-height,
47
+ 32px
48
+ );
49
+ }
@@ -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,3 @@
1
+ export * from "./ReadOnlyField";
2
+ export * from "./WithReadOnlyWrapper";
3
+ export * from "./ReadOnlyTextField";
@@ -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
+ };