@snapdragonsnursery/react-components 1.6.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -1
- package/src/ChildSearchModal.jsx +38 -0
- package/src/ChildSearchPage.jsx +51 -0
- package/src/EmployeeSearchModal.jsx +86 -36
- package/src/EmployeeSearchPage.jsx +52 -1
- package/src/EmployeeSearchPage.test.jsx +1 -254
- package/src/components/app-sidebar.jsx +205 -0
- package/src/components/nav-main.jsx +60 -0
- package/src/components/nav-projects.jsx +76 -0
- package/src/components/nav-user.jsx +104 -0
- package/src/components/room-switcher.jsx +116 -0
- package/src/components/site-switcher.jsx +116 -0
- package/src/components/team-switcher.jsx +83 -0
- package/src/components/theme-mode-toggle.jsx +62 -0
- package/src/components/ui/avatar.jsx +47 -0
- package/src/components/ui/breadcrumb.jsx +112 -0
- package/src/components/ui/collapsible.jsx +23 -0
- package/src/components/ui/date-range-picker.jsx +2 -0
- package/src/components/ui/dropdown-menu.jsx +221 -0
- package/src/components/ui/separator.jsx +25 -0
- package/src/components/ui/sheet.jsx +140 -0
- package/src/components/ui/sidebar.jsx +681 -0
- package/src/components/ui/skeleton.jsx +15 -0
- package/src/components/ui/stat-card.jsx +100 -0
- package/src/components/ui/stat-card.test.jsx +24 -0
- package/src/components/ui/tooltip.jsx +53 -0
- package/src/hooks/use-current-site.js +61 -0
- package/src/hooks/use-mobile.js +19 -0
- package/src/index.css +44 -0
- package/src/index.d.ts +87 -1
- package/src/index.js +71 -22
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Stat Card UI Component (shared library)
|
|
2
|
+
// Reusable statistic card with optional icon and caption.
|
|
3
|
+
// Example:
|
|
4
|
+
// <StatCard title="Active Users" value="97K" caption="+24.3% this month" icon={ArrowTrendingUpIcon} tone="success" />
|
|
5
|
+
|
|
6
|
+
import React from 'react'
|
|
7
|
+
import { cn } from '../../lib/utils'
|
|
8
|
+
|
|
9
|
+
// Lightweight Card primitives aligned with this package styling
|
|
10
|
+
const Card = React.forwardRef(function Card({ className, ...props }, ref) {
|
|
11
|
+
return (
|
|
12
|
+
<div
|
|
13
|
+
ref={ref}
|
|
14
|
+
className={cn('rounded-lg border bg-card text-card-foreground shadow-sm', className)}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const CardHeader = React.forwardRef(function CardHeader({ className, ...props }, ref) {
|
|
21
|
+
return <div ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const CardTitle = React.forwardRef(function CardTitle({ className, ...props }, ref) {
|
|
25
|
+
return (
|
|
26
|
+
<h3
|
|
27
|
+
ref={ref}
|
|
28
|
+
className={cn('text-2xl font-semibold leading-none tracking-tight', className)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const CardContent = React.forwardRef(function CardContent({ className, ...props }, ref) {
|
|
35
|
+
return <div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
function Skeleton({ className, ...props }) {
|
|
39
|
+
return <div className={cn('animate-pulse rounded-md bg-muted', className)} {...props} />
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const toneClasses = {
|
|
43
|
+
default: {
|
|
44
|
+
badge: 'bg-gray-100 text-gray-700',
|
|
45
|
+
value: 'text-foreground',
|
|
46
|
+
ring: 'ring-gray-200',
|
|
47
|
+
},
|
|
48
|
+
success: {
|
|
49
|
+
badge: 'bg-emerald-100 text-emerald-700',
|
|
50
|
+
value: 'text-emerald-700',
|
|
51
|
+
ring: 'ring-emerald-200',
|
|
52
|
+
},
|
|
53
|
+
danger: {
|
|
54
|
+
badge: 'bg-rose-100 text-rose-700',
|
|
55
|
+
value: 'text-rose-700',
|
|
56
|
+
ring: 'ring-rose-200',
|
|
57
|
+
},
|
|
58
|
+
warning: {
|
|
59
|
+
badge: 'bg-amber-100 text-amber-700',
|
|
60
|
+
value: 'text-amber-700',
|
|
61
|
+
ring: 'ring-amber-200',
|
|
62
|
+
},
|
|
63
|
+
info: {
|
|
64
|
+
badge: 'bg-sky-100 text-sky-700',
|
|
65
|
+
value: 'text-sky-700',
|
|
66
|
+
ring: 'ring-sky-200',
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function StatCard({ title, value, caption, icon: Icon, tone = 'default', className, loading = false }) {
|
|
71
|
+
const styles = toneClasses[tone] || toneClasses.default
|
|
72
|
+
return (
|
|
73
|
+
<Card className={cn('shadow-sm hover:shadow transition-shadow', className)}>
|
|
74
|
+
<CardHeader className="pb-3">
|
|
75
|
+
<div className="flex items-center justify-between">
|
|
76
|
+
<CardTitle className="text-sm font-medium text-muted-foreground">
|
|
77
|
+
{loading ? <Skeleton className="h-4 w-24" /> : title}
|
|
78
|
+
</CardTitle>
|
|
79
|
+
{Icon ? (
|
|
80
|
+
<div className={cn('inline-flex h-10 w-10 items-center justify-center rounded-full ring-1', styles.badge, styles.ring)}>
|
|
81
|
+
{loading ? <Skeleton className="h-5 w-5 rounded-full" /> : <Icon className="h-5 w-5" />}
|
|
82
|
+
</div>
|
|
83
|
+
) : null}
|
|
84
|
+
</div>
|
|
85
|
+
</CardHeader>
|
|
86
|
+
<CardContent>
|
|
87
|
+
<div className={cn('text-3xl font-extrabold tracking-tight', styles.value)}>
|
|
88
|
+
{loading ? <Skeleton className="h-8 w-20" /> : value}
|
|
89
|
+
</div>
|
|
90
|
+
{caption ? (
|
|
91
|
+
<div className="mt-1 text-sm text-muted-foreground">
|
|
92
|
+
{loading ? <Skeleton className="h-4 w-28" /> : caption}
|
|
93
|
+
</div>
|
|
94
|
+
) : null}
|
|
95
|
+
</CardContent>
|
|
96
|
+
</Card>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export default StatCard
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Basic render tests for StatCard
|
|
2
|
+
// Example usage demonstrated in the component file header.
|
|
3
|
+
|
|
4
|
+
import React from 'react'
|
|
5
|
+
import { render, screen } from '@testing-library/react'
|
|
6
|
+
import StatCard from './stat-card'
|
|
7
|
+
|
|
8
|
+
describe('StatCard (library)', () => {
|
|
9
|
+
it('renders title and value', () => {
|
|
10
|
+
render(<StatCard title="Total" value={42} caption="units" />)
|
|
11
|
+
expect(screen.getByText('Total')).toBeInTheDocument()
|
|
12
|
+
expect(screen.getByText('42')).toBeInTheDocument()
|
|
13
|
+
expect(screen.getByText('units')).toBeInTheDocument()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('renders skeletons when loading', () => {
|
|
17
|
+
const { container } = render(<StatCard title="Total" value={42} caption="units" loading />)
|
|
18
|
+
expect(screen.queryByText('Total')).toBeNull()
|
|
19
|
+
expect(screen.queryByText('42')).toBeNull()
|
|
20
|
+
expect(screen.queryByText('units')).toBeNull()
|
|
21
|
+
// Skeletons exist
|
|
22
|
+
expect(container.querySelectorAll('.animate-pulse').length).toBeGreaterThan(0)
|
|
23
|
+
})
|
|
24
|
+
})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
|
3
|
+
|
|
4
|
+
import { cn } from "../../lib/utils"
|
|
5
|
+
|
|
6
|
+
function TooltipProvider({
|
|
7
|
+
delayDuration = 0,
|
|
8
|
+
...props
|
|
9
|
+
}) {
|
|
10
|
+
return (<TooltipPrimitive.Provider data-slot="tooltip-provider" delayDuration={delayDuration} {...props} />);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function Tooltip({
|
|
14
|
+
...props
|
|
15
|
+
}) {
|
|
16
|
+
return (
|
|
17
|
+
<TooltipProvider>
|
|
18
|
+
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
|
19
|
+
</TooltipProvider>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function TooltipTrigger({
|
|
24
|
+
...props
|
|
25
|
+
}) {
|
|
26
|
+
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function TooltipContent({
|
|
30
|
+
className,
|
|
31
|
+
sideOffset = 0,
|
|
32
|
+
children,
|
|
33
|
+
...props
|
|
34
|
+
}) {
|
|
35
|
+
return (
|
|
36
|
+
<TooltipPrimitive.Portal>
|
|
37
|
+
<TooltipPrimitive.Content
|
|
38
|
+
data-slot="tooltip-content"
|
|
39
|
+
sideOffset={sideOffset}
|
|
40
|
+
className={cn(
|
|
41
|
+
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
|
42
|
+
className
|
|
43
|
+
)}
|
|
44
|
+
{...props}>
|
|
45
|
+
{children}
|
|
46
|
+
<TooltipPrimitive.Arrow
|
|
47
|
+
className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
|
|
48
|
+
</TooltipPrimitive.Content>
|
|
49
|
+
</TooltipPrimitive.Portal>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
export const SITE_STORAGE_KEY = "current_site_id"
|
|
4
|
+
export const SITE_EVENT_NAME = "siteChanged"
|
|
5
|
+
|
|
6
|
+
export function readCurrentSiteId(storageKey = SITE_STORAGE_KEY) {
|
|
7
|
+
if (typeof window === "undefined") return null
|
|
8
|
+
try {
|
|
9
|
+
const v = window.localStorage.getItem(storageKey)
|
|
10
|
+
if (v == null) return null
|
|
11
|
+
const n = Number(v)
|
|
12
|
+
return Number.isNaN(n) ? v : n
|
|
13
|
+
} catch {
|
|
14
|
+
return null
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function writeCurrentSiteId(siteId, storageKey = SITE_STORAGE_KEY) {
|
|
19
|
+
if (typeof window === "undefined") return
|
|
20
|
+
try {
|
|
21
|
+
if (siteId == null) {
|
|
22
|
+
window.localStorage.removeItem(storageKey)
|
|
23
|
+
} else {
|
|
24
|
+
window.localStorage.setItem(storageKey, String(siteId))
|
|
25
|
+
}
|
|
26
|
+
} catch {}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const numeric = typeof siteId === "number" ? siteId : Number(siteId)
|
|
30
|
+
const detail = { siteId: Number.isFinite(numeric) ? numeric : siteId }
|
|
31
|
+
window.dispatchEvent(new CustomEvent(SITE_EVENT_NAME, { detail }))
|
|
32
|
+
} catch {}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function useCurrentSiteId({ storageKey = SITE_STORAGE_KEY, eventName = SITE_EVENT_NAME } = {}) {
|
|
36
|
+
const [currentSiteId, setCurrentSiteId] = React.useState(null)
|
|
37
|
+
|
|
38
|
+
React.useEffect(() => {
|
|
39
|
+
// Initialize from storage on mount
|
|
40
|
+
const initial = readCurrentSiteId(storageKey)
|
|
41
|
+
setCurrentSiteId(initial)
|
|
42
|
+
|
|
43
|
+
// Listen for global site changes
|
|
44
|
+
const handler = (e) => {
|
|
45
|
+
try {
|
|
46
|
+
const id = e?.detail?.siteId
|
|
47
|
+
if (typeof id !== "undefined") setCurrentSiteId(id)
|
|
48
|
+
} catch {}
|
|
49
|
+
}
|
|
50
|
+
window.addEventListener(eventName, handler)
|
|
51
|
+
return () => window.removeEventListener(eventName, handler)
|
|
52
|
+
}, [storageKey, eventName])
|
|
53
|
+
|
|
54
|
+
const update = React.useCallback((id) => {
|
|
55
|
+
setCurrentSiteId(id)
|
|
56
|
+
writeCurrentSiteId(id, storageKey)
|
|
57
|
+
}, [storageKey])
|
|
58
|
+
|
|
59
|
+
return [currentSiteId, update]
|
|
60
|
+
}
|
|
61
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
const MOBILE_BREAKPOINT = 768
|
|
4
|
+
|
|
5
|
+
export function useIsMobile() {
|
|
6
|
+
const [isMobile, setIsMobile] = React.useState(undefined)
|
|
7
|
+
|
|
8
|
+
React.useEffect(() => {
|
|
9
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
|
10
|
+
const onChange = () => {
|
|
11
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
12
|
+
}
|
|
13
|
+
mql.addEventListener("change", onChange)
|
|
14
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
15
|
+
return () => mql.removeEventListener("change", onChange);
|
|
16
|
+
}, [])
|
|
17
|
+
|
|
18
|
+
return !!isMobile
|
|
19
|
+
}
|
package/src/index.css
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
@tailwind base;
|
|
2
|
+
|
|
3
|
+
@custom-variant dark (&:is(.dark *));
|
|
2
4
|
@tailwind components;
|
|
3
5
|
@tailwind utilities;
|
|
4
6
|
|
|
@@ -56,4 +58,46 @@
|
|
|
56
58
|
body {
|
|
57
59
|
@apply bg-background text-foreground;
|
|
58
60
|
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
:root {
|
|
64
|
+
--sidebar: hsl(0 0% 98%);
|
|
65
|
+
--sidebar-foreground: hsl(240 5.3% 26.1%);
|
|
66
|
+
--sidebar-primary: hsl(240 5.9% 10%);
|
|
67
|
+
--sidebar-primary-foreground: hsl(0 0% 98%);
|
|
68
|
+
--sidebar-accent: hsl(240 4.8% 95.9%);
|
|
69
|
+
--sidebar-accent-foreground: hsl(240 5.9% 10%);
|
|
70
|
+
--sidebar-border: hsl(220 13% 91%);
|
|
71
|
+
--sidebar-ring: hsl(217.2 91.2% 59.8%);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.dark {
|
|
75
|
+
--sidebar: hsl(240 5.9% 10%);
|
|
76
|
+
--sidebar-foreground: hsl(240 4.8% 95.9%);
|
|
77
|
+
--sidebar-primary: hsl(224.3 76.3% 48%);
|
|
78
|
+
--sidebar-primary-foreground: hsl(0 0% 100%);
|
|
79
|
+
--sidebar-accent: hsl(240 3.7% 15.9%);
|
|
80
|
+
--sidebar-accent-foreground: hsl(240 4.8% 95.9%);
|
|
81
|
+
--sidebar-border: hsl(240 3.7% 15.9%);
|
|
82
|
+
--sidebar-ring: hsl(217.2 91.2% 59.8%);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@theme inline {
|
|
86
|
+
--color-sidebar: var(--sidebar);
|
|
87
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
88
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
89
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
90
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
91
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
92
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
93
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@layer base {
|
|
97
|
+
* {
|
|
98
|
+
@apply border-border outline-ring/50;
|
|
99
|
+
}
|
|
100
|
+
body {
|
|
101
|
+
@apply bg-background text-foreground;
|
|
102
|
+
}
|
|
59
103
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -36,13 +36,99 @@ export const EmployeeSearchDemo: React.ComponentType<any>
|
|
|
36
36
|
export const EmployeeSearchFilters: React.ComponentType<any>
|
|
37
37
|
|
|
38
38
|
export const DateRangePicker: React.ComponentType<any>
|
|
39
|
-
export
|
|
39
|
+
export interface DatePickerProps {
|
|
40
|
+
selectedDate?: Date | null
|
|
41
|
+
onSelect: (date: Date | null) => void
|
|
42
|
+
className?: string
|
|
43
|
+
placeholder?: string
|
|
44
|
+
disabled?: boolean
|
|
45
|
+
disableFuture?: boolean
|
|
46
|
+
}
|
|
47
|
+
export const DatePicker: React.ComponentType<DatePickerProps>
|
|
40
48
|
export const Calendar: React.ComponentType<any>
|
|
41
49
|
export const SimpleCalendar: React.ComponentType<any>
|
|
42
50
|
export const Popover: React.ComponentType<any>
|
|
43
51
|
export const PopoverContent: React.ComponentType<any>
|
|
44
52
|
export const PopoverTrigger: React.ComponentType<any>
|
|
45
53
|
|
|
54
|
+
export interface StatCardProps {
|
|
55
|
+
title: string
|
|
56
|
+
value: React.ReactNode
|
|
57
|
+
caption?: React.ReactNode
|
|
58
|
+
icon?: React.ComponentType<any>
|
|
59
|
+
tone?: 'default' | 'success' | 'danger' | 'warning' | 'info'
|
|
60
|
+
className?: string
|
|
61
|
+
loading?: boolean
|
|
62
|
+
}
|
|
63
|
+
export const StatCard: React.ComponentType<StatCardProps>
|
|
64
|
+
|
|
46
65
|
export function configureTelemetry(...args: any[]): any
|
|
47
66
|
|
|
48
67
|
|
|
68
|
+
// Sidebar + UI exports
|
|
69
|
+
export const AppSidebar: React.ComponentType<any>
|
|
70
|
+
export const Sidebar: React.ComponentType<any>
|
|
71
|
+
export const SidebarContent: React.ComponentType<any>
|
|
72
|
+
export const SidebarFooter: React.ComponentType<any>
|
|
73
|
+
export const SidebarGroup: React.ComponentType<any>
|
|
74
|
+
export const SidebarGroupAction: React.ComponentType<any>
|
|
75
|
+
export const SidebarGroupContent: React.ComponentType<any>
|
|
76
|
+
export const SidebarGroupLabel: React.ComponentType<any>
|
|
77
|
+
export const SidebarHeader: React.ComponentType<any>
|
|
78
|
+
export const SidebarInput: React.ComponentType<any>
|
|
79
|
+
export const SidebarInset: React.ComponentType<any>
|
|
80
|
+
export const SidebarMenu: React.ComponentType<any>
|
|
81
|
+
export const SidebarMenuAction: React.ComponentType<any>
|
|
82
|
+
export const SidebarMenuBadge: React.ComponentType<any>
|
|
83
|
+
export const SidebarMenuButton: React.ComponentType<any>
|
|
84
|
+
export const SidebarMenuItem: React.ComponentType<any>
|
|
85
|
+
export const SidebarMenuSkeleton: React.ComponentType<any>
|
|
86
|
+
export const SidebarMenuSub: React.ComponentType<any>
|
|
87
|
+
export const SidebarMenuSubButton: React.ComponentType<any>
|
|
88
|
+
export const SidebarMenuSubItem: React.ComponentType<any>
|
|
89
|
+
export const SidebarProvider: React.ComponentType<any>
|
|
90
|
+
export const SidebarRail: React.ComponentType<any>
|
|
91
|
+
export const SidebarSeparator: React.ComponentType<any>
|
|
92
|
+
export const SidebarTrigger: React.ComponentType<any>
|
|
93
|
+
export function useSidebar(): any
|
|
94
|
+
|
|
95
|
+
export const Separator: React.ComponentType<any>
|
|
96
|
+
export const Breadcrumb: React.ComponentType<any>
|
|
97
|
+
export const BreadcrumbItem: React.ComponentType<any>
|
|
98
|
+
export const BreadcrumbLink: React.ComponentType<any>
|
|
99
|
+
export const BreadcrumbList: React.ComponentType<any>
|
|
100
|
+
export const BreadcrumbPage: React.ComponentType<any>
|
|
101
|
+
export const BreadcrumbSeparator: React.ComponentType<any>
|
|
102
|
+
export const BreadcrumbEllipsis: React.ComponentType<any>
|
|
103
|
+
|
|
104
|
+
// Switchers
|
|
105
|
+
export interface SwitcherItem {
|
|
106
|
+
id?: string | number
|
|
107
|
+
name: string
|
|
108
|
+
icon?: React.ComponentType<any>
|
|
109
|
+
logo?: React.ComponentType<any>
|
|
110
|
+
}
|
|
111
|
+
export interface SiteSwitcherProps {
|
|
112
|
+
items?: SwitcherItem[]
|
|
113
|
+
activeId?: string | number
|
|
114
|
+
onChange?: (item: SwitcherItem) => void
|
|
115
|
+
label?: string
|
|
116
|
+
isLoading?: boolean
|
|
117
|
+
}
|
|
118
|
+
export interface RoomSwitcherProps {
|
|
119
|
+
items?: SwitcherItem[]
|
|
120
|
+
activeId?: string | number
|
|
121
|
+
onChange?: (item: SwitcherItem) => void
|
|
122
|
+
label?: string
|
|
123
|
+
isLoading?: boolean
|
|
124
|
+
baseColor?: string
|
|
125
|
+
}
|
|
126
|
+
export const SiteSwitcher: React.ComponentType<SiteSwitcherProps>
|
|
127
|
+
export const RoomSwitcher: React.ComponentType<RoomSwitcherProps>
|
|
128
|
+
|
|
129
|
+
// Site selection helpers
|
|
130
|
+
export const SITE_STORAGE_KEY: string
|
|
131
|
+
export const SITE_EVENT_NAME: string
|
|
132
|
+
export function readCurrentSiteId(storageKey?: string): string | number | null
|
|
133
|
+
export function writeCurrentSiteId(siteId: string | number | null, storageKey?: string): void
|
|
134
|
+
export function useCurrentSiteId(options?: { storageKey?: string; eventName?: string }): [string | number | null, (id: string | number | null) => void]
|
package/src/index.js
CHANGED
|
@@ -1,27 +1,76 @@
|
|
|
1
|
-
export { default as AuthButtons } from "./AuthButtons";
|
|
2
|
-
export { default as ThemeToggle } from "./ThemeToggle";
|
|
3
|
-
export { default as ChildSearchModal } from "./ChildSearchModal";
|
|
4
|
-
export { default as ChildSearchPage } from "./ChildSearchPage";
|
|
5
|
-
export { default as ChildSearchPageDemo } from "./ChildSearchPageDemo";
|
|
6
|
-
export { default as ThemeToggleTest } from "./ThemeToggleTest";
|
|
7
|
-
export { default as LandingPage } from "./LandingPage";
|
|
8
|
-
export { default as ChildSearchFilters } from "./components/ChildSearchFilters";
|
|
9
|
-
export { default as DateRangePickerDemo } from "./DateRangePickerDemo";
|
|
10
|
-
export { default as CalendarDemo } from "./CalendarDemo";
|
|
11
|
-
export { default as DateRangePickerTest } from "./DateRangePickerTest";
|
|
12
|
-
export { default as ApplyButtonDemo } from "./ApplyButtonDemo";
|
|
1
|
+
export { default as AuthButtons } from "./AuthButtons.jsx";
|
|
2
|
+
export { default as ThemeToggle } from "./ThemeToggle.jsx";
|
|
3
|
+
export { default as ChildSearchModal } from "./ChildSearchModal.jsx";
|
|
4
|
+
export { default as ChildSearchPage } from "./ChildSearchPage.jsx";
|
|
5
|
+
export { default as ChildSearchPageDemo } from "./ChildSearchPageDemo.jsx";
|
|
6
|
+
export { default as ThemeToggleTest } from "./ThemeToggleTest.jsx";
|
|
7
|
+
export { default as LandingPage } from "./LandingPage.jsx";
|
|
8
|
+
export { default as ChildSearchFilters } from "./components/ChildSearchFilters.jsx";
|
|
9
|
+
export { default as DateRangePickerDemo } from "./DateRangePickerDemo.jsx";
|
|
10
|
+
export { default as CalendarDemo } from "./CalendarDemo.jsx";
|
|
11
|
+
export { default as DateRangePickerTest } from "./DateRangePickerTest.jsx";
|
|
12
|
+
export { default as ApplyButtonDemo } from "./ApplyButtonDemo.jsx";
|
|
13
13
|
|
|
14
14
|
// Employee Search Components
|
|
15
|
-
export { default as EmployeeSearchPage } from "./EmployeeSearchPage";
|
|
16
|
-
export { default as EmployeeSearchModal } from "./EmployeeSearchModal";
|
|
17
|
-
export { default as EmployeeSearchDemo } from "./EmployeeSearchDemo";
|
|
18
|
-
export { default as EmployeeSearchFilters } from "./components/EmployeeSearchFilters";
|
|
15
|
+
export { default as EmployeeSearchPage } from "./EmployeeSearchPage.jsx";
|
|
16
|
+
export { default as EmployeeSearchModal } from "./EmployeeSearchModal.jsx";
|
|
17
|
+
export { default as EmployeeSearchDemo } from "./EmployeeSearchDemo.jsx";
|
|
18
|
+
export { default as EmployeeSearchFilters } from "./components/EmployeeSearchFilters.jsx";
|
|
19
19
|
|
|
20
|
-
export { configureTelemetry } from "./telemetry";
|
|
20
|
+
export { configureTelemetry } from "./telemetry.js";
|
|
21
21
|
|
|
22
22
|
// UI Components
|
|
23
|
-
export { DateRangePicker, DatePicker } from "./components/ui/date-range-picker";
|
|
24
|
-
export { Calendar } from "./components/ui/calendar";
|
|
25
|
-
export { SimpleCalendar } from "./components/ui/simple-calendar";
|
|
26
|
-
export { Popover, PopoverContent, PopoverTrigger } from "./components/ui/popover";
|
|
27
|
-
export { default as SoftWarningAlert } from "./components/ui/soft-warning-alert";
|
|
23
|
+
export { DateRangePicker, DatePicker } from "./components/ui/date-range-picker.jsx";
|
|
24
|
+
export { Calendar } from "./components/ui/calendar.jsx";
|
|
25
|
+
export { SimpleCalendar } from "./components/ui/simple-calendar.jsx";
|
|
26
|
+
export { Popover, PopoverContent, PopoverTrigger } from "./components/ui/popover.jsx";
|
|
27
|
+
export { default as SoftWarningAlert } from "./components/ui/soft-warning-alert.jsx";
|
|
28
|
+
export { default as StatCard } from "./components/ui/stat-card.jsx";
|
|
29
|
+
|
|
30
|
+
// Shadcn Sidebar + related UI
|
|
31
|
+
export { AppSidebar } from "./components/app-sidebar.jsx";
|
|
32
|
+
export { SiteSwitcher } from "./components/site-switcher.jsx";
|
|
33
|
+
export { RoomSwitcher } from "./components/room-switcher.jsx";
|
|
34
|
+
export {
|
|
35
|
+
useCurrentSiteId,
|
|
36
|
+
readCurrentSiteId,
|
|
37
|
+
writeCurrentSiteId,
|
|
38
|
+
SITE_STORAGE_KEY,
|
|
39
|
+
SITE_EVENT_NAME,
|
|
40
|
+
} from "./hooks/use-current-site.js";
|
|
41
|
+
export {
|
|
42
|
+
Sidebar,
|
|
43
|
+
SidebarContent,
|
|
44
|
+
SidebarFooter,
|
|
45
|
+
SidebarGroup,
|
|
46
|
+
SidebarGroupAction,
|
|
47
|
+
SidebarGroupContent,
|
|
48
|
+
SidebarGroupLabel,
|
|
49
|
+
SidebarHeader,
|
|
50
|
+
SidebarInput,
|
|
51
|
+
SidebarInset,
|
|
52
|
+
SidebarMenu,
|
|
53
|
+
SidebarMenuAction,
|
|
54
|
+
SidebarMenuBadge,
|
|
55
|
+
SidebarMenuButton,
|
|
56
|
+
SidebarMenuItem,
|
|
57
|
+
SidebarMenuSkeleton,
|
|
58
|
+
SidebarMenuSub,
|
|
59
|
+
SidebarMenuSubButton,
|
|
60
|
+
SidebarMenuSubItem,
|
|
61
|
+
SidebarProvider,
|
|
62
|
+
SidebarRail,
|
|
63
|
+
SidebarSeparator,
|
|
64
|
+
SidebarTrigger,
|
|
65
|
+
useSidebar,
|
|
66
|
+
} from "./components/ui/sidebar.jsx";
|
|
67
|
+
export { Separator } from "./components/ui/separator.jsx";
|
|
68
|
+
export {
|
|
69
|
+
Breadcrumb,
|
|
70
|
+
BreadcrumbItem,
|
|
71
|
+
BreadcrumbLink,
|
|
72
|
+
BreadcrumbList,
|
|
73
|
+
BreadcrumbPage,
|
|
74
|
+
BreadcrumbSeparator,
|
|
75
|
+
BreadcrumbEllipsis,
|
|
76
|
+
} from "./components/ui/breadcrumb.jsx";
|