# disco/1.4.21/backend/views/components/Main/utilities/countdown-style.js

Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO, version 1.4.21. 189 lines.

- Page: https://pluginprobe.com/plugins/disco/1.4.21/code/backend/views/components/Main/utilities/countdown-style.js
- Raw: https://pluginprobe.com/plugins/disco/1.4.21/raw/backend/views/components/Main/utilities/countdown-style.js
- Modified: 2026-01-13T04:23:18+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/disco/1.4.21/code/backend/views/components/Main/utilities/countdown-style.js#L10-L20`.

```javascript
/**
 * Utility functions for countdown timer styling
 */

// Keys to skip when converting to style object
const SKIP_KEYS = ['text', 'isChain', 'radius', 'border', 'border-color'];

/**
 * Convert kebab-case CSS properties to camelCase React style object
 */
export const toStyleObject = (styleObj, skipKeys = SKIP_KEYS) => {
	if (!styleObj) return {};
	const result = {};
	Object.entries(styleObj).forEach(([key, value]) => {
		if (skipKeys.includes(key)) return;
		const camelKey = key.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
		result[camelKey] = value;
	});
	return result;
};

/**
 * Build border radius string from radius object
 */
const getBorderRadius = (radius) => {
	if (!radius) return undefined;
	return `${radius['top-left']} ${radius['top-right']} ${radius['bottom-right']} ${radius['bottom-left']}`;
};

/**
 * Apply border styles to style object
 */
const applyBorderStyles = (style, borderWidth, borderColor) => {
	style.borderWidth = `${borderWidth}px`;
	style.borderStyle = 'solid';
	style.borderColor = borderColor;
};

/**
 * Get container style with border and radius
 */
export const getContainerStyle = (container) => {
	if (!container) return {};
	const style = toStyleObject(container);

	if (container.radius) {
		style.borderRadius = getBorderRadius(container.radius);
	}

	applyBorderStyles(
		style,
		container.border ?? 0,
		container['border-color'] ?? 'rgba(0, 0, 0, 0)'
	);

	return style;
};

/**
 * Get box style with border and radius
 */
export const getBoxStyle = (box) => {
	if (!box) return {};
	const style = toStyleObject(box);

	if (box.radius) {
		style.borderRadius = getBorderRadius(box.radius);
	}

	applyBorderStyles(
		style,
		box.border ?? 0,
		box['border-color'] ?? 'rgba(0, 0, 0, 0)'
	);

	return style;
};

/**
 * Replace discount variables with sample values for preview
 */
export const replaceVariables = (text) => {
	if (!text) return '';
	return text
		.replace(/\[discounted_percentage\]/g, '20%')
		.replace(/\[discount_amount\]/g, '$50')
		.replace(/\[remaining_quantity\]/g, '2')
		.replace(/\[remaining_amount\]/g, '$25');
};

/**
 * Calculate time left from target date
 */
export const calculateTimeLeft = (targetDate) => {
	const difference = new Date(targetDate) - new Date();
	if (difference > 0) {
		return {
			days: String(Math.floor(difference / (1000 * 60 * 60 * 24))).padStart(2, '0'),
			hours: String(Math.floor((difference / (1000 * 60 * 60)) % 24)).padStart(2, '0'),
			minutes: String(Math.floor((difference / (1000 * 60)) % 60)).padStart(2, '0'),
			seconds: String(Math.floor((difference / 1000) % 60)).padStart(2, '0'),
		};
	}
	return { days: '02', hours: '08', minutes: '15', seconds: '05' };
};

/**
 * Get time units array from time left object
 */
export const getTimeUnits = (timeLeft) => [
	{ value: timeLeft.days, label: 'DAYS' },
	{ value: timeLeft.hours, label: 'HOURS' },
	{ value: timeLeft.minutes, label: 'MINUTES' },
	{ value: timeLeft.seconds, label: 'SECONDS' },
];

/**
 * Build default countdown state from design
 */
export const buildDefaultCountdownState = (design) => ({
	selected_design: design.id,
	title: {
		text: design.title.text,
		'font-family': design.title['font-family'] || '',
		'font-size': design.title['font-size'],
		'font-weight': design.title['font-weight'],
		'font-style': design.title['font-style'] || 'normal',
		'text-decoration': 'none',
		color: design.title.color,
	},
	subtitle: {
		text: design.subtitle.text,
		'font-family': design.subtitle['font-family'] || '',
		'font-size': design.subtitle['font-size'],
		'font-weight': design.subtitle['font-weight'],
		'font-style': design.subtitle['font-style'] || 'normal',
		'text-decoration': 'none',
		color: design.subtitle.color,
	},
	container: {
		background: design.container.background,
		'border-radius': design.container['border-radius'],
		padding: design.container.padding,
		border: design.container.border || 0,
		'border-color': design.container['border-color'] || 'rgba(0, 0, 0, 0)',
		isChain: false,
		radius: {
			'top-left': '6px',
			'top-right': '6px',
			'bottom-right': '6px',
			'bottom-left': '6px',
		},
	},
	box: {
		background: design.box.background,
		'border-radius': design.box['border-radius'],
		padding: design.box.padding,
		'min-width': design.box['min-width'] || '50px',
		border: 0,
		'border-color': 'rgba(0, 0, 0, 0)',
		isChain: false,
		radius: {
			'top-left': '2px',
			'top-right': '2px',
			'bottom-right': '2px',
			'bottom-left': '2px',
		},
	},
	number: {
		'font-family': design.number['font-family'] || '',
		'font-size': design.number['font-size'],
		'font-weight': design.number['font-weight'],
		color: design.number.color,
	},
	label: {
		'font-family': design.label['font-family'] || '',
		'font-size': design.label['font-size'],
		'font-weight': design.label['font-weight'],
		color: design.label.color,
	},
	separator: {
		color: design.separator.color,
		'font-size': design.separator['font-size'],
		'font-weight': design.separator['font-weight'],
	},
	hasSeparator: design.hasSeparator,
	singleContainer: design.singleContainer,
});

```
