@fayz-ai/ui 0.9.0 → 0.10.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 (156) hide show
  1. package/README.md +2 -2
  2. package/dist/analytics/AnalyticsCard.d.ts +10 -0
  3. package/dist/analytics/AnalyticsCard.d.ts.map +1 -0
  4. package/dist/analytics/AnalyticsControls.d.ts +18 -0
  5. package/dist/analytics/AnalyticsControls.d.ts.map +1 -0
  6. package/dist/analytics/AnalyticsGrid.d.ts +16 -0
  7. package/dist/analytics/AnalyticsGrid.d.ts.map +1 -0
  8. package/dist/analytics/context.d.ts +58 -0
  9. package/dist/analytics/context.d.ts.map +1 -0
  10. package/dist/analytics/derive.d.ts +81 -0
  11. package/dist/analytics/derive.d.ts.map +1 -0
  12. package/dist/analytics/index.d.ts +13 -0
  13. package/dist/analytics/index.d.ts.map +1 -0
  14. package/dist/analytics/range.d.ts +22 -0
  15. package/dist/analytics/range.d.ts.map +1 -0
  16. package/dist/{chunk-PVIB724L.js → chunk-22EVFMS3.js} +5 -3
  17. package/dist/chunk-22EVFMS3.js.map +1 -0
  18. package/dist/{chunk-G6OKZ7WL.js → chunk-6V5MGYXH.js} +13 -9
  19. package/dist/chunk-6V5MGYXH.js.map +1 -0
  20. package/dist/{chunk-KV3MHB6N.js → chunk-H63TOSQ7.js} +196 -53
  21. package/dist/chunk-H63TOSQ7.js.map +1 -0
  22. package/dist/{chunk-OUPJDGKE.js → chunk-I6CPKAOD.js} +134 -37
  23. package/dist/chunk-I6CPKAOD.js.map +1 -0
  24. package/dist/{chunk-YRVE4FOD.js → chunk-OKZ6WQB3.js} +3 -3
  25. package/dist/chunk-OKZ6WQB3.js.map +1 -0
  26. package/dist/{chunk-S5KNM4D2.js → chunk-SEIY2F5F.js} +235 -107
  27. package/dist/chunk-SEIY2F5F.js.map +1 -0
  28. package/dist/{chunk-75EFDLST.js → chunk-VAKWUUVC.js} +157 -6
  29. package/dist/chunk-VAKWUUVC.js.map +1 -0
  30. package/dist/dashboard/OnboardingWidget.d.ts +2 -14
  31. package/dist/dashboard/OnboardingWidget.d.ts.map +1 -1
  32. package/dist/dashboard/SidebarOnboarding.d.ts +28 -0
  33. package/dist/dashboard/SidebarOnboarding.d.ts.map +1 -0
  34. package/dist/dashboard/index.d.ts +2 -0
  35. package/dist/dashboard/index.d.ts.map +1 -1
  36. package/dist/dashboard/index.js +4 -4
  37. package/dist/dashboard/types.d.ts +18 -0
  38. package/dist/dashboard/types.d.ts.map +1 -1
  39. package/dist/dashboard/useOnboardingProgress.d.ts +28 -0
  40. package/dist/dashboard/useOnboardingProgress.d.ts.map +1 -0
  41. package/dist/icons.js +1 -1
  42. package/dist/index.d.ts +5 -4
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +960 -14
  45. package/dist/index.js.map +1 -1
  46. package/dist/layout/AppShell.d.ts +14 -1
  47. package/dist/layout/AppShell.d.ts.map +1 -1
  48. package/dist/layout/ModulePage.d.ts +11 -2
  49. package/dist/layout/ModulePage.d.ts.map +1 -1
  50. package/dist/layout/Sidebar.d.ts +8 -1
  51. package/dist/layout/Sidebar.d.ts.map +1 -1
  52. package/dist/layout/index.js +4 -4
  53. package/dist/lib/cn.d.ts.map +1 -0
  54. package/dist/preset.d.ts +3 -0
  55. package/dist/preset.d.ts.map +1 -0
  56. package/dist/primitives/data-table.d.ts +19 -4
  57. package/dist/primitives/data-table.d.ts.map +1 -1
  58. package/dist/primitives/date-picker.d.ts +4 -2
  59. package/dist/primitives/date-picker.d.ts.map +1 -1
  60. package/dist/primitives/filter-chip.d.ts +26 -0
  61. package/dist/primitives/filter-chip.d.ts.map +1 -0
  62. package/dist/primitives/header-tabs.d.ts +32 -0
  63. package/dist/primitives/header-tabs.d.ts.map +1 -0
  64. package/dist/primitives/hint.d.ts +25 -0
  65. package/dist/primitives/hint.d.ts.map +1 -0
  66. package/dist/primitives/index.d.ts +7 -0
  67. package/dist/primitives/index.d.ts.map +1 -1
  68. package/dist/primitives/index.js +4 -4
  69. package/dist/primitives/list-view.d.ts +14 -1
  70. package/dist/primitives/list-view.d.ts.map +1 -1
  71. package/dist/primitives/page-header.d.ts +23 -0
  72. package/dist/primitives/page-header.d.ts.map +1 -0
  73. package/dist/primitives/stat-tiles.d.ts +30 -0
  74. package/dist/primitives/stat-tiles.d.ts.map +1 -0
  75. package/dist/primitives/switch.d.ts +11 -0
  76. package/dist/primitives/switch.d.ts.map +1 -0
  77. package/dist/stores/index.d.ts +1 -0
  78. package/dist/stores/index.d.ts.map +1 -1
  79. package/dist/stores/page-header.store.d.ts +69 -0
  80. package/dist/stores/page-header.store.d.ts.map +1 -0
  81. package/package.json +4 -13
  82. package/dist/chunk-75EFDLST.js.map +0 -1
  83. package/dist/chunk-G6OKZ7WL.js.map +0 -1
  84. package/dist/chunk-KV3MHB6N.js.map +0 -1
  85. package/dist/chunk-OUPJDGKE.js.map +0 -1
  86. package/dist/chunk-PVIB724L.js.map +0 -1
  87. package/dist/chunk-S5KNM4D2.js.map +0 -1
  88. package/dist/chunk-YRVE4FOD.js.map +0 -1
  89. package/dist/utils/cn.d.ts.map +0 -1
  90. package/src/dashboard/ChartWidget.tsx +0 -50
  91. package/src/dashboard/ChartWidgetInner.tsx +0 -83
  92. package/src/dashboard/DashboardCanvas.tsx +0 -210
  93. package/src/dashboard/DashboardCustomizeMenu.tsx +0 -53
  94. package/src/dashboard/DashboardGrid.tsx +0 -35
  95. package/src/dashboard/DashboardRange.tsx +0 -62
  96. package/src/dashboard/GoldCard.tsx +0 -38
  97. package/src/dashboard/KpiCard.tsx +0 -238
  98. package/src/dashboard/OnboardingWidget.tsx +0 -140
  99. package/src/dashboard/TableWidget.tsx +0 -51
  100. package/src/dashboard/define.ts +0 -53
  101. package/src/dashboard/icon.ts +0 -13
  102. package/src/dashboard/index.ts +0 -38
  103. package/src/dashboard/layout.ts +0 -50
  104. package/src/dashboard/preferences.ts +0 -71
  105. package/src/dashboard/types.ts +0 -41
  106. package/src/icons.ts +0 -66
  107. package/src/index.ts +0 -238
  108. package/src/layout/AppShell.tsx +0 -987
  109. package/src/layout/ContentSplit.tsx +0 -153
  110. package/src/layout/ModulePage.tsx +0 -466
  111. package/src/layout/PageTransition.tsx +0 -57
  112. package/src/layout/SaveBar.tsx +0 -247
  113. package/src/layout/Sidebar.tsx +0 -535
  114. package/src/layout/Topbar.tsx +0 -462
  115. package/src/layout/index.ts +0 -39
  116. package/src/layout/useCrossModuleBack.ts +0 -30
  117. package/src/primitives/Avatar.tsx +0 -48
  118. package/src/primitives/SearchCombobox.tsx +0 -216
  119. package/src/primitives/badge.tsx +0 -68
  120. package/src/primitives/breadcrumb.tsx +0 -43
  121. package/src/primitives/button.tsx +0 -60
  122. package/src/primitives/card.tsx +0 -79
  123. package/src/primitives/checkbox.tsx +0 -53
  124. package/src/primitives/confirm-dialog.tsx +0 -125
  125. package/src/primitives/currency-input.tsx +0 -121
  126. package/src/primitives/data-table.tsx +0 -160
  127. package/src/primitives/date-picker.tsx +0 -225
  128. package/src/primitives/dropdown.tsx +0 -196
  129. package/src/primitives/index.ts +0 -87
  130. package/src/primitives/input.tsx +0 -50
  131. package/src/primitives/list-view.tsx +0 -252
  132. package/src/primitives/markdown-editor.tsx +0 -75
  133. package/src/primitives/markdown.tsx +0 -169
  134. package/src/primitives/modal.tsx +0 -156
  135. package/src/primitives/phone-link.tsx +0 -138
  136. package/src/primitives/popover.tsx +0 -30
  137. package/src/primitives/search-select.tsx +0 -314
  138. package/src/primitives/segmented-control.tsx +0 -66
  139. package/src/primitives/select.tsx +0 -157
  140. package/src/primitives/separator.tsx +0 -29
  141. package/src/primitives/sheet.tsx +0 -181
  142. package/src/primitives/skeleton.tsx +0 -46
  143. package/src/primitives/tabs.tsx +0 -53
  144. package/src/primitives/time-picker.tsx +0 -148
  145. package/src/primitives/toast.tsx +0 -46
  146. package/src/primitives/tooltip.tsx +0 -28
  147. package/src/stores/index.ts +0 -10
  148. package/src/stores/layout.store.ts +0 -31
  149. package/src/stores/theme.store.ts +0 -457
  150. package/src/styles.css +0 -461
  151. package/src/tailwind.ts +0 -43
  152. package/src/theme/index.ts +0 -94
  153. package/src/theme/preset.ts +0 -209
  154. package/src/theme/presets.ts +0 -106
  155. package/src/utils/cn.ts +0 -6
  156. /package/dist/{utils → lib}/cn.d.ts +0 -0
@@ -1,314 +0,0 @@
1
- import * as React from 'react'
2
- import { Search, X, ChevronDown, Loader2 } from 'lucide-react'
3
- import { cn } from '../utils/cn'
4
-
5
- // ---------------------------------------------------------------------------
6
- // Types
7
- // ---------------------------------------------------------------------------
8
-
9
- export interface SearchSelectOption {
10
- id: string
11
- label: string
12
- subtitle?: string
13
- icon?: React.ReactNode
14
- group?: string
15
- disabled?: boolean
16
- data?: any
17
- }
18
-
19
- export interface SearchSelectProps {
20
- /** Currently selected option ID */
21
- value?: string
22
- /** Display text when a value is selected (overrides auto-lookup) */
23
- displayValue?: string
24
- /** Callback when an option is selected */
25
- onChange: (id: string, option: SearchSelectOption | null) => void
26
- /** Search function — async or sync. Called with debounced query. */
27
- onSearch: (query: string) => Promise<SearchSelectOption[]> | SearchSelectOption[]
28
- /** Placeholder text */
29
- placeholder?: string
30
- /** Label above the input */
31
- label?: string
32
- /** Required field indicator */
33
- required?: boolean
34
- /** Debounce delay in ms (default: 250) */
35
- debounce?: number
36
- /** Minimum characters before searching (default: 1) */
37
- minChars?: number
38
- /** Show a "Create new" action at the bottom */
39
- allowCreate?: boolean
40
- /** Label for create action (default: "Add") */
41
- createLabel?: string
42
- /** Callback when create is clicked. Can be async — component shows optimistic state while waiting. */
43
- onCreate?: (query: string) => void | Promise<void>
44
- /** Custom render for each option */
45
- renderOption?: (option: SearchSelectOption) => React.ReactNode
46
- /** Load initial results when dropdown opens (calls onSearch('')). Default
47
- * true — clicking lists options before any typing; pass false to require
48
- * a query first (e.g. very large datasets with no cheap top-N). */
49
- loadOnOpen?: boolean
50
- /** Additional className for the container */
51
- className?: string
52
- /** Disabled state */
53
- disabled?: boolean
54
- }
55
-
56
- // ---------------------------------------------------------------------------
57
- // Component
58
- // ---------------------------------------------------------------------------
59
-
60
- export function SearchSelect({
61
- value,
62
- displayValue,
63
- onChange,
64
- onSearch,
65
- placeholder = 'Search...',
66
- label,
67
- required,
68
- debounce = 250,
69
- minChars = 1,
70
- allowCreate,
71
- createLabel = 'Add',
72
- onCreate,
73
- renderOption,
74
- loadOnOpen = true,
75
- className,
76
- disabled,
77
- }: SearchSelectProps) {
78
- const [open, setOpen] = React.useState(false)
79
- const [query, setQuery] = React.useState('')
80
- const [results, setResults] = React.useState<SearchSelectOption[]>([])
81
- const [loading, setLoading] = React.useState(false)
82
- const [creating, setCreating] = React.useState(false)
83
- const [selectedLabel, setSelectedLabel] = React.useState(displayValue ?? '')
84
- const containerRef = React.useRef<HTMLDivElement>(null)
85
- const inputRef = React.useRef<HTMLInputElement>(null)
86
- const timerRef = React.useRef<ReturnType<typeof setTimeout>>()
87
-
88
- // Close on outside click
89
- React.useEffect(() => {
90
- function handler(e: MouseEvent) {
91
- if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
92
- setOpen(false)
93
- }
94
- }
95
- document.addEventListener('mousedown', handler)
96
- return () => document.removeEventListener('mousedown', handler)
97
- }, [])
98
-
99
- // Update display when value/displayValue changes externally
100
- React.useEffect(() => {
101
- if (displayValue !== undefined) setSelectedLabel(displayValue)
102
- }, [displayValue])
103
-
104
- // Load initial results when dropdown opens with empty query
105
- React.useEffect(() => {
106
- if (open && loadOnOpen && query.length === 0 && results.length === 0 && !loading) {
107
- setLoading(true)
108
- Promise.resolve(onSearch('')).then(setResults).catch(() => setResults([])).finally(() => setLoading(false))
109
- }
110
- }, [open, loadOnOpen])
111
-
112
- function handleQueryChange(q: string) {
113
- setQuery(q)
114
- if (timerRef.current) clearTimeout(timerRef.current)
115
-
116
- if (q.length < minChars && !(loadOnOpen && q.length === 0)) {
117
- setResults([])
118
- setLoading(false)
119
- return
120
- }
121
-
122
- setLoading(true)
123
- timerRef.current = setTimeout(async () => {
124
- try {
125
- const res = await onSearch(q)
126
- setResults(res)
127
- } catch {
128
- setResults([])
129
- }
130
- setLoading(false)
131
- }, debounce)
132
- }
133
-
134
- function handleSelect(option: SearchSelectOption) {
135
- onChange(option.id, option)
136
- setSelectedLabel(option.label)
137
- setOpen(false)
138
- setQuery('')
139
- setResults([])
140
- }
141
-
142
- function handleClear() {
143
- onChange('', null)
144
- setSelectedLabel('')
145
- setQuery('')
146
- setResults([])
147
- }
148
-
149
- async function handleCreate(name: string) {
150
- if (!onCreate) return
151
- setCreating(true)
152
- setSelectedLabel(name)
153
- setOpen(false)
154
- setQuery('')
155
- setResults([])
156
- try {
157
- await onCreate(name)
158
- } finally {
159
- setCreating(false)
160
- }
161
- }
162
-
163
- function handleOpen() {
164
- if (disabled || creating) return
165
- setOpen(true)
166
- setQuery('')
167
- // Stale results from a previous typed query would render for the empty
168
- // query now that the dropdown shows immediately — drop them so the
169
- // loadOnOpen effect refetches the initial listing.
170
- setResults([])
171
- setTimeout(() => inputRef.current?.focus(), 0)
172
- }
173
-
174
- // Group results
175
- const groups = React.useMemo(() => {
176
- const map = new Map<string, SearchSelectOption[]>()
177
- for (const opt of results) {
178
- const group = opt.group ?? ''
179
- if (!map.has(group)) map.set(group, [])
180
- map.get(group)!.push(opt)
181
- }
182
- return map
183
- }, [results])
184
-
185
- const hasValue = !!value && !!selectedLabel
186
- // With loadOnOpen the dropdown must show for the EMPTY query too — gating it
187
- // on minChars silently hid the initial listing loadOnOpen had just fetched.
188
- const showDropdown = open && (query.length >= minChars || loadOnOpen)
189
-
190
- return (
191
- <div ref={containerRef} className={cn('relative', className)}>
192
- {label && (
193
- <label className="text-xs font-medium text-muted-foreground">
194
- {label}{required && ' *'}
195
- </label>
196
- )}
197
-
198
- {/* Trigger — shows selected value or search input */}
199
- <div
200
- className={cn(
201
- 'mt-1 flex items-center gap-2 rounded-lg border bg-background transition-colors',
202
- open ? 'ring-2 ring-primary/20' : 'hover:bg-muted/30',
203
- disabled && 'opacity-50 cursor-not-allowed',
204
- )}
205
- >
206
- <Search className="h-3.5 w-3.5 text-muted-foreground ml-3 shrink-0" />
207
- {open ? (
208
- <input
209
- ref={inputRef}
210
- type="text"
211
- value={query}
212
- onChange={(e) => handleQueryChange(e.target.value)}
213
- placeholder={placeholder}
214
- className="flex-1 bg-transparent py-2 pr-3 text-sm outline-none"
215
- onKeyDown={(e) => {
216
- if (e.key === 'Escape') setOpen(false)
217
- }}
218
- />
219
- ) : (
220
- <button
221
- type="button"
222
- onClick={handleOpen}
223
- className="flex-1 text-left py-2 pr-3 text-sm outline-none"
224
- disabled={disabled || creating}
225
- >
226
- {creating ? (
227
- <span className="flex items-center gap-1.5 text-muted-foreground">
228
- <Loader2 className="h-3 w-3 animate-spin" />
229
- <span className="font-medium text-foreground">{selectedLabel}</span>
230
- </span>
231
- ) : hasValue ? (
232
- <span className="font-medium">{selectedLabel}</span>
233
- ) : (
234
- <span className="text-muted-foreground">{placeholder}</span>
235
- )}
236
- </button>
237
- )}
238
- {hasValue && !open && (
239
- <button onClick={handleClear} className="pr-3 text-muted-foreground hover:text-foreground">
240
- <X className="h-3 w-3" />
241
- </button>
242
- )}
243
- {!hasValue && !open && (
244
- <ChevronDown className="h-3 w-3 text-muted-foreground mr-3 shrink-0" />
245
- )}
246
- </div>
247
-
248
- {/* Dropdown */}
249
- {showDropdown && (
250
- <div className="fayz-glass-surface absolute top-full left-0 right-0 z-50 mt-1 rounded-lg border bg-popover shadow-lg overflow-hidden">
251
- {loading ? (
252
- <div className="flex items-center justify-center gap-2 px-4 py-6 text-xs text-muted-foreground">
253
- <Loader2 className="h-3.5 w-3.5 animate-spin" /> Searching...
254
- </div>
255
- ) : results.length === 0 ? (
256
- <div className="px-4 py-4 text-center">
257
- <p className="text-xs text-muted-foreground">{query ? `No results for "${query}"` : 'No results'}</p>
258
- {allowCreate && onCreate && (
259
- <button
260
- onClick={() => handleCreate(query)}
261
- className="mt-2 text-xs text-primary hover:underline"
262
- >
263
- + {createLabel} "{query}"
264
- </button>
265
- )}
266
- </div>
267
- ) : (
268
- <div className="max-h-64 overflow-auto py-1">
269
- {[...groups.entries()].map(([group, options]) => (
270
- <React.Fragment key={group}>
271
- {group && (
272
- <div className="sticky top-0 bg-muted/50 px-3 py-1 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
273
- {group}
274
- </div>
275
- )}
276
- {options.map((opt) => (
277
- <button
278
- key={opt.id}
279
- onClick={() => handleSelect(opt)}
280
- disabled={opt.disabled}
281
- className={cn(
282
- 'w-full text-left px-3 py-2 hover:bg-muted/50 transition-colors flex items-center gap-2.5',
283
- opt.disabled && 'opacity-40 cursor-not-allowed',
284
- opt.id === value && 'bg-muted/30',
285
- )}
286
- >
287
- {renderOption ? renderOption(opt) : (
288
- <>
289
- {opt.icon}
290
- <div className="min-w-0 flex-1">
291
- <p className="text-sm truncate">{opt.label}</p>
292
- {opt.subtitle && <p className="text-[10px] text-muted-foreground truncate">{opt.subtitle}</p>}
293
- </div>
294
- </>
295
- )}
296
- </button>
297
- ))}
298
- </React.Fragment>
299
- ))}
300
- {allowCreate && onCreate && (
301
- <button
302
- onClick={() => handleCreate(query)}
303
- className="w-full text-left px-3 py-2 text-xs text-primary hover:bg-muted/50 transition-colors border-t"
304
- >
305
- + {createLabel} "{query}"
306
- </button>
307
- )}
308
- </div>
309
- )}
310
- </div>
311
- )}
312
- </div>
313
- )
314
- }
@@ -1,66 +0,0 @@
1
- import * as React from 'react'
2
- import { cn } from '../utils/cn'
3
-
4
- export interface SegmentedOption<T extends string = string> {
5
- value: T
6
- label: React.ReactNode
7
- }
8
-
9
- export interface SegmentedControlProps<T extends string = string> {
10
- /** Options as plain values (label = value) or `{ value, label }` objects. */
11
- options: ReadonlyArray<T | SegmentedOption<T>>
12
- value: T
13
- onChange: (value: T) => void
14
- /** Matches the equivalent Button heights: sm = 26px, md = 30px. */
15
- size?: 'sm' | 'md'
16
- className?: string
17
- 'aria-label'?: string
18
- }
19
-
20
- const SIZE: Record<'sm' | 'md', { container: string; segment: string }> = {
21
- sm: { container: 'h-[26px]', segment: 'px-2.5 text-xs' },
22
- md: { container: 'h-[30px]', segment: 'px-3 text-sm' },
23
- }
24
-
25
- /**
26
- * Canonical segmented (pill) control — same chrome as Button (rounded-button
27
- * radius, hairline border + shadow-button bevel on a card surface). Use this for
28
- * any 7d/30d/90d-style toggle so every surface stays visually consistent instead
29
- * of hand-rolling a styled toggle group.
30
- */
31
- export function SegmentedControl<T extends string = string>({
32
- options, value, onChange, size = 'sm', className, ...rest
33
- }: SegmentedControlProps<T>) {
34
- const items = options.map((o) => (typeof o === 'string' ? { value: o, label: o } : o)) as SegmentedOption<T>[]
35
- return (
36
- <div
37
- role="tablist"
38
- aria-label={rest['aria-label']}
39
- className={cn(
40
- 'inline-flex items-center rounded-button border border-border bg-card p-0.5 shadow-button',
41
- SIZE[size].container,
42
- className,
43
- )}
44
- >
45
- {items.map((item) => {
46
- const active = item.value === value
47
- return (
48
- <button
49
- key={item.value}
50
- type="button"
51
- role="tab"
52
- aria-selected={active}
53
- onClick={() => onChange(item.value)}
54
- className={cn(
55
- 'flex h-full items-center rounded-button font-semibold transition-colors',
56
- SIZE[size].segment,
57
- active ? 'bg-foreground text-background' : 'text-muted-foreground hover:bg-muted/60',
58
- )}
59
- >
60
- {item.label}
61
- </button>
62
- )
63
- })}
64
- </div>
65
- )
66
- }
@@ -1,157 +0,0 @@
1
- import * as React from 'react'
2
- import * as SelectPrimitive from '@radix-ui/react-select'
3
- import { ChevronDown, ChevronUp, Check } from 'lucide-react'
4
-
5
- import { cn } from '../utils/cn'
6
-
7
- const Select = SelectPrimitive.Root
8
-
9
- const SelectGroup = SelectPrimitive.Group
10
-
11
- const SelectValue = SelectPrimitive.Value
12
-
13
- const SelectTrigger = React.forwardRef<
14
- React.ElementRef<typeof SelectPrimitive.Trigger>,
15
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
16
- >(({ className, children, ...props }, ref) => (
17
- <SelectPrimitive.Trigger
18
- ref={ref}
19
- className={cn(
20
- 'flex h-10 w-full items-center justify-between rounded-input border border-input bg-background px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1',
21
- className
22
- )}
23
- {...props}
24
- >
25
- {children}
26
- <SelectPrimitive.Icon asChild>
27
- <ChevronDown className="h-4 w-4 opacity-50" />
28
- </SelectPrimitive.Icon>
29
- </SelectPrimitive.Trigger>
30
- ))
31
- SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
32
-
33
- const SelectScrollUpButton = React.forwardRef<
34
- React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
35
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
36
- >(({ className, ...props }, ref) => (
37
- <SelectPrimitive.ScrollUpButton
38
- ref={ref}
39
- className={cn(
40
- 'flex cursor-default items-center justify-center py-1',
41
- className
42
- )}
43
- {...props}
44
- >
45
- <ChevronUp className="h-4 w-4" />
46
- </SelectPrimitive.ScrollUpButton>
47
- ))
48
- SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
49
-
50
- const SelectScrollDownButton = React.forwardRef<
51
- React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
52
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
53
- >(({ className, ...props }, ref) => (
54
- <SelectPrimitive.ScrollDownButton
55
- ref={ref}
56
- className={cn(
57
- 'flex cursor-default items-center justify-center py-1',
58
- className
59
- )}
60
- {...props}
61
- >
62
- <ChevronDown className="h-4 w-4" />
63
- </SelectPrimitive.ScrollDownButton>
64
- ))
65
- SelectScrollDownButton.displayName =
66
- SelectPrimitive.ScrollDownButton.displayName
67
-
68
- const SelectContent = React.forwardRef<
69
- React.ElementRef<typeof SelectPrimitive.Content>,
70
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
71
- >(({ className, children, position = 'popper', ...props }, ref) => (
72
- <SelectPrimitive.Portal>
73
- <SelectPrimitive.Content
74
- ref={ref}
75
- className={cn(
76
- 'fayz-glass-surface relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-card border bg-popover text-popover-foreground shadow-md',
77
- position === 'popper' &&
78
- 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
79
- className
80
- )}
81
- position={position}
82
- {...props}
83
- >
84
- <SelectScrollUpButton />
85
- <SelectPrimitive.Viewport
86
- className={cn(
87
- 'p-1',
88
- position === 'popper' &&
89
- 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]'
90
- )}
91
- >
92
- {children}
93
- </SelectPrimitive.Viewport>
94
- <SelectScrollDownButton />
95
- </SelectPrimitive.Content>
96
- </SelectPrimitive.Portal>
97
- ))
98
- SelectContent.displayName = SelectPrimitive.Content.displayName
99
-
100
- const SelectLabel = React.forwardRef<
101
- React.ElementRef<typeof SelectPrimitive.Label>,
102
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
103
- >(({ className, ...props }, ref) => (
104
- <SelectPrimitive.Label
105
- ref={ref}
106
- className={cn('py-1.5 pl-8 pr-2 text-sm font-semibold', className)}
107
- {...props}
108
- />
109
- ))
110
- SelectLabel.displayName = SelectPrimitive.Label.displayName
111
-
112
- const SelectItem = React.forwardRef<
113
- React.ElementRef<typeof SelectPrimitive.Item>,
114
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
115
- >(({ className, children, ...props }, ref) => (
116
- <SelectPrimitive.Item
117
- ref={ref}
118
- className={cn(
119
- 'relative flex w-full cursor-default select-none items-center rounded-button py-1.5 pl-8 pr-2 text-sm outline-none data-[highlighted]:bg-muted focus:bg-muted data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
120
- className
121
- )}
122
- {...props}
123
- >
124
- <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
125
- <SelectPrimitive.ItemIndicator>
126
- <Check className="h-4 w-4" />
127
- </SelectPrimitive.ItemIndicator>
128
- </span>
129
- <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
130
- </SelectPrimitive.Item>
131
- ))
132
- SelectItem.displayName = SelectPrimitive.Item.displayName
133
-
134
- const SelectSeparator = React.forwardRef<
135
- React.ElementRef<typeof SelectPrimitive.Separator>,
136
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
137
- >(({ className, ...props }, ref) => (
138
- <SelectPrimitive.Separator
139
- ref={ref}
140
- className={cn('-mx-1 my-1 h-px bg-muted', className)}
141
- {...props}
142
- />
143
- ))
144
- SelectSeparator.displayName = SelectPrimitive.Separator.displayName
145
-
146
- export {
147
- Select,
148
- SelectGroup,
149
- SelectValue,
150
- SelectTrigger,
151
- SelectContent,
152
- SelectLabel,
153
- SelectItem,
154
- SelectSeparator,
155
- SelectScrollUpButton,
156
- SelectScrollDownButton,
157
- }
@@ -1,29 +0,0 @@
1
- import * as React from 'react'
2
- import * as SeparatorPrimitive from '@radix-ui/react-separator'
3
-
4
- import { cn } from '../utils/cn'
5
-
6
- const Separator = React.forwardRef<
7
- React.ElementRef<typeof SeparatorPrimitive.Root>,
8
- React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
9
- >(
10
- (
11
- { className, orientation = 'horizontal', decorative = true, ...props },
12
- ref
13
- ) => (
14
- <SeparatorPrimitive.Root
15
- ref={ref}
16
- decorative={decorative}
17
- orientation={orientation}
18
- className={cn(
19
- 'shrink-0 bg-border',
20
- orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
21
- className
22
- )}
23
- {...props}
24
- />
25
- )
26
- )
27
- Separator.displayName = SeparatorPrimitive.Root.displayName
28
-
29
- export { Separator }