@umituz/web-design-system 5.2.0 → 5.3.1
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.
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/__tests__/cn.test.ts +0 -3
- package/src/__tests__/component-slots.test.tsx +0 -4
- package/src/__tests__/components.smoke.test.tsx +3 -11
- package/src/__tests__/format.test.ts +18 -0
- package/src/__tests__/id.test.ts +17 -0
- package/src/__tests__/money.test.tsx +0 -3
- package/src/__tests__/styles.contract.test.ts +0 -13
- package/src/domain/tokens/index.ts +0 -7
- package/src/domain/tokens/responsive-map.tokens.ts +18 -107
- package/src/domain/types/breakpoint.types.ts +9 -13
- package/src/domain/types/component.types.ts +0 -4
- package/src/domain/types/index.ts +0 -5
- package/src/global.d.ts +0 -4
- package/src/index.ts +0 -21
- package/src/infrastructure/constants/breakpoint.constants.ts +0 -31
- package/src/infrastructure/constants/component.constants.ts +0 -4
- package/src/infrastructure/constants/index.ts +0 -5
- package/src/infrastructure/constants/size-variant.constants.ts +0 -33
- package/src/infrastructure/constants/spacing.constants.ts +34 -63
- package/src/infrastructure/constants/timing.constants.ts +0 -18
- package/src/infrastructure/constants/typography.constants.ts +22 -54
- package/src/infrastructure/utils/calculation.utils.ts +0 -9
- package/src/infrastructure/utils/cn.util.ts +0 -18
- package/src/infrastructure/utils/format.util.ts +1 -0
- package/src/infrastructure/utils/hash.util.ts +0 -5
- package/src/infrastructure/utils/id.util.ts +2 -0
- package/src/infrastructure/utils/index.ts +4 -5
- package/src/infrastructure/utils/money.utils.ts +0 -7
- package/src/infrastructure/utils/responsive.utils.ts +0 -66
- package/src/presentation/atoms/AspectRatio.tsx +0 -10
- package/src/presentation/atoms/Badge.tsx +0 -5
- package/src/presentation/atoms/BatteryPill.tsx +0 -5
- package/src/presentation/atoms/Button.tsx +0 -2
- package/src/presentation/atoms/Checkbox.tsx +0 -4
- package/src/presentation/atoms/Divider.tsx +0 -4
- package/src/presentation/atoms/HeatmapStrip.tsx +0 -10
- package/src/presentation/atoms/Hide.tsx +0 -24
- package/src/presentation/atoms/Icon.tsx +0 -4
- package/src/presentation/atoms/IconButton.tsx +0 -4
- package/src/presentation/atoms/Input.tsx +0 -4
- package/src/presentation/atoms/Kbd.tsx +0 -4
- package/src/presentation/atoms/Label.tsx +0 -4
- package/src/presentation/atoms/Link.tsx +0 -4
- package/src/presentation/atoms/Money.tsx +0 -6
- package/src/presentation/atoms/Progress.tsx +0 -6
- package/src/presentation/atoms/Radio.tsx +0 -4
- package/src/presentation/atoms/Separator.tsx +0 -4
- package/src/presentation/atoms/Show.tsx +0 -24
- package/src/presentation/atoms/Skeleton.tsx +0 -4
- package/src/presentation/atoms/Slider.tsx +0 -4
- package/src/presentation/atoms/Sparkline.tsx +0 -4
- package/src/presentation/atoms/Spinner.tsx +0 -4
- package/src/presentation/atoms/Switch.tsx +0 -4
- package/src/presentation/atoms/Text.tsx +0 -4
- package/src/presentation/atoms/Textarea.tsx +0 -4
- package/src/presentation/atoms/Toggle.tsx +0 -4
- package/src/presentation/atoms/Tooltip.tsx +0 -4
- package/src/presentation/atoms/index.ts +0 -5
- package/src/presentation/hooks/index.ts +0 -5
- package/src/presentation/hooks/useClickOutside.ts +0 -6
- package/src/presentation/hooks/useClipboard.ts +0 -4
- package/src/presentation/hooks/useDebounce.ts +0 -8
- package/src/presentation/hooks/useKeyboard.ts +0 -6
- package/src/presentation/hooks/useLocalStorage.ts +0 -4
- package/src/presentation/hooks/useMediaQuery.ts +0 -37
- package/src/presentation/hooks/useScrollLock.ts +0 -5
- package/src/presentation/hooks/useTheme.ts +9 -13
- package/src/presentation/hooks/useToggle.ts +0 -4
- package/src/presentation/molecules/ActiveFilterTags.tsx +0 -4
- package/src/presentation/molecules/Avatar.tsx +0 -5
- package/src/presentation/molecules/BookmarkButton.tsx +0 -15
- package/src/presentation/molecules/CheckboxGroup.tsx +0 -4
- package/src/presentation/molecules/Chip.tsx +0 -5
- package/src/presentation/molecules/CodeBlock.tsx +0 -5
- package/src/presentation/molecules/Field.tsx +0 -7
- package/src/presentation/molecules/FormField.tsx +1 -5
- package/src/presentation/molecules/InputGroup.tsx +0 -4
- package/src/presentation/molecules/ListItem.tsx +0 -4
- package/src/presentation/molecules/OptionTile.tsx +0 -10
- package/src/presentation/molecules/RadioGroup.tsx +0 -4
- package/src/presentation/molecules/RatingStars.tsx +0 -8
- package/src/presentation/molecules/ScrollArea.tsx +0 -4
- package/src/presentation/molecules/SearchBox.tsx +0 -4
- package/src/presentation/molecules/Select.tsx +0 -4
- package/src/presentation/molecules/StatPill.tsx +0 -5
- package/src/presentation/molecules/TagInput.tsx +0 -7
- package/src/presentation/molecules/Textarea.tsx +0 -4
- package/src/presentation/molecules/Toggle.tsx +0 -4
- package/src/presentation/molecules/index.ts +0 -6
- package/src/presentation/organisms/Accordion.tsx +0 -4
- package/src/presentation/organisms/Alert.tsx +0 -4
- package/src/presentation/organisms/AvatarStack.tsx +0 -5
- package/src/presentation/organisms/Breadcrumb.tsx +0 -7
- package/src/presentation/organisms/Card.tsx +0 -6
- package/src/presentation/organisms/Checklist.tsx +0 -4
- package/src/presentation/organisms/Collapsible.tsx +0 -4
- package/src/presentation/organisms/ConfirmDialog.tsx +0 -8
- package/src/presentation/organisms/CoverArt.tsx +0 -9
- package/src/presentation/organisms/DataTable.tsx +0 -8
- package/src/presentation/organisms/DateRangePicker.tsx +0 -9
- package/src/presentation/organisms/Dialog.tsx +0 -4
- package/src/presentation/organisms/Drawer.tsx +0 -6
- package/src/presentation/organisms/DropdownMenu.tsx +0 -4
- package/src/presentation/organisms/ErrorBoundary.tsx +0 -12
- package/src/presentation/organisms/FileUploader.tsx +0 -9
- package/src/presentation/organisms/FilterPopover.tsx +0 -8
- package/src/presentation/organisms/FormModal.tsx +0 -5
- package/src/presentation/organisms/HoverCard.tsx +0 -4
- package/src/presentation/organisms/KeyValueList.tsx +0 -4
- package/src/presentation/organisms/KpiCard.tsx +0 -6
- package/src/presentation/organisms/Lightbox.tsx +0 -7
- package/src/presentation/organisms/LoadingState.tsx +0 -4
- package/src/presentation/organisms/MapPreview.tsx +0 -9
- package/src/presentation/organisms/MetricCard.tsx +1 -5
- package/src/presentation/organisms/Modal.tsx +0 -4
- package/src/presentation/organisms/PhotoGallery.tsx +0 -9
- package/src/presentation/organisms/PlanPicker.tsx +0 -5
- package/src/presentation/organisms/Popover.tsx +0 -4
- package/src/presentation/organisms/Sheet.tsx +0 -4
- package/src/presentation/organisms/StatCard.tsx +0 -5
- package/src/presentation/organisms/StatusBadge.tsx +0 -12
- package/src/presentation/organisms/Stepper.tsx +0 -5
- package/src/presentation/organisms/Table.tsx +0 -4
- package/src/presentation/organisms/Tabs.tsx +0 -7
- package/src/presentation/organisms/Timeline.tsx +0 -8
- package/src/presentation/organisms/Toaster.tsx +0 -9
- package/src/presentation/organisms/ToggleGroup.tsx +0 -4
- package/src/presentation/organisms/index.ts +0 -5
- package/src/presentation/templates/Form.tsx +0 -4
- package/src/presentation/templates/List.tsx +0 -4
- package/src/presentation/templates/PageHeader.tsx +0 -4
- package/src/presentation/templates/PageLayout.tsx +0 -4
- package/src/presentation/templates/ProjectSkeleton.tsx +0 -4
- package/src/presentation/templates/ResponsiveContainer.tsx +0 -43
- package/src/presentation/templates/Section.tsx +0 -4
- package/src/presentation/templates/index.ts +0 -5
- package/src/styles/app.css +0 -18
- package/src/styles/bridge.css +0 -34
- package/src/styles/compile.css +0 -13
- package/src/styles/source.css +0 -12
- package/src/styles/theme.css +0 -27
|
@@ -1,68 +1,40 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Typography Constants
|
|
3
|
-
* @description Typography scale values for the design system
|
|
4
|
-
*
|
|
5
|
-
* All font size and text utility values are defined here.
|
|
6
|
-
* This provides consistency with Tailwind's default typography scale.
|
|
7
|
-
*/
|
|
8
1
|
|
|
9
|
-
/**
|
|
10
|
-
* Text size utilities (Tailwind text classes)
|
|
11
|
-
*/
|
|
12
2
|
export const TEXT_SIZES = {
|
|
13
|
-
xs: 'text-xs',
|
|
14
|
-
sm: 'text-sm',
|
|
15
|
-
base: 'text-base',
|
|
16
|
-
lg: 'text-lg',
|
|
17
|
-
xl: 'text-xl',
|
|
18
|
-
'2xl': 'text-2xl',
|
|
19
|
-
'3xl': 'text-3xl',
|
|
20
|
-
'4xl': 'text-4xl',
|
|
21
|
-
'5xl': 'text-5xl',
|
|
22
|
-
'6xl': 'text-6xl',
|
|
23
|
-
'7xl': 'text-7xl',
|
|
24
|
-
'8xl': 'text-8xl',
|
|
25
|
-
'9xl': 'text-9xl',
|
|
3
|
+
xs: 'text-xs',
|
|
4
|
+
sm: 'text-sm',
|
|
5
|
+
base: 'text-base',
|
|
6
|
+
lg: 'text-lg',
|
|
7
|
+
xl: 'text-xl',
|
|
8
|
+
'2xl': 'text-2xl',
|
|
9
|
+
'3xl': 'text-3xl',
|
|
10
|
+
'4xl': 'text-4xl',
|
|
11
|
+
'5xl': 'text-5xl',
|
|
12
|
+
'6xl': 'text-6xl',
|
|
13
|
+
'7xl': 'text-7xl',
|
|
14
|
+
'8xl': 'text-8xl',
|
|
15
|
+
'9xl': 'text-9xl',
|
|
26
16
|
} as const;
|
|
27
17
|
|
|
28
|
-
/**
|
|
29
|
-
* Type for text size keys
|
|
30
|
-
*/
|
|
31
18
|
export type TextSizeKey = keyof typeof TEXT_SIZES;
|
|
32
19
|
|
|
33
|
-
/**
|
|
34
|
-
* Type for text size values
|
|
35
|
-
*/
|
|
36
20
|
export type TextSize = typeof TEXT_SIZES[TextSizeKey];
|
|
37
21
|
|
|
38
|
-
/**
|
|
39
|
-
* Font weight utilities
|
|
40
|
-
*/
|
|
41
22
|
export const FONT_WEIGHTS = {
|
|
42
|
-
thin: 'font-thin',
|
|
43
|
-
extralight: 'font-extralight',
|
|
44
|
-
light: 'font-light',
|
|
45
|
-
normal: 'font-normal',
|
|
46
|
-
medium: 'font-medium',
|
|
47
|
-
semibold: 'font-semibold',
|
|
48
|
-
bold: 'font-bold',
|
|
49
|
-
extrabold: 'font-extrabold',
|
|
50
|
-
black: 'font-black',
|
|
23
|
+
thin: 'font-thin',
|
|
24
|
+
extralight: 'font-extralight',
|
|
25
|
+
light: 'font-light',
|
|
26
|
+
normal: 'font-normal',
|
|
27
|
+
medium: 'font-medium',
|
|
28
|
+
semibold: 'font-semibold',
|
|
29
|
+
bold: 'font-bold',
|
|
30
|
+
extrabold: 'font-extrabold',
|
|
31
|
+
black: 'font-black',
|
|
51
32
|
} as const;
|
|
52
33
|
|
|
53
|
-
/**
|
|
54
|
-
* Type for font weight keys
|
|
55
|
-
*/
|
|
56
34
|
export type FontWeightKey = keyof typeof FONT_WEIGHTS;
|
|
57
35
|
|
|
58
|
-
/**
|
|
59
|
-
* Type for font weight values
|
|
60
|
-
*/
|
|
61
36
|
export type FontWeight = typeof FONT_WEIGHTS[FontWeightKey];
|
|
62
37
|
|
|
63
|
-
/**
|
|
64
|
-
* Common text sizes for different element types
|
|
65
|
-
*/
|
|
66
38
|
export const COMMON_TEXT_SIZES = {
|
|
67
39
|
caption: TEXT_SIZES.xs,
|
|
68
40
|
small: TEXT_SIZES.sm,
|
|
@@ -73,10 +45,6 @@ export const COMMON_TEXT_SIZES = {
|
|
|
73
45
|
display: TEXT_SIZES['4xl'],
|
|
74
46
|
} as const;
|
|
75
47
|
|
|
76
|
-
/**
|
|
77
|
-
* Text sizes by size variant
|
|
78
|
-
* Maps size variants to appropriate text sizes
|
|
79
|
-
*/
|
|
80
48
|
export const TEXT_SIZE_BY_VARIANT = {
|
|
81
49
|
xs: {
|
|
82
50
|
mobile: TEXT_SIZES.xs,
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Calculation Utils
|
|
3
|
-
* @description Small numeric helpers used by presentation components
|
|
4
|
-
* (progress percentage, pagination bounds, trend formatting, clamping)
|
|
5
|
-
*/
|
|
6
1
|
|
|
7
|
-
// --- Clamping ---
|
|
8
2
|
|
|
9
3
|
export const clampToRange = (value: number, min: number, max: number): number => {
|
|
10
4
|
if (Number.isNaN(value)) return min;
|
|
@@ -20,7 +14,6 @@ export const clampToNonNegative = (value: number): number =>
|
|
|
20
14
|
export const clampToPositive = (value: number, fallback: number = 1): number =>
|
|
21
15
|
value <= 0 || Number.isNaN(value) ? fallback : value;
|
|
22
16
|
|
|
23
|
-
// --- Percentage ---
|
|
24
17
|
|
|
25
18
|
const PERCENT_MIN = 0;
|
|
26
19
|
const PERCENT_MAX = 100;
|
|
@@ -30,7 +23,6 @@ export const percentOfMax = (value: number, max: number): number => {
|
|
|
30
23
|
return clampToRange((value / max) * PERCENT_MAX, PERCENT_MIN, PERCENT_MAX);
|
|
31
24
|
};
|
|
32
25
|
|
|
33
|
-
// --- Trend formatting ---
|
|
34
26
|
|
|
35
27
|
const PERCENT_FRACTION_DIGITS = 1;
|
|
36
28
|
const SIGN_THRESHOLD = 0;
|
|
@@ -43,7 +35,6 @@ export const formatTrendMagnitude = (value: number, fractionDigits: number = PER
|
|
|
43
35
|
return `${sign}${Math.abs(value).toFixed(fractionDigits)}%`;
|
|
44
36
|
};
|
|
45
37
|
|
|
46
|
-
// --- Pagination bounds ---
|
|
47
38
|
|
|
48
39
|
export interface PageBounds {
|
|
49
40
|
totalPages: number;
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* cn Utility
|
|
3
|
-
* @description Conditional className utility using clsx + tailwind-merge for proper Tailwind class merging with LRU cache for performance
|
|
4
|
-
*/
|
|
5
1
|
|
|
6
2
|
import { clsx, type ClassValue } from 'clsx';
|
|
7
3
|
import { twMerge } from 'tailwind-merge';
|
|
8
4
|
|
|
9
5
|
export type { ClassValue };
|
|
10
6
|
|
|
11
|
-
// Simple LRU Cache implementation for className caching
|
|
12
7
|
class LRUCache<K, V> {
|
|
13
8
|
private cache: Map<K, V>;
|
|
14
9
|
private maxSize: number;
|
|
@@ -21,7 +16,6 @@ class LRUCache<K, V> {
|
|
|
21
16
|
get(key: K): V | undefined {
|
|
22
17
|
const value = this.cache.get(key);
|
|
23
18
|
if (value !== undefined) {
|
|
24
|
-
// Move to end (most recently used)
|
|
25
19
|
this.cache.delete(key);
|
|
26
20
|
this.cache.set(key, value);
|
|
27
21
|
}
|
|
@@ -29,14 +23,11 @@ class LRUCache<K, V> {
|
|
|
29
23
|
}
|
|
30
24
|
|
|
31
25
|
set(key: K, value: V): void {
|
|
32
|
-
// Remove existing entry to update position
|
|
33
26
|
if (this.cache.has(key)) {
|
|
34
27
|
this.cache.delete(key);
|
|
35
28
|
}
|
|
36
|
-
// Remove oldest entry if at capacity
|
|
37
29
|
else if (this.cache.size >= this.maxSize) {
|
|
38
30
|
const firstKey = this.cache.keys().next().value;
|
|
39
|
-
// FIX: Check if firstKey exists before deleting
|
|
40
31
|
if (firstKey !== undefined) {
|
|
41
32
|
this.cache.delete(firstKey);
|
|
42
33
|
}
|
|
@@ -49,23 +40,18 @@ class LRUCache<K, V> {
|
|
|
49
40
|
}
|
|
50
41
|
}
|
|
51
42
|
|
|
52
|
-
// Create cache instance
|
|
53
43
|
const classNameCache = new LRUCache<string, string>(256);
|
|
54
44
|
|
|
55
|
-
// FIX: Better cache key generator that handles functions and undefined
|
|
56
45
|
function generateCacheKey(inputs: ClassValue[]): string {
|
|
57
46
|
try {
|
|
58
|
-
// Convert inputs to a cacheable string representation
|
|
59
47
|
const normalized = inputs.map((input) => {
|
|
60
48
|
if (input === null || input === undefined) {
|
|
61
49
|
return 'null';
|
|
62
50
|
}
|
|
63
51
|
if (typeof input === 'function') {
|
|
64
|
-
// For functions, use a placeholder since functions can't be reliably serialized
|
|
65
52
|
return 'function';
|
|
66
53
|
}
|
|
67
54
|
if (typeof input === 'object') {
|
|
68
|
-
// Handle objects (like conditional objects in clsx)
|
|
69
55
|
return JSON.stringify(
|
|
70
56
|
Object.entries(input)
|
|
71
57
|
.filter(([, value]) => Boolean(value))
|
|
@@ -78,13 +64,11 @@ function generateCacheKey(inputs: ClassValue[]): string {
|
|
|
78
64
|
|
|
79
65
|
return normalized.join('|');
|
|
80
66
|
} catch {
|
|
81
|
-
// Fallback if anything goes wrong with serialization
|
|
82
67
|
return inputs.join('|');
|
|
83
68
|
}
|
|
84
69
|
}
|
|
85
70
|
|
|
86
71
|
export function cn(...inputs: ClassValue[]): string {
|
|
87
|
-
// Skip cache for dynamic inputs that might contain functions
|
|
88
72
|
const hasFunction = inputs.some((input) => typeof input === 'function');
|
|
89
73
|
|
|
90
74
|
if (!hasFunction) {
|
|
@@ -101,9 +85,7 @@ export function cn(...inputs: ClassValue[]): string {
|
|
|
101
85
|
return result;
|
|
102
86
|
}
|
|
103
87
|
|
|
104
|
-
// For inputs with functions, skip cache and compute directly
|
|
105
88
|
return twMerge(clsx(inputs));
|
|
106
89
|
}
|
|
107
90
|
|
|
108
|
-
// Export cache for manual clearing if needed
|
|
109
91
|
export { classNameCache };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const formatCount = (value: number, locale: string): string => new Intl.NumberFormat(locale).format(value);
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Infrastructure Utils
|
|
3
|
-
* @description Utility function exports
|
|
4
|
-
* Subpath: @umituz/web-design-system/utils
|
|
5
|
-
*/
|
|
6
1
|
|
|
7
2
|
export {
|
|
8
3
|
cn,
|
|
@@ -33,6 +28,10 @@ export type { PageBounds } from './calculation.utils';
|
|
|
33
28
|
|
|
34
29
|
export { hashSeed } from './hash.util';
|
|
35
30
|
|
|
31
|
+
export { formatCount } from './format.util';
|
|
32
|
+
|
|
33
|
+
export { uniqueId } from './id.util';
|
|
34
|
+
|
|
36
35
|
export {
|
|
37
36
|
currencyFractionDigits,
|
|
38
37
|
formatMoney,
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Money Utils
|
|
3
|
-
* @description Minor-unit money math and locale-aware formatting (ISO 4217)
|
|
4
|
-
*/
|
|
5
1
|
|
|
6
|
-
/** Currencies that don't use 2 decimal places. Everything else defaults to 2. */
|
|
7
2
|
const FRACTION_DIGITS: Record<string, number> = {
|
|
8
3
|
BHD: 3,
|
|
9
4
|
IQD: 3,
|
|
@@ -58,7 +53,6 @@ export function toMinor(amount: number, currency: string): number {
|
|
|
58
53
|
return Math.round(amount * 10 ** currencyFractionDigits(currency));
|
|
59
54
|
}
|
|
60
55
|
|
|
61
|
-
/** Parses user input like '12.50' into minor units for the currency. Null when invalid. */
|
|
62
56
|
export function parseAmountToMinor(input: string, currency: string): number | null {
|
|
63
57
|
const digits = currencyFractionDigits(currency);
|
|
64
58
|
const trimmed = input.trim().replace(',', '.');
|
|
@@ -69,7 +63,6 @@ export function parseAmountToMinor(input: string, currency: string): number | nu
|
|
|
69
63
|
return Number.isSafeInteger(minor) ? minor : null;
|
|
70
64
|
}
|
|
71
65
|
|
|
72
|
-
/** Percentage of an amount, rounded half-up to whole minor units. */
|
|
73
66
|
export function pctOfMinor(amountMinor: number, pct: number): number {
|
|
74
67
|
return Math.round((amountMinor * pct) / 100);
|
|
75
68
|
}
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Responsive Utility Functions
|
|
3
|
-
* @description Centralized functions for building responsive Tailwind classes
|
|
4
|
-
* All responsive class construction logic lives here - components should only call these functions
|
|
5
|
-
*/
|
|
6
1
|
|
|
7
2
|
import { cn } from './cn.util';
|
|
8
3
|
import type { SizeVariant, Breakpoint } from '../../domain/types';
|
|
@@ -13,25 +8,14 @@ import {
|
|
|
13
8
|
RESPONSIVE_TEXT_SIZE,
|
|
14
9
|
} from '../../domain/tokens/responsive-map.tokens';
|
|
15
10
|
|
|
16
|
-
/**
|
|
17
|
-
* Build responsive padding/margin/gap classes
|
|
18
|
-
* @param property - Tailwind spacing property ('p', 'm', 'px', 'py', 'gap', 'space-y', 'space-x')
|
|
19
|
-
* @param size - Size variant (sm, md, lg, xl)
|
|
20
|
-
* @returns Complete responsive class string
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* getSpacing('p', 'md') // "p-4 sm:p-5 md:p-5 lg:p-6 xl:p-8 2xl:p-10"
|
|
24
|
-
*/
|
|
25
11
|
export function getSpacing(
|
|
26
12
|
property: 'p' | 'm' | 'px' | 'py' | 'pt' | 'pb' | 'pl' | 'pr' | 'gap' | 'space-y' | 'space-x',
|
|
27
13
|
size: SizeVariant
|
|
28
14
|
): string {
|
|
29
15
|
const token = RESPONSIVE_SPACING[size];
|
|
30
16
|
|
|
31
|
-
// Start with base (xs/mobile) value
|
|
32
17
|
const classes: string[] = [`${property}-${token.xs}`];
|
|
33
18
|
|
|
34
|
-
// Add breakpoint-specific classes
|
|
35
19
|
const breakpoints: Breakpoint[] = ['sm', 'md', 'lg', 'xl', '2xl'];
|
|
36
20
|
breakpoints.forEach((bp) => {
|
|
37
21
|
if (token[bp] !== token.xs) {
|
|
@@ -42,14 +26,6 @@ export function getSpacing(
|
|
|
42
26
|
return classes.join(' ');
|
|
43
27
|
}
|
|
44
28
|
|
|
45
|
-
/**
|
|
46
|
-
* Build responsive icon size classes (height + width)
|
|
47
|
-
* @param size - Size variant
|
|
48
|
-
* @returns Combined height and width classes
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* getIconSize('md') // "h-5 w-5 sm:h-6 sm:w-6 md:h-7 md:w-7 lg:h-8 lg:w-8 xl:h-9 xl:w-9 2xl:h-10 2xl:w-10"
|
|
52
|
-
*/
|
|
53
29
|
export function getIconSize(size: SizeVariant): string {
|
|
54
30
|
const token = RESPONSIVE_ICON_SIZE[size];
|
|
55
31
|
const classes: string[] = [`h-${token.xs}`, `w-${token.xs}`];
|
|
@@ -64,14 +40,6 @@ export function getIconSize(size: SizeVariant): string {
|
|
|
64
40
|
return classes.join(' ');
|
|
65
41
|
}
|
|
66
42
|
|
|
67
|
-
/**
|
|
68
|
-
* Build responsive container size classes (for icon wrappers)
|
|
69
|
-
* @param size - Size variant
|
|
70
|
-
* @returns Combined height, width, and flex center classes
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* getContainerSize('md') // "w-10 h-10 sm:w-12 sm:h-12 md:w-12 md:h-12..."
|
|
74
|
-
*/
|
|
75
43
|
export function getContainerSize(size: SizeVariant): string {
|
|
76
44
|
const token = RESPONSIVE_CONTAINER_SIZE[size];
|
|
77
45
|
const classes: string[] = [`w-${token.xs}`, `h-${token.xs}`];
|
|
@@ -86,53 +54,19 @@ export function getContainerSize(size: SizeVariant): string {
|
|
|
86
54
|
return classes.join(' ');
|
|
87
55
|
}
|
|
88
56
|
|
|
89
|
-
/**
|
|
90
|
-
* Get responsive text size classes
|
|
91
|
-
* @param size - Size variant
|
|
92
|
-
* @returns Text size class string
|
|
93
|
-
*
|
|
94
|
-
* @example
|
|
95
|
-
* getTextSize('md') // "text-sm sm:text-base"
|
|
96
|
-
*/
|
|
97
57
|
export function getTextSize(size: SizeVariant): string {
|
|
98
58
|
const token = RESPONSIVE_TEXT_SIZE[size];
|
|
99
59
|
return cn(token.mobile, token.tablet);
|
|
100
60
|
}
|
|
101
61
|
|
|
102
|
-
/**
|
|
103
|
-
* Build responsive gap/spacing classes for layout
|
|
104
|
-
* @param size - Size variant
|
|
105
|
-
* @returns Gap class string
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* getGap('md') // "gap-3 sm:gap-4 md:gap-4 lg:gap-5 xl:gap-5 2xl:gap-6"
|
|
109
|
-
*/
|
|
110
62
|
export function getGap(size: SizeVariant): string {
|
|
111
63
|
return getSpacing('gap', size);
|
|
112
64
|
}
|
|
113
65
|
|
|
114
|
-
/**
|
|
115
|
-
* Build responsive space-y classes for vertical stacking
|
|
116
|
-
* @param size - Size variant
|
|
117
|
-
* @returns Space-y class string
|
|
118
|
-
*
|
|
119
|
-
* @example
|
|
120
|
-
* getSpaceY('md') // "space-y-3 sm:space-y-4 md:space-y-4 lg:space-y-5..."
|
|
121
|
-
*/
|
|
122
66
|
export function getSpaceY(size: SizeVariant): string {
|
|
123
67
|
return getSpacing('space-y', size);
|
|
124
68
|
}
|
|
125
69
|
|
|
126
|
-
/**
|
|
127
|
-
* Get complete responsive styles for common component patterns
|
|
128
|
-
* @param size - Size variant
|
|
129
|
-
* @param options - Which styles to include
|
|
130
|
-
* @returns Combined class string
|
|
131
|
-
*
|
|
132
|
-
* @example
|
|
133
|
-
* getResponsiveStyles('md', { padding: true, gap: true })
|
|
134
|
-
* // "p-4 sm:p-5 md:p-5 lg:p-6 xl:p-8 2xl:p-10 gap-3 sm:gap-4..."
|
|
135
|
-
*/
|
|
136
70
|
export function getResponsiveStyles(
|
|
137
71
|
size: SizeVariant,
|
|
138
72
|
options: {
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AspectRatio Component
|
|
3
|
-
* @description Aspect ratio container component
|
|
4
|
-
* @example
|
|
5
|
-
* import { AspectRatio } from '@umituz/web-design-system/atoms';
|
|
6
|
-
*
|
|
7
|
-
* <AspectRatio ratio={16 / 9}>
|
|
8
|
-
* <img src="..." alt="..." className="object-cover w-full h-full" />
|
|
9
|
-
* </AspectRatio>
|
|
10
|
-
*/
|
|
11
1
|
|
|
12
2
|
import * as React from "react";
|
|
13
3
|
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Badge Component (Atom)
|
|
3
|
-
* @description Small status or label indicator
|
|
4
|
-
*/
|
|
5
1
|
|
|
6
2
|
import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';
|
|
7
3
|
import { cn } from '../../infrastructure/utils';
|
|
@@ -13,7 +9,6 @@ export type BadgeVariant = ColorVariant | 'info' | 'danger' | 'neutral' | 'accen
|
|
|
13
9
|
export interface BadgeProps extends HTMLAttributes<HTMLDivElement>, BaseProps {
|
|
14
10
|
variant?: BadgeVariant;
|
|
15
11
|
tone?: BadgeVariant;
|
|
16
|
-
/** Icon rendered before the label; svgs are sized to the badge text. */
|
|
17
12
|
icon?: ReactNode;
|
|
18
13
|
size?: MediumSizes;
|
|
19
14
|
small?: boolean;
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* BatteryPill Component (Atom)
|
|
3
|
-
* @description Battery charge indicator: outline cell with fill level and percentage
|
|
4
|
-
*/
|
|
5
1
|
|
|
6
2
|
import { forwardRef, type HTMLAttributes } from 'react';
|
|
7
3
|
import { cn } from '../../infrastructure/utils';
|
|
8
4
|
import type { BaseProps } from '../../domain/types';
|
|
9
5
|
|
|
10
6
|
export interface BatteryPillProps extends HTMLAttributes<HTMLSpanElement>, BaseProps {
|
|
11
|
-
/** Charge percentage, clamped to 0-100. */
|
|
12
7
|
pct: number;
|
|
13
8
|
}
|
|
14
9
|
|
|
@@ -46,7 +46,6 @@ export interface ButtonProps
|
|
|
46
46
|
icon?: React.ReactNode;
|
|
47
47
|
iconRight?: React.ReactNode;
|
|
48
48
|
loading?: boolean;
|
|
49
|
-
/** Renders the button as a client-side navigation link (`react-router`). */
|
|
50
49
|
to?: string;
|
|
51
50
|
}
|
|
52
51
|
|
|
@@ -60,7 +59,6 @@ const Button = React.memo(React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
60
59
|
className={cn(block && 'w-full', buttonVariants({ variant, size, className }))}
|
|
61
60
|
ref={ref as React.Ref<HTMLAnchorElement>}
|
|
62
61
|
aria-disabled={disabled || loading || undefined}
|
|
63
|
-
// Button-typed DOM props (onClick, aria-*, …) flow straight onto the anchor.
|
|
64
62
|
{...(props as unknown as React.AnchorHTMLAttributes<HTMLAnchorElement>)}
|
|
65
63
|
>
|
|
66
64
|
{loading ? <Spinner size="sm" /> : icon}
|
|
@@ -1,28 +1,18 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HeatmapStrip Component (Atom)
|
|
3
|
-
* @description Compact threshold-toned strip of cells — percent-driven color
|
|
4
|
-
* and opacity ramps (skill coverage, streak calendars, activity strips).
|
|
5
|
-
*/
|
|
6
1
|
|
|
7
2
|
import { forwardRef } from 'react';
|
|
8
3
|
import { cn } from '../../infrastructure/utils';
|
|
9
4
|
import type { BaseProps } from '../../domain/types';
|
|
10
5
|
|
|
11
6
|
export interface HeatmapCell {
|
|
12
|
-
/** 0–100, or null for "no data". */
|
|
13
7
|
percent: number | null;
|
|
14
|
-
/** Tooltip text for the cell. */
|
|
15
8
|
label?: string;
|
|
16
9
|
}
|
|
17
10
|
|
|
18
11
|
export interface HeatmapStripProps extends BaseProps {
|
|
19
12
|
cells: readonly HeatmapCell[];
|
|
20
|
-
/** >= goodAt renders success; >= lowAt renders primary; below renders destructive. */
|
|
21
13
|
goodAt?: number;
|
|
22
14
|
lowAt?: number;
|
|
23
|
-
/** Cell height in px. */
|
|
24
15
|
height?: number;
|
|
25
|
-
/** Accessible name for the whole strip. */
|
|
26
16
|
label?: string;
|
|
27
17
|
}
|
|
28
18
|
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hide Component (Atom)
|
|
3
|
-
* @description Conditionally hide content based on screen breakpoint
|
|
4
|
-
*/
|
|
5
1
|
|
|
6
2
|
import { useBreakpoint } from '../hooks/useMediaQuery';
|
|
7
3
|
import type { HideProps } from '../../domain/types/breakpoint.types';
|
|
@@ -11,29 +7,9 @@ export interface HideComponentProps extends BaseProps, HideProps {
|
|
|
11
7
|
children: React.ReactNode;
|
|
12
8
|
}
|
|
13
9
|
|
|
14
|
-
/**
|
|
15
|
-
* Conditionally hide content based on breakpoint
|
|
16
|
-
* @param above - Hide on screens larger than this breakpoint
|
|
17
|
-
* @param below - Hide on screens smaller than this breakpoint
|
|
18
|
-
* @param at - Hide only on this specific breakpoint
|
|
19
|
-
* @param children - Content to hide
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```tsx
|
|
23
|
-
* // Hide on mobile (md and below)
|
|
24
|
-
* <Hide below="md"><DesktopNav /></Hide>
|
|
25
|
-
*
|
|
26
|
-
* // Hide on desktop (lg and above)
|
|
27
|
-
* <Hide above="lg"><MobileNav /></Hide>
|
|
28
|
-
*
|
|
29
|
-
* // Hide only on tablet
|
|
30
|
-
* <Hide at="md"><TabletContent /></Hide>
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
10
|
export const Hide = ({ above, below, at, children, className }: HideComponentProps) => {
|
|
34
11
|
const { matches, isGreaterThan, isLessThan } = useBreakpoint();
|
|
35
12
|
|
|
36
|
-
// Determine if content should be hidden
|
|
37
13
|
let shouldHide = false;
|
|
38
14
|
|
|
39
15
|
if (above) {
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Money Component (Atom)
|
|
3
|
-
* @description Locale-aware currency amount from minor units, tabular digits
|
|
4
|
-
*/
|
|
5
1
|
|
|
6
2
|
import { forwardRef, type HTMLAttributes } from 'react';
|
|
7
3
|
import { formatMoney } from '../../infrastructure/utils';
|
|
@@ -9,9 +5,7 @@ import { cn } from '../../infrastructure/utils';
|
|
|
9
5
|
import type { BaseProps } from '../../domain/types';
|
|
10
6
|
|
|
11
7
|
export interface MoneyProps extends HTMLAttributes<HTMLSpanElement>, BaseProps {
|
|
12
|
-
/** Integer amount in minor units (e.g. cents) — never floating point. */
|
|
13
8
|
amountMinor: number;
|
|
14
|
-
/** ISO 4217 currency code; drives the fraction digits. */
|
|
15
9
|
currency: string;
|
|
16
10
|
locale?: string;
|
|
17
11
|
}
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Progress Component (Atom)
|
|
3
|
-
* @description Progress indicator bar with optional percent readout and
|
|
4
|
-
* threshold-driven auto tone (>=95 success, >=70 primary, below muted)
|
|
5
|
-
*/
|
|
6
1
|
|
|
7
2
|
import { forwardRef, type HTMLAttributes } from 'react';
|
|
8
3
|
import { cn } from '../../infrastructure/utils';
|
|
@@ -15,7 +10,6 @@ export interface ProgressProps extends HTMLAttributes<HTMLDivElement>, BaseProps
|
|
|
15
10
|
size?: 'sm' | 'md' | 'lg';
|
|
16
11
|
tone?: 'primary' | 'success' | 'warning' | 'destructive' | 'info' | 'auto';
|
|
17
12
|
label?: string;
|
|
18
|
-
/** Render the rounded percentage next to the bar. */
|
|
19
13
|
showValue?: boolean;
|
|
20
14
|
}
|
|
21
15
|
|