react-iro-gradient-picker 1.2.4 → 1.2.6

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 CHANGED
@@ -323,6 +323,91 @@ radial-gradient(circle at 40% 40%, #C6FFDD, #FBD786, #F7797D)
323
323
  - **Flexible syntax**: Supports various positioning keywords and percentage values
324
324
  - **Error recovery**: Invalid gradients fall back to a default gradient instead of crashing
325
325
  - **Type safety**: Full TypeScript support with proper gradient object interfaces
326
+ - **Smart position mapping**: Automatically highlights correct position markers for all gradient formats
327
+
328
+ ## 📐 Gradient Value Format Guide
329
+
330
+ The component accepts gradient values in multiple formats and automatically maps them to the correct UI controls:
331
+
332
+ ### ✅ Supported Gradient Formats
333
+
334
+ #### Linear Gradients
335
+
336
+ ```css
337
+ /* Angle-based (0-360 degrees) */
338
+ linear-gradient(45deg, #FF6B6B, #4ECDC4)
339
+ linear-gradient(180deg, #667eea 0%, #764ba2 100%)
340
+
341
+ /* Named directions (automatically converted to angles) */
342
+ linear-gradient(to top, #FF6B6B, #4ECDC4) → 0deg
343
+ linear-gradient(to top right, #FF6B6B, #4ECDC4) → 45deg
344
+ linear-gradient(to right, #FF6B6B, #4ECDC4) → 90deg
345
+ linear-gradient(to bottom, #FF6B6B, #4ECDC4) → 180deg
346
+ ```
347
+
348
+ #### Radial Gradients - Standard Positions
349
+
350
+ ```css
351
+ /* Standard position keywords (auto-mapped to UI markers) */
352
+ radial-gradient(circle at center, #FF6B6B, #4ECDC4)
353
+ radial-gradient(circle at top left, #FF6B6B, #4ECDC4)
354
+ radial-gradient(circle at top center, #FF6B6B, #4ECDC4) ✨ Maps to "center top"
355
+ radial-gradient(circle at right center, #FF6B6B, #4ECDC4) ✨ Maps to "center right"
356
+
357
+ /* Percentage-based positions */
358
+ radial-gradient(circle at 70% 30%, #FF6B6B, #4ECDC4)
359
+ radial-gradient(circle at 0% 100%, #FF6B6B, #4ECDC4)
360
+ ```
361
+
362
+ #### Radial Gradients - Edge Cases ✨ NEW
363
+
364
+ ```css
365
+ /* Size-only gradients (automatically default to center position) */
366
+ radial-gradient(70, #ff0000, #0000ff) ✨ → circle at center
367
+ radial-gradient(150%, #FFB347, #FFCC33, #FF6347) ✨ → circle at center
368
+ radial-gradient(200px, #FF6B6B, #4ECDC4) ✨ → circle at center
369
+
370
+ /* Size keywords (automatically default to center position) */
371
+ radial-gradient(closest-side, #FF6B6B, #4ECDC4) ✨ → circle at center
372
+ radial-gradient(farthest-corner, #FF6B6B, #4ECDC4) ✨ → circle at center
373
+ ```
374
+
375
+ ### 🎯 Position Mapping Intelligence
376
+
377
+ The component intelligently maps gradient positions to UI markers:
378
+
379
+ | **Input Format** | **UI Marker Highlighted** | **Notes** |
380
+ | ------------------------ | ------------------------- | ------------------------------- |
381
+ | `circle at center` | Center (●) | Standard center position |
382
+ | `circle at top center` | Center Top (●) | Alias automatically normalized |
383
+ | `circle at right center` | Center Right (●) | Alias automatically normalized |
384
+ | `70`, `150%`, `200px` | Center (●) | Size-only defaults to center |
385
+ | `closest-side` | Center (●) | Size keywords default to center |
386
+ | `circle at 25% 75%` | No marker | Custom percentage position |
387
+
388
+ ### 📝 Gradient Value Requirements
389
+
390
+ #### ✅ Valid Examples
391
+
392
+ ```css
393
+ /* With explicit positions (recommended) */
394
+ linear-gradient(90deg, #FF6B6B 0%, #4ECDC4 100%)
395
+ radial-gradient(circle at center, #FF6B6B 0%, #4ECDC4 50%, #FFD93D 100%)
396
+
397
+ /* Without positions (auto-distributed) */
398
+ linear-gradient(45deg, #FF6B6B, #4ECDC4, #FFD93D)
399
+ radial-gradient(circle at top left, #FF6B6B, #4ECDC4)
400
+ ```
401
+
402
+ #### ❌ Invalid Examples
403
+
404
+ ```css
405
+ /* Missing gradient type */
406
+ 90deg, #FF6B6B, #4ECDC4
407
+
408
+ /* Invalid color format */
409
+ linear-gradient(90deg, notacolor, #4ECDC4)
410
+ ```
326
411
 
327
412
  ## Props
328
413
 
@@ -351,39 +436,48 @@ radial-gradient(circle at 40% 40%, #C6FFDD, #FBD786, #F7797D)
351
436
  | showReset | `bool` | `false` | Show/hide reset button in the picker interface |
352
437
  | onReset | `function` | `null` | Callback function triggered when reset button is clicked |
353
438
 
354
- When passing a value for a gradient, you must specify the position of all colors. Otherwise the component will throw an exception.
355
- For example:
356
-
357
- ### Wrong
439
+ ## 🎯 Radial Gradient Position Reference
358
440
 
359
- ```
360
-
361
- linear-gradient(180deg, #000000,#ff0000)
362
-
363
- ```
364
-
365
- ### Correct
441
+ The component supports all standard radial gradient positions and automatically maps them to UI markers:
366
442
 
367
- ```
368
-
369
- linear-gradient(180deg, #000000 0%,#ff0000 100%)
443
+ ### Standard Positions (9-Point Grid)
370
444
 
445
+ ```css
446
+ /* Top Row */
447
+ circle at left top → Top-Left marker (●)
448
+ circle at center top → Top-Center marker (●)
449
+ circle at right top → Top-Right marker (●)
450
+
451
+ /* Middle Row */
452
+ circle at left → Middle-Left marker (●)
453
+ circle at center → Center marker (●) [Default]
454
+ circle at right → Middle-Right marker (●)
455
+
456
+ /* Bottom Row */
457
+ circle at left bottom → Bottom-Left marker (●)
458
+ circle at center bottom → Bottom-Center marker (●)
459
+ circle at right bottom → Bottom-Right marker (●)
371
460
  ```
372
461
 
373
- If you are using a radial gradient a list of possible directions for it:
462
+ ### Position Aliases (Auto-Normalized)
374
463
 
464
+ ```css
465
+ /* These aliases are automatically converted: */
466
+ circle at top center → circle at center top
467
+ circle at bottom center → circle at center bottom
468
+ circle at left center → circle at center left
469
+ circle at right center → circle at center right
375
470
  ```
376
471
 
377
- circle at left top
378
- circle at center top
379
- circle at right top
380
- circle at left
381
- circle at center
382
- circle at right
383
- circle at left bottom
384
- circle at center bottom
385
- circle at right bottom
472
+ ### Edge Cases (Auto-Defaulted to Center)
386
473
 
474
+ ```css
475
+ /* Size-only gradients default to center: */
476
+ 70 → circle at center
477
+ 150% → circle at center
478
+ 200px → circle at center
479
+ closest-side → circle at center
480
+ farthest-corner → circle at center
387
481
  ```
388
482
 
389
483
  ## Default color list
package/dist/index.es.js CHANGED
@@ -6430,10 +6430,18 @@ var validGradient = (function (input) {
6430
6430
  var colorStops = [];
6431
6431
  // Determine if first part is direction/angle or color stop
6432
6432
  var firstPart = parts[0];
6433
- var isDirection = /^\d+deg$/i.test(firstPart) ||
6434
- /^to\s+/.test(firstPart) ||
6435
- /^(?:circle|ellipse)/.test(firstPart) ||
6436
- /at\s+/.test(firstPart);
6433
+ var isDirection = false;
6434
+ if (type === 'linear') {
6435
+ isDirection = /^\d+deg$/i.test(firstPart) || /^to\s+/.test(firstPart);
6436
+ }
6437
+ else if (type === 'radial') {
6438
+ // For radial gradients, check for size, shape, or position keywords
6439
+ isDirection =
6440
+ /^(?:circle|ellipse)/.test(firstPart) ||
6441
+ /at\s+/.test(firstPart) ||
6442
+ /^(?:closest-side|closest-corner|farthest-side|farthest-corner)$/i.test(firstPart) ||
6443
+ /^\d+(?:%|px|em|rem)?$/i.test(firstPart); // Size values like "70", "70%", "70px"
6444
+ }
6437
6445
  if (isDirection) {
6438
6446
  if (type === 'linear') {
6439
6447
  if (/^\d+deg$/i.test(firstPart)) {
@@ -6593,12 +6601,23 @@ var parseGradient = (function (str) {
6593
6601
  var findF = (_a = LINEAR_POS.find(function (item) { return item.name === angle_1; })) === null || _a === void 0 ? void 0 : _a.angle;
6594
6602
  var helperAngle = type === 'linear' ? '180' : 'circle at center';
6595
6603
  var modifier = findF || angle_1 || helperAngle;
6604
+ // For radial gradients, preserve the full modifier string to maintain positioning
6605
+ var processedModifier = void 0;
6606
+ if (type === 'radial') {
6607
+ // Keep the full radial gradient specification
6608
+ processedModifier = modifier;
6609
+ }
6610
+ else {
6611
+ // For linear gradients, extract number if it's a degree value
6612
+ processedModifier =
6613
+ modifier.match(/\d+/) !== null
6614
+ ? Number((_b = modifier.match(/\d+/)) === null || _b === void 0 ? void 0 : _b.join(''))
6615
+ : modifier;
6616
+ }
6596
6617
  return {
6597
6618
  gradient: typeof gradient !== 'string' ? gradient.original : str,
6598
6619
  type: type,
6599
- modifier: modifier.match(/\d+/) !== null
6600
- ? Number((_b = modifier.match(/\d+/)) === null || _b === void 0 ? void 0 : _b.join(''))
6601
- : modifier,
6620
+ modifier: processedModifier,
6602
6621
  stops: stops.map(function (stop, index) {
6603
6622
  var formatStop = ["".concat(stop.color), index];
6604
6623
  if (stop.position || stop.position === 0) {
@@ -7455,9 +7474,18 @@ var Markers = function (_a) {
7455
7474
  };
7456
7475
  var onDrag = function (e) {
7457
7476
  var _a;
7458
- var x = e.clientX;
7459
- var y = e.clientY;
7477
+ // Defensive check for event object
7478
+ if (!e) {
7479
+ console.warn('onDrag called with undefined event object');
7480
+ return;
7481
+ }
7482
+ var x = e.clientX || 0;
7483
+ var y = e.clientY || 0;
7460
7484
  var rect = (_a = node === null || node === void 0 ? void 0 : node.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
7485
+ if (!rect) {
7486
+ console.warn('Unable to get bounding rect for drag operation');
7487
+ return;
7488
+ }
7461
7489
  var rootDistance = y - rect.y;
7462
7490
  // Now we know user is actually dragging
7463
7491
  setIsDragging(true);
@@ -7712,10 +7740,15 @@ var GradientPanel = function (_a) {
7712
7740
  }
7713
7741
  };
7714
7742
  var onDrag = function (e) {
7715
- var x = e.clientX;
7716
- var y = e.clientY;
7717
- var shiftKey = e.shiftKey;
7718
- var ctrlKey = e.ctrlKey * 2;
7743
+ // Defensive check for event object
7744
+ if (!e) {
7745
+ console.warn('onDrag called with undefined event object');
7746
+ return;
7747
+ }
7748
+ var x = e.clientX || 0;
7749
+ var y = e.clientY || 0;
7750
+ var shiftKey = e.shiftKey || false;
7751
+ var ctrlKey = (e.ctrlKey || false) * 2;
7719
7752
  pointMoveTo({
7720
7753
  x: x,
7721
7754
  y: y,
@@ -7854,7 +7887,10 @@ var IroGradient = function (_a) {
7854
7887
  console.warn('Gradient parsing failed, using fallback:', parsed);
7855
7888
  var fallback = parseGradient('linear-gradient(90deg, #ffffff 0%, #000000 100%)');
7856
7889
  // Ensure fallback has valid structure
7857
- if (fallback && typeof fallback === 'object' && Array.isArray(fallback.stops) && fallback.stops.length > 0) {
7890
+ if (fallback &&
7891
+ typeof fallback === 'object' &&
7892
+ Array.isArray(fallback.stops) &&
7893
+ fallback.stops.length > 0) {
7858
7894
  return fallback;
7859
7895
  }
7860
7896
  // Ultimate fallback with guaranteed structure
@@ -7869,7 +7905,10 @@ var IroGradient = function (_a) {
7869
7905
  };
7870
7906
  }
7871
7907
  // Validate parsed result has required structure
7872
- if (parsed && typeof parsed === 'object' && Array.isArray(parsed.stops) && parsed.stops.length > 0) {
7908
+ if (parsed &&
7909
+ typeof parsed === 'object' &&
7910
+ Array.isArray(parsed.stops) &&
7911
+ parsed.stops.length > 0) {
7873
7912
  return parsed;
7874
7913
  }
7875
7914
  // If parsed result is invalid, use ultimate fallback
@@ -7904,11 +7943,22 @@ var IroGradient = function (_a) {
7904
7943
  var isUpdatingFromGradientStop = useRef(false);
7905
7944
  var _t = __read(useState(200), 2), pickerWidth = _t[0], setPickerWidth = _t[1];
7906
7945
  // Safe extraction of stop data with fallbacks
7907
- var safeStops = Array.isArray(stops) && stops.length > 0 ? stops : [['rgba(255, 255, 255, 1)', 0, 0], ['rgba(0, 0, 0, 1)', 1, 1]];
7946
+ var safeStops = Array.isArray(stops) && stops.length > 0
7947
+ ? stops
7948
+ : [
7949
+ ['rgba(255, 255, 255, 1)', 0, 0],
7950
+ ['rgba(0, 0, 0, 1)', 1, 1]
7951
+ ];
7908
7952
  var safeLastStop = rgbaToArray(safeStops[safeStops.length - 1][0]);
7909
- var safeParsedLastStop = Array.isArray(safeLastStop) && safeLastStop.length >= 4 ? safeLastStop : [255, 255, 255, 1];
7953
+ var safeParsedLastStop = Array.isArray(safeLastStop) && safeLastStop.length >= 4
7954
+ ? safeLastStop
7955
+ : [255, 255, 255, 1];
7910
7956
  var activeStopIndex = safeStops.length - 1;
7911
- var activeStop = rgbaToHex([safeParsedLastStop[0], safeParsedLastStop[1], safeParsedLastStop[2]]);
7957
+ var activeStop = rgbaToHex([
7958
+ safeParsedLastStop[0],
7959
+ safeParsedLastStop[1],
7960
+ safeParsedLastStop[2]
7961
+ ]);
7912
7962
  var activeAlpha = Math.round(safeParsedLastStop[3] * 100);
7913
7963
  // Responsive width for IroColorPicker - match solid picker logic
7914
7964
  useEffect(function () {