react-iro-gradient-picker 1.2.1 → 1.2.3

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
@@ -272,6 +272,58 @@ This is an enhanced version of the original react-gcolor-picker with major impro
272
272
  - **Updated Dependencies** - Latest versions of all packages
273
273
  - **Better Build Process** - Optimized for modern React applications
274
274
 
275
+ ## 🎨 Supported CSS Gradient Formats
276
+
277
+ **v1.2.2+ supports all standard CSS gradient formats with robust parsing:**
278
+
279
+ ### Linear Gradients
280
+
281
+ ```css
282
+ /* Angle-based directions */
283
+ linear-gradient(120deg, #FF6B6B, #FFD93D, #6BCB77)
284
+ linear-gradient(45deg, #4FACFE, #00F2FE, #38EF7D)
285
+ linear-gradient(200deg, #FF9A9E, #FAD0C4, #FBC2EB)
286
+ linear-gradient(60deg, #30CFD0, #330867, #6A82FB)
287
+
288
+ /* Named directions */
289
+ linear-gradient(to top right, #FF6B6B, #FFD93D)
290
+ linear-gradient(to bottom, #4FACFE, #00F2FE)
291
+ linear-gradient(to left, #FF9A9E, #FAD0C4)
292
+
293
+ /* With explicit positions */
294
+ linear-gradient(90deg, #FF6B6B 0%, #FFD93D 50%, #6BCB77 100%)
295
+
296
+ /* Without positions (auto-distributed) */
297
+ linear-gradient(180deg, #FF9966, #FF5E62, #F54EA2)
298
+ ```
299
+
300
+ ### Radial Gradients
301
+
302
+ ```css
303
+ /* Basic circle gradients */
304
+ radial-gradient(circle at center, #00C9FF, #92FE9D, #0061FF)
305
+ radial-gradient(circle at top left, #FF6B6B, #FF4757, #2F3542)
306
+ radial-gradient(circle at bottom right, #1E90FF, #3742FA, #2C3E50)
307
+
308
+ /* Positioned radial gradients */
309
+ radial-gradient(circle at 70% 30%, #2ED573, #1EAE98, #004E64)
310
+ radial-gradient(circle at 20% 80%, #FFB347, #FFCC33, #FF6347)
311
+ radial-gradient(circle at top center, #FF7E5F, #FEB47B, #FFD93D)
312
+ radial-gradient(circle at right center, #6A82FB, #FC5C7D, #FF85A1)
313
+
314
+ /* Complex positioning */
315
+ radial-gradient(circle at 30% 70%, #11998E, #38EF7D, #8BC34A)
316
+ radial-gradient(circle at 80% 20%, #F7971E, #FFD200, #FF512F)
317
+ radial-gradient(circle at 40% 40%, #C6FFDD, #FBD786, #F7797D)
318
+ ```
319
+
320
+ ### Advanced Features
321
+
322
+ - **Auto-positioning**: Color stops without explicit positions are automatically distributed evenly
323
+ - **Flexible syntax**: Supports various positioning keywords and percentage values
324
+ - **Error recovery**: Invalid gradients fall back to a default gradient instead of crashing
325
+ - **Type safety**: Full TypeScript support with proper gradient object interfaces
326
+
275
327
  ## Props
276
328
 
277
329
  | Attribute | Type | Default | Description |
package/dist/index.es.js CHANGED
@@ -6386,111 +6386,139 @@ var isValidRgba = (function (rgba) {
6386
6386
  return !!rgbaToHex(rgba);
6387
6387
  });
6388
6388
 
6389
- var combineRegExp = function (regexpList, flags) {
6390
- return new RegExp(regexpList.reduce(function (result, item) {
6391
- return result + (typeof item === 'string' ? item : item.source);
6392
- }, ''), flags);
6393
- };
6394
- var generateRegExp = function () {
6395
- var searchFlags = 'gi';
6396
- var rAngle = /(?:[+-]?\d*\.?\d+)(?:deg|grad|rad|turn)/;
6397
- var rSideCornerCapture = /to\s+((?:(?:left|right)(?:\s+(?:top|bottom))?))/;
6398
- var rRadial = /circle at\s+((?:(?:left|right|center|top|bottom)(?:\s+(?:left|right|center|top|bottom))?))/;
6399
- var rComma = /\s*,\s*/;
6400
- var rColorHex = /\#(?:[a-f0-9]{6,8}|[a-f0-9]{3})/;
6401
- var rDigits3 = /\(\s*(?:\d{1,3}%?\s*,\s*){2}%?\d{1,3}%?\s*\)/;
6402
- var rDigits4 = /\(\s*(?:\d{1,3}%?\s*,\s*){2}%?\d{1,3}%?\s*,\s*\d*\.?\d+\)/;
6403
- var rValue = /(?:[+-]?\d*\.?\d+)(?:%|[a-z]+)?/;
6404
- var rKeyword = /[_a-z-][_a-z0-9-]*/;
6405
- var rColor = combineRegExp([
6406
- '(?:',
6407
- rColorHex,
6408
- '|',
6409
- '(?:rgb|hsl)',
6410
- rDigits3,
6411
- '|',
6412
- '(?:rgba|hsla)',
6413
- rDigits4,
6414
- '|',
6415
- rKeyword,
6416
- ')'
6417
- ], '');
6418
- var rColorStop = combineRegExp([rColor, '(?:\\s+', rValue, '(?:\\s+', rValue, ')?)?'], '');
6419
- var rColorStopList = combineRegExp(['(?:', rColorStop, rComma, ')*', rColorStop], '');
6420
- var rLineCapture = combineRegExp(['(?:(', rAngle, ')|', rSideCornerCapture, '|', rRadial, ')'], '');
6421
- var rGradientSearch = combineRegExp(['(?:(', rLineCapture, ')', rComma, ')?(', rColorStopList, ')'], searchFlags);
6422
- var rColorStopSearch = combineRegExp([
6423
- '\\s*(',
6424
- rColor,
6425
- ')',
6426
- '(?:\\s+',
6427
- '(',
6428
- rValue,
6429
- '))?',
6430
- '(?:',
6431
- rComma,
6432
- '\\s*)?'
6433
- ], searchFlags);
6434
- return {
6435
- gradientSearch: rGradientSearch,
6436
- colorStopSearch: rColorStopSearch
6437
- };
6438
- };
6439
- var parseGradient$1 = function (regExpLib, input) {
6440
- var result = {
6441
- stops: [],
6442
- angle: '',
6443
- line: '',
6444
- original: ''
6445
- };
6446
- var matchGradient, matchColorStop, stopResult;
6447
- regExpLib.gradientSearch.lastIndex = 0;
6448
- matchGradient = regExpLib.gradientSearch.exec(input);
6449
- if (matchGradient !== null) {
6450
- result = __assign(__assign({}, result), { original: matchGradient[0] });
6451
- if (matchGradient[1]) {
6452
- result.line = matchGradient[1];
6389
+ var validGradient = (function (input) {
6390
+ try {
6391
+ // Clean input
6392
+ var cleanInput = input
6393
+ .trim()
6394
+ .replace(/;$/, '')
6395
+ .replace(/^background-image:\s*/, '');
6396
+ // Extract gradient type and content
6397
+ var gradientMatch = cleanInput.match(/^(linear|radial)-gradient\s*\(\s*(.*)\s*\)$/i);
6398
+ if (!gradientMatch) {
6399
+ return 'Failed to find gradient';
6453
6400
  }
6454
- if (matchGradient[2]) {
6455
- result.angle = matchGradient[2];
6401
+ var _a = __read(gradientMatch, 3), type = _a[1], content = _a[2];
6402
+ var parts = [];
6403
+ var currentPart = '';
6404
+ var parenDepth = 0;
6405
+ var inQuotes = false;
6406
+ // Parse content by splitting on commas, but respect parentheses and quotes
6407
+ for (var i = 0; i < content.length; i++) {
6408
+ var char = content[i];
6409
+ if (char === '"' || char === "'") {
6410
+ inQuotes = !inQuotes;
6411
+ }
6412
+ else if (!inQuotes) {
6413
+ if (char === '(')
6414
+ parenDepth++;
6415
+ else if (char === ')')
6416
+ parenDepth--;
6417
+ else if (char === ',' && parenDepth === 0) {
6418
+ parts.push(currentPart.trim());
6419
+ currentPart = '';
6420
+ continue;
6421
+ }
6422
+ }
6423
+ currentPart += char;
6456
6424
  }
6457
- if (matchGradient[3]) {
6458
- result.sideCorner = matchGradient[3];
6425
+ if (currentPart.trim()) {
6426
+ parts.push(currentPart.trim());
6459
6427
  }
6460
- regExpLib.colorStopSearch.lastIndex = 0;
6461
- matchColorStop = regExpLib.colorStopSearch.exec(matchGradient[5]);
6462
- while (matchColorStop !== null) {
6463
- var tinyColor = tinycolor(matchColorStop[1]);
6464
- stopResult = {
6465
- color: tinyColor.toRgbString()
6466
- };
6467
- if (matchColorStop[2]) {
6468
- stopResult.position = Number((parseInt(matchColorStop[2], 10) / 100).toFixed(2));
6428
+ var angle = '';
6429
+ var line = '';
6430
+ var colorStops = [];
6431
+ // Determine if first part is direction/angle or color stop
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);
6437
+ if (isDirection) {
6438
+ if (type === 'linear') {
6439
+ if (/^\d+deg$/i.test(firstPart)) {
6440
+ angle = firstPart.replace(/deg$/i, '');
6441
+ }
6442
+ else if (/^to\s+/.test(firstPart)) {
6443
+ line = firstPart;
6444
+ // Convert named directions to angles
6445
+ var directionMap = {
6446
+ 'to top': '0',
6447
+ 'to top right': '45',
6448
+ 'to right': '90',
6449
+ 'to bottom right': '135',
6450
+ 'to bottom': '180',
6451
+ 'to bottom left': '225',
6452
+ 'to left': '270',
6453
+ 'to top left': '315'
6454
+ };
6455
+ angle = directionMap[firstPart] || '0';
6456
+ }
6457
+ }
6458
+ else {
6459
+ line = firstPart;
6469
6460
  }
6470
- result.stops.push(stopResult);
6471
- matchColorStop = regExpLib.colorStopSearch.exec(matchGradient[5]);
6461
+ colorStops = parts.slice(1);
6472
6462
  }
6473
- }
6474
- return result;
6475
- };
6476
- var validGradient = (function (input) {
6477
- var regExpLib = generateRegExp();
6478
- var result;
6479
- var rGradientEnclosedInBrackets = /.*gradient\s*\(((?:\([^\)]*\)|[^\)\(]*)*)\)/;
6480
- var match = rGradientEnclosedInBrackets.exec(input);
6481
- if (match !== null) {
6482
- result = parseGradient$1(regExpLib, match[1]);
6483
- if (result.original.trim() !== match[1].trim()) {
6484
- result.parseWarning = true;
6463
+ else {
6464
+ // No explicit direction, use defaults
6465
+ angle = type === 'linear' ? '180' : '';
6466
+ line = type === 'radial' ? 'circle at center' : '';
6467
+ colorStops = parts;
6468
+ }
6469
+ // Parse color stops
6470
+ var stops_1 = [];
6471
+ for (var i = 0; i < colorStops.length; i++) {
6472
+ var stopString = colorStops[i].trim();
6473
+ // Try to extract color and position
6474
+ var stopMatch = stopString.match(/^(.+?)(?:\s+(\d+(?:\.\d+)?)(%)?)?$/);
6475
+ if (stopMatch) {
6476
+ var _b = __read(stopMatch, 4), colorStr = _b[1], positionStr = _b[2], isPercent = _b[3];
6477
+ var tinyColorInstance = tinycolor(colorStr.trim());
6478
+ if (tinyColorInstance.isValid()) {
6479
+ var stop_1 = {
6480
+ color: tinyColorInstance.toRgbString()
6481
+ };
6482
+ if (positionStr) {
6483
+ var position = parseFloat(positionStr);
6484
+ // Assume percentage if no unit specified
6485
+ if (isPercent || !isPercent) {
6486
+ position = position / 100;
6487
+ }
6488
+ stop_1.position = Math.max(0, Math.min(1, position));
6489
+ }
6490
+ stops_1.push(stop_1);
6491
+ }
6492
+ }
6485
6493
  }
6486
- if (result.stops.every(function (item) { return item.hasOwnProperty('position'); }) === false) {
6487
- result = 'Not correct position';
6494
+ // Auto-assign positions if missing
6495
+ stops_1.forEach(function (stop, index) {
6496
+ if (!stop.hasOwnProperty('position')) {
6497
+ stop.position = stops_1.length > 1 ? index / (stops_1.length - 1) : 0;
6498
+ }
6499
+ });
6500
+ // Ensure we have at least 2 stops
6501
+ if (stops_1.length === 0) {
6502
+ return 'No valid color stops found';
6503
+ }
6504
+ else if (stops_1.length === 1) {
6505
+ // Duplicate the single stop to create a valid gradient
6506
+ stops_1.push({
6507
+ color: stops_1[0].color,
6508
+ position: 1
6509
+ });
6488
6510
  }
6511
+ return {
6512
+ stops: stops_1,
6513
+ angle: angle,
6514
+ line: line,
6515
+ original: cleanInput
6516
+ };
6489
6517
  }
6490
- else {
6491
- result = 'Failed to find gradient';
6518
+ catch (error) {
6519
+ console.warn('Error parsing gradient:', error);
6520
+ return 'Failed to parse gradient';
6492
6521
  }
6493
- return result;
6494
6522
  });
6495
6523
 
6496
6524
  var LINEAR_POS = [
@@ -7731,7 +7759,19 @@ var IroGradient = function (_a) {
7731
7759
  // Store the initial value for reset functionality
7732
7760
  var initialValue = useRef(value);
7733
7761
  var parsedColors = useCallback(function () {
7734
- return parseGradient(value);
7762
+ try {
7763
+ var parsed = parseGradient(value);
7764
+ // If parsing failed, return fallback gradient
7765
+ if (typeof parsed === 'string') {
7766
+ console.warn('Gradient parsing failed, using fallback:', parsed);
7767
+ return parseGradient('linear-gradient(90deg, #ffffff 0%, #000000 100%)');
7768
+ }
7769
+ return parsed;
7770
+ }
7771
+ catch (error) {
7772
+ console.warn('Error parsing gradient, using fallback:', error);
7773
+ return parseGradient('linear-gradient(90deg, #ffffff 0%, #000000 100%)');
7774
+ }
7735
7775
  // eslint-disable-next-line react-hooks/exhaustive-deps
7736
7776
  }, [value]);
7737
7777
  var _s = parsedColors(), stops = _s.stops, type = _s.type, modifier = _s.modifier;