markupr 2.1.8
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/.claude/commands/review-feedback.md +47 -0
- package/.eslintrc.json +35 -0
- package/.github/CODEOWNERS +16 -0
- package/.github/FUNDING.yml +1 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +56 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +54 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +89 -0
- package/.github/dependabot.yml +70 -0
- package/.github/workflows/ci.yml +184 -0
- package/.github/workflows/deploy-landing.yml +134 -0
- package/.github/workflows/nightly.yml +288 -0
- package/.github/workflows/release.yml +318 -0
- package/CHANGELOG.md +127 -0
- package/CLAUDE.md +137 -0
- package/CODE_OF_CONDUCT.md +9 -0
- package/CONTRIBUTING.md +390 -0
- package/LICENSE +21 -0
- package/PRODUCT_VISION.md +277 -0
- package/README.md +517 -0
- package/SECURITY.md +51 -0
- package/SIGNING_INSTRUCTIONS.md +284 -0
- package/assets/DMG_BACKGROUND_INSTRUCTIONS.md +130 -0
- package/assets/svg-source/dmg-background.svg +70 -0
- package/assets/svg-source/icon.svg +20 -0
- package/assets/svg-source/tray-icon-processing.svg +7 -0
- package/assets/svg-source/tray-icon-recording.svg +7 -0
- package/assets/svg-source/tray-icon.svg +6 -0
- package/assets/tray-complete.png +0 -0
- package/assets/tray-complete@2x.png +0 -0
- package/assets/tray-completeTemplate.png +0 -0
- package/assets/tray-completeTemplate@2x.png +0 -0
- package/assets/tray-error.png +0 -0
- package/assets/tray-error@2x.png +0 -0
- package/assets/tray-errorTemplate.png +0 -0
- package/assets/tray-errorTemplate@2x.png +0 -0
- package/assets/tray-icon-processing.png +0 -0
- package/assets/tray-icon-processing@2x.png +0 -0
- package/assets/tray-icon-processingTemplate.png +0 -0
- package/assets/tray-icon-processingTemplate@2x.png +0 -0
- package/assets/tray-icon-recording.png +0 -0
- package/assets/tray-icon-recording@2x.png +0 -0
- package/assets/tray-icon-recordingTemplate.png +0 -0
- package/assets/tray-icon-recordingTemplate@2x.png +0 -0
- package/assets/tray-icon.png +0 -0
- package/assets/tray-icon@2x.png +0 -0
- package/assets/tray-iconTemplate.png +0 -0
- package/assets/tray-iconTemplate@2x.png +0 -0
- package/assets/tray-idle.png +0 -0
- package/assets/tray-idle@2x.png +0 -0
- package/assets/tray-idleTemplate.png +0 -0
- package/assets/tray-idleTemplate@2x.png +0 -0
- package/assets/tray-processing-0.png +0 -0
- package/assets/tray-processing-0@2x.png +0 -0
- package/assets/tray-processing-0Template.png +0 -0
- package/assets/tray-processing-0Template@2x.png +0 -0
- package/assets/tray-processing-1.png +0 -0
- package/assets/tray-processing-1@2x.png +0 -0
- package/assets/tray-processing-1Template.png +0 -0
- package/assets/tray-processing-1Template@2x.png +0 -0
- package/assets/tray-processing-2.png +0 -0
- package/assets/tray-processing-2@2x.png +0 -0
- package/assets/tray-processing-2Template.png +0 -0
- package/assets/tray-processing-2Template@2x.png +0 -0
- package/assets/tray-processing-3.png +0 -0
- package/assets/tray-processing-3@2x.png +0 -0
- package/assets/tray-processing-3Template.png +0 -0
- package/assets/tray-processing-3Template@2x.png +0 -0
- package/assets/tray-processing.png +0 -0
- package/assets/tray-processing@2x.png +0 -0
- package/assets/tray-processingTemplate.png +0 -0
- package/assets/tray-processingTemplate@2x.png +0 -0
- package/assets/tray-recording.png +0 -0
- package/assets/tray-recording@2x.png +0 -0
- package/assets/tray-recordingTemplate.png +0 -0
- package/assets/tray-recordingTemplate@2x.png +0 -0
- package/build/DMG_BACKGROUND_SPEC.md +50 -0
- package/build/dmg-background.png +0 -0
- package/build/dmg-background@2x.png +0 -0
- package/build/entitlements.mac.inherit.plist +27 -0
- package/build/entitlements.mac.plist +41 -0
- package/build/favicon-16.png +0 -0
- package/build/favicon-180.png +0 -0
- package/build/favicon-192.png +0 -0
- package/build/favicon-32.png +0 -0
- package/build/favicon-48.png +0 -0
- package/build/favicon-512.png +0 -0
- package/build/favicon-64.png +0 -0
- package/build/icon-128.png +0 -0
- package/build/icon-16.png +0 -0
- package/build/icon-24.png +0 -0
- package/build/icon-256.png +0 -0
- package/build/icon-32.png +0 -0
- package/build/icon-48.png +0 -0
- package/build/icon-64.png +0 -0
- package/build/icon.icns +0 -0
- package/build/icon.ico +0 -0
- package/build/icon.iconset/icon_128x128.png +0 -0
- package/build/icon.iconset/icon_128x128@2x.png +0 -0
- package/build/icon.iconset/icon_16x16.png +0 -0
- package/build/icon.iconset/icon_16x16@2x.png +0 -0
- package/build/icon.iconset/icon_256x256.png +0 -0
- package/build/icon.iconset/icon_256x256@2x.png +0 -0
- package/build/icon.iconset/icon_32x32.png +0 -0
- package/build/icon.iconset/icon_32x32@2x.png +0 -0
- package/build/icon.iconset/icon_512x512.png +0 -0
- package/build/icon.iconset/icon_512x512@2x.png +0 -0
- package/build/icon.png +0 -0
- package/build/installer-header.bmp +0 -0
- package/build/installer-header.png +0 -0
- package/build/installer-sidebar.bmp +0 -0
- package/build/installer-sidebar.png +0 -0
- package/build/installer.nsh +45 -0
- package/build/overlay-processing.png +0 -0
- package/build/overlay-recording.png +0 -0
- package/build/toolbar-record.png +0 -0
- package/build/toolbar-screenshot.png +0 -0
- package/build/toolbar-settings.png +0 -0
- package/build/toolbar-stop.png +0 -0
- package/dist/main/index.mjs +12612 -0
- package/dist/preload/index.mjs +907 -0
- package/dist/renderer/assets/index-CCmUjl9K.js +19495 -0
- package/dist/renderer/assets/index-CUqz_Gs6.css +2270 -0
- package/dist/renderer/index.html +27 -0
- package/docs/AI_AGENT_QUICKSTART.md +42 -0
- package/docs/AI_PIPELINE_DESIGN.md +595 -0
- package/docs/API.md +514 -0
- package/docs/ARCHITECTURE.md +460 -0
- package/docs/CONFIGURATION.md +336 -0
- package/docs/DEVELOPMENT.md +508 -0
- package/docs/EXPORT_FORMATS.md +451 -0
- package/docs/GETTING_STARTED.md +236 -0
- package/docs/KEYBOARD_SHORTCUTS.md +334 -0
- package/docs/TROUBLESHOOTING.md +418 -0
- package/docs/landing/index.html +672 -0
- package/docs/landing/script.js +342 -0
- package/docs/landing/styles.css +1543 -0
- package/electron-builder.yml +140 -0
- package/electron.vite.config.ts +63 -0
- package/package.json +108 -0
- package/railway.json +12 -0
- package/scripts/build.mjs +51 -0
- package/scripts/generate-icons.mjs +314 -0
- package/scripts/generate-installer-images.cjs +253 -0
- package/scripts/generate-tray-icons.mjs +258 -0
- package/scripts/notarize.cjs +180 -0
- package/scripts/one-click-clean-test.sh +147 -0
- package/scripts/postinstall.mjs +36 -0
- package/scripts/setup-markupr.sh +55 -0
- package/setup +17 -0
- package/site/index.html +1835 -0
- package/site/package.json +11 -0
- package/site/railway.json +12 -0
- package/site/server.js +31 -0
- package/src/main/AutoUpdater.ts +392 -0
- package/src/main/CrashRecovery.ts +655 -0
- package/src/main/ErrorHandler.ts +703 -0
- package/src/main/HotkeyManager.ts +399 -0
- package/src/main/MenuManager.ts +529 -0
- package/src/main/PermissionManager.ts +420 -0
- package/src/main/SessionController.ts +1465 -0
- package/src/main/TrayManager.ts +540 -0
- package/src/main/ai/AIPipelineManager.ts +199 -0
- package/src/main/ai/ClaudeAnalyzer.ts +339 -0
- package/src/main/ai/ImageOptimizer.ts +176 -0
- package/src/main/ai/StructuredMarkdownBuilder.ts +379 -0
- package/src/main/ai/index.ts +16 -0
- package/src/main/ai/types.ts +258 -0
- package/src/main/analysis/ClarificationGenerator.ts +385 -0
- package/src/main/analysis/FeedbackAnalyzer.ts +531 -0
- package/src/main/analysis/index.ts +19 -0
- package/src/main/audio/AudioCapture.ts +978 -0
- package/src/main/audio/audioUtils.ts +100 -0
- package/src/main/audio/index.ts +20 -0
- package/src/main/capture/index.ts +1 -0
- package/src/main/index.ts +1693 -0
- package/src/main/ipc/captureHandlers.ts +272 -0
- package/src/main/ipc/index.ts +45 -0
- package/src/main/ipc/outputHandlers.ts +302 -0
- package/src/main/ipc/sessionHandlers.ts +56 -0
- package/src/main/ipc/settingsHandlers.ts +471 -0
- package/src/main/ipc/types.ts +56 -0
- package/src/main/ipc/windowHandlers.ts +277 -0
- package/src/main/output/ClipboardService.ts +369 -0
- package/src/main/output/ExportService.ts +539 -0
- package/src/main/output/FileManager.ts +416 -0
- package/src/main/output/MarkdownGenerator.ts +791 -0
- package/src/main/output/MarkdownPatcher.ts +299 -0
- package/src/main/output/index.ts +186 -0
- package/src/main/output/sessionAdapter.ts +207 -0
- package/src/main/output/templates/html-template.ts +553 -0
- package/src/main/pipeline/FrameExtractor.ts +330 -0
- package/src/main/pipeline/PostProcessor.ts +399 -0
- package/src/main/pipeline/TranscriptAnalyzer.ts +226 -0
- package/src/main/pipeline/index.ts +36 -0
- package/src/main/platform/WindowsTaskbar.ts +600 -0
- package/src/main/platform/index.ts +16 -0
- package/src/main/settings/SettingsManager.ts +730 -0
- package/src/main/settings/index.ts +19 -0
- package/src/main/transcription/ModelDownloadManager.ts +494 -0
- package/src/main/transcription/TierManager.ts +219 -0
- package/src/main/transcription/TranscriptionRecoveryService.ts +340 -0
- package/src/main/transcription/WhisperService.ts +748 -0
- package/src/main/transcription/index.ts +56 -0
- package/src/main/transcription/types.ts +135 -0
- package/src/main/windows/PopoverManager.ts +284 -0
- package/src/main/windows/TaskbarIntegration.ts +452 -0
- package/src/main/windows/index.ts +23 -0
- package/src/preload/index.ts +1047 -0
- package/src/renderer/App.tsx +515 -0
- package/src/renderer/AppWrapper.tsx +28 -0
- package/src/renderer/assets/logo-dark.svg +7 -0
- package/src/renderer/assets/logo.svg +7 -0
- package/src/renderer/audio/AudioCaptureRenderer.ts +454 -0
- package/src/renderer/capture/ScreenRecordingRenderer.ts +492 -0
- package/src/renderer/components/AnnotationOverlay.tsx +836 -0
- package/src/renderer/components/AudioWaveform.tsx +811 -0
- package/src/renderer/components/ClarificationQuestions.tsx +656 -0
- package/src/renderer/components/CountdownTimer.tsx +495 -0
- package/src/renderer/components/CrashRecoveryDialog.tsx +632 -0
- package/src/renderer/components/DonateButton.tsx +127 -0
- package/src/renderer/components/ErrorBoundary.tsx +308 -0
- package/src/renderer/components/ExportDialog.tsx +872 -0
- package/src/renderer/components/HotkeyHint.tsx +261 -0
- package/src/renderer/components/KeyboardShortcuts.tsx +787 -0
- package/src/renderer/components/ModelDownloadDialog.tsx +844 -0
- package/src/renderer/components/Onboarding.tsx +1830 -0
- package/src/renderer/components/ProcessingOverlay.tsx +157 -0
- package/src/renderer/components/RecordingOverlay.tsx +423 -0
- package/src/renderer/components/SessionHistory.tsx +1746 -0
- package/src/renderer/components/SessionReview.tsx +1321 -0
- package/src/renderer/components/SettingsPanel.tsx +217 -0
- package/src/renderer/components/Skeleton.tsx +347 -0
- package/src/renderer/components/StatusIndicator.tsx +86 -0
- package/src/renderer/components/ThemeProvider.tsx +429 -0
- package/src/renderer/components/Tooltip.tsx +370 -0
- package/src/renderer/components/TranscriptionPreview.tsx +183 -0
- package/src/renderer/components/TranscriptionTierSelector.tsx +640 -0
- package/src/renderer/components/UpdateNotification.tsx +377 -0
- package/src/renderer/components/WindowSelector.tsx +947 -0
- package/src/renderer/components/index.ts +99 -0
- package/src/renderer/components/primitives/ApiKeyInput.tsx +98 -0
- package/src/renderer/components/primitives/ColorPicker.tsx +65 -0
- package/src/renderer/components/primitives/DangerButton.tsx +45 -0
- package/src/renderer/components/primitives/DirectoryPicker.tsx +41 -0
- package/src/renderer/components/primitives/Dropdown.tsx +34 -0
- package/src/renderer/components/primitives/KeyRecorder.tsx +117 -0
- package/src/renderer/components/primitives/SettingsSection.tsx +32 -0
- package/src/renderer/components/primitives/Slider.tsx +43 -0
- package/src/renderer/components/primitives/Toggle.tsx +36 -0
- package/src/renderer/components/primitives/index.ts +10 -0
- package/src/renderer/components/settings/AdvancedTab.tsx +174 -0
- package/src/renderer/components/settings/AppearanceTab.tsx +77 -0
- package/src/renderer/components/settings/GeneralTab.tsx +40 -0
- package/src/renderer/components/settings/HotkeysTab.tsx +79 -0
- package/src/renderer/components/settings/RecordingTab.tsx +84 -0
- package/src/renderer/components/settings/index.ts +9 -0
- package/src/renderer/components/settings/settingsStyles.ts +673 -0
- package/src/renderer/components/settings/tabConfig.tsx +85 -0
- package/src/renderer/components/settings/useSettingsPanel.ts +447 -0
- package/src/renderer/contexts/ProcessingContext.tsx +227 -0
- package/src/renderer/contexts/RecordingContext.tsx +683 -0
- package/src/renderer/contexts/UIContext.tsx +326 -0
- package/src/renderer/contexts/index.ts +24 -0
- package/src/renderer/donateMessages.ts +69 -0
- package/src/renderer/hooks/index.ts +75 -0
- package/src/renderer/hooks/useAnimation.tsx +544 -0
- package/src/renderer/hooks/useTheme.ts +313 -0
- package/src/renderer/index.html +26 -0
- package/src/renderer/main.tsx +52 -0
- package/src/renderer/styles/animations.css +1093 -0
- package/src/renderer/styles/app-shell.css +662 -0
- package/src/renderer/styles/globals.css +515 -0
- package/src/renderer/styles/theme.ts +578 -0
- package/src/renderer/types/electron.d.ts +385 -0
- package/src/shared/hotkeys.ts +283 -0
- package/src/shared/types.ts +809 -0
- package/tests/clipboard.test.ts +228 -0
- package/tests/e2e/criticalPaths.test.ts +594 -0
- package/tests/feedbackAnalyzer.test.ts +303 -0
- package/tests/integration/sessionFlow.test.ts +583 -0
- package/tests/markdownGenerator.test.ts +418 -0
- package/tests/output.test.ts +96 -0
- package/tests/setup.ts +486 -0
- package/tests/unit/appIntegration.test.ts +676 -0
- package/tests/unit/appViewState.test.ts +281 -0
- package/tests/unit/audioIpcChannels.test.ts +17 -0
- package/tests/unit/exportService.test.ts +492 -0
- package/tests/unit/hotkeys.test.ts +92 -0
- package/tests/unit/navigationPreload.test.ts +94 -0
- package/tests/unit/onboardingFlow.test.ts +345 -0
- package/tests/unit/permissionManager.test.ts +175 -0
- package/tests/unit/permissionManagerExpanded.test.ts +296 -0
- package/tests/unit/screenRecordingRenderer.test.ts +368 -0
- package/tests/unit/sessionController.test.ts +515 -0
- package/tests/unit/tierManager.test.ts +61 -0
- package/tests/unit/tierManagerExpanded.test.ts +142 -0
- package/tests/unit/transcriptAnalyzer.test.ts +64 -0
- package/tsconfig.json +25 -0
- package/vitest.config.ts +46 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* markupr Theme Hook
|
|
3
|
+
*
|
|
4
|
+
* Provides theme state management and utilities for components.
|
|
5
|
+
* Must be used within a ThemeProvider.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useContext, createContext, useMemo } from 'react';
|
|
9
|
+
import {
|
|
10
|
+
ThemeColors,
|
|
11
|
+
ThemeMode,
|
|
12
|
+
AccentColorKey,
|
|
13
|
+
accentColors,
|
|
14
|
+
darkTheme,
|
|
15
|
+
lightTheme,
|
|
16
|
+
typography,
|
|
17
|
+
spacing,
|
|
18
|
+
shadows,
|
|
19
|
+
borderRadius,
|
|
20
|
+
transitions,
|
|
21
|
+
zIndex,
|
|
22
|
+
generateCSSProperties,
|
|
23
|
+
} from '../styles/theme';
|
|
24
|
+
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Context Types
|
|
27
|
+
// ============================================================================
|
|
28
|
+
|
|
29
|
+
export interface ThemeContextValue {
|
|
30
|
+
// Current state
|
|
31
|
+
mode: ThemeMode;
|
|
32
|
+
accentColor: AccentColorKey;
|
|
33
|
+
isDark: boolean;
|
|
34
|
+
colors: ThemeColors;
|
|
35
|
+
|
|
36
|
+
// Setters
|
|
37
|
+
setMode: (mode: ThemeMode) => void;
|
|
38
|
+
setAccentColor: (color: AccentColorKey) => void;
|
|
39
|
+
toggleMode: () => void;
|
|
40
|
+
|
|
41
|
+
// Design tokens (static)
|
|
42
|
+
typography: typeof typography;
|
|
43
|
+
spacing: typeof spacing;
|
|
44
|
+
shadows: typeof shadows;
|
|
45
|
+
borderRadius: typeof borderRadius;
|
|
46
|
+
transitions: typeof transitions;
|
|
47
|
+
zIndex: typeof zIndex;
|
|
48
|
+
|
|
49
|
+
// Utilities
|
|
50
|
+
getAccentColors: () => typeof accentColors;
|
|
51
|
+
getCSSVar: (name: string) => string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Create context with null default (must be used within provider)
|
|
55
|
+
export const ThemeContext = createContext<ThemeContextValue | null>(null);
|
|
56
|
+
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// Main Hook
|
|
59
|
+
// ============================================================================
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Access the theme context and utilities
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```tsx
|
|
66
|
+
* const { isDark, colors, toggleMode, setAccentColor } = useTheme();
|
|
67
|
+
*
|
|
68
|
+
* // Use colors directly
|
|
69
|
+
* <div style={{ background: colors.bg.primary }}>
|
|
70
|
+
*
|
|
71
|
+
* // Or use CSS variables
|
|
72
|
+
* <div className="bg-[var(--bg-primary)]">
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export function useTheme(): ThemeContextValue {
|
|
76
|
+
const context = useContext(ThemeContext);
|
|
77
|
+
|
|
78
|
+
if (!context) {
|
|
79
|
+
throw new Error(
|
|
80
|
+
'useTheme must be used within a ThemeProvider. ' +
|
|
81
|
+
'Make sure to wrap your app with <ThemeProvider>.'
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return context;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ============================================================================
|
|
89
|
+
// Utility Hooks
|
|
90
|
+
// ============================================================================
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Returns just the dark mode state - useful for conditional rendering
|
|
94
|
+
*/
|
|
95
|
+
export function useIsDarkMode(): boolean {
|
|
96
|
+
const { isDark } = useTheme();
|
|
97
|
+
return isDark;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Returns the current accent color details
|
|
102
|
+
*/
|
|
103
|
+
export function useAccentColor() {
|
|
104
|
+
const { accentColor } = useTheme();
|
|
105
|
+
return useMemo(
|
|
106
|
+
() => ({
|
|
107
|
+
key: accentColor,
|
|
108
|
+
...accentColors[accentColor],
|
|
109
|
+
}),
|
|
110
|
+
[accentColor]
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Get a specific color from the theme
|
|
116
|
+
*/
|
|
117
|
+
export function useThemeColor<
|
|
118
|
+
Category extends keyof ThemeColors,
|
|
119
|
+
Color extends keyof ThemeColors[Category]
|
|
120
|
+
>(category: Category, color: Color): string {
|
|
121
|
+
const { colors } = useTheme();
|
|
122
|
+
return colors[category][color] as string;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Generate inline styles from theme values
|
|
127
|
+
*/
|
|
128
|
+
export function useThemeStyles<T extends Record<string, unknown>>(
|
|
129
|
+
stylesFn: (theme: {
|
|
130
|
+
colors: ThemeColors;
|
|
131
|
+
isDark: boolean;
|
|
132
|
+
spacing: typeof spacing;
|
|
133
|
+
borderRadius: typeof borderRadius;
|
|
134
|
+
shadows: typeof shadows;
|
|
135
|
+
transitions: typeof transitions;
|
|
136
|
+
}) => T
|
|
137
|
+
): T {
|
|
138
|
+
const { colors, isDark } = useTheme();
|
|
139
|
+
|
|
140
|
+
return useMemo(
|
|
141
|
+
() =>
|
|
142
|
+
stylesFn({
|
|
143
|
+
colors,
|
|
144
|
+
isDark,
|
|
145
|
+
spacing,
|
|
146
|
+
borderRadius,
|
|
147
|
+
shadows,
|
|
148
|
+
transitions,
|
|
149
|
+
}),
|
|
150
|
+
[colors, isDark, stylesFn]
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ============================================================================
|
|
155
|
+
// Theme Builder (for provider use)
|
|
156
|
+
// ============================================================================
|
|
157
|
+
|
|
158
|
+
export interface ThemeBuilderOptions {
|
|
159
|
+
mode: ThemeMode;
|
|
160
|
+
accentColor: AccentColorKey;
|
|
161
|
+
systemPrefersDark: boolean;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Builds the complete theme from options
|
|
166
|
+
* Used internally by ThemeProvider
|
|
167
|
+
*/
|
|
168
|
+
export function buildTheme(options: ThemeBuilderOptions) {
|
|
169
|
+
const { mode, accentColor, systemPrefersDark } = options;
|
|
170
|
+
|
|
171
|
+
// Determine if dark mode is active
|
|
172
|
+
const isDark = mode === 'system' ? systemPrefersDark : mode === 'dark';
|
|
173
|
+
|
|
174
|
+
// Get base theme
|
|
175
|
+
const baseColors = isDark ? darkTheme : lightTheme;
|
|
176
|
+
|
|
177
|
+
// Get accent color values
|
|
178
|
+
const accent = accentColors[accentColor];
|
|
179
|
+
|
|
180
|
+
// Merge accent into theme colors
|
|
181
|
+
const colors: ThemeColors = {
|
|
182
|
+
...baseColors,
|
|
183
|
+
accent: {
|
|
184
|
+
default: accent.default,
|
|
185
|
+
hover: accent.hover,
|
|
186
|
+
active: accent.active,
|
|
187
|
+
subtle: `${accent.default}1a`, // 10% opacity
|
|
188
|
+
muted: `${accent.default}40`, // 25% opacity
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// Generate CSS custom properties
|
|
193
|
+
const cssProperties = generateCSSProperties(colors, accent);
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
isDark,
|
|
197
|
+
colors,
|
|
198
|
+
cssProperties,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// ============================================================================
|
|
203
|
+
// Storage Keys
|
|
204
|
+
// ============================================================================
|
|
205
|
+
|
|
206
|
+
export const THEME_STORAGE_KEYS = {
|
|
207
|
+
mode: 'markupr-theme-mode',
|
|
208
|
+
accent: 'markupr-theme-accent',
|
|
209
|
+
} as const;
|
|
210
|
+
|
|
211
|
+
// ============================================================================
|
|
212
|
+
// CSS Variable Helpers
|
|
213
|
+
// ============================================================================
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get a CSS variable value from the document
|
|
217
|
+
*/
|
|
218
|
+
export function getCSSVariable(name: string): string {
|
|
219
|
+
if (typeof document === 'undefined') return '';
|
|
220
|
+
|
|
221
|
+
const value = getComputedStyle(document.documentElement)
|
|
222
|
+
.getPropertyValue(name)
|
|
223
|
+
.trim();
|
|
224
|
+
|
|
225
|
+
return value;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Set a CSS variable on the document
|
|
230
|
+
*/
|
|
231
|
+
export function setCSSVariable(name: string, value: string): void {
|
|
232
|
+
if (typeof document === 'undefined') return;
|
|
233
|
+
document.documentElement.style.setProperty(name, value);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Apply all CSS properties to document root
|
|
238
|
+
*/
|
|
239
|
+
export function applyCSSProperties(properties: Record<string, string>): void {
|
|
240
|
+
if (typeof document === 'undefined') return;
|
|
241
|
+
|
|
242
|
+
const root = document.documentElement;
|
|
243
|
+
Object.entries(properties).forEach(([key, value]) => {
|
|
244
|
+
root.style.setProperty(key, value);
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ============================================================================
|
|
249
|
+
// Color Utilities
|
|
250
|
+
// ============================================================================
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Convert hex to RGB values
|
|
254
|
+
*/
|
|
255
|
+
export function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
|
|
256
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
257
|
+
return result
|
|
258
|
+
? {
|
|
259
|
+
r: parseInt(result[1], 16),
|
|
260
|
+
g: parseInt(result[2], 16),
|
|
261
|
+
b: parseInt(result[3], 16),
|
|
262
|
+
}
|
|
263
|
+
: null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Convert RGB to hex
|
|
268
|
+
*/
|
|
269
|
+
export function rgbToHex(r: number, g: number, b: number): string {
|
|
270
|
+
return '#' + [r, g, b].map((x) => x.toString(16).padStart(2, '0')).join('');
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Get contrasting text color (black or white) for a background
|
|
275
|
+
*/
|
|
276
|
+
export function getContrastColor(backgroundColor: string): 'white' | 'black' {
|
|
277
|
+
const rgb = hexToRgb(backgroundColor);
|
|
278
|
+
if (!rgb) return 'white';
|
|
279
|
+
|
|
280
|
+
// Calculate relative luminance
|
|
281
|
+
const luminance = (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;
|
|
282
|
+
|
|
283
|
+
return luminance > 0.5 ? 'black' : 'white';
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Adjust color brightness
|
|
288
|
+
*/
|
|
289
|
+
export function adjustBrightness(hex: string, percent: number): string {
|
|
290
|
+
const rgb = hexToRgb(hex);
|
|
291
|
+
if (!rgb) return hex;
|
|
292
|
+
|
|
293
|
+
const adjust = (value: number) =>
|
|
294
|
+
Math.min(255, Math.max(0, Math.round(value + (value * percent) / 100)));
|
|
295
|
+
|
|
296
|
+
return rgbToHex(adjust(rgb.r), adjust(rgb.g), adjust(rgb.b));
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Add alpha to a hex color
|
|
301
|
+
*/
|
|
302
|
+
export function withAlpha(hex: string, alpha: number): string {
|
|
303
|
+
const rgb = hexToRgb(hex);
|
|
304
|
+
if (!rgb) return hex;
|
|
305
|
+
|
|
306
|
+
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// ============================================================================
|
|
310
|
+
// Default Export
|
|
311
|
+
// ============================================================================
|
|
312
|
+
|
|
313
|
+
export default useTheme;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'" />
|
|
7
|
+
<title>markupr</title>
|
|
8
|
+
<style>
|
|
9
|
+
* {
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
}
|
|
14
|
+
html, body, #root {
|
|
15
|
+
width: 100%;
|
|
16
|
+
height: 100%;
|
|
17
|
+
overflow: hidden;
|
|
18
|
+
background: transparent;
|
|
19
|
+
}
|
|
20
|
+
</style>
|
|
21
|
+
</head>
|
|
22
|
+
<body>
|
|
23
|
+
<div id="root"></div>
|
|
24
|
+
<script type="module" src="./main.tsx"></script>
|
|
25
|
+
</body>
|
|
26
|
+
</html>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* markupr - Renderer Entry Point
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { createRoot } from 'react-dom/client';
|
|
7
|
+
import AppWrapper from './AppWrapper';
|
|
8
|
+
import { ErrorBoundary } from './components/ErrorBoundary';
|
|
9
|
+
import { ThemeProvider } from './components/ThemeProvider';
|
|
10
|
+
import { initAudioCapture, destroyAudioCapture } from './audio/AudioCaptureRenderer';
|
|
11
|
+
|
|
12
|
+
// Import global styles (includes CSS reset and theme utilities)
|
|
13
|
+
import './styles/globals.css';
|
|
14
|
+
// Import premium animation styles
|
|
15
|
+
import './styles/animations.css';
|
|
16
|
+
|
|
17
|
+
const container = document.getElementById('root');
|
|
18
|
+
if (!container) {
|
|
19
|
+
throw new Error('Root element not found');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Initialize renderer-side audio capture bridge for main-process orchestration.
|
|
23
|
+
initAudioCapture();
|
|
24
|
+
window.addEventListener('beforeunload', () => {
|
|
25
|
+
destroyAudioCapture();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Global error handler for uncaught errors
|
|
29
|
+
window.addEventListener('error', (event) => {
|
|
30
|
+
console.error('[Global Error Handler]', event.error);
|
|
31
|
+
// Could report to main process here
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
window.addEventListener('unhandledrejection', (event) => {
|
|
35
|
+
console.error('[Unhandled Promise Rejection]', event.reason);
|
|
36
|
+
// Could report to main process here
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const root = createRoot(container);
|
|
40
|
+
root.render(
|
|
41
|
+
<React.StrictMode>
|
|
42
|
+
<ThemeProvider defaultMode="light" defaultAccentColor="blue">
|
|
43
|
+
<ErrorBoundary
|
|
44
|
+
onError={(error, errorInfo) => {
|
|
45
|
+
console.error('[App ErrorBoundary]', error, errorInfo);
|
|
46
|
+
}}
|
|
47
|
+
>
|
|
48
|
+
<AppWrapper />
|
|
49
|
+
</ErrorBoundary>
|
|
50
|
+
</ThemeProvider>
|
|
51
|
+
</React.StrictMode>
|
|
52
|
+
);
|