@djangocfg/ui-core 2.1.157 → 2.1.159
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 +44 -2
- package/package.json +10 -5
- package/src/styles/palette/index.ts +55 -0
- package/src/styles/palette/types.ts +90 -0
- package/src/styles/palette/useThemePalette.ts +233 -0
- package/src/styles/palette/utils.ts +91 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @djangocfg/ui-core
|
|
2
2
|
|
|
3
|
-
Pure React UI library with
|
|
3
|
+
Pure React UI library with 60+ components built on Radix UI + Tailwind CSS v4.
|
|
4
4
|
|
|
5
5
|
**No Next.js dependencies** — works with Electron, Vite, CRA, and any React environment.
|
|
6
6
|
|
|
@@ -19,9 +19,10 @@ pnpm add @djangocfg/ui-core
|
|
|
19
19
|
| Package | Use Case |
|
|
20
20
|
|---------|----------|
|
|
21
21
|
| `@djangocfg/ui-core` | Electron, Vite, CRA, any React app |
|
|
22
|
+
| `@djangocfg/ui-tools` | Heavy tools with lazy loading |
|
|
22
23
|
| `@djangocfg/ui-nextjs` | Next.js apps (extends ui-core) |
|
|
23
24
|
|
|
24
|
-
## Components (60)
|
|
25
|
+
## Components (60+)
|
|
25
26
|
|
|
26
27
|
### Forms (17)
|
|
27
28
|
`Label` `Button` `ButtonLink` `Input` `Checkbox` `RadioGroup` `Select` `Textarea` `Switch` `Slider` `Combobox` `MultiSelect` `CountrySelect` `InputOTP` `PhoneInput` `Form` `Field`
|
|
@@ -62,6 +63,46 @@ pnpm add @djangocfg/ui-core
|
|
|
62
63
|
| `useBrowserDetect` | Browser detection (Chrome, Safari, in-app browsers, etc.) |
|
|
63
64
|
| `useDeviceDetect` | Device detection (mobile, tablet, desktop, OS, etc.) |
|
|
64
65
|
|
|
66
|
+
## Theme Palette Hooks
|
|
67
|
+
|
|
68
|
+
Hooks for accessing theme colors from CSS variables (useful for charts, diagrams, etc.):
|
|
69
|
+
|
|
70
|
+
| Hook | Description |
|
|
71
|
+
|------|-------------|
|
|
72
|
+
| `useThemePalette()` | Full color palette from CSS variables |
|
|
73
|
+
| `useStylePresets()` | Pre-built style configs for diagrams |
|
|
74
|
+
| `useBoxColors()` | Colors for boxes/containers |
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
import { useStylePresets, useBoxColors } from '@djangocfg/ui-core/styles/palette';
|
|
78
|
+
|
|
79
|
+
function MyChart() {
|
|
80
|
+
const presets = useStylePresets();
|
|
81
|
+
// presets.success = { fill: '#22c55e', stroke: '#16a34a', color: '#ffffff' }
|
|
82
|
+
// presets.warning = { fill: '#f59e0b', stroke: '#d97706', color: '#000000' }
|
|
83
|
+
// presets.danger = { fill: '#ef4444', stroke: '#dc2626', color: '#ffffff' }
|
|
84
|
+
// presets.info = { fill: '#3b82f6', stroke: '#2563eb', color: '#ffffff' }
|
|
85
|
+
// presets.primary = { fill: '#...', stroke: '#...', color: '#...' }
|
|
86
|
+
|
|
87
|
+
const boxes = useBoxColors();
|
|
88
|
+
// boxes.primary = 'rgba(59, 130, 246, 0.2)'
|
|
89
|
+
// boxes.success = 'rgba(34, 197, 94, 0.2)'
|
|
90
|
+
// etc.
|
|
91
|
+
|
|
92
|
+
return <Chart colors={[presets.success.fill, presets.warning.fill]} />;
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Color Utilities
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
import { hslToHex, hslToRgbString, hslToRgba } from '@djangocfg/ui-core/styles/palette';
|
|
100
|
+
|
|
101
|
+
hslToHex('217 91% 60%'); // '#3b82f6'
|
|
102
|
+
hslToRgbString('217 91% 60%'); // 'rgb(59, 130, 246)'
|
|
103
|
+
hslToRgba('217 91% 60%', 0.5); // 'rgba(59, 130, 246, 0.5)'
|
|
104
|
+
```
|
|
105
|
+
|
|
65
106
|
## Dialog Service
|
|
66
107
|
|
|
67
108
|
Universal dialog service to replace native `window.alert`, `window.confirm`, `window.prompt` with beautiful shadcn dialogs.
|
|
@@ -153,6 +194,7 @@ import '@djangocfg/ui-core/styles/globals';
|
|
|
153
194
|
| `@djangocfg/ui-core/lib` | Utilities (cn, etc.) |
|
|
154
195
|
| `@djangocfg/ui-core/lib/dialog-service` | Dialog service |
|
|
155
196
|
| `@djangocfg/ui-core/styles` | CSS |
|
|
197
|
+
| `@djangocfg/ui-core/styles/palette` | Theme palette hooks & utilities |
|
|
156
198
|
|
|
157
199
|
## What's NOT included (use ui-nextjs)
|
|
158
200
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/ui-core",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.159",
|
|
4
4
|
"description": "Pure React UI component library without Next.js dependencies - for Electron, Vite, CRA apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ui-components",
|
|
@@ -57,7 +57,12 @@
|
|
|
57
57
|
"./styles/globals": "./src/styles/globals.css",
|
|
58
58
|
"./styles/theme": "./src/styles/theme.css",
|
|
59
59
|
"./styles/base": "./src/styles/base.css",
|
|
60
|
-
"./styles/utilities": "./src/styles/utilities.css"
|
|
60
|
+
"./styles/utilities": "./src/styles/utilities.css",
|
|
61
|
+
"./styles/palette": {
|
|
62
|
+
"types": "./src/styles/palette/index.ts",
|
|
63
|
+
"import": "./src/styles/palette/index.ts",
|
|
64
|
+
"require": "./src/styles/palette/index.ts"
|
|
65
|
+
}
|
|
61
66
|
},
|
|
62
67
|
"files": [
|
|
63
68
|
"dist",
|
|
@@ -71,7 +76,7 @@
|
|
|
71
76
|
"playground": "playground dev"
|
|
72
77
|
},
|
|
73
78
|
"peerDependencies": {
|
|
74
|
-
"@djangocfg/i18n": "^2.1.
|
|
79
|
+
"@djangocfg/i18n": "^2.1.159",
|
|
75
80
|
"react-device-detect": "^2.2.3",
|
|
76
81
|
"consola": "^3.4.2",
|
|
77
82
|
"lucide-react": "^0.545.0",
|
|
@@ -133,9 +138,9 @@
|
|
|
133
138
|
"vaul": "1.1.2"
|
|
134
139
|
},
|
|
135
140
|
"devDependencies": {
|
|
136
|
-
"@djangocfg/i18n": "^2.1.
|
|
141
|
+
"@djangocfg/i18n": "^2.1.159",
|
|
137
142
|
"@djangocfg/playground": "workspace:*",
|
|
138
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
143
|
+
"@djangocfg/typescript-config": "^2.1.159",
|
|
139
144
|
"@types/node": "^24.7.2",
|
|
140
145
|
"@types/react": "^19.1.0",
|
|
141
146
|
"@types/react-dom": "^19.1.0",
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Palette
|
|
3
|
+
*
|
|
4
|
+
* Hooks and utilities for accessing theme colors programmatically.
|
|
5
|
+
* Colors are read directly from CSS variables, ensuring consistency
|
|
6
|
+
* with the theme system.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* import {
|
|
11
|
+
* useThemePalette,
|
|
12
|
+
* useStylePresets,
|
|
13
|
+
* useBoxColors
|
|
14
|
+
* } from '@djangocfg/ui-core/styles/palette';
|
|
15
|
+
*
|
|
16
|
+
* function MyComponent() {
|
|
17
|
+
* const palette = useThemePalette();
|
|
18
|
+
* const presets = useStylePresets();
|
|
19
|
+
* const boxes = useBoxColors();
|
|
20
|
+
*
|
|
21
|
+
* // Use in canvas
|
|
22
|
+
* ctx.fillStyle = palette.primary;
|
|
23
|
+
*
|
|
24
|
+
* // Use in Mermaid FlowDiagram
|
|
25
|
+
* flow.style.define('success', presets.success);
|
|
26
|
+
*
|
|
27
|
+
* // Use in Mermaid SequenceDiagram rect
|
|
28
|
+
* rect(boxes.primary, () => { ... });
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @module ui-core/styles/palette
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
// Types
|
|
36
|
+
export type {
|
|
37
|
+
ThemePalette,
|
|
38
|
+
StyleColors,
|
|
39
|
+
StylePresets,
|
|
40
|
+
BoxColors,
|
|
41
|
+
} from './types';
|
|
42
|
+
|
|
43
|
+
// Hooks
|
|
44
|
+
export {
|
|
45
|
+
useThemePalette,
|
|
46
|
+
useStylePresets,
|
|
47
|
+
useBoxColors,
|
|
48
|
+
} from './useThemePalette';
|
|
49
|
+
|
|
50
|
+
// Utils (for advanced use)
|
|
51
|
+
export {
|
|
52
|
+
hslToHex,
|
|
53
|
+
hslToRgbString,
|
|
54
|
+
hslToRgba,
|
|
55
|
+
} from './utils';
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Palette Types
|
|
3
|
+
* @module ui-core/styles/palette/types
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Complete semantic color palette for programmatic use
|
|
8
|
+
* (Canvas, SVG, Mermaid diagrams, etc.)
|
|
9
|
+
*/
|
|
10
|
+
export interface ThemePalette {
|
|
11
|
+
// Base Colors
|
|
12
|
+
background: string;
|
|
13
|
+
foreground: string;
|
|
14
|
+
card: string;
|
|
15
|
+
cardForeground: string;
|
|
16
|
+
popover: string;
|
|
17
|
+
popoverForeground: string;
|
|
18
|
+
muted: string;
|
|
19
|
+
mutedForeground: string;
|
|
20
|
+
border: string;
|
|
21
|
+
input: string;
|
|
22
|
+
ring: string;
|
|
23
|
+
|
|
24
|
+
// Semantic Colors
|
|
25
|
+
primary: string;
|
|
26
|
+
primaryForeground: string;
|
|
27
|
+
secondary: string;
|
|
28
|
+
secondaryForeground: string;
|
|
29
|
+
accent: string;
|
|
30
|
+
accentForeground: string;
|
|
31
|
+
destructive: string;
|
|
32
|
+
destructiveForeground: string;
|
|
33
|
+
|
|
34
|
+
// Status Colors
|
|
35
|
+
success: string;
|
|
36
|
+
successForeground: string;
|
|
37
|
+
warning: string;
|
|
38
|
+
warningForeground: string;
|
|
39
|
+
info: string;
|
|
40
|
+
infoForeground: string;
|
|
41
|
+
|
|
42
|
+
// Chart Colors
|
|
43
|
+
chart1: string;
|
|
44
|
+
chart2: string;
|
|
45
|
+
chart3: string;
|
|
46
|
+
chart4: string;
|
|
47
|
+
chart5: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Style colors for elements (fill, stroke, text)
|
|
52
|
+
*/
|
|
53
|
+
export interface StyleColors {
|
|
54
|
+
fill: string;
|
|
55
|
+
stroke: string;
|
|
56
|
+
color: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Style presets for common UI patterns
|
|
61
|
+
*/
|
|
62
|
+
export interface StylePresets {
|
|
63
|
+
primary: StyleColors;
|
|
64
|
+
secondary: StyleColors;
|
|
65
|
+
success: StyleColors;
|
|
66
|
+
danger: StyleColors;
|
|
67
|
+
warning: StyleColors;
|
|
68
|
+
info: StyleColors;
|
|
69
|
+
muted: StyleColors;
|
|
70
|
+
card: StyleColors;
|
|
71
|
+
accent: StyleColors;
|
|
72
|
+
chart1: StyleColors;
|
|
73
|
+
chart2: StyleColors;
|
|
74
|
+
chart3: StyleColors;
|
|
75
|
+
chart4: StyleColors;
|
|
76
|
+
chart5: StyleColors;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Background colors for boxes/regions
|
|
81
|
+
* (e.g., Mermaid rect blocks, highlighted sections)
|
|
82
|
+
*/
|
|
83
|
+
export interface BoxColors {
|
|
84
|
+
primary: string;
|
|
85
|
+
success: string;
|
|
86
|
+
warning: string;
|
|
87
|
+
danger: string;
|
|
88
|
+
info: string;
|
|
89
|
+
muted: string;
|
|
90
|
+
}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hook to get theme colors from CSS variables
|
|
5
|
+
*
|
|
6
|
+
* Reads colors directly from document, converting HSL to hex for compatibility
|
|
7
|
+
* with Canvas, SVG, Mermaid, and other tools that don't support CSS variables.
|
|
8
|
+
*
|
|
9
|
+
* @module ui-core/styles/palette/useThemePalette
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { useMemo } from 'react';
|
|
13
|
+
import { useResolvedTheme } from '../../hooks/useResolvedTheme';
|
|
14
|
+
import { hslToHex, hslToRgba } from './utils';
|
|
15
|
+
import type { ThemePalette, StylePresets, BoxColors } from './types';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Read a CSS variable from document and convert to hex
|
|
19
|
+
*/
|
|
20
|
+
function getCssColorAsHex(varName: string): string {
|
|
21
|
+
if (typeof document === 'undefined') return '#000000';
|
|
22
|
+
|
|
23
|
+
const style = getComputedStyle(document.documentElement);
|
|
24
|
+
const value = style.getPropertyValue(`--${varName}`).trim();
|
|
25
|
+
|
|
26
|
+
if (!value) return '#000000';
|
|
27
|
+
|
|
28
|
+
// If already hex, return as-is
|
|
29
|
+
if (value.startsWith('#')) return value;
|
|
30
|
+
|
|
31
|
+
// Convert HSL to hex
|
|
32
|
+
return hslToHex(value);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Read a CSS variable from document and convert to rgba with opacity
|
|
37
|
+
*/
|
|
38
|
+
function getCssColorAsRgba(varName: string, alpha: number): string {
|
|
39
|
+
if (typeof document === 'undefined') return `rgba(0, 0, 0, ${alpha})`;
|
|
40
|
+
|
|
41
|
+
const style = getComputedStyle(document.documentElement);
|
|
42
|
+
const value = style.getPropertyValue(`--${varName}`).trim();
|
|
43
|
+
|
|
44
|
+
if (!value) return `rgba(0, 0, 0, ${alpha})`;
|
|
45
|
+
|
|
46
|
+
return hslToRgba(value, alpha);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Hook to get the full theme palette from CSS variables
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* function MyComponent() {
|
|
55
|
+
* const palette = useThemePalette();
|
|
56
|
+
*
|
|
57
|
+
* // Use in canvas
|
|
58
|
+
* ctx.fillStyle = palette.primary;
|
|
59
|
+
*
|
|
60
|
+
* // Use in inline styles
|
|
61
|
+
* <div style={{ backgroundColor: palette.success }} />
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export function useThemePalette(): ThemePalette {
|
|
66
|
+
const theme = useResolvedTheme();
|
|
67
|
+
|
|
68
|
+
return useMemo(() => {
|
|
69
|
+
return {
|
|
70
|
+
// Base colors
|
|
71
|
+
background: getCssColorAsHex('background'),
|
|
72
|
+
foreground: getCssColorAsHex('foreground'),
|
|
73
|
+
card: getCssColorAsHex('card'),
|
|
74
|
+
cardForeground: getCssColorAsHex('card-foreground'),
|
|
75
|
+
popover: getCssColorAsHex('popover'),
|
|
76
|
+
popoverForeground: getCssColorAsHex('popover-foreground'),
|
|
77
|
+
muted: getCssColorAsHex('muted'),
|
|
78
|
+
mutedForeground: getCssColorAsHex('muted-foreground'),
|
|
79
|
+
border: getCssColorAsHex('border'),
|
|
80
|
+
input: getCssColorAsHex('input'),
|
|
81
|
+
ring: getCssColorAsHex('ring'),
|
|
82
|
+
|
|
83
|
+
// Semantic colors
|
|
84
|
+
primary: getCssColorAsHex('primary'),
|
|
85
|
+
primaryForeground: getCssColorAsHex('primary-foreground'),
|
|
86
|
+
secondary: getCssColorAsHex('secondary'),
|
|
87
|
+
secondaryForeground: getCssColorAsHex('secondary-foreground'),
|
|
88
|
+
accent: getCssColorAsHex('accent'),
|
|
89
|
+
accentForeground: getCssColorAsHex('accent-foreground'),
|
|
90
|
+
destructive: getCssColorAsHex('destructive'),
|
|
91
|
+
destructiveForeground: getCssColorAsHex('destructive-foreground'),
|
|
92
|
+
|
|
93
|
+
// Status colors (mapped from chart colors)
|
|
94
|
+
success: getCssColorAsHex('chart-2'), // Green
|
|
95
|
+
successForeground: '#ffffff',
|
|
96
|
+
warning: getCssColorAsHex('chart-4'), // Orange
|
|
97
|
+
warningForeground: '#ffffff',
|
|
98
|
+
info: getCssColorAsHex('chart-1'), // Blue (same as primary)
|
|
99
|
+
infoForeground: '#ffffff',
|
|
100
|
+
|
|
101
|
+
// Chart colors
|
|
102
|
+
chart1: getCssColorAsHex('chart-1'),
|
|
103
|
+
chart2: getCssColorAsHex('chart-2'),
|
|
104
|
+
chart3: getCssColorAsHex('chart-3'),
|
|
105
|
+
chart4: getCssColorAsHex('chart-4'),
|
|
106
|
+
chart5: getCssColorAsHex('chart-5'),
|
|
107
|
+
};
|
|
108
|
+
}, [theme]);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Hook to get style presets for elements (nodes, boxes, etc.)
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```tsx
|
|
116
|
+
* function MyDiagram() {
|
|
117
|
+
* const presets = useStylePresets();
|
|
118
|
+
*
|
|
119
|
+
* // Use in Mermaid FlowDiagram
|
|
120
|
+
* flow.style.define('success', presets.success);
|
|
121
|
+
* flow.style.define('primary', presets.primary);
|
|
122
|
+
* }
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
export function useStylePresets(): StylePresets {
|
|
126
|
+
const palette = useThemePalette();
|
|
127
|
+
|
|
128
|
+
return useMemo(() => ({
|
|
129
|
+
primary: {
|
|
130
|
+
fill: palette.primary,
|
|
131
|
+
stroke: palette.primary,
|
|
132
|
+
color: palette.primaryForeground,
|
|
133
|
+
},
|
|
134
|
+
secondary: {
|
|
135
|
+
fill: palette.secondary,
|
|
136
|
+
stroke: palette.secondary,
|
|
137
|
+
color: palette.secondaryForeground,
|
|
138
|
+
},
|
|
139
|
+
success: {
|
|
140
|
+
fill: palette.success,
|
|
141
|
+
stroke: palette.success,
|
|
142
|
+
color: palette.successForeground,
|
|
143
|
+
},
|
|
144
|
+
danger: {
|
|
145
|
+
fill: palette.destructive,
|
|
146
|
+
stroke: palette.destructive,
|
|
147
|
+
color: palette.destructiveForeground,
|
|
148
|
+
},
|
|
149
|
+
warning: {
|
|
150
|
+
fill: palette.warning,
|
|
151
|
+
stroke: palette.warning,
|
|
152
|
+
color: palette.warningForeground,
|
|
153
|
+
},
|
|
154
|
+
info: {
|
|
155
|
+
fill: palette.info,
|
|
156
|
+
stroke: palette.info,
|
|
157
|
+
color: palette.infoForeground,
|
|
158
|
+
},
|
|
159
|
+
muted: {
|
|
160
|
+
fill: palette.muted,
|
|
161
|
+
stroke: palette.border,
|
|
162
|
+
color: palette.mutedForeground,
|
|
163
|
+
},
|
|
164
|
+
card: {
|
|
165
|
+
fill: palette.card,
|
|
166
|
+
stroke: palette.border,
|
|
167
|
+
color: palette.cardForeground,
|
|
168
|
+
},
|
|
169
|
+
accent: {
|
|
170
|
+
fill: palette.accent,
|
|
171
|
+
stroke: palette.border,
|
|
172
|
+
color: palette.accentForeground,
|
|
173
|
+
},
|
|
174
|
+
chart1: {
|
|
175
|
+
fill: palette.chart1,
|
|
176
|
+
stroke: palette.chart1,
|
|
177
|
+
color: palette.primaryForeground,
|
|
178
|
+
},
|
|
179
|
+
chart2: {
|
|
180
|
+
fill: palette.chart2,
|
|
181
|
+
stroke: palette.chart2,
|
|
182
|
+
color: palette.primaryForeground,
|
|
183
|
+
},
|
|
184
|
+
chart3: {
|
|
185
|
+
fill: palette.chart3,
|
|
186
|
+
stroke: palette.chart3,
|
|
187
|
+
color: palette.primaryForeground,
|
|
188
|
+
},
|
|
189
|
+
chart4: {
|
|
190
|
+
fill: palette.chart4,
|
|
191
|
+
stroke: palette.chart4,
|
|
192
|
+
color: palette.primaryForeground,
|
|
193
|
+
},
|
|
194
|
+
chart5: {
|
|
195
|
+
fill: palette.chart5,
|
|
196
|
+
stroke: palette.chart5,
|
|
197
|
+
color: palette.primaryForeground,
|
|
198
|
+
},
|
|
199
|
+
}), [palette]);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Hook to get box/region colors (e.g., for Mermaid rect blocks)
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```tsx
|
|
207
|
+
* function MySequenceDiagram() {
|
|
208
|
+
* const boxes = useBoxColors();
|
|
209
|
+
*
|
|
210
|
+
* // Use in Mermaid SequenceDiagram
|
|
211
|
+
* rect(boxes.primary, () => {
|
|
212
|
+
* d.Alice.sync.Bob.msg('Hello');
|
|
213
|
+
* });
|
|
214
|
+
* }
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
export function useBoxColors(): BoxColors {
|
|
218
|
+
const theme = useResolvedTheme();
|
|
219
|
+
|
|
220
|
+
return useMemo(() => {
|
|
221
|
+
// Semi-transparent backgrounds for boxes
|
|
222
|
+
const alpha = theme === 'dark' ? 0.3 : 0.15;
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
primary: getCssColorAsRgba('primary', alpha),
|
|
226
|
+
success: getCssColorAsRgba('chart-2', alpha),
|
|
227
|
+
warning: getCssColorAsRgba('chart-4', alpha),
|
|
228
|
+
danger: getCssColorAsRgba('destructive', alpha),
|
|
229
|
+
info: getCssColorAsRgba('chart-3', alpha),
|
|
230
|
+
muted: getCssColorAsRgba('muted', alpha),
|
|
231
|
+
};
|
|
232
|
+
}, [theme]);
|
|
233
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color conversion utilities
|
|
3
|
+
* @module ui-core/styles/palette/utils
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Parse HSL string from CSS variable (e.g., "217 91% 60%") to components
|
|
8
|
+
*/
|
|
9
|
+
function parseHslString(hsl: string): { h: number; s: number; l: number } | null {
|
|
10
|
+
const match = hsl.trim().match(/^(\d+)\s+(\d+)%\s+(\d+)%$/);
|
|
11
|
+
if (!match) return null;
|
|
12
|
+
return {
|
|
13
|
+
h: parseInt(match[1], 10),
|
|
14
|
+
s: parseInt(match[2], 10),
|
|
15
|
+
l: parseInt(match[3], 10),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Convert HSL to RGB
|
|
21
|
+
*/
|
|
22
|
+
function hslToRgb(h: number, s: number, l: number): { r: number; g: number; b: number } {
|
|
23
|
+
s /= 100;
|
|
24
|
+
l /= 100;
|
|
25
|
+
|
|
26
|
+
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
27
|
+
const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
|
|
28
|
+
const m = l - c / 2;
|
|
29
|
+
|
|
30
|
+
let r = 0, g = 0, b = 0;
|
|
31
|
+
|
|
32
|
+
if (h >= 0 && h < 60) { r = c; g = x; b = 0; }
|
|
33
|
+
else if (h >= 60 && h < 120) { r = x; g = c; b = 0; }
|
|
34
|
+
else if (h >= 120 && h < 180) { r = 0; g = c; b = x; }
|
|
35
|
+
else if (h >= 180 && h < 240) { r = 0; g = x; b = c; }
|
|
36
|
+
else if (h >= 240 && h < 300) { r = x; g = 0; b = c; }
|
|
37
|
+
else { r = c; g = 0; b = x; }
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
r: Math.round((r + m) * 255),
|
|
41
|
+
g: Math.round((g + m) * 255),
|
|
42
|
+
b: Math.round((b + m) * 255),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Convert RGB to hex string
|
|
48
|
+
*/
|
|
49
|
+
function rgbToHex(r: number, g: number, b: number): string {
|
|
50
|
+
const toHex = (n: number) => n.toString(16).padStart(2, '0');
|
|
51
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Convert CSS HSL variable value to hex
|
|
56
|
+
* Input: "217 91% 60%" (from CSS --primary: 217 91% 60%)
|
|
57
|
+
* Output: "#3b82f6"
|
|
58
|
+
*/
|
|
59
|
+
export function hslToHex(hslString: string): string {
|
|
60
|
+
const parsed = parseHslString(hslString);
|
|
61
|
+
if (!parsed) return '#000000';
|
|
62
|
+
|
|
63
|
+
const { r, g, b } = hslToRgb(parsed.h, parsed.s, parsed.l);
|
|
64
|
+
return rgbToHex(r, g, b);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Convert CSS HSL variable value to rgb() string
|
|
69
|
+
* Input: "217 91% 60%"
|
|
70
|
+
* Output: "rgb(59, 130, 246)"
|
|
71
|
+
*/
|
|
72
|
+
export function hslToRgbString(hslString: string): string {
|
|
73
|
+
const parsed = parseHslString(hslString);
|
|
74
|
+
if (!parsed) return 'rgb(0, 0, 0)';
|
|
75
|
+
|
|
76
|
+
const { r, g, b } = hslToRgb(parsed.h, parsed.s, parsed.l);
|
|
77
|
+
return `rgb(${r}, ${g}, ${b})`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Convert CSS HSL variable value to rgba() string with opacity
|
|
82
|
+
* Input: "217 91% 60%", 0.2
|
|
83
|
+
* Output: "rgba(59, 130, 246, 0.2)"
|
|
84
|
+
*/
|
|
85
|
+
export function hslToRgba(hslString: string, alpha: number): string {
|
|
86
|
+
const parsed = parseHslString(hslString);
|
|
87
|
+
if (!parsed) return `rgba(0, 0, 0, ${alpha})`;
|
|
88
|
+
|
|
89
|
+
const { r, g, b } = hslToRgb(parsed.h, parsed.s, parsed.l);
|
|
90
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
91
|
+
}
|