@asafarim/react-dropdowns 1.0.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/README.md +396 -0
- package/dist/components/Dropdown.d.ts +3 -0
- package/dist/components/DropdownItem.d.ts +3 -0
- package/dist/components/DropdownMenu.d.ts +3 -0
- package/dist/components/DropdownTrigger.d.ts +3 -0
- package/dist/hooks/useClickOutside.d.ts +8 -0
- package/dist/hooks/useDropdown.d.ts +17 -0
- package/dist/hooks/useKeyboardNavigation.d.ts +9 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.esm.css +1 -0
- package/dist/index.esm.js +411 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +419 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +64 -0
- package/package.json +67 -0
- package/src/components/Dropdown.tsx +158 -0
- package/src/components/DropdownItem.tsx +54 -0
- package/src/components/DropdownMenu.tsx +34 -0
- package/src/components/DropdownTrigger.module.css +204 -0
- package/src/components/DropdownTrigger.module.css.d.ts +14 -0
- package/src/components/DropdownTrigger.tsx +60 -0
- package/src/hooks/useClickOutside.ts +34 -0
- package/src/hooks/useDropdown.ts +195 -0
- package/src/hooks/useKeyboardNavigation.ts +108 -0
- package/src/index.ts +26 -0
- package/src/styles/dropdown.css +231 -0
- package/src/types/css-modules.d.ts +14 -0
- package/src/types/index.ts +86 -0
package/README.md
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
# @asafarim/react-dropdowns
|
|
2
|
+
|
|
3
|
+
Comprehensive, accessible, and mobile-first dropdown components for React with TypeScript support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎯 **Comprehensive**: Multiple components for different use cases
|
|
8
|
+
- ♿ **Accessible**: Full keyboard navigation and screen reader support
|
|
9
|
+
- 📱 **Mobile-First**: Optimized for touch devices with responsive design
|
|
10
|
+
- 🎨 **Themeable**: Uses ASafariM design tokens with dark theme support
|
|
11
|
+
- 🔧 **TypeScript**: Full type safety and IntelliSense support
|
|
12
|
+
- âš¡ **Performant**: Lightweight with minimal dependencies
|
|
13
|
+
- 🎪 **Flexible**: Multiple placement options and customization
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @asafarim/react-dropdowns
|
|
19
|
+
# or
|
|
20
|
+
yarn add @asafarim/react-dropdowns
|
|
21
|
+
# or
|
|
22
|
+
pnpm add @asafarim/react-dropdowns
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { Dropdown } from '@asafarim/react-dropdowns';
|
|
29
|
+
import '@asafarim/react-dropdowns/dist/dropdown.css';
|
|
30
|
+
|
|
31
|
+
function App() {
|
|
32
|
+
return (
|
|
33
|
+
<Dropdown
|
|
34
|
+
items={[
|
|
35
|
+
{
|
|
36
|
+
id: 'edit',
|
|
37
|
+
label: 'Edit',
|
|
38
|
+
onClick: () => console.log('Edit clicked')
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 'delete',
|
|
42
|
+
label: 'Delete',
|
|
43
|
+
danger: true,
|
|
44
|
+
onClick: () => console.log('Delete clicked')
|
|
45
|
+
}
|
|
46
|
+
]}
|
|
47
|
+
placement="bottom-start"
|
|
48
|
+
>
|
|
49
|
+
<button>Actions</button>
|
|
50
|
+
</Dropdown>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Components
|
|
56
|
+
|
|
57
|
+
### Dropdown
|
|
58
|
+
|
|
59
|
+
The main dropdown component that combines trigger and menu functionality.
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
<Dropdown
|
|
63
|
+
items={[
|
|
64
|
+
{
|
|
65
|
+
id: 'option1',
|
|
66
|
+
label: 'Option 1',
|
|
67
|
+
icon: <Icon />,
|
|
68
|
+
onClick: () => {},
|
|
69
|
+
disabled: false,
|
|
70
|
+
danger: false
|
|
71
|
+
},
|
|
72
|
+
{ divider: true }, // Separator
|
|
73
|
+
{
|
|
74
|
+
id: 'option2',
|
|
75
|
+
label: 'Option 2',
|
|
76
|
+
onClick: () => {}
|
|
77
|
+
}
|
|
78
|
+
]}
|
|
79
|
+
isOpen={isOpen}
|
|
80
|
+
onToggle={setIsOpen}
|
|
81
|
+
placement="bottom-start"
|
|
82
|
+
size="md"
|
|
83
|
+
disabled={false}
|
|
84
|
+
closeOnSelect={true}
|
|
85
|
+
>
|
|
86
|
+
<button>Trigger</button>
|
|
87
|
+
</Dropdown>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### DropdownItem
|
|
91
|
+
|
|
92
|
+
Individual menu item component.
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
<DropdownItem
|
|
96
|
+
label="Edit Item"
|
|
97
|
+
icon={<EditIcon />}
|
|
98
|
+
onClick={() => {}}
|
|
99
|
+
disabled={false}
|
|
100
|
+
danger={false}
|
|
101
|
+
/>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### DropdownMenu
|
|
105
|
+
|
|
106
|
+
Standalone menu component for custom implementations.
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
<DropdownMenu
|
|
110
|
+
isOpen={isOpen}
|
|
111
|
+
position={{ top: 100, left: 50 }}
|
|
112
|
+
size="md"
|
|
113
|
+
>
|
|
114
|
+
<DropdownItem label="Option 1" onClick={() => {}} />
|
|
115
|
+
<DropdownItem label="Option 2" onClick={() => {}} />
|
|
116
|
+
</DropdownMenu>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Props
|
|
120
|
+
|
|
121
|
+
### DropdownProps
|
|
122
|
+
|
|
123
|
+
| Prop | Type | Default | Description |
|
|
124
|
+
|------|------|---------|-------------|
|
|
125
|
+
| `children` | `ReactNode` | - | Trigger element |
|
|
126
|
+
| `items` | `DropdownItemData[]` | `[]` | Menu items |
|
|
127
|
+
| `isOpen` | `boolean` | - | Controlled open state |
|
|
128
|
+
| `onToggle` | `(isOpen: boolean) => void` | - | Open state change handler |
|
|
129
|
+
| `placement` | `DropdownPlacement` | `'bottom-start'` | Menu position |
|
|
130
|
+
| `size` | `DropdownSize` | `'md'` | Menu size |
|
|
131
|
+
| `disabled` | `boolean` | `false` | Disable the dropdown |
|
|
132
|
+
| `closeOnSelect` | `boolean` | `true` | Close menu on item select |
|
|
133
|
+
|
|
134
|
+
### DropdownItemData
|
|
135
|
+
|
|
136
|
+
| Prop | Type | Default | Description |
|
|
137
|
+
|------|------|---------|-------------|
|
|
138
|
+
| `id` | `string` | - | Unique identifier |
|
|
139
|
+
| `label` | `string` | - | Item text |
|
|
140
|
+
| `value` | `string` | - | Item value |
|
|
141
|
+
| `icon` | `ReactNode` | - | Item icon |
|
|
142
|
+
| `disabled` | `boolean` | `false` | Disable the item |
|
|
143
|
+
| `danger` | `boolean` | `false` | Danger styling |
|
|
144
|
+
| `divider` | `boolean` | `false` | Render as divider |
|
|
145
|
+
| `onClick` | `(event: MouseEvent) => void` | - | Click handler |
|
|
146
|
+
|
|
147
|
+
## Placement Options
|
|
148
|
+
|
|
149
|
+
The dropdown supports 12 different placement options:
|
|
150
|
+
|
|
151
|
+
- `top`, `top-start`, `top-end`
|
|
152
|
+
- `bottom`, `bottom-start`, `bottom-end`
|
|
153
|
+
- `left`, `left-start`, `left-end`
|
|
154
|
+
- `right`, `right-start`, `right-end`
|
|
155
|
+
|
|
156
|
+
## Size Options
|
|
157
|
+
|
|
158
|
+
Three size variants are available:
|
|
159
|
+
|
|
160
|
+
- `sm` - Compact size for tight spaces
|
|
161
|
+
- `md` - Default size for most use cases
|
|
162
|
+
- `lg` - Large size for better touch targets
|
|
163
|
+
|
|
164
|
+
## Hooks
|
|
165
|
+
|
|
166
|
+
### useDropdown
|
|
167
|
+
|
|
168
|
+
Custom hook for building dropdown functionality:
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import { useDropdown } from '@asafarim/react-dropdowns';
|
|
172
|
+
|
|
173
|
+
const {
|
|
174
|
+
isOpen,
|
|
175
|
+
position,
|
|
176
|
+
triggerRef,
|
|
177
|
+
menuRef,
|
|
178
|
+
toggle,
|
|
179
|
+
open,
|
|
180
|
+
close,
|
|
181
|
+
handleItemClick
|
|
182
|
+
} = useDropdown({
|
|
183
|
+
placement: 'bottom-start',
|
|
184
|
+
offset: 8,
|
|
185
|
+
closeOnSelect: true
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### useClickOutside
|
|
190
|
+
|
|
191
|
+
Hook for detecting clicks outside an element:
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
import { useClickOutside } from '@asafarim/react-dropdowns';
|
|
195
|
+
|
|
196
|
+
useClickOutside({
|
|
197
|
+
ref: elementRef,
|
|
198
|
+
handler: () => setIsOpen(false),
|
|
199
|
+
enabled: isOpen
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### useKeyboardNavigation
|
|
204
|
+
|
|
205
|
+
Hook for keyboard navigation support:
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
import { useKeyboardNavigation } from '@asafarim/react-dropdowns';
|
|
209
|
+
|
|
210
|
+
useKeyboardNavigation({
|
|
211
|
+
isOpen,
|
|
212
|
+
menuRef,
|
|
213
|
+
onClose: () => setIsOpen(false),
|
|
214
|
+
onSelect: (index) => selectItem(index)
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Styling
|
|
219
|
+
|
|
220
|
+
The components use CSS custom properties (CSS variables) from the ASafariM design token system. Import the CSS file:
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
import '@asafarim/react-dropdowns/dist/dropdown.css';
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Custom Styling
|
|
227
|
+
|
|
228
|
+
You can override the default styles by targeting the CSS classes:
|
|
229
|
+
|
|
230
|
+
```css
|
|
231
|
+
.asm-dropdown-menu {
|
|
232
|
+
/* Custom menu styles */
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.asm-dropdown-item {
|
|
236
|
+
/* Custom item styles */
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.asm-dropdown-item--danger {
|
|
240
|
+
/* Custom danger item styles */
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Accessibility
|
|
245
|
+
|
|
246
|
+
The dropdown components are built with accessibility in mind:
|
|
247
|
+
|
|
248
|
+
- **Keyboard Navigation**: Arrow keys, Enter, Escape, Home, End
|
|
249
|
+
- **Screen Reader Support**: Proper ARIA attributes and roles
|
|
250
|
+
- **Focus Management**: Automatic focus handling and restoration
|
|
251
|
+
- **High Contrast**: Support for high contrast mode
|
|
252
|
+
- **Reduced Motion**: Respects user's motion preferences
|
|
253
|
+
|
|
254
|
+
### Keyboard Shortcuts
|
|
255
|
+
|
|
256
|
+
| Key | Action |
|
|
257
|
+
|-----|--------|
|
|
258
|
+
| `Space` / `Enter` | Open/close dropdown or select item |
|
|
259
|
+
| `Arrow Down` | Navigate to next item or open dropdown |
|
|
260
|
+
| `Arrow Up` | Navigate to previous item |
|
|
261
|
+
| `Home` | Navigate to first item |
|
|
262
|
+
| `End` | Navigate to last item |
|
|
263
|
+
| `Escape` | Close dropdown |
|
|
264
|
+
| `Tab` | Close dropdown and move to next element |
|
|
265
|
+
|
|
266
|
+
## Examples
|
|
267
|
+
|
|
268
|
+
### Basic Menu
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
<Dropdown
|
|
272
|
+
items={[
|
|
273
|
+
{ id: 'new', label: 'New', onClick: () => {} },
|
|
274
|
+
{ id: 'edit', label: 'Edit', onClick: () => {} },
|
|
275
|
+
{ divider: true },
|
|
276
|
+
{ id: 'delete', label: 'Delete', danger: true, onClick: () => {} }
|
|
277
|
+
]}
|
|
278
|
+
>
|
|
279
|
+
<button>File</button>
|
|
280
|
+
</Dropdown>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### User Menu
|
|
284
|
+
|
|
285
|
+
```tsx
|
|
286
|
+
<Dropdown
|
|
287
|
+
items={[
|
|
288
|
+
{
|
|
289
|
+
id: 'profile',
|
|
290
|
+
label: 'Profile',
|
|
291
|
+
icon: <UserIcon />,
|
|
292
|
+
onClick: () => navigate('/profile')
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
id: 'settings',
|
|
296
|
+
label: 'Settings',
|
|
297
|
+
icon: <SettingsIcon />,
|
|
298
|
+
onClick: () => navigate('/settings')
|
|
299
|
+
},
|
|
300
|
+
{ divider: true },
|
|
301
|
+
{
|
|
302
|
+
id: 'logout',
|
|
303
|
+
label: 'Logout',
|
|
304
|
+
icon: <LogoutIcon />,
|
|
305
|
+
danger: true,
|
|
306
|
+
onClick: handleLogout
|
|
307
|
+
}
|
|
308
|
+
]}
|
|
309
|
+
placement="bottom-end"
|
|
310
|
+
>
|
|
311
|
+
<img src={user.avatar} alt={user.name} />
|
|
312
|
+
</Dropdown>
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Filter Dropdown
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
const [filter, setFilter] = useState('all');
|
|
319
|
+
|
|
320
|
+
<Dropdown
|
|
321
|
+
items={[
|
|
322
|
+
{
|
|
323
|
+
id: 'all',
|
|
324
|
+
label: 'All Items',
|
|
325
|
+
icon: filter === 'all' ? <CheckIcon /> : undefined,
|
|
326
|
+
onClick: () => setFilter('all')
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
id: 'active',
|
|
330
|
+
label: 'Active Only',
|
|
331
|
+
icon: filter === 'active' ? <CheckIcon /> : undefined,
|
|
332
|
+
onClick: () => setFilter('active')
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
id: 'archived',
|
|
336
|
+
label: 'Archived',
|
|
337
|
+
icon: filter === 'archived' ? <CheckIcon /> : undefined,
|
|
338
|
+
onClick: () => setFilter('archived')
|
|
339
|
+
}
|
|
340
|
+
]}
|
|
341
|
+
>
|
|
342
|
+
<button>
|
|
343
|
+
<FilterIcon />
|
|
344
|
+
Filter: {filter}
|
|
345
|
+
<ChevronDownIcon />
|
|
346
|
+
</button>
|
|
347
|
+
</Dropdown>
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## Demo
|
|
351
|
+
|
|
352
|
+
Run the demo application to see all features in action:
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
cd packages/react-dropdowns/demo
|
|
356
|
+
npm install
|
|
357
|
+
npm start
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
The demo showcases:
|
|
361
|
+
- Basic usage examples
|
|
362
|
+
- All placement options
|
|
363
|
+
- Interactive examples (filters, user selectors)
|
|
364
|
+
- Different sizes and states
|
|
365
|
+
- Mobile optimizations
|
|
366
|
+
- Dark theme support
|
|
367
|
+
|
|
368
|
+
## Browser Support
|
|
369
|
+
|
|
370
|
+
- Chrome 88+
|
|
371
|
+
- Firefox 78+
|
|
372
|
+
- Safari 14+
|
|
373
|
+
- Edge 88+
|
|
374
|
+
|
|
375
|
+
## Contributing
|
|
376
|
+
|
|
377
|
+
1. Fork the repository
|
|
378
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
379
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
380
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
381
|
+
5. Open a Pull Request
|
|
382
|
+
|
|
383
|
+
## License
|
|
384
|
+
|
|
385
|
+
MIT © ASafariM
|
|
386
|
+
|
|
387
|
+
## Changelog
|
|
388
|
+
|
|
389
|
+
### 1.0.0
|
|
390
|
+
|
|
391
|
+
- Initial release
|
|
392
|
+
- Comprehensive dropdown components
|
|
393
|
+
- Mobile-first responsive design
|
|
394
|
+
- Full accessibility support
|
|
395
|
+
- TypeScript support
|
|
396
|
+
- ASafariM design token integration
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DropdownPlacement, DropdownPosition } from '../types';
|
|
2
|
+
interface UseDropdownProps {
|
|
3
|
+
placement?: DropdownPlacement;
|
|
4
|
+
offset?: number;
|
|
5
|
+
closeOnSelect?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare const useDropdown: ({ placement, offset, closeOnSelect }?: UseDropdownProps) => {
|
|
8
|
+
isOpen: boolean;
|
|
9
|
+
position: DropdownPosition;
|
|
10
|
+
triggerRef: import("react").RefObject<HTMLDivElement>;
|
|
11
|
+
menuRef: import("react").RefObject<HTMLDivElement>;
|
|
12
|
+
toggle: () => void;
|
|
13
|
+
open: () => void;
|
|
14
|
+
close: () => void;
|
|
15
|
+
handleItemClick: () => void;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
interface UseKeyboardNavigationProps {
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
menuRef: RefObject<HTMLElement>;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
onSelect?: (index: number) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare const useKeyboardNavigation: ({ isOpen, menuRef, onClose, onSelect }: UseKeyboardNavigationProps) => void;
|
|
9
|
+
export {};
|
package/dist/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.dropdown_asm-dropdown__h1OJq{display:inline-block;position:relative}.dropdown_asm-dropdown-trigger__NJPo2{align-items:center;background:none;border:none;cursor:pointer;display:inline-flex;justify-content:center;margin:0;padding:0}.dropdown_asm-dropdown-trigger__NJPo2:disabled{cursor:not-allowed;opacity:.6}.dropdown_asm-dropdown-trigger__NJPo2:focus-visible{border-radius:var(--asm-radius-sm);outline:2px solid var(--asm-color-primary-500);outline-offset:2px}.dropdown_asm-dropdown-menu__YMlWB{animation:dropdown_asm-dropdown-enter__rh5Tw .15s ease-out;background-color:var(--asm-color-surface);border:1px solid var(--asm-color-border);border-radius:var(--asm-radius-lg);box-shadow:var(--asm-effect-shadow-lg);max-height:400px;max-width:320px;min-width:160px;overflow-y:auto;padding:var(--asm-space-1);transform-origin:top;z-index:var(--asm-z-dropdown)}@keyframes dropdown_asm-dropdown-enter__rh5Tw{0%{opacity:0;transform:scale(.95) translateY(-8px)}to{opacity:1;transform:scale(1) translateY(0)}}.dropdown_asm-dropdown-menu--sm__jecEV{min-width:120px;padding:var(--asm-space-0-5)}.dropdown_asm-dropdown-menu--md__X4BwH{min-width:160px;padding:var(--asm-space-1)}.dropdown_asm-dropdown-menu--lg__BQ3dL{min-width:200px;padding:var(--asm-space-1-5)}.dropdown_asm-dropdown-item__8UHDs{align-items:center;background:transparent;border:none;border-radius:var(--asm-radius-md);color:var(--asm-color-text);cursor:pointer;display:flex;font-size:var(--asm-font-size-sm);font-weight:var(--asm-font-weight-400);gap:var(--asm-space-2);min-height:36px;padding:var(--asm-space-2) var(--asm-space-3);text-align:left;transition:var(--asm-transition-fade);width:100%}.dropdown_asm-dropdown-item__8UHDs:focus,.dropdown_asm-dropdown-item__8UHDs:hover:not(:disabled){background-color:var(--asm-color-button-ghost-bg-hover);color:var(--asm-color-text)}.dropdown_asm-dropdown-item__8UHDs:focus{outline:none}.dropdown_asm-dropdown-item__8UHDs:active:not(:disabled){background-color:var(--asm-color-button-ghost-bg-hover)}.dropdown_asm-dropdown-item--disabled__FiaRm{color:var(--asm-color-text-muted);cursor:not-allowed;opacity:.6}.dropdown_asm-dropdown-item--danger__8yZZC{color:var(--asm-color-danger-600)}.dropdown_asm-dropdown-item--danger__8yZZC:focus,.dropdown_asm-dropdown-item--danger__8yZZC:hover:not(:disabled){background-color:var(--asm-color-danger-50);color:var(--asm-color-danger-700)}.dropdown_asm-dropdown-item__icon__r1aA0{align-items:center;display:flex;flex-shrink:0;height:16px;justify-content:center;width:16px}.dropdown_asm-dropdown-item__label__UVmKu{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dropdown_asm-dropdown-divider__JN-Gh{background-color:var(--asm-color-border);height:1px;margin:var(--asm-space-1) 0}[data-theme=dark] .dropdown_asm-dropdown-menu__YMlWB{background-color:var(--asm-color-surface);border-color:var(--asm-color-border);box-shadow:var(--asm-effect-shadow-lg)}[data-theme=dark] .dropdown_asm-dropdown-item__8UHDs{color:var(--asm-color-text)}[data-theme=dark] .dropdown_asm-dropdown-item__8UHDs:hover:not(:disabled){background-color:var(--asm-color-button-ghost-bg-hover)}[data-theme=dark] .dropdown_asm-dropdown-item--danger__8yZZC{color:var(--asm-color-danger-400)}[data-theme=dark] .dropdown_asm-dropdown-item--danger__8yZZC:hover:not(:disabled){background-color:var(--asm-color-danger-900);color:var(--asm-color-danger-300)}@media (max-width:640px){.dropdown_asm-dropdown-menu__YMlWB{max-height:60vh;max-width:calc(100vw - 32px);min-width:200px}.dropdown_asm-dropdown-item__8UHDs{font-size:var(--asm-font-size-md);min-height:44px;padding:var(--asm-space-3) var(--asm-space-4)}.dropdown_asm-dropdown-item__icon__r1aA0{height:20px;width:20px}}@media (hover:none) and (pointer:coarse){.dropdown_asm-dropdown-item__8UHDs{min-height:44px;padding:var(--asm-space-3) var(--asm-space-4)}}@media (prefers-reduced-motion:reduce){.dropdown_asm-dropdown-menu__YMlWB{animation:none}.dropdown_asm-dropdown-item__8UHDs{transition:none}}@media (prefers-contrast:high){.dropdown_asm-dropdown-menu__YMlWB{border-width:2px}.dropdown_asm-dropdown-item__8UHDs:focus{outline:2px solid currentColor;outline-offset:-2px}}@import "@asafarim/design-tokens/css/index.css";.DropdownTrigger-module_trigger__2aFGL{align-items:center;border:none;border-radius:var(--asm-radius-md);cursor:pointer;display:inline-flex;font-family:var(--asm-font-family-primary);font-size:var(--asm-font-size-md);font-weight:var(--asm-font-weight-500);gap:var(--asm-space-2);justify-content:center;transition:all var(--asm-motion-duration-normal) var(--asm-motion-easing-standard);white-space:nowrap}.DropdownTrigger-module_trigger__2aFGL:disabled{cursor:not-allowed;opacity:.6}.DropdownTrigger-module_trigger__2aFGL:focus-visible{outline:2px solid var(--asm-color-focus-ring);outline-offset:2px}.DropdownTrigger-module_sm__J-u1E{font-size:var(--asm-font-size-sm);padding:calc(var(--asm-space-control-padding-y)*.75) calc(var(--asm-space-control-padding-x)*.75)}.DropdownTrigger-module_md__9rX9v{font-size:var(--asm-font-size-md);padding:var(--asm-space-control-padding-y) var(--asm-space-control-padding-x)}.DropdownTrigger-module_lg__Q-JAS{font-size:var(--asm-font-size-lg);padding:calc(var(--asm-space-control-padding-y)*1.25) calc(var(--asm-space-control-padding-x)*1.25)}.DropdownTrigger-module_primary__UQ1Xa{background-color:var(--asm-color-button-primary-bg);border:1px solid transparent;color:var(--asm-color-button-primary-text)}.DropdownTrigger-module_primary__UQ1Xa:hover:not(:disabled){background-color:var(--asm-color-button-primary-bg-hover)}.DropdownTrigger-module_primary__UQ1Xa:active:not(:disabled){background-color:var(--asm-color-button-primary-bg-active)}.DropdownTrigger-module_secondary__1NNLR{background-color:var(--asm-color-button-secondary-bg);border:1px solid var(--asm-color-border);color:var(--asm-color-button-secondary-text)}.DropdownTrigger-module_secondary__1NNLR:hover:not(:disabled){background-color:var(--asm-color-surface-muted);border-color:var(--asm-color-text)}.DropdownTrigger-module_secondary__1NNLR:active:not(:disabled){background-color:var(--asm-color-surface-muted)}.DropdownTrigger-module_success__bHgUD{background-color:var(--asm-color-success-400);border:1px solid transparent;color:#fff}.DropdownTrigger-module_success__bHgUD:hover:not(:disabled){background-color:var(--asm-color-success-500)}.DropdownTrigger-module_success__bHgUD:active:not(:disabled){background-color:var(--asm-color-success-600)}.DropdownTrigger-module_warning__ifDRF{background-color:var(--asm-color-warning-400);border:1px solid transparent;color:#fff}.DropdownTrigger-module_warning__ifDRF:hover:not(:disabled){background-color:var(--asm-color-warning-500)}.DropdownTrigger-module_warning__ifDRF:active:not(:disabled){background-color:var(--asm-color-warning-600)}.DropdownTrigger-module_danger__v-d7N{background-color:var(--asm-color-button-destructive-bg);border:1px solid transparent;color:var(--asm-color-button-destructive-text)}.DropdownTrigger-module_danger__v-d7N:hover:not(:disabled){background-color:var(--asm-color-danger-500)}.DropdownTrigger-module_danger__v-d7N:active:not(:disabled){background-color:var(--asm-color-danger-600)}.DropdownTrigger-module_info__3czXi{background-color:var(--asm-color-info-400);border:1px solid transparent;color:#fff}.DropdownTrigger-module_info__3czXi:hover:not(:disabled){background-color:var(--asm-color-info-500)}.DropdownTrigger-module_info__3czXi:active:not(:disabled){background-color:var(--asm-color-info-600)}.DropdownTrigger-module_ghost__dbCKD{background-color:transparent;border:1px solid transparent;color:var(--asm-color-text)}.DropdownTrigger-module_ghost__dbCKD:active:not(:disabled),.DropdownTrigger-module_ghost__dbCKD:hover:not(:disabled){background-color:var(--asm-color-button-ghost-bg-hover)}.DropdownTrigger-module_outline__VnDA7{background-color:transparent;border:1px solid var(--asm-color-border);color:var(--asm-color-text)}.DropdownTrigger-module_outline__VnDA7:hover:not(:disabled){background-color:var(--asm-color-surface-muted);border-color:var(--asm-color-text)}.DropdownTrigger-module_outline__VnDA7:active:not(:disabled){background-color:var(--asm-color-surface-muted)}.DropdownTrigger-module_link__BWU0o{background-color:transparent;border:none;color:var(--asm-color-primary-500);padding:0;text-decoration:none}.DropdownTrigger-module_link__BWU0o:hover:not(:disabled){color:var(--asm-color-primary-600);text-decoration:underline}.DropdownTrigger-module_link__BWU0o:active:not(:disabled){color:var(--asm-color-primary-700)}.DropdownTrigger-module_brand__SAI0y{background-color:var(--asm-color-brand-primary-500);border:1px solid transparent;color:#fff}.DropdownTrigger-module_brand__SAI0y:hover:not(:disabled){background-color:var(--asm-color-brand-primary-600)}.DropdownTrigger-module_brand__SAI0y:active:not(:disabled){background-color:var(--asm-color-brand-primary-700)}.DropdownTrigger-module_trigger__2aFGL:disabled{background-color:var(--asm-color-button-disabled-bg);border-color:transparent;color:var(--asm-color-button-disabled-text)}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import './styles/dropdown.css';
|
|
2
|
+
export { Dropdown } from './components/Dropdown';
|
|
3
|
+
export { DropdownItem } from './components/DropdownItem';
|
|
4
|
+
export { DropdownMenu } from './components/DropdownMenu';
|
|
5
|
+
export { DropdownTrigger } from './components/DropdownTrigger';
|
|
6
|
+
export { useDropdown } from './hooks/useDropdown';
|
|
7
|
+
export { useClickOutside } from './hooks/useClickOutside';
|
|
8
|
+
export { useKeyboardNavigation } from './hooks/useKeyboardNavigation';
|
|
9
|
+
export type { DropdownProps, DropdownItemProps, DropdownMenuProps, DropdownTriggerProps, DropdownPosition, DropdownPlacement, DropdownSize, DropdownVariant, DropdownItemData } from './types';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.dropdown_asm-dropdown__h1OJq{display:inline-block;position:relative}.dropdown_asm-dropdown-trigger__NJPo2{align-items:center;background:none;border:none;cursor:pointer;display:inline-flex;justify-content:center;margin:0;padding:0}.dropdown_asm-dropdown-trigger__NJPo2:disabled{cursor:not-allowed;opacity:.6}.dropdown_asm-dropdown-trigger__NJPo2:focus-visible{border-radius:var(--asm-radius-sm);outline:2px solid var(--asm-color-primary-500);outline-offset:2px}.dropdown_asm-dropdown-menu__YMlWB{animation:dropdown_asm-dropdown-enter__rh5Tw .15s ease-out;background-color:var(--asm-color-surface);border:1px solid var(--asm-color-border);border-radius:var(--asm-radius-lg);box-shadow:var(--asm-effect-shadow-lg);max-height:400px;max-width:320px;min-width:160px;overflow-y:auto;padding:var(--asm-space-1);transform-origin:top;z-index:var(--asm-z-dropdown)}@keyframes dropdown_asm-dropdown-enter__rh5Tw{0%{opacity:0;transform:scale(.95) translateY(-8px)}to{opacity:1;transform:scale(1) translateY(0)}}.dropdown_asm-dropdown-menu--sm__jecEV{min-width:120px;padding:var(--asm-space-0-5)}.dropdown_asm-dropdown-menu--md__X4BwH{min-width:160px;padding:var(--asm-space-1)}.dropdown_asm-dropdown-menu--lg__BQ3dL{min-width:200px;padding:var(--asm-space-1-5)}.dropdown_asm-dropdown-item__8UHDs{align-items:center;background:transparent;border:none;border-radius:var(--asm-radius-md);color:var(--asm-color-text);cursor:pointer;display:flex;font-size:var(--asm-font-size-sm);font-weight:var(--asm-font-weight-400);gap:var(--asm-space-2);min-height:36px;padding:var(--asm-space-2) var(--asm-space-3);text-align:left;transition:var(--asm-transition-fade);width:100%}.dropdown_asm-dropdown-item__8UHDs:focus,.dropdown_asm-dropdown-item__8UHDs:hover:not(:disabled){background-color:var(--asm-color-button-ghost-bg-hover);color:var(--asm-color-text)}.dropdown_asm-dropdown-item__8UHDs:focus{outline:none}.dropdown_asm-dropdown-item__8UHDs:active:not(:disabled){background-color:var(--asm-color-button-ghost-bg-hover)}.dropdown_asm-dropdown-item--disabled__FiaRm{color:var(--asm-color-text-muted);cursor:not-allowed;opacity:.6}.dropdown_asm-dropdown-item--danger__8yZZC{color:var(--asm-color-danger-600)}.dropdown_asm-dropdown-item--danger__8yZZC:focus,.dropdown_asm-dropdown-item--danger__8yZZC:hover:not(:disabled){background-color:var(--asm-color-danger-50);color:var(--asm-color-danger-700)}.dropdown_asm-dropdown-item__icon__r1aA0{align-items:center;display:flex;flex-shrink:0;height:16px;justify-content:center;width:16px}.dropdown_asm-dropdown-item__label__UVmKu{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dropdown_asm-dropdown-divider__JN-Gh{background-color:var(--asm-color-border);height:1px;margin:var(--asm-space-1) 0}[data-theme=dark] .dropdown_asm-dropdown-menu__YMlWB{background-color:var(--asm-color-surface);border-color:var(--asm-color-border);box-shadow:var(--asm-effect-shadow-lg)}[data-theme=dark] .dropdown_asm-dropdown-item__8UHDs{color:var(--asm-color-text)}[data-theme=dark] .dropdown_asm-dropdown-item__8UHDs:hover:not(:disabled){background-color:var(--asm-color-button-ghost-bg-hover)}[data-theme=dark] .dropdown_asm-dropdown-item--danger__8yZZC{color:var(--asm-color-danger-400)}[data-theme=dark] .dropdown_asm-dropdown-item--danger__8yZZC:hover:not(:disabled){background-color:var(--asm-color-danger-900);color:var(--asm-color-danger-300)}@media (max-width:640px){.dropdown_asm-dropdown-menu__YMlWB{max-height:60vh;max-width:calc(100vw - 32px);min-width:200px}.dropdown_asm-dropdown-item__8UHDs{font-size:var(--asm-font-size-md);min-height:44px;padding:var(--asm-space-3) var(--asm-space-4)}.dropdown_asm-dropdown-item__icon__r1aA0{height:20px;width:20px}}@media (hover:none) and (pointer:coarse){.dropdown_asm-dropdown-item__8UHDs{min-height:44px;padding:var(--asm-space-3) var(--asm-space-4)}}@media (prefers-reduced-motion:reduce){.dropdown_asm-dropdown-menu__YMlWB{animation:none}.dropdown_asm-dropdown-item__8UHDs{transition:none}}@media (prefers-contrast:high){.dropdown_asm-dropdown-menu__YMlWB{border-width:2px}.dropdown_asm-dropdown-item__8UHDs:focus{outline:2px solid currentColor;outline-offset:-2px}}@import "@asafarim/design-tokens/css/index.css";.DropdownTrigger-module_trigger__2aFGL{align-items:center;border:none;border-radius:var(--asm-radius-md);cursor:pointer;display:inline-flex;font-family:var(--asm-font-family-primary);font-size:var(--asm-font-size-md);font-weight:var(--asm-font-weight-500);gap:var(--asm-space-2);justify-content:center;transition:all var(--asm-motion-duration-normal) var(--asm-motion-easing-standard);white-space:nowrap}.DropdownTrigger-module_trigger__2aFGL:disabled{cursor:not-allowed;opacity:.6}.DropdownTrigger-module_trigger__2aFGL:focus-visible{outline:2px solid var(--asm-color-focus-ring);outline-offset:2px}.DropdownTrigger-module_sm__J-u1E{font-size:var(--asm-font-size-sm);padding:calc(var(--asm-space-control-padding-y)*.75) calc(var(--asm-space-control-padding-x)*.75)}.DropdownTrigger-module_md__9rX9v{font-size:var(--asm-font-size-md);padding:var(--asm-space-control-padding-y) var(--asm-space-control-padding-x)}.DropdownTrigger-module_lg__Q-JAS{font-size:var(--asm-font-size-lg);padding:calc(var(--asm-space-control-padding-y)*1.25) calc(var(--asm-space-control-padding-x)*1.25)}.DropdownTrigger-module_primary__UQ1Xa{background-color:var(--asm-color-button-primary-bg);border:1px solid transparent;color:var(--asm-color-button-primary-text)}.DropdownTrigger-module_primary__UQ1Xa:hover:not(:disabled){background-color:var(--asm-color-button-primary-bg-hover)}.DropdownTrigger-module_primary__UQ1Xa:active:not(:disabled){background-color:var(--asm-color-button-primary-bg-active)}.DropdownTrigger-module_secondary__1NNLR{background-color:var(--asm-color-button-secondary-bg);border:1px solid var(--asm-color-border);color:var(--asm-color-button-secondary-text)}.DropdownTrigger-module_secondary__1NNLR:hover:not(:disabled){background-color:var(--asm-color-surface-muted);border-color:var(--asm-color-text)}.DropdownTrigger-module_secondary__1NNLR:active:not(:disabled){background-color:var(--asm-color-surface-muted)}.DropdownTrigger-module_success__bHgUD{background-color:var(--asm-color-success-400);border:1px solid transparent;color:#fff}.DropdownTrigger-module_success__bHgUD:hover:not(:disabled){background-color:var(--asm-color-success-500)}.DropdownTrigger-module_success__bHgUD:active:not(:disabled){background-color:var(--asm-color-success-600)}.DropdownTrigger-module_warning__ifDRF{background-color:var(--asm-color-warning-400);border:1px solid transparent;color:#fff}.DropdownTrigger-module_warning__ifDRF:hover:not(:disabled){background-color:var(--asm-color-warning-500)}.DropdownTrigger-module_warning__ifDRF:active:not(:disabled){background-color:var(--asm-color-warning-600)}.DropdownTrigger-module_danger__v-d7N{background-color:var(--asm-color-button-destructive-bg);border:1px solid transparent;color:var(--asm-color-button-destructive-text)}.DropdownTrigger-module_danger__v-d7N:hover:not(:disabled){background-color:var(--asm-color-danger-500)}.DropdownTrigger-module_danger__v-d7N:active:not(:disabled){background-color:var(--asm-color-danger-600)}.DropdownTrigger-module_info__3czXi{background-color:var(--asm-color-info-400);border:1px solid transparent;color:#fff}.DropdownTrigger-module_info__3czXi:hover:not(:disabled){background-color:var(--asm-color-info-500)}.DropdownTrigger-module_info__3czXi:active:not(:disabled){background-color:var(--asm-color-info-600)}.DropdownTrigger-module_ghost__dbCKD{background-color:transparent;border:1px solid transparent;color:var(--asm-color-text)}.DropdownTrigger-module_ghost__dbCKD:active:not(:disabled),.DropdownTrigger-module_ghost__dbCKD:hover:not(:disabled){background-color:var(--asm-color-button-ghost-bg-hover)}.DropdownTrigger-module_outline__VnDA7{background-color:transparent;border:1px solid var(--asm-color-border);color:var(--asm-color-text)}.DropdownTrigger-module_outline__VnDA7:hover:not(:disabled){background-color:var(--asm-color-surface-muted);border-color:var(--asm-color-text)}.DropdownTrigger-module_outline__VnDA7:active:not(:disabled){background-color:var(--asm-color-surface-muted)}.DropdownTrigger-module_link__BWU0o{background-color:transparent;border:none;color:var(--asm-color-primary-500);padding:0;text-decoration:none}.DropdownTrigger-module_link__BWU0o:hover:not(:disabled){color:var(--asm-color-primary-600);text-decoration:underline}.DropdownTrigger-module_link__BWU0o:active:not(:disabled){color:var(--asm-color-primary-700)}.DropdownTrigger-module_brand__SAI0y{background-color:var(--asm-color-brand-primary-500);border:1px solid transparent;color:#fff}.DropdownTrigger-module_brand__SAI0y:hover:not(:disabled){background-color:var(--asm-color-brand-primary-600)}.DropdownTrigger-module_brand__SAI0y:active:not(:disabled){background-color:var(--asm-color-brand-primary-700)}.DropdownTrigger-module_trigger__2aFGL:disabled{background-color:var(--asm-color-button-disabled-bg);border-color:transparent;color:var(--asm-color-button-disabled-text)}
|