@sudobility/monitoring-components 1.0.8
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/break-timer.d.ts +33 -0
- package/dist/break-timer.d.ts.map +1 -0
- package/dist/copy-button.d.ts +52 -0
- package/dist/copy-button.d.ts.map +1 -0
- package/dist/cursor-tracker.d.ts +33 -0
- package/dist/cursor-tracker.d.ts.map +1 -0
- package/dist/gas-tracker.d.ts +33 -0
- package/dist/gas-tracker.d.ts.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +586 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.umd.js +7 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/overtime-tracker.d.ts +33 -0
- package/dist/overtime-tracker.d.ts.map +1 -0
- package/dist/portal.d.ts +29 -0
- package/dist/portal.d.ts.map +1 -0
- package/dist/recycling-tracker.d.ts +18 -0
- package/dist/recycling-tracker.d.ts.map +1 -0
- package/dist/show.d.ts +31 -0
- package/dist/show.d.ts.map +1 -0
- package/dist/sleep-tracker.d.ts +33 -0
- package/dist/sleep-tracker.d.ts.map +1 -0
- package/dist/time-tracker.d.ts +33 -0
- package/dist/time-tracker.d.ts.map +1 -0
- package/dist/water-intake.d.ts +33 -0
- package/dist/water-intake.d.ts.map +1 -0
- package/package.json +53 -0
- package/src/break-timer.tsx +60 -0
- package/src/copy-button.tsx +156 -0
- package/src/cursor-tracker.tsx +60 -0
- package/src/gas-tracker.tsx +60 -0
- package/src/index.ts +19 -0
- package/src/overtime-tracker.tsx +60 -0
- package/src/portal.tsx +44 -0
- package/src/recycling-tracker.tsx +41 -0
- package/src/show.tsx +38 -0
- package/src/sleep-tracker.tsx +60 -0
- package/src/time-tracker.tsx +60 -0
- package/src/water-intake.tsx +60 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { cn } from '@sudobility/components';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UbreakUtimer Component
|
|
5
|
+
*
|
|
6
|
+
* A reusable UbreakUtimer component with full dark mode support.
|
|
7
|
+
* Optimized for accessibility and AI-assisted development.
|
|
8
|
+
*
|
|
9
|
+
* @component
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <UbreakUtimer className="custom-class" />
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* This component supports:
|
|
17
|
+
* - Light and dark themes automatically
|
|
18
|
+
* - Responsive design
|
|
19
|
+
* - Accessibility features
|
|
20
|
+
* - TypeScript type safety
|
|
21
|
+
*
|
|
22
|
+
* @see {@link https://docs.example.com/components/break-timer}
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export interface UbreakUtimerProps {
|
|
26
|
+
/** Additional CSS classes */
|
|
27
|
+
className?: string;
|
|
28
|
+
/** Component children */
|
|
29
|
+
children?: React.ReactNode;
|
|
30
|
+
/** Disabled state */
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
/** Callback when component is interacted with */
|
|
33
|
+
onClick?: () => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const UbreakUtimer = ({
|
|
37
|
+
className,
|
|
38
|
+
children,
|
|
39
|
+
disabled = false,
|
|
40
|
+
onClick,
|
|
41
|
+
}: UbreakUtimerProps) => {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
className={cn(
|
|
45
|
+
'p-4 rounded-lg border transition-colors',
|
|
46
|
+
'bg-white dark:bg-gray-900',
|
|
47
|
+
'border-gray-200 dark:border-gray-700',
|
|
48
|
+
'text-gray-900 dark:text-white',
|
|
49
|
+
disabled && 'opacity-50 cursor-not-allowed',
|
|
50
|
+
'hover:bg-gray-50 dark:hover:bg-gray-800',
|
|
51
|
+
className
|
|
52
|
+
)}
|
|
53
|
+
onClick={disabled ? undefined : onClick}
|
|
54
|
+
role='region'
|
|
55
|
+
aria-label='UbreakUtimer'
|
|
56
|
+
>
|
|
57
|
+
{children || 'UbreakUtimer Component'}
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { cn, useCopyToClipboard } from '@sudobility/components';
|
|
3
|
+
import { ClipboardDocumentIcon, CheckIcon } from '@heroicons/react/24/outline';
|
|
4
|
+
|
|
5
|
+
export interface CopyButtonProps {
|
|
6
|
+
/** Text to copy to clipboard */
|
|
7
|
+
text: string;
|
|
8
|
+
/** Button size */
|
|
9
|
+
size?: 'sm' | 'md' | 'lg';
|
|
10
|
+
/** Button variant */
|
|
11
|
+
variant?: 'icon' | 'text' | 'outline';
|
|
12
|
+
/** Custom label (for text/outline variants) */
|
|
13
|
+
label?: string;
|
|
14
|
+
/** Custom success label (for text/outline variants) */
|
|
15
|
+
successLabel?: string;
|
|
16
|
+
/** Icon position (for text/outline variants) */
|
|
17
|
+
iconPosition?: 'left' | 'right';
|
|
18
|
+
/** Additional className */
|
|
19
|
+
className?: string;
|
|
20
|
+
/** Custom tooltip text */
|
|
21
|
+
title?: string;
|
|
22
|
+
/** Callback after successful copy */
|
|
23
|
+
onCopySuccess?: () => void;
|
|
24
|
+
/** Callback after copy error */
|
|
25
|
+
onCopyError?: (error: Error) => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* CopyButton Component
|
|
30
|
+
*
|
|
31
|
+
* A button that copies text to the clipboard with visual feedback.
|
|
32
|
+
* Commonly used for copying IDs, addresses, code snippets, or URLs.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* // Icon button (default)
|
|
37
|
+
* <CopyButton text="0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb" />
|
|
38
|
+
*
|
|
39
|
+
* // Text button with label
|
|
40
|
+
* <CopyButton
|
|
41
|
+
* text="https://example.com?referral=abc123"
|
|
42
|
+
* variant="text"
|
|
43
|
+
* label="Copy Link"
|
|
44
|
+
* successLabel="Copied!"
|
|
45
|
+
* />
|
|
46
|
+
*
|
|
47
|
+
* // Outline button
|
|
48
|
+
* <CopyButton
|
|
49
|
+
* text={templateId}
|
|
50
|
+
* variant="outline"
|
|
51
|
+
* label="Copy ID"
|
|
52
|
+
* />
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export const CopyButton: React.FC<CopyButtonProps> = ({
|
|
56
|
+
text,
|
|
57
|
+
size = 'md',
|
|
58
|
+
variant = 'icon',
|
|
59
|
+
label = 'Copy',
|
|
60
|
+
successLabel = 'Copied!',
|
|
61
|
+
iconPosition = 'left',
|
|
62
|
+
className,
|
|
63
|
+
title,
|
|
64
|
+
onCopySuccess,
|
|
65
|
+
onCopyError,
|
|
66
|
+
}) => {
|
|
67
|
+
const { copyToClipboard, isCopied } = useCopyToClipboard({
|
|
68
|
+
successDuration: 2000,
|
|
69
|
+
onSuccess: onCopySuccess,
|
|
70
|
+
onError: onCopyError,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const copied = isCopied(text);
|
|
74
|
+
|
|
75
|
+
const handleClick = () => {
|
|
76
|
+
copyToClipboard(text);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Size configurations
|
|
80
|
+
const sizeClasses = {
|
|
81
|
+
sm: {
|
|
82
|
+
icon: 'h-3.5 w-3.5',
|
|
83
|
+
button: 'p-1',
|
|
84
|
+
text: 'text-xs px-2 py-1',
|
|
85
|
+
},
|
|
86
|
+
md: {
|
|
87
|
+
icon: 'h-4 w-4',
|
|
88
|
+
button: 'p-1.5',
|
|
89
|
+
text: 'text-sm px-3 py-1.5',
|
|
90
|
+
},
|
|
91
|
+
lg: {
|
|
92
|
+
icon: 'h-5 w-5',
|
|
93
|
+
button: 'p-2',
|
|
94
|
+
text: 'text-base px-4 py-2',
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const sizeConfig = sizeClasses[size];
|
|
99
|
+
const Icon = copied ? CheckIcon : ClipboardDocumentIcon;
|
|
100
|
+
|
|
101
|
+
// Icon-only button
|
|
102
|
+
if (variant === 'icon') {
|
|
103
|
+
return (
|
|
104
|
+
<button
|
|
105
|
+
onClick={handleClick}
|
|
106
|
+
className={cn(
|
|
107
|
+
'inline-flex items-center justify-center rounded transition-colors',
|
|
108
|
+
copied
|
|
109
|
+
? 'text-green-600 dark:text-green-400'
|
|
110
|
+
: 'text-gray-400 hover:text-gray-600 dark:hover:text-gray-300',
|
|
111
|
+
sizeConfig.button,
|
|
112
|
+
className
|
|
113
|
+
)}
|
|
114
|
+
title={title || (copied ? 'Copied!' : 'Copy to clipboard')}
|
|
115
|
+
type='button'
|
|
116
|
+
>
|
|
117
|
+
<Icon className={sizeConfig.icon} />
|
|
118
|
+
</button>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Text or outline button
|
|
123
|
+
const baseTextClasses = cn(
|
|
124
|
+
'inline-flex items-center gap-2 rounded font-medium transition-colors',
|
|
125
|
+
sizeConfig.text
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const variantClasses = {
|
|
129
|
+
text: cn(
|
|
130
|
+
copied
|
|
131
|
+
? 'text-green-600 dark:text-green-400'
|
|
132
|
+
: 'text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300'
|
|
133
|
+
),
|
|
134
|
+
outline: cn(
|
|
135
|
+
'border',
|
|
136
|
+
copied
|
|
137
|
+
? 'border-green-600 text-green-600 dark:border-green-400 dark:text-green-400'
|
|
138
|
+
: 'border-gray-300 text-gray-700 hover:border-gray-400 dark:border-gray-600 dark:text-gray-300 dark:hover:border-gray-500'
|
|
139
|
+
),
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const displayLabel = copied ? successLabel : label;
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<button
|
|
146
|
+
onClick={handleClick}
|
|
147
|
+
className={cn(baseTextClasses, variantClasses[variant], className)}
|
|
148
|
+
title={title || (copied ? 'Copied!' : 'Copy to clipboard')}
|
|
149
|
+
type='button'
|
|
150
|
+
>
|
|
151
|
+
{iconPosition === 'left' && <Icon className={sizeConfig.icon} />}
|
|
152
|
+
<span>{displayLabel}</span>
|
|
153
|
+
{iconPosition === 'right' && <Icon className={sizeConfig.icon} />}
|
|
154
|
+
</button>
|
|
155
|
+
);
|
|
156
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { cn } from '@sudobility/components';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UcursorUtracker Component
|
|
5
|
+
*
|
|
6
|
+
* A reusable UcursorUtracker component with full dark mode support.
|
|
7
|
+
* Optimized for accessibility and AI-assisted development.
|
|
8
|
+
*
|
|
9
|
+
* @component
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <UcursorUtracker className="custom-class" />
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* This component supports:
|
|
17
|
+
* - Light and dark themes automatically
|
|
18
|
+
* - Responsive design
|
|
19
|
+
* - Accessibility features
|
|
20
|
+
* - TypeScript type safety
|
|
21
|
+
*
|
|
22
|
+
* @see {@link https://docs.example.com/components/cursor-tracker}
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export interface UcursorUtrackerProps {
|
|
26
|
+
/** Additional CSS classes */
|
|
27
|
+
className?: string;
|
|
28
|
+
/** Component children */
|
|
29
|
+
children?: React.ReactNode;
|
|
30
|
+
/** Disabled state */
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
/** Callback when component is interacted with */
|
|
33
|
+
onClick?: () => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const UcursorUtracker = ({
|
|
37
|
+
className,
|
|
38
|
+
children,
|
|
39
|
+
disabled = false,
|
|
40
|
+
onClick,
|
|
41
|
+
}: UcursorUtrackerProps) => {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
className={cn(
|
|
45
|
+
'p-4 rounded-lg border transition-colors',
|
|
46
|
+
'bg-white dark:bg-gray-900',
|
|
47
|
+
'border-gray-200 dark:border-gray-700',
|
|
48
|
+
'text-gray-900 dark:text-white',
|
|
49
|
+
disabled && 'opacity-50 cursor-not-allowed',
|
|
50
|
+
'hover:bg-gray-50 dark:hover:bg-gray-800',
|
|
51
|
+
className
|
|
52
|
+
)}
|
|
53
|
+
onClick={disabled ? undefined : onClick}
|
|
54
|
+
role='region'
|
|
55
|
+
aria-label='UcursorUtracker'
|
|
56
|
+
>
|
|
57
|
+
{children || 'UcursorUtracker Component'}
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { cn } from '@sudobility/components';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UgasUtracker Component
|
|
5
|
+
*
|
|
6
|
+
* A reusable UgasUtracker component with full dark mode support.
|
|
7
|
+
* Optimized for accessibility and AI-assisted development.
|
|
8
|
+
*
|
|
9
|
+
* @component
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <UgasUtracker className="custom-class" />
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* This component supports:
|
|
17
|
+
* - Light and dark themes automatically
|
|
18
|
+
* - Responsive design
|
|
19
|
+
* - Accessibility features
|
|
20
|
+
* - TypeScript type safety
|
|
21
|
+
*
|
|
22
|
+
* @see {@link https://docs.example.com/components/gas-tracker}
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export interface UgasUtrackerProps {
|
|
26
|
+
/** Additional CSS classes */
|
|
27
|
+
className?: string;
|
|
28
|
+
/** Component children */
|
|
29
|
+
children?: React.ReactNode;
|
|
30
|
+
/** Disabled state */
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
/** Callback when component is interacted with */
|
|
33
|
+
onClick?: () => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const UgasUtracker = ({
|
|
37
|
+
className,
|
|
38
|
+
children,
|
|
39
|
+
disabled = false,
|
|
40
|
+
onClick,
|
|
41
|
+
}: UgasUtrackerProps) => {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
className={cn(
|
|
45
|
+
'p-4 rounded-lg border transition-colors',
|
|
46
|
+
'bg-white dark:bg-gray-900',
|
|
47
|
+
'border-gray-200 dark:border-gray-700',
|
|
48
|
+
'text-gray-900 dark:text-white',
|
|
49
|
+
disabled && 'opacity-50 cursor-not-allowed',
|
|
50
|
+
'hover:bg-gray-50 dark:hover:bg-gray-800',
|
|
51
|
+
className
|
|
52
|
+
)}
|
|
53
|
+
onClick={disabled ? undefined : onClick}
|
|
54
|
+
role='region'
|
|
55
|
+
aria-label='UgasUtracker'
|
|
56
|
+
>
|
|
57
|
+
{children || 'UgasUtracker Component'}
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* monitoring-components
|
|
3
|
+
*
|
|
4
|
+
* Specialized components for the monitoring domain
|
|
5
|
+
*
|
|
6
|
+
* @package @sudobility/monitoring-components
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export * from './break-timer';
|
|
10
|
+
export * from './copy-button';
|
|
11
|
+
export * from './cursor-tracker';
|
|
12
|
+
export * from './gas-tracker';
|
|
13
|
+
export * from './overtime-tracker';
|
|
14
|
+
export * from './portal';
|
|
15
|
+
export * from './recycling-tracker';
|
|
16
|
+
export * from './show';
|
|
17
|
+
export * from './sleep-tracker';
|
|
18
|
+
export * from './time-tracker';
|
|
19
|
+
export * from './water-intake';
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { cn } from '@sudobility/components';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UovertimeUtracker Component
|
|
5
|
+
*
|
|
6
|
+
* A reusable UovertimeUtracker component with full dark mode support.
|
|
7
|
+
* Optimized for accessibility and AI-assisted development.
|
|
8
|
+
*
|
|
9
|
+
* @component
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <UovertimeUtracker className="custom-class" />
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* This component supports:
|
|
17
|
+
* - Light and dark themes automatically
|
|
18
|
+
* - Responsive design
|
|
19
|
+
* - Accessibility features
|
|
20
|
+
* - TypeScript type safety
|
|
21
|
+
*
|
|
22
|
+
* @see {@link https://docs.example.com/components/overtime-tracker}
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export interface UovertimeUtrackerProps {
|
|
26
|
+
/** Additional CSS classes */
|
|
27
|
+
className?: string;
|
|
28
|
+
/** Component children */
|
|
29
|
+
children?: React.ReactNode;
|
|
30
|
+
/** Disabled state */
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
/** Callback when component is interacted with */
|
|
33
|
+
onClick?: () => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const UovertimeUtracker = ({
|
|
37
|
+
className,
|
|
38
|
+
children,
|
|
39
|
+
disabled = false,
|
|
40
|
+
onClick,
|
|
41
|
+
}: UovertimeUtrackerProps) => {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
className={cn(
|
|
45
|
+
'p-4 rounded-lg border transition-colors',
|
|
46
|
+
'bg-white dark:bg-gray-900',
|
|
47
|
+
'border-gray-200 dark:border-gray-700',
|
|
48
|
+
'text-gray-900 dark:text-white',
|
|
49
|
+
disabled && 'opacity-50 cursor-not-allowed',
|
|
50
|
+
'hover:bg-gray-50 dark:hover:bg-gray-800',
|
|
51
|
+
className
|
|
52
|
+
)}
|
|
53
|
+
onClick={disabled ? undefined : onClick}
|
|
54
|
+
role='region'
|
|
55
|
+
aria-label='UovertimeUtracker'
|
|
56
|
+
>
|
|
57
|
+
{children || 'UovertimeUtracker Component'}
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
};
|
package/src/portal.tsx
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
|
|
4
|
+
export interface PortalProps {
|
|
5
|
+
/** Content to portal */
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
/** Target container (defaults to document.body) */
|
|
8
|
+
container?: Element | null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Portal Component
|
|
13
|
+
*
|
|
14
|
+
* Renders children into a DOM node outside the parent component's hierarchy.
|
|
15
|
+
* Useful for modals, tooltips, and overlays that need to break out of z-index stacking.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* <Portal>
|
|
20
|
+
* <Modal>Content</Modal>
|
|
21
|
+
* </Portal>
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* <Portal container={customElement}>
|
|
27
|
+
* <Tooltip>Tooltip content</Tooltip>
|
|
28
|
+
* </Portal>
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export const Portal: React.FC<PortalProps> = ({ children, container }) => {
|
|
32
|
+
const [mounted, setMounted] = useState(false);
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
setMounted(true);
|
|
36
|
+
return () => setMounted(false);
|
|
37
|
+
}, []);
|
|
38
|
+
|
|
39
|
+
if (!mounted) return null;
|
|
40
|
+
|
|
41
|
+
const target = container || document.body;
|
|
42
|
+
|
|
43
|
+
return createPortal(children, target);
|
|
44
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { cn } from '@sudobility/components';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* RecyclingTracker Component
|
|
5
|
+
*
|
|
6
|
+
* Environmental/sustainability component with full dark mode support.
|
|
7
|
+
*
|
|
8
|
+
* @component
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <RecyclingTracker className="custom-class" />
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export interface RecyclingTrackerProps {
|
|
15
|
+
className?: string;
|
|
16
|
+
children?: React.ReactNode;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const RecyclingTracker = ({
|
|
21
|
+
className,
|
|
22
|
+
children,
|
|
23
|
+
disabled,
|
|
24
|
+
}: RecyclingTrackerProps) => {
|
|
25
|
+
return (
|
|
26
|
+
<div
|
|
27
|
+
className={cn(
|
|
28
|
+
'p-4 rounded-lg border transition-colors',
|
|
29
|
+
'bg-white dark:bg-gray-900',
|
|
30
|
+
'border-gray-200 dark:border-gray-700',
|
|
31
|
+
'text-gray-900 dark:text-white',
|
|
32
|
+
disabled && 'opacity-50 cursor-not-allowed',
|
|
33
|
+
className
|
|
34
|
+
)}
|
|
35
|
+
role='region'
|
|
36
|
+
aria-label='RecyclingTracker'
|
|
37
|
+
>
|
|
38
|
+
{children || 'RecyclingTracker Component'}
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
};
|
package/src/show.tsx
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export interface ShowProps {
|
|
4
|
+
/** Condition to evaluate */
|
|
5
|
+
when: boolean;
|
|
6
|
+
/** Content to show when condition is true */
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
/** Fallback content when condition is false */
|
|
9
|
+
fallback?: React.ReactNode;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Show Component
|
|
14
|
+
*
|
|
15
|
+
* Conditional rendering component with optional fallback.
|
|
16
|
+
* Provides cleaner syntax than ternary operators for conditional UI.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* <Show when={isLoading} fallback={<Content />}>
|
|
21
|
+
* <Spinner />
|
|
22
|
+
* </Show>
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* <Show when={user !== null}>
|
|
28
|
+
* <WelcomeMessage user={user} />
|
|
29
|
+
* </Show>
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export const Show: React.FC<ShowProps> = ({
|
|
33
|
+
when,
|
|
34
|
+
children,
|
|
35
|
+
fallback = null,
|
|
36
|
+
}) => {
|
|
37
|
+
return <>{when ? children : fallback}</>;
|
|
38
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { cn } from '@sudobility/components';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UsleepUtracker Component
|
|
5
|
+
*
|
|
6
|
+
* A reusable UsleepUtracker component with full dark mode support.
|
|
7
|
+
* Optimized for accessibility and AI-assisted development.
|
|
8
|
+
*
|
|
9
|
+
* @component
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <UsleepUtracker className="custom-class" />
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* This component supports:
|
|
17
|
+
* - Light and dark themes automatically
|
|
18
|
+
* - Responsive design
|
|
19
|
+
* - Accessibility features
|
|
20
|
+
* - TypeScript type safety
|
|
21
|
+
*
|
|
22
|
+
* @see {@link https://docs.example.com/components/sleep-tracker}
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export interface UsleepUtrackerProps {
|
|
26
|
+
/** Additional CSS classes */
|
|
27
|
+
className?: string;
|
|
28
|
+
/** Component children */
|
|
29
|
+
children?: React.ReactNode;
|
|
30
|
+
/** Disabled state */
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
/** Callback when component is interacted with */
|
|
33
|
+
onClick?: () => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const UsleepUtracker = ({
|
|
37
|
+
className,
|
|
38
|
+
children,
|
|
39
|
+
disabled = false,
|
|
40
|
+
onClick,
|
|
41
|
+
}: UsleepUtrackerProps) => {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
className={cn(
|
|
45
|
+
'p-4 rounded-lg border transition-colors',
|
|
46
|
+
'bg-white dark:bg-gray-900',
|
|
47
|
+
'border-gray-200 dark:border-gray-700',
|
|
48
|
+
'text-gray-900 dark:text-white',
|
|
49
|
+
disabled && 'opacity-50 cursor-not-allowed',
|
|
50
|
+
'hover:bg-gray-50 dark:hover:bg-gray-800',
|
|
51
|
+
className
|
|
52
|
+
)}
|
|
53
|
+
onClick={disabled ? undefined : onClick}
|
|
54
|
+
role='region'
|
|
55
|
+
aria-label='UsleepUtracker'
|
|
56
|
+
>
|
|
57
|
+
{children || 'UsleepUtracker Component'}
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { cn } from '@sudobility/components';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UtimeUtracker Component
|
|
5
|
+
*
|
|
6
|
+
* A reusable UtimeUtracker component with full dark mode support.
|
|
7
|
+
* Optimized for accessibility and AI-assisted development.
|
|
8
|
+
*
|
|
9
|
+
* @component
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <UtimeUtracker className="custom-class" />
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* This component supports:
|
|
17
|
+
* - Light and dark themes automatically
|
|
18
|
+
* - Responsive design
|
|
19
|
+
* - Accessibility features
|
|
20
|
+
* - TypeScript type safety
|
|
21
|
+
*
|
|
22
|
+
* @see {@link https://docs.example.com/components/time-tracker}
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export interface UtimeUtrackerProps {
|
|
26
|
+
/** Additional CSS classes */
|
|
27
|
+
className?: string;
|
|
28
|
+
/** Component children */
|
|
29
|
+
children?: React.ReactNode;
|
|
30
|
+
/** Disabled state */
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
/** Callback when component is interacted with */
|
|
33
|
+
onClick?: () => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const UtimeUtracker = ({
|
|
37
|
+
className,
|
|
38
|
+
children,
|
|
39
|
+
disabled = false,
|
|
40
|
+
onClick,
|
|
41
|
+
}: UtimeUtrackerProps) => {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
className={cn(
|
|
45
|
+
'p-4 rounded-lg border transition-colors',
|
|
46
|
+
'bg-white dark:bg-gray-900',
|
|
47
|
+
'border-gray-200 dark:border-gray-700',
|
|
48
|
+
'text-gray-900 dark:text-white',
|
|
49
|
+
disabled && 'opacity-50 cursor-not-allowed',
|
|
50
|
+
'hover:bg-gray-50 dark:hover:bg-gray-800',
|
|
51
|
+
className
|
|
52
|
+
)}
|
|
53
|
+
onClick={disabled ? undefined : onClick}
|
|
54
|
+
role='region'
|
|
55
|
+
aria-label='UtimeUtracker'
|
|
56
|
+
>
|
|
57
|
+
{children || 'UtimeUtracker Component'}
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
};
|