@real1ty-obsidian-plugins/utils 2.9.0 → 2.11.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.
@@ -0,0 +1,17 @@
1
+ export declare function parseColor(color: string): {
2
+ h: number;
3
+ s: number;
4
+ l: number;
5
+ } | null;
6
+ /**
7
+ * Generates an array of evenly distributed HSL colors for visualization.
8
+ * Uses the HSL color space to create visually distinct colors by distributing
9
+ * them evenly around the color wheel.
10
+ *
11
+ * @param count - Number of colors to generate
12
+ * @param saturation - Saturation percentage (0-100), defaults to 70
13
+ * @param lightness - Lightness percentage (0-100), defaults to 60
14
+ * @returns Array of HSL color strings
15
+ */
16
+ export declare function generateColors(count: number, saturation?: number, lightness?: number): string[];
17
+ //# sourceMappingURL=color-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-utils.d.ts","sourceRoot":"","sources":["../../src/core/color-utils.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAMpF;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,SAAK,EAAE,SAAS,SAAK,GAAG,MAAM,EAAE,CAQvF"}
@@ -0,0 +1,29 @@
1
+ import { colord } from "colord";
2
+ export function parseColor(color) {
3
+ const parsed = colord(color);
4
+ if (!parsed.isValid()) {
5
+ return null;
6
+ }
7
+ return parsed.toHsl();
8
+ }
9
+ /**
10
+ * Generates an array of evenly distributed HSL colors for visualization.
11
+ * Uses the HSL color space to create visually distinct colors by distributing
12
+ * them evenly around the color wheel.
13
+ *
14
+ * @param count - Number of colors to generate
15
+ * @param saturation - Saturation percentage (0-100), defaults to 70
16
+ * @param lightness - Lightness percentage (0-100), defaults to 60
17
+ * @returns Array of HSL color strings
18
+ */
19
+ export function generateColors(count, saturation = 70, lightness = 60) {
20
+ if (count <= 0)
21
+ return [];
22
+ const colors = [];
23
+ for (let i = 0; i < count; i++) {
24
+ const hue = (i * 360) / count;
25
+ colors.push(`hsl(${hue}, ${saturation}%, ${lightness}%)`);
26
+ }
27
+ return colors;
28
+ }
29
+ //# sourceMappingURL=color-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-utils.js","sourceRoot":"","sources":["../../src/core/color-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,UAAU,UAAU,CAAC,KAAa;IACvC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,EAAE,CAAC;AACvB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,UAAU,GAAG,EAAE,EAAE,SAAS,GAAG,EAAE;IAC5E,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,GAAG,KAAK,UAAU,MAAM,SAAS,IAAI,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC","sourcesContent":["import { colord } from \"colord\";\n\nexport function parseColor(color: string): { h: number; s: number; l: number } | null {\n\tconst parsed = colord(color);\n\tif (!parsed.isValid()) {\n\t\treturn null;\n\t}\n\treturn parsed.toHsl();\n}\n\n/**\n * Generates an array of evenly distributed HSL colors for visualization.\n * Uses the HSL color space to create visually distinct colors by distributing\n * them evenly around the color wheel.\n *\n * @param count - Number of colors to generate\n * @param saturation - Saturation percentage (0-100), defaults to 70\n * @param lightness - Lightness percentage (0-100), defaults to 60\n * @returns Array of HSL color strings\n */\nexport function generateColors(count: number, saturation = 70, lightness = 60): string[] {\n\tif (count <= 0) return [];\n\tconst colors: string[] = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tconst hue = (i * 360) / count;\n\t\tcolors.push(`hsl(${hue}, ${saturation}%, ${lightness}%)`);\n\t}\n\treturn colors;\n}\n"]}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Prefixes class names with the standard plugin prefix.
3
+ * Handles multiple class names and automatically adds the prefix.
4
+ *
5
+ * @example
6
+ * cls("calendar-view") => "prisma-calendar-view"
7
+ * cls("button", "active") => "prisma-button prisma-active"
8
+ * cls("modal calendar") => "prisma-modal prisma-calendar"
9
+ */
10
+ export declare function cls(...classNames: string[]): string;
11
+ /**
12
+ * Adds prefixed class names to an element.
13
+ *
14
+ * @example
15
+ * addCls(element, "active", "selected")
16
+ */
17
+ export declare function addCls(element: HTMLElement, ...classNames: string[]): void;
18
+ /**
19
+ * Removes prefixed class names from an element.
20
+ *
21
+ * @example
22
+ * removeCls(element, "active", "selected")
23
+ */
24
+ export declare function removeCls(element: HTMLElement, ...classNames: string[]): void;
25
+ /**
26
+ * Toggles prefixed class names on an element.
27
+ *
28
+ * @example
29
+ * toggleCls(element, "active")
30
+ */
31
+ export declare function toggleCls(element: HTMLElement, className: string, force?: boolean): boolean;
32
+ /**
33
+ * Checks if element has a prefixed class.
34
+ *
35
+ * @example
36
+ * hasCls(element, "active")
37
+ */
38
+ export declare function hasCls(element: HTMLElement, className: string): boolean;
39
+ //# sourceMappingURL=css-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css-utils.d.ts","sourceRoot":"","sources":["../../src/core/css-utils.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,GAAG,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAMnD;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,CAK1E;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,CAK7E;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAE3F;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAEvE"}
@@ -0,0 +1,60 @@
1
+ const CSS_PREFIX = "prisma-";
2
+ /**
3
+ * Prefixes class names with the standard plugin prefix.
4
+ * Handles multiple class names and automatically adds the prefix.
5
+ *
6
+ * @example
7
+ * cls("calendar-view") => "prisma-calendar-view"
8
+ * cls("button", "active") => "prisma-button prisma-active"
9
+ * cls("modal calendar") => "prisma-modal prisma-calendar"
10
+ */
11
+ export function cls(...classNames) {
12
+ return classNames
13
+ .flatMap((name) => name.split(/\s+/))
14
+ .filter((name) => name.length > 0)
15
+ .map((name) => `${CSS_PREFIX}${name}`)
16
+ .join(" ");
17
+ }
18
+ /**
19
+ * Adds prefixed class names to an element.
20
+ *
21
+ * @example
22
+ * addCls(element, "active", "selected")
23
+ */
24
+ export function addCls(element, ...classNames) {
25
+ const classes = cls(...classNames);
26
+ if (classes) {
27
+ element.classList.add(...classes.split(/\s+/));
28
+ }
29
+ }
30
+ /**
31
+ * Removes prefixed class names from an element.
32
+ *
33
+ * @example
34
+ * removeCls(element, "active", "selected")
35
+ */
36
+ export function removeCls(element, ...classNames) {
37
+ const classes = cls(...classNames);
38
+ if (classes) {
39
+ element.classList.remove(...classes.split(/\s+/));
40
+ }
41
+ }
42
+ /**
43
+ * Toggles prefixed class names on an element.
44
+ *
45
+ * @example
46
+ * toggleCls(element, "active")
47
+ */
48
+ export function toggleCls(element, className, force) {
49
+ return element.classList.toggle(cls(className), force);
50
+ }
51
+ /**
52
+ * Checks if element has a prefixed class.
53
+ *
54
+ * @example
55
+ * hasCls(element, "active")
56
+ */
57
+ export function hasCls(element, className) {
58
+ return element.classList.contains(cls(className));
59
+ }
60
+ //# sourceMappingURL=css-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css-utils.js","sourceRoot":"","sources":["../../src/core/css-utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,SAAS,CAAC;AAE7B;;;;;;;;GAQG;AACH,MAAM,UAAU,GAAG,CAAC,GAAG,UAAoB;IAC1C,OAAO,UAAU;SACf,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;SACpC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;SACjC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,UAAU,GAAG,IAAI,EAAE,CAAC;SACrC,IAAI,CAAC,GAAG,CAAC,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,OAAoB,EAAE,GAAG,UAAoB;IACnE,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC;IACnC,IAAI,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,OAAoB,EAAE,GAAG,UAAoB;IACtE,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC;IACnC,IAAI,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,OAAoB,EAAE,SAAiB,EAAE,KAAe;IACjF,OAAO,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,OAAoB,EAAE,SAAiB;IAC7D,OAAO,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;AACnD,CAAC","sourcesContent":["const CSS_PREFIX = \"prisma-\";\n\n/**\n * Prefixes class names with the standard plugin prefix.\n * Handles multiple class names and automatically adds the prefix.\n *\n * @example\n * cls(\"calendar-view\") => \"prisma-calendar-view\"\n * cls(\"button\", \"active\") => \"prisma-button prisma-active\"\n * cls(\"modal calendar\") => \"prisma-modal prisma-calendar\"\n */\nexport function cls(...classNames: string[]): string {\n\treturn classNames\n\t\t.flatMap((name) => name.split(/\\s+/))\n\t\t.filter((name) => name.length > 0)\n\t\t.map((name) => `${CSS_PREFIX}${name}`)\n\t\t.join(\" \");\n}\n\n/**\n * Adds prefixed class names to an element.\n *\n * @example\n * addCls(element, \"active\", \"selected\")\n */\nexport function addCls(element: HTMLElement, ...classNames: string[]): void {\n\tconst classes = cls(...classNames);\n\tif (classes) {\n\t\telement.classList.add(...classes.split(/\\s+/));\n\t}\n}\n\n/**\n * Removes prefixed class names from an element.\n *\n * @example\n * removeCls(element, \"active\", \"selected\")\n */\nexport function removeCls(element: HTMLElement, ...classNames: string[]): void {\n\tconst classes = cls(...classNames);\n\tif (classes) {\n\t\telement.classList.remove(...classes.split(/\\s+/));\n\t}\n}\n\n/**\n * Toggles prefixed class names on an element.\n *\n * @example\n * toggleCls(element, \"active\")\n */\nexport function toggleCls(element: HTMLElement, className: string, force?: boolean): boolean {\n\treturn element.classList.toggle(cls(className), force);\n}\n\n/**\n * Checks if element has a prefixed class.\n *\n * @example\n * hasCls(element, \"active\")\n */\nexport function hasCls(element: HTMLElement, className: string): boolean {\n\treturn element.classList.contains(cls(className));\n}\n"]}
@@ -1,5 +1,8 @@
1
+ export * from "./color-utils";
2
+ export * from "./css-utils";
1
3
  export * from "./evaluator";
2
4
  export * from "./expression-utils";
3
5
  export * from "./frontmatter-value";
4
6
  export * from "./generate";
7
+ export * from "./validation";
5
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
@@ -1,5 +1,8 @@
1
+ export * from "./color-utils";
2
+ export * from "./css-utils";
1
3
  export * from "./evaluator";
2
4
  export * from "./expression-utils";
3
5
  export * from "./frontmatter-value";
4
6
  export * from "./generate";
7
+ export * from "./validation";
5
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC","sourcesContent":["export * from \"./evaluator\";\nexport * from \"./expression-utils\";\nexport * from \"./frontmatter-value\";\nexport * from \"./generate\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC","sourcesContent":["export * from \"./color-utils\";\nexport * from \"./css-utils\";\nexport * from \"./evaluator\";\nexport * from \"./expression-utils\";\nexport * from \"./frontmatter-value\";\nexport * from \"./generate\";\nexport * from \"./validation\";\n"]}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Checks if a value is not empty.
3
+ * Returns false for: undefined, null, empty string, or empty arrays.
4
+ * Returns true for all other values.
5
+ */
6
+ export declare function isNotEmpty(value: unknown): boolean;
7
+ /**
8
+ * Parses a value to a positive integer.
9
+ * Handles both number and string types from frontmatter.
10
+ * Returns the parsed integer if valid and positive, otherwise returns the fallback value.
11
+ */
12
+ export declare function parsePositiveInt(value: unknown, fallback: number): number;
13
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQlD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMzE"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Checks if a value is not empty.
3
+ * Returns false for: undefined, null, empty string, or empty arrays.
4
+ * Returns true for all other values.
5
+ */
6
+ export function isNotEmpty(value) {
7
+ if (value === undefined || value === null || value === "") {
8
+ return false;
9
+ }
10
+ if (Array.isArray(value) && value.length === 0) {
11
+ return false;
12
+ }
13
+ return true;
14
+ }
15
+ /**
16
+ * Parses a value to a positive integer.
17
+ * Handles both number and string types from frontmatter.
18
+ * Returns the parsed integer if valid and positive, otherwise returns the fallback value.
19
+ */
20
+ export function parsePositiveInt(value, fallback) {
21
+ if (value === undefined || value === null) {
22
+ return fallback;
23
+ }
24
+ const parsed = typeof value === "number" ? Math.floor(value) : Number.parseInt(String(value), 10);
25
+ return !Number.isNaN(parsed) && parsed > 0 ? parsed : fallback;
26
+ }
27
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,KAAc;IACxC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QAC3D,OAAO,KAAK,CAAC;IACd,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc,EAAE,QAAgB;IAChE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC3C,OAAO,QAAQ,CAAC;IACjB,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IAClG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AAChE,CAAC","sourcesContent":["/**\n * Checks if a value is not empty.\n * Returns false for: undefined, null, empty string, or empty arrays.\n * Returns true for all other values.\n */\nexport function isNotEmpty(value: unknown): boolean {\n\tif (value === undefined || value === null || value === \"\") {\n\t\treturn false;\n\t}\n\tif (Array.isArray(value) && value.length === 0) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Parses a value to a positive integer.\n * Handles both number and string types from frontmatter.\n * Returns the parsed integer if valid and positive, otherwise returns the fallback value.\n */\nexport function parsePositiveInt(value: unknown, fallback: number): number {\n\tif (value === undefined || value === null) {\n\t\treturn fallback;\n\t}\n\tconst parsed = typeof value === \"number\" ? Math.floor(value) : Number.parseInt(String(value), 10);\n\treturn !Number.isNaN(parsed) && parsed > 0 ? parsed : fallback;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real1ty-obsidian-plugins/utils",
3
- "version": "2.9.0",
3
+ "version": "2.11.0",
4
4
  "description": "Shared utilities for Obsidian plugins",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -49,6 +49,7 @@
49
49
  "vitest": "^2.0.5"
50
50
  },
51
51
  "dependencies": {
52
+ "colord": "^2.9.3",
52
53
  "gray-matter": "^4.0.3",
53
54
  "luxon": "^3.7.2",
54
55
  "obsidian": "^1.8.7",
@@ -0,0 +1,29 @@
1
+ import { colord } from "colord";
2
+
3
+ export function parseColor(color: string): { h: number; s: number; l: number } | null {
4
+ const parsed = colord(color);
5
+ if (!parsed.isValid()) {
6
+ return null;
7
+ }
8
+ return parsed.toHsl();
9
+ }
10
+
11
+ /**
12
+ * Generates an array of evenly distributed HSL colors for visualization.
13
+ * Uses the HSL color space to create visually distinct colors by distributing
14
+ * them evenly around the color wheel.
15
+ *
16
+ * @param count - Number of colors to generate
17
+ * @param saturation - Saturation percentage (0-100), defaults to 70
18
+ * @param lightness - Lightness percentage (0-100), defaults to 60
19
+ * @returns Array of HSL color strings
20
+ */
21
+ export function generateColors(count: number, saturation = 70, lightness = 60): string[] {
22
+ if (count <= 0) return [];
23
+ const colors: string[] = [];
24
+ for (let i = 0; i < count; i++) {
25
+ const hue = (i * 360) / count;
26
+ colors.push(`hsl(${hue}, ${saturation}%, ${lightness}%)`);
27
+ }
28
+ return colors;
29
+ }
@@ -0,0 +1,64 @@
1
+ const CSS_PREFIX = "prisma-";
2
+
3
+ /**
4
+ * Prefixes class names with the standard plugin prefix.
5
+ * Handles multiple class names and automatically adds the prefix.
6
+ *
7
+ * @example
8
+ * cls("calendar-view") => "prisma-calendar-view"
9
+ * cls("button", "active") => "prisma-button prisma-active"
10
+ * cls("modal calendar") => "prisma-modal prisma-calendar"
11
+ */
12
+ export function cls(...classNames: string[]): string {
13
+ return classNames
14
+ .flatMap((name) => name.split(/\s+/))
15
+ .filter((name) => name.length > 0)
16
+ .map((name) => `${CSS_PREFIX}${name}`)
17
+ .join(" ");
18
+ }
19
+
20
+ /**
21
+ * Adds prefixed class names to an element.
22
+ *
23
+ * @example
24
+ * addCls(element, "active", "selected")
25
+ */
26
+ export function addCls(element: HTMLElement, ...classNames: string[]): void {
27
+ const classes = cls(...classNames);
28
+ if (classes) {
29
+ element.classList.add(...classes.split(/\s+/));
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Removes prefixed class names from an element.
35
+ *
36
+ * @example
37
+ * removeCls(element, "active", "selected")
38
+ */
39
+ export function removeCls(element: HTMLElement, ...classNames: string[]): void {
40
+ const classes = cls(...classNames);
41
+ if (classes) {
42
+ element.classList.remove(...classes.split(/\s+/));
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Toggles prefixed class names on an element.
48
+ *
49
+ * @example
50
+ * toggleCls(element, "active")
51
+ */
52
+ export function toggleCls(element: HTMLElement, className: string, force?: boolean): boolean {
53
+ return element.classList.toggle(cls(className), force);
54
+ }
55
+
56
+ /**
57
+ * Checks if element has a prefixed class.
58
+ *
59
+ * @example
60
+ * hasCls(element, "active")
61
+ */
62
+ export function hasCls(element: HTMLElement, className: string): boolean {
63
+ return element.classList.contains(cls(className));
64
+ }
package/src/core/index.ts CHANGED
@@ -1,4 +1,7 @@
1
+ export * from "./color-utils";
2
+ export * from "./css-utils";
1
3
  export * from "./evaluator";
2
4
  export * from "./expression-utils";
3
5
  export * from "./frontmatter-value";
4
6
  export * from "./generate";
7
+ export * from "./validation";
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Checks if a value is not empty.
3
+ * Returns false for: undefined, null, empty string, or empty arrays.
4
+ * Returns true for all other values.
5
+ */
6
+ export function isNotEmpty(value: unknown): boolean {
7
+ if (value === undefined || value === null || value === "") {
8
+ return false;
9
+ }
10
+ if (Array.isArray(value) && value.length === 0) {
11
+ return false;
12
+ }
13
+ return true;
14
+ }
15
+
16
+ /**
17
+ * Parses a value to a positive integer.
18
+ * Handles both number and string types from frontmatter.
19
+ * Returns the parsed integer if valid and positive, otherwise returns the fallback value.
20
+ */
21
+ export function parsePositiveInt(value: unknown, fallback: number): number {
22
+ if (value === undefined || value === null) {
23
+ return fallback;
24
+ }
25
+ const parsed = typeof value === "number" ? Math.floor(value) : Number.parseInt(String(value), 10);
26
+ return !Number.isNaN(parsed) && parsed > 0 ? parsed : fallback;
27
+ }