@fastwork/xosmoz-svelte 0.0.21

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,31 @@
1
+ /**
2
+ * Clipboard utilities for copying text
3
+ */
4
+ /**
5
+ * Copy text to clipboard
6
+ *
7
+ * @param text - The text to copy to clipboard
8
+ * @returns Promise that resolves to true if successful, false otherwise
9
+ *
10
+ * @example
11
+ * const success = await copyToClipboard('Hello World')
12
+ * if (success) {
13
+ * console.log('Copied!')
14
+ * }
15
+ */
16
+ export declare function copyToClipboard(text: string): Promise<boolean>;
17
+ /**
18
+ * Create a clipboard handler with state management for tracking copied items
19
+ *
20
+ * @param copiedValue - Svelte state for the currently copied value
21
+ * @param timeout - Optional timeout duration in milliseconds (default: 2000)
22
+ * @returns Function to copy text and update state
23
+ *
24
+ * @example
25
+ * let copiedVar = $state('')
26
+ * const handleCopy = createClipboardHandler(() => copiedVar, (val) => copiedVar = val)
27
+ *
28
+ * // In your component
29
+ * await handleCopy('some-text')
30
+ */
31
+ export declare function createClipboardHandler(getCopiedValue: () => string, setCopiedValue: (value: string) => void, timeout?: number): (text: string) => Promise<boolean>;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Clipboard utilities for copying text
3
+ */
4
+ /**
5
+ * Copy text to clipboard
6
+ *
7
+ * @param text - The text to copy to clipboard
8
+ * @returns Promise that resolves to true if successful, false otherwise
9
+ *
10
+ * @example
11
+ * const success = await copyToClipboard('Hello World')
12
+ * if (success) {
13
+ * console.log('Copied!')
14
+ * }
15
+ */
16
+ export async function copyToClipboard(text) {
17
+ try {
18
+ await navigator.clipboard.writeText(text);
19
+ return true;
20
+ }
21
+ catch (error) {
22
+ console.error('Failed to copy to clipboard:', error);
23
+ return false;
24
+ }
25
+ }
26
+ /**
27
+ * Create a clipboard handler with state management for tracking copied items
28
+ *
29
+ * @param copiedValue - Svelte state for the currently copied value
30
+ * @param timeout - Optional timeout duration in milliseconds (default: 2000)
31
+ * @returns Function to copy text and update state
32
+ *
33
+ * @example
34
+ * let copiedVar = $state('')
35
+ * const handleCopy = createClipboardHandler(() => copiedVar, (val) => copiedVar = val)
36
+ *
37
+ * // In your component
38
+ * await handleCopy('some-text')
39
+ */
40
+ export function createClipboardHandler(getCopiedValue, setCopiedValue, timeout = 2000) {
41
+ let copyTimeout = null;
42
+ return async (text) => {
43
+ const success = await copyToClipboard(text);
44
+ if (success) {
45
+ setCopiedValue(text);
46
+ // Clear existing timeout
47
+ if (copyTimeout) {
48
+ clearTimeout(copyTimeout);
49
+ }
50
+ // Reset after timeout
51
+ copyTimeout = setTimeout(() => {
52
+ setCopiedValue('');
53
+ }, timeout);
54
+ }
55
+ return success;
56
+ };
57
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Color calculation utilities
3
+ */
4
+ /**
5
+ * Calculate APCA contrast between two colors
6
+ * Using Color.js APCA implementation: https://colorjs.io/docs/contrast
7
+ *
8
+ * @param fgColor - The foreground color (text color)
9
+ * @param bgColor - The background color
10
+ * @returns The absolute APCA contrast value rounded to 1 decimal place, or 0 if calculation fails
11
+ *
12
+ * @example
13
+ * const contrast = calculateAPCA('#ffffff', '#000000')
14
+ * console.log(contrast) // High contrast value
15
+ */
16
+ export declare function calculateAPCA(fgColor: string, bgColor: string): number;
17
+ /**
18
+ * Convert a color string to hexadecimal format (sRGB)
19
+ *
20
+ * @param color - A color string in any format supported by Color.js (e.g., OKLCH, RGB, HSL)
21
+ * @returns Hexadecimal color string or '⚠️ Out of gamut' if the color cannot be represented in sRGB
22
+ *
23
+ * @example
24
+ * const hex = toHex('oklch(0.5 0.2 180)')
25
+ * console.log(hex) // '#00a5a5' or similar
26
+ *
27
+ * @example
28
+ * // For colors outside sRGB gamut
29
+ * const hex = toHex('oklch(0.8 0.4 180)')
30
+ * console.log(hex) // '⚠️ Out of gamut'
31
+ */
32
+ export declare function toHex(color: string): string;
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Color calculation utilities
3
+ */
4
+ import Color from 'colorjs.io';
5
+ /**
6
+ * Calculate APCA contrast between two colors
7
+ * Using Color.js APCA implementation: https://colorjs.io/docs/contrast
8
+ *
9
+ * @param fgColor - The foreground color (text color)
10
+ * @param bgColor - The background color
11
+ * @returns The absolute APCA contrast value rounded to 1 decimal place, or 0 if calculation fails
12
+ *
13
+ * @example
14
+ * const contrast = calculateAPCA('#ffffff', '#000000')
15
+ * console.log(contrast) // High contrast value
16
+ */
17
+ export function calculateAPCA(fgColor, bgColor) {
18
+ try {
19
+ // Create Color objects
20
+ const background = new Color(bgColor);
21
+ const text = new Color(fgColor);
22
+ // Calculate APCA contrast
23
+ // APCA requires: background.contrast(text, "APCA")
24
+ // Returns negative values for light text on dark bg, positive for dark text on light bg
25
+ const contrast = background.contrast(text, 'APCA');
26
+ // Return 0 if the result is NaN or invalid
27
+ if (isNaN(contrast) || !isFinite(contrast)) {
28
+ return 0;
29
+ }
30
+ // Return absolute value rounded to 1 decimal place
31
+ return Math.round(Math.abs(contrast) * 10) / 10;
32
+ }
33
+ catch (error) {
34
+ console.error('APCA calculation error:', error);
35
+ return 0;
36
+ }
37
+ }
38
+ /**
39
+ * Convert a color string to hexadecimal format (sRGB)
40
+ *
41
+ * @param color - A color string in any format supported by Color.js (e.g., OKLCH, RGB, HSL)
42
+ * @returns Hexadecimal color string or '⚠️ Out of gamut' if the color cannot be represented in sRGB
43
+ *
44
+ * @example
45
+ * const hex = toHex('oklch(0.5 0.2 180)')
46
+ * console.log(hex) // '#00a5a5' or similar
47
+ *
48
+ * @example
49
+ * // For colors outside sRGB gamut
50
+ * const hex = toHex('oklch(0.8 0.4 180)')
51
+ * console.log(hex) // '⚠️ Out of gamut'
52
+ */
53
+ export function toHex(color) {
54
+ try {
55
+ const colorObj = new Color(color);
56
+ // Try to convert to hex (sRGB)
57
+ const hexValue = colorObj.to('srgb').toString({ format: 'hex' });
58
+ // Check if conversion resulted in a valid hex
59
+ if (!hexValue || hexValue === 'undefined' || hexValue === 'null') {
60
+ return '⚠️ Out of gamut';
61
+ }
62
+ return hexValue;
63
+ }
64
+ catch {
65
+ // Color is likely out of sRGB gamut - these colors are more vibrant
66
+ // than what hex (sRGB) can represent
67
+ return '⚠️ Out of gamut';
68
+ }
69
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Theme detection utilities for Storybook and other environments
3
+ */
4
+ import type { ThemeConfig } from '@fastwork/xosmoz-theme';
5
+ /**
6
+ * Detects if the current theme is dark by checking CSS variables
7
+ * @returns true if dark theme is active, false otherwise
8
+ */
9
+ export declare function detectDarkTheme(): boolean;
10
+ /**
11
+ * Gets the active theme configuration based on current CSS variables
12
+ * @returns The active theme configuration (lightTheme or darkTheme)
13
+ */
14
+ export declare function getActiveTheme(): ThemeConfig;
15
+ /**
16
+ * Watches for theme changes and calls a callback when the theme changes
17
+ * @param callback Function to call when theme changes
18
+ * @returns Cleanup function to stop watching
19
+ */
20
+ export declare function watchThemeChanges(callback: () => void): () => void;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Theme detection utilities for Storybook and other environments
3
+ */
4
+ import { lightTheme, darkTheme } from '@fastwork/xosmoz-theme';
5
+ /**
6
+ * Detects if the current theme is dark by checking CSS variables
7
+ * @returns true if dark theme is active, false otherwise
8
+ */
9
+ export function detectDarkTheme() {
10
+ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
11
+ const bgColor = getComputedStyle(document.documentElement)
12
+ .getPropertyValue('--xz-color-bg-100')
13
+ .trim();
14
+ // Parse OKLCH lightness value to determine theme
15
+ const lightnessMatch = bgColor.match(/oklch\(([\d.]+)/);
16
+ if (lightnessMatch) {
17
+ const lightness = parseFloat(lightnessMatch[1]);
18
+ // If lightness is less than 0.5, it's dark theme
19
+ return lightness < 0.5;
20
+ }
21
+ }
22
+ return false;
23
+ }
24
+ /**
25
+ * Gets the active theme configuration based on current CSS variables
26
+ * @returns The active theme configuration (lightTheme or darkTheme)
27
+ */
28
+ export function getActiveTheme() {
29
+ return detectDarkTheme() ? darkTheme : lightTheme;
30
+ }
31
+ /**
32
+ * Watches for theme changes and calls a callback when the theme changes
33
+ * @param callback Function to call when theme changes
34
+ * @returns Cleanup function to stop watching
35
+ */
36
+ export function watchThemeChanges(callback) {
37
+ if (typeof window === 'undefined' || typeof document === 'undefined') {
38
+ return () => { };
39
+ }
40
+ const observer = new MutationObserver(() => {
41
+ callback();
42
+ });
43
+ observer.observe(document.documentElement, {
44
+ attributes: true,
45
+ attributeFilter: ['class', 'data-theme', 'style'],
46
+ });
47
+ return () => observer.disconnect();
48
+ }
package/package.json ADDED
@@ -0,0 +1,89 @@
1
+ {
2
+ "name": "@fastwork/xosmoz-svelte",
3
+ "version": "0.0.21",
4
+ "description": "Svelte 5 components for Xosmoz design system",
5
+ "type": "module",
6
+ "svelte": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "svelte": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./styles.css": "./dist/styles.css",
15
+ "./Button.svelte": {
16
+ "types": "./dist/components/Button.svelte.d.ts",
17
+ "svelte": "./dist/components/Button.svelte",
18
+ "default": "./dist/components/Button.svelte"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "!dist/**/*.stories.*",
24
+ "!dist/**/ButtonShowcase.*",
25
+ "!dist/**/ButtonAllVariants.*"
26
+ ],
27
+ "scripts": {
28
+ "dev": "vite dev",
29
+ "build": "vite build",
30
+ "build:package": "svelte-kit sync && svelte-package -o dist",
31
+ "package": "yarn build:package",
32
+ "preview": "vite preview",
33
+ "prepare": "svelte-kit sync || echo ''",
34
+ "prepublishOnly": "yarn build:package",
35
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
36
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
37
+ "format": "prettier --write .",
38
+ "lint": "prettier --check . && eslint .",
39
+ "storybook": "storybook dev -p 6006",
40
+ "build-storybook": "storybook build"
41
+ },
42
+ "peerDependencies": {
43
+ "@fastwork/xosmoz-css": "*",
44
+ "@fastwork/xosmoz-theme": "*",
45
+ "svelte": "^5.0.0"
46
+ },
47
+ "devDependencies": {
48
+ "@eslint/compat": "^1.4.0",
49
+ "@eslint/js": "^9.38.0",
50
+ "@fastwork/xosmoz-css": "workspace:*",
51
+ "@fastwork/xosmoz-theme": "workspace:*",
52
+ "@sveltejs/adapter-auto": "^7.0.0",
53
+ "@sveltejs/kit": "^2.47.1",
54
+ "@sveltejs/package": "^2.5.7",
55
+ "@sveltejs/vite-plugin-svelte": "^5.0.0",
56
+ "@types/node": "^22",
57
+ "colorjs.io": "^0.5.2",
58
+ "eslint": "^9.38.0",
59
+ "eslint-config-prettier": "^10.1.8",
60
+ "eslint-plugin-svelte": "^3.12.4",
61
+ "globals": "^16.4.0",
62
+ "prettier": "^3.6.2",
63
+ "prettier-plugin-svelte": "^3.4.0",
64
+ "svelte": "^5.41.0",
65
+ "svelte-check": "^4.3.3",
66
+ "typescript": "^5.9.3",
67
+ "typescript-eslint": "^8.46.1",
68
+ "vite": "^6.3.0"
69
+ },
70
+ "keywords": [
71
+ "svelte",
72
+ "svelte5",
73
+ "components",
74
+ "ui",
75
+ "design-system",
76
+ "xosmoz",
77
+ "fastwork"
78
+ ],
79
+ "author": "",
80
+ "license": "MIT",
81
+ "publishConfig": {
82
+ "access": "public"
83
+ },
84
+ "repository": {
85
+ "type": "git",
86
+ "url": "https://github.com/fastwork-co/fw-xosmoz.git",
87
+ "directory": "packages/xosmoz-svelte"
88
+ }
89
+ }