@thehoneyjar/sigil-hud 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/LICENSE.md +660 -0
- package/README.md +146 -0
- package/dist/index.d.ts +911 -0
- package/dist/index.js +3079 -0
- package/package.json +68 -0
- package/src/components/DataSourceIndicator.tsx +185 -0
- package/src/components/DiagnosticsPanel.tsx +444 -0
- package/src/components/FeedbackPrompt.tsx +348 -0
- package/src/components/HudPanel.tsx +179 -0
- package/src/components/HudTrigger.tsx +81 -0
- package/src/components/IssueList.tsx +228 -0
- package/src/components/LensPanel.tsx +286 -0
- package/src/components/ObservationCaptureModal.tsx +502 -0
- package/src/components/PhysicsAnalysis.tsx +273 -0
- package/src/components/SimulationPanel.tsx +173 -0
- package/src/components/StateComparison.tsx +238 -0
- package/src/hooks/useDataSource.ts +324 -0
- package/src/hooks/useKeyboardShortcuts.ts +125 -0
- package/src/hooks/useObservationCapture.ts +154 -0
- package/src/hooks/useSignalCapture.ts +138 -0
- package/src/index.ts +112 -0
- package/src/providers/HudProvider.tsx +115 -0
- package/src/store.ts +60 -0
- package/src/styles/theme.ts +256 -0
- package/src/types.ts +276 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signal Capture Hook
|
|
3
|
+
*
|
|
4
|
+
* Capture taste signals from HUD interactions.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { useCallback, useRef } from 'react'
|
|
8
|
+
import type { Signal } from '../types'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Props for useSignalCapture
|
|
12
|
+
*/
|
|
13
|
+
export interface UseSignalCaptureProps {
|
|
14
|
+
/** Whether signal capture is enabled */
|
|
15
|
+
enabled?: boolean
|
|
16
|
+
/** Callback when signal is captured */
|
|
17
|
+
onSignal?: (signal: Signal) => void
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Hook to capture taste signals from HUD
|
|
22
|
+
*/
|
|
23
|
+
export function useSignalCapture({
|
|
24
|
+
enabled = true,
|
|
25
|
+
onSignal,
|
|
26
|
+
}: UseSignalCaptureProps = {}) {
|
|
27
|
+
const signalsRef = useRef<Signal[]>([])
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Append a signal to the taste log
|
|
31
|
+
*/
|
|
32
|
+
const appendSignal = useCallback(
|
|
33
|
+
async (signalData: Omit<Signal, 'timestamp' | 'source'>): Promise<void> => {
|
|
34
|
+
if (!enabled) return
|
|
35
|
+
|
|
36
|
+
const signal: Signal = {
|
|
37
|
+
...signalData,
|
|
38
|
+
timestamp: new Date().toISOString(),
|
|
39
|
+
source: 'hud',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Store locally
|
|
43
|
+
signalsRef.current.push(signal)
|
|
44
|
+
|
|
45
|
+
// Notify callback
|
|
46
|
+
onSignal?.(signal)
|
|
47
|
+
|
|
48
|
+
// In a full implementation, this would write to grimoires/sigil/taste.md
|
|
49
|
+
// For now, we log to console in development
|
|
50
|
+
if (process.env.NODE_ENV === 'development') {
|
|
51
|
+
console.log('[Sigil HUD] Signal captured:', signal)
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
[enabled, onSignal]
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Create an ACCEPT signal
|
|
59
|
+
*/
|
|
60
|
+
const accept = useCallback(
|
|
61
|
+
(component: string, effect: string, craftType: Signal['component']['craft_type'] = 'generate') => {
|
|
62
|
+
return appendSignal({
|
|
63
|
+
signal: 'ACCEPT',
|
|
64
|
+
component: {
|
|
65
|
+
name: component,
|
|
66
|
+
effect,
|
|
67
|
+
craft_type: craftType,
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
},
|
|
71
|
+
[appendSignal]
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Create a MODIFY signal
|
|
76
|
+
*/
|
|
77
|
+
const modify = useCallback(
|
|
78
|
+
(
|
|
79
|
+
component: string,
|
|
80
|
+
effect: string,
|
|
81
|
+
change: { from: string; to: string },
|
|
82
|
+
learning?: { inference: string; recommendation?: string }
|
|
83
|
+
) => {
|
|
84
|
+
return appendSignal({
|
|
85
|
+
signal: 'MODIFY',
|
|
86
|
+
component: {
|
|
87
|
+
name: component,
|
|
88
|
+
effect,
|
|
89
|
+
craft_type: 'generate',
|
|
90
|
+
},
|
|
91
|
+
change,
|
|
92
|
+
learning,
|
|
93
|
+
})
|
|
94
|
+
},
|
|
95
|
+
[appendSignal]
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Create a REJECT signal
|
|
100
|
+
*/
|
|
101
|
+
const reject = useCallback(
|
|
102
|
+
(component: string, effect: string, reason: string) => {
|
|
103
|
+
return appendSignal({
|
|
104
|
+
signal: 'REJECT',
|
|
105
|
+
component: {
|
|
106
|
+
name: component,
|
|
107
|
+
effect,
|
|
108
|
+
craft_type: 'generate',
|
|
109
|
+
},
|
|
110
|
+
rejection_reason: reason,
|
|
111
|
+
})
|
|
112
|
+
},
|
|
113
|
+
[appendSignal]
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get all captured signals
|
|
118
|
+
*/
|
|
119
|
+
const getSignals = useCallback(() => {
|
|
120
|
+
return [...signalsRef.current]
|
|
121
|
+
}, [])
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Clear captured signals
|
|
125
|
+
*/
|
|
126
|
+
const clearSignals = useCallback(() => {
|
|
127
|
+
signalsRef.current = []
|
|
128
|
+
}, [])
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
appendSignal,
|
|
132
|
+
accept,
|
|
133
|
+
modify,
|
|
134
|
+
reject,
|
|
135
|
+
getSignals,
|
|
136
|
+
clearSignals,
|
|
137
|
+
}
|
|
138
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sigil/hud
|
|
3
|
+
*
|
|
4
|
+
* Diagnostic HUD for Sigil - composable React components for development.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Types
|
|
8
|
+
export type {
|
|
9
|
+
HudPosition,
|
|
10
|
+
HudConfig,
|
|
11
|
+
HudPanelType,
|
|
12
|
+
HudState,
|
|
13
|
+
HudActions,
|
|
14
|
+
HudContextValue,
|
|
15
|
+
HudProviderProps,
|
|
16
|
+
Observation,
|
|
17
|
+
Signal,
|
|
18
|
+
// Service types (mirrored from optional packages)
|
|
19
|
+
LensService,
|
|
20
|
+
LensState,
|
|
21
|
+
ForkService,
|
|
22
|
+
ForkState,
|
|
23
|
+
SimulationService,
|
|
24
|
+
SimulationState,
|
|
25
|
+
DiagnosticsService,
|
|
26
|
+
DiagnosticResult,
|
|
27
|
+
DiagnosticIssue,
|
|
28
|
+
EffectType,
|
|
29
|
+
ComplianceResult,
|
|
30
|
+
BehavioralCompliance,
|
|
31
|
+
AnimationCompliance,
|
|
32
|
+
MaterialCompliance,
|
|
33
|
+
} from './types'
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
DEFAULT_HUD_STATE,
|
|
37
|
+
DEFAULT_HUD_CONFIG,
|
|
38
|
+
DEFAULT_LENS_STATE,
|
|
39
|
+
} from './types'
|
|
40
|
+
|
|
41
|
+
// Store
|
|
42
|
+
export { useHudStore, getHudState } from './store'
|
|
43
|
+
export type { HudStore } from './store'
|
|
44
|
+
|
|
45
|
+
// Provider
|
|
46
|
+
export { HudProvider, useHud, useHudOptional } from './providers/HudProvider'
|
|
47
|
+
|
|
48
|
+
// Components
|
|
49
|
+
export { HudPanel } from './components/HudPanel'
|
|
50
|
+
export type { HudPanelProps } from './components/HudPanel'
|
|
51
|
+
|
|
52
|
+
export { HudTrigger } from './components/HudTrigger'
|
|
53
|
+
export type { HudTriggerProps } from './components/HudTrigger'
|
|
54
|
+
|
|
55
|
+
export { LensPanel } from './components/LensPanel'
|
|
56
|
+
export type { LensPanelProps } from './components/LensPanel'
|
|
57
|
+
|
|
58
|
+
export { SimulationPanel } from './components/SimulationPanel'
|
|
59
|
+
export type { SimulationPanelProps } from './components/SimulationPanel'
|
|
60
|
+
|
|
61
|
+
export { DiagnosticsPanel } from './components/DiagnosticsPanel'
|
|
62
|
+
export type { DiagnosticsPanelProps } from './components/DiagnosticsPanel'
|
|
63
|
+
|
|
64
|
+
export { PhysicsAnalysis } from './components/PhysicsAnalysis'
|
|
65
|
+
export type { PhysicsAnalysisProps } from './components/PhysicsAnalysis'
|
|
66
|
+
|
|
67
|
+
export { IssueList } from './components/IssueList'
|
|
68
|
+
export type { IssueListProps } from './components/IssueList'
|
|
69
|
+
|
|
70
|
+
export { DataSourceIndicator } from './components/DataSourceIndicator'
|
|
71
|
+
export type { DataSourceIndicatorProps, DataSourceType } from './components/DataSourceIndicator'
|
|
72
|
+
|
|
73
|
+
export { StateComparison } from './components/StateComparison'
|
|
74
|
+
export type { StateComparisonProps } from './components/StateComparison'
|
|
75
|
+
|
|
76
|
+
export { ObservationCaptureModal } from './components/ObservationCaptureModal'
|
|
77
|
+
export type { ObservationCaptureModalProps } from './components/ObservationCaptureModal'
|
|
78
|
+
|
|
79
|
+
export { FeedbackPrompt } from './components/FeedbackPrompt'
|
|
80
|
+
export type { FeedbackPromptProps } from './components/FeedbackPrompt'
|
|
81
|
+
|
|
82
|
+
// Hooks
|
|
83
|
+
export { useKeyboardShortcuts, getShortcutHelp } from './hooks/useKeyboardShortcuts'
|
|
84
|
+
export type { UseKeyboardShortcutsProps } from './hooks/useKeyboardShortcuts'
|
|
85
|
+
|
|
86
|
+
export { useSignalCapture } from './hooks/useSignalCapture'
|
|
87
|
+
export type { UseSignalCaptureProps } from './hooks/useSignalCapture'
|
|
88
|
+
|
|
89
|
+
export { useObservationCapture } from './hooks/useObservationCapture'
|
|
90
|
+
export type { UseObservationCaptureProps } from './hooks/useObservationCapture'
|
|
91
|
+
|
|
92
|
+
export { useDataSource, useMultipleDataSources } from './hooks/useDataSource'
|
|
93
|
+
export type {
|
|
94
|
+
UseDataSourceProps,
|
|
95
|
+
DataSourceMeta,
|
|
96
|
+
DataSourceEntry,
|
|
97
|
+
} from './hooks/useDataSource'
|
|
98
|
+
|
|
99
|
+
// Theme
|
|
100
|
+
export {
|
|
101
|
+
colors,
|
|
102
|
+
typography,
|
|
103
|
+
spacing,
|
|
104
|
+
radii,
|
|
105
|
+
shadows,
|
|
106
|
+
transitions,
|
|
107
|
+
zIndex,
|
|
108
|
+
patterns,
|
|
109
|
+
effectColors,
|
|
110
|
+
getEffectColor,
|
|
111
|
+
createStyles,
|
|
112
|
+
} from './styles/theme'
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HUD Provider
|
|
3
|
+
*
|
|
4
|
+
* Context provider for HUD state and services.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createContext, useContext, useMemo } from 'react'
|
|
8
|
+
import type { HudProviderProps, HudContextValue, HudConfig } from '../types'
|
|
9
|
+
import { DEFAULT_HUD_CONFIG, DEFAULT_HUD_STATE } from '../types'
|
|
10
|
+
import { useHudStore } from '../store'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* HUD context
|
|
14
|
+
*/
|
|
15
|
+
const HudContext = createContext<HudContextValue | null>(null)
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* HUD Provider component
|
|
19
|
+
*/
|
|
20
|
+
export function HudProvider({
|
|
21
|
+
children,
|
|
22
|
+
config = {},
|
|
23
|
+
lensService,
|
|
24
|
+
forkService,
|
|
25
|
+
simulationService,
|
|
26
|
+
diagnosticsService,
|
|
27
|
+
anchorClient,
|
|
28
|
+
}: HudProviderProps) {
|
|
29
|
+
// Get state and actions from store
|
|
30
|
+
const isOpen = useHudStore((state) => state.isOpen)
|
|
31
|
+
const activePanel = useHudStore((state) => state.activePanel)
|
|
32
|
+
const position = useHudStore((state) => state.position)
|
|
33
|
+
const isMinimized = useHudStore((state) => state.isMinimized)
|
|
34
|
+
const open = useHudStore((state) => state.open)
|
|
35
|
+
const close = useHudStore((state) => state.close)
|
|
36
|
+
const toggle = useHudStore((state) => state.toggle)
|
|
37
|
+
const setActivePanel = useHudStore((state) => state.setActivePanel)
|
|
38
|
+
const setPosition = useHudStore((state) => state.setPosition)
|
|
39
|
+
const toggleMinimized = useHudStore((state) => state.toggleMinimized)
|
|
40
|
+
|
|
41
|
+
// Merge config with defaults
|
|
42
|
+
const mergedConfig: HudConfig = useMemo(
|
|
43
|
+
() => ({
|
|
44
|
+
...DEFAULT_HUD_CONFIG,
|
|
45
|
+
...config,
|
|
46
|
+
}),
|
|
47
|
+
[config]
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
// Build context value
|
|
51
|
+
const value: HudContextValue = useMemo(
|
|
52
|
+
() => ({
|
|
53
|
+
// State
|
|
54
|
+
isOpen,
|
|
55
|
+
activePanel,
|
|
56
|
+
position,
|
|
57
|
+
isMinimized,
|
|
58
|
+
// Actions
|
|
59
|
+
open,
|
|
60
|
+
close,
|
|
61
|
+
toggle,
|
|
62
|
+
setActivePanel,
|
|
63
|
+
setPosition,
|
|
64
|
+
toggleMinimized,
|
|
65
|
+
// Services
|
|
66
|
+
lensService: lensService ?? null,
|
|
67
|
+
forkService: forkService ?? null,
|
|
68
|
+
simulationService: simulationService ?? null,
|
|
69
|
+
diagnosticsService: diagnosticsService ?? null,
|
|
70
|
+
anchorClient: anchorClient ?? null,
|
|
71
|
+
// Config
|
|
72
|
+
config: mergedConfig,
|
|
73
|
+
}),
|
|
74
|
+
[
|
|
75
|
+
isOpen,
|
|
76
|
+
activePanel,
|
|
77
|
+
position,
|
|
78
|
+
isMinimized,
|
|
79
|
+
open,
|
|
80
|
+
close,
|
|
81
|
+
toggle,
|
|
82
|
+
setActivePanel,
|
|
83
|
+
setPosition,
|
|
84
|
+
toggleMinimized,
|
|
85
|
+
lensService,
|
|
86
|
+
forkService,
|
|
87
|
+
simulationService,
|
|
88
|
+
diagnosticsService,
|
|
89
|
+
anchorClient,
|
|
90
|
+
mergedConfig,
|
|
91
|
+
]
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
return <HudContext.Provider value={value}>{children}</HudContext.Provider>
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Hook to access HUD context
|
|
99
|
+
*
|
|
100
|
+
* @throws Error if used outside HudProvider
|
|
101
|
+
*/
|
|
102
|
+
export function useHud(): HudContextValue {
|
|
103
|
+
const context = useContext(HudContext)
|
|
104
|
+
if (!context) {
|
|
105
|
+
throw new Error('useHud must be used within a HudProvider')
|
|
106
|
+
}
|
|
107
|
+
return context
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Hook to access HUD context (returns null if not in provider)
|
|
112
|
+
*/
|
|
113
|
+
export function useHudOptional(): HudContextValue | null {
|
|
114
|
+
return useContext(HudContext)
|
|
115
|
+
}
|
package/src/store.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HUD Store
|
|
3
|
+
*
|
|
4
|
+
* Zustand store for HUD state management.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { create } from 'zustand'
|
|
8
|
+
import { persist } from 'zustand/middleware'
|
|
9
|
+
import type { HudState, HudActions, HudPosition, HudPanelType } from './types'
|
|
10
|
+
import { DEFAULT_HUD_STATE } from './types'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Combined HUD store type
|
|
14
|
+
*/
|
|
15
|
+
export type HudStore = HudState & HudActions
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Create the HUD store
|
|
19
|
+
*/
|
|
20
|
+
export const useHudStore = create<HudStore>()(
|
|
21
|
+
persist(
|
|
22
|
+
(set) => ({
|
|
23
|
+
...DEFAULT_HUD_STATE,
|
|
24
|
+
|
|
25
|
+
open: () => set({ isOpen: true }),
|
|
26
|
+
|
|
27
|
+
close: () => set({ isOpen: false }),
|
|
28
|
+
|
|
29
|
+
toggle: () => set((state) => ({ isOpen: !state.isOpen })),
|
|
30
|
+
|
|
31
|
+
setActivePanel: (panel: HudPanelType | null) =>
|
|
32
|
+
set({ activePanel: panel }),
|
|
33
|
+
|
|
34
|
+
setPosition: (position: HudPosition) => set({ position }),
|
|
35
|
+
|
|
36
|
+
toggleMinimized: () =>
|
|
37
|
+
set((state) => ({ isMinimized: !state.isMinimized })),
|
|
38
|
+
}),
|
|
39
|
+
{
|
|
40
|
+
name: 'sigil-hud-storage',
|
|
41
|
+
partialize: (state) => ({
|
|
42
|
+
position: state.position,
|
|
43
|
+
isMinimized: state.isMinimized,
|
|
44
|
+
}),
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get HUD store state (for non-React contexts)
|
|
51
|
+
*/
|
|
52
|
+
export function getHudState(): HudState {
|
|
53
|
+
const state = useHudStore.getState()
|
|
54
|
+
return {
|
|
55
|
+
isOpen: state.isOpen,
|
|
56
|
+
activePanel: state.activePanel,
|
|
57
|
+
position: state.position,
|
|
58
|
+
isMinimized: state.isMinimized,
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HUD Theme Constants
|
|
3
|
+
*
|
|
4
|
+
* Shared design tokens for consistent styling across HUD components.
|
|
5
|
+
* Implements TASK-205 styling requirements.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Color palette
|
|
10
|
+
*/
|
|
11
|
+
export const colors = {
|
|
12
|
+
// Brand
|
|
13
|
+
primary: '#10b981', // emerald-500
|
|
14
|
+
primaryLight: 'rgba(16, 185, 129, 0.2)',
|
|
15
|
+
primaryBorder: 'rgba(16, 185, 129, 0.3)',
|
|
16
|
+
|
|
17
|
+
// Status
|
|
18
|
+
success: '#22c55e', // green-500
|
|
19
|
+
successLight: 'rgba(34, 197, 94, 0.1)',
|
|
20
|
+
successBorder: 'rgba(34, 197, 94, 0.3)',
|
|
21
|
+
|
|
22
|
+
warning: '#eab308', // yellow-500
|
|
23
|
+
warningLight: 'rgba(234, 179, 8, 0.1)',
|
|
24
|
+
warningBorder: 'rgba(234, 179, 8, 0.3)',
|
|
25
|
+
|
|
26
|
+
error: '#ef4444', // red-500
|
|
27
|
+
errorLight: 'rgba(239, 68, 68, 0.1)',
|
|
28
|
+
errorBorder: 'rgba(239, 68, 68, 0.3)',
|
|
29
|
+
|
|
30
|
+
info: '#3b82f6', // blue-500
|
|
31
|
+
infoLight: 'rgba(59, 130, 246, 0.1)',
|
|
32
|
+
infoBorder: 'rgba(59, 130, 246, 0.3)',
|
|
33
|
+
|
|
34
|
+
// Neutral
|
|
35
|
+
text: '#fff',
|
|
36
|
+
textMuted: '#888',
|
|
37
|
+
textDim: '#666',
|
|
38
|
+
textDisabled: '#555',
|
|
39
|
+
|
|
40
|
+
background: 'rgba(0, 0, 0, 0.9)',
|
|
41
|
+
backgroundElevated: 'rgba(26, 26, 26, 1)',
|
|
42
|
+
backgroundHover: 'rgba(255, 255, 255, 0.05)',
|
|
43
|
+
backgroundActive: 'rgba(255, 255, 255, 0.08)',
|
|
44
|
+
backgroundInput: 'rgba(255, 255, 255, 0.02)',
|
|
45
|
+
|
|
46
|
+
border: 'rgba(255, 255, 255, 0.1)',
|
|
47
|
+
borderSubtle: 'rgba(255, 255, 255, 0.05)',
|
|
48
|
+
borderStrong: 'rgba(255, 255, 255, 0.2)',
|
|
49
|
+
|
|
50
|
+
// Effects
|
|
51
|
+
financial: '#ef4444',
|
|
52
|
+
destructive: '#f97316',
|
|
53
|
+
softDelete: '#eab308',
|
|
54
|
+
standard: '#22c55e',
|
|
55
|
+
local: '#3b82f6',
|
|
56
|
+
navigation: '#8b5cf6',
|
|
57
|
+
query: '#06b6d4',
|
|
58
|
+
} as const
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Typography
|
|
62
|
+
*/
|
|
63
|
+
export const typography = {
|
|
64
|
+
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
|
|
65
|
+
fontFamilySans: 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif',
|
|
66
|
+
|
|
67
|
+
// Sizes
|
|
68
|
+
xs: '10px',
|
|
69
|
+
sm: '11px',
|
|
70
|
+
base: '12px',
|
|
71
|
+
md: '13px',
|
|
72
|
+
lg: '14px',
|
|
73
|
+
|
|
74
|
+
// Weights
|
|
75
|
+
normal: 400,
|
|
76
|
+
medium: 500,
|
|
77
|
+
semibold: 600,
|
|
78
|
+
bold: 700,
|
|
79
|
+
|
|
80
|
+
// Line heights
|
|
81
|
+
lineHeightTight: 1.25,
|
|
82
|
+
lineHeightNormal: 1.5,
|
|
83
|
+
lineHeightRelaxed: 1.6,
|
|
84
|
+
|
|
85
|
+
// Letter spacing
|
|
86
|
+
letterSpacingTight: '-0.02em',
|
|
87
|
+
letterSpacingNormal: '0',
|
|
88
|
+
letterSpacingWide: '0.5px',
|
|
89
|
+
} as const
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Spacing
|
|
93
|
+
*/
|
|
94
|
+
export const spacing = {
|
|
95
|
+
xs: '4px',
|
|
96
|
+
sm: '6px',
|
|
97
|
+
md: '8px',
|
|
98
|
+
lg: '12px',
|
|
99
|
+
xl: '16px',
|
|
100
|
+
'2xl': '20px',
|
|
101
|
+
'3xl': '24px',
|
|
102
|
+
} as const
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Border radius
|
|
106
|
+
*/
|
|
107
|
+
export const radii = {
|
|
108
|
+
sm: '4px',
|
|
109
|
+
md: '6px',
|
|
110
|
+
lg: '8px',
|
|
111
|
+
xl: '12px',
|
|
112
|
+
full: '9999px',
|
|
113
|
+
} as const
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Shadows
|
|
117
|
+
*/
|
|
118
|
+
export const shadows = {
|
|
119
|
+
sm: '0 2px 4px rgba(0, 0, 0, 0.2)',
|
|
120
|
+
md: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
|
121
|
+
lg: '0 8px 20px rgba(0, 0, 0, 0.4)',
|
|
122
|
+
xl: '0 20px 40px rgba(0, 0, 0, 0.5)',
|
|
123
|
+
primary: '0 4px 12px rgba(16, 185, 129, 0.3)',
|
|
124
|
+
primaryHover: '0 6px 16px rgba(16, 185, 129, 0.4)',
|
|
125
|
+
} as const
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Transitions
|
|
129
|
+
*/
|
|
130
|
+
export const transitions = {
|
|
131
|
+
fast: '0.1s ease-out',
|
|
132
|
+
normal: '0.15s ease-out',
|
|
133
|
+
slow: '0.2s ease-out',
|
|
134
|
+
spring: '0.3s cubic-bezier(0.34, 1.56, 0.64, 1)',
|
|
135
|
+
} as const
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Z-index
|
|
139
|
+
*/
|
|
140
|
+
export const zIndex = {
|
|
141
|
+
base: 1,
|
|
142
|
+
dropdown: 100,
|
|
143
|
+
sticky: 1000,
|
|
144
|
+
fixed: 5000,
|
|
145
|
+
modal: 10000,
|
|
146
|
+
tooltip: 15000,
|
|
147
|
+
} as const
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Common style patterns
|
|
151
|
+
*/
|
|
152
|
+
export const patterns = {
|
|
153
|
+
// Buttons
|
|
154
|
+
button: {
|
|
155
|
+
base: {
|
|
156
|
+
padding: `${spacing.md} ${spacing.lg}`,
|
|
157
|
+
borderRadius: radii.md,
|
|
158
|
+
fontSize: typography.sm,
|
|
159
|
+
fontWeight: typography.medium,
|
|
160
|
+
cursor: 'pointer',
|
|
161
|
+
transition: transitions.normal,
|
|
162
|
+
border: '1px solid',
|
|
163
|
+
},
|
|
164
|
+
primary: {
|
|
165
|
+
backgroundColor: colors.primaryLight,
|
|
166
|
+
borderColor: colors.primaryBorder,
|
|
167
|
+
color: colors.primary,
|
|
168
|
+
},
|
|
169
|
+
secondary: {
|
|
170
|
+
backgroundColor: colors.backgroundInput,
|
|
171
|
+
borderColor: colors.border,
|
|
172
|
+
color: colors.textMuted,
|
|
173
|
+
},
|
|
174
|
+
danger: {
|
|
175
|
+
backgroundColor: colors.errorLight,
|
|
176
|
+
borderColor: colors.errorBorder,
|
|
177
|
+
color: colors.error,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
// Inputs
|
|
182
|
+
input: {
|
|
183
|
+
base: {
|
|
184
|
+
padding: spacing.md,
|
|
185
|
+
backgroundColor: colors.backgroundInput,
|
|
186
|
+
border: `1px solid ${colors.border}`,
|
|
187
|
+
borderRadius: radii.md,
|
|
188
|
+
color: colors.text,
|
|
189
|
+
fontSize: typography.sm,
|
|
190
|
+
fontFamily: typography.fontFamily,
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
// Cards
|
|
195
|
+
card: {
|
|
196
|
+
base: {
|
|
197
|
+
padding: spacing.lg,
|
|
198
|
+
backgroundColor: 'rgba(0, 0, 0, 0.2)',
|
|
199
|
+
borderRadius: radii.lg,
|
|
200
|
+
border: `1px solid ${colors.borderSubtle}`,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
// Labels
|
|
205
|
+
label: {
|
|
206
|
+
base: {
|
|
207
|
+
fontSize: typography.xs,
|
|
208
|
+
fontWeight: typography.semibold,
|
|
209
|
+
color: colors.textMuted,
|
|
210
|
+
textTransform: 'uppercase' as const,
|
|
211
|
+
letterSpacing: typography.letterSpacingWide,
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
// Badges
|
|
216
|
+
badge: {
|
|
217
|
+
base: {
|
|
218
|
+
padding: `2px ${spacing.sm}`,
|
|
219
|
+
borderRadius: radii.sm,
|
|
220
|
+
fontSize: '9px',
|
|
221
|
+
fontWeight: typography.semibold,
|
|
222
|
+
border: '1px solid',
|
|
223
|
+
textTransform: 'uppercase' as const,
|
|
224
|
+
letterSpacing: '0.3px',
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
} as const
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Effect type to color mapping
|
|
231
|
+
*/
|
|
232
|
+
export const effectColors: Record<string, string> = {
|
|
233
|
+
financial: colors.financial,
|
|
234
|
+
destructive: colors.destructive,
|
|
235
|
+
'soft-delete': colors.softDelete,
|
|
236
|
+
standard: colors.standard,
|
|
237
|
+
local: colors.local,
|
|
238
|
+
navigation: colors.navigation,
|
|
239
|
+
query: colors.query,
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Get effect color
|
|
244
|
+
*/
|
|
245
|
+
export function getEffectColor(effect: string): string {
|
|
246
|
+
return effectColors[effect] ?? colors.textMuted
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Create CSS properties object
|
|
251
|
+
*/
|
|
252
|
+
export function createStyles<T extends Record<string, React.CSSProperties>>(
|
|
253
|
+
styles: T
|
|
254
|
+
): T {
|
|
255
|
+
return styles
|
|
256
|
+
}
|