@splendidlabz/utils 1.12.0 → 1.13.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.
Files changed (62) hide show
  1. package/dist/cjs/dom/font-size.cjs +1 -1
  2. package/dist/cjs/dom/index.cjs +1 -1
  3. package/dist/cjs/lib/colors.cjs +39 -0
  4. package/dist/cjs/lib/date/index.cjs +1 -1
  5. package/dist/cjs/lib/date/time.cjs +1 -1
  6. package/dist/cjs/lib/http/index.cjs +100 -0
  7. package/dist/cjs/lib/http/status-text.cjs +98 -0
  8. package/dist/cjs/lib/index.cjs +584 -11
  9. package/dist/cjs/lib/numbers/index.cjs +12 -1
  10. package/dist/cjs/lib/numbers/random.cjs +35 -0
  11. package/dist/cjs/lib/numbers/split-unit.cjs +35 -0
  12. package/dist/cjs/lib/promises/index.cjs +72 -15
  13. package/dist/cjs/lib/promises/reject.cjs +72 -13
  14. package/dist/cjs/lib/strings/index.cjs +368 -6
  15. package/dist/cjs/lib/strings/pluralize.cjs +372 -14
  16. package/dist/cjs/lib/strings/query-string.cjs +0 -6
  17. package/dist/cjs/lib/style/index.cjs +35 -1
  18. package/dist/cjs/lib/style/scatter.cjs +60 -0
  19. package/dist/cjs/lib/style/to-style-string.cjs +64 -0
  20. package/dist/cjs/lib/svg/displace.cjs +94 -0
  21. package/dist/cjs/lib/svg/index.cjs +126 -0
  22. package/dist/cjs/lib/svg/noise.cjs +56 -0
  23. package/dist/esm/lib/colors.js +14 -0
  24. package/dist/esm/lib/http/index.js +1 -0
  25. package/dist/esm/lib/http/status-text.js +72 -0
  26. package/dist/esm/lib/index.js +3 -0
  27. package/dist/esm/lib/numbers/index.js +2 -10
  28. package/dist/esm/lib/numbers/random.js +10 -0
  29. package/dist/esm/lib/numbers/split-unit.js +10 -0
  30. package/dist/esm/lib/promises/reject.js +2 -2
  31. package/dist/esm/lib/strings/pluralize.js +366 -3
  32. package/dist/esm/lib/strings/query-string.js +0 -5
  33. package/dist/esm/lib/style/index.js +2 -12
  34. package/dist/esm/lib/style/scatter.js +25 -0
  35. package/dist/esm/lib/style/to-style-string.js +12 -0
  36. package/dist/esm/lib/svg/displace.js +68 -0
  37. package/dist/esm/lib/svg/index.js +2 -0
  38. package/dist/esm/lib/svg/noise.js +16 -0
  39. package/dist/types/dom/font-size.d.cts +1 -1
  40. package/dist/types/lib/colors.d.cts +12 -0
  41. package/dist/types/lib/http/index.d.cts +1 -0
  42. package/dist/types/lib/http/status-text.d.cts +73 -0
  43. package/dist/types/lib/index.d.cts +11 -5
  44. package/dist/types/lib/numbers/index.d.cts +2 -4
  45. package/dist/types/lib/numbers/random.d.cts +14 -0
  46. package/dist/types/lib/numbers/split-unit.d.cts +8 -0
  47. package/dist/types/lib/strings/index.d.cts +2 -2
  48. package/dist/types/lib/strings/pluralize.d.cts +24 -2
  49. package/dist/types/lib/strings/query-string.d.cts +1 -2
  50. package/dist/types/lib/style/index.d.cts +2 -3
  51. package/dist/types/lib/style/scatter.d.cts +48 -0
  52. package/dist/types/lib/style/to-style-string.d.cts +8 -0
  53. package/dist/types/lib/svg/displace.d.cts +54 -0
  54. package/dist/types/lib/svg/index.d.cts +2 -0
  55. package/dist/types/lib/svg/noise.d.cts +24 -0
  56. package/dist/types/node/dirname.d.cts +2 -2
  57. package/dist/types/node/file.d.cts +1 -1
  58. package/dist/types/node/hash.d.cts +1 -1
  59. package/dist/types/node/pkce.d.cts +4 -4
  60. package/dist/types/node/random-string.d.cts +1 -1
  61. package/dist/types/node/uuid.d.cts +1 -1
  62. package/package.json +3 -6
@@ -38,10 +38,13 @@ __export(lib_exports, {
38
38
  composeAsync: () => composeAsync,
39
39
  concatMix: () => concatMix,
40
40
  createMix: () => createMix,
41
+ createPluralize: () => createPluralize,
41
42
  createSSE: () => createSSE,
42
43
  curry: () => curry,
43
44
  debounce: () => debounce,
44
45
  delay: () => delay,
46
+ displacePresets: () => displacePresets,
47
+ displaceSettings: () => displaceSettings,
45
48
  extendObject: () => extendObject,
46
49
  flattenArrayFields: () => flattenArrayFields,
47
50
  flattenObject: () => flattenObject,
@@ -54,6 +57,7 @@ __export(lib_exports, {
54
57
  getSymbolValue: () => getSymbolValue,
55
58
  getTimeInMs: () => getTimeInMs,
56
59
  getType: () => getType,
60
+ hexToRgb: () => hexToRgb,
57
61
  isArray: () => isArray,
58
62
  isEmpty: () => isEmpty,
59
63
  isEqual: () => isEqual,
@@ -61,12 +65,16 @@ __export(lib_exports, {
61
65
  isHashedValue: () => isHashedValue,
62
66
  isLastItem: () => isLastItem,
63
67
  isObject: () => isObject,
68
+ isPlural: () => isPlural,
69
+ isSingular: () => isSingular,
64
70
  joinWithConjunction: () => joinWithConjunction,
65
71
  last: () => last,
66
72
  lastArrayItem: () => lastArrayItem,
67
73
  markdown: () => markdown,
68
74
  mix: () => mix,
69
75
  ms: () => ms,
76
+ noiseColorMatrix: () => noiseColorMatrix,
77
+ noisePresets: () => noisePresets,
70
78
  normalizeObject: () => normalizeObject,
71
79
  notEmpty: () => notEmpty,
72
80
  notEqual: () => notEqual,
@@ -86,12 +94,17 @@ __export(lib_exports, {
86
94
  sanitize: () => sanitize,
87
95
  sanitizeArray: () => sanitizeArray,
88
96
  sanitizeObject: () => sanitizeObject,
97
+ scatter: () => scatter,
98
+ seededRandom: () => seededRandom,
89
99
  shuffle: () => shuffle,
100
+ singular: () => singular,
90
101
  sizeOf: () => sizeOf,
91
102
  sort: () => sort,
92
103
  splitArray: () => splitArray,
93
104
  splitObject: () => splitObject,
94
105
  splitUnit: () => splitUnit,
106
+ statusText: () => statusText,
107
+ statusTexts: () => statusTexts,
95
108
  stripNumbers: () => stripNumbers,
96
109
  throttle: () => throttle,
97
110
  timeout: () => timeout,
@@ -279,6 +292,19 @@ function isFunction(x) {
279
292
  return typeof x === "function";
280
293
  }
281
294
 
295
+ // src/lib/colors.js
296
+ function hexToRgb(hex) {
297
+ let h = hex.replace("#", "");
298
+ if (h.length === 3)
299
+ h = h.split("").map((c) => c + c).join("");
300
+ const int = parseInt(h, 16);
301
+ return {
302
+ r: +((int >> 16 & 255) / 255).toFixed(3),
303
+ g: +((int >> 8 & 255) / 255).toFixed(3),
304
+ b: +((int & 255) / 255).toFixed(3)
305
+ };
306
+ }
307
+
282
308
  // src/lib/date/days.js
283
309
  var DAYS = [
284
310
  { short: "Sun", long: "Sunday", numeric: 1 },
@@ -374,7 +400,16 @@ function toRadians(angle) {
374
400
  return angle * (Math.PI / 180);
375
401
  }
376
402
 
377
- // src/lib/numbers/index.js
403
+ // src/lib/numbers/random.js
404
+ function seededRandom(seed = 1) {
405
+ let state = seed >>> 0;
406
+ return () => {
407
+ state = state * 1664525 + 1013904223 >>> 0;
408
+ return state / 4294967296;
409
+ };
410
+ }
411
+
412
+ // src/lib/numbers/split-unit.js
378
413
  function splitUnit(string) {
379
414
  if (typeof string === "number") return [string, null];
380
415
  const regex = /(-?\d*\.?\d+)\s*([a-z]+)/i;
@@ -644,6 +679,76 @@ function isHashedValue(value, type = "sha256") {
644
679
  return null;
645
680
  }
646
681
 
682
+ // src/lib/http/status-text.js
683
+ var statusTexts = {
684
+ 100: "Continue",
685
+ 101: "Switching Protocols",
686
+ 102: "Processing",
687
+ 103: "Early Hints",
688
+ 200: "OK",
689
+ 201: "Created",
690
+ 202: "Accepted",
691
+ 203: "Non-Authoritative Information",
692
+ 204: "No Content",
693
+ 205: "Reset Content",
694
+ 206: "Partial Content",
695
+ 207: "Multi-Status",
696
+ 208: "Already Reported",
697
+ 226: "IM Used",
698
+ 300: "Multiple Choices",
699
+ 301: "Moved Permanently",
700
+ 302: "Found",
701
+ 303: "See Other",
702
+ 304: "Not Modified",
703
+ 305: "Use Proxy",
704
+ 307: "Temporary Redirect",
705
+ 308: "Permanent Redirect",
706
+ 400: "Bad Request",
707
+ 401: "Unauthorized",
708
+ 402: "Payment Required",
709
+ 403: "Forbidden",
710
+ 404: "Not Found",
711
+ 405: "Method Not Allowed",
712
+ 406: "Not Acceptable",
713
+ 407: "Proxy Authentication Required",
714
+ 408: "Request Timeout",
715
+ 409: "Conflict",
716
+ 410: "Gone",
717
+ 411: "Length Required",
718
+ 412: "Precondition Failed",
719
+ 413: "Payload Too Large",
720
+ 414: "URI Too Long",
721
+ 415: "Unsupported Media Type",
722
+ 416: "Range Not Satisfiable",
723
+ 417: "Expectation Failed",
724
+ 418: "I'm a Teapot",
725
+ 421: "Misdirected Request",
726
+ 422: "Unprocessable Entity",
727
+ 423: "Locked",
728
+ 424: "Failed Dependency",
729
+ 425: "Too Early",
730
+ 426: "Upgrade Required",
731
+ 428: "Precondition Required",
732
+ 429: "Too Many Requests",
733
+ 431: "Request Header Fields Too Large",
734
+ 451: "Unavailable For Legal Reasons",
735
+ 500: "Internal Server Error",
736
+ 501: "Not Implemented",
737
+ 502: "Bad Gateway",
738
+ 503: "Service Unavailable",
739
+ 504: "Gateway Timeout",
740
+ 505: "HTTP Version Not Supported",
741
+ 506: "Variant Also Negotiates",
742
+ 507: "Insufficient Storage",
743
+ 508: "Loop Detected",
744
+ 509: "Bandwidth Limit Exceeded",
745
+ 510: "Not Extended",
746
+ 511: "Network Authentication Required"
747
+ };
748
+ function statusText(code) {
749
+ return statusTexts[code];
750
+ }
751
+
647
752
  // src/lib/objects/loop.js
648
753
  function objectForEach(object, callback) {
649
754
  Object.entries(object).forEach(([key, value]) => {
@@ -936,13 +1041,12 @@ function splitObject(obj, keys) {
936
1041
  }
937
1042
 
938
1043
  // src/lib/promises/reject.js
939
- var import_statuses = __toESM(require("statuses"), 1);
940
1044
  function reject(props, { includeStack = true } = {}) {
941
- const { status, statusText, body, message } = props;
1045
+ const { status, statusText: statusText2, body, message } = props;
942
1046
  const e = new Error();
943
1047
  const err = {
944
1048
  status,
945
- statusText: statusText || status && (0, import_statuses.default)(status),
1049
+ statusText: statusText2 || status && statusText(status),
946
1050
  body,
947
1051
  message,
948
1052
  stack: includeStack && e.stack
@@ -1055,8 +1159,366 @@ function parseFullName(name) {
1055
1159
  }
1056
1160
 
1057
1161
  // src/lib/strings/pluralize.js
1058
- var import_pluralize = __toESM(require("pluralize"), 1);
1059
- var pluralize = import_pluralize.default;
1162
+ function sanitizeRule(rule) {
1163
+ if (typeof rule === "string") return new RegExp("^" + rule + "$", "i");
1164
+ return rule;
1165
+ }
1166
+ function restoreCase(word, token) {
1167
+ if (word === token) return token;
1168
+ if (word === word.toLowerCase()) return token.toLowerCase();
1169
+ if (word === word.toUpperCase()) return token.toUpperCase();
1170
+ if (word[0] === word[0].toUpperCase()) {
1171
+ return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase();
1172
+ }
1173
+ return token.toLowerCase();
1174
+ }
1175
+ function interpolate(str, args) {
1176
+ return str.replace(/\$(\d{1,2})/g, (match, index) => args[index] || "");
1177
+ }
1178
+ function replace(word, rule) {
1179
+ return word.replace(rule[0], function(match, index) {
1180
+ const result = interpolate(rule[1], arguments);
1181
+ if (match === "") return restoreCase(word[index - 1], result);
1182
+ return restoreCase(match, result);
1183
+ });
1184
+ }
1185
+ function sanitizeWord(token, word, rules, uncountables) {
1186
+ if (!token.length || uncountables.hasOwnProperty(token)) return word;
1187
+ let len = rules.length;
1188
+ while (len--) {
1189
+ const rule = rules[len];
1190
+ if (rule[0].test(word)) return replace(word, rule);
1191
+ }
1192
+ return word;
1193
+ }
1194
+ function replaceWord(replaceMap, keepMap, rules, uncountables) {
1195
+ return function(word) {
1196
+ const token = word.toLowerCase();
1197
+ if (keepMap.hasOwnProperty(token)) return restoreCase(word, token);
1198
+ if (replaceMap.hasOwnProperty(token)) {
1199
+ return restoreCase(word, replaceMap[token]);
1200
+ }
1201
+ return sanitizeWord(token, word, rules, uncountables);
1202
+ };
1203
+ }
1204
+ function checkWord(replaceMap, keepMap, rules, uncountables) {
1205
+ return function(word) {
1206
+ const token = word.toLowerCase();
1207
+ if (keepMap.hasOwnProperty(token)) return true;
1208
+ if (replaceMap.hasOwnProperty(token)) return false;
1209
+ return sanitizeWord(token, token, rules, uncountables) === token;
1210
+ };
1211
+ }
1212
+ var BASE_IRREGULAR = [
1213
+ // Pronouns.
1214
+ ["I", "we"],
1215
+ ["me", "us"],
1216
+ ["he", "they"],
1217
+ ["she", "they"],
1218
+ ["them", "them"],
1219
+ ["myself", "ourselves"],
1220
+ ["yourself", "yourselves"],
1221
+ ["itself", "themselves"],
1222
+ ["herself", "themselves"],
1223
+ ["himself", "themselves"],
1224
+ ["themself", "themselves"],
1225
+ ["is", "are"],
1226
+ ["was", "were"],
1227
+ ["has", "have"],
1228
+ ["this", "these"],
1229
+ ["that", "those"],
1230
+ // Words ending with a consonant and `o`.
1231
+ ["echo", "echoes"],
1232
+ ["dingo", "dingoes"],
1233
+ ["volcano", "volcanoes"],
1234
+ ["tornado", "tornadoes"],
1235
+ ["torpedo", "torpedoes"],
1236
+ // Ends with `us`.
1237
+ ["genus", "genera"],
1238
+ ["viscus", "viscera"],
1239
+ // Ends with `ma`.
1240
+ ["stigma", "stigmata"],
1241
+ ["stoma", "stomata"],
1242
+ ["dogma", "dogmata"],
1243
+ ["lemma", "lemmata"],
1244
+ ["schema", "schemata"],
1245
+ ["anathema", "anathemata"],
1246
+ // Other irregular rules.
1247
+ ["ox", "oxen"],
1248
+ ["axe", "axes"],
1249
+ ["die", "dice"],
1250
+ ["yes", "yeses"],
1251
+ ["foot", "feet"],
1252
+ ["eave", "eaves"],
1253
+ ["goose", "geese"],
1254
+ ["tooth", "teeth"],
1255
+ ["quiz", "quizzes"],
1256
+ ["human", "humans"],
1257
+ ["proof", "proofs"],
1258
+ ["carve", "carves"],
1259
+ ["valve", "valves"],
1260
+ ["looey", "looies"],
1261
+ ["thief", "thieves"],
1262
+ ["groove", "grooves"],
1263
+ ["pickaxe", "pickaxes"],
1264
+ ["passerby", "passersby"]
1265
+ ];
1266
+ var BASE_PLURAL = [
1267
+ [/s?$/i, "s"],
1268
+ // eslint-disable-next-line no-control-regex
1269
+ [/[^\u0000-\u007F]$/i, "$0"],
1270
+ [/([^aeiou]ese)$/i, "$1"],
1271
+ [/(ax|test)is$/i, "$1es"],
1272
+ [/(alias|[^aou]us|t[lm]as|gas|ris)$/i, "$1es"],
1273
+ [/(e[mn]u)s?$/i, "$1s"],
1274
+ [/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i, "$1"],
1275
+ [
1276
+ /(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,
1277
+ "$1i"
1278
+ ],
1279
+ [/(alumn|alg|vertebr)(?:a|ae)$/i, "$1ae"],
1280
+ [/(seraph|cherub)(?:im)?$/i, "$1im"],
1281
+ [/(her|at|gr)o$/i, "$1oes"],
1282
+ [
1283
+ /(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i,
1284
+ "$1a"
1285
+ ],
1286
+ [
1287
+ /(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i,
1288
+ "$1a"
1289
+ ],
1290
+ [/sis$/i, "ses"],
1291
+ [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, "$1$2ves"],
1292
+ [/([^aeiouy]|qu)y$/i, "$1ies"],
1293
+ [/([^ch][ieo][ln])ey$/i, "$1ies"],
1294
+ [/(x|ch|ss|sh|zz)$/i, "$1es"],
1295
+ [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, "$1ices"],
1296
+ [/\b((?:tit)?m|l)(?:ice|ouse)$/i, "$1ice"],
1297
+ [/(pe)(?:rson|ople)$/i, "$1ople"],
1298
+ [/(child)(?:ren)?$/i, "$1ren"],
1299
+ [/eaux$/i, "$0"],
1300
+ [/m[ae]n$/i, "men"],
1301
+ ["thou", "you"]
1302
+ ];
1303
+ var BASE_SINGULAR = [
1304
+ [/s$/i, ""],
1305
+ [/(ss)$/i, "$1"],
1306
+ [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, "$1fe"],
1307
+ [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, "$1f"],
1308
+ [/ies$/i, "y"],
1309
+ [
1310
+ /\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i,
1311
+ "$1ie"
1312
+ ],
1313
+ [/\b(mon|smil)ies$/i, "$1ey"],
1314
+ [/\b((?:tit)?m|l)ice$/i, "$1ouse"],
1315
+ [/(seraph|cherub)im$/i, "$1"],
1316
+ [
1317
+ /(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i,
1318
+ "$1"
1319
+ ],
1320
+ [
1321
+ /(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i,
1322
+ "$1sis"
1323
+ ],
1324
+ [/(movie|twelve|abuse|e[mn]u)s$/i, "$1"],
1325
+ [/(test)(?:is|es)$/i, "$1is"],
1326
+ [
1327
+ /(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i,
1328
+ "$1us"
1329
+ ],
1330
+ [
1331
+ /(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i,
1332
+ "$1um"
1333
+ ],
1334
+ [
1335
+ /(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i,
1336
+ "$1on"
1337
+ ],
1338
+ [/(alumn|alg|vertebr)ae$/i, "$1a"],
1339
+ [/(cod|mur|sil|vert|ind)ices$/i, "$1ex"],
1340
+ [/(matr|append)ices$/i, "$1ix"],
1341
+ [/(pe)(rson|ople)$/i, "$1rson"],
1342
+ [/(child)ren$/i, "$1"],
1343
+ [/(eau)x?$/i, "$1"],
1344
+ [/men$/i, "man"]
1345
+ ];
1346
+ var BASE_UNCOUNTABLE = [
1347
+ // Singular words with no plurals.
1348
+ "adulthood",
1349
+ "advice",
1350
+ "agenda",
1351
+ "aid",
1352
+ "aircraft",
1353
+ "alcohol",
1354
+ "ammo",
1355
+ "analytics",
1356
+ "anime",
1357
+ "athletics",
1358
+ "audio",
1359
+ "bison",
1360
+ "blood",
1361
+ "bream",
1362
+ "buffalo",
1363
+ "butter",
1364
+ "carp",
1365
+ "cash",
1366
+ "chassis",
1367
+ "chess",
1368
+ "clothing",
1369
+ "cod",
1370
+ "commerce",
1371
+ "cooperation",
1372
+ "corps",
1373
+ "debris",
1374
+ "diabetes",
1375
+ "digestion",
1376
+ "elk",
1377
+ "energy",
1378
+ "equipment",
1379
+ "excretion",
1380
+ "expertise",
1381
+ "firmware",
1382
+ "flounder",
1383
+ "fun",
1384
+ "gallows",
1385
+ "garbage",
1386
+ "graffiti",
1387
+ "hardware",
1388
+ "headquarters",
1389
+ "health",
1390
+ "herpes",
1391
+ "highjinks",
1392
+ "homework",
1393
+ "housework",
1394
+ "information",
1395
+ "jeans",
1396
+ "justice",
1397
+ "kudos",
1398
+ "labour",
1399
+ "literature",
1400
+ "machinery",
1401
+ "mackerel",
1402
+ "mail",
1403
+ "media",
1404
+ "mews",
1405
+ "moose",
1406
+ "music",
1407
+ "mud",
1408
+ "manga",
1409
+ "news",
1410
+ "only",
1411
+ "personnel",
1412
+ "pike",
1413
+ "plankton",
1414
+ "pliers",
1415
+ "police",
1416
+ "pollution",
1417
+ "premises",
1418
+ "rain",
1419
+ "research",
1420
+ "rice",
1421
+ "salmon",
1422
+ "scissors",
1423
+ "series",
1424
+ "sewage",
1425
+ "shambles",
1426
+ "shrimp",
1427
+ "software",
1428
+ "species",
1429
+ "staff",
1430
+ "swine",
1431
+ "tennis",
1432
+ "traffic",
1433
+ "transportation",
1434
+ "trout",
1435
+ "tuna",
1436
+ "wealth",
1437
+ "welfare",
1438
+ "whiting",
1439
+ "wildebeest",
1440
+ "wildlife",
1441
+ "you",
1442
+ /pok[eé]mon$/i,
1443
+ // Regexes.
1444
+ /[^aeiou]ese$/i,
1445
+ // "chinese", "japanese"
1446
+ /deer$/i,
1447
+ // "deer", "reindeer"
1448
+ /fish$/i,
1449
+ // "fish", "blowfish", "angelfish"
1450
+ /measles$/i,
1451
+ /o[iu]s$/i,
1452
+ // "carnivorous"
1453
+ /pox$/i,
1454
+ // "chickpox", "smallpox"
1455
+ /sheep$/i
1456
+ ];
1457
+ function createPluralize(config = {}) {
1458
+ const pluralRules = [];
1459
+ const singularRules = [];
1460
+ const uncountables = {};
1461
+ const irregularPlurals = {};
1462
+ const irregularSingles = {};
1463
+ for (const [single, plur] of [
1464
+ ...BASE_IRREGULAR,
1465
+ ...config.irregular || []
1466
+ ]) {
1467
+ irregularSingles[single.toLowerCase()] = plur.toLowerCase();
1468
+ irregularPlurals[plur.toLowerCase()] = single.toLowerCase();
1469
+ }
1470
+ for (const [rule, replacement] of [...BASE_PLURAL, ...config.plural || []]) {
1471
+ pluralRules.push([sanitizeRule(rule), replacement]);
1472
+ }
1473
+ for (const [rule, replacement] of [
1474
+ ...BASE_SINGULAR,
1475
+ ...config.singular || []
1476
+ ]) {
1477
+ singularRules.push([sanitizeRule(rule), replacement]);
1478
+ }
1479
+ for (const word of [...BASE_UNCOUNTABLE, ...config.uncountable || []]) {
1480
+ if (typeof word === "string") {
1481
+ uncountables[word.toLowerCase()] = true;
1482
+ } else {
1483
+ pluralRules.push([sanitizeRule(word), "$0"]);
1484
+ singularRules.push([sanitizeRule(word), "$0"]);
1485
+ }
1486
+ }
1487
+ const plural2 = replaceWord(
1488
+ irregularSingles,
1489
+ irregularPlurals,
1490
+ pluralRules,
1491
+ uncountables
1492
+ );
1493
+ const singular2 = replaceWord(
1494
+ irregularPlurals,
1495
+ irregularSingles,
1496
+ singularRules,
1497
+ uncountables
1498
+ );
1499
+ const isPlural2 = checkWord(
1500
+ irregularSingles,
1501
+ irregularPlurals,
1502
+ pluralRules,
1503
+ uncountables
1504
+ );
1505
+ const isSingular2 = checkWord(
1506
+ irregularPlurals,
1507
+ irregularSingles,
1508
+ singularRules,
1509
+ uncountables
1510
+ );
1511
+ function pluralize2(word, count, inclusive) {
1512
+ const out = count === 1 ? singular2(word) : plural2(word);
1513
+ return (inclusive ? count + " " : "") + out;
1514
+ }
1515
+ return Object.assign(pluralize2, { plural: plural2, singular: singular2, isPlural: isPlural2, isSingular: isSingular2 });
1516
+ }
1517
+ var pluralize = createPluralize();
1518
+ var plural = pluralize.plural;
1519
+ var singular = pluralize.singular;
1520
+ var isPlural = pluralize.isPlural;
1521
+ var isSingular = pluralize.isSingular;
1060
1522
 
1061
1523
  // src/lib/strings/query-string.js
1062
1524
  function toQueryString(object) {
@@ -1090,15 +1552,34 @@ function parseQueryString(string = "") {
1090
1552
  }
1091
1553
  return result;
1092
1554
  }
1093
- function plural(count, noun, suffix = "s") {
1094
- console.warn("plural is deprecated. Use pluralize instead");
1095
- return `${count} ${noun}${count !== 1 ? suffix : ""}`;
1096
- }
1097
1555
  function stripNumbers(string) {
1098
1556
  return string.replace(/\d*/, "");
1099
1557
  }
1100
1558
 
1101
- // src/lib/style/index.js
1559
+ // src/lib/style/scatter.js
1560
+ var round = (n) => {
1561
+ const value = Math.round(n * 100) / 100;
1562
+ return value === 0 ? 0 : value;
1563
+ };
1564
+ function scatter(count, options = {}) {
1565
+ const { seed = 1, spread = 20, rotation = 6, amount = 1 } = options;
1566
+ const random = seededRandom(seed);
1567
+ const items = [];
1568
+ for (let i = 0; i < count; i++) {
1569
+ const x = round((random() - 0.5) * 2 * spread * amount);
1570
+ const y = round((random() - 0.5) * 2 * spread * amount);
1571
+ const r = round((random() - 0.5) * 2 * rotation * amount);
1572
+ items.push({
1573
+ x,
1574
+ y,
1575
+ rotation: r,
1576
+ transform: `translate(${x}%, ${y}%) rotate(${r}deg)`
1577
+ });
1578
+ }
1579
+ return items;
1580
+ }
1581
+
1582
+ // src/lib/style/to-style-string.js
1102
1583
  function toStyleString(style) {
1103
1584
  if (!style) return null;
1104
1585
  if (typeof style === "string") return style;
@@ -1108,6 +1589,85 @@ function toStyleString(style) {
1108
1589
  }).join("; ").concat(";");
1109
1590
  }
1110
1591
 
1592
+ // src/lib/svg/displace.js
1593
+ var displacePresets = {
1594
+ // Ink bleeding into absorbent paper. Long wavelength, small push.
1595
+ "wet-ink": {
1596
+ type: "fractalNoise",
1597
+ frequency: 0.015,
1598
+ octaves: 3,
1599
+ scale: 9,
1600
+ seed: 2
1601
+ },
1602
+ // Ink bitten into paper tooth. The edge roughens without the letterform
1603
+ // moving, so this is the only preset that survives at body sizes.
1604
+ letterpress: {
1605
+ type: "fractalNoise",
1606
+ frequency: 0.09,
1607
+ octaves: 1,
1608
+ scale: 2,
1609
+ seed: 5
1610
+ },
1611
+ // Air over heat. Anisotropic so the shimmer rises instead of swimming.
1612
+ // Reads as nothing unless animated.
1613
+ "heat-haze": {
1614
+ type: "fractalNoise",
1615
+ frequency: [4e-3, 0.02],
1616
+ animateTo: [6e-3, 0.03],
1617
+ duration: 8,
1618
+ octaves: 2,
1619
+ scale: 7,
1620
+ seed: 11
1621
+ },
1622
+ // Tracking error on worn tape. A near-infinite horizontal wavelength against
1623
+ // a very short vertical one is what tears rather than blobs.
1624
+ "bad-tape": {
1625
+ type: "turbulence",
1626
+ frequency: [8e-4, 0.06],
1627
+ animateTo: [8e-4, 0.09],
1628
+ duration: 2.5,
1629
+ octaves: 1,
1630
+ scale: 14,
1631
+ seed: 3
1632
+ },
1633
+ // Past the shred threshold on purpose.
1634
+ shred: {
1635
+ type: "turbulence",
1636
+ frequency: 0.055,
1637
+ octaves: 2,
1638
+ scale: 32,
1639
+ seed: 7
1640
+ }
1641
+ };
1642
+ var format = (f) => Array.isArray(f) ? f.join(" ") : String(f);
1643
+ function displaceSettings(opts = {}) {
1644
+ const base = opts.preset && displacePresets[opts.preset] || displacePresets["wet-ink"];
1645
+ const frequency = opts.frequency ?? base.frequency;
1646
+ const animateTo = opts.animateTo ?? base.animateTo;
1647
+ return {
1648
+ type: opts.type ?? base.type,
1649
+ frequency: format(frequency),
1650
+ animateTo: animateTo ? format(animateTo) : null,
1651
+ duration: opts.duration ?? base.duration ?? 6,
1652
+ octaves: opts.octaves ?? base.octaves,
1653
+ scale: opts.scale ?? base.scale,
1654
+ seed: opts.seed ?? base.seed
1655
+ };
1656
+ }
1657
+
1658
+ // src/lib/svg/noise.js
1659
+ var noisePresets = {
1660
+ black: "#000000",
1661
+ sepia: "#a67c52",
1662
+ synthwave: "#ff2bd6"
1663
+ };
1664
+ function noiseColorMatrix(color, strength) {
1665
+ if (!color || color === "rainbow")
1666
+ return `1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 ${strength} 0`;
1667
+ const { r, g, b } = hexToRgb(noisePresets[color] ?? color);
1668
+ return `0 0 0 0 ${r} 0 0 0 0 ${g} 0 0 0 0 ${b} 0 0 0 ${strength} 0`;
1669
+ }
1670
+
1111
1671
  // src/lib/symbols/symbols.js
1112
1672
  function getSymbol(object, description) {
1113
1673
  return Object.getOwnPropertySymbols(object).find(
@@ -1128,10 +1688,13 @@ function getSymbolValue(object, description) {
1128
1688
  composeAsync,
1129
1689
  concatMix,
1130
1690
  createMix,
1691
+ createPluralize,
1131
1692
  createSSE,
1132
1693
  curry,
1133
1694
  debounce,
1134
1695
  delay,
1696
+ displacePresets,
1697
+ displaceSettings,
1135
1698
  extendObject,
1136
1699
  flattenArrayFields,
1137
1700
  flattenObject,
@@ -1144,6 +1707,7 @@ function getSymbolValue(object, description) {
1144
1707
  getSymbolValue,
1145
1708
  getTimeInMs,
1146
1709
  getType,
1710
+ hexToRgb,
1147
1711
  isArray,
1148
1712
  isEmpty,
1149
1713
  isEqual,
@@ -1151,12 +1715,16 @@ function getSymbolValue(object, description) {
1151
1715
  isHashedValue,
1152
1716
  isLastItem,
1153
1717
  isObject,
1718
+ isPlural,
1719
+ isSingular,
1154
1720
  joinWithConjunction,
1155
1721
  last,
1156
1722
  lastArrayItem,
1157
1723
  markdown,
1158
1724
  mix,
1159
1725
  ms,
1726
+ noiseColorMatrix,
1727
+ noisePresets,
1160
1728
  normalizeObject,
1161
1729
  notEmpty,
1162
1730
  notEqual,
@@ -1176,12 +1744,17 @@ function getSymbolValue(object, description) {
1176
1744
  sanitize,
1177
1745
  sanitizeArray,
1178
1746
  sanitizeObject,
1747
+ scatter,
1748
+ seededRandom,
1179
1749
  shuffle,
1750
+ singular,
1180
1751
  sizeOf,
1181
1752
  sort,
1182
1753
  splitArray,
1183
1754
  splitObject,
1184
1755
  splitUnit,
1756
+ statusText,
1757
+ statusTexts,
1185
1758
  stripNumbers,
1186
1759
  throttle,
1187
1760
  timeout,