triiiceratops 0.8.1 → 0.9.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/dist/chunks/TriiiceratopsViewer-BGtsfUPF.js +10298 -0
- package/dist/chunks/openseadragon-BTypULhm.js +12427 -0
- package/dist/components/AnnotationOverlay.svelte +288 -0
- package/dist/components/AnnotationOverlay.svelte.d.ts +3 -0
- package/dist/components/CanvasNavigation.svelte +32 -0
- package/dist/components/CanvasNavigation.svelte.d.ts +11 -0
- package/dist/components/DemoHeader.svelte +703 -0
- package/dist/components/DemoHeader.svelte.d.ts +9 -0
- package/dist/components/FloatingMenu.svelte +208 -0
- package/dist/components/FloatingMenu.svelte.d.ts +3 -0
- package/dist/components/LeftFab.svelte +69 -0
- package/dist/components/LeftFab.svelte.d.ts +3 -0
- package/dist/components/MetadataDialog.svelte +151 -0
- package/dist/components/MetadataDialog.svelte.d.ts +3 -0
- package/dist/components/OSDViewer.svelte +260 -0
- package/dist/components/OSDViewer.svelte.d.ts +8 -0
- package/dist/components/SearchPanel.svelte +150 -0
- package/dist/components/SearchPanel.svelte.d.ts +3 -0
- package/dist/components/ThemeToggle.svelte +118 -0
- package/dist/components/ThemeToggle.svelte.d.ts +3 -0
- package/dist/components/ThumbnailGallery.svelte +601 -0
- package/dist/components/ThumbnailGallery.svelte.d.ts +36 -0
- package/dist/components/TriiiceratopsViewer.svelte +434 -0
- package/dist/components/TriiiceratopsViewer.svelte.d.ts +20 -0
- package/dist/components/TriiiceratopsViewerElement.svelte +139 -0
- package/dist/components/TriiiceratopsViewerElement.svelte.d.ts +27 -0
- package/dist/components/TriiiceratopsViewerElementImage.svelte +143 -0
- package/dist/components/TriiiceratopsViewerElementImage.svelte.d.ts +27 -0
- package/dist/custom-element-image.d.ts +1 -0
- package/dist/custom-element-image.js +2 -0
- package/dist/custom-element.d.ts +1 -0
- package/dist/custom-element.js +3 -0
- package/dist/{src/lib/index.d.ts → index.d.ts} +1 -0
- package/dist/index.js +10 -4480
- package/dist/plugins/image-manipulation/ImageManipulationPanel.svelte +134 -0
- package/dist/plugins/image-manipulation/ImageManipulationPanel.svelte.d.ts +10 -0
- package/dist/{src/lib/plugins → plugins}/image-manipulation/ImageManipulationPlugin.svelte.d.ts +2 -2
- package/dist/plugins/image-manipulation/ImageManipulationPlugin.svelte.js +122 -0
- package/dist/{src/lib/plugins → plugins}/image-manipulation/filters.d.ts +1 -1
- package/dist/plugins/image-manipulation/filters.js +48 -0
- package/dist/plugins/image-manipulation/index.js +2 -0
- package/dist/plugins/image-manipulation/types.js +7 -0
- package/dist/state/i18n.svelte.d.ts +4 -0
- package/dist/state/i18n.svelte.js +18 -0
- package/dist/state/manifests.svelte.js +210 -0
- package/dist/state/manifests.test.d.ts +1 -0
- package/dist/state/manifests.test.js +242 -0
- package/dist/{src/lib/state → state}/viewer.svelte.d.ts +4 -4
- package/dist/state/viewer.svelte.js +693 -0
- package/dist/theme/colorUtils.js +196 -0
- package/dist/theme/colorUtils.test.d.ts +1 -0
- package/dist/theme/colorUtils.test.js +90 -0
- package/dist/theme/index.js +52 -0
- package/dist/{src/lib/theme → theme}/themeManager.d.ts +4 -1
- package/dist/theme/themeManager.js +177 -0
- package/dist/theme/types.js +40 -0
- package/dist/triiiceratops-bundle.js +4676 -0
- package/dist/triiiceratops-element-image.js +1 -1
- package/dist/triiiceratops-element.js +1 -1
- package/dist/types/config.js +1 -0
- package/dist/{src/lib/types → types}/plugin.d.ts +3 -3
- package/dist/types/plugin.js +36 -0
- package/dist/utils/annotationAdapter.js +354 -0
- package/dist/utils/annotationAdapter.test.d.ts +1 -0
- package/dist/utils/annotationAdapter.test.js +91 -0
- package/package.json +6 -5
- package/dist/chunks/TriiiceratopsViewer-CyamQrMe.js +0 -22698
- package/dist/plugin-De14WKQl.js +0 -546
- package/dist/plugins/image-manipulation.js +0 -454
- package/dist/src/lib/components/AnnotationOverlay.svelte.d.ts +0 -1
- package/dist/src/lib/components/CanvasNavigation.svelte.d.ts +0 -1
- package/dist/src/lib/components/FloatingMenu.svelte.d.ts +0 -1
- package/dist/src/lib/components/LeftFab.svelte.d.ts +0 -1
- package/dist/src/lib/components/MetadataDialog.svelte.d.ts +0 -1
- package/dist/src/lib/components/OSDViewer.svelte.d.ts +0 -1
- package/dist/src/lib/components/SearchPanel.svelte.d.ts +0 -1
- package/dist/src/lib/components/ThumbnailGallery.svelte.d.ts +0 -1
- package/dist/src/lib/components/TriiiceratopsViewer.svelte.d.ts +0 -1
- package/dist/src/lib/custom-element-image.d.ts +0 -0
- package/dist/src/lib/custom-element.d.ts +0 -0
- package/dist/src/lib/paraglide/messages/de.d.ts +0 -96
- package/dist/src/lib/paraglide/messages/en.d.ts +0 -96
- package/dist/src/lib/paraglide/messages.d.ts +0 -272
- package/dist/src/lib/paraglide/runtime.d.ts +0 -52
- package/dist/src/lib/plugins/image-manipulation/ImageManipulationPanel.svelte.d.ts +0 -1
- package/dist/src/lib/state/i18n.svelte.d.ts +0 -5
- /package/dist/{src/lib/plugins → plugins}/image-manipulation/index.d.ts +0 -0
- /package/dist/{src/lib/plugins → plugins}/image-manipulation/types.d.ts +0 -0
- /package/dist/{src/lib/state → state}/manifests.svelte.d.ts +0 -0
- /package/dist/{src/lib/theme → theme}/colorUtils.d.ts +0 -0
- /package/dist/{src/lib/theme → theme}/index.d.ts +0 -0
- /package/dist/{src/lib/theme → theme}/types.d.ts +0 -0
- /package/dist/{src/lib/types → types}/config.d.ts +0 -0
- /package/dist/{src/lib/utils → utils}/annotationAdapter.d.ts +0 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color conversion utilities for DaisyUI theming.
|
|
3
|
+
* DaisyUI v5 uses oklch color format for all theme colors.
|
|
4
|
+
* The conversion functions were largely generated by Opus 4.5
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Parse a hex color string to RGB values (0-255)
|
|
8
|
+
*/
|
|
9
|
+
function parseHex(hex) {
|
|
10
|
+
// Remove # prefix if present
|
|
11
|
+
hex = hex.replace(/^#/, '');
|
|
12
|
+
var r, g, b;
|
|
13
|
+
if (hex.length === 3) {
|
|
14
|
+
// Short form #rgb
|
|
15
|
+
r = parseInt(hex[0] + hex[0], 16);
|
|
16
|
+
g = parseInt(hex[1] + hex[1], 16);
|
|
17
|
+
b = parseInt(hex[2] + hex[2], 16);
|
|
18
|
+
}
|
|
19
|
+
else if (hex.length === 6 || hex.length === 8) {
|
|
20
|
+
// Full form #rrggbb or #rrggbbaa (ignore alpha)
|
|
21
|
+
r = parseInt(hex.slice(0, 2), 16);
|
|
22
|
+
g = parseInt(hex.slice(2, 4), 16);
|
|
23
|
+
b = parseInt(hex.slice(4, 6), 16);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
if (isNaN(r) || isNaN(g) || isNaN(b)) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return { r: r, g: g, b: b };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parse an rgb() or rgba() color string to RGB values (0-255)
|
|
35
|
+
*/
|
|
36
|
+
function parseRgb(rgb) {
|
|
37
|
+
// Match rgb(r, g, b) or rgba(r, g, b, a) or modern rgb(r g b) / rgb(r g b / a)
|
|
38
|
+
var match = rgb.match(/rgba?\(\s*(\d+(?:\.\d+)?%?)\s*[,\s]\s*(\d+(?:\.\d+)?%?)\s*[,\s]\s*(\d+(?:\.\d+)?%?)(?:\s*[,/]\s*(\d*\.?\d+%?))?\s*\)/i);
|
|
39
|
+
if (!match)
|
|
40
|
+
return null;
|
|
41
|
+
var parseValue = function (val) {
|
|
42
|
+
if (val.endsWith('%')) {
|
|
43
|
+
return (parseFloat(val) / 100) * 255;
|
|
44
|
+
}
|
|
45
|
+
return parseFloat(val);
|
|
46
|
+
};
|
|
47
|
+
var r = parseValue(match[1]);
|
|
48
|
+
var g = parseValue(match[2]);
|
|
49
|
+
var b = parseValue(match[3]);
|
|
50
|
+
if (isNaN(r) || isNaN(g) || isNaN(b)) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return { r: r, g: g, b: b };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Convert sRGB to linear RGB
|
|
57
|
+
*/
|
|
58
|
+
function srgbToLinear(c) {
|
|
59
|
+
var v = c / 255;
|
|
60
|
+
return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Convert linear RGB to XYZ (D65 illuminant)
|
|
64
|
+
*/
|
|
65
|
+
function linearRgbToXyz(r, g, b) {
|
|
66
|
+
return {
|
|
67
|
+
x: 0.4124564 * r + 0.3575761 * g + 0.1804375 * b,
|
|
68
|
+
y: 0.2126729 * r + 0.7151522 * g + 0.072175 * b,
|
|
69
|
+
z: 0.0193339 * r + 0.119192 * g + 0.9503041 * b,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Convert XYZ to OKLAB
|
|
74
|
+
* Using the standard OKLAB transformation matrices
|
|
75
|
+
*/
|
|
76
|
+
function xyzToOklab(x, y, z) {
|
|
77
|
+
// XYZ to LMS (using OKLAB's M1 matrix)
|
|
78
|
+
var l = 0.8189330101 * x + 0.3618667424 * y - 0.1288597137 * z;
|
|
79
|
+
var m = 0.0329845436 * x + 0.9293118715 * y + 0.0361456387 * z;
|
|
80
|
+
var s = 0.0482003018 * x + 0.2643662691 * y + 0.633851707 * z;
|
|
81
|
+
// Cube root
|
|
82
|
+
var l_ = Math.cbrt(l);
|
|
83
|
+
var m_ = Math.cbrt(m);
|
|
84
|
+
var s_ = Math.cbrt(s);
|
|
85
|
+
// LMS to OKLAB (using OKLAB's M2 matrix)
|
|
86
|
+
return {
|
|
87
|
+
L: 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_,
|
|
88
|
+
a: 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_,
|
|
89
|
+
b: 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Convert OKLAB to OKLCH
|
|
94
|
+
*/
|
|
95
|
+
function oklabToOklch(L, a, b) {
|
|
96
|
+
var C = Math.sqrt(a * a + b * b);
|
|
97
|
+
var h = (Math.atan2(b, a) * 180) / Math.PI;
|
|
98
|
+
if (h < 0)
|
|
99
|
+
h += 360;
|
|
100
|
+
return { L: L, C: C, h: h };
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Convert RGB (0-255) to OKLCH
|
|
104
|
+
*/
|
|
105
|
+
function rgbToOklch(r, g, b) {
|
|
106
|
+
// sRGB to linear RGB
|
|
107
|
+
var lr = srgbToLinear(r);
|
|
108
|
+
var lg = srgbToLinear(g);
|
|
109
|
+
var lb = srgbToLinear(b);
|
|
110
|
+
// Linear RGB to XYZ
|
|
111
|
+
var _a = linearRgbToXyz(lr, lg, lb), x = _a.x, y = _a.y, z = _a.z;
|
|
112
|
+
// XYZ to OKLAB
|
|
113
|
+
var _b = xyzToOklab(x, y, z), L = _b.L, a = _b.a, labB = _b.b;
|
|
114
|
+
// OKLAB to OKLCH
|
|
115
|
+
return oklabToOklch(L, a, labB);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Format OKLCH values as a CSS oklch() string
|
|
119
|
+
* @param L - Lightness (0-1)
|
|
120
|
+
* @param C - Chroma (typically 0-0.4)
|
|
121
|
+
* @param h - Hue (0-360)
|
|
122
|
+
*/
|
|
123
|
+
function formatOklch(L, C, h) {
|
|
124
|
+
// L as percentage, C as decimal, h in degrees
|
|
125
|
+
var lPercent = (L * 100).toFixed(2);
|
|
126
|
+
var cValue = C.toFixed(4);
|
|
127
|
+
var hValue = C < 0.0001 ? 0 : h.toFixed(2); // For achromatic colors, hue is meaningless
|
|
128
|
+
return "oklch(".concat(lPercent, "% ").concat(cValue, " ").concat(hValue, ")");
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Check if a string is already in oklch format
|
|
132
|
+
*/
|
|
133
|
+
export function isOklch(value) {
|
|
134
|
+
return value.trim().toLowerCase().startsWith('oklch(');
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check if a string is a hex color
|
|
138
|
+
*/
|
|
139
|
+
export function isHex(value) {
|
|
140
|
+
return /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(value.trim());
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Check if a string is an rgb() or rgba() color
|
|
144
|
+
*/
|
|
145
|
+
export function isRgb(value) {
|
|
146
|
+
return /^rgba?\s*\(/i.test(value.trim());
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Convert hex color to oklch format for DaisyUI
|
|
150
|
+
* @param hex - Color in hex format (#rgb, #rrggbb, or #rrggbbaa)
|
|
151
|
+
* @returns oklch string like "oklch(65.00% 0.2000 250.00)"
|
|
152
|
+
*/
|
|
153
|
+
export function hexToOklch(hex) {
|
|
154
|
+
var rgb = parseHex(hex);
|
|
155
|
+
if (!rgb) {
|
|
156
|
+
console.warn("Invalid hex color: ".concat(hex, ", returning as-is"));
|
|
157
|
+
return hex;
|
|
158
|
+
}
|
|
159
|
+
var _a = rgbToOklch(rgb.r, rgb.g, rgb.b), L = _a.L, C = _a.C, h = _a.h;
|
|
160
|
+
return formatOklch(L, C, h);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Convert rgb() color to oklch format for DaisyUI
|
|
164
|
+
* @param rgb - Color in rgb(r, g, b) or rgba(r, g, b, a) format
|
|
165
|
+
* @returns oklch string like "oklch(65.00% 0.2000 250.00)"
|
|
166
|
+
*/
|
|
167
|
+
export function rgbToOklchString(rgb) {
|
|
168
|
+
var parsed = parseRgb(rgb);
|
|
169
|
+
if (!parsed) {
|
|
170
|
+
console.warn("Invalid rgb color: ".concat(rgb, ", returning as-is"));
|
|
171
|
+
return rgb;
|
|
172
|
+
}
|
|
173
|
+
var _a = rgbToOklch(parsed.r, parsed.g, parsed.b), L = _a.L, C = _a.C, h = _a.h;
|
|
174
|
+
return formatOklch(L, C, h);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Normalize color input - accepts hex, rgb(), or oklch()
|
|
178
|
+
* Converts hex and rgb to oklch format for DaisyUI compatibility.
|
|
179
|
+
* @param color - Color in any supported format
|
|
180
|
+
* @returns oklch string or original value if already oklch
|
|
181
|
+
*/
|
|
182
|
+
export function normalizeColor(color) {
|
|
183
|
+
var trimmed = color.trim();
|
|
184
|
+
if (isOklch(trimmed)) {
|
|
185
|
+
return trimmed;
|
|
186
|
+
}
|
|
187
|
+
if (isHex(trimmed)) {
|
|
188
|
+
return hexToOklch(trimmed);
|
|
189
|
+
}
|
|
190
|
+
if (isRgb(trimmed)) {
|
|
191
|
+
return rgbToOklchString(trimmed);
|
|
192
|
+
}
|
|
193
|
+
// Pass through as-is (could be a CSS variable, named color, etc.)
|
|
194
|
+
console.warn("Unrecognized color format: ".concat(color, ", passing through as-is"));
|
|
195
|
+
return color;
|
|
196
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { hexToOklch, normalizeColor, isOklch, isHex, isRgb, } from './colorUtils';
|
|
3
|
+
describe('colorUtils', function () {
|
|
4
|
+
describe('isHex', function () {
|
|
5
|
+
it('should return true for valid hex colors', function () {
|
|
6
|
+
expect(isHex('#fff')).toBe(true);
|
|
7
|
+
expect(isHex('#FFF')).toBe(true);
|
|
8
|
+
expect(isHex('#ffffff')).toBe(true);
|
|
9
|
+
expect(isHex('#FFFFFF')).toBe(true);
|
|
10
|
+
expect(isHex('#3b82f6')).toBe(true);
|
|
11
|
+
expect(isHex('#3B82F6')).toBe(true);
|
|
12
|
+
expect(isHex('#3b82f6ff')).toBe(true); // with alpha
|
|
13
|
+
});
|
|
14
|
+
it('should return false for invalid hex colors', function () {
|
|
15
|
+
expect(isHex('fff')).toBe(false);
|
|
16
|
+
expect(isHex('#ff')).toBe(false);
|
|
17
|
+
expect(isHex('#ffff')).toBe(false);
|
|
18
|
+
expect(isHex('#fffff')).toBe(false);
|
|
19
|
+
expect(isHex('rgb(255, 255, 255)')).toBe(false);
|
|
20
|
+
expect(isHex('oklch(50% 0.2 250)')).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
describe('isRgb', function () {
|
|
24
|
+
it('should return true for valid rgb colors', function () {
|
|
25
|
+
expect(isRgb('rgb(255, 255, 255)')).toBe(true);
|
|
26
|
+
expect(isRgb('rgb(0, 0, 0)')).toBe(true);
|
|
27
|
+
expect(isRgb('rgba(255, 255, 255, 0.5)')).toBe(true);
|
|
28
|
+
expect(isRgb('rgb(59 130 246)')).toBe(true); // modern syntax
|
|
29
|
+
});
|
|
30
|
+
it('should return false for non-rgb colors', function () {
|
|
31
|
+
expect(isRgb('#fff')).toBe(false);
|
|
32
|
+
expect(isRgb('oklch(50% 0.2 250)')).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe('isOklch', function () {
|
|
36
|
+
it('should return true for oklch colors', function () {
|
|
37
|
+
expect(isOklch('oklch(50% 0.2 250)')).toBe(true);
|
|
38
|
+
expect(isOklch('OKLCH(50% 0.2 250)')).toBe(true);
|
|
39
|
+
expect(isOklch(' oklch(50% 0.2 250) ')).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
it('should return false for non-oklch colors', function () {
|
|
42
|
+
expect(isOklch('#fff')).toBe(false);
|
|
43
|
+
expect(isOklch('rgb(255, 255, 255)')).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
describe('hexToOklch', function () {
|
|
47
|
+
it('should convert black correctly', function () {
|
|
48
|
+
var result = hexToOklch('#000000');
|
|
49
|
+
expect(result).toMatch(/^oklch\(0\.00%/);
|
|
50
|
+
});
|
|
51
|
+
it('should convert white correctly', function () {
|
|
52
|
+
var result = hexToOklch('#ffffff');
|
|
53
|
+
// White should have high lightness and low chroma
|
|
54
|
+
expect(result).toMatch(/^oklch\(100\.00%/);
|
|
55
|
+
});
|
|
56
|
+
it('should convert primary blue correctly', function () {
|
|
57
|
+
var result = hexToOklch('#3b82f6');
|
|
58
|
+
// Should produce a valid oklch string
|
|
59
|
+
expect(result).toMatch(/^oklch\(\d+\.\d+% \d+\.\d+ \d+\.\d+\)$/);
|
|
60
|
+
});
|
|
61
|
+
it('should handle short hex notation', function () {
|
|
62
|
+
var result = hexToOklch('#fff');
|
|
63
|
+
expect(result).toMatch(/^oklch\(100\.00%/);
|
|
64
|
+
});
|
|
65
|
+
it('should handle hex with alpha (ignoring alpha)', function () {
|
|
66
|
+
var result = hexToOklch('#3b82f680');
|
|
67
|
+
// Should produce same result as without alpha
|
|
68
|
+
expect(result).toMatch(/^oklch\(\d+\.\d+% \d+\.\d+ \d+\.\d+\)$/);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('normalizeColor', function () {
|
|
72
|
+
it('should pass through oklch colors unchanged', function () {
|
|
73
|
+
var oklch = 'oklch(65.00% 0.2000 250.00)';
|
|
74
|
+
expect(normalizeColor(oklch)).toBe(oklch);
|
|
75
|
+
});
|
|
76
|
+
it('should convert hex to oklch', function () {
|
|
77
|
+
var result = normalizeColor('#3b82f6');
|
|
78
|
+
expect(result).toMatch(/^oklch\(/);
|
|
79
|
+
});
|
|
80
|
+
it('should convert rgb to oklch', function () {
|
|
81
|
+
var result = normalizeColor('rgb(59, 130, 246)');
|
|
82
|
+
expect(result).toMatch(/^oklch\(/);
|
|
83
|
+
});
|
|
84
|
+
it('should pass through unknown formats with warning', function () {
|
|
85
|
+
// Named colors, CSS variables, etc. should pass through
|
|
86
|
+
var result = normalizeColor('var(--some-color)');
|
|
87
|
+
expect(result).toBe('var(--some-color)');
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme customization for Triiiceratops viewer.
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for customizing DaisyUI themes.
|
|
5
|
+
*
|
|
6
|
+
* @example Setting a built-in theme
|
|
7
|
+
* ```html
|
|
8
|
+
* <triiiceratops-viewer manifest-id="..." theme="dark"></triiiceratops-viewer>
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* @example Custom theme configuration (web component)
|
|
12
|
+
* ```html
|
|
13
|
+
* <triiiceratops-viewer
|
|
14
|
+
* manifest-id="..."
|
|
15
|
+
* theme="light"
|
|
16
|
+
* theme-config='{"primary":"#3b82f6","radiusBox":"0.5rem"}'
|
|
17
|
+
* ></triiiceratops-viewer>
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @example Custom theme configuration (JavaScript)
|
|
21
|
+
* ```javascript
|
|
22
|
+
* const viewer = document.querySelector('triiiceratops-viewer');
|
|
23
|
+
* viewer.theme = 'dark';
|
|
24
|
+
* viewer.themeConfig = {
|
|
25
|
+
* primary: '#3b82f6',
|
|
26
|
+
* secondary: '#8b5cf6',
|
|
27
|
+
* radiusBox: '0.75rem',
|
|
28
|
+
* border: '2px',
|
|
29
|
+
* };
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @example Svelte component
|
|
33
|
+
* ```svelte
|
|
34
|
+
* <script>
|
|
35
|
+
* import { TriiiceratopsViewer } from 'triiiceratops';
|
|
36
|
+
* import { MediaQuery } from 'svelte/reactivity';
|
|
37
|
+
*
|
|
38
|
+
* const prefersDark = new MediaQuery('(prefers-color-scheme: dark)');
|
|
39
|
+
* </script>
|
|
40
|
+
*
|
|
41
|
+
* <TriiiceratopsViewer
|
|
42
|
+
* manifestId="..."
|
|
43
|
+
* theme={prefersDark.current ? 'dark' : 'light'}
|
|
44
|
+
* themeConfig={{ primary: '#0ea5e9' }}
|
|
45
|
+
* />
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export { DAISYUI_THEMES } from './types';
|
|
49
|
+
// Theme manager utilities
|
|
50
|
+
export { applyTheme, applyBuiltInTheme, applyThemeConfig, clearThemeConfig, isBuiltInTheme, parseThemeConfig, getThemeCssVariables, getThemePropertyNames, } from './themeManager';
|
|
51
|
+
// Color utilities
|
|
52
|
+
export { hexToOklch, normalizeColor, isOklch, isHex, isRgb, } from './colorUtils';
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Theme manager for applying DaisyUI themes and custom theme configurations.
|
|
3
|
+
*/
|
|
4
|
+
import type { ThemeConfig, DaisyUITheme } from './types';
|
|
2
5
|
/**
|
|
3
6
|
* Check if a string is a valid built-in DaisyUI theme name
|
|
4
7
|
*/
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme manager for applying DaisyUI themes and custom theme configurations.
|
|
3
|
+
*/
|
|
4
|
+
import { DAISYUI_THEMES } from './types';
|
|
5
|
+
import { normalizeColor } from './colorUtils';
|
|
6
|
+
/**
|
|
7
|
+
* Map friendly ThemeConfig property names to DaisyUI CSS variable names
|
|
8
|
+
*/
|
|
9
|
+
var CSS_VAR_MAP = {
|
|
10
|
+
// Semantic colors
|
|
11
|
+
primary: '--color-primary',
|
|
12
|
+
primaryContent: '--color-primary-content',
|
|
13
|
+
secondary: '--color-secondary',
|
|
14
|
+
secondaryContent: '--color-secondary-content',
|
|
15
|
+
accent: '--color-accent',
|
|
16
|
+
accentContent: '--color-accent-content',
|
|
17
|
+
neutral: '--color-neutral',
|
|
18
|
+
neutralContent: '--color-neutral-content',
|
|
19
|
+
// Base colors
|
|
20
|
+
base100: '--color-base-100',
|
|
21
|
+
base200: '--color-base-200',
|
|
22
|
+
base300: '--color-base-300',
|
|
23
|
+
baseContent: '--color-base-content',
|
|
24
|
+
// State colors
|
|
25
|
+
info: '--color-info',
|
|
26
|
+
infoContent: '--color-info-content',
|
|
27
|
+
success: '--color-success',
|
|
28
|
+
successContent: '--color-success-content',
|
|
29
|
+
warning: '--color-warning',
|
|
30
|
+
warningContent: '--color-warning-content',
|
|
31
|
+
error: '--color-error',
|
|
32
|
+
errorContent: '--color-error-content',
|
|
33
|
+
// Border radius
|
|
34
|
+
radiusBox: '--radius-box',
|
|
35
|
+
radiusField: '--radius-field',
|
|
36
|
+
radiusSelector: '--radius-selector',
|
|
37
|
+
// Sizing
|
|
38
|
+
sizeSelector: '--size-selector',
|
|
39
|
+
sizeField: '--size-field',
|
|
40
|
+
// Border
|
|
41
|
+
border: '--border',
|
|
42
|
+
// Effects
|
|
43
|
+
depth: '--depth',
|
|
44
|
+
noise: '--noise',
|
|
45
|
+
// Color scheme (handled specially, not a CSS variable)
|
|
46
|
+
colorScheme: 'color-scheme',
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Set of properties that are colors and need oklch conversion
|
|
50
|
+
*/
|
|
51
|
+
var COLOR_PROPS = new Set([
|
|
52
|
+
'primary',
|
|
53
|
+
'primaryContent',
|
|
54
|
+
'secondary',
|
|
55
|
+
'secondaryContent',
|
|
56
|
+
'accent',
|
|
57
|
+
'accentContent',
|
|
58
|
+
'neutral',
|
|
59
|
+
'neutralContent',
|
|
60
|
+
'base100',
|
|
61
|
+
'base200',
|
|
62
|
+
'base300',
|
|
63
|
+
'baseContent',
|
|
64
|
+
'info',
|
|
65
|
+
'infoContent',
|
|
66
|
+
'success',
|
|
67
|
+
'successContent',
|
|
68
|
+
'warning',
|
|
69
|
+
'warningContent',
|
|
70
|
+
'error',
|
|
71
|
+
'errorContent',
|
|
72
|
+
]);
|
|
73
|
+
/**
|
|
74
|
+
* Check if a string is a valid built-in DaisyUI theme name
|
|
75
|
+
*/
|
|
76
|
+
export function isBuiltInTheme(theme) {
|
|
77
|
+
return DAISYUI_THEMES.includes(theme);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Apply a built-in theme to an element by setting data-theme attribute
|
|
81
|
+
*/
|
|
82
|
+
export function applyBuiltInTheme(element, theme) {
|
|
83
|
+
element.setAttribute('data-theme', theme);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Apply custom theme configuration as CSS custom properties on an element.
|
|
87
|
+
* These override the base theme's values.
|
|
88
|
+
*/
|
|
89
|
+
export function applyThemeConfig(element, config) {
|
|
90
|
+
for (var _i = 0, _a = Object.entries(config); _i < _a.length; _i++) {
|
|
91
|
+
var _b = _a[_i], key = _b[0], value = _b[1];
|
|
92
|
+
if (value === undefined || value === null)
|
|
93
|
+
continue;
|
|
94
|
+
var propKey = key;
|
|
95
|
+
// Handle colorScheme specially - it's not a CSS variable
|
|
96
|
+
if (propKey === 'colorScheme') {
|
|
97
|
+
element.style.colorScheme = value;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
var cssVar = CSS_VAR_MAP[propKey];
|
|
101
|
+
if (!cssVar)
|
|
102
|
+
continue;
|
|
103
|
+
var cssValue = String(value);
|
|
104
|
+
// Convert colors to oklch format
|
|
105
|
+
if (COLOR_PROPS.has(propKey)) {
|
|
106
|
+
cssValue = normalizeColor(cssValue);
|
|
107
|
+
}
|
|
108
|
+
element.style.setProperty(cssVar, cssValue);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Clear all custom theme CSS variables from an element
|
|
113
|
+
*/
|
|
114
|
+
export function clearThemeConfig(element) {
|
|
115
|
+
for (var _i = 0, _a = Object.entries(CSS_VAR_MAP); _i < _a.length; _i++) {
|
|
116
|
+
var _b = _a[_i], key = _b[0], cssVar = _b[1];
|
|
117
|
+
if (key === 'colorScheme') {
|
|
118
|
+
element.style.colorScheme = '';
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
element.style.removeProperty(cssVar);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Parse a theme config from a JSON string (for HTML attribute usage)
|
|
127
|
+
*/
|
|
128
|
+
export function parseThemeConfig(json) {
|
|
129
|
+
try {
|
|
130
|
+
var parsed = JSON.parse(json);
|
|
131
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
132
|
+
return parsed;
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
catch (_a) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Apply theme to an element.
|
|
142
|
+
*
|
|
143
|
+
* @param element - The HTML element to apply the theme to
|
|
144
|
+
* @param theme - Built-in theme name (defaults to light/dark based on prefers-color-scheme)
|
|
145
|
+
* @param config - Optional custom theme configuration to override the base theme
|
|
146
|
+
* @param prefersDark - Whether the user prefers dark mode (from media query)
|
|
147
|
+
*/
|
|
148
|
+
export function applyTheme(element, theme, config) {
|
|
149
|
+
if (theme) {
|
|
150
|
+
// Apply the requested theme
|
|
151
|
+
applyBuiltInTheme(element, theme);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
// If no theme specified, remove the attribute to allow inheritance
|
|
155
|
+
element.removeAttribute('data-theme');
|
|
156
|
+
}
|
|
157
|
+
// Clear any previous custom config
|
|
158
|
+
if (!config) {
|
|
159
|
+
clearThemeConfig(element);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
// Apply custom config overrides
|
|
163
|
+
applyThemeConfig(element, config);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get all CSS variable names that can be customized
|
|
168
|
+
*/
|
|
169
|
+
export function getThemeCssVariables() {
|
|
170
|
+
return Object.values(CSS_VAR_MAP).filter(function (v) { return v !== 'color-scheme'; });
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get all customizable theme property names
|
|
174
|
+
*/
|
|
175
|
+
export function getThemePropertyNames() {
|
|
176
|
+
return Object.keys(CSS_VAR_MAP);
|
|
177
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* List of all built-in DaisyUI themes for runtime validation
|
|
3
|
+
*/
|
|
4
|
+
export var DAISYUI_THEMES = [
|
|
5
|
+
'light',
|
|
6
|
+
'dark',
|
|
7
|
+
'cupcake',
|
|
8
|
+
'bumblebee',
|
|
9
|
+
'emerald',
|
|
10
|
+
'corporate',
|
|
11
|
+
'synthwave',
|
|
12
|
+
'retro',
|
|
13
|
+
'cyberpunk',
|
|
14
|
+
'valentine',
|
|
15
|
+
'halloween',
|
|
16
|
+
'garden',
|
|
17
|
+
'forest',
|
|
18
|
+
'aqua',
|
|
19
|
+
'lofi',
|
|
20
|
+
'pastel',
|
|
21
|
+
'fantasy',
|
|
22
|
+
'wireframe',
|
|
23
|
+
'black',
|
|
24
|
+
'luxury',
|
|
25
|
+
'dracula',
|
|
26
|
+
'cmyk',
|
|
27
|
+
'autumn',
|
|
28
|
+
'business',
|
|
29
|
+
'acid',
|
|
30
|
+
'lemonade',
|
|
31
|
+
'night',
|
|
32
|
+
'coffee',
|
|
33
|
+
'winter',
|
|
34
|
+
'dim',
|
|
35
|
+
'nord',
|
|
36
|
+
'sunset',
|
|
37
|
+
'caramellatte',
|
|
38
|
+
'abyss',
|
|
39
|
+
'silk',
|
|
40
|
+
];
|