@tableslayer/ui 0.1.4 → 0.1.5

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.
Files changed (206) hide show
  1. package/dist/components/PropsTable/PropsTable.svelte +1 -1
  2. package/package.json +9 -9
  3. package/src/lib/components/Avatar/Avatar.svelte +0 -82
  4. package/src/lib/components/Avatar/AvatarFileInput.svelte +0 -85
  5. package/src/lib/components/Avatar/AvatarPopover.svelte +0 -34
  6. package/src/lib/components/Avatar/index.ts +0 -4
  7. package/src/lib/components/Avatar/types.ts +0 -24
  8. package/src/lib/components/BrushSizeSlider/BrushSizeSlider.svelte +0 -174
  9. package/src/lib/components/BrushSizeSlider/index.ts +0 -1
  10. package/src/lib/components/Button/Button.svelte +0 -182
  11. package/src/lib/components/Button/ConfirmActionButton.svelte +0 -98
  12. package/src/lib/components/Button/IconButton.svelte +0 -121
  13. package/src/lib/components/Button/RadioButton.svelte +0 -93
  14. package/src/lib/components/Button/index.ts +0 -5
  15. package/src/lib/components/Button/types.ts +0 -54
  16. package/src/lib/components/CardFan/CardFan.svelte +0 -165
  17. package/src/lib/components/CardFan/index.ts +0 -2
  18. package/src/lib/components/CardFan/types.ts +0 -6
  19. package/src/lib/components/CodeBlock/Code.svelte +0 -7
  20. package/src/lib/components/CodeBlock/CodeBlock.svelte +0 -102
  21. package/src/lib/components/CodeBlock/index.ts +0 -3
  22. package/src/lib/components/CodeBlock/types.ts +0 -10
  23. package/src/lib/components/ColorMode/ColorMode.svelte +0 -8
  24. package/src/lib/components/ColorMode/index.ts +0 -2
  25. package/src/lib/components/ColorMode/types.ts +0 -12
  26. package/src/lib/components/ColorPicker/ColorPicker.svelte +0 -838
  27. package/src/lib/components/ColorPicker/ColorPickerSwatch.svelte +0 -32
  28. package/src/lib/components/ColorPicker/index.ts +0 -3
  29. package/src/lib/components/ColorPicker/types.ts +0 -51
  30. package/src/lib/components/ContextMenu/ContextMenu.svelte +0 -86
  31. package/src/lib/components/ContextMenu/index.ts +0 -2
  32. package/src/lib/components/ContextMenu/types.ts +0 -15
  33. package/src/lib/components/DrawingSliders/DrawingSliders.svelte +0 -379
  34. package/src/lib/components/DrawingSliders/index.ts +0 -1
  35. package/src/lib/components/Editor/Editor.svelte +0 -825
  36. package/src/lib/components/Editor/index.ts +0 -1
  37. package/src/lib/components/FogSliders/FogSliders.svelte +0 -33
  38. package/src/lib/components/FogSliders/index.ts +0 -1
  39. package/src/lib/components/Hr/Hr.svelte +0 -15
  40. package/src/lib/components/Hr/index.ts +0 -1
  41. package/src/lib/components/Icon/Icon.svelte +0 -6
  42. package/src/lib/components/Icon/index.ts +0 -2
  43. package/src/lib/components/Icon/types.ts +0 -20
  44. package/src/lib/components/Input/DualInputSlider.svelte +0 -126
  45. package/src/lib/components/Input/FileInput.svelte +0 -176
  46. package/src/lib/components/Input/FormControl.svelte +0 -150
  47. package/src/lib/components/Input/FormError.svelte +0 -37
  48. package/src/lib/components/Input/Input.svelte +0 -56
  49. package/src/lib/components/Input/InputCheckbox.svelte +0 -99
  50. package/src/lib/components/Input/InputSlider.svelte +0 -86
  51. package/src/lib/components/Input/Label.svelte +0 -19
  52. package/src/lib/components/Input/index.ts +0 -9
  53. package/src/lib/components/Input/types.ts +0 -39
  54. package/src/lib/components/Link/Link.svelte +0 -41
  55. package/src/lib/components/Link/LinkBox.svelte +0 -20
  56. package/src/lib/components/Link/LinkOverlay.svelte +0 -23
  57. package/src/lib/components/Link/index.ts +0 -4
  58. package/src/lib/components/Link/types.ts +0 -17
  59. package/src/lib/components/Loading/Loader.svelte +0 -60
  60. package/src/lib/components/Loading/Skeleton.svelte +0 -9
  61. package/src/lib/components/Loading/index.ts +0 -2
  62. package/src/lib/components/Logo/Logo.svelte +0 -16
  63. package/src/lib/components/Logo/index.ts +0 -1
  64. package/src/lib/components/MarkerTooltip/MarkerTooltip.svelte +0 -435
  65. package/src/lib/components/MarkerTooltip/index.ts +0 -1
  66. package/src/lib/components/Menu/SelectorMenu.svelte +0 -280
  67. package/src/lib/components/Menu/index.ts +0 -2
  68. package/src/lib/components/Menu/types.ts +0 -17
  69. package/src/lib/components/MyCounterButton.svelte +0 -11
  70. package/src/lib/components/Panel/index.ts +0 -2
  71. package/src/lib/components/Panel/panel.svelte +0 -18
  72. package/src/lib/components/Panel/types.ts +0 -8
  73. package/src/lib/components/PersistButton/PersistButton.svelte +0 -100
  74. package/src/lib/components/PersistButton/index.ts +0 -1
  75. package/src/lib/components/Popover/Popover.svelte +0 -81
  76. package/src/lib/components/Popover/index.ts +0 -2
  77. package/src/lib/components/Popover/types.ts +0 -19
  78. package/src/lib/components/PropsTable/PropsTable.svelte +0 -107
  79. package/src/lib/components/RadialMenu/EffectPreview.svelte +0 -36
  80. package/src/lib/components/RadialMenu/EffectPreviewScene.svelte +0 -194
  81. package/src/lib/components/RadialMenu/RadialMenu.svelte +0 -503
  82. package/src/lib/components/RadialMenu/RadialMenuItem.svelte +0 -176
  83. package/src/lib/components/RadialMenu/index.ts +0 -2
  84. package/src/lib/components/RadialMenu/types.ts +0 -35
  85. package/src/lib/components/Select/Select.svelte +0 -342
  86. package/src/lib/components/Select/index.ts +0 -2
  87. package/src/lib/components/Select/types.ts +0 -22
  88. package/src/lib/components/Spacer/Spacer.svelte +0 -14
  89. package/src/lib/components/Spacer/index.ts +0 -2
  90. package/src/lib/components/Spacer/types.ts +0 -5
  91. package/src/lib/components/Stage/components/AnnotationLayer/AnnotationLayer.svelte +0 -445
  92. package/src/lib/components/Stage/components/AnnotationLayer/AnnotationMaterial.svelte +0 -167
  93. package/src/lib/components/Stage/components/AnnotationLayer/types.ts +0 -196
  94. package/src/lib/components/Stage/components/CursorLayer/CursorLayer.svelte +0 -148
  95. package/src/lib/components/Stage/components/CursorLayer/cursor.svg +0 -26
  96. package/src/lib/components/Stage/components/CursorLayer/index.ts +0 -2
  97. package/src/lib/components/Stage/components/CursorLayer/types.ts +0 -23
  98. package/src/lib/components/Stage/components/DrawingLayer/DrawingMaterial.svelte +0 -364
  99. package/src/lib/components/Stage/components/DrawingLayer/types.ts +0 -65
  100. package/src/lib/components/Stage/components/EdgeOverlayLayer/EdgeOverlayLayer.svelte +0 -72
  101. package/src/lib/components/Stage/components/EdgeOverlayLayer/types.ts +0 -34
  102. package/src/lib/components/Stage/components/FogLayer/FogLayer.svelte +0 -75
  103. package/src/lib/components/Stage/components/FogLayer/types.ts +0 -51
  104. package/src/lib/components/Stage/components/FogOfWarLayer/FogOfWarLayer.svelte +0 -249
  105. package/src/lib/components/Stage/components/FogOfWarLayer/FogOfWarMaterial.svelte +0 -200
  106. package/src/lib/components/Stage/components/FogOfWarLayer/types.ts +0 -116
  107. package/src/lib/components/Stage/components/GridLayer/GridLayer.svelte +0 -20
  108. package/src/lib/components/Stage/components/GridLayer/GridMaterial.svelte +0 -69
  109. package/src/lib/components/Stage/components/GridLayer/types.ts +0 -79
  110. package/src/lib/components/Stage/components/LayerInput/LayerInput.svelte +0 -300
  111. package/src/lib/components/Stage/components/MapLayer/MapLayer.svelte +0 -196
  112. package/src/lib/components/Stage/components/MapLayer/dataSources/GifDataSource.ts +0 -265
  113. package/src/lib/components/Stage/components/MapLayer/dataSources/IMapDataSource.ts +0 -55
  114. package/src/lib/components/Stage/components/MapLayer/dataSources/ImageDataSource.ts +0 -87
  115. package/src/lib/components/Stage/components/MapLayer/dataSources/VideoDataSource.ts +0 -150
  116. package/src/lib/components/Stage/components/MapLayer/dataSources/dataSourceFactory.ts +0 -48
  117. package/src/lib/components/Stage/components/MapLayer/dataSources/index.ts +0 -16
  118. package/src/lib/components/Stage/components/MapLayer/types.ts +0 -58
  119. package/src/lib/components/Stage/components/MarkerLayer/MarkerLayer.svelte +0 -398
  120. package/src/lib/components/Stage/components/MarkerLayer/MarkerToken.svelte +0 -262
  121. package/src/lib/components/Stage/components/MarkerLayer/types.ts +0 -126
  122. package/src/lib/components/Stage/components/MeasurementLayer/MeasurementLayer.svelte +0 -364
  123. package/src/lib/components/Stage/components/MeasurementLayer/MeasurementManager.svelte +0 -473
  124. package/src/lib/components/Stage/components/MeasurementLayer/measurements/BaseMeasurement.ts +0 -427
  125. package/src/lib/components/Stage/components/MeasurementLayer/measurements/BeamMeasurement.ts +0 -105
  126. package/src/lib/components/Stage/components/MeasurementLayer/measurements/CircleMeasurement.ts +0 -98
  127. package/src/lib/components/Stage/components/MeasurementLayer/measurements/ConeMeasurement.ts +0 -163
  128. package/src/lib/components/Stage/components/MeasurementLayer/measurements/LineMeasurement.ts +0 -102
  129. package/src/lib/components/Stage/components/MeasurementLayer/measurements/RectangleMeasurement.ts +0 -120
  130. package/src/lib/components/Stage/components/MeasurementLayer/measurements/index.ts +0 -7
  131. package/src/lib/components/Stage/components/MeasurementLayer/types.ts +0 -94
  132. package/src/lib/components/Stage/components/MeasurementLayer/utils/canvasDrawing.ts +0 -357
  133. package/src/lib/components/Stage/components/MeasurementLayer/utils/distanceCalculations.ts +0 -170
  134. package/src/lib/components/Stage/components/ParticleSystem/ParticleSystem.svelte +0 -220
  135. package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/ash.png +0 -0
  136. package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/leaves.png +0 -0
  137. package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/rain.png +0 -0
  138. package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/snow.png +0 -0
  139. package/src/lib/components/Stage/components/ParticleSystem/rng.js +0 -20
  140. package/src/lib/components/Stage/components/ParticleSystem/types.ts +0 -95
  141. package/src/lib/components/Stage/components/PerformanceDebugger/PerformanceDebugger.svelte +0 -144
  142. package/src/lib/components/Stage/components/PerformanceDebugger/index.ts +0 -1
  143. package/src/lib/components/Stage/components/PerformanceOverlay/PerformanceOverlay.svelte +0 -208
  144. package/src/lib/components/Stage/components/PerformanceOverlay/index.ts +0 -1
  145. package/src/lib/components/Stage/components/PointerInputManager/PointerInputManager.svelte +0 -201
  146. package/src/lib/components/Stage/components/Scene/Scene.svelte +0 -651
  147. package/src/lib/components/Stage/components/Scene/luts.ts +0 -24
  148. package/src/lib/components/Stage/components/Scene/types.ts +0 -225
  149. package/src/lib/components/Stage/components/Stage/Stage.svelte +0 -332
  150. package/src/lib/components/Stage/components/Stage/types.ts +0 -136
  151. package/src/lib/components/Stage/components/WeatherLayer/WeatherLayer.svelte +0 -135
  152. package/src/lib/components/Stage/components/WeatherLayer/presets/AshPreset.ts +0 -71
  153. package/src/lib/components/Stage/components/WeatherLayer/presets/LeavesPreset.ts +0 -70
  154. package/src/lib/components/Stage/components/WeatherLayer/presets/RainPreset.ts +0 -68
  155. package/src/lib/components/Stage/components/WeatherLayer/presets/SnowPreset.ts +0 -70
  156. package/src/lib/components/Stage/components/WeatherLayer/presets/index.ts +0 -6
  157. package/src/lib/components/Stage/components/WeatherLayer/types.ts +0 -35
  158. package/src/lib/components/Stage/helpers/clippingPlaneStore.svelte.ts +0 -28
  159. package/src/lib/components/Stage/helpers/debugState.svelte.ts +0 -18
  160. package/src/lib/components/Stage/helpers/grid.ts +0 -548
  161. package/src/lib/components/Stage/helpers/lazyBrush.ts +0 -171
  162. package/src/lib/components/Stage/helpers/performanceMetrics.svelte.ts +0 -220
  163. package/src/lib/components/Stage/helpers/utils.ts +0 -21
  164. package/src/lib/components/Stage/index.ts +0 -49
  165. package/src/lib/components/Stage/shaders/AnnotationEffects.frag +0 -1070
  166. package/src/lib/components/Stage/shaders/Annotations.frag +0 -29
  167. package/src/lib/components/Stage/shaders/Drawing.frag +0 -83
  168. package/src/lib/components/Stage/shaders/Drawing.vert +0 -5
  169. package/src/lib/components/Stage/shaders/Fog.frag +0 -147
  170. package/src/lib/components/Stage/shaders/FractalNoise.frag +0 -96
  171. package/src/lib/components/Stage/shaders/GridShader.frag +0 -174
  172. package/src/lib/components/Stage/shaders/Overlay.frag +0 -23
  173. package/src/lib/components/Stage/shaders/Overlay.vert +0 -0
  174. package/src/lib/components/Stage/shaders/Particles.frag +0 -27
  175. package/src/lib/components/Stage/shaders/Particles.vert +0 -51
  176. package/src/lib/components/Stage/shaders/ToolOutline.frag +0 -59
  177. package/src/lib/components/Stage/shaders/default.vert +0 -8
  178. package/src/lib/components/Stage/types.ts +0 -4
  179. package/src/lib/components/Table/Table.svelte +0 -16
  180. package/src/lib/components/Table/Td.svelte +0 -17
  181. package/src/lib/components/Table/Th.svelte +0 -18
  182. package/src/lib/components/Table/index.ts +0 -4
  183. package/src/lib/components/Table/types.ts +0 -14
  184. package/src/lib/components/Text/Text.svelte +0 -23
  185. package/src/lib/components/Text/index.ts +0 -2
  186. package/src/lib/components/Text/types.ts +0 -12
  187. package/src/lib/components/Title/Title.svelte +0 -54
  188. package/src/lib/components/Title/index.ts +0 -2
  189. package/src/lib/components/Title/types.ts +0 -9
  190. package/src/lib/components/Toast/Toast.svelte +0 -155
  191. package/src/lib/components/Toast/index.ts +0 -5
  192. package/src/lib/components/Toast/toastCookie.ts +0 -24
  193. package/src/lib/components/Toast/types.ts +0 -6
  194. package/src/lib/components/ToolTip/ToolTip.svelte +0 -70
  195. package/src/lib/components/ToolTip/index.ts +0 -2
  196. package/src/lib/components/ToolTip/types.ts +0 -14
  197. package/src/lib/components/index.ts +0 -32
  198. package/src/lib/components/types.ts +0 -0
  199. package/src/lib/index.ts +0 -2
  200. package/src/lib/styles/globals.css +0 -108
  201. package/src/lib/styles/normalize.css +0 -9
  202. package/src/lib/styles/reset.css +0 -133
  203. package/src/lib/styles/utilities.css +0 -179
  204. package/src/lib/styles/vars.css +0 -1103
  205. package/src/lib/types/awareness.ts +0 -17
  206. package/src/lib/utils/rle.ts +0 -217
@@ -1,838 +0,0 @@
1
- <script lang="ts">
2
- import { onMount } from 'svelte';
3
- import { Input, Select } from '../'; // Adjust the import path based on your project structure
4
- import type { ColorState, ColorPickerFormats, ColorPickerProps } from './types';
5
- import chroma from 'chroma-js';
6
-
7
- // Bindable props with correct syntax and typings
8
- let {
9
- hex = $bindable<string>(''),
10
- rgba = $bindable(),
11
- hsva = $bindable(),
12
- hsla = $bindable(),
13
- showInputs = false,
14
- showOpacity = true,
15
- onUpdate = () => {},
16
- id,
17
- ...restProps
18
- }: ColorPickerProps = $props();
19
-
20
- const color = $state<ColorState>({
21
- hue: 0,
22
- saturation: 100,
23
- value: 100,
24
- opacity: 100,
25
- isSelecting: false,
26
- isAdjustingSV: false,
27
- isAdjustingHue: false
28
- });
29
-
30
- let lastValidHue = color.hue;
31
-
32
- let canvasElement: HTMLCanvasElement;
33
- let colorInputFocused = false;
34
- let selectedFormat = $state<ColorPickerFormats>('hex');
35
-
36
- // Input fields for different color modes
37
- let hexInput = $state('');
38
- let rgbInputs = $state({ r: '', g: '', b: '', a: '' });
39
- let hslInputs = $state({ h: '', s: '', l: '', a: '' });
40
- let hsvInputs = $state({ h: '', s: '', v: '', a: '' });
41
-
42
- // Helper Functions using chroma-js
43
- const toHex = (color: ColorState): string => {
44
- const alpha = color.opacity / 100;
45
- const chromaColor = chroma.hsv(color.hue, color.saturation / 100, color.value / 100).alpha(alpha);
46
- if (showOpacity) {
47
- return chromaColor.hex();
48
- } else {
49
- return chromaColor.hex().slice(0, 7); // Return only 6-digit hex without alpha
50
- }
51
- };
52
-
53
- const drawSaturationValueGradient = (): void => {
54
- if (!canvasElement) return;
55
- const ctx = canvasElement.getContext('2d');
56
- if (!ctx) return;
57
- const width = canvasElement.width;
58
- const height = canvasElement.height;
59
-
60
- // Clear the canvas
61
- ctx.clearRect(0, 0, width, height);
62
-
63
- const saturationGradient = ctx.createLinearGradient(0, 0, width, 0);
64
- saturationGradient.addColorStop(0, 'white');
65
- saturationGradient.addColorStop(1, `hsl(${displayHue()}, 100%, 50%)`);
66
- ctx.fillStyle = saturationGradient;
67
- ctx.fillRect(0, 0, width, height);
68
-
69
- const valueGradient = ctx.createLinearGradient(0, 0, 0, height);
70
- valueGradient.addColorStop(0, 'rgba(0,0,0,0)');
71
- valueGradient.addColorStop(1, 'rgba(0,0,0,1)');
72
- ctx.fillStyle = valueGradient;
73
- ctx.fillRect(0, 0, width, height);
74
- };
75
-
76
- let saturationBoxRect: DOMRect;
77
-
78
- const updateSaturationValue = (e: MouseEvent): void => {
79
- if (!saturationBoxRect) return;
80
- const rect = saturationBoxRect;
81
- const x = e.clientX - rect.left;
82
- const y = e.clientY - rect.top;
83
- color.saturation = Math.max(0, Math.min(100, (x / rect.width) * 100));
84
- color.value = Math.max(0, Math.min(100, 100 - (y / rect.height) * 100));
85
- };
86
-
87
- const startSelection = (e: MouseEvent): void => {
88
- e.preventDefault();
89
- saturationBoxRect = canvasElement.getBoundingClientRect();
90
- color.isSelecting = true;
91
- color.isAdjustingSV = true;
92
- updateSaturationValue(e);
93
- };
94
-
95
- const endSelection = (): void => {
96
- color.isSelecting = false;
97
- color.isAdjustingSV = false;
98
- };
99
-
100
- const handleMouseMove = (e: MouseEvent): void => {
101
- if (color.isSelecting) {
102
- updateSaturationValue(e);
103
- }
104
- };
105
-
106
- const handleMouseUp = (): void => {
107
- if (color.isSelecting) {
108
- endSelection();
109
- }
110
- };
111
-
112
- // Touch event handlers
113
- const updateSaturationValueFromTouch = (e: TouchEvent): void => {
114
- if (!saturationBoxRect) return;
115
- const rect = saturationBoxRect;
116
- const touch = e.touches[0] || e.changedTouches[0];
117
- const x = touch.clientX - rect.left;
118
- const y = touch.clientY - rect.top;
119
- color.saturation = Math.max(0, Math.min(100, (x / rect.width) * 100));
120
- color.value = Math.max(0, Math.min(100, 100 - (y / rect.height) * 100));
121
- };
122
-
123
- const startTouchSelection = (e: TouchEvent): void => {
124
- e.preventDefault();
125
- saturationBoxRect = canvasElement.getBoundingClientRect();
126
- color.isSelecting = true;
127
- color.isAdjustingSV = true;
128
- updateSaturationValueFromTouch(e);
129
- };
130
-
131
- const handleTouchMove = (e: TouchEvent): void => {
132
- if (color.isSelecting) {
133
- e.preventDefault();
134
- updateSaturationValueFromTouch(e);
135
- }
136
- };
137
-
138
- const handleTouchEnd = (): void => {
139
- if (color.isSelecting) {
140
- endSelection();
141
- }
142
- };
143
-
144
- const getOpacityGradient = (): string => {
145
- const chromaColor = chroma.hsv(displayHue(), color.saturation / 100, color.value / 100);
146
- const [r, g, b] = chromaColor.rgb();
147
- const rgba0 = `rgba(${r}, ${g}, ${b}, 0)`;
148
- const rgba1 = `rgba(${r}, ${g}, ${b}, 1)`;
149
- return `linear-gradient(to right, ${rgba0}, ${rgba1})`;
150
- };
151
-
152
- // Synchronize internal color state with bindable props
153
- let updatingFromProps = false;
154
-
155
- // Update internal color state when bindable props change
156
- $effect(() => {
157
- if (colorInputFocused || updatingFromProps) return;
158
-
159
- updatingFromProps = true;
160
-
161
- if (!color.isAdjustingSV) {
162
- if (hex && hex.trim()) {
163
- try {
164
- const chromaColor = chroma(hex.trim());
165
- const [h, s, v] = chromaColor.hsv();
166
- const alpha = chromaColor.alpha();
167
- if (!isNaN(h)) {
168
- color.hue = h;
169
- lastValidHue = h;
170
- } else {
171
- color.hue = lastValidHue;
172
- }
173
- color.saturation = s * 100;
174
- color.value = v * 100;
175
- color.opacity = alpha * 100;
176
- } catch (error) {
177
- console.log(error);
178
- // Invalid hex code
179
- }
180
- } else if (rgba) {
181
- const { r, g, b, a } = rgba;
182
- if (typeof r === 'number' && typeof g === 'number' && typeof b === 'number') {
183
- const chromaColor = chroma.rgb(r, g, b).alpha(a);
184
- const [h, s, v] = chromaColor.hsv();
185
- if (!isNaN(h)) {
186
- color.hue = h;
187
- lastValidHue = h;
188
- } else {
189
- color.hue = lastValidHue;
190
- }
191
- color.saturation = s * 100;
192
- color.value = v * 100;
193
- color.opacity = chromaColor.alpha() * 100;
194
- }
195
- } else if (hsva) {
196
- const { h, s, v, a } = hsva;
197
- if (!isNaN(h)) {
198
- color.hue = h;
199
- lastValidHue = h;
200
- } else {
201
- color.hue = lastValidHue;
202
- }
203
- color.saturation = s;
204
- color.value = v;
205
- color.opacity = a * 100;
206
- } else if (hsla) {
207
- const { h, s, l, a } = hsla;
208
- const chromaColor = chroma.hsl(h, s / 100, l / 100).alpha(a);
209
- const [h2, s2, v] = chromaColor.hsv();
210
- if (!isNaN(h2)) {
211
- color.hue = h2;
212
- lastValidHue = h2;
213
- } else {
214
- color.hue = lastValidHue;
215
- }
216
- color.saturation = s2 * 100;
217
- color.value = v * 100;
218
- color.opacity = chromaColor.alpha() * 100;
219
- }
220
- }
221
-
222
- updatingFromProps = false;
223
- });
224
-
225
- // Update bindable props when internal color state changes
226
- let previousColor = { ...color };
227
-
228
- $effect(() => {
229
- if (updatingFromProps) return;
230
-
231
- const hueChanged = color.hue !== previousColor.hue && !isNaN(color.hue);
232
- const satChanged = color.saturation !== previousColor.saturation;
233
- const valChanged = color.value !== previousColor.value;
234
- const opacityChanged = color.opacity !== previousColor.opacity;
235
-
236
- if (hueChanged || satChanged || valChanged || opacityChanged) {
237
- if (!color.isAdjustingSV) {
238
- if (hueChanged) {
239
- lastValidHue = color.hue;
240
- }
241
- } else {
242
- // When adjusting SV, keep the hue constant
243
- color.hue = lastValidHue;
244
- }
245
-
246
- // Compute color representations using chroma-js
247
- const opacity = showOpacity ? color.opacity / 100 : 1;
248
- const chromaColor = chroma.hsv(displayHue(), color.saturation / 100, color.value / 100).alpha(opacity);
249
-
250
- const [r, g, b] = chromaColor.rgb();
251
- let newHex;
252
- if (showOpacity) {
253
- newHex = chromaColor.hex();
254
- } else {
255
- newHex = chromaColor.hex().slice(0, 7); // Return only 6-digit hex without alpha
256
- }
257
- const newRgba = { r, g, b, a: chromaColor.alpha() };
258
- const [hHSL, sHSL, lHSL] = chromaColor.hsl();
259
- const newHsla = { h: hHSL, s: sHSL * 100, l: lHSL * 100, a: chromaColor.alpha() };
260
- const [hHSV, sHSV, vHSV] = chromaColor.hsv();
261
- const newHsva = { h: hHSV, s: sHSV * 100, v: vHSV * 100, a: chromaColor.alpha() };
262
-
263
- // Update bindable props
264
- hex = newHex;
265
- rgba = newRgba;
266
- hsla = newHsla;
267
- hsva = newHsva;
268
-
269
- // Call onUpdate
270
- onUpdate({ hex: newHex, rgba: newRgba, hsva: newHsva, hsla: newHsla });
271
-
272
- previousColor = { ...color };
273
- }
274
- });
275
-
276
- // Function to update color inputs based on selectedFormat and color state
277
- const updateColorInputs = () => {
278
- const chromaColor = chroma.hsv(color.hue, color.saturation / 100, color.value / 100).alpha(color.opacity / 100);
279
-
280
- switch (selectedFormat) {
281
- case 'hex': {
282
- hexInput = toHex(color);
283
- break;
284
- }
285
- case 'rgb': {
286
- const [r, g, b] = chromaColor.rgb();
287
- rgbInputs = {
288
- r: r.toString(),
289
- g: g.toString(),
290
- b: b.toString(),
291
- a: chromaColor.alpha().toFixed(2)
292
- };
293
- break;
294
- }
295
- case 'hsl': {
296
- const [h, s, l] = chromaColor.hsl();
297
- hslInputs = {
298
- h: Math.round(h).toString(),
299
- s: Math.round(s * 100).toString(),
300
- l: Math.round(l * 100).toString(),
301
- a: chromaColor.alpha().toFixed(2)
302
- };
303
- break;
304
- }
305
- case 'hsv': {
306
- const [h, s, v] = chromaColor.hsv();
307
- hsvInputs = {
308
- h: Math.round(h).toString(),
309
- s: Math.round(s * 100).toString(),
310
- v: Math.round(v * 100).toString(),
311
- a: chromaColor.alpha().toFixed(2)
312
- };
313
- break;
314
- }
315
- }
316
- };
317
-
318
- // Function to parse inputs and update color state
319
- const parseColorInputs = () => {
320
- try {
321
- switch (selectedFormat) {
322
- case 'hex': {
323
- const hexValue = hexInput.trim();
324
- // Regular expression for either 6-digit or 8-digit hex
325
- if (/^#?([0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(hexValue)) {
326
- const chromaColor = chroma(hexValue);
327
- const [h, s, v] = chromaColor.hsv();
328
- if (!isNaN(h)) {
329
- color.hue = h;
330
- lastValidHue = h;
331
- } else {
332
- color.hue = lastValidHue;
333
- }
334
- color.saturation = s * 100;
335
- color.value = v * 100;
336
- // Only update opacity if we're showing the opacity slider
337
- if (showOpacity) {
338
- color.opacity = chromaColor.alpha() * 100;
339
- } else {
340
- color.opacity = 100; // Always full opacity when showOpacity is false
341
- }
342
- } else {
343
- console.error('Invalid hex code');
344
- }
345
- break;
346
- }
347
- case 'rgb': {
348
- const r = parseInt(rgbInputs.r);
349
- const g = parseInt(rgbInputs.g);
350
- const b = parseInt(rgbInputs.b);
351
- const a = parseFloat(rgbInputs.a);
352
- if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {
353
- const chromaColor = chroma.rgb(r, g, b).alpha(a);
354
- const [h, s, v] = chromaColor.hsv();
355
- if (!isNaN(h)) {
356
- color.hue = h;
357
- lastValidHue = h;
358
- } else {
359
- color.hue = lastValidHue;
360
- }
361
- color.saturation = s * 100;
362
- color.value = v * 100;
363
- if (!isNaN(a)) {
364
- color.opacity = a * 100;
365
- }
366
- }
367
- break;
368
- }
369
- case 'hsl': {
370
- const h = parseFloat(hslInputs.h);
371
- const s = parseFloat(hslInputs.s);
372
- const l = parseFloat(hslInputs.l);
373
- const a = parseFloat(hslInputs.a);
374
- if (!isNaN(h) && !isNaN(s) && !isNaN(l)) {
375
- const chromaColor = chroma.hsl(h, s / 100, l / 100).alpha(a);
376
- const [h2, s2, v] = chromaColor.hsv();
377
- if (!isNaN(h2)) {
378
- color.hue = h2;
379
- lastValidHue = h2;
380
- } else {
381
- color.hue = lastValidHue;
382
- }
383
- color.saturation = s2 * 100;
384
- color.value = v * 100;
385
- if (!isNaN(a)) {
386
- color.opacity = a * 100;
387
- }
388
- }
389
- break;
390
- }
391
- case 'hsv': {
392
- const h = parseFloat(hsvInputs.h);
393
- const s = parseFloat(hsvInputs.s);
394
- const v = parseFloat(hsvInputs.v);
395
- const a = parseFloat(hsvInputs.a);
396
- if (!isNaN(h) && !isNaN(s) && !isNaN(v)) {
397
- if (!isNaN(h)) {
398
- color.hue = h;
399
- lastValidHue = h;
400
- } else {
401
- color.hue = lastValidHue;
402
- }
403
- color.saturation = s;
404
- color.value = v;
405
- if (!isNaN(a)) {
406
- color.opacity = a * 100;
407
- }
408
- }
409
- break;
410
- }
411
- }
412
- } catch (error) {
413
- // Invalid input; reset inputs to current color
414
- console.error(error);
415
- updateColorInputs();
416
- }
417
- };
418
-
419
- // Update inputs when color changes, but not if input is focused
420
- $effect(() => {
421
- if (!colorInputFocused) {
422
- updateColorInputs();
423
- }
424
- drawSaturationValueGradient();
425
- });
426
-
427
- // Handle input changes on blur (when input loses focus)
428
- const handleInputsBlur = (): void => {
429
- colorInputFocused = false;
430
- parseColorInputs();
431
- updateColorInputs();
432
- };
433
-
434
- // Update inputs when format changes
435
- $effect(() => {
436
- updateColorInputs();
437
- });
438
-
439
- // Keyboard event handler for adjusting saturation and value
440
- const handleKeyDown = (e: KeyboardEvent): void => {
441
- const step = 2; // Adjust this step size as needed for fine control
442
-
443
- // Handle the arrow keys for movement
444
- switch (e.key) {
445
- case 'ArrowUp':
446
- color.value = Math.min(100, color.value + step);
447
- e.preventDefault(); // Prevent default scrolling
448
- break;
449
- case 'ArrowDown':
450
- color.value = Math.max(0, color.value - step);
451
- e.preventDefault(); // Prevent default scrolling
452
- break;
453
- case 'ArrowLeft':
454
- color.saturation = Math.max(0, color.saturation - step);
455
- e.preventDefault(); // Prevent default scrolling
456
- break;
457
- case 'ArrowRight':
458
- color.saturation = Math.min(100, color.saturation + step);
459
- e.preventDefault(); // Prevent default scrolling
460
- break;
461
- case 'Tab':
462
- // Allow default behavior for Tab key to prevent focus lock
463
- return;
464
- }
465
- };
466
-
467
- // Function to start focusing and adjusting the saturation/value box
468
- const startSaturationAdjustment = () => {
469
- color.isAdjustingSV = true;
470
- };
471
-
472
- // Function to end focusing and adjusting the saturation/value box
473
- const endSaturationAdjustment = () => {
474
- color.isAdjustingSV = false;
475
- };
476
-
477
- // onMount
478
- onMount(() => {
479
- if (canvasElement) {
480
- drawSaturationValueGradient();
481
- }
482
- // Initialize inputs
483
- updateColorInputs();
484
- });
485
-
486
- const displayHue = () => (isNaN(color.hue) ? lastValidHue : color.hue);
487
-
488
- // @ts-expect-error Can't figure out how to type this to FormatOption
489
- const handleFormatChange = (selected) => {
490
- selectedFormat = selected[0];
491
- updateColorInputs();
492
- };
493
-
494
- const formatOptions = [
495
- { value: 'hex', label: 'HEX' },
496
- { value: 'rgb', label: 'RGB' },
497
- { value: 'hsl', label: 'HSL' },
498
- { value: 'hsv', label: 'HSV' }
499
- ];
500
- </script>
501
-
502
- <svelte:window
503
- onmousemove={handleMouseMove}
504
- onmouseup={handleMouseUp}
505
- ontouchmove={handleTouchMove}
506
- ontouchend={handleTouchEnd}
507
- />
508
-
509
- <div class="colorPicker" {...restProps}>
510
- <!-- Saturation/Value Selector -->
511
- <div class="colorPicker__box">
512
- <canvas
513
- class="colorPicker__canvas"
514
- bind:this={canvasElement}
515
- width="200"
516
- height="200"
517
- tabindex="0"
518
- onmousedown={startSelection}
519
- ontouchstart={startTouchSelection}
520
- onfocus={startSaturationAdjustment}
521
- onblur={endSaturationAdjustment}
522
- onkeydown={handleKeyDown}
523
- {id}
524
- ></canvas>
525
- <!-- Selection Indicator -->
526
- <div
527
- class="colorPicker__boxIndicator"
528
- style="top: {100 - color.value}%; left: {color.saturation}%; background-color: {toHex(color)};"
529
- ></div>
530
- </div>
531
-
532
- <!-- Hue Slider -->
533
- <div class="colorPicker__sliderWrapper colorPicker__sliderWrapper--hue">
534
- <input
535
- type="range"
536
- min="0"
537
- max="360"
538
- step="1"
539
- bind:value={color.hue}
540
- onmousedown={() => (color.isAdjustingHue = true)}
541
- onmouseup={() => (color.isAdjustingHue = false)}
542
- ontouchstart={() => (color.isAdjustingHue = true)}
543
- ontouchend={() => (color.isAdjustingHue = false)}
544
- oninput={() => {
545
- color.isAdjustingHue = true;
546
- lastValidHue = color.hue;
547
- }}
548
- onchange={() => (color.isAdjustingHue = false)}
549
- aria-label="Hue Selector"
550
- style="--thumbBG: hsl({displayHue()}, 100%, 50%)"
551
- class="colorPicker__slider"
552
- />
553
- </div>
554
-
555
- {#if showOpacity}
556
- <div
557
- class="colorPicker__sliderWrapper colorPicker__sliderWrapper--opacity"
558
- style="--opacityGradient: {getOpacityGradient()};"
559
- >
560
- <input
561
- type="range"
562
- min="0"
563
- max="100"
564
- step="1"
565
- bind:value={color.opacity}
566
- aria-label="Opacity Slider"
567
- class="colorPicker__slider"
568
- style="--thumbBG: {toHex(color)};"
569
- />
570
- </div>
571
- {/if}
572
-
573
- {#if showInputs}
574
- <div class="colorPicker__inputs colorPicker__inputs--{selectedFormat}">
575
- <Select selected={[formatOptions[0].value]} options={formatOptions} onSelectedChange={handleFormatChange} />
576
-
577
- <!-- Inputs based on selected format -->
578
- {#if selectedFormat === 'hex'}
579
- <Input
580
- type="text"
581
- bind:value={hexInput}
582
- aria-label="Hex Color Input"
583
- onfocus={() => (colorInputFocused = true)}
584
- onblur={handleInputsBlur}
585
- />
586
- {:else if selectedFormat === 'rgb'}
587
- <Input
588
- type="number"
589
- min="0"
590
- max="255"
591
- bind:value={rgbInputs.r}
592
- aria-label="Red"
593
- placeholder="R"
594
- onfocus={() => (colorInputFocused = true)}
595
- onblur={handleInputsBlur}
596
- />
597
- <Input
598
- type="number"
599
- min="0"
600
- max="255"
601
- bind:value={rgbInputs.g}
602
- aria-label="Green"
603
- placeholder="G"
604
- onfocus={() => (colorInputFocused = true)}
605
- onblur={handleInputsBlur}
606
- />
607
- <Input
608
- type="number"
609
- min="0"
610
- max="255"
611
- bind:value={rgbInputs.b}
612
- aria-label="Blue"
613
- placeholder="B"
614
- onfocus={() => (colorInputFocused = true)}
615
- onblur={handleInputsBlur}
616
- />
617
- {#if showOpacity}
618
- <Input
619
- type="number"
620
- min="0"
621
- max="1"
622
- step="0.01"
623
- bind:value={rgbInputs.a}
624
- aria-label="Alpha"
625
- placeholder="A"
626
- onfocus={() => (colorInputFocused = true)}
627
- onblur={handleInputsBlur}
628
- />
629
- {/if}
630
- {:else if selectedFormat === 'hsl'}
631
- <Input
632
- type="number"
633
- min="0"
634
- max="360"
635
- bind:value={hslInputs.h}
636
- aria-label="Hue"
637
- placeholder="H"
638
- onfocus={() => (colorInputFocused = true)}
639
- onblur={handleInputsBlur}
640
- />
641
- <Input
642
- type="number"
643
- min="0"
644
- max="100"
645
- bind:value={hslInputs.s}
646
- aria-label="Saturation"
647
- placeholder="S"
648
- onfocus={() => (colorInputFocused = true)}
649
- onblur={handleInputsBlur}
650
- />
651
- <Input
652
- type="number"
653
- min="0"
654
- max="100"
655
- bind:value={hslInputs.l}
656
- aria-label="Lightness"
657
- placeholder="L"
658
- onfocus={() => (colorInputFocused = true)}
659
- onblur={handleInputsBlur}
660
- />
661
- {#if showOpacity}
662
- <Input
663
- type="number"
664
- min="0"
665
- max="1"
666
- step="0.01"
667
- bind:value={hslInputs.a}
668
- aria-label="Alpha"
669
- placeholder="A"
670
- onfocus={() => (colorInputFocused = true)}
671
- onblur={handleInputsBlur}
672
- />
673
- {/if}
674
- {:else if selectedFormat === 'hsv'}
675
- <Input
676
- type="number"
677
- min="0"
678
- max="360"
679
- bind:value={hsvInputs.h}
680
- aria-label="Hue"
681
- placeholder="H"
682
- onfocus={() => (colorInputFocused = true)}
683
- onblur={handleInputsBlur}
684
- />
685
- <Input
686
- type="number"
687
- min="0"
688
- max="100"
689
- bind:value={hsvInputs.s}
690
- aria-label="Saturation"
691
- placeholder="S"
692
- onfocus={() => (colorInputFocused = true)}
693
- onblur={handleInputsBlur}
694
- />
695
- <Input
696
- type="number"
697
- min="0"
698
- max="100"
699
- bind:value={hsvInputs.v}
700
- aria-label="Value"
701
- placeholder="V"
702
- onfocus={() => (colorInputFocused = true)}
703
- onblur={handleInputsBlur}
704
- />
705
- {#if showOpacity}
706
- <Input
707
- type="number"
708
- min="0"
709
- max="1"
710
- step="0.01"
711
- bind:value={hsvInputs.a}
712
- aria-label="Alpha"
713
- placeholder="A"
714
- onfocus={() => (colorInputFocused = true)}
715
- onblur={handleInputsBlur}
716
- />
717
- {/if}
718
- {/if}
719
- </div>
720
- {/if}
721
- </div>
722
-
723
- <style>
724
- .colorPicker {
725
- display: flex;
726
- flex-direction: column;
727
- gap: 0.5rem;
728
- width: 100%;
729
- max-width: 25rem;
730
- }
731
-
732
- .colorPicker__box {
733
- width: 100%;
734
- height: 8rem;
735
- position: relative;
736
- cursor: crosshair;
737
- }
738
-
739
- .colorPicker__canvas {
740
- width: 100%;
741
- height: 100%;
742
- touch-action: none;
743
- }
744
-
745
- .colorPicker__boxIndicator {
746
- position: absolute;
747
- width: 0.75rem;
748
- height: 0.75rem;
749
- border-radius: 50%;
750
- border: 2px solid white;
751
- transform: translate(-50%, -50%);
752
- pointer-events: none;
753
- }
754
-
755
- .colorPicker__sliderWrapper {
756
- position: relative;
757
- width: 100%;
758
- height: 1rem;
759
- }
760
-
761
- .colorPicker__sliderWrapper::before {
762
- content: '';
763
- position: absolute;
764
- top: 50%;
765
- left: 0;
766
- right: 0;
767
- height: 0.25rem;
768
- transform: translateY(-50%);
769
- border-radius: 0.125rem;
770
- pointer-events: none;
771
- }
772
-
773
- .colorPicker__sliderWrapper--hue::before {
774
- background: linear-gradient(to right, red, yellow, lime, cyan, blue, magenta, red);
775
- }
776
-
777
- .colorPicker__sliderWrapper--opacity::before {
778
- background: var(--opacityGradient);
779
- background-size: cover;
780
- }
781
-
782
- .colorPicker__slider {
783
- -webkit-appearance: none;
784
- appearance: none;
785
- width: 100%;
786
- height: 100%;
787
- cursor: pointer;
788
- background: transparent;
789
- position: relative;
790
- z-index: 1;
791
- }
792
-
793
- .colorPicker__slider::-webkit-slider-thumb {
794
- -webkit-appearance: none;
795
- appearance: none;
796
- width: 0.5rem;
797
- height: 0.5rem;
798
- border-radius: 50%;
799
- border: 2px solid white;
800
- background-color: var(--thumbBG);
801
- }
802
-
803
- .colorPicker__slider::-moz-range-thumb {
804
- width: 0.5rem;
805
- height: 0.5rem;
806
- border-radius: 50%;
807
- border: 2px solid white;
808
- background-color: var(--thumbBG);
809
- }
810
-
811
- .colorPicker__inputs {
812
- display: grid;
813
- grid-template-columns: repeat(5, minmax(0, 1fr));
814
- gap: 0.5rem;
815
- }
816
- .colorPicker__inputs--hex {
817
- grid-template-columns: 1fr 2fr;
818
- }
819
-
820
- @media (pointer: coarse) {
821
- .colorPicker__slider {
822
- height: 1rem;
823
- border-radius: var(--radius-2);
824
- }
825
-
826
- .colorPicker__sliderWrapper::before {
827
- height: 1rem;
828
- }
829
- .colorPicker__slider::-webkit-slider-thumb {
830
- width: 1rem;
831
- height: 1rem;
832
- }
833
- .colorPicker__slider::-moz-range-thumb {
834
- width: 1rem;
835
- height: 1rem;
836
- }
837
- }
838
- </style>