@startsimpli/ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +537 -0
- package/package.json +80 -0
- package/src/components/index.ts +50 -0
- package/src/components/navigation/sidebar.tsx +178 -0
- package/src/components/ui/accordion.tsx +58 -0
- package/src/components/ui/alert.tsx +59 -0
- package/src/components/ui/badge.tsx +36 -0
- package/src/components/ui/button.tsx +57 -0
- package/src/components/ui/calendar.tsx +70 -0
- package/src/components/ui/card.tsx +68 -0
- package/src/components/ui/checkbox.tsx +30 -0
- package/src/components/ui/collapsible.tsx +12 -0
- package/src/components/ui/dialog.tsx +122 -0
- package/src/components/ui/dropdown-menu.tsx +200 -0
- package/src/components/ui/index.ts +24 -0
- package/src/components/ui/input.tsx +25 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/popover.tsx +31 -0
- package/src/components/ui/progress.tsx +28 -0
- package/src/components/ui/scroll-area.tsx +48 -0
- package/src/components/ui/select.tsx +160 -0
- package/src/components/ui/separator.tsx +31 -0
- package/src/components/ui/skeleton.tsx +15 -0
- package/src/components/ui/table.tsx +117 -0
- package/src/components/ui/tabs.tsx +55 -0
- package/src/components/ui/textarea.tsx +24 -0
- package/src/components/ui/tooltip.tsx +30 -0
- package/src/components/unified-table/UnifiedTable.tsx +553 -0
- package/src/components/unified-table/__tests__/components/BulkActionBar.test.tsx +477 -0
- package/src/components/unified-table/__tests__/components/ExportButton.test.tsx +467 -0
- package/src/components/unified-table/__tests__/components/InlineEditCell.test.tsx +159 -0
- package/src/components/unified-table/__tests__/components/SavedViewsDropdown.test.tsx +128 -0
- package/src/components/unified-table/__tests__/components/TablePagination.test.tsx +374 -0
- package/src/components/unified-table/__tests__/hooks/useColumnReorder.test.ts +191 -0
- package/src/components/unified-table/__tests__/hooks/useColumnResize.test.ts +122 -0
- package/src/components/unified-table/__tests__/hooks/useColumnVisibility.test.ts +594 -0
- package/src/components/unified-table/__tests__/hooks/useFilters.test.ts +460 -0
- package/src/components/unified-table/__tests__/hooks/usePagination.test.ts +439 -0
- package/src/components/unified-table/__tests__/hooks/useResponsive.test.ts +421 -0
- package/src/components/unified-table/__tests__/hooks/useSelection.test.ts +367 -0
- package/src/components/unified-table/__tests__/hooks/useTableKeyboard.test.ts +803 -0
- package/src/components/unified-table/__tests__/hooks/useTableState.test.ts +210 -0
- package/src/components/unified-table/__tests__/integration/table-with-selection.test.tsx +624 -0
- package/src/components/unified-table/__tests__/utils/export.test.ts +427 -0
- package/src/components/unified-table/components/BulkActionBar/index.tsx +119 -0
- package/src/components/unified-table/components/DataTableCore/index.tsx +473 -0
- package/src/components/unified-table/components/InlineEditCell/index.tsx +159 -0
- package/src/components/unified-table/components/MobileView/Card.tsx +218 -0
- package/src/components/unified-table/components/MobileView/CardActions.tsx +126 -0
- package/src/components/unified-table/components/MobileView/README.md +411 -0
- package/src/components/unified-table/components/MobileView/index.tsx +77 -0
- package/src/components/unified-table/components/MobileView/types.ts +77 -0
- package/src/components/unified-table/components/TableFilters/index.tsx +298 -0
- package/src/components/unified-table/components/TablePagination/index.tsx +157 -0
- package/src/components/unified-table/components/Toolbar/ExportButton.tsx +229 -0
- package/src/components/unified-table/components/Toolbar/SavedViewsDropdown.tsx +251 -0
- package/src/components/unified-table/components/Toolbar/StandardTableToolbar.tsx +146 -0
- package/src/components/unified-table/components/Toolbar/index.tsx +3 -0
- package/src/components/unified-table/hooks/index.ts +21 -0
- package/src/components/unified-table/hooks/useColumnReorder.ts +90 -0
- package/src/components/unified-table/hooks/useColumnResize.ts +123 -0
- package/src/components/unified-table/hooks/useColumnVisibility.ts +92 -0
- package/src/components/unified-table/hooks/useFilters.ts +53 -0
- package/src/components/unified-table/hooks/usePagination.ts +120 -0
- package/src/components/unified-table/hooks/useResponsive.ts +50 -0
- package/src/components/unified-table/hooks/useSelection.ts +152 -0
- package/src/components/unified-table/hooks/useTableKeyboard.ts +206 -0
- package/src/components/unified-table/hooks/useTablePreferences.ts +198 -0
- package/src/components/unified-table/hooks/useTableState.ts +103 -0
- package/src/components/unified-table/hooks/useTableURL.test.tsx +921 -0
- package/src/components/unified-table/hooks/useTableURL.ts +301 -0
- package/src/components/unified-table/index.ts +16 -0
- package/src/components/unified-table/types.ts +393 -0
- package/src/components/unified-table/utils/export.ts +236 -0
- package/src/components/unified-table/utils/index.ts +4 -0
- package/src/components/unified-table/utils/renderers.ts +105 -0
- package/src/components/unified-table/utils/themes.ts +87 -0
- package/src/components/unified-table/utils/validation.ts +122 -0
- package/src/index.ts +6 -0
- package/src/lib/utils.ts +1 -0
- package/src/theme/contract.ts +46 -0
- package/src/theme/index.ts +9 -0
- package/src/theme/tailwind.config.js +70 -0
- package/src/theme/tailwind.preset.ts +93 -0
- package/src/utils/cn.ts +6 -0
- package/src/utils/index.ts +91 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { Config } from 'tailwindcss'
|
|
2
|
+
|
|
3
|
+
// Presets intentionally omit `content` — each consuming app supplies its own.
|
|
4
|
+
// tailwindcss exposes PresetsConfig = Partial<Config> for this purpose.
|
|
5
|
+
const preset: Partial<Config> = {
|
|
6
|
+
darkMode: ['class'],
|
|
7
|
+
theme: {
|
|
8
|
+
extend: {
|
|
9
|
+
colors: {
|
|
10
|
+
background: 'hsl(var(--background))',
|
|
11
|
+
foreground: 'hsl(var(--foreground))',
|
|
12
|
+
card: {
|
|
13
|
+
DEFAULT: 'hsl(var(--card))',
|
|
14
|
+
foreground: 'hsl(var(--card-foreground))',
|
|
15
|
+
},
|
|
16
|
+
popover: {
|
|
17
|
+
DEFAULT: 'hsl(var(--popover))',
|
|
18
|
+
foreground: 'hsl(var(--popover-foreground))',
|
|
19
|
+
},
|
|
20
|
+
primary: {
|
|
21
|
+
DEFAULT: 'hsl(var(--primary))',
|
|
22
|
+
foreground: 'hsl(var(--primary-foreground))',
|
|
23
|
+
},
|
|
24
|
+
secondary: {
|
|
25
|
+
DEFAULT: 'hsl(var(--secondary))',
|
|
26
|
+
foreground: 'hsl(var(--secondary-foreground))',
|
|
27
|
+
},
|
|
28
|
+
muted: {
|
|
29
|
+
DEFAULT: 'hsl(var(--muted))',
|
|
30
|
+
foreground: 'hsl(var(--muted-foreground))',
|
|
31
|
+
},
|
|
32
|
+
accent: {
|
|
33
|
+
DEFAULT: 'hsl(var(--accent))',
|
|
34
|
+
foreground: 'hsl(var(--accent-foreground))',
|
|
35
|
+
},
|
|
36
|
+
destructive: {
|
|
37
|
+
DEFAULT: 'hsl(var(--destructive))',
|
|
38
|
+
foreground: 'hsl(var(--destructive-foreground))',
|
|
39
|
+
},
|
|
40
|
+
border: 'hsl(var(--border))',
|
|
41
|
+
input: 'hsl(var(--input))',
|
|
42
|
+
ring: 'hsl(var(--ring))',
|
|
43
|
+
},
|
|
44
|
+
borderRadius: {
|
|
45
|
+
// All derived from per-step vars so changing --radius reshapes everything
|
|
46
|
+
sm: 'var(--radius-sm)',
|
|
47
|
+
md: 'var(--radius-md)',
|
|
48
|
+
lg: 'var(--radius-lg)',
|
|
49
|
+
xl: 'var(--radius-xl)',
|
|
50
|
+
full: 'var(--radius-full)',
|
|
51
|
+
DEFAULT: 'var(--radius)',
|
|
52
|
+
},
|
|
53
|
+
boxShadow: {
|
|
54
|
+
sm: 'var(--shadow-sm)',
|
|
55
|
+
DEFAULT: 'var(--shadow-md)',
|
|
56
|
+
md: 'var(--shadow-md)',
|
|
57
|
+
lg: 'var(--shadow-lg)',
|
|
58
|
+
xl: 'var(--shadow-xl)',
|
|
59
|
+
none: 'none',
|
|
60
|
+
},
|
|
61
|
+
fontFamily: {
|
|
62
|
+
sans: ['var(--font-sans)', 'ui-sans-serif', 'system-ui', 'sans-serif'],
|
|
63
|
+
mono: ['var(--font-mono)', 'ui-monospace', 'monospace'],
|
|
64
|
+
heading: ['var(--font-heading, var(--font-sans))', 'ui-sans-serif', 'sans-serif'],
|
|
65
|
+
},
|
|
66
|
+
transitionDuration: {
|
|
67
|
+
fast: 'var(--duration-fast)',
|
|
68
|
+
DEFAULT: 'var(--duration-normal)',
|
|
69
|
+
slow: 'var(--duration-slow)',
|
|
70
|
+
},
|
|
71
|
+
borderWidth: {
|
|
72
|
+
DEFAULT: 'var(--border-width)',
|
|
73
|
+
},
|
|
74
|
+
keyframes: {
|
|
75
|
+
'accordion-down': {
|
|
76
|
+
from: { height: '0' },
|
|
77
|
+
to: { height: 'var(--radix-accordion-content-height)' },
|
|
78
|
+
},
|
|
79
|
+
'accordion-up': {
|
|
80
|
+
from: { height: 'var(--radix-accordion-content-height)' },
|
|
81
|
+
to: { height: '0' },
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
animation: {
|
|
85
|
+
'accordion-down': 'accordion-down 0.2s ease-out',
|
|
86
|
+
'accordion-up': 'accordion-up 0.2s ease-out',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
plugins: [],
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export default preset
|
package/src/utils/cn.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export { cn } from './cn'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generate a random ID with optional prefix
|
|
5
|
+
*/
|
|
6
|
+
export function generateId(prefix = ''): string {
|
|
7
|
+
const random = Math.random().toString(36).substring(2, 9)
|
|
8
|
+
return prefix ? `${prefix}_${random}` : random
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Sleep for a given number of milliseconds
|
|
13
|
+
*/
|
|
14
|
+
export function sleep(ms: number): Promise<void> {
|
|
15
|
+
return new Promise((resolve) => setTimeout(resolve, ms))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Format a date as a short human-readable string (e.g. "Jan 5, 2024").
|
|
20
|
+
* Accepts a Date object or an ISO date string.
|
|
21
|
+
*/
|
|
22
|
+
export function formatDate(date: Date | string): string {
|
|
23
|
+
const d = typeof date === 'string' ? new Date(date) : date
|
|
24
|
+
return new Intl.DateTimeFormat('en-US', {
|
|
25
|
+
month: 'short',
|
|
26
|
+
day: 'numeric',
|
|
27
|
+
year: 'numeric',
|
|
28
|
+
}).format(d)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Format a date relative to now using coarse buckets
|
|
33
|
+
* (Today / Yesterday / N days ago / N weeks ago / formatted date).
|
|
34
|
+
* Accepts a Date object or an ISO date string.
|
|
35
|
+
*/
|
|
36
|
+
export function formatRelativeTime(date: Date | string): string {
|
|
37
|
+
const d = typeof date === 'string' ? new Date(date) : date
|
|
38
|
+
const now = new Date()
|
|
39
|
+
const diffMs = now.getTime() - d.getTime()
|
|
40
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24))
|
|
41
|
+
|
|
42
|
+
if (diffDays === 0) return 'Today'
|
|
43
|
+
if (diffDays === 1) return 'Yesterday'
|
|
44
|
+
if (diffDays < 7) return `${diffDays} days ago`
|
|
45
|
+
if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`
|
|
46
|
+
return formatDate(d)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Format a date relative to now using fine-grained buckets
|
|
51
|
+
* (just now / Xm ago / Xh ago / Xd ago / formatted date).
|
|
52
|
+
*/
|
|
53
|
+
export function formatRelativeDate(date: Date): string {
|
|
54
|
+
const now = new Date()
|
|
55
|
+
const diffMs = now.getTime() - date.getTime()
|
|
56
|
+
const diffSecs = Math.floor(diffMs / 1000)
|
|
57
|
+
const diffMins = Math.floor(diffSecs / 60)
|
|
58
|
+
const diffHours = Math.floor(diffMins / 60)
|
|
59
|
+
const diffDays = Math.floor(diffHours / 24)
|
|
60
|
+
|
|
61
|
+
if (diffSecs < 60) return 'just now'
|
|
62
|
+
if (diffMins < 60) return `${diffMins}m ago`
|
|
63
|
+
if (diffHours < 24) return `${diffHours}h ago`
|
|
64
|
+
if (diffDays < 7) return `${diffDays}d ago`
|
|
65
|
+
|
|
66
|
+
return date.toLocaleDateString()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Format a number as USD currency (no cents, e.g. "$1,000,000")
|
|
71
|
+
*/
|
|
72
|
+
export function formatCurrency(amount: number): string {
|
|
73
|
+
return new Intl.NumberFormat('en-US', {
|
|
74
|
+
style: 'currency',
|
|
75
|
+
currency: 'USD',
|
|
76
|
+
minimumFractionDigits: 0,
|
|
77
|
+
maximumFractionDigits: 0,
|
|
78
|
+
}).format(amount)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get initials from a display name (up to 2 characters)
|
|
83
|
+
*/
|
|
84
|
+
export function getInitials(name: string): string {
|
|
85
|
+
return name
|
|
86
|
+
.split(' ')
|
|
87
|
+
.map((word) => word[0])
|
|
88
|
+
.join('')
|
|
89
|
+
.toUpperCase()
|
|
90
|
+
.slice(0, 2)
|
|
91
|
+
}
|