@mieweb/ui 0.1.0 → 0.1.1

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 (72) hide show
  1. package/LICENSE +39 -15
  2. package/README.md +9 -1
  3. package/dist/{chunk-CLNOI5J7.js → chunk-4SMSH4OY.js} +4 -4
  4. package/dist/chunk-4SMSH4OY.js.map +1 -0
  5. package/dist/chunk-5T3AWNHG.cjs +471 -0
  6. package/dist/chunk-5T3AWNHG.cjs.map +1 -0
  7. package/dist/chunk-74K3RRU7.cjs +4 -0
  8. package/dist/{chunk-ZO46CFVN.cjs.map → chunk-74K3RRU7.cjs.map} +1 -1
  9. package/dist/{chunk-VWXGUNBR.cjs → chunk-AKTUXJPI.cjs} +107 -18
  10. package/dist/chunk-AKTUXJPI.cjs.map +1 -0
  11. package/dist/{chunk-NH2JVQ6V.cjs → chunk-I7L6CQXR.cjs} +21 -9
  12. package/dist/chunk-I7L6CQXR.cjs.map +1 -0
  13. package/dist/{chunk-KJOFWJHV.js → chunk-MFB4FS7D.js} +120 -81
  14. package/dist/chunk-MFB4FS7D.js.map +1 -0
  15. package/dist/{chunk-LEE3NMNP.cjs → chunk-NL3CZNBH.cjs} +120 -81
  16. package/dist/chunk-NL3CZNBH.cjs.map +1 -0
  17. package/dist/{chunk-BR2XGATJ.cjs → chunk-NNEFAUHV.cjs} +4 -4
  18. package/dist/chunk-NNEFAUHV.cjs.map +1 -0
  19. package/dist/chunk-SCV7C55E.cjs +11 -0
  20. package/dist/chunk-SCV7C55E.cjs.map +1 -0
  21. package/dist/{chunk-D5IBXXF2.js → chunk-SD44QJIP.js} +20 -8
  22. package/dist/chunk-SD44QJIP.js.map +1 -0
  23. package/dist/{chunk-QBWVTJKF.js → chunk-UBRDKNLQ.js} +107 -18
  24. package/dist/chunk-UBRDKNLQ.js.map +1 -0
  25. package/dist/chunk-V2DF2GUE.js +3 -0
  26. package/dist/{chunk-ZQ4XMJH7.js.map → chunk-V2DF2GUE.js.map} +1 -1
  27. package/dist/chunk-VSQF22GL.js +9 -0
  28. package/dist/chunk-VSQF22GL.js.map +1 -0
  29. package/dist/chunk-XVZ4SLQB.js +447 -0
  30. package/dist/chunk-XVZ4SLQB.js.map +1 -0
  31. package/dist/components/AudioPlayer/index.cjs +6 -6
  32. package/dist/components/AudioPlayer/index.d.cts +5 -1
  33. package/dist/components/AudioPlayer/index.d.ts +5 -1
  34. package/dist/components/AudioPlayer/index.js +1 -1
  35. package/dist/components/Modal/index.cjs +11 -10
  36. package/dist/components/Modal/index.js +3 -2
  37. package/dist/components/RecordButton/index.cjs +4 -8
  38. package/dist/components/RecordButton/index.d.cts +57 -44
  39. package/dist/components/RecordButton/index.d.ts +57 -44
  40. package/dist/components/RecordButton/index.js +1 -1
  41. package/dist/components/Select/index.cjs +3 -4
  42. package/dist/components/Select/index.js +1 -2
  43. package/dist/components/Spinner/index.d.cts +1 -1
  44. package/dist/components/Spinner/index.d.ts +1 -1
  45. package/dist/hooks/index.cjs +3 -2
  46. package/dist/hooks/index.js +2 -1
  47. package/dist/index.cjs +880 -667
  48. package/dist/index.cjs.map +1 -1
  49. package/dist/index.d.cts +16 -11
  50. package/dist/index.d.ts +16 -11
  51. package/dist/index.js +801 -588
  52. package/dist/index.js.map +1 -1
  53. package/dist/styles.css +1 -1
  54. package/dist/utils/index.cjs +6 -1
  55. package/dist/utils/index.d.cts +14 -1
  56. package/dist/utils/index.d.ts +14 -1
  57. package/dist/utils/index.js +2 -1
  58. package/package.json +7 -7
  59. package/dist/chunk-BR2XGATJ.cjs.map +0 -1
  60. package/dist/chunk-CLNOI5J7.js.map +0 -1
  61. package/dist/chunk-D5IBXXF2.js.map +0 -1
  62. package/dist/chunk-FQ5G7J24.js +0 -297
  63. package/dist/chunk-FQ5G7J24.js.map +0 -1
  64. package/dist/chunk-HLW3XD5R.cjs +0 -322
  65. package/dist/chunk-HLW3XD5R.cjs.map +0 -1
  66. package/dist/chunk-KJOFWJHV.js.map +0 -1
  67. package/dist/chunk-LEE3NMNP.cjs.map +0 -1
  68. package/dist/chunk-NH2JVQ6V.cjs.map +0 -1
  69. package/dist/chunk-QBWVTJKF.js.map +0 -1
  70. package/dist/chunk-VWXGUNBR.cjs.map +0 -1
  71. package/dist/chunk-ZO46CFVN.cjs +0 -4
  72. package/dist/chunk-ZQ4XMJH7.js +0 -3
@@ -1,7 +1,7 @@
1
- import { useClickOutside } from './chunk-OT36EMM5.js';
2
1
  import { useEscapeKey } from './chunk-T4ME7QCT.js';
3
2
  import { cn } from './chunk-F3SOEIN2.js';
4
3
  import * as React from 'react';
4
+ import { createPortal } from 'react-dom';
5
5
  import { cva } from 'class-variance-authority';
6
6
  import { jsxs, jsx } from 'react/jsx-runtime';
7
7
 
@@ -61,6 +61,7 @@ function Select({
61
61
  const triggerRef = React.useRef(null);
62
62
  const searchInputRef = React.useRef(null);
63
63
  const listRef = React.useRef(null);
64
+ const dropdownRef = React.useRef(null);
64
65
  const generatedId = React.useId();
65
66
  const selectId = id || generatedId;
66
67
  const listboxId = `${selectId}-listbox`;
@@ -111,13 +112,47 @@ function Select({
111
112
  return result;
112
113
  }, [filteredOptions]);
113
114
  const selectedOption = flatOptions.find((opt) => opt.value === value);
114
- useClickOutside(containerRef, () => setIsOpen(false));
115
+ React.useEffect(() => {
116
+ if (!isOpen) return;
117
+ const handleClickOutside = (e) => {
118
+ const target = e.target;
119
+ if (containerRef.current && !containerRef.current.contains(target) && dropdownRef.current && !dropdownRef.current.contains(target)) {
120
+ setIsOpen(false);
121
+ }
122
+ };
123
+ document.addEventListener("mousedown", handleClickOutside);
124
+ return () => document.removeEventListener("mousedown", handleClickOutside);
125
+ }, [isOpen]);
115
126
  useEscapeKey(() => {
116
127
  if (isOpen) {
117
128
  setIsOpen(false);
118
129
  triggerRef.current?.focus();
119
130
  }
120
131
  }, isOpen);
132
+ const [dropdownStyle, setDropdownStyle] = React.useState(
133
+ {}
134
+ );
135
+ const updateDropdownPosition = React.useCallback(() => {
136
+ if (!triggerRef.current) return;
137
+ const rect = triggerRef.current.getBoundingClientRect();
138
+ setDropdownStyle({
139
+ position: "fixed",
140
+ top: rect.bottom + 4,
141
+ left: rect.left,
142
+ width: rect.width,
143
+ zIndex: 9999
144
+ });
145
+ }, []);
146
+ React.useEffect(() => {
147
+ if (!isOpen) return;
148
+ updateDropdownPosition();
149
+ window.addEventListener("scroll", updateDropdownPosition, true);
150
+ window.addEventListener("resize", updateDropdownPosition);
151
+ return () => {
152
+ window.removeEventListener("scroll", updateDropdownPosition, true);
153
+ window.removeEventListener("resize", updateDropdownPosition);
154
+ };
155
+ }, [isOpen, updateDropdownPosition]);
121
156
  const handleValueChange = React.useCallback(
122
157
  (newValue) => {
123
158
  if (!isControlled) {
@@ -237,83 +272,87 @@ function Select({
237
272
  ]
238
273
  }
239
274
  ),
240
- isOpen && /* @__PURE__ */ jsxs(
241
- "div",
242
- {
243
- className: cn(
244
- "absolute z-50 mt-1 w-full",
245
- "border-border bg-card rounded-lg border shadow-lg",
246
- "animate-in fade-in zoom-in-95 duration-100"
247
- ),
248
- children: [
249
- searchable && /* @__PURE__ */ jsx("div", { className: "border-border border-b p-2", children: /* @__PURE__ */ jsx(
250
- "input",
251
- {
252
- ref: searchInputRef,
253
- type: "text",
254
- value: searchQuery,
255
- onChange: (e) => setSearchQuery(e.target.value),
256
- onKeyDown: handleKeyDown,
257
- placeholder: searchPlaceholder,
258
- className: cn(
259
- "border-input bg-background w-full rounded-md border px-3 py-2 text-sm",
260
- "placeholder:text-muted-foreground",
261
- "focus:ring-ring focus:ring-2 focus:outline-none"
262
- ),
263
- "aria-label": "Search options"
264
- }
265
- ) }),
266
- /* @__PURE__ */ jsx(
267
- "ul",
268
- {
269
- ref: listRef,
270
- id: listboxId,
271
- role: "listbox",
272
- "aria-label": label || "Options",
273
- className: "max-h-60 overflow-auto p-1",
274
- children: filteredFlatOptions.length === 0 ? /* @__PURE__ */ jsx("li", { className: "text-muted-foreground px-3 py-2 text-center text-sm", children: noResultsText }) : filteredOptions.map((item) => {
275
- if ("options" in item) {
276
- return /* @__PURE__ */ jsxs("li", { role: "presentation", children: [
277
- /* @__PURE__ */ jsx("div", { className: "text-muted-foreground px-3 py-1.5 text-xs font-semibold tracking-wider uppercase", children: item.label }),
278
- /* @__PURE__ */ jsx("ul", { role: "group", "aria-label": item.label, children: item.options.map((option) => /* @__PURE__ */ jsx(
279
- SelectOptionItem,
280
- {
281
- option,
282
- isSelected: option.value === value,
283
- isHighlighted: filteredFlatOptions[highlightedIndex]?.value === option.value,
284
- onSelect: () => handleValueChange(option.value),
285
- onMouseEnter: () => {
286
- const idx = filteredFlatOptions.findIndex(
287
- (o) => o.value === option.value
288
- );
289
- setHighlightedIndex(idx);
290
- }
291
- },
292
- option.value
293
- )) })
294
- ] }, `group-${item.label}`);
295
- }
296
- return /* @__PURE__ */ jsx(
297
- SelectOptionItem,
298
- {
299
- option: item,
300
- isSelected: item.value === value,
301
- isHighlighted: filteredFlatOptions[highlightedIndex]?.value === item.value,
302
- onSelect: () => handleValueChange(item.value),
303
- onMouseEnter: () => {
304
- const idx = filteredFlatOptions.findIndex(
305
- (o) => o.value === item.value
306
- );
307
- setHighlightedIndex(idx);
308
- }
309
- },
310
- item.value
311
- );
312
- })
313
- }
314
- )
315
- ]
316
- }
275
+ isOpen && createPortal(
276
+ /* @__PURE__ */ jsxs(
277
+ "div",
278
+ {
279
+ ref: dropdownRef,
280
+ style: dropdownStyle,
281
+ className: cn(
282
+ "border-border bg-card rounded-lg border shadow-lg",
283
+ "animate-in fade-in zoom-in-95 duration-100"
284
+ ),
285
+ children: [
286
+ searchable && /* @__PURE__ */ jsx("div", { className: "border-border border-b p-2", children: /* @__PURE__ */ jsx(
287
+ "input",
288
+ {
289
+ ref: searchInputRef,
290
+ type: "text",
291
+ value: searchQuery,
292
+ onChange: (e) => setSearchQuery(e.target.value),
293
+ onKeyDown: handleKeyDown,
294
+ placeholder: searchPlaceholder,
295
+ className: cn(
296
+ "border-input bg-background w-full rounded-md border px-3 py-2 text-sm",
297
+ "placeholder:text-muted-foreground",
298
+ "focus:ring-ring focus:ring-2 focus:outline-none"
299
+ ),
300
+ "aria-label": "Search options"
301
+ }
302
+ ) }),
303
+ /* @__PURE__ */ jsx(
304
+ "ul",
305
+ {
306
+ ref: listRef,
307
+ id: listboxId,
308
+ role: "listbox",
309
+ "aria-label": label || "Options",
310
+ className: "max-h-60 overflow-auto p-1",
311
+ children: filteredFlatOptions.length === 0 ? /* @__PURE__ */ jsx("li", { className: "text-muted-foreground px-3 py-2 text-center text-sm", children: noResultsText }) : filteredOptions.map((item) => {
312
+ if ("options" in item) {
313
+ return /* @__PURE__ */ jsxs("li", { role: "presentation", children: [
314
+ /* @__PURE__ */ jsx("div", { className: "text-muted-foreground px-3 py-1.5 text-xs font-semibold tracking-wider uppercase", children: item.label }),
315
+ /* @__PURE__ */ jsx("ul", { role: "group", "aria-label": item.label, children: item.options.map((option) => /* @__PURE__ */ jsx(
316
+ SelectOptionItem,
317
+ {
318
+ option,
319
+ isSelected: option.value === value,
320
+ isHighlighted: filteredFlatOptions[highlightedIndex]?.value === option.value,
321
+ onSelect: () => handleValueChange(option.value),
322
+ onMouseEnter: () => {
323
+ const idx = filteredFlatOptions.findIndex(
324
+ (o) => o.value === option.value
325
+ );
326
+ setHighlightedIndex(idx);
327
+ }
328
+ },
329
+ option.value
330
+ )) })
331
+ ] }, `group-${item.label}`);
332
+ }
333
+ return /* @__PURE__ */ jsx(
334
+ SelectOptionItem,
335
+ {
336
+ option: item,
337
+ isSelected: item.value === value,
338
+ isHighlighted: filteredFlatOptions[highlightedIndex]?.value === item.value,
339
+ onSelect: () => handleValueChange(item.value),
340
+ onMouseEnter: () => {
341
+ const idx = filteredFlatOptions.findIndex(
342
+ (o) => o.value === item.value
343
+ );
344
+ setHighlightedIndex(idx);
345
+ }
346
+ },
347
+ item.value
348
+ );
349
+ })
350
+ }
351
+ )
352
+ ]
353
+ }
354
+ ),
355
+ document.body
317
356
  )
318
357
  ] }),
319
358
  error && /* @__PURE__ */ jsx("p", { id: errorId, className: "text-destructive text-sm", role: "alert", children: error }),
@@ -402,5 +441,5 @@ function CheckIcon({ className }) {
402
441
  }
403
442
 
404
443
  export { Select, selectTriggerVariants };
405
- //# sourceMappingURL=chunk-KJOFWJHV.js.map
406
- //# sourceMappingURL=chunk-KJOFWJHV.js.map
444
+ //# sourceMappingURL=chunk-MFB4FS7D.js.map
445
+ //# sourceMappingURL=chunk-MFB4FS7D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Select/Select.tsx"],"names":[],"mappings":"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","file":"chunk-MFB4FS7D.js","sourcesContent":["import * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { useEscapeKey } from '../../hooks/useEscapeKey';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SelectOption {\n /** Unique value for the option */\n value: string;\n /** Display label for the option */\n label: string;\n /** Whether the option is disabled */\n disabled?: boolean;\n /** Optional group this option belongs to */\n group?: string;\n}\n\nexport interface SelectGroup {\n /** Group label */\n label: string;\n /** Options in this group */\n options: SelectOption[];\n}\n\n// ============================================================================\n// Variants\n// ============================================================================\n\nconst selectTriggerVariants = cva(\n [\n 'flex w-full items-center justify-between gap-2',\n 'border border-input rounded-lg',\n 'bg-background text-foreground',\n 'transition-colors duration-200',\n 'focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n ],\n {\n variants: {\n size: {\n sm: 'h-8 px-3 text-sm',\n md: 'h-10 px-3 text-base',\n lg: 'h-12 px-4 text-lg',\n },\n hasError: {\n true: 'border-destructive focus:ring-destructive',\n false: '',\n },\n },\n defaultVariants: {\n size: 'md',\n hasError: false,\n },\n }\n);\n\n// ============================================================================\n// Select Component\n// ============================================================================\n\nexport interface SelectProps extends VariantProps<\n typeof selectTriggerVariants\n> {\n /** Array of options or groups */\n options: (SelectOption | SelectGroup)[];\n /** Controlled value */\n value?: string;\n /** Default value (uncontrolled) */\n defaultValue?: string;\n /** Callback when value changes */\n onValueChange?: (value: string) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the select is disabled */\n disabled?: boolean;\n /** Label for the select */\n label?: string;\n /** Hide the label visually */\n hideLabel?: boolean;\n /** Error message */\n error?: string;\n /** Helper text */\n helperText?: string;\n /** Enable search/filter */\n searchable?: boolean;\n /** Search placeholder */\n searchPlaceholder?: string;\n /** No results text */\n noResultsText?: string;\n /** Additional class name */\n className?: string;\n /** ID for the select */\n id?: string;\n}\n\n/**\n * An accessible select/dropdown component with search support.\n *\n * @example\n * ```tsx\n * <Select\n * label=\"Country\"\n * placeholder=\"Select a country\"\n * options={[\n * { value: 'us', label: 'United States' },\n * { value: 'ca', label: 'Canada' },\n * { value: 'uk', label: 'United Kingdom' },\n * ]}\n * onValueChange={(value) => console.log(value)}\n * />\n * ```\n */\nfunction Select({\n options,\n value: controlledValue,\n defaultValue,\n onValueChange,\n placeholder = 'Select an option',\n disabled = false,\n label,\n hideLabel = false,\n error,\n helperText,\n size,\n hasError,\n searchable = false,\n searchPlaceholder = 'Search...',\n noResultsText = 'No results found',\n className,\n id,\n}: SelectProps) {\n const [isOpen, setIsOpen] = React.useState(false);\n const [uncontrolledValue, setUncontrolledValue] = React.useState(\n defaultValue || ''\n );\n const [searchQuery, setSearchQuery] = React.useState('');\n const [highlightedIndex, setHighlightedIndex] = React.useState(-1);\n\n const containerRef = React.useRef<HTMLDivElement>(null);\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const searchInputRef = React.useRef<HTMLInputElement>(null);\n const listRef = React.useRef<HTMLUListElement>(null);\n const dropdownRef = React.useRef<HTMLDivElement>(null);\n\n const generatedId = React.useId();\n const selectId = id || generatedId;\n const listboxId = `${selectId}-listbox`;\n const errorId = `${selectId}-error`;\n const helperId = `${selectId}-helper`;\n\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : uncontrolledValue;\n\n // Flatten options for easy access\n const flatOptions = React.useMemo(() => {\n const result: SelectOption[] = [];\n for (const item of options) {\n if ('options' in item) {\n result.push(...item.options);\n } else {\n result.push(item);\n }\n }\n return result;\n }, [options]);\n\n // Filter options based on search query\n const filteredOptions = React.useMemo(() => {\n if (!searchQuery) return options;\n\n const query = searchQuery.toLowerCase();\n const result: (SelectOption | SelectGroup)[] = [];\n\n for (const item of options) {\n if ('options' in item) {\n const filteredGroupOptions = item.options.filter((opt) =>\n opt.label.toLowerCase().includes(query)\n );\n if (filteredGroupOptions.length > 0) {\n result.push({ ...item, options: filteredGroupOptions });\n }\n } else {\n if (item.label.toLowerCase().includes(query)) {\n result.push(item);\n }\n }\n }\n\n return result;\n }, [options, searchQuery]);\n\n // Get filtered flat options for keyboard navigation\n const filteredFlatOptions = React.useMemo(() => {\n const result: SelectOption[] = [];\n for (const item of filteredOptions) {\n if ('options' in item) {\n result.push(...item.options.filter((opt) => !opt.disabled));\n } else if (!item.disabled) {\n result.push(item);\n }\n }\n return result;\n }, [filteredOptions]);\n\n // Get selected option\n const selectedOption = flatOptions.find((opt) => opt.value === value);\n\n // Close dropdown on click outside (handles both container and portaled dropdown)\n React.useEffect(() => {\n if (!isOpen) return;\n const handleClickOutside = (e: MouseEvent) => {\n const target = e.target as Node;\n if (\n containerRef.current &&\n !containerRef.current.contains(target) &&\n dropdownRef.current &&\n !dropdownRef.current.contains(target)\n ) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [isOpen]);\n\n useEscapeKey(() => {\n if (isOpen) {\n setIsOpen(false);\n triggerRef.current?.focus();\n }\n }, isOpen);\n\n // Track trigger position for portal dropdown\n const [dropdownStyle, setDropdownStyle] = React.useState<React.CSSProperties>(\n {}\n );\n\n const updateDropdownPosition = React.useCallback(() => {\n if (!triggerRef.current) return;\n const rect = triggerRef.current.getBoundingClientRect();\n setDropdownStyle({\n position: 'fixed',\n top: rect.bottom + 4,\n left: rect.left,\n width: rect.width,\n zIndex: 9999,\n });\n }, []);\n\n React.useEffect(() => {\n if (!isOpen) return;\n updateDropdownPosition();\n\n window.addEventListener('scroll', updateDropdownPosition, true);\n window.addEventListener('resize', updateDropdownPosition);\n return () => {\n window.removeEventListener('scroll', updateDropdownPosition, true);\n window.removeEventListener('resize', updateDropdownPosition);\n };\n }, [isOpen, updateDropdownPosition]);\n\n // Handle value change\n const handleValueChange = React.useCallback(\n (newValue: string) => {\n if (!isControlled) {\n setUncontrolledValue(newValue);\n }\n onValueChange?.(newValue);\n setIsOpen(false);\n setSearchQuery('');\n triggerRef.current?.focus();\n },\n [isControlled, onValueChange]\n );\n\n // Handle keyboard navigation\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n if (!isOpen) {\n setIsOpen(true);\n } else {\n setHighlightedIndex((prev) =>\n prev < filteredFlatOptions.length - 1 ? prev + 1 : 0\n );\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n if (!isOpen) {\n setIsOpen(true);\n } else {\n setHighlightedIndex((prev) =>\n prev > 0 ? prev - 1 : filteredFlatOptions.length - 1\n );\n }\n break;\n case 'Enter':\n case ' ':\n e.preventDefault();\n if (isOpen && highlightedIndex >= 0) {\n handleValueChange(filteredFlatOptions[highlightedIndex].value);\n } else if (!isOpen) {\n setIsOpen(true);\n }\n break;\n case 'Home':\n e.preventDefault();\n setHighlightedIndex(0);\n break;\n case 'End':\n e.preventDefault();\n setHighlightedIndex(filteredFlatOptions.length - 1);\n break;\n }\n },\n [isOpen, highlightedIndex, filteredFlatOptions, handleValueChange]\n );\n\n // Focus search input when dropdown opens\n React.useEffect(() => {\n if (isOpen && searchable && searchInputRef.current) {\n searchInputRef.current.focus();\n }\n }, [isOpen, searchable]);\n\n // Reset highlighted index when search changes\n React.useEffect(() => {\n setHighlightedIndex(filteredFlatOptions.length > 0 ? 0 : -1);\n }, [searchQuery, filteredFlatOptions.length]);\n\n // Build aria-describedby\n const describedByIds = [error ? errorId : null, helperText ? helperId : null]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={cn('flex flex-col gap-1.5', className)}>\n {label && (\n <label\n htmlFor={selectId}\n className={cn(\n 'text-foreground text-sm font-medium',\n hideLabel && 'sr-only'\n )}\n >\n {label}\n </label>\n )}\n\n <div ref={containerRef} className=\"relative\">\n {/* Trigger Button */}\n <button\n ref={triggerRef}\n id={selectId}\n type=\"button\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded={isOpen}\n aria-controls={listboxId}\n aria-invalid={hasError || !!error}\n aria-describedby={describedByIds || undefined}\n disabled={disabled}\n onClick={() => setIsOpen(!isOpen)}\n onKeyDown={handleKeyDown}\n className={cn(\n selectTriggerVariants({ size, hasError: hasError || !!error })\n )}\n >\n <span\n className={cn(\n 'truncate',\n !selectedOption && 'text-muted-foreground'\n )}\n >\n {selectedOption?.label || placeholder}\n </span>\n <ChevronDownIcon\n className={cn(\n 'text-muted-foreground h-4 w-4 shrink-0 transition-transform',\n isOpen && 'rotate-180'\n )}\n />\n </button>\n\n {/* Dropdown (portaled to body to avoid overflow clipping) */}\n {isOpen &&\n createPortal(\n <div\n ref={dropdownRef}\n style={dropdownStyle}\n className={cn(\n 'border-border bg-card rounded-lg border shadow-lg',\n 'animate-in fade-in zoom-in-95 duration-100'\n )}\n >\n {/* Search Input */}\n {searchable && (\n <div className=\"border-border border-b p-2\">\n <input\n ref={searchInputRef}\n type=\"text\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={searchPlaceholder}\n className={cn(\n 'border-input bg-background w-full rounded-md border px-3 py-2 text-sm',\n 'placeholder:text-muted-foreground',\n 'focus:ring-ring focus:ring-2 focus:outline-none'\n )}\n aria-label=\"Search options\"\n />\n </div>\n )}\n\n {/* Options List */}\n <ul\n ref={listRef}\n id={listboxId}\n role=\"listbox\"\n aria-label={label || 'Options'}\n className=\"max-h-60 overflow-auto p-1\"\n >\n {filteredFlatOptions.length === 0 ? (\n <li className=\"text-muted-foreground px-3 py-2 text-center text-sm\">\n {noResultsText}\n </li>\n ) : (\n filteredOptions.map((item) => {\n if ('options' in item) {\n // Render group\n return (\n <li key={`group-${item.label}`} role=\"presentation\">\n <div className=\"text-muted-foreground px-3 py-1.5 text-xs font-semibold tracking-wider uppercase\">\n {item.label}\n </div>\n <ul role=\"group\" aria-label={item.label}>\n {item.options.map((option) => (\n <SelectOptionItem\n key={option.value}\n option={option}\n isSelected={option.value === value}\n isHighlighted={\n filteredFlatOptions[highlightedIndex]\n ?.value === option.value\n }\n onSelect={() => handleValueChange(option.value)}\n onMouseEnter={() => {\n const idx = filteredFlatOptions.findIndex(\n (o) => o.value === option.value\n );\n setHighlightedIndex(idx);\n }}\n />\n ))}\n </ul>\n </li>\n );\n }\n\n // Render single option\n return (\n <SelectOptionItem\n key={item.value}\n option={item}\n isSelected={item.value === value}\n isHighlighted={\n filteredFlatOptions[highlightedIndex]?.value ===\n item.value\n }\n onSelect={() => handleValueChange(item.value)}\n onMouseEnter={() => {\n const idx = filteredFlatOptions.findIndex(\n (o) => o.value === item.value\n );\n setHighlightedIndex(idx);\n }}\n />\n );\n })\n )}\n </ul>\n </div>,\n document.body\n )}\n </div>\n\n {/* Error Message */}\n {error && (\n <p id={errorId} className=\"text-destructive text-sm\" role=\"alert\">\n {error}\n </p>\n )}\n\n {/* Helper Text */}\n {helperText && !error && (\n <p id={helperId} className=\"text-muted-foreground text-sm\">\n {helperText}\n </p>\n )}\n </div>\n );\n}\n\nSelect.displayName = 'Select';\n\n// ============================================================================\n// Select Option Item (Internal)\n// ============================================================================\n\ninterface SelectOptionItemProps {\n option: SelectOption;\n isSelected: boolean;\n isHighlighted: boolean;\n onSelect: () => void;\n onMouseEnter: () => void;\n}\n\nfunction SelectOptionItem({\n option,\n isSelected,\n isHighlighted,\n onSelect,\n onMouseEnter,\n}: SelectOptionItemProps) {\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n if (!option.disabled) {\n onSelect();\n }\n }\n };\n\n return (\n <li\n role=\"option\"\n aria-selected={isSelected}\n aria-disabled={option.disabled}\n data-highlighted={isHighlighted}\n data-disabled={option.disabled}\n tabIndex={isHighlighted ? 0 : -1}\n onClick={option.disabled ? undefined : onSelect}\n onKeyDown={handleKeyDown}\n onMouseEnter={option.disabled ? undefined : onMouseEnter}\n className={cn(\n 'flex cursor-pointer items-center gap-2 rounded-md px-3 py-2 text-sm',\n 'transition-colors outline-none',\n isHighlighted && 'bg-muted',\n isSelected &&\n 'bg-primary-50 text-primary-900 dark:bg-primary-950 dark:text-primary-100',\n option.disabled && 'cursor-not-allowed opacity-50'\n )}\n >\n <span className=\"flex-1 truncate\">{option.label}</span>\n {isSelected && (\n <CheckIcon className=\"text-primary-500 h-4 w-4 shrink-0\" />\n )}\n </li>\n );\n}\n\n// ============================================================================\n// Icons\n// ============================================================================\n\nfunction ChevronDownIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n );\n}\n\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n );\n}\n\nexport { Select, selectTriggerVariants };\n"]}
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var chunkSWMRCGL4_cjs = require('./chunk-SWMRCGL4.cjs');
4
3
  var chunkFHY3K6PL_cjs = require('./chunk-FHY3K6PL.cjs');
5
4
  var chunkOR5DRJCW_cjs = require('./chunk-OR5DRJCW.cjs');
6
5
  var React = require('react');
6
+ var reactDom = require('react-dom');
7
7
  var classVarianceAuthority = require('class-variance-authority');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
9
 
@@ -83,6 +83,7 @@ function Select({
83
83
  const triggerRef = React__namespace.useRef(null);
84
84
  const searchInputRef = React__namespace.useRef(null);
85
85
  const listRef = React__namespace.useRef(null);
86
+ const dropdownRef = React__namespace.useRef(null);
86
87
  const generatedId = React__namespace.useId();
87
88
  const selectId = id || generatedId;
88
89
  const listboxId = `${selectId}-listbox`;
@@ -133,13 +134,47 @@ function Select({
133
134
  return result;
134
135
  }, [filteredOptions]);
135
136
  const selectedOption = flatOptions.find((opt) => opt.value === value);
136
- chunkSWMRCGL4_cjs.useClickOutside(containerRef, () => setIsOpen(false));
137
+ React__namespace.useEffect(() => {
138
+ if (!isOpen) return;
139
+ const handleClickOutside = (e) => {
140
+ const target = e.target;
141
+ if (containerRef.current && !containerRef.current.contains(target) && dropdownRef.current && !dropdownRef.current.contains(target)) {
142
+ setIsOpen(false);
143
+ }
144
+ };
145
+ document.addEventListener("mousedown", handleClickOutside);
146
+ return () => document.removeEventListener("mousedown", handleClickOutside);
147
+ }, [isOpen]);
137
148
  chunkFHY3K6PL_cjs.useEscapeKey(() => {
138
149
  if (isOpen) {
139
150
  setIsOpen(false);
140
151
  triggerRef.current?.focus();
141
152
  }
142
153
  }, isOpen);
154
+ const [dropdownStyle, setDropdownStyle] = React__namespace.useState(
155
+ {}
156
+ );
157
+ const updateDropdownPosition = React__namespace.useCallback(() => {
158
+ if (!triggerRef.current) return;
159
+ const rect = triggerRef.current.getBoundingClientRect();
160
+ setDropdownStyle({
161
+ position: "fixed",
162
+ top: rect.bottom + 4,
163
+ left: rect.left,
164
+ width: rect.width,
165
+ zIndex: 9999
166
+ });
167
+ }, []);
168
+ React__namespace.useEffect(() => {
169
+ if (!isOpen) return;
170
+ updateDropdownPosition();
171
+ window.addEventListener("scroll", updateDropdownPosition, true);
172
+ window.addEventListener("resize", updateDropdownPosition);
173
+ return () => {
174
+ window.removeEventListener("scroll", updateDropdownPosition, true);
175
+ window.removeEventListener("resize", updateDropdownPosition);
176
+ };
177
+ }, [isOpen, updateDropdownPosition]);
143
178
  const handleValueChange = React__namespace.useCallback(
144
179
  (newValue) => {
145
180
  if (!isControlled) {
@@ -259,83 +294,87 @@ function Select({
259
294
  ]
260
295
  }
261
296
  ),
262
- isOpen && /* @__PURE__ */ jsxRuntime.jsxs(
263
- "div",
264
- {
265
- className: chunkOR5DRJCW_cjs.cn(
266
- "absolute z-50 mt-1 w-full",
267
- "border-border bg-card rounded-lg border shadow-lg",
268
- "animate-in fade-in zoom-in-95 duration-100"
269
- ),
270
- children: [
271
- searchable && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-border border-b p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
272
- "input",
273
- {
274
- ref: searchInputRef,
275
- type: "text",
276
- value: searchQuery,
277
- onChange: (e) => setSearchQuery(e.target.value),
278
- onKeyDown: handleKeyDown,
279
- placeholder: searchPlaceholder,
280
- className: chunkOR5DRJCW_cjs.cn(
281
- "border-input bg-background w-full rounded-md border px-3 py-2 text-sm",
282
- "placeholder:text-muted-foreground",
283
- "focus:ring-ring focus:ring-2 focus:outline-none"
284
- ),
285
- "aria-label": "Search options"
286
- }
287
- ) }),
288
- /* @__PURE__ */ jsxRuntime.jsx(
289
- "ul",
290
- {
291
- ref: listRef,
292
- id: listboxId,
293
- role: "listbox",
294
- "aria-label": label || "Options",
295
- className: "max-h-60 overflow-auto p-1",
296
- children: filteredFlatOptions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("li", { className: "text-muted-foreground px-3 py-2 text-center text-sm", children: noResultsText }) : filteredOptions.map((item) => {
297
- if ("options" in item) {
298
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { role: "presentation", children: [
299
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground px-3 py-1.5 text-xs font-semibold tracking-wider uppercase", children: item.label }),
300
- /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "group", "aria-label": item.label, children: item.options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
301
- SelectOptionItem,
302
- {
303
- option,
304
- isSelected: option.value === value,
305
- isHighlighted: filteredFlatOptions[highlightedIndex]?.value === option.value,
306
- onSelect: () => handleValueChange(option.value),
307
- onMouseEnter: () => {
308
- const idx = filteredFlatOptions.findIndex(
309
- (o) => o.value === option.value
310
- );
311
- setHighlightedIndex(idx);
312
- }
313
- },
314
- option.value
315
- )) })
316
- ] }, `group-${item.label}`);
317
- }
318
- return /* @__PURE__ */ jsxRuntime.jsx(
319
- SelectOptionItem,
320
- {
321
- option: item,
322
- isSelected: item.value === value,
323
- isHighlighted: filteredFlatOptions[highlightedIndex]?.value === item.value,
324
- onSelect: () => handleValueChange(item.value),
325
- onMouseEnter: () => {
326
- const idx = filteredFlatOptions.findIndex(
327
- (o) => o.value === item.value
328
- );
329
- setHighlightedIndex(idx);
330
- }
331
- },
332
- item.value
333
- );
334
- })
335
- }
336
- )
337
- ]
338
- }
297
+ isOpen && reactDom.createPortal(
298
+ /* @__PURE__ */ jsxRuntime.jsxs(
299
+ "div",
300
+ {
301
+ ref: dropdownRef,
302
+ style: dropdownStyle,
303
+ className: chunkOR5DRJCW_cjs.cn(
304
+ "border-border bg-card rounded-lg border shadow-lg",
305
+ "animate-in fade-in zoom-in-95 duration-100"
306
+ ),
307
+ children: [
308
+ searchable && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-border border-b p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
309
+ "input",
310
+ {
311
+ ref: searchInputRef,
312
+ type: "text",
313
+ value: searchQuery,
314
+ onChange: (e) => setSearchQuery(e.target.value),
315
+ onKeyDown: handleKeyDown,
316
+ placeholder: searchPlaceholder,
317
+ className: chunkOR5DRJCW_cjs.cn(
318
+ "border-input bg-background w-full rounded-md border px-3 py-2 text-sm",
319
+ "placeholder:text-muted-foreground",
320
+ "focus:ring-ring focus:ring-2 focus:outline-none"
321
+ ),
322
+ "aria-label": "Search options"
323
+ }
324
+ ) }),
325
+ /* @__PURE__ */ jsxRuntime.jsx(
326
+ "ul",
327
+ {
328
+ ref: listRef,
329
+ id: listboxId,
330
+ role: "listbox",
331
+ "aria-label": label || "Options",
332
+ className: "max-h-60 overflow-auto p-1",
333
+ children: filteredFlatOptions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("li", { className: "text-muted-foreground px-3 py-2 text-center text-sm", children: noResultsText }) : filteredOptions.map((item) => {
334
+ if ("options" in item) {
335
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { role: "presentation", children: [
336
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground px-3 py-1.5 text-xs font-semibold tracking-wider uppercase", children: item.label }),
337
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "group", "aria-label": item.label, children: item.options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
338
+ SelectOptionItem,
339
+ {
340
+ option,
341
+ isSelected: option.value === value,
342
+ isHighlighted: filteredFlatOptions[highlightedIndex]?.value === option.value,
343
+ onSelect: () => handleValueChange(option.value),
344
+ onMouseEnter: () => {
345
+ const idx = filteredFlatOptions.findIndex(
346
+ (o) => o.value === option.value
347
+ );
348
+ setHighlightedIndex(idx);
349
+ }
350
+ },
351
+ option.value
352
+ )) })
353
+ ] }, `group-${item.label}`);
354
+ }
355
+ return /* @__PURE__ */ jsxRuntime.jsx(
356
+ SelectOptionItem,
357
+ {
358
+ option: item,
359
+ isSelected: item.value === value,
360
+ isHighlighted: filteredFlatOptions[highlightedIndex]?.value === item.value,
361
+ onSelect: () => handleValueChange(item.value),
362
+ onMouseEnter: () => {
363
+ const idx = filteredFlatOptions.findIndex(
364
+ (o) => o.value === item.value
365
+ );
366
+ setHighlightedIndex(idx);
367
+ }
368
+ },
369
+ item.value
370
+ );
371
+ })
372
+ }
373
+ )
374
+ ]
375
+ }
376
+ ),
377
+ document.body
339
378
  )
340
379
  ] }),
341
380
  error && /* @__PURE__ */ jsxRuntime.jsx("p", { id: errorId, className: "text-destructive text-sm", role: "alert", children: error }),
@@ -425,5 +464,5 @@ function CheckIcon({ className }) {
425
464
 
426
465
  exports.Select = Select;
427
466
  exports.selectTriggerVariants = selectTriggerVariants;
428
- //# sourceMappingURL=chunk-LEE3NMNP.cjs.map
429
- //# sourceMappingURL=chunk-LEE3NMNP.cjs.map
467
+ //# sourceMappingURL=chunk-NL3CZNBH.cjs.map
468
+ //# sourceMappingURL=chunk-NL3CZNBH.cjs.map