buildgrid-ui 1.1.0-dev.9 → 1.2.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 (125) hide show
  1. package/dist/blocks/help-carousel/help-carousel.d.ts +9 -0
  2. package/dist/blocks/help-carousel/index.d.ts +1 -0
  3. package/dist/blocks/index.d.ts +4 -0
  4. package/dist/blocks/month-navigator/index.d.ts +1 -0
  5. package/dist/blocks/month-navigator/month-navigator.d.ts +9 -0
  6. package/dist/blocks/pagination-controls/index.d.ts +1 -0
  7. package/dist/blocks/pagination-controls/pagination-controls.d.ts +7 -0
  8. package/dist/blocks/sidebar/index.d.ts +1 -0
  9. package/dist/blocks/sidebar/sidebar.d.ts +26 -0
  10. package/dist/buildgrid-ui.es.js +8678 -3036
  11. package/dist/buildgrid-ui.umd.js +104 -43
  12. package/dist/components/autocomplete/autocomplete.d.ts +1 -0
  13. package/dist/components/calendar/calendar.d.ts +8 -0
  14. package/dist/components/calendar/index.d.ts +1 -0
  15. package/dist/components/dialog/dialog.d.ts +19 -0
  16. package/dist/components/dialog/index.d.ts +1 -0
  17. package/dist/components/index.d.ts +14 -0
  18. package/dist/components/label/index.d.ts +1 -0
  19. package/dist/components/label/label.d.ts +5 -0
  20. package/dist/components/navigation-menu/index.d.ts +1 -0
  21. package/dist/components/navigation-menu/navigation-menu.d.ts +12 -0
  22. package/dist/components/pagination/index.d.ts +1 -0
  23. package/dist/components/pagination/pagination.d.ts +28 -0
  24. package/dist/components/radio-group/index.d.ts +1 -0
  25. package/dist/components/radio-group/radio-group.d.ts +5 -0
  26. package/dist/components/select/index.d.ts +1 -0
  27. package/dist/components/select/select.d.ts +13 -0
  28. package/dist/components/table/index.d.ts +1 -0
  29. package/dist/components/table/table.d.ts +10 -0
  30. package/dist/components/tabs/index.d.ts +1 -0
  31. package/dist/components/tabs/tabs.d.ts +7 -0
  32. package/dist/components/textarea/index.d.ts +1 -0
  33. package/dist/components/textarea/textarea.d.ts +3 -0
  34. package/dist/components/toaster/index.d.ts +2 -0
  35. package/dist/components/toaster/toaster.d.ts +9 -0
  36. package/dist/components/toggle/index.d.ts +1 -0
  37. package/dist/components/toggle/toggle.d.ts +12 -0
  38. package/dist/components/toggle-group/index.d.ts +1 -0
  39. package/dist/components/toggle-group/toggle-group.d.ts +12 -0
  40. package/dist/components/tooltip/index.d.ts +1 -0
  41. package/dist/components/tooltip/tooltip.d.ts +7 -0
  42. package/dist/index.d.ts +3 -1
  43. package/dist/lib/hooks/index.d.ts +5 -0
  44. package/dist/lib/hooks/use-debounce.d.ts +2 -0
  45. package/dist/lib/hooks/use-dialog.d.ts +30 -0
  46. package/dist/lib/hooks/use-media-query.d.ts +1 -0
  47. package/dist/lib/hooks/use-mobile.d.ts +1 -0
  48. package/dist/lib/hooks/use-pwa-install.d.ts +7 -0
  49. package/dist/lib/utils/date-formatters.d.ts +13 -0
  50. package/dist/lib/utils/formatters.d.ts +1 -7
  51. package/dist/lib/utils/index.d.ts +3 -0
  52. package/package.json +19 -2
  53. package/.editorconfig +0 -5
  54. package/.eslintrc.json +0 -3
  55. package/.github/workflows/release.yml +0 -25
  56. package/.husky/commit-msg +0 -1
  57. package/.prettierignore +0 -6
  58. package/.prettierrc +0 -6
  59. package/.releaserc.json +0 -40
  60. package/.storybook/main.ts +0 -26
  61. package/.storybook/preview.ts +0 -15
  62. package/CHANGELOG.md +0 -53
  63. package/commitlint.config.js +0 -3
  64. package/components.json +0 -21
  65. package/dist/lib/index.d.ts +0 -2
  66. package/eslint.config.mjs +0 -13
  67. package/postcss.config.js +0 -6
  68. package/src/components/adaptive-input/adaptive-input.stories.tsx +0 -31
  69. package/src/components/adaptive-input/adaptive-input.tsx +0 -66
  70. package/src/components/adaptive-input/index.ts +0 -1
  71. package/src/components/alert-dialog/alert-dialog.stories.tsx +0 -49
  72. package/src/components/alert-dialog/alert-dialog.tsx +0 -130
  73. package/src/components/alert-dialog/index.ts +0 -1
  74. package/src/components/autocomplete/autocomplete.stories.tsx +0 -84
  75. package/src/components/autocomplete/autocomplete.tsx +0 -136
  76. package/src/components/autocomplete/index.ts +0 -1
  77. package/src/components/avatar/avatar.stories.tsx +0 -29
  78. package/src/components/avatar/avatar.tsx +0 -48
  79. package/src/components/avatar/index.ts +0 -1
  80. package/src/components/badge/badge.stories.tsx +0 -30
  81. package/src/components/badge/badge.tsx +0 -34
  82. package/src/components/badge/index.ts +0 -1
  83. package/src/components/button/button.stories.tsx +0 -62
  84. package/src/components/button/button.tsx +0 -82
  85. package/src/components/button/index.ts +0 -1
  86. package/src/components/card/card.stories.tsx +0 -41
  87. package/src/components/card/card.tsx +0 -61
  88. package/src/components/card/index.ts +0 -1
  89. package/src/components/checkbox/checkbox.stories.tsx +0 -36
  90. package/src/components/checkbox/checkbox.tsx +0 -28
  91. package/src/components/checkbox/index.ts +0 -1
  92. package/src/components/currency-input/currency-input.stories.tsx +0 -28
  93. package/src/components/currency-input/currency-input.tsx +0 -93
  94. package/src/components/currency-input/index.ts +0 -1
  95. package/src/components/dropdown-menu/dropdown-menu.stories.tsx +0 -90
  96. package/src/components/dropdown-menu/dropdown-menu.tsx +0 -192
  97. package/src/components/dropdown-menu/index.ts +0 -1
  98. package/src/components/index.ts +0 -16
  99. package/src/components/input/index.ts +0 -1
  100. package/src/components/input/input.stories.tsx +0 -22
  101. package/src/components/input/input.tsx +0 -41
  102. package/src/components/password-input/index.ts +0 -1
  103. package/src/components/password-input/password-input.stories.tsx +0 -26
  104. package/src/components/password-input/password-input.tsx +0 -98
  105. package/src/components/popover/index.ts +0 -1
  106. package/src/components/popover/popover.stories.tsx +0 -32
  107. package/src/components/popover/popover.tsx +0 -30
  108. package/src/components/progress/index.ts +0 -1
  109. package/src/components/progress/progress.stories.tsx +0 -21
  110. package/src/components/progress/progress.tsx +0 -26
  111. package/src/components/skeleton/index.ts +0 -1
  112. package/src/components/skeleton/skeleton.stories.tsx +0 -24
  113. package/src/components/skeleton/skeleton.tsx +0 -19
  114. package/src/components/switch/index.ts +0 -1
  115. package/src/components/switch/switch.stories.tsx +0 -21
  116. package/src/components/switch/switch.tsx +0 -26
  117. package/src/index.ts +0 -2
  118. package/src/lib/index.ts +0 -2
  119. package/src/lib/utils/cn.ts +0 -6
  120. package/src/lib/utils/formatters.ts +0 -55
  121. package/src/styles/tailwind.css +0 -66
  122. package/tailwind.config.js +0 -57
  123. package/tsconfig.app.json +0 -10
  124. package/tsconfig.json +0 -29
  125. package/vite.config.ts +0 -34
@@ -1,3 +0,0 @@
1
- module.exports = {
2
- extends: ["@commitlint/config-conventional"],
3
- };
package/components.json DELETED
@@ -1,21 +0,0 @@
1
- {
2
- "$schema": "https://ui.shadcn.com/schema.json",
3
- "style": "default",
4
- "rsc": false,
5
- "tsx": true,
6
- "tailwind": {
7
- "config": "tailwind.config.js",
8
- "css": "src/styles/tailwind.css",
9
- "baseColor": "neutral",
10
- "cssVariables": true,
11
- "prefix": ""
12
- },
13
- "aliases": {
14
- "components": "@/components",
15
- "utils": "@/lib/utils",
16
- "ui": "@/components/ui",
17
- "lib": "@/lib",
18
- "hooks": "@/hooks"
19
- },
20
- "iconLibrary": "lucide"
21
- }
@@ -1,2 +0,0 @@
1
- export * from './utils/cn';
2
- export * from './utils/formatters';
package/eslint.config.mjs DELETED
@@ -1,13 +0,0 @@
1
- import path from "node:path";
2
- import { fileURLToPath } from "node:url";
3
- import js from "@eslint/js";
4
- import { FlatCompat } from "@eslint/eslintrc";
5
-
6
- const __filename = fileURLToPath(import.meta.url);
7
- const __dirname = path.dirname(__filename);
8
- const compat = new FlatCompat({
9
- baseDirectory: __dirname,
10
- recommendedConfig: js.configs.recommended,
11
- allConfig: js.configs.all
12
- });
13
- export default [...compat.extends("next/core-web-vitals", "next/typescript", "prettier")];
package/postcss.config.js DELETED
@@ -1,6 +0,0 @@
1
- module.exports = {
2
- plugins: {
3
- tailwindcss: {},
4
- autoprefixer: {},
5
- },
6
- };
@@ -1,31 +0,0 @@
1
- // organize-imports-ignore
2
- import React from 'react'
3
- import type { Meta, StoryObj } from '@storybook/react'
4
-
5
- import { AdaptiveInput } from './adaptive-input'
6
- import { HelpCircle, Phone, User } from 'lucide-react'
7
-
8
- const meta: Meta<typeof AdaptiveInput> = {
9
- title: 'Components/input/adaptiveInput',
10
- component: AdaptiveInput,
11
- }
12
-
13
- export default meta
14
- type Story = StoryObj<typeof AdaptiveInput>
15
-
16
- const Template = () => {
17
- return (
18
- <div className="w-64">
19
- <AdaptiveInput
20
- leftIcon={<Phone className="w-4 h-4" />}
21
- rightIcon={<HelpCircle className="w-4 h-4" />}
22
- mask="+00 0000-0000"
23
- />
24
- </div>
25
- )
26
- }
27
-
28
- export const Default: Story = {
29
- render: Template.bind({}),
30
- args: {},
31
- }
@@ -1,66 +0,0 @@
1
- import { cn } from '@/lib'
2
- import * as React from 'react'
3
- import { Input, InputProps } from '../input'
4
-
5
- export interface AdaptiveInputProps extends InputProps {
6
- leftIcon?: React.ReactNode
7
- rightIcon?: React.ReactNode
8
- mask?: string // New prop for the mask
9
- }
10
-
11
- const applyMask = (value: string, mask: string): string => {
12
- const cleanValue = value.replace(/\D/g, '')
13
- let maskedValue = ''
14
- let maskIndex = 0
15
- let valueIndex = 0
16
-
17
- while (maskIndex < mask.length && valueIndex < cleanValue.length) {
18
- if (mask[maskIndex] === '0') {
19
- maskedValue += cleanValue[valueIndex]
20
- valueIndex++
21
- } else {
22
- maskedValue += mask[maskIndex]
23
- }
24
- maskIndex++
25
- }
26
-
27
- return maskedValue
28
- }
29
-
30
- const AdaptiveInput = React.forwardRef<HTMLInputElement, AdaptiveInputProps>(
31
- ({ className, leftIcon, rightIcon, mask, onChange, ...props }, ref) => {
32
- const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
33
- const input = e.target
34
- if (mask) {
35
- const maskedValue = applyMask(input.value, mask)
36
- input.value = maskedValue
37
- }
38
- onChange?.(e) // Call the original onChange if provided
39
- }
40
-
41
- return (
42
- <div className="relative w-full">
43
- {leftIcon && (
44
- <div className="absolute left-2 top-1/2 -translate-y-1/2 text-muted-foreground">
45
- {leftIcon}
46
- </div>
47
- )}
48
- <Input
49
- className={cn(leftIcon && 'pl-8', rightIcon && 'pr-8', className)}
50
- ref={ref}
51
- onInput={handleInputChange} // Attach the input handler
52
- {...props}
53
- />
54
- {rightIcon && (
55
- <div className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground">
56
- {rightIcon}
57
- </div>
58
- )}
59
- </div>
60
- )
61
- },
62
- )
63
-
64
- AdaptiveInput.displayName = 'AdaptiveInput'
65
-
66
- export { AdaptiveInput }
@@ -1 +0,0 @@
1
- export * from './adaptive-input'
@@ -1,49 +0,0 @@
1
- // organize-imports-ignore
2
- import React from 'react'
3
- import type { Meta, StoryObj } from '@storybook/react'
4
- import {
5
- AlertDialog,
6
- AlertDialogAction,
7
- AlertDialogCancel,
8
- AlertDialogContent,
9
- AlertDialogDescription,
10
- AlertDialogFooter,
11
- AlertDialogHeader,
12
- AlertDialogTitle,
13
- AlertDialogTrigger,
14
- } from './alert-dialog'
15
- import { Button } from '../button'
16
-
17
- const meta: Meta<typeof AlertDialog> = {
18
- component: AlertDialog,
19
- }
20
-
21
- export default meta
22
- type Story = StoryObj<typeof AlertDialog>
23
-
24
- const Template = () => {
25
- return (
26
- <AlertDialog>
27
- <AlertDialogTrigger asChild>
28
- <Button>Open dialog</Button>
29
- </AlertDialogTrigger>
30
- <AlertDialogContent>
31
- <AlertDialogHeader>
32
- <AlertDialogTitle>Alert title</AlertDialogTitle>
33
- <AlertDialogDescription>This is the alert description</AlertDialogDescription>
34
- </AlertDialogHeader>
35
- <div className="bg-gray-200 p-4 h-20 text-sm">Content goes here</div>
36
-
37
- <AlertDialogFooter>
38
- <AlertDialogCancel>Cancel</AlertDialogCancel>
39
- <AlertDialogAction>Submit</AlertDialogAction>
40
- </AlertDialogFooter>
41
- </AlertDialogContent>
42
- </AlertDialog>
43
- )
44
- }
45
-
46
- export const Default: Story = {
47
- render: Template.bind({}),
48
- args: {},
49
- }
@@ -1,130 +0,0 @@
1
- import { cn } from '@/lib'
2
- import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'
3
- import * as React from 'react'
4
- import { buttonVariants } from '../button'
5
-
6
- const AlertDialog = AlertDialogPrimitive.Root
7
-
8
- const AlertDialogTrigger = AlertDialogPrimitive.Trigger
9
-
10
- const AlertDialogPortal = AlertDialogPrimitive.Portal
11
-
12
- const AlertDialogOverlay = React.forwardRef<
13
- React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
14
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
15
- >(({ className, ...props }, ref) => (
16
- <AlertDialogPrimitive.Overlay
17
- className={cn(
18
- 'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
19
- className,
20
- )}
21
- {...props}
22
- ref={ref}
23
- />
24
- ))
25
- AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
26
-
27
- const AlertDialogContent = React.forwardRef<
28
- React.ElementRef<typeof AlertDialogPrimitive.Content>,
29
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
30
- >(({ className, ...props }, ref) => (
31
- <AlertDialogPortal>
32
- <AlertDialogOverlay />
33
- <AlertDialogPrimitive.Content
34
- ref={ref}
35
- className={cn(
36
- 'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
37
- className,
38
- )}
39
- {...props}
40
- />
41
- </AlertDialogPortal>
42
- ))
43
- AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
44
-
45
- const AlertDialogHeader = ({
46
- className,
47
- ...props
48
- }: React.HTMLAttributes<HTMLDivElement>) => (
49
- <div
50
- className={cn('flex flex-col space-y-2 text-center sm:text-left', className)}
51
- {...props}
52
- />
53
- )
54
- AlertDialogHeader.displayName = 'AlertDialogHeader'
55
-
56
- const AlertDialogFooter = ({
57
- className,
58
- ...props
59
- }: React.HTMLAttributes<HTMLDivElement>) => (
60
- <div
61
- className={cn(
62
- 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
63
- className,
64
- )}
65
- {...props}
66
- />
67
- )
68
- AlertDialogFooter.displayName = 'AlertDialogFooter'
69
-
70
- const AlertDialogTitle = React.forwardRef<
71
- React.ElementRef<typeof AlertDialogPrimitive.Title>,
72
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
73
- >(({ className, ...props }, ref) => (
74
- <AlertDialogPrimitive.Title
75
- ref={ref}
76
- className={cn('text-lg font-semibold', className)}
77
- {...props}
78
- />
79
- ))
80
- AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
81
-
82
- const AlertDialogDescription = React.forwardRef<
83
- React.ElementRef<typeof AlertDialogPrimitive.Description>,
84
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
85
- >(({ className, ...props }, ref) => (
86
- <AlertDialogPrimitive.Description
87
- ref={ref}
88
- className={cn('text-sm text-muted-foreground', className)}
89
- {...props}
90
- />
91
- ))
92
- AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName
93
-
94
- const AlertDialogAction = React.forwardRef<
95
- React.ElementRef<typeof AlertDialogPrimitive.Action>,
96
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
97
- >(({ className, ...props }, ref) => (
98
- <AlertDialogPrimitive.Action
99
- ref={ref}
100
- className={cn(buttonVariants(), className)}
101
- {...props}
102
- />
103
- ))
104
- AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
105
-
106
- const AlertDialogCancel = React.forwardRef<
107
- React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
108
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
109
- >(({ className, ...props }, ref) => (
110
- <AlertDialogPrimitive.Cancel
111
- ref={ref}
112
- className={cn(buttonVariants({ variant: 'outline' }), 'mt-2 sm:mt-0', className)}
113
- {...props}
114
- />
115
- ))
116
- AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
117
-
118
- export {
119
- AlertDialog,
120
- AlertDialogAction,
121
- AlertDialogCancel,
122
- AlertDialogContent,
123
- AlertDialogDescription,
124
- AlertDialogFooter,
125
- AlertDialogHeader,
126
- AlertDialogOverlay,
127
- AlertDialogPortal,
128
- AlertDialogTitle,
129
- AlertDialogTrigger,
130
- }
@@ -1 +0,0 @@
1
- export * from './alert-dialog'
@@ -1,84 +0,0 @@
1
- // organize-imports-ignore
2
- import React from 'react'
3
- import type { Meta, StoryObj } from '@storybook/react'
4
-
5
- import { Autocomplete } from './autocomplete'
6
-
7
- const meta: Meta<typeof Autocomplete> = {
8
- title: 'Components/input/autocomplete',
9
- component: Autocomplete,
10
- }
11
-
12
- export default meta
13
- type Story = StoryObj<typeof Autocomplete>
14
-
15
- // list of 50 names of countries
16
- const options = [
17
- 'United States',
18
- 'Canada',
19
- 'Argentina',
20
- 'Brazil',
21
- 'Chile',
22
- 'Colombia',
23
- 'Ecuador',
24
- 'Peru',
25
- 'Uruguay',
26
- 'Venezuela',
27
- 'Australia',
28
- 'China',
29
- 'India',
30
- 'Indonesia',
31
- 'Japan',
32
- 'Korea',
33
- 'Malaysia',
34
- 'Philippines',
35
- 'Singapore',
36
- 'Thailand',
37
- 'Vietnam',
38
- 'Austria',
39
- 'Belgium',
40
- 'Croatia',
41
- 'Denmark',
42
- 'Finland',
43
- 'France',
44
- 'Germany',
45
- 'Greece',
46
- 'Hungary',
47
- 'Ireland',
48
- 'Italy',
49
- 'Netherlands',
50
- 'Norway',
51
- 'Poland',
52
- 'Portugal',
53
- 'Romania',
54
- 'Russia',
55
- 'Spain',
56
- 'Sweden',
57
- 'Switzerland',
58
- 'Turkey',
59
- 'Ukraine',
60
- 'United Kingdom',
61
- 'Egypt',
62
- 'Nigeria',
63
- 'South Africa',
64
- 'Kenya',
65
- ]
66
-
67
- const Template = () => {
68
- const [value, setValue] = React.useState('')
69
- return (
70
- <div className="w-80">
71
- <Autocomplete
72
- value={value}
73
- onChange={(value) => setValue(value)}
74
- options={options.map((option) => ({ value: option, label: option }))}
75
- />
76
- <p className="mt-4">Selected value: {value}</p>
77
- </div>
78
- )
79
- }
80
-
81
- export const Default: Story = {
82
- render: Template.bind({}),
83
- args: {},
84
- }
@@ -1,136 +0,0 @@
1
- import { Search } from 'lucide-react'
2
- import { useState } from 'react'
3
-
4
- import { cn } from '@/lib'
5
- import { AdaptiveInput } from '../adaptive-input'
6
- import { Popover, PopoverContent, PopoverTrigger } from '../popover'
7
-
8
- interface Option {
9
- value: string
10
- label: string
11
- }
12
-
13
- interface AutoCompleteProps {
14
- value?: string
15
- onChange?: (value: string) => void
16
- options: Option[]
17
- className?: string
18
- placeholder?: string
19
- emptyMessage?: string
20
- }
21
-
22
- export function Autocomplete(props: AutoCompleteProps) {
23
- const {
24
- value = '',
25
- onChange,
26
- options: staticOptions,
27
- className,
28
- placeholder = 'Search...',
29
- emptyMessage = 'Nothing found',
30
- } = props
31
-
32
- const [query, setQuery] = useState(value)
33
- const [suggestions, setSuggestions] = useState<Option[]>(staticOptions)
34
- const [selectedIndex, setSelectedIndex] = useState(-1)
35
- const [isFocused, setIsFocused] = useState(false)
36
-
37
- const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
38
- const newValue = e.target.value
39
- setQuery(newValue)
40
- onChange?.(newValue)
41
- setSelectedIndex(-1)
42
- setIsFocused(true)
43
-
44
- if (newValue.trim() === '') {
45
- setSuggestions(staticOptions)
46
- } else {
47
- setSuggestions(
48
- staticOptions.filter((option) =>
49
- option.label.toLowerCase().includes(newValue.toLowerCase()),
50
- ),
51
- )
52
- }
53
- }
54
-
55
- const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
56
- if (e.key === 'ArrowDown') {
57
- e.preventDefault()
58
- setSelectedIndex((prev) => (prev < suggestions.length - 1 ? prev + 1 : prev))
59
- } else if (e.key === 'ArrowUp') {
60
- e.preventDefault()
61
- setSelectedIndex((prev) => (prev > 0 ? prev - 1 : -1))
62
- } else if (e.key === 'Enter' && selectedIndex >= 0) {
63
- const selectedOption = suggestions[selectedIndex]
64
- setQuery(selectedOption.label)
65
- onChange?.(selectedOption.value)
66
- setSuggestions([])
67
- setSelectedIndex(-1)
68
- setIsFocused(false)
69
- } else if (e.key === 'Escape') {
70
- setSuggestions([])
71
- setSelectedIndex(-1)
72
- }
73
- }
74
-
75
- const handleSuggestionClick = (option: Option) => {
76
- setIsFocused(false)
77
- setQuery(option.label)
78
- onChange?.(option.value)
79
- setSuggestions(staticOptions)
80
- setSelectedIndex(-1)
81
- }
82
-
83
- const handleFocus = () => {
84
- setIsFocused(true)
85
- }
86
-
87
- const handleBlur = () => {
88
- setIsFocused(false)
89
- }
90
-
91
- return (
92
- <Popover open={isFocused}>
93
- <PopoverTrigger asChild>
94
- <div className="relative w-full">
95
- <AdaptiveInput
96
- type="text"
97
- placeholder={placeholder}
98
- value={query}
99
- onChange={handleInputChange}
100
- onKeyDown={handleKeyDown}
101
- onClick={handleFocus}
102
- onFocus={handleFocus}
103
- onBlur={handleBlur}
104
- className={cn('pr-10', className)}
105
- aria-label="Search field"
106
- aria-autocomplete="list"
107
- aria-controls="suggestions-list"
108
- aria-expanded={suggestions.length > 0}
109
- leftIcon={<Search className="w-4 h-4" />}
110
- />
111
- </div>
112
- </PopoverTrigger>
113
- <PopoverContent className="p-0 w-[var(--radix-popover-trigger-width)] max-h-96 overflow-y-auto">
114
- {suggestions.length > 0 ? (
115
- <ul id="suggestions-list" role="listbox">
116
- {suggestions.map((option, index) => (
117
- <li
118
- key={option.value}
119
- className={`px-4 py-2 cursor-pointer hover:bg-muted ${
120
- index === selectedIndex ? 'bg-muted' : ''
121
- }`}
122
- onClick={() => handleSuggestionClick(option)}
123
- role="option"
124
- aria-selected={index === selectedIndex}
125
- >
126
- {option.label}
127
- </li>
128
- ))}
129
- </ul>
130
- ) : (
131
- <span className="px-4 py-2 block">{emptyMessage}</span>
132
- )}
133
- </PopoverContent>
134
- </Popover>
135
- )
136
- }
@@ -1 +0,0 @@
1
- export * from './autocomplete'
@@ -1,29 +0,0 @@
1
- // organize-imports-ignore
2
- import React from 'react'
3
- import type { Meta, StoryObj } from '@storybook/react'
4
-
5
- import { Avatar, AvatarFallback, AvatarImage } from './avatar'
6
-
7
- const meta: Meta<typeof Avatar> = {
8
- component: Avatar,
9
- }
10
-
11
- export default meta
12
- type Story = StoryObj<typeof Avatar>
13
-
14
- const Template = () => {
15
- return (
16
- <Avatar className="w-24 h-24">
17
- <AvatarImage
18
- src="https://upload.wikimedia.org/wikipedia/commons/7/7c/Profile_avatar_placeholder_large.png?20150327203541"
19
- alt="User avatar"
20
- />
21
- <AvatarFallback>NS</AvatarFallback>
22
- </Avatar>
23
- )
24
- }
25
-
26
- export const Default: Story = {
27
- render: Template.bind({}),
28
- args: {},
29
- }
@@ -1,48 +0,0 @@
1
- import * as AvatarPrimitive from '@radix-ui/react-avatar'
2
- import * as React from 'react'
3
-
4
- import { cn } from '@/lib/utils/cn'
5
-
6
- const Avatar = React.forwardRef<
7
- React.ElementRef<typeof AvatarPrimitive.Root>,
8
- React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
9
- >(({ className, ...props }, ref) => (
10
- <AvatarPrimitive.Root
11
- ref={ref}
12
- className={cn(
13
- 'relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full',
14
- className,
15
- )}
16
- {...props}
17
- />
18
- ))
19
- Avatar.displayName = AvatarPrimitive.Root.displayName
20
-
21
- const AvatarImage = React.forwardRef<
22
- React.ElementRef<typeof AvatarPrimitive.Image>,
23
- React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
24
- >(({ className, ...props }, ref) => (
25
- <AvatarPrimitive.Image
26
- ref={ref}
27
- className={cn('aspect-square h-full w-full', className)}
28
- {...props}
29
- />
30
- ))
31
- AvatarImage.displayName = AvatarPrimitive.Image.displayName
32
-
33
- const AvatarFallback = React.forwardRef<
34
- React.ElementRef<typeof AvatarPrimitive.Fallback>,
35
- React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
36
- >(({ className, ...props }, ref) => (
37
- <AvatarPrimitive.Fallback
38
- ref={ref}
39
- className={cn(
40
- 'flex h-full w-full items-center justify-center rounded-full bg-muted',
41
- className,
42
- )}
43
- {...props}
44
- />
45
- ))
46
- AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
47
-
48
- export { Avatar, AvatarFallback, AvatarImage }
@@ -1 +0,0 @@
1
- export * from './avatar'
@@ -1,30 +0,0 @@
1
- // organize-imports-ignore
2
- import React from 'react'
3
- import type { Meta, StoryObj } from '@storybook/react'
4
-
5
- import { Badge, BadgeProps, badgeVariants } from './badge'
6
-
7
- const meta: Meta<typeof Badge> = {
8
- component: Badge,
9
- }
10
-
11
- export default meta
12
- type Story = StoryObj<typeof Badge>
13
-
14
- const Template = (args: BadgeProps) => {
15
- const variants = ['default', 'secondary', 'destructive', 'outline']
16
- return (
17
- <div className="flex gap-2">
18
- {Object.values(variants).map((variant) => (
19
- <Badge {...args} variant={variant as BadgeProps['variant']}>
20
- {variant}
21
- </Badge>
22
- ))}
23
- </div>
24
- )
25
- }
26
-
27
- export const Default: Story = {
28
- render: Template.bind({}),
29
- args: {},
30
- }