@phsa.tec/design-system-react 0.1.6 → 0.1.9

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 (217) hide show
  1. package/README.md +390 -209
  2. package/dist/index.d.mts +485 -0
  3. package/dist/index.d.ts +485 -0
  4. package/dist/index.js +4259 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/index.mjs +4186 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/dist/styles.css +2534 -0
  9. package/dist/styles.css.map +1 -0
  10. package/dist/styles.d.mts +2 -0
  11. package/dist/styles.d.ts +2 -0
  12. package/package.json +46 -6
  13. package/.eslintrc.json +0 -7
  14. package/.github/workflows/deploy-storybook.yml +0 -75
  15. package/.storybook/main.ts +0 -16
  16. package/.storybook/preview.ts +0 -15
  17. package/components.json +0 -21
  18. package/jest.config.ts +0 -25
  19. package/next.config.ts +0 -7
  20. package/postcss.config.mjs +0 -8
  21. package/public/file.svg +0 -1
  22. package/public/globe.svg +0 -1
  23. package/public/next.svg +0 -1
  24. package/public/vercel.svg +0 -1
  25. package/public/window.svg +0 -1
  26. package/src/app/columns.tsx +0 -178
  27. package/src/app/favicon.ico +0 -0
  28. package/src/app/fonts/GeistMonoVF.woff +0 -0
  29. package/src/app/fonts/GeistVF.woff +0 -0
  30. package/src/app/globals.css +0 -94
  31. package/src/app/layout.tsx +0 -35
  32. package/src/app/page.tsx +0 -7
  33. package/src/components/actions/AlertDialog/AlertDialog.tsx +0 -45
  34. package/src/components/actions/AlertDialog/alert-dialog.stories.tsx +0 -21
  35. package/src/components/actions/AlertDialog/index.ts +0 -1
  36. package/src/components/actions/Button/Button.stories.ts +0 -38
  37. package/src/components/actions/Button/Button.tsx +0 -23
  38. package/src/components/actions/Button/index.ts +0 -1
  39. package/src/components/actions/Collapsible/index.ts +0 -1
  40. package/src/components/actions/Dialog/Dialog.stories.tsx +0 -70
  41. package/src/components/actions/Dialog/Dialog.tsx +0 -87
  42. package/src/components/actions/Dialog/components/DialogWithActions/index.tsx +0 -40
  43. package/src/components/actions/Dialog/index.ts +0 -1
  44. package/src/components/actions/Steps/Steps.stories.tsx +0 -25
  45. package/src/components/actions/Steps/Steps.tsx +0 -51
  46. package/src/components/actions/Steps/index.ts +0 -1
  47. package/src/components/actions/index.ts +0 -5
  48. package/src/components/dataDisplay/Avatar/Avatar.stories.tsx +0 -22
  49. package/src/components/dataDisplay/Avatar/Avatar.tsx +0 -21
  50. package/src/components/dataDisplay/Avatar/index.ts +0 -2
  51. package/src/components/dataDisplay/Badge/Badge.stories.tsx +0 -36
  52. package/src/components/dataDisplay/Badge/index.ts +0 -1
  53. package/src/components/dataDisplay/Card/Card.stories.tsx +0 -24
  54. package/src/components/dataDisplay/Card/Card.tsx +0 -34
  55. package/src/components/dataDisplay/Card/index.ts +0 -1
  56. package/src/components/dataDisplay/DataPairList/DataPairList.tsx +0 -56
  57. package/src/components/dataDisplay/DataPairList/data-pair-list.stories.tsx +0 -87
  58. package/src/components/dataDisplay/DataPairList/index.ts +0 -2
  59. package/src/components/dataDisplay/DataPairList/types.ts +0 -10
  60. package/src/components/dataDisplay/DropDownMenu/index.ts +0 -1
  61. package/src/components/dataDisplay/ErrorMessage/ErrorMessage.tsx +0 -6
  62. package/src/components/dataDisplay/ErrorMessage/index.ts +0 -1
  63. package/src/components/dataDisplay/Icon/Icon.stories.tsx +0 -21
  64. package/src/components/dataDisplay/Icon/Icon.tsx +0 -47
  65. package/src/components/dataDisplay/Icon/index.ts +0 -1
  66. package/src/components/dataDisplay/Icon/types.ts +0 -6
  67. package/src/components/dataDisplay/Label/Label.stories.tsx +0 -21
  68. package/src/components/dataDisplay/Label/Label.tsx +0 -10
  69. package/src/components/dataDisplay/Label/index.ts +0 -1
  70. package/src/components/dataDisplay/Table/Table.tsx +0 -173
  71. package/src/components/dataDisplay/Table/columns.tsx +0 -223
  72. package/src/components/dataDisplay/Table/components/DynamicTable/data-table-column-header.tsx +0 -72
  73. package/src/components/dataDisplay/Table/components/DynamicTable/data-table-pagination.tsx +0 -91
  74. package/src/components/dataDisplay/Table/components/DynamicTable/data-table-toolbar.tsx +0 -17
  75. package/src/components/dataDisplay/Table/components/DynamicTable/data-table-view-options.tsx +0 -58
  76. package/src/components/dataDisplay/Table/components/DynamicTable/data-table.stories.tsx +0 -118
  77. package/src/components/dataDisplay/Table/components/DynamicTable/index.tsx +0 -136
  78. package/src/components/dataDisplay/Table/components/DynamicTable/types.ts +0 -43
  79. package/src/components/dataDisplay/Table/custom/CustomTable/data-table-column-header.tsx +0 -71
  80. package/src/components/dataDisplay/Table/custom/CustomTable/data-table-faceted-filter.tsx +0 -147
  81. package/src/components/dataDisplay/Table/custom/CustomTable/data-table-pagination.tsx +0 -97
  82. package/src/components/dataDisplay/Table/custom/CustomTable/data-table-row-actions.tsx +0 -78
  83. package/src/components/dataDisplay/Table/custom/CustomTable/data-table-toolbar.tsx +0 -60
  84. package/src/components/dataDisplay/Table/custom/CustomTable/data-table-view-options.tsx +0 -59
  85. package/src/components/dataDisplay/Table/custom/CustomTable/data-table.tsx +0 -145
  86. package/src/components/dataDisplay/Table/custom/CustomTable/data.ts +0 -71
  87. package/src/components/dataDisplay/Table/custom/CustomTable/index.tsx +0 -34
  88. package/src/components/dataDisplay/Table/custom/CustomTable/schema.ts +0 -11
  89. package/src/components/dataDisplay/Table/index.ts +0 -2
  90. package/src/components/dataDisplay/Table/table.stories.tsx +0 -147
  91. package/src/components/dataDisplay/Table/types.ts +0 -15
  92. package/src/components/dataDisplay/Tabs/Tabs.stories.tsx +0 -34
  93. package/src/components/dataDisplay/Tabs/Tabs.tsx +0 -53
  94. package/src/components/dataDisplay/Tabs/index.ts +0 -1
  95. package/src/components/dataDisplay/Text/Text.stories.tsx +0 -66
  96. package/src/components/dataDisplay/Text/Text.tsx +0 -56
  97. package/src/components/dataDisplay/Text/index.ts +0 -1
  98. package/src/components/dataDisplay/index.ts +0 -8
  99. package/src/components/dataInput/Input/components/Input/Input.stories.tsx +0 -99
  100. package/src/components/dataInput/Input/components/Input/InputBase.tsx +0 -50
  101. package/src/components/dataInput/Input/components/Input/__tests__/input.test.tsx +0 -38
  102. package/src/components/dataInput/Input/components/Input/index.tsx +0 -48
  103. package/src/components/dataInput/Input/components/Input/types.ts +0 -15
  104. package/src/components/dataInput/Input/components/InputBase/index.tsx +0 -31
  105. package/src/components/dataInput/Input/components/MaskInput/__tests__/mask-input.test.tsx +0 -77
  106. package/src/components/dataInput/Input/components/MaskInput/index.ts +0 -1
  107. package/src/components/dataInput/Input/components/MaskInput/mask-input.stories.tsx +0 -85
  108. package/src/components/dataInput/Input/components/MaskInput/mask-input.tsx +0 -73
  109. package/src/components/dataInput/Input/components/MultipleInput/MultipleInput.tsx +0 -105
  110. package/src/components/dataInput/Input/components/MultipleInput/MultipleInputBase.tsx +0 -100
  111. package/src/components/dataInput/Input/components/MultipleInput/MultipleMaskInput.tsx +0 -35
  112. package/src/components/dataInput/Input/components/MultipleInput/MultipleNumberInput.tsx +0 -35
  113. package/src/components/dataInput/Input/components/MultipleInput/__tests__/multiple-input.test.tsx +0 -152
  114. package/src/components/dataInput/Input/components/MultipleInput/index.ts +0 -2
  115. package/src/components/dataInput/Input/components/MultipleInput/multiple-input.stories.tsx +0 -96
  116. package/src/components/dataInput/Input/components/NumberInput/__tests__/number-input.test.tsx +0 -175
  117. package/src/components/dataInput/Input/components/NumberInput/index.ts +0 -1
  118. package/src/components/dataInput/Input/components/NumberInput/number-input.stories.tsx +0 -76
  119. package/src/components/dataInput/Input/components/NumberInput/number-input.tsx +0 -70
  120. package/src/components/dataInput/Input/index.ts +0 -4
  121. package/src/components/dataInput/Select/MultiSelect/MultiSelect.stories.tsx +0 -119
  122. package/src/components/dataInput/Select/MultiSelect/MultiSelectBase.tsx +0 -135
  123. package/src/components/dataInput/Select/MultiSelect/index.tsx +0 -75
  124. package/src/components/dataInput/Select/Select.stories.tsx +0 -61
  125. package/src/components/dataInput/Select/Select.tsx +0 -73
  126. package/src/components/dataInput/Select/SelectBase.tsx +0 -58
  127. package/src/components/dataInput/Select/index.ts +0 -2
  128. package/src/components/dataInput/Switch/Switch.stories.tsx +0 -75
  129. package/src/components/dataInput/Switch/Switch.tsx +0 -52
  130. package/src/components/dataInput/Switch/index.ts +0 -1
  131. package/src/components/dataInput/checkbox/Checkbox.tsx +0 -57
  132. package/src/components/dataInput/checkbox/Checkbox_old.tsx +0 -58
  133. package/src/components/dataInput/checkbox/Checkout.stories.tsx +0 -62
  134. package/src/components/dataInput/checkbox/index.ts +0 -1
  135. package/src/components/dataInput/form/Form.tsx +0 -47
  136. package/src/components/dataInput/form/index.ts +0 -3
  137. package/src/components/dataInput/index.ts +0 -5
  138. package/src/components/feedback/ErrorLabel/index.tsx +0 -24
  139. package/src/components/feedback/Spinner/index.ts +0 -1
  140. package/src/components/feedback/Toast/Toast.stories.tsx +0 -45
  141. package/src/components/feedback/Toast/index.ts +0 -2
  142. package/src/components/feedback/index.ts +0 -2
  143. package/src/components/index.ts +0 -6
  144. package/src/components/layout/Crud/components/Table/index.tsx +0 -183
  145. package/src/components/layout/Crud/components/Table/types.ts +0 -15
  146. package/src/components/layout/Crud/crud.stories.tsx +0 -317
  147. package/src/components/layout/Crud/hook/useCrudLayout/index.tsx +0 -94
  148. package/src/components/layout/Crud/hook/useRequest/index.tsx +0 -156
  149. package/src/components/layout/Crud/index.tsx +0 -295
  150. package/src/components/layout/Crud/store/CrudLayoutStore.ts +0 -75
  151. package/src/components/layout/Crud/types.ts +0 -14
  152. package/src/components/layout/Drawer/CustomDrawer/index.tsx +0 -33
  153. package/src/components/layout/Drawer/Drawer.stories.tsx +0 -80
  154. package/src/components/layout/Drawer/index.ts +0 -2
  155. package/src/components/layout/PageLayout/PageLayout.stories.tsx +0 -42
  156. package/src/components/layout/PageLayout/index.tsx +0 -28
  157. package/src/components/layout/Separator/index.ts +0 -1
  158. package/src/components/layout/Sheet/Sheet.stories.tsx +0 -28
  159. package/src/components/layout/Sheet/Sheet.tsx +0 -22
  160. package/src/components/layout/Sheet/index.ts +0 -1
  161. package/src/components/layout/Sidebar/Sidebar.stories.tsx +0 -116
  162. package/src/components/layout/Sidebar/Sidebar.tsx +0 -50
  163. package/src/components/layout/Sidebar/components/app-sidebar.tsx +0 -203
  164. package/src/components/layout/Sidebar/components/footer-sidebar.tsx +0 -17
  165. package/src/components/layout/Sidebar/components/header-sidebar.tsx +0 -90
  166. package/src/components/layout/Sidebar/components/menus.tsx +0 -55
  167. package/src/components/layout/Sidebar/components/nav-projects.tsx +0 -88
  168. package/src/components/layout/Sidebar/components/nav-user.tsx +0 -114
  169. package/src/components/layout/Sidebar/components/team-switcher.tsx +0 -85
  170. package/src/components/layout/Sidebar/index.ts +0 -2
  171. package/src/components/layout/Sidebar/provider/index.tsx +0 -51
  172. package/src/components/layout/Tabs/Tabs.tsx +0 -51
  173. package/src/components/layout/Tabs/index.ts +0 -1
  174. package/src/components/layout/Tabs/tabs.stories.tsx +0 -57
  175. package/src/components/layout/index.ts +0 -6
  176. package/src/components/navigation/Breadcrumbs/Breadcrumbs.tsx +0 -66
  177. package/src/components/navigation/Breadcrumbs/index.ts +0 -2
  178. package/src/components/navigation/index.ts +0 -1
  179. package/src/components/ui/alert-dialog.tsx +0 -141
  180. package/src/components/ui/alert.tsx +0 -59
  181. package/src/components/ui/avatar.tsx +0 -50
  182. package/src/components/ui/badge.tsx +0 -40
  183. package/src/components/ui/breadcrumb.tsx +0 -115
  184. package/src/components/ui/button.tsx +0 -57
  185. package/src/components/ui/card.tsx +0 -83
  186. package/src/components/ui/checkbox.tsx +0 -34
  187. package/src/components/ui/collapsible.tsx +0 -11
  188. package/src/components/ui/command.tsx +0 -153
  189. package/src/components/ui/dialog.tsx +0 -124
  190. package/src/components/ui/drawer.tsx +0 -117
  191. package/src/components/ui/dropdown-menu.tsx +0 -201
  192. package/src/components/ui/form.tsx +0 -179
  193. package/src/components/ui/input.tsx +0 -24
  194. package/src/components/ui/label.tsx +0 -30
  195. package/src/components/ui/popover.tsx +0 -33
  196. package/src/components/ui/select.tsx +0 -161
  197. package/src/components/ui/separator.tsx +0 -31
  198. package/src/components/ui/sheet.tsx +0 -140
  199. package/src/components/ui/sidebar.tsx +0 -763
  200. package/src/components/ui/skeleton.tsx +0 -15
  201. package/src/components/ui/sonner.tsx +0 -31
  202. package/src/components/ui/spinner.tsx +0 -54
  203. package/src/components/ui/switch.tsx +0 -33
  204. package/src/components/ui/table.tsx +0 -120
  205. package/src/components/ui/tabs.tsx +0 -55
  206. package/src/components/ui/toast.tsx +0 -130
  207. package/src/components/ui/toaster.tsx +0 -35
  208. package/src/components/ui/tooltip.tsx +0 -32
  209. package/src/hooks/use-conditional-controller.tsx +0 -35
  210. package/src/hooks/use-mask.tsx +0 -116
  211. package/src/hooks/use-mobile.tsx +0 -19
  212. package/src/hooks/use-toast.ts +0 -191
  213. package/src/index.ts +0 -1
  214. package/src/introduction.mdx +0 -132
  215. package/src/lib/utils.ts +0 -6
  216. package/tailwind.config.ts +0 -83
  217. package/tsconfig.json +0 -27
@@ -1,70 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
- import {
5
- NumericFormat,
6
- NumericFormatProps,
7
- SourceInfo,
8
- } from "react-number-format";
9
- import { InputBase } from "../InputBase";
10
- import { Input } from "../../../../ui/input";
11
- import { InputProps } from "../Input/types";
12
- import { useCallback, useMemo } from "react";
13
- import { useConditionalController } from "@/hooks/use-conditional-controller";
14
-
15
- export type NumberInputProps = Omit<NumericFormatProps, "onChange"> &
16
- InputProps;
17
-
18
- export const NumberInput = (props: NumberInputProps) => {
19
- const formData = useConditionalController({
20
- name: props.name || "",
21
- withoutForm: props.withoutForm,
22
- });
23
-
24
- const inputProps = useMemo(() => {
25
- return {
26
- ...formData,
27
- ...props,
28
- };
29
- }, [formData, props]);
30
-
31
- const onValueChange = useCallback(
32
- (
33
- data: {
34
- value: string;
35
- floatValue: number | undefined;
36
- formattedValue: string;
37
- },
38
- sourceInfo: SourceInfo
39
- ) => {
40
- const syntheticEvent = {
41
- target: {
42
- value: data.formattedValue,
43
- name: props.name,
44
- },
45
- currentTarget: {
46
- value: data.formattedValue,
47
- name: props.name,
48
- },
49
- } as React.ChangeEvent<HTMLInputElement>;
50
-
51
- props.onChange?.(syntheticEvent);
52
- props.onValueChange?.(data, sourceInfo);
53
- if (formData.onChange) {
54
- formData.onChange(data.formattedValue);
55
- }
56
- },
57
- [props, formData]
58
- );
59
-
60
- return (
61
- <InputBase {...props}>
62
- <NumericFormat
63
- {...inputProps}
64
- customInput={Input}
65
- value={props.value}
66
- onValueChange={onValueChange}
67
- />
68
- </InputBase>
69
- );
70
- };
@@ -1,4 +0,0 @@
1
- export * from "./components/Input";
2
- export * from "./components/NumberInput";
3
- export * from "./components/MaskInput";
4
- export * from "./components/MultipleInput";
@@ -1,119 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/nextjs";
2
- import { MultiSelect } from "./index";
3
- import { useState } from "react";
4
- import { Form } from "../../form";
5
- import { useForm } from "react-hook-form";
6
-
7
- const meta: Meta<typeof MultiSelect> = {
8
- title: "Data Input/MultiSelect",
9
- component: MultiSelect,
10
- tags: ["autodocs"],
11
- };
12
-
13
- export default meta;
14
- type Story = StoryObj<typeof MultiSelect>;
15
-
16
- const options = [
17
- { label: "Next.js", value: "nextjs" },
18
- { label: "SvelteKit", value: "sveltekit" },
19
- { label: "Nuxt.js", value: "nuxtjs" },
20
- { label: "Remix", value: "remix" },
21
- { label: "Astro", value: "astro" },
22
- ];
23
-
24
- const MultiSelectWithHooks = () => {
25
- const [selected, setSelected] = useState<string[]>([]);
26
-
27
- return (
28
- <MultiSelect
29
- label="MultiSelect"
30
- options={options}
31
- selected={selected}
32
- onChange={setSelected}
33
- placeholder="Select frameworks..."
34
- />
35
- );
36
- };
37
-
38
- export const Default: Story = {
39
- render: () => <MultiSelectWithHooks />,
40
- };
41
-
42
- export const Preselected: Story = {
43
- render: () => {
44
- const [selected, setSelected] = useState<string[]>(["nextjs", "nuxtjs"]);
45
-
46
- return (
47
- <MultiSelect
48
- options={options}
49
- selected={selected}
50
- onChange={setSelected}
51
- placeholder="Select frameworks..."
52
- />
53
- );
54
- },
55
- };
56
-
57
- export const CustomPlaceholder: Story = {
58
- render: () => {
59
- const [selected, setSelected] = useState<string[]>([]);
60
-
61
- return (
62
- <MultiSelect
63
- options={options}
64
- selected={selected}
65
- onChange={setSelected}
66
- placeholder="Choose your favorite frameworks..."
67
- />
68
- );
69
- },
70
- };
71
-
72
- export const ManyOptions: Story = {
73
- render: () => {
74
- const [selected, setSelected] = useState<string[]>([]);
75
- const manyOptions = [
76
- ...options,
77
- { label: "React", value: "react" },
78
- { label: "Vue", value: "vue" },
79
- { label: "Angular", value: "angular" },
80
- { label: "Solid", value: "solid" },
81
- { label: "Qwik", value: "qwik" },
82
- { label: "Ember", value: "ember" },
83
- { label: "Preact", value: "preact" },
84
- { label: "Alpine", value: "alpine" },
85
- ];
86
-
87
- return (
88
- <MultiSelect
89
- options={manyOptions}
90
- selected={selected}
91
- onChange={setSelected}
92
- placeholder="Select frameworks..."
93
- />
94
- );
95
- },
96
- };
97
-
98
- export const WithForm: Story = {
99
- args: {
100
- name: "multiSelect",
101
- options: [{ label: "Next.js", value: "nextjs" }],
102
- label: "MultiSelect",
103
- required: true,
104
- },
105
- decorators: [
106
- (Story: React.ComponentType) => {
107
- const form = useForm({
108
- defaultValues: {
109
- multiSelect: ["nextjs"],
110
- },
111
- });
112
- return (
113
- <Form {...form}>
114
- <Story />
115
- </Form>
116
- );
117
- },
118
- ],
119
- };
@@ -1,135 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
- import { Search, X } from "lucide-react";
5
- import { cn } from "../../../../lib/utils";
6
- import * as Popover from "@radix-ui/react-popover";
7
-
8
- export type MultiSelectBaseProps = {
9
- options: { label: string; value: string }[];
10
- selected?: string[];
11
- onChange?: (values: string[]) => void;
12
- placeholder?: string;
13
- className?: string;
14
- };
15
-
16
- export function MultiSelectBase({
17
- options = [],
18
- selected = [],
19
- onChange = () => {},
20
- placeholder = "Select frameworks...",
21
- className,
22
- }: MultiSelectBaseProps) {
23
- const [open, setOpen] = React.useState(false);
24
- const [inputValue, setInputValue] = React.useState("");
25
- const inputRef = React.useRef<HTMLInputElement>(null);
26
-
27
- const handleRemoveItem = (valueToRemove: string) => {
28
- onChange(selected.filter((value) => value !== valueToRemove));
29
- };
30
-
31
- const handleSelectItem = (value: string) => {
32
- if (selected.includes(value)) {
33
- onChange(selected.filter((v) => v !== value));
34
- } else {
35
- onChange([...selected, value]);
36
- }
37
- };
38
-
39
- const filteredOptions = options.filter((option) =>
40
- option.label.toLowerCase().includes(inputValue.toLowerCase())
41
- );
42
-
43
- return (
44
- <Popover.Root open={open} onOpenChange={setOpen}>
45
- <Popover.Trigger asChild>
46
- <div
47
- className={cn(
48
- "flex min-h-[40px] w-full flex-wrap gap-1.5 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
49
- className
50
- )}
51
- >
52
- {selected.map((value) => {
53
- const option = options.find((o) => o.value === value);
54
- if (!option) return null;
55
-
56
- return (
57
- <div
58
- key={value}
59
- className="flex items-center gap-1 rounded-md bg-secondary px-2 py-1 text-sm text-secondary-foreground"
60
- >
61
- {option.label}
62
- <button
63
- type="button"
64
- onClick={(e) => {
65
- e.stopPropagation();
66
- handleRemoveItem(value);
67
- }}
68
- className="rounded-full hover:bg-secondary-foreground/20"
69
- >
70
- <X className="h-3 w-3" />
71
- <span className="sr-only">Remove {option.label}</span>
72
- </button>
73
- </div>
74
- );
75
- })}
76
- <div className="flex-1">
77
- {selected.length === 0 && (
78
- <span className="text-muted-foreground">{placeholder}</span>
79
- )}
80
- </div>
81
- </div>
82
- </Popover.Trigger>
83
-
84
- <Popover.Portal>
85
- <Popover.Content
86
- className="w-[--radix-popover-trigger-width] z-50 mt-1 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95"
87
- align="start"
88
- sideOffset={4}
89
- >
90
- <div className="flex items-center border-b border-border px-3 py-2">
91
- <Search className="h-4 w-4 text-muted-foreground" />
92
- <input
93
- ref={inputRef}
94
- value={inputValue}
95
- onChange={(e) => setInputValue(e.target.value)}
96
- placeholder="Search..."
97
- className="flex-1 bg-transparent px-2 outline-none placeholder:text-muted-foreground"
98
- />
99
- </div>
100
- <div className="max-h-[200px] overflow-auto">
101
- {filteredOptions.length === 0 ? (
102
- <div className="px-2 py-4 text-center text-sm text-muted-foreground">
103
- No results found.
104
- </div>
105
- ) : (
106
- filteredOptions.map((option) => (
107
- <div
108
- key={option.value}
109
- onClick={() => handleSelectItem(option.value)}
110
- className={cn(
111
- "flex cursor-pointer items-center gap-2 px-4 py-2 text-sm hover:bg-accent",
112
- selected.includes(option.value) && "bg-accent"
113
- )}
114
- >
115
- <div
116
- className={cn(
117
- "flex h-4 w-4 items-center justify-center rounded border border-primary",
118
- selected.includes(option.value) &&
119
- "bg-primary text-primary-foreground"
120
- )}
121
- >
122
- {selected.includes(option.value) && (
123
- <span className="text-[10px]">✓</span>
124
- )}
125
- </div>
126
- {option.label}
127
- </div>
128
- ))
129
- )}
130
- </div>
131
- </Popover.Content>
132
- </Popover.Portal>
133
- </Popover.Root>
134
- );
135
- }
@@ -1,75 +0,0 @@
1
- "use client";
2
- import React from "react";
3
- import { Label } from "../../../../components/dataDisplay/Label";
4
- import { MultiSelectBase, MultiSelectBaseProps } from "./MultiSelectBase";
5
- import {
6
- FormControl,
7
- FormField,
8
- FormItem,
9
- FormLabel,
10
- FormMessage,
11
- } from "../../../../components/ui/form";
12
- import { useFormContext } from "react-hook-form";
13
-
14
- type MultiSelectProps = MultiSelectBaseProps & {
15
- label?: string;
16
- name?: string;
17
- withoutForm?: boolean;
18
- className?: string;
19
- required?: boolean;
20
- "data-testid"?: string;
21
- };
22
-
23
- export function MultiSelect({
24
- label,
25
- name,
26
- withoutForm,
27
- className,
28
- required,
29
- "data-testid": testId,
30
- ...props
31
- }: MultiSelectProps) {
32
- const form = useFormContext();
33
- const hasForm = !withoutForm && !!form && !!name;
34
-
35
- if (!hasForm)
36
- return (
37
- <div className="grid w-full items-center gap-3">
38
- {label && <Label htmlFor={name}>{label}</Label>}
39
- <MultiSelectBase {...props} />
40
- </div>
41
- );
42
-
43
- return (
44
- <FormField
45
- control={form.control}
46
- name={name}
47
- render={({ field: { value, ...rest } }) => {
48
- return (
49
- <FormItem
50
- className={className}
51
- data-testid={testId ? `form-item-${testId}` : undefined}
52
- >
53
- {label && (
54
- <FormLabel
55
- htmlFor={name}
56
- data-testid={testId ? `form-label-${testId}` : undefined}
57
- >
58
- {`${label}${required ? " *" : ""}`}
59
- </FormLabel>
60
- )}
61
- <FormControl>
62
- <div className="flex w-full items-center space-x-2">
63
- <MultiSelectBase {...props} {...rest} selected={value} />
64
- </div>
65
- </FormControl>
66
- <FormMessage
67
- role="alert"
68
- data-testid={testId ? `form-message-${testId}` : undefined}
69
- />
70
- </FormItem>
71
- );
72
- }}
73
- />
74
- );
75
- }
@@ -1,61 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/nextjs";
2
- import { Select } from "./index";
3
- import { useForm } from "react-hook-form";
4
- import { Button } from "../../../components/actions";
5
- import { Form } from "../form";
6
-
7
- const meta: Meta<typeof Select> = {
8
- title: "Data Input/Select",
9
- component: Select,
10
- tags: ["autodocs"],
11
- parameters: {
12
- layout: "centered",
13
- },
14
- argTypes: {
15
- options: { control: "object" },
16
- placeholder: { control: "text" },
17
- label: { control: "text" },
18
- value: { control: "text" },
19
- onChange: { action: "changed" },
20
- },
21
- };
22
-
23
- export default meta;
24
- type Story = StoryObj<typeof Select>;
25
-
26
- export const Default: Story = {
27
- args: {
28
- options: [
29
- { value: "option1", label: "Option 1" },
30
- { value: "option2", label: "Option 2" },
31
- ],
32
- placeholder: "Select an option",
33
- label: "Select Label",
34
- },
35
- };
36
-
37
- export const WithForm: Story = {
38
- args: {
39
- options: [
40
- { value: "option1", label: "Option 1" },
41
- { value: "option2", label: "Option 2" },
42
- ],
43
- placeholder: "Select an option",
44
- label: "Select Label",
45
- name: "select",
46
- },
47
- render: (args) => {
48
- const form = useForm();
49
- const onSubmit = (data: unknown) => console.log(data);
50
- return (
51
- <Form {...form}>
52
- <form className="space-y-6" onSubmit={form.handleSubmit(onSubmit)}>
53
- <Select {...args} />
54
- <Button type="button" onClick={() => console.log(form.getValues())}>
55
- Submit
56
- </Button>
57
- </form>
58
- </Form>
59
- );
60
- },
61
- };
@@ -1,73 +0,0 @@
1
- import React from "react";
2
- import { Label } from "../../../components/ui/label";
3
-
4
- import {
5
- FormField,
6
- FormItem,
7
- FormLabel,
8
- FormControl,
9
- FormMessage,
10
- FormDescription,
11
- } from "../../../components/ui/form";
12
- import { SelectBase, SelectBaseProps } from "./SelectBase";
13
- import { useFormContext } from "react-hook-form";
14
- import { cn } from "../../../lib/utils";
15
- import { ErrorMessage } from "../../../components/dataDisplay/ErrorMessage/ErrorMessage";
16
-
17
- export type SelectProps = SelectBaseProps & {
18
- label?: string;
19
- name?: string;
20
- error?: string;
21
- description?: string;
22
- withoutForm?: boolean;
23
- };
24
-
25
- export const Select = ({
26
- name,
27
- label,
28
- description,
29
- error,
30
- className,
31
- withoutForm,
32
- options,
33
- placeholder,
34
- ...props
35
- }: SelectProps) => {
36
- const form = useFormContext();
37
- const hasForm = !!form && !!name;
38
-
39
- if (!hasForm || withoutForm) {
40
- return (
41
- <div className={cn("space-y-2", className)}>
42
- {label && <Label>{label}</Label>}
43
- <SelectBase options={options} placeholder={placeholder} {...props} />
44
- {description && (
45
- <p className="text-sm text-muted-foreground">{description}</p>
46
- )}
47
- {error && <ErrorMessage>{error}</ErrorMessage>}
48
- </div>
49
- );
50
- }
51
-
52
- return (
53
- <FormField
54
- control={form.control}
55
- name={name!}
56
- render={({ field }) => (
57
- <FormItem className={className}>
58
- {label && <FormLabel>{label}</FormLabel>}
59
- <FormControl>
60
- <SelectBase
61
- options={options}
62
- placeholder={placeholder}
63
- {...props}
64
- {...field}
65
- />
66
- </FormControl>
67
- {description && <FormDescription>{description}</FormDescription>}
68
- <FormMessage />
69
- </FormItem>
70
- )}
71
- />
72
- );
73
- };
@@ -1,58 +0,0 @@
1
- import { useCallback } from "react";
2
- import {
3
- Select,
4
- SelectProps,
5
- SelectContent,
6
- SelectItem,
7
- SelectTrigger,
8
- SelectValue,
9
- } from "../../../components/ui/select";
10
-
11
- export type SelectBaseProps = Omit<SelectProps, "onValueChange"> & {
12
- options: {
13
- value: string | number;
14
- label: string;
15
- }[];
16
- placeholder?: string;
17
- className?: string;
18
- id?: string;
19
- onChange?: (value: string) => void;
20
- value?: string;
21
- onChangeCallback?: (value: string) => void;
22
- };
23
-
24
- export const SelectBase = ({
25
- options,
26
- placeholder,
27
- onChange = () => {},
28
- onChangeCallback = () => {},
29
- value,
30
- ...rest
31
- }: SelectBaseProps) => {
32
- const onSelect = useCallback(
33
- (value: string) => {
34
- onChange(value);
35
- onChangeCallback(value);
36
- },
37
- [onChange, onChangeCallback]
38
- );
39
- return (
40
- <Select
41
- {...rest}
42
- onValueChange={onSelect}
43
- defaultValue={value}
44
- value={value}
45
- >
46
- <SelectTrigger>
47
- <SelectValue placeholder={placeholder} />
48
- </SelectTrigger>
49
- <SelectContent>
50
- {options?.map((option, index: number) => (
51
- <SelectItem key={index} value={String(option.value)}>
52
- {option.label}
53
- </SelectItem>
54
- ))}
55
- </SelectContent>
56
- </Select>
57
- );
58
- };
@@ -1,2 +0,0 @@
1
- export * from "./Select";
2
- export * from "./MultiSelect";
@@ -1,75 +0,0 @@
1
- import type { Meta, StoryObj } from "@storybook/nextjs";
2
- import { Switch } from "./index";
3
- import { useState } from "react";
4
- import { Form } from "../form";
5
- import { useForm } from "react-hook-form";
6
-
7
- const meta: Meta<typeof Switch> = {
8
- title: "Data Input/Switch",
9
- component: Switch,
10
- tags: ["autodocs"],
11
- };
12
-
13
- export default meta;
14
- type Story = StoryObj<typeof Switch>;
15
-
16
- const SwitchWithHooks = () => {
17
- const [checked, setChecked] = useState(false);
18
-
19
- return (
20
- <Switch
21
- label="Notifications"
22
- checked={checked}
23
- onCheckedChange={setChecked}
24
- />
25
- );
26
- };
27
-
28
- export const Default: Story = {
29
- render: () => <SwitchWithHooks />,
30
- };
31
-
32
- export const WithoutLabel: Story = {
33
- render: () => {
34
- const [checked, setChecked] = useState(false);
35
-
36
- return <Switch checked={checked} onCheckedChange={setChecked} />;
37
- },
38
- };
39
-
40
- export const Checked: Story = {
41
- render: () => {
42
- const [checked, setChecked] = useState(true);
43
-
44
- return (
45
- <Switch
46
- label="Active status"
47
- checked={checked}
48
- onCheckedChange={setChecked}
49
- />
50
- );
51
- },
52
- };
53
-
54
- export const WithForm: Story = {
55
- args: {
56
- name: "switch",
57
- label: "Terms and Conditions",
58
- required: true,
59
- },
60
- decorators: [
61
- (Story: React.ComponentType) => {
62
- const form = useForm({
63
- defaultValues: {
64
- switch: true,
65
- },
66
- });
67
-
68
- return (
69
- <Form {...form}>
70
- <Story />
71
- </Form>
72
- );
73
- },
74
- ],
75
- };