@canonical/utils 0.20.0 → 0.21.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 (93) hide show
  1. package/dist/esm/casing/capitalize.js +12 -0
  2. package/dist/esm/casing/capitalize.js.map +1 -0
  3. package/dist/esm/casing/capitalize.test.js +17 -0
  4. package/dist/esm/casing/capitalize.test.js.map +1 -0
  5. package/dist/esm/casing/index.js +8 -0
  6. package/dist/esm/casing/index.js.map +1 -0
  7. package/dist/esm/casing/isPascalCase.js +11 -0
  8. package/dist/esm/casing/isPascalCase.js.map +1 -0
  9. package/dist/esm/casing/isPascalCase.test.js +22 -0
  10. package/dist/esm/casing/isPascalCase.test.js.map +1 -0
  11. package/dist/esm/casing/toCamelCase.js +15 -0
  12. package/dist/esm/casing/toCamelCase.js.map +1 -0
  13. package/dist/esm/casing/toCamelCase.test.js +20 -0
  14. package/dist/esm/casing/toCamelCase.test.js.map +1 -0
  15. package/dist/esm/casing/toConstantCase.js +14 -0
  16. package/dist/esm/casing/toConstantCase.js.map +1 -0
  17. package/dist/esm/casing/toConstantCase.test.js +17 -0
  18. package/dist/esm/casing/toConstantCase.test.js.map +1 -0
  19. package/dist/esm/casing/toKebabCase.js +21 -0
  20. package/dist/esm/casing/toKebabCase.js.map +1 -0
  21. package/dist/esm/casing/toKebabCase.test.js +26 -0
  22. package/dist/esm/casing/toKebabCase.test.js.map +1 -0
  23. package/dist/esm/casing/toPascalCase.js +16 -0
  24. package/dist/esm/casing/toPascalCase.js.map +1 -0
  25. package/dist/esm/casing/toPascalCase.test.js +20 -0
  26. package/dist/esm/casing/toPascalCase.test.js.map +1 -0
  27. package/dist/esm/casing/toSnakeCase.js +17 -0
  28. package/dist/esm/casing/toSnakeCase.js.map +1 -0
  29. package/dist/esm/casing/toSnakeCase.test.js +20 -0
  30. package/dist/esm/casing/toSnakeCase.test.js.map +1 -0
  31. package/dist/esm/debounce.test.js +68 -0
  32. package/dist/esm/debounce.test.js.map +1 -0
  33. package/dist/esm/indent.js +14 -0
  34. package/dist/esm/indent.js.map +1 -0
  35. package/dist/esm/indent.test.js +14 -0
  36. package/dist/esm/indent.test.js.map +1 -0
  37. package/dist/esm/index.js +3 -1
  38. package/dist/esm/index.js.map +1 -1
  39. package/dist/esm/join.js +11 -0
  40. package/dist/esm/join.js.map +1 -0
  41. package/dist/esm/join.test.js +17 -0
  42. package/dist/esm/join.test.js.map +1 -0
  43. package/dist/esm/throttle.test.js +59 -0
  44. package/dist/esm/throttle.test.js.map +1 -0
  45. package/dist/types/casing/capitalize.d.ts +8 -0
  46. package/dist/types/casing/capitalize.d.ts.map +1 -0
  47. package/dist/types/casing/capitalize.test.d.ts +2 -0
  48. package/dist/types/casing/capitalize.test.d.ts.map +1 -0
  49. package/dist/types/casing/index.d.ts +8 -0
  50. package/dist/types/casing/index.d.ts.map +1 -0
  51. package/dist/types/casing/isPascalCase.d.ts +9 -0
  52. package/dist/types/casing/isPascalCase.d.ts.map +1 -0
  53. package/dist/types/casing/isPascalCase.test.d.ts +2 -0
  54. package/dist/types/casing/isPascalCase.test.d.ts.map +1 -0
  55. package/dist/types/casing/toCamelCase.d.ts +9 -0
  56. package/dist/types/casing/toCamelCase.d.ts.map +1 -0
  57. package/dist/types/casing/toCamelCase.test.d.ts +2 -0
  58. package/dist/types/casing/toCamelCase.test.d.ts.map +1 -0
  59. package/dist/types/casing/toConstantCase.d.ts +9 -0
  60. package/dist/types/casing/toConstantCase.d.ts.map +1 -0
  61. package/dist/types/casing/toConstantCase.test.d.ts +2 -0
  62. package/dist/types/casing/toConstantCase.test.d.ts.map +1 -0
  63. package/dist/types/casing/toKebabCase.d.ts +12 -0
  64. package/dist/types/casing/toKebabCase.d.ts.map +1 -0
  65. package/dist/types/casing/toKebabCase.test.d.ts +2 -0
  66. package/dist/types/casing/toKebabCase.test.d.ts.map +1 -0
  67. package/dist/types/casing/toPascalCase.d.ts +9 -0
  68. package/dist/types/casing/toPascalCase.d.ts.map +1 -0
  69. package/dist/types/casing/toPascalCase.test.d.ts +2 -0
  70. package/dist/types/casing/toPascalCase.test.d.ts.map +1 -0
  71. package/dist/types/casing/toSnakeCase.d.ts +10 -0
  72. package/dist/types/casing/toSnakeCase.d.ts.map +1 -0
  73. package/dist/types/casing/toSnakeCase.test.d.ts +2 -0
  74. package/dist/types/casing/toSnakeCase.test.d.ts.map +1 -0
  75. package/dist/types/debounce.test.d.ts +2 -0
  76. package/dist/types/debounce.test.d.ts.map +1 -0
  77. package/dist/types/indent.d.ts +8 -0
  78. package/dist/types/indent.d.ts.map +1 -0
  79. package/dist/types/indent.test.d.ts +2 -0
  80. package/dist/types/indent.test.d.ts.map +1 -0
  81. package/dist/types/index.d.ts +3 -1
  82. package/dist/types/index.d.ts.map +1 -1
  83. package/dist/types/join.d.ts +9 -0
  84. package/dist/types/join.d.ts.map +1 -0
  85. package/dist/types/join.test.d.ts +2 -0
  86. package/dist/types/join.test.d.ts.map +1 -0
  87. package/dist/types/throttle.test.d.ts +2 -0
  88. package/dist/types/throttle.test.d.ts.map +1 -0
  89. package/package.json +7 -7
  90. package/dist/esm/casing.js +0 -66
  91. package/dist/esm/casing.js.map +0 -1
  92. package/dist/types/casing.d.ts +0 -8
  93. package/dist/types/casing.d.ts.map +0 -1
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Capitalize the first character of a string.
3
+ *
4
+ * @example
5
+ * capitalize("hello") // "Hello"
6
+ */
7
+ export default function capitalize(s) {
8
+ if (!s)
9
+ return "";
10
+ return s.charAt(0).toUpperCase() + s.slice(1);
11
+ }
12
+ //# sourceMappingURL=capitalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capitalize.js","sourceRoot":"","sources":["../../../src/casing/capitalize.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,CAAS;IAC1C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import capitalize from "./capitalize.js";
3
+ describe("capitalize", () => {
4
+ it("capitalizes the first character", () => {
5
+ expect(capitalize("hello")).toBe("Hello");
6
+ });
7
+ it("preserves the rest of the string", () => {
8
+ expect(capitalize("hello world")).toBe("Hello world");
9
+ });
10
+ it("handles already capitalized strings", () => {
11
+ expect(capitalize("Hello")).toBe("Hello");
12
+ });
13
+ it("returns empty string for empty input", () => {
14
+ expect(capitalize("")).toBe("");
15
+ });
16
+ });
17
+ //# sourceMappingURL=capitalize.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capitalize.test.js","sourceRoot":"","sources":["../../../src/casing/capitalize.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,UAAU,MAAM,iBAAiB,CAAC;AAEzC,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { default as capitalize } from "./capitalize.js";
2
+ export { default as isPascalCase } from "./isPascalCase.js";
3
+ export { default as toCamelCase } from "./toCamelCase.js";
4
+ export { default as toConstantCase } from "./toConstantCase.js";
5
+ export { default as toKebabCase } from "./toKebabCase.js";
6
+ export { default as toPascalCase } from "./toPascalCase.js";
7
+ export { default as toSnakeCase } from "./toSnakeCase.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/casing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Check if a string is in PascalCase.
3
+ *
4
+ * @example
5
+ * isPascalCase("MyComponent") // true
6
+ * isPascalCase("myComponent") // false
7
+ */
8
+ export default function isPascalCase(s) {
9
+ return /^[A-Z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$/.test(s);
10
+ }
11
+ //# sourceMappingURL=isPascalCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isPascalCase.js","sourceRoot":"","sources":["../../../src/casing/isPascalCase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,CAAS;IAC5C,OAAO,qCAAqC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import isPascalCase from "./isPascalCase.js";
3
+ describe("isPascalCase", () => {
4
+ it("returns true for PascalCase strings", () => {
5
+ expect(isPascalCase("MyComponent")).toBe(true);
6
+ expect(isPascalCase("Hello")).toBe(true);
7
+ expect(isPascalCase("A")).toBe(true);
8
+ });
9
+ it("returns false for camelCase", () => {
10
+ expect(isPascalCase("myComponent")).toBe(false);
11
+ });
12
+ it("returns false for kebab-case", () => {
13
+ expect(isPascalCase("my-component")).toBe(false);
14
+ });
15
+ it("returns false for snake_case", () => {
16
+ expect(isPascalCase("my_component")).toBe(false);
17
+ });
18
+ it("returns false for empty string", () => {
19
+ expect(isPascalCase("")).toBe(false);
20
+ });
21
+ });
22
+ //# sourceMappingURL=isPascalCase.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isPascalCase.test.js","sourceRoot":"","sources":["../../../src/casing/isPascalCase.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAE7C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Convert a string to camelCase.
3
+ *
4
+ * @example
5
+ * toCamelCase("my-component") // "myComponent"
6
+ * toCamelCase("some_thing") // "someThing"
7
+ */
8
+ export default function toCamelCase(s) {
9
+ if (!s)
10
+ return "";
11
+ return s
12
+ .replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ""))
13
+ .replace(/^[A-Z]/, (c) => c.toLowerCase());
14
+ }
15
+ //# sourceMappingURL=toCamelCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toCamelCase.js","sourceRoot":"","sources":["../../../src/casing/toCamelCase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAS;IAC3C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC;SACL,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAC7D,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import toCamelCase from "./toCamelCase.js";
3
+ describe("toCamelCase", () => {
4
+ it("converts kebab-case", () => {
5
+ expect(toCamelCase("my-component")).toBe("myComponent");
6
+ });
7
+ it("converts snake_case", () => {
8
+ expect(toCamelCase("some_thing")).toBe("someThing");
9
+ });
10
+ it("converts space-separated", () => {
11
+ expect(toCamelCase("hello world")).toBe("helloWorld");
12
+ });
13
+ it("lowercases leading uppercase", () => {
14
+ expect(toCamelCase("MyComponent")).toBe("myComponent");
15
+ });
16
+ it("returns empty string for empty input", () => {
17
+ expect(toCamelCase("")).toBe("");
18
+ });
19
+ });
20
+ //# sourceMappingURL=toCamelCase.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toCamelCase.test.js","sourceRoot":"","sources":["../../../src/casing/toCamelCase.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAE3C,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import toSnakeCase from "./toSnakeCase.js";
2
+ /**
3
+ * Convert a string to CONSTANT_CASE.
4
+ *
5
+ * @example
6
+ * toConstantCase("myComponent") // "MY_COMPONENT"
7
+ * toConstantCase("some-thing") // "SOME_THING"
8
+ */
9
+ export default function toConstantCase(s) {
10
+ if (!s)
11
+ return "";
12
+ return toSnakeCase(s).toUpperCase();
13
+ }
14
+ //# sourceMappingURL=toConstantCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toConstantCase.js","sourceRoot":"","sources":["../../../src/casing/toConstantCase.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,CAAS;IAC9C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;AACtC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import toConstantCase from "./toConstantCase.js";
3
+ describe("toConstantCase", () => {
4
+ it("converts camelCase", () => {
5
+ expect(toConstantCase("myComponent")).toBe("MY_COMPONENT");
6
+ });
7
+ it("converts kebab-case", () => {
8
+ expect(toConstantCase("some-thing")).toBe("SOME_THING");
9
+ });
10
+ it("converts PascalCase", () => {
11
+ expect(toConstantCase("MyComponent")).toBe("MY_COMPONENT");
12
+ });
13
+ it("returns empty string for empty input", () => {
14
+ expect(toConstantCase("")).toBe("");
15
+ });
16
+ });
17
+ //# sourceMappingURL=toConstantCase.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toConstantCase.test.js","sourceRoot":"","sources":["../../../src/casing/toConstantCase.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,cAAc,MAAM,qBAAqB,CAAC;AAEjD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Convert a string to kebab-case.
3
+ *
4
+ * Handles camelCase, PascalCase, snake_case, spaces, and consecutive uppercase.
5
+ *
6
+ * @example
7
+ * toKebabCase("MyComponent") // "my-component"
8
+ * toKebabCase("some_thing") // "some-thing"
9
+ * toKebabCase("HTMLParser") // "html-parser"
10
+ */
11
+ export default function toKebabCase(s) {
12
+ if (!s)
13
+ return "";
14
+ return s
15
+ .trim()
16
+ .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
17
+ .replace(/([A-Z])([A-Z][a-z])/g, "$1-$2")
18
+ .replace(/[\s_]+/g, "-")
19
+ .toLowerCase();
20
+ }
21
+ //# sourceMappingURL=toKebabCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toKebabCase.js","sourceRoot":"","sources":["../../../src/casing/toKebabCase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAS;IAC3C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC;SACL,IAAI,EAAE;SACN,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,OAAO,CAAC,sBAAsB,EAAE,OAAO,CAAC;SACxC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,WAAW,EAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import toKebabCase from "./toKebabCase.js";
3
+ describe("toKebabCase", () => {
4
+ it("converts PascalCase", () => {
5
+ expect(toKebabCase("MyComponent")).toBe("my-component");
6
+ });
7
+ it("converts camelCase", () => {
8
+ expect(toKebabCase("myComponent")).toBe("my-component");
9
+ });
10
+ it("converts snake_case", () => {
11
+ expect(toKebabCase("some_thing")).toBe("some-thing");
12
+ });
13
+ it("converts spaces", () => {
14
+ expect(toKebabCase("hello world")).toBe("hello-world");
15
+ });
16
+ it("handles consecutive uppercase", () => {
17
+ expect(toKebabCase("HTMLParser")).toBe("html-parser");
18
+ });
19
+ it("returns empty string for empty input", () => {
20
+ expect(toKebabCase("")).toBe("");
21
+ });
22
+ it("trims whitespace", () => {
23
+ expect(toKebabCase(" MyComponent ")).toBe("my-component");
24
+ });
25
+ });
26
+ //# sourceMappingURL=toKebabCase.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toKebabCase.test.js","sourceRoot":"","sources":["../../../src/casing/toKebabCase.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAE3C,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE;QACzB,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC1B,MAAM,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Convert a string to PascalCase.
3
+ *
4
+ * @example
5
+ * toPascalCase("my-component") // "MyComponent"
6
+ * toPascalCase("some_thing") // "SomeThing"
7
+ */
8
+ export default function toPascalCase(s) {
9
+ if (!s)
10
+ return "";
11
+ const camel = s
12
+ .replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ""))
13
+ .replace(/^[A-Z]/, (c) => c.toLowerCase());
14
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
15
+ }
16
+ //# sourceMappingURL=toPascalCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toPascalCase.js","sourceRoot":"","sources":["../../../src/casing/toPascalCase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,CAAS;IAC5C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,MAAM,KAAK,GAAG,CAAC;SACZ,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAC7D,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAE7C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import toPascalCase from "./toPascalCase.js";
3
+ describe("toPascalCase", () => {
4
+ it("converts kebab-case", () => {
5
+ expect(toPascalCase("my-component")).toBe("MyComponent");
6
+ });
7
+ it("converts snake_case", () => {
8
+ expect(toPascalCase("some_thing")).toBe("SomeThing");
9
+ });
10
+ it("converts space-separated", () => {
11
+ expect(toPascalCase("hello world")).toBe("HelloWorld");
12
+ });
13
+ it("handles already PascalCase", () => {
14
+ expect(toPascalCase("MyComponent")).toBe("MyComponent");
15
+ });
16
+ it("returns empty string for empty input", () => {
17
+ expect(toPascalCase("")).toBe("");
18
+ });
19
+ });
20
+ //# sourceMappingURL=toPascalCase.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toPascalCase.test.js","sourceRoot":"","sources":["../../../src/casing/toPascalCase.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAE7C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Convert a string to snake_case.
3
+ *
4
+ * @example
5
+ * toSnakeCase("myComponent") // "my_component"
6
+ * toSnakeCase("MyComponent") // "my_component"
7
+ * toSnakeCase("some-thing") // "some_thing"
8
+ */
9
+ export default function toSnakeCase(s) {
10
+ if (!s)
11
+ return "";
12
+ return s
13
+ .replace(/([a-z])([A-Z])/g, "$1_$2")
14
+ .replace(/[\s-]+/g, "_")
15
+ .toLowerCase();
16
+ }
17
+ //# sourceMappingURL=toSnakeCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toSnakeCase.js","sourceRoot":"","sources":["../../../src/casing/toSnakeCase.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAS;IAC3C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC;SACL,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC;SACnC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,WAAW,EAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import toSnakeCase from "./toSnakeCase.js";
3
+ describe("toSnakeCase", () => {
4
+ it("converts camelCase", () => {
5
+ expect(toSnakeCase("myComponent")).toBe("my_component");
6
+ });
7
+ it("converts PascalCase", () => {
8
+ expect(toSnakeCase("MyComponent")).toBe("my_component");
9
+ });
10
+ it("converts kebab-case", () => {
11
+ expect(toSnakeCase("some-thing")).toBe("some_thing");
12
+ });
13
+ it("converts spaces", () => {
14
+ expect(toSnakeCase("hello world")).toBe("hello_world");
15
+ });
16
+ it("returns empty string for empty input", () => {
17
+ expect(toSnakeCase("")).toBe("");
18
+ });
19
+ });
20
+ //# sourceMappingURL=toSnakeCase.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toSnakeCase.test.js","sourceRoot":"","sources":["../../../src/casing/toSnakeCase.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAE3C,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE;QACzB,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import debounce from "./debounce.js";
3
+ describe("debounce", () => {
4
+ beforeEach(() => {
5
+ vi.useFakeTimers();
6
+ });
7
+ afterEach(() => {
8
+ vi.useRealTimers();
9
+ });
10
+ it("delays execution until after the wait period", async () => {
11
+ const fn = vi.fn(() => 42);
12
+ const debounced = debounce(fn, 100);
13
+ const promise = debounced();
14
+ expect(fn).not.toHaveBeenCalled();
15
+ vi.advanceTimersByTime(100);
16
+ await expect(promise).resolves.toBe(42);
17
+ expect(fn).toHaveBeenCalledOnce();
18
+ });
19
+ it("only calls the function once for rapid invocations", async () => {
20
+ const fn = vi.fn((x) => x * 2);
21
+ const debounced = debounce(fn, 100);
22
+ debounced(1);
23
+ debounced(2);
24
+ const promise = debounced(3);
25
+ vi.advanceTimersByTime(100);
26
+ await expect(promise).resolves.toBe(6);
27
+ expect(fn).toHaveBeenCalledOnce();
28
+ expect(fn).toHaveBeenCalledWith(3);
29
+ });
30
+ it("resets the timer on each call", async () => {
31
+ const fn = vi.fn(() => "done");
32
+ const debounced = debounce(fn, 100);
33
+ debounced();
34
+ vi.advanceTimersByTime(50);
35
+ expect(fn).not.toHaveBeenCalled();
36
+ const promise = debounced();
37
+ vi.advanceTimersByTime(50);
38
+ expect(fn).not.toHaveBeenCalled();
39
+ vi.advanceTimersByTime(50);
40
+ await expect(promise).resolves.toBe("done");
41
+ expect(fn).toHaveBeenCalledOnce();
42
+ });
43
+ it("cancel prevents the function from being called", () => {
44
+ const fn = vi.fn();
45
+ const debounced = debounce(fn, 100);
46
+ debounced();
47
+ debounced.cancel();
48
+ vi.advanceTimersByTime(200);
49
+ expect(fn).not.toHaveBeenCalled();
50
+ });
51
+ it("propagates errors from the debounced function", async () => {
52
+ const fn = vi.fn(() => {
53
+ throw new Error("boom");
54
+ });
55
+ const debounced = debounce(fn, 100);
56
+ const promise = debounced();
57
+ vi.advanceTimersByTime(100);
58
+ await expect(promise).rejects.toThrow("boom");
59
+ });
60
+ it("works with async functions", async () => {
61
+ const fn = vi.fn(async (x) => `hello ${x}`);
62
+ const debounced = debounce(fn, 50);
63
+ const promise = debounced("world");
64
+ vi.advanceTimersByTime(50);
65
+ await expect(promise).resolves.toBe("hello world");
66
+ });
67
+ });
68
+ //# sourceMappingURL=debounce.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.test.js","sourceRoot":"","sources":["../../src/debounce.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Indent every line of a string by a given number of spaces.
3
+ *
4
+ * @example
5
+ * indent("a\nb", 2) // " a\n b"
6
+ */
7
+ export default function indent(str, spaces) {
8
+ const pad = " ".repeat(spaces);
9
+ return str
10
+ .split("\n")
11
+ .map((line) => pad + line)
12
+ .join("\n");
13
+ }
14
+ //# sourceMappingURL=indent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indent.js","sourceRoot":"","sources":["../../src/indent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,GAAW,EAAE,MAAc;IACxD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,OAAO,GAAG;SACP,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC;SACzB,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import indent from "./indent.js";
3
+ describe("indent", () => {
4
+ it("indents a single line", () => {
5
+ expect(indent("hello", 2)).toBe(" hello");
6
+ });
7
+ it("indents every line of a multi-line string", () => {
8
+ expect(indent("a\nb\nc", 4)).toBe(" a\n b\n c");
9
+ });
10
+ it("handles zero spaces", () => {
11
+ expect(indent("hello", 0)).toBe("hello");
12
+ });
13
+ });
14
+ //# sourceMappingURL=indent.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indent.test.js","sourceRoot":"","sources":["../../src/indent.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;IACtB,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/dist/esm/index.js CHANGED
@@ -1,7 +1,9 @@
1
- export { default as casing } from "./casing.js";
1
+ export * from "./casing/index.js";
2
2
  export { default as debounce } from "./debounce.js";
3
3
  export { default as humanizeNumber } from "./humanizeNumber/index.js";
4
+ export { default as indent } from "./indent.js";
4
5
  export { default as invariant } from "./invariant.js";
6
+ export { default as join } from "./join.js";
5
7
  export * from "./navigation/index.js";
6
8
  export { default as pluralize } from "./pluralize/index.js";
7
9
  export { default as throttle } from "./throttle.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEtD,cAAc,uBAAuB,CAAC;AAGtC,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAE5C,cAAc,uBAAuB,CAAC;AAGtC,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Join an array into a string, converting each element to a string first.
3
+ *
4
+ * @example
5
+ * join(["a", "b", "c"]) // "a, b, c"
6
+ * join([1, 2, 3], " | ") // "1 | 2 | 3"
7
+ */
8
+ export default function join(arr, separator = ", ") {
9
+ return arr.map(String).join(separator);
10
+ }
11
+ //# sourceMappingURL=join.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join.js","sourceRoot":"","sources":["../../src/join.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,GAAc,EAAE,SAAS,GAAG,IAAI;IAC3D,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import join from "./join.js";
3
+ describe("join", () => {
4
+ it("joins with default separator", () => {
5
+ expect(join(["a", "b", "c"])).toBe("a, b, c");
6
+ });
7
+ it("joins with custom separator", () => {
8
+ expect(join([1, 2, 3], " | ")).toBe("1 | 2 | 3");
9
+ });
10
+ it("converts elements to strings", () => {
11
+ expect(join([1, true, null])).toBe("1, true, null");
12
+ });
13
+ it("returns empty string for empty array", () => {
14
+ expect(join([])).toBe("");
15
+ });
16
+ });
17
+ //# sourceMappingURL=join.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join.test.js","sourceRoot":"","sources":["../../src/join.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;IACpB,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import throttle from "./throttle.js";
3
+ describe("throttle", () => {
4
+ beforeEach(() => {
5
+ vi.useFakeTimers();
6
+ });
7
+ afterEach(() => {
8
+ vi.useRealTimers();
9
+ });
10
+ it("calls the function after the wait period", () => {
11
+ const fn = vi.fn();
12
+ const throttled = throttle(fn, 100);
13
+ throttled();
14
+ expect(fn).not.toHaveBeenCalled();
15
+ vi.advanceTimersByTime(100);
16
+ expect(fn).toHaveBeenCalledOnce();
17
+ });
18
+ it("only executes the last call when called rapidly", () => {
19
+ const fn = vi.fn();
20
+ const throttled = throttle(fn, 100);
21
+ throttled();
22
+ throttled();
23
+ throttled();
24
+ vi.advanceTimersByTime(100);
25
+ expect(fn).toHaveBeenCalledOnce();
26
+ });
27
+ it("passes the latest arguments", () => {
28
+ const fn = vi.fn((x) => x);
29
+ const throttled = throttle(fn, 100);
30
+ throttled(1);
31
+ throttled(2);
32
+ throttled(3);
33
+ vi.advanceTimersByTime(100);
34
+ expect(fn).toHaveBeenCalledWith(3);
35
+ });
36
+ it("resets the timer on each call", () => {
37
+ const fn = vi.fn();
38
+ const throttled = throttle(fn, 100);
39
+ throttled();
40
+ vi.advanceTimersByTime(50);
41
+ expect(fn).not.toHaveBeenCalled();
42
+ throttled();
43
+ vi.advanceTimersByTime(50);
44
+ expect(fn).not.toHaveBeenCalled();
45
+ vi.advanceTimersByTime(50);
46
+ expect(fn).toHaveBeenCalledOnce();
47
+ });
48
+ it("allows subsequent calls after the wait period expires", () => {
49
+ const fn = vi.fn();
50
+ const throttled = throttle(fn, 100);
51
+ throttled();
52
+ vi.advanceTimersByTime(100);
53
+ expect(fn).toHaveBeenCalledOnce();
54
+ throttled();
55
+ vi.advanceTimersByTime(100);
56
+ expect(fn).toHaveBeenCalledTimes(2);
57
+ });
58
+ });
59
+ //# sourceMappingURL=throttle.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"throttle.test.js","sourceRoot":"","sources":["../../src/throttle.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Capitalize the first character of a string.
3
+ *
4
+ * @example
5
+ * capitalize("hello") // "Hello"
6
+ */
7
+ export default function capitalize(s: string): string;
8
+ //# sourceMappingURL=capitalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capitalize.d.ts","sourceRoot":"","sources":["../../../src/casing/capitalize.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAIpD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=capitalize.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capitalize.test.d.ts","sourceRoot":"","sources":["../../../src/casing/capitalize.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export { default as capitalize } from "./capitalize.js";
2
+ export { default as isPascalCase } from "./isPascalCase.js";
3
+ export { default as toCamelCase } from "./toCamelCase.js";
4
+ export { default as toConstantCase } from "./toConstantCase.js";
5
+ export { default as toKebabCase } from "./toKebabCase.js";
6
+ export { default as toPascalCase } from "./toPascalCase.js";
7
+ export { default as toSnakeCase } from "./toSnakeCase.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/casing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Check if a string is in PascalCase.
3
+ *
4
+ * @example
5
+ * isPascalCase("MyComponent") // true
6
+ * isPascalCase("myComponent") // false
7
+ */
8
+ export default function isPascalCase(s: string): boolean;
9
+ //# sourceMappingURL=isPascalCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isPascalCase.d.ts","sourceRoot":"","sources":["../../../src/casing/isPascalCase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEvD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=isPascalCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isPascalCase.test.d.ts","sourceRoot":"","sources":["../../../src/casing/isPascalCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Convert a string to camelCase.
3
+ *
4
+ * @example
5
+ * toCamelCase("my-component") // "myComponent"
6
+ * toCamelCase("some_thing") // "someThing"
7
+ */
8
+ export default function toCamelCase(s: string): string;
9
+ //# sourceMappingURL=toCamelCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toCamelCase.d.ts","sourceRoot":"","sources":["../../../src/casing/toCamelCase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAMrD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=toCamelCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toCamelCase.test.d.ts","sourceRoot":"","sources":["../../../src/casing/toCamelCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Convert a string to CONSTANT_CASE.
3
+ *
4
+ * @example
5
+ * toConstantCase("myComponent") // "MY_COMPONENT"
6
+ * toConstantCase("some-thing") // "SOME_THING"
7
+ */
8
+ export default function toConstantCase(s: string): string;
9
+ //# sourceMappingURL=toConstantCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toConstantCase.d.ts","sourceRoot":"","sources":["../../../src/casing/toConstantCase.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAIxD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=toConstantCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toConstantCase.test.d.ts","sourceRoot":"","sources":["../../../src/casing/toConstantCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Convert a string to kebab-case.
3
+ *
4
+ * Handles camelCase, PascalCase, snake_case, spaces, and consecutive uppercase.
5
+ *
6
+ * @example
7
+ * toKebabCase("MyComponent") // "my-component"
8
+ * toKebabCase("some_thing") // "some-thing"
9
+ * toKebabCase("HTMLParser") // "html-parser"
10
+ */
11
+ export default function toKebabCase(s: string): string;
12
+ //# sourceMappingURL=toKebabCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toKebabCase.d.ts","sourceRoot":"","sources":["../../../src/casing/toKebabCase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CASrD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=toKebabCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toKebabCase.test.d.ts","sourceRoot":"","sources":["../../../src/casing/toKebabCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Convert a string to PascalCase.
3
+ *
4
+ * @example
5
+ * toPascalCase("my-component") // "MyComponent"
6
+ * toPascalCase("some_thing") // "SomeThing"
7
+ */
8
+ export default function toPascalCase(s: string): string;
9
+ //# sourceMappingURL=toPascalCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toPascalCase.d.ts","sourceRoot":"","sources":["../../../src/casing/toPascalCase.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAQtD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=toPascalCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toPascalCase.test.d.ts","sourceRoot":"","sources":["../../../src/casing/toPascalCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Convert a string to snake_case.
3
+ *
4
+ * @example
5
+ * toSnakeCase("myComponent") // "my_component"
6
+ * toSnakeCase("MyComponent") // "my_component"
7
+ * toSnakeCase("some-thing") // "some_thing"
8
+ */
9
+ export default function toSnakeCase(s: string): string;
10
+ //# sourceMappingURL=toSnakeCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toSnakeCase.d.ts","sourceRoot":"","sources":["../../../src/casing/toSnakeCase.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAOrD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=toSnakeCase.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toSnakeCase.test.d.ts","sourceRoot":"","sources":["../../../src/casing/toSnakeCase.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=debounce.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debounce.test.d.ts","sourceRoot":"","sources":["../../src/debounce.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Indent every line of a string by a given number of spaces.
3
+ *
4
+ * @example
5
+ * indent("a\nb", 2) // " a\n b"
6
+ */
7
+ export default function indent(str: string, spaces: number): string;
8
+ //# sourceMappingURL=indent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indent.d.ts","sourceRoot":"","sources":["../../src/indent.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMlE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=indent.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indent.test.d.ts","sourceRoot":"","sources":["../../src/indent.test.ts"],"names":[],"mappings":""}
@@ -1,8 +1,10 @@
1
- export { default as casing } from "./casing.js";
1
+ export * from "./casing/index.js";
2
2
  export { default as debounce } from "./debounce.js";
3
3
  export type * from "./humanizeNumber/index.js";
4
4
  export { default as humanizeNumber } from "./humanizeNumber/index.js";
5
+ export { default as indent } from "./indent.js";
5
6
  export { default as invariant } from "./invariant.js";
7
+ export { default as join } from "./join.js";
6
8
  export * from "./navigation/index.js";
7
9
  export type * from "./pluralize/index.js";
8
10
  export { default as pluralize } from "./pluralize/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,mBAAmB,2BAA2B,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEtD,cAAc,uBAAuB,CAAC;AAEtC,mBAAmB,sBAAsB,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,mBAAmB,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAElC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AACpD,mBAAmB,2BAA2B,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,WAAW,CAAC;AAE5C,cAAc,uBAAuB,CAAC;AAEtC,mBAAmB,sBAAsB,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,mBAAmB,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Join an array into a string, converting each element to a string first.
3
+ *
4
+ * @example
5
+ * join(["a", "b", "c"]) // "a, b, c"
6
+ * join([1, 2, 3], " | ") // "1 | 2 | 3"
7
+ */
8
+ export default function join(arr: unknown[], separator?: string): string;
9
+ //# sourceMappingURL=join.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join.d.ts","sourceRoot":"","sources":["../../src/join.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,SAAS,SAAO,GAAG,MAAM,CAErE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=join.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"join.test.d.ts","sourceRoot":"","sources":["../../src/join.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=throttle.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"throttle.test.d.ts","sourceRoot":"","sources":["../../src/throttle.test.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@canonical/utils",
3
3
  "description": "Standard utility functions for Canonical's Web Engineering team",
4
- "version": "0.20.0",
4
+ "version": "0.21.0",
5
5
  "type": "module",
6
6
  "module": "dist/esm/index.js",
7
7
  "types": "dist/types/index.d.ts",
@@ -42,13 +42,13 @@
42
42
  "test:vitest:watch": "vitest"
43
43
  },
44
44
  "dependencies": {
45
- "@canonical/ds-types": "^0.20.0"
45
+ "@canonical/ds-types": "^0.21.0"
46
46
  },
47
47
  "devDependencies": {
48
- "@biomejs/biome": "2.4.6",
49
- "@canonical/biome-config": "^0.20.0",
50
- "@canonical/typescript-config": "^0.20.0",
51
- "@canonical/webarchitect": "^0.20.0",
48
+ "@biomejs/biome": "2.4.9",
49
+ "@canonical/biome-config": "^0.21.0",
50
+ "@canonical/typescript-config": "^0.21.0",
51
+ "@canonical/webarchitect": "^0.21.0",
52
52
  "@types/node": "^24.12.0",
53
53
  "globals": "^17.4.0",
54
54
  "typescript": "^5.9.3",
@@ -56,5 +56,5 @@
56
56
  "vite-tsconfig-paths": "^6.1.1",
57
57
  "vitest": "^4.0.18"
58
58
  },
59
- "gitHead": "1aee634b278922f2aa1cfe2a11d3b14e64280905"
59
+ "gitHead": "4a39c954e7bbad4903397f8371f801982034a26d"
60
60
  }
@@ -1,66 +0,0 @@
1
- /**
2
- * Convert a string to PascalCase
3
- * @param s - The string to convert
4
- * @returns The PascalCase string
5
- * @example
6
- * toPascalCase("my-component") // "MyComponent"
7
- */
8
- const toPascalCase = (s) => {
9
- if (!s)
10
- return "";
11
- const camelCased = toCamelCase(s);
12
- return camelCased.charAt(0).toUpperCase() + camelCased.slice(1);
13
- };
14
- /**
15
- * Convert a string to kebab-case
16
- * @param s - The string to convert
17
- * @returns The kebab-case string
18
- * @example
19
- * toKebabCase("MyComponent") // "my-component"
20
- */
21
- const toKebabCase = (s) => {
22
- if (!s)
23
- return "";
24
- return s
25
- .trim()
26
- .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
27
- .toLowerCase();
28
- };
29
- /**
30
- * Convert a string to camelCase
31
- * @param s - The string to convert
32
- * @returns The camelCase string
33
- * @example
34
- * toCamelCase("my-component") // "myComponent"
35
- */
36
- const toCamelCase = (s) => {
37
- if (!s)
38
- return "";
39
- return s
40
- .replace(/-([a-z])/g, (g) => g[1].toUpperCase())
41
- .replaceAll("-", "")
42
- .replaceAll("_", "")
43
- .replaceAll(" ", "");
44
- };
45
- /**
46
- * Check if a string is in PascalCase.
47
- * @param s - The string to check
48
- * @returns True if the string is in PascalCase, false otherwise.
49
- * @example
50
- * isPascalCase("MyComponent") // true
51
- * isPascalCase("myComponent") // false
52
- */
53
- const isPascalCase = (s) => {
54
- // A simple regular expression that requires:
55
- // - the string to start with an uppercase letter
56
- // - followed by zero or more lowercase letters or digits,
57
- // - then zero or more groups that start with an uppercase letter followed by zero or more lowercase letters or digits.
58
- return /^[A-Z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$/.test(s);
59
- };
60
- export default {
61
- toPascalCase,
62
- toKebabCase,
63
- toCamelCase,
64
- isPascalCase,
65
- };
66
- //# sourceMappingURL=casing.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"casing.js","sourceRoot":"","sources":["../../src/casing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,YAAY,GAAG,CAAC,CAAS,EAAU,EAAE;IACzC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAElC,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,CAAC,CAAS,EAAU,EAAE;IACxC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC;SACL,IAAI,EAAE;SACN,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,WAAW,EAAE,CAAC;AACnB,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,WAAW,GAAG,CAAC,CAAS,EAAU,EAAE;IACxC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAElB,OAAO,CAAC;SACL,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SAC/C,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC;SACnB,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC;SACnB,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACzB,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,YAAY,GAAG,CAAC,CAAS,EAAW,EAAE;IAC1C,6CAA6C;IAC7C,iDAAiD;IACjD,0DAA0D;IAC1D,uHAAuH;IACvH,OAAO,qCAAqC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF,eAAe;IACb,YAAY;IACZ,WAAW;IACX,WAAW;IACX,YAAY;CACb,CAAC"}
@@ -1,8 +0,0 @@
1
- declare const _default: {
2
- toPascalCase: (s: string) => string;
3
- toKebabCase: (s: string) => string;
4
- toCamelCase: (s: string) => string;
5
- isPascalCase: (s: string) => boolean;
6
- };
7
- export default _default;
8
- //# sourceMappingURL=casing.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"casing.d.ts","sourceRoot":"","sources":["../../src/casing.ts"],"names":[],"mappings":";sBAOyB,MAAM,KAAG,MAAM;qBAehB,MAAM,KAAG,MAAM;qBAgBf,MAAM,KAAG,MAAM;sBAkBd,MAAM,KAAG,OAAO;;AAQzC,wBAKE"}