@fayz-ai/ui 0.8.4 → 0.8.5

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 (78) hide show
  1. package/dist/ChartWidgetInner-GDE5PBTR.js +46 -0
  2. package/dist/ChartWidgetInner-GDE5PBTR.js.map +1 -0
  3. package/dist/{chunk-VVQ45ZDZ.js → chunk-KV3MHB6N.js} +85 -179
  4. package/dist/chunk-KV3MHB6N.js.map +1 -0
  5. package/dist/{chunk-M34ACV5E.js → chunk-OUPJDGKE.js} +6 -41
  6. package/dist/chunk-OUPJDGKE.js.map +1 -0
  7. package/dist/chunk-PVIB724L.js +161 -0
  8. package/dist/chunk-PVIB724L.js.map +1 -0
  9. package/dist/{chunk-DYMBFHD7.js → chunk-VDAYIQX4.js} +202 -3
  10. package/dist/chunk-VDAYIQX4.js.map +1 -0
  11. package/dist/{chunk-R4LPSXTT.js → chunk-YLQGUJAQ.js} +18 -6
  12. package/dist/chunk-YLQGUJAQ.js.map +1 -0
  13. package/dist/dashboard/ChartWidget.d.ts.map +1 -1
  14. package/dist/dashboard/ChartWidgetInner.d.ts +11 -0
  15. package/dist/dashboard/ChartWidgetInner.d.ts.map +1 -0
  16. package/dist/dashboard/index.js +2 -1
  17. package/dist/icons.d.ts +8 -0
  18. package/dist/icons.d.ts.map +1 -0
  19. package/dist/icons.js +3 -0
  20. package/dist/icons.js.map +1 -0
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +5 -5
  24. package/dist/layout/Sidebar.d.ts +1 -2
  25. package/dist/layout/Sidebar.d.ts.map +1 -1
  26. package/dist/layout/index.js +2 -1
  27. package/dist/preset.cjs +201 -11
  28. package/dist/preset.cjs.map +1 -1
  29. package/dist/preset.js +201 -1
  30. package/dist/preset.js.map +1 -1
  31. package/dist/primitives/date-picker.d.ts +7 -1
  32. package/dist/primitives/date-picker.d.ts.map +1 -1
  33. package/dist/primitives/index.js +1 -1
  34. package/dist/tailwind.cjs +199 -2
  35. package/dist/tailwind.cjs.map +1 -1
  36. package/dist/tailwind.js +198 -1
  37. package/dist/tailwind.js.map +1 -1
  38. package/dist/theme/index.js +1 -2
  39. package/package.json +24 -22
  40. package/src/dashboard/ChartWidget.tsx +8 -65
  41. package/src/dashboard/ChartWidgetInner.tsx +83 -0
  42. package/src/dashboard/icon.ts +2 -2
  43. package/src/icons.ts +66 -0
  44. package/src/index.ts +4 -0
  45. package/src/layout/Sidebar.tsx +4 -110
  46. package/src/primitives/date-picker.tsx +30 -4
  47. package/dist/chunk-2P7T6QQK.cjs +0 -206
  48. package/dist/chunk-2P7T6QQK.cjs.map +0 -1
  49. package/dist/chunk-7ZQQZD4Q.cjs +0 -1823
  50. package/dist/chunk-7ZQQZD4Q.cjs.map +0 -1
  51. package/dist/chunk-B3BTZDTA.cjs +0 -1701
  52. package/dist/chunk-B3BTZDTA.cjs.map +0 -1
  53. package/dist/chunk-DYMBFHD7.js.map +0 -1
  54. package/dist/chunk-H6OULCHF.cjs +0 -81
  55. package/dist/chunk-H6OULCHF.cjs.map +0 -1
  56. package/dist/chunk-IWBXYV4U.js +0 -203
  57. package/dist/chunk-IWBXYV4U.js.map +0 -1
  58. package/dist/chunk-M34ACV5E.js.map +0 -1
  59. package/dist/chunk-MUGRP5DD.cjs +0 -701
  60. package/dist/chunk-MUGRP5DD.cjs.map +0 -1
  61. package/dist/chunk-NZV47HWO.cjs +0 -380
  62. package/dist/chunk-NZV47HWO.cjs.map +0 -1
  63. package/dist/chunk-OW73RZOU.cjs +0 -313
  64. package/dist/chunk-OW73RZOU.cjs.map +0 -1
  65. package/dist/chunk-R4LPSXTT.js.map +0 -1
  66. package/dist/chunk-R4SQ2GVD.cjs +0 -475
  67. package/dist/chunk-R4SQ2GVD.cjs.map +0 -1
  68. package/dist/chunk-VVQ45ZDZ.js.map +0 -1
  69. package/dist/dashboard/index.cjs +0 -106
  70. package/dist/dashboard/index.cjs.map +0 -1
  71. package/dist/index.cjs +0 -650
  72. package/dist/index.cjs.map +0 -1
  73. package/dist/layout/index.cjs +0 -98
  74. package/dist/layout/index.cjs.map +0 -1
  75. package/dist/primitives/index.cjs +0 -363
  76. package/dist/primitives/index.cjs.map +0 -1
  77. package/dist/theme/index.cjs +0 -41
  78. package/dist/theme/index.cjs.map +0 -1
@@ -1,27 +1,8 @@
1
1
  import * as React from 'react'
2
- import {
3
- ResponsiveContainer,
4
- LineChart, Line,
5
- BarChart, Bar,
6
- AreaChart, Area,
7
- PieChart, Pie, Cell,
8
- XAxis, YAxis, CartesianGrid, Tooltip, Legend,
9
- } from 'recharts'
10
2
  import { Card, CardContent, CardHeader, CardTitle } from '../primitives/card'
11
3
  import { renderIcon } from './icon'
12
4
  import type { ChartSeries, ChartType, IconRef } from './types'
13
5
 
14
- /** Theme-driven palette (HSL triplet CSS vars defined in styles.css). */
15
- const PALETTE = [
16
- 'hsl(var(--info))',
17
- 'hsl(var(--magic))',
18
- 'hsl(var(--success))',
19
- 'hsl(var(--warning))',
20
- 'hsl(var(--destructive))',
21
- ]
22
- const AXIS = 'hsl(var(--muted-foreground))'
23
- const GRID = 'hsl(var(--border))'
24
-
25
6
  export interface ChartWidgetProps {
26
7
  type: ChartType
27
8
  /** Rows of data; each key referenced by a series.dataKey. */
@@ -37,12 +18,15 @@ export interface ChartWidgetProps {
37
18
  className?: string
38
19
  }
39
20
 
21
+ // The recharts body is lazy so recharts ships as an async chunk instead of in
22
+ // every consumer's entry bundle; the Card shell renders immediately and the
23
+ // fallback reserves the chart's height to avoid layout shift.
24
+ const ChartWidgetInner = React.lazy(() => import('./ChartWidgetInner'))
25
+
40
26
  /** recharts-backed chart in a Card. Replaces the hand-rolled CSS bar charts. */
41
27
  export function ChartWidget({
42
28
  type, data, series, categoryKey = 'name', title, icon, headerAction, height = 240, className,
43
29
  }: ChartWidgetProps) {
44
- const color = (i: number, explicit?: string) => explicit ?? PALETTE[i % PALETTE.length]
45
-
46
30
  return (
47
31
  <Card className={className}>
48
32
  {(title || headerAction) && (
@@ -57,50 +41,9 @@ export function ChartWidget({
57
41
  </CardHeader>
58
42
  )}
59
43
  <CardContent className="p-4 pt-2">
60
- <ResponsiveContainer width="100%" height={height}>
61
- {type === 'pie' ? (
62
- <PieChart>
63
- <Tooltip />
64
- <Pie data={data} dataKey={series[0]?.dataKey ?? 'value'} nameKey={categoryKey} innerRadius={50} outerRadius={80} paddingAngle={2}>
65
- {data.map((_, i) => <Cell key={i} fill={color(i, series[0]?.color)} />)}
66
- </Pie>
67
- <Legend />
68
- </PieChart>
69
- ) : type === 'bar' ? (
70
- <BarChart data={data}>
71
- <CartesianGrid strokeDasharray="3 3" stroke={GRID} vertical={false} />
72
- <XAxis dataKey={categoryKey} stroke={AXIS} fontSize={12} tickLine={false} axisLine={false} />
73
- <YAxis stroke={AXIS} fontSize={12} tickLine={false} axisLine={false} width={36} />
74
- <Tooltip cursor={{ fill: GRID, opacity: 0.3 }} />
75
- {series.length > 1 && <Legend />}
76
- {series.map((s, i) => (
77
- <Bar key={s.dataKey} dataKey={s.dataKey} name={s.label ?? s.dataKey} fill={color(i, s.color)} radius={[4, 4, 0, 0]} />
78
- ))}
79
- </BarChart>
80
- ) : type === 'area' ? (
81
- <AreaChart data={data}>
82
- <CartesianGrid strokeDasharray="3 3" stroke={GRID} vertical={false} />
83
- <XAxis dataKey={categoryKey} stroke={AXIS} fontSize={12} tickLine={false} axisLine={false} />
84
- <YAxis stroke={AXIS} fontSize={12} tickLine={false} axisLine={false} width={36} />
85
- <Tooltip />
86
- {series.length > 1 && <Legend />}
87
- {series.map((s, i) => (
88
- <Area key={s.dataKey} dataKey={s.dataKey} name={s.label ?? s.dataKey} stroke={color(i, s.color)} fill={color(i, s.color)} fillOpacity={0.15} />
89
- ))}
90
- </AreaChart>
91
- ) : (
92
- <LineChart data={data}>
93
- <CartesianGrid strokeDasharray="3 3" stroke={GRID} vertical={false} />
94
- <XAxis dataKey={categoryKey} stroke={AXIS} fontSize={12} tickLine={false} axisLine={false} />
95
- <YAxis stroke={AXIS} fontSize={12} tickLine={false} axisLine={false} width={36} />
96
- <Tooltip />
97
- {series.length > 1 && <Legend />}
98
- {series.map((s, i) => (
99
- <Line key={s.dataKey} dataKey={s.dataKey} name={s.label ?? s.dataKey} stroke={color(i, s.color)} strokeWidth={2} dot={false} />
100
- ))}
101
- </LineChart>
102
- )}
103
- </ResponsiveContainer>
44
+ <React.Suspense fallback={<div style={{ height }} />}>
45
+ <ChartWidgetInner type={type} data={data} series={series} categoryKey={categoryKey} height={height} />
46
+ </React.Suspense>
104
47
  </CardContent>
105
48
  </Card>
106
49
  )
@@ -0,0 +1,83 @@
1
+ import * as React from 'react'
2
+ import {
3
+ ResponsiveContainer,
4
+ LineChart, Line,
5
+ BarChart, Bar,
6
+ AreaChart, Area,
7
+ PieChart, Pie, Cell,
8
+ XAxis, YAxis, CartesianGrid, Tooltip, Legend,
9
+ } from 'recharts'
10
+ import type { ChartSeries, ChartType } from './types'
11
+
12
+ /** Theme-driven palette (HSL triplet CSS vars defined in styles.css). */
13
+ const PALETTE = [
14
+ 'hsl(var(--info))',
15
+ 'hsl(var(--magic))',
16
+ 'hsl(var(--success))',
17
+ 'hsl(var(--warning))',
18
+ 'hsl(var(--destructive))',
19
+ ]
20
+ const AXIS = 'hsl(var(--muted-foreground))'
21
+ const GRID = 'hsl(var(--border))'
22
+
23
+ export interface ChartWidgetInnerProps {
24
+ type: ChartType
25
+ data: Array<Record<string, string | number>>
26
+ series: ChartSeries[]
27
+ categoryKey: string
28
+ height: number
29
+ }
30
+
31
+ // recharts-backed chart body. Default export + own module so ChartWidget can
32
+ // React.lazy it — recharts (~400 KB min) then lives in an async chunk instead
33
+ // of every consumer's entry bundle.
34
+ export default function ChartWidgetInner({ type, data, series, categoryKey, height }: ChartWidgetInnerProps) {
35
+ const color = (i: number, explicit?: string) => explicit ?? PALETTE[i % PALETTE.length]
36
+
37
+ return (
38
+ <ResponsiveContainer width="100%" height={height}>
39
+ {type === 'pie' ? (
40
+ <PieChart>
41
+ <Tooltip />
42
+ <Pie data={data} dataKey={series[0]?.dataKey ?? 'value'} nameKey={categoryKey} innerRadius={50} outerRadius={80} paddingAngle={2}>
43
+ {data.map((_, i) => <Cell key={i} fill={color(i, series[0]?.color)} />)}
44
+ </Pie>
45
+ <Legend />
46
+ </PieChart>
47
+ ) : type === 'bar' ? (
48
+ <BarChart data={data}>
49
+ <CartesianGrid strokeDasharray="3 3" stroke={GRID} vertical={false} />
50
+ <XAxis dataKey={categoryKey} stroke={AXIS} fontSize={12} tickLine={false} axisLine={false} />
51
+ <YAxis stroke={AXIS} fontSize={12} tickLine={false} axisLine={false} width={36} />
52
+ <Tooltip cursor={{ fill: GRID, opacity: 0.3 }} />
53
+ {series.length > 1 && <Legend />}
54
+ {series.map((s, i) => (
55
+ <Bar key={s.dataKey} dataKey={s.dataKey} name={s.label ?? s.dataKey} fill={color(i, s.color)} radius={[4, 4, 0, 0]} />
56
+ ))}
57
+ </BarChart>
58
+ ) : type === 'area' ? (
59
+ <AreaChart data={data}>
60
+ <CartesianGrid strokeDasharray="3 3" stroke={GRID} vertical={false} />
61
+ <XAxis dataKey={categoryKey} stroke={AXIS} fontSize={12} tickLine={false} axisLine={false} />
62
+ <YAxis stroke={AXIS} fontSize={12} tickLine={false} axisLine={false} width={36} />
63
+ <Tooltip />
64
+ {series.length > 1 && <Legend />}
65
+ {series.map((s, i) => (
66
+ <Area key={s.dataKey} dataKey={s.dataKey} name={s.label ?? s.dataKey} stroke={color(i, s.color)} fill={color(i, s.color)} fillOpacity={0.15} />
67
+ ))}
68
+ </AreaChart>
69
+ ) : (
70
+ <LineChart data={data}>
71
+ <CartesianGrid strokeDasharray="3 3" stroke={GRID} vertical={false} />
72
+ <XAxis dataKey={categoryKey} stroke={AXIS} fontSize={12} tickLine={false} axisLine={false} />
73
+ <YAxis stroke={AXIS} fontSize={12} tickLine={false} axisLine={false} width={36} />
74
+ <Tooltip />
75
+ {series.length > 1 && <Legend />}
76
+ {series.map((s, i) => (
77
+ <Line key={s.dataKey} dataKey={s.dataKey} name={s.label ?? s.dataKey} stroke={color(i, s.color)} strokeWidth={2} dot={false} />
78
+ ))}
79
+ </LineChart>
80
+ )}
81
+ </ResponsiveContainer>
82
+ )
83
+ }
@@ -1,12 +1,12 @@
1
1
  import * as React from 'react'
2
- import * as LucideIcons from 'lucide-react'
2
+ import { getLucideIcon } from '../icons'
3
3
  import type { IconRef } from './types'
4
4
 
5
5
  /** Resolve an IconRef (lucide name or component) to a renderable element. */
6
6
  export function renderIcon(icon: IconRef | undefined, className = 'h-4 w-4'): React.ReactNode {
7
7
  if (!icon) return null
8
8
  if (typeof icon === 'string') {
9
- const Comp = (LucideIcons as unknown as Record<string, React.ComponentType<{ className?: string }>>)[icon]
9
+ const Comp = getLucideIcon(icon)
10
10
  return Comp ? React.createElement(Comp, { className }) : null
11
11
  }
12
12
  return React.createElement(icon, { className })
package/src/icons.ts ADDED
@@ -0,0 +1,66 @@
1
+ import type { LucideIcon } from 'lucide-react'
2
+ import {
3
+ Activity, AlertTriangle, Apple, ArrowDownCircle, ArrowDownRight, ArrowLeftRight, ArrowUpCircle, ArrowUpRight,
4
+ Award, BadgeDollarSign, Ban, Banknote, BarChart3, Bell, Bike, BookOpen,
5
+ BookOpenCheck, Box, Boxes, Briefcase, Building2, Calendar, CalendarCheck, CalendarCheck2,
6
+ CalendarClock, CalendarDays, CalendarPlus, CalendarX, Camera, Cat, Check, CheckCircle,
7
+ CheckSquare, ChefHat, ChevronsUpDown, Circle, CircleCheck, CircleDollarSign, Clapperboard, ClipboardList,
8
+ Clock, Clock3, Command, Compass, Contact, CreditCard, Disc3, Dog,
9
+ DollarSign, DoorOpen, Egg, ExternalLink, Eye, FileCheck2, FileDown,
10
+ FileText, Filter, Flame, FolderOpen, Globe, GraduationCap, Handshake, Heart,
11
+ Home, Image, Inbox, Instagram, Landmark, Layers, LayoutDashboard, LayoutTemplate,
12
+ Leaf, LeafyGreen, Link, List, ListChecks, ListMusic, ListPlus, Lock,
13
+ Mail, Map, MapPin, Megaphone, MessageCircle, MessageSquare, Mic, MoreHorizontal,
14
+ MousePointerClick, Music, Newspaper, Package, PackageCheck, Palette, PartyPopper, PawPrint,
15
+ Pencil, Percent, Phone, PieChart, Plug, Plus, PlusCircle, Puzzle, Radio,
16
+ Receipt, Repeat, RotateCcw, Ruler, Search, Send, Settings, Shield,
17
+ ShieldCheck, ShoppingBag, ShoppingCart, Sigma, SlidersHorizontal, Sparkles, Star, Tag,
18
+ Tags, Target, ToggleLeft, TreePalm, TrendingDown, TrendingUp, Trophy, Truck,
19
+ User, UserCheck, UserCog, UserPlus, UserX, Users, UsersRound, Utensils,
20
+ UtensilsCrossed, Wallet, Warehouse, Wheat, Workflow, Wrench, X, XCircle,
21
+ Zap,
22
+ } from 'lucide-react'
23
+
24
+ // ---------------------------------------------------------------------------
25
+ // Central lucide icon registry. The SDK's manifest-driven surfaces resolve
26
+ // icons by string name; a namespace import (`import * as LucideIcons`) defeats
27
+ // tree-shaking and drags all ~1,500 icons (~500 KB min) into every bundle, so
28
+ // the SDK ships this curated set instead — the union of every icon name the
29
+ // SDK, plugins, and app templates reference. Apps using names outside the set
30
+ // call registerIcons({ Name: Component }) with their own named imports.
31
+ // ---------------------------------------------------------------------------
32
+
33
+ const registry: Record<string, LucideIcon> = {
34
+ Activity, AlertTriangle, Apple, ArrowDownCircle, ArrowDownRight, ArrowLeftRight, ArrowUpCircle, ArrowUpRight,
35
+ Award, BadgeDollarSign, Ban, Banknote, BarChart3, Bell, Bike, BookOpen,
36
+ BookOpenCheck, Box, Boxes, Briefcase, Building2, Calendar, CalendarCheck, CalendarCheck2,
37
+ CalendarClock, CalendarDays, CalendarPlus, CalendarX, Camera, Cat, Check, CheckCircle,
38
+ CheckSquare, ChefHat, ChevronsUpDown, Circle, CircleCheck, CircleDollarSign, Clapperboard, ClipboardList,
39
+ Clock, Clock3, Command, Compass, Contact, CreditCard, Disc3, Dog,
40
+ DollarSign, DoorOpen, Egg, ExternalLink, Eye, FileCheck2, FileDown,
41
+ FileText, Filter, Flame, FolderOpen, Globe, GraduationCap, Handshake, Heart,
42
+ Home, Image, Inbox, Instagram, Landmark, Layers, LayoutDashboard, LayoutTemplate,
43
+ Leaf, LeafyGreen, Link, List, ListChecks, ListMusic, ListPlus, Lock,
44
+ Mail, Map, MapPin, Megaphone, MessageCircle, MessageSquare, Mic, MoreHorizontal,
45
+ MousePointerClick, Music, Newspaper, Package, PackageCheck, Palette, PartyPopper, PawPrint,
46
+ Pencil, Percent, Phone, PieChart, Plug, Plus, PlusCircle, Puzzle, Radio,
47
+ Receipt, Repeat, RotateCcw, Ruler, Search, Send, Settings, Shield,
48
+ ShieldCheck, ShoppingBag, ShoppingCart, Sigma, SlidersHorizontal, Sparkles, Star, Tag,
49
+ Tags, Target, ToggleLeft, TreePalm, TrendingDown, TrendingUp, Trophy, Truck,
50
+ User, UserCheck, UserCog, UserPlus, UserX, Users, UsersRound, Utensils,
51
+ UtensilsCrossed, Wallet, Warehouse, Wheat, Workflow, Wrench, X, XCircle,
52
+ Zap,
53
+ }
54
+
55
+ /** Add or override icons resolvable by string name (e.g. from app manifests). */
56
+ export function registerIcons(icons: Record<string, LucideIcon>): void {
57
+ Object.assign(registry, icons)
58
+ }
59
+
60
+ /** Resolve a lucide icon by name; undefined when not registered. */
61
+ export function getLucideIcon(name: string): LucideIcon | undefined {
62
+ return registry[name]
63
+ }
64
+
65
+ /** The registered icon map (live reference — do not mutate directly). */
66
+ export const ICON_MAP = registry
package/src/index.ts CHANGED
@@ -228,3 +228,7 @@ export {
228
228
  type ChartType,
229
229
  type ChartSeries,
230
230
  } from './dashboard'
231
+
232
+ // Central lucide icon registry — curated tree-shakable set + escape hatch for
233
+ // apps that need icon names outside it (registerIcons({ Name: Component })).
234
+ export { registerIcons, getLucideIcon } from './icons'
@@ -1,106 +1,10 @@
1
1
  import * as React from 'react'
2
2
  import * as Tooltip from '@radix-ui/react-tooltip'
3
3
  import {
4
- Crown,
5
- ExternalLink,
6
- Home,
7
- Users,
8
- Settings,
9
- CreditCard,
10
- Bell,
11
- Calendar,
12
- CalendarClock,
13
- Package,
14
- Activity,
15
- BarChart3,
16
- FileText,
17
- Mail,
18
- PanelLeftClose,
19
- PanelLeft,
20
- Search,
21
- Shield,
22
- DollarSign,
23
- Megaphone,
24
- Receipt,
25
- ShoppingCart,
26
- ShoppingBag,
27
- Target,
28
- Wrench,
29
- Truck,
30
- ClipboardList,
31
- ListChecks,
32
- Briefcase,
33
- UserCog,
34
- BookOpen,
35
- BookOpenCheck,
36
- MessageCircle,
37
- Globe,
38
- Percent,
39
- Tag,
40
- Tags,
41
- Camera,
42
- UtensilsCrossed,
43
- MapPin,
44
- Map,
45
- Handshake,
46
- Contact,
47
- Building2,
48
- Filter,
49
- Plus,
50
- List,
51
- ListPlus,
52
- ChevronDown,
53
- Ban,
54
- Clock,
55
- Dog,
56
- Cat,
57
- PawPrint,
58
- Heart,
59
- FolderOpen,
60
- LayoutTemplate,
61
- LeafyGreen,
62
- Apple,
63
- Egg,
64
- Wheat,
65
- PartyPopper,
66
- Radio,
67
- CalendarDays,
68
- CalendarCheck2,
69
- CalendarX,
70
- BadgeDollarSign,
71
- Banknote,
72
- Landmark,
73
- CircleDollarSign,
74
- Layers,
75
- Music,
76
- Eye,
77
- ListMusic,
78
- Disc3,
79
- UsersRound,
80
- Mic,
81
- Zap,
82
- Award,
83
- LayoutDashboard,
84
- MessageSquare,
85
- Inbox,
86
- Star,
87
- TrendingUp,
88
- GraduationCap,
89
- Repeat,
90
- UserCheck,
91
- UserPlus,
92
- UserX,
93
- Workflow,
94
- Boxes,
95
- Clock3,
96
- FileCheck2,
97
- User,
98
- Palette,
99
- ShieldCheck,
100
- SlidersHorizontal,
101
- Puzzle,
4
+ Bell, ChevronDown, Crown, ExternalLink, Home, PanelLeft, PanelLeftClose, Search, Settings, User,
102
5
  type LucideIcon,
103
6
  } from 'lucide-react'
7
+ import { ICON_MAP } from '../icons'
104
8
  import { cn } from '../utils/cn'
105
9
  import { useLayoutStore } from '../stores/layout.store'
106
10
 
@@ -166,18 +70,8 @@ export interface SidebarProps {
166
70
  navDirection?: 'forward' | 'back'
167
71
  }
168
72
 
169
- const ICON_MAP: Record<string, LucideIcon> = {
170
- Home, Users, Settings, CreditCard, Bell, Calendar, CalendarClock, Package, Activity, BarChart3,
171
- FileText, Mail, DollarSign, Megaphone, ShoppingCart, Target, Wrench, Truck,
172
- Receipt, ShoppingBag, ClipboardList, ListChecks, Briefcase, UserCog, BookOpen, BookOpenCheck, MessageCircle, Globe,
173
- Percent, Tag, Tags, Camera, UtensilsCrossed, MapPin, Map, Handshake, Contact,
174
- Building2, Filter, Plus, List, ListPlus, Search, Shield, Ban, Clock, Dog, Cat, PawPrint, Heart, FolderOpen, LayoutTemplate, LeafyGreen, Apple, Egg, Wheat,
175
- PartyPopper, Radio, CalendarDays, CalendarCheck2, CalendarX, BadgeDollarSign, Banknote, Landmark, CircleDollarSign, Layers, Music, Eye, ListMusic, Disc3, UsersRound, Mic,
176
- Zap, Award, LayoutDashboard, MessageSquare, Inbox, Star, TrendingUp, UserCheck, UserPlus, UserX, Workflow, Boxes, Clock3, FileCheck2,
177
- GraduationCap, Repeat,
178
- User, Palette, ShieldCheck, SlidersHorizontal, Puzzle,
179
- }
180
-
73
+ // ICON_MAP now lives in ../icons (central curated registry, shared by every
74
+ // string-name icon lookup in the SDK); re-exported here for compat.
181
75
  export { ICON_MAP }
182
76
 
183
77
  /** Kept in sync with --saas-rail-duration in styles.css. */
@@ -28,6 +28,17 @@ function formatDate(date: Date, locale: string) {
28
28
  return date.toLocaleDateString(toDateLocale(locale), { month: 'short', day: 'numeric', year: 'numeric' })
29
29
  }
30
30
 
31
+ /** Toolbar label: the year is noise while you're inside it, and two of these sit
32
+ * side by side in a range — it only earns its space on another year. */
33
+ function formatDateCompact(date: Date, locale: string) {
34
+ const sameYear = date.getFullYear() === new Date().getFullYear()
35
+ return date.toLocaleDateString(toDateLocale(locale), {
36
+ month: 'short',
37
+ day: 'numeric',
38
+ ...(sameYear ? {} : { year: 'numeric' }),
39
+ })
40
+ }
41
+
31
42
  function toDateStr(d: Date) {
32
43
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
33
44
  }
@@ -42,13 +53,24 @@ interface DatePickerProps {
42
53
  value: string
43
54
  onChange: (value: string) => void
44
55
  className?: string
56
+ /**
57
+ * `input` (default) is the form-field trigger. `toolbar` is the 26px pill that
58
+ * matches SegmentedControl/Button `sm`, for filter bars where a full-height
59
+ * form field towers over everything beside it.
60
+ */
61
+ variant?: 'input' | 'toolbar'
45
62
  /** Open the dropdown immediately on mount */
46
63
  defaultOpen?: boolean
47
64
  /** Called when the dropdown opens or closes */
48
65
  onOpenChange?: (open: boolean) => void
49
66
  }
50
67
 
51
- export function DatePicker({ value, onChange, className, defaultOpen, onOpenChange }: DatePickerProps) {
68
+ const TRIGGER_VARIANT: Record<'input' | 'toolbar', string> = {
69
+ input: 'rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-3 py-2 text-sm w-full',
70
+ toolbar: 'h-[26px] rounded-button border border-border bg-card shadow-button px-2.5 text-xs font-medium',
71
+ }
72
+
73
+ export function DatePicker({ value, onChange, className, variant = 'input', defaultOpen, onOpenChange }: DatePickerProps) {
52
74
  const t = useTranslation()
53
75
  const locale = getCurrentLocale()
54
76
  const [open, setOpen] = useState(defaultOpen ?? false)
@@ -129,9 +151,13 @@ export function DatePicker({ value, onChange, className, defaultOpen, onOpenChan
129
151
  <div ref={ref} className={`relative ${className ?? ''}`}>
130
152
  {/* Trigger */}
131
153
  <button ref={triggerRef} type="button" onClick={() => setOpen((p) => !p)}
132
- className="flex items-center gap-2 rounded-input border border-input bg-card shadow-[inset_0_1px_0_rgb(0_0_0_/0.06)] px-3 py-2 text-sm hover:bg-muted/30 transition-colors w-full text-left">
133
- <Calendar className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
134
- <span>{value ? formatDate(selectedDate, locale) : t('common.selectDate')}</span>
154
+ className={`flex items-center gap-2 text-left transition-colors hover:bg-muted/30 ${TRIGGER_VARIANT[variant]}`}>
155
+ <Calendar className={`shrink-0 text-muted-foreground ${variant === 'toolbar' ? 'h-3 w-3' : 'h-3.5 w-3.5'}`} />
156
+ <span className="whitespace-nowrap">
157
+ {value
158
+ ? (variant === 'toolbar' ? formatDateCompact : formatDate)(selectedDate, locale)
159
+ : t('common.selectDate')}
160
+ </span>
135
161
  </button>
136
162
 
137
163
  {/* Dropdown — portal to escape overflow containers */}
@@ -1,206 +0,0 @@
1
- 'use strict';
2
-
3
- // src/theme/preset.ts
4
- var fayzUiPreset = {
5
- darkMode: "class",
6
- theme: {
7
- extend: {
8
- colors: {
9
- border: "hsl(var(--border))",
10
- input: "hsl(var(--input))",
11
- ring: "hsl(var(--ring))",
12
- background: "hsl(var(--background))",
13
- foreground: "hsl(var(--foreground))",
14
- primary: {
15
- DEFAULT: "hsl(var(--primary))",
16
- foreground: "hsl(var(--primary-foreground))"
17
- },
18
- secondary: {
19
- DEFAULT: "hsl(var(--secondary))",
20
- foreground: "hsl(var(--secondary-foreground))"
21
- },
22
- destructive: {
23
- DEFAULT: "hsl(var(--destructive))",
24
- foreground: "hsl(var(--destructive-foreground))"
25
- },
26
- success: {
27
- DEFAULT: "hsl(var(--success))",
28
- foreground: "hsl(var(--success-foreground))"
29
- },
30
- warning: {
31
- DEFAULT: "hsl(var(--warning))",
32
- foreground: "hsl(var(--warning-foreground))"
33
- },
34
- info: {
35
- DEFAULT: "hsl(var(--info))",
36
- foreground: "hsl(var(--info-foreground))"
37
- },
38
- magic: {
39
- DEFAULT: "hsl(var(--magic))",
40
- foreground: "hsl(var(--magic-foreground))"
41
- },
42
- "info-soft": {
43
- DEFAULT: "hsl(var(--info-soft))",
44
- foreground: "hsl(var(--info-soft-foreground))"
45
- },
46
- "success-soft": {
47
- DEFAULT: "hsl(var(--success-soft))",
48
- foreground: "hsl(var(--success-soft-foreground))"
49
- },
50
- "warning-soft": {
51
- DEFAULT: "hsl(var(--warning-soft))",
52
- foreground: "hsl(var(--warning-soft-foreground))"
53
- },
54
- "destructive-soft": {
55
- DEFAULT: "hsl(var(--destructive-soft))",
56
- foreground: "hsl(var(--destructive-soft-foreground))"
57
- },
58
- "magic-soft": {
59
- DEFAULT: "hsl(var(--magic-soft))",
60
- foreground: "hsl(var(--magic-soft-foreground))"
61
- },
62
- muted: {
63
- DEFAULT: "hsl(var(--muted))",
64
- foreground: "hsl(var(--muted-foreground))"
65
- },
66
- accent: {
67
- DEFAULT: "hsl(var(--accent))",
68
- foreground: "hsl(var(--accent-foreground))"
69
- },
70
- card: {
71
- DEFAULT: "hsl(var(--card))",
72
- foreground: "hsl(var(--card-foreground))"
73
- },
74
- popover: {
75
- DEFAULT: "hsl(var(--popover))",
76
- foreground: "hsl(var(--popover-foreground))"
77
- },
78
- // Layout surface tokens
79
- sidebar: {
80
- DEFAULT: "hsl(var(--sidebar))",
81
- foreground: "hsl(var(--sidebar-foreground))",
82
- border: "hsl(var(--sidebar-border))",
83
- accent: "hsl(var(--sidebar-accent))",
84
- "accent-foreground": "hsl(var(--sidebar-accent-foreground))",
85
- muted: "hsl(var(--sidebar-muted))"
86
- },
87
- content: "hsl(var(--content))"
88
- },
89
- borderRadius: {
90
- button: "var(--button-radius)",
91
- card: "var(--card-radius)",
92
- input: "var(--input-radius)",
93
- modal: "var(--modal-radius)"
94
- },
95
- fontFamily: {
96
- sans: ["var(--font-family)"],
97
- mono: ["var(--font-family-mono)"]
98
- },
99
- boxShadow: {
100
- sm: "var(--shadow-sm)",
101
- md: "var(--shadow-md)",
102
- lg: "var(--shadow-lg)",
103
- button: "var(--shadow-button)",
104
- "button-primary": "var(--shadow-button-primary)",
105
- "button-inset": "var(--shadow-button-inset)"
106
- },
107
- keyframes: {
108
- "fade-in": {
109
- from: { opacity: "0" },
110
- to: { opacity: "1" }
111
- },
112
- "fade-out": {
113
- from: { opacity: "1" },
114
- to: { opacity: "0" }
115
- },
116
- "zoom-in": {
117
- from: { transform: "scale(0.95)", opacity: "0" },
118
- to: { transform: "scale(1)", opacity: "1" }
119
- },
120
- "zoom-out": {
121
- from: { transform: "scale(1)", opacity: "1" },
122
- to: { transform: "scale(0.95)", opacity: "0" }
123
- },
124
- "slide-in-from-top": {
125
- from: { transform: "translateY(-4px)", opacity: "0" },
126
- to: { transform: "translateY(0)", opacity: "1" }
127
- },
128
- "slide-in-from-bottom": {
129
- from: { transform: "translateY(4px)", opacity: "0" },
130
- to: { transform: "translateY(0)", opacity: "1" }
131
- },
132
- "slide-out-to-top": {
133
- from: { transform: "translateY(0)", opacity: "1" },
134
- to: { transform: "translateY(-4px)", opacity: "0" }
135
- },
136
- "page-in": {
137
- from: { opacity: "0", transform: "translateY(6px)" },
138
- to: { opacity: "1", transform: "translateY(0)" }
139
- },
140
- "slide-in-from-right": {
141
- from: { transform: "translateX(100%)" },
142
- to: { transform: "translateX(0)" }
143
- },
144
- "slide-out-to-right": {
145
- from: { transform: "translateX(0)" },
146
- to: { transform: "translateX(100%)" }
147
- },
148
- "fade-up": {
149
- from: { opacity: "0", transform: "translateY(18px)" },
150
- to: { opacity: "1", transform: "translateY(0)" }
151
- },
152
- kenburns: {
153
- from: { transform: "scale(1)" },
154
- to: { transform: "scale(1.07)" }
155
- },
156
- "badge-pop": {
157
- "0%": { transform: "scale(0.6)" },
158
- "60%": { transform: "scale(1.25)" },
159
- "100%": { transform: "scale(1)" }
160
- },
161
- "draw-check": {
162
- from: { "stroke-dashoffset": "48" },
163
- to: { "stroke-dashoffset": "0" }
164
- },
165
- "pop-in": {
166
- "0%": { transform: "scale(0)", opacity: "0" },
167
- "70%": { transform: "scale(1.15)", opacity: "1" },
168
- "100%": { transform: "scale(1)", opacity: "1" }
169
- },
170
- "confetti-fall": {
171
- "0%": { transform: "translateY(-10px) rotate(0deg)", opacity: "1" },
172
- "100%": { transform: "translateY(140px) rotate(540deg)", opacity: "0" }
173
- },
174
- "pulse-soft": {
175
- "0%, 100%": { opacity: "1" },
176
- "50%": { opacity: "0.55" }
177
- }
178
- },
179
- animation: {
180
- "fade-in": "fade-in 200ms ease-out",
181
- "fade-out": "fade-out 150ms ease-in",
182
- "zoom-in": "zoom-in 200ms ease-out",
183
- "zoom-out": "zoom-out 150ms ease-in",
184
- "slide-in-from-top": "slide-in-from-top 200ms ease-out",
185
- "slide-in-from-bottom": "slide-in-from-bottom 200ms ease-out",
186
- "slide-out-to-top": "slide-out-to-top 150ms ease-in",
187
- "slide-in-from-right": "slide-in-from-right 250ms cubic-bezier(0.16, 1, 0.3, 1)",
188
- "slide-out-to-right": "slide-out-to-right 200ms ease-in",
189
- "page-in": "page-in 250ms ease-out",
190
- "fade-up": "fade-up 600ms cubic-bezier(0.16, 1, 0.3, 1) both",
191
- kenburns: "kenburns 9s ease-out both",
192
- "badge-pop": "badge-pop 350ms cubic-bezier(0.34, 1.56, 0.64, 1)",
193
- "draw-check": "draw-check 600ms ease-out 250ms both",
194
- "pop-in": "pop-in 450ms cubic-bezier(0.34, 1.56, 0.64, 1) both",
195
- "confetti-fall": "confetti-fall 1100ms ease-in both",
196
- "pulse-soft": "pulse-soft 1.6s ease-in-out infinite"
197
- }
198
- }
199
- }
200
- };
201
- var preset_default = fayzUiPreset;
202
-
203
- exports.fayzUiPreset = fayzUiPreset;
204
- exports.preset_default = preset_default;
205
- //# sourceMappingURL=chunk-2P7T6QQK.cjs.map
206
- //# sourceMappingURL=chunk-2P7T6QQK.cjs.map