@catalystsoftware/ui 1.0.5 → 1.0.7

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.
Files changed (155) hide show
  1. package/dist/data/data.tsx +29 -29
  2. package/dist/data/tailwind.config.js +3821 -261
  3. package/dist/data.tsx +29 -29
  4. package/package.json +4 -3
  5. package/components/catalyst-ui/buttons/burger.tsx +0 -207
  6. package/components/catalyst-ui/core/data-display/timeline.tsx +0 -210
  7. package/components/catalyst-ui/core/feedback/alert.tsx +0 -491
  8. package/components/catalyst-ui/core/feedback/spinner-1.tsx +0 -65
  9. package/components/catalyst-ui/core/feedback/toast.tsx +0 -1857
  10. package/components/catalyst-ui/core/navigation/menu.tsx +0 -164
  11. package/components/catalyst-ui/forms/toggle-class.tsx +0 -176
  12. package/components/catalyst-ui/hooks/use-copy-to-clipboard.tsx +0 -419
  13. package/components/catalyst-ui/hooks/use-counter.tsx +0 -13
  14. package/components/catalyst-ui/hooks/use-event-listener.tsx +0 -23
  15. package/components/catalyst-ui/hooks/use-export-markdown.tsx +0 -47
  16. package/components/catalyst-ui/hooks/use-focus.tsx +0 -17
  17. package/components/catalyst-ui/hooks/use-interval.tsx +0 -23
  18. package/components/catalyst-ui/hooks/use-is-client.tsx +0 -16
  19. package/components/catalyst-ui/hooks/use-media-query.tsx +0 -19
  20. package/components/catalyst-ui/hooks/use-mobile.tsx +0 -19
  21. package/components/catalyst-ui/hooks/use-resize-observer.tsx +0 -81
  22. package/components/catalyst-ui/hooks/use-timeout.tsx +0 -21
  23. package/components/catalyst-ui/hooks/use-timer.tsx +0 -209
  24. package/components/catalyst-ui/hooks/use-toggle.tsx +0 -12
  25. package/components/catalyst-ui/media/image.tsx +0 -13
  26. package/components/catalyst-ui/overlays/dual-sidebar.tsx +0 -4142
  27. package/components/catalyst-ui/overlays/sidebar-original.tsx +0 -726
  28. package/components/catalyst-ui/primitives/accordion.tsx +0 -250
  29. package/components/catalyst-ui/primitives/alert-dialog.tsx +0 -126
  30. package/components/catalyst-ui/primitives/aspect-ratio.tsx +0 -9
  31. package/components/catalyst-ui/primitives/avatar.tsx +0 -296
  32. package/components/catalyst-ui/primitives/badge.tsx +0 -57
  33. package/components/catalyst-ui/primitives/breadcrumb.tsx +0 -101
  34. package/components/catalyst-ui/primitives/button.tsx +0 -265
  35. package/components/catalyst-ui/primitives/calendar-v4.tsx +0 -208
  36. package/components/catalyst-ui/primitives/calendar.tsx +0 -295
  37. package/components/catalyst-ui/primitives/card.tsx +0 -618
  38. package/components/catalyst-ui/primitives/carousel.tsx +0 -238
  39. package/components/catalyst-ui/primitives/chart.tsx +0 -347
  40. package/components/catalyst-ui/primitives/checkbox.tsx +0 -225
  41. package/components/catalyst-ui/primitives/collapsible.tsx +0 -212
  42. package/components/catalyst-ui/primitives/command.tsx +0 -393
  43. package/components/catalyst-ui/primitives/context-menu.tsx +0 -236
  44. package/components/catalyst-ui/primitives/dialog.tsx +0 -471
  45. package/components/catalyst-ui/primitives/drawer.tsx +0 -761
  46. package/components/catalyst-ui/primitives/dropdown-menu.tsx +0 -290
  47. package/components/catalyst-ui/primitives/empty.tsx +0 -104
  48. package/components/catalyst-ui/primitives/field.tsx +0 -244
  49. package/components/catalyst-ui/primitives/hover-card.tsx +0 -124
  50. package/components/catalyst-ui/primitives/input-otp.tsx +0 -76
  51. package/components/catalyst-ui/primitives/input.tsx +0 -64
  52. package/components/catalyst-ui/primitives/item.tsx +0 -196
  53. package/components/catalyst-ui/primitives/kbd.tsx +0 -75
  54. package/components/catalyst-ui/primitives/label.tsx +0 -24
  55. package/components/catalyst-ui/primitives/navigation-menu.tsx +0 -150
  56. package/components/catalyst-ui/primitives/pagination.tsx +0 -198
  57. package/components/catalyst-ui/primitives/popover.tsx +0 -232
  58. package/components/catalyst-ui/primitives/progress.tsx +0 -34
  59. package/components/catalyst-ui/primitives/radio-group.tsx +0 -43
  60. package/components/catalyst-ui/primitives/resizable.tsx +0 -56
  61. package/components/catalyst-ui/primitives/select.tsx +0 -155
  62. package/components/catalyst-ui/primitives/separator.tsx +0 -74
  63. package/components/catalyst-ui/primitives/sheet.tsx +0 -126
  64. package/components/catalyst-ui/primitives/skeleton.tsx +0 -15
  65. package/components/catalyst-ui/primitives/slider.tsx +0 -27
  66. package/components/catalyst-ui/primitives/switch.tsx +0 -187
  67. package/components/catalyst-ui/primitives/tabs.tsx +0 -335
  68. package/components/catalyst-ui/primitives/textarea.tsx +0 -24
  69. package/components/catalyst-ui/primitives/toggle-group.tsx +0 -55
  70. package/components/catalyst-ui/primitives/toggle.tsx +0 -42
  71. package/components/catalyst-ui/primitives/tooltip.tsx +0 -116
  72. package/components/catalyst-ui/utils/basic-auth.tsx +0 -40
  73. package/components/catalyst-ui/utils/context-storage.tsx +0 -19
  74. package/components/catalyst-ui/utils/cors-middleware.tsx +0 -71
  75. package/components/catalyst-ui/utils/deferred-content.tsx +0 -595
  76. package/components/catalyst-ui/utils/honeypot-middleware.tsx +0 -38
  77. package/components/catalyst-ui/utils/incId.tsx +0 -75
  78. package/components/catalyst-ui/utils/jwk-auth.tsx +0 -36
  79. package/components/catalyst-ui/utils/request-id.tsx +0 -14
  80. package/components/catalyst-ui/utils/secure-headers.tsx +0 -37
  81. package/components/catalyst-ui/utils/server-timing.tsx +0 -23
  82. package/components/catalyst-ui/utils/utils.ts +0 -43
  83. package/components/catalyst-ui/utils/with-cookie.tsx +0 -43
  84. package/components/catalyst-ui/x/accordian-x.tsx +0 -428
  85. package/components/catalyst-ui/x/alert-x.tsx +0 -413
  86. package/components/catalyst-ui/x/animated-text-x.tsx +0 -2242
  87. package/components/catalyst-ui/x/avatar-x.tsx +0 -515
  88. package/components/catalyst-ui/x/badge-x.tsx +0 -670
  89. package/components/catalyst-ui/x/button-X.tsx +0 -2857
  90. package/components/catalyst-ui/x/button-group-x.tsx +0 -847
  91. package/components/catalyst-ui/x/calendar-x.tsx +0 -1910
  92. package/components/catalyst-ui/x/card-x.tsx +0 -2597
  93. package/components/catalyst-ui/x/checkbox-x.tsx +0 -656
  94. package/components/catalyst-ui/x/collapsible-x.tsx +0 -1360
  95. package/components/catalyst-ui/x/combobox-x.tsx +0 -911
  96. package/components/catalyst-ui/x/data-table-x.tsx +0 -1753
  97. package/components/catalyst-ui/x/date-picker-x.tsx +0 -648
  98. package/components/catalyst-ui/x/dialog-x.tsx +0 -659
  99. package/components/catalyst-ui/x/dropdown-menu-x.tsx +0 -612
  100. package/components/catalyst-ui/x/hover-card-x.tsx +0 -375
  101. package/components/catalyst-ui/x/icon-x.tsx +0 -840
  102. package/components/catalyst-ui/x/input-mask-x.tsx +0 -981
  103. package/components/catalyst-ui/x/input-otp-x.tsx +0 -659
  104. package/components/catalyst-ui/x/loader-x.tsx +0 -1757
  105. package/components/catalyst-ui/x/pagination-x.tsx +0 -622
  106. package/components/catalyst-ui/x/popover-x.tsx +0 -744
  107. package/components/catalyst-ui/x/radio-group-x.tsx +0 -499
  108. package/components/catalyst-ui/x/select-x.tsx +0 -1127
  109. package/components/catalyst-ui/x/sheet-x.tsx +0 -668
  110. package/components/catalyst-ui/x/switch-x.tsx +0 -681
  111. package/components/catalyst-ui/x/table-x.tsx +0 -574
  112. package/components/catalyst-ui/x/tabs-x.tsx +0 -839
  113. package/components/catalyst-ui/x/textarea-x.tsx +0 -1263
  114. package/components/catalyst-ui/x/tooltip-x.tsx +0 -396
  115. package/components/catalyst-ui/x/tracker-x.tsx +0 -560
  116. package/data/bg-data.tsx +0 -901
  117. package/data/buttons-data.tsx +0 -2327
  118. package/data/charts-data.tsx +0 -102
  119. package/data/chat-data.tsx +0 -83
  120. package/data/code-data.tsx +0 -1040
  121. package/data/comboboxes-data.tsx +0 -1843
  122. package/data/command-data.tsx +0 -1381
  123. package/data/core-data.tsx +0 -15953
  124. package/data/crm-data.tsx +0 -47
  125. package/data/data.tsx +0 -159
  126. package/data/date-and-time-data.tsx +0 -554
  127. package/data/dependencies.tsx +0 -7
  128. package/data/ecommerce-data.tsx +0 -1387
  129. package/data/forms-data.tsx +0 -7890
  130. package/data/hooks-data.tsx +0 -5487
  131. package/data/index.ts +0 -34
  132. package/data/inputs-data.tsx +0 -557
  133. package/data/interactive-data.tsx +0 -5394
  134. package/data/lofi-data.tsx +0 -18295
  135. package/data/marketing-data.tsx +0 -2546
  136. package/data/media-data.tsx +0 -1510
  137. package/data/motion-data.tsx +0 -5801
  138. package/data/overlay-data.tsx +0 -4136
  139. package/data/pdf-data.tsx +0 -124
  140. package/data/pos-data.tsx +0 -213
  141. package/data/postcss.config.js +0 -6
  142. package/data/primitive-data.tsx +0 -5170
  143. package/data/prompt-data.tsx +0 -1226
  144. package/data/requiredLibs.ts +0 -4
  145. package/data/sandbox-data.tsx +0 -1
  146. package/data/sidebars-data.tsx +0 -5421
  147. package/data/stacks-data.tsx +0 -32
  148. package/data/table-data.tsx +0 -706
  149. package/data/tailwind.config.js +0 -270
  150. package/data/tailwind.config.ngin.js +0 -3830
  151. package/data/tailwind.css +0 -431
  152. package/data/tools-data.tsx +0 -6910
  153. package/data/typography-data.tsx +0 -2050
  154. package/data/utils-data.tsx +0 -6500
  155. package/data/x-data.tsx +0 -1171
@@ -1,419 +0,0 @@
1
-
2
- import * as React from "react"
3
-
4
-
5
- /**
6
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ useCopyToClipboard Hook ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
7
- * ★ ━━━━ ☆ ━━━━ ━━━━ ☆ ━━━━ ★
8
- * useCopyToClipboard: A React hook for copying text to clipboard with timeout and callbacks
9
- *
10
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Basic Usage ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
11
- * ```jsx
12
- * const { isCopied, copyToClipboard } = useCopyToClipboard()
13
- *
14
- * return (
15
- * <button onClick={() => copyToClipboard('Hello World')}>
16
- * {isCopied ? 'Copied!' : 'Copy Text'}
17
- * </button>
18
- * )
19
- * ```
20
- *
21
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ With Custom Timeout ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
22
- * ```jsx
23
- * // 2 second timeout
24
- * const { copyToClipboard } = useCopyToClipboard({
25
- * timeout: 2000
26
- * })
27
- *
28
- * // 10 second timeout (for important info)
29
- * const { copyToClipboard } = useCopyToClipboard({
30
- * timeout: 10000
31
- * })
32
- * ```
33
- *
34
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ With Callback ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
35
- * ```jsx
36
- * const { copyToClipboard } = useCopyToClipboard({
37
- * onCopy: () => {
38
- * // Show success toast
39
- * toast.success('Copied to clipboard!')
40
- *
41
- * // Track analytics event
42
- * analytics.track('text_copied')
43
- *
44
- * // Update UI state
45
- * setShowCopiedFeedback(true)
46
- * }
47
- * })
48
- * ```
49
- *
50
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ In Component Examples ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
51
- * ```jsx
52
- * // Copy button component
53
- * function CopyButton({ text }) {
54
- * const { isCopied, copyToClipboard } = useCopyToClipboard()
55
- *
56
- * return (
57
- * <button
58
- * onClick={() => copyToClipboard(text)}
59
- * className={isCopied ? 'copied' : ''}
60
- * >
61
- * {isCopied ? '✓ Copied' : 'Copy'}
62
- * </button>
63
- * )
64
- * }
65
- *
66
- * // Code snippet with copy
67
- * function CodeSnippet({ code }) {
68
- * const { isCopied, copyToClipboard } = useCopyToClipboard({
69
- * timeout: 3000,
70
- * onCopy: () => console.log('Code copied:', code)
71
- * })
72
- *
73
- * return (
74
- * <div className="code-block">
75
- * <pre>{code}</pre>
76
- * <button onClick={() => copyToClipboard(code)}>
77
- * {isCopied ? 'Copied!' : 'Copy Code'}
78
- * </button>
79
- * </div>
80
- * )
81
- * }
82
- * ```
83
- *
84
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Multiple Copy Instances ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
85
- * ```jsx
86
- * // Track which item was copied
87
- * function CopyList({ items }) {
88
- * const { isCopied, copyToClipboard } = useCopyToClipboard()
89
- *
90
- * return (
91
- * <ul>
92
- * {items.map((item) => (
93
- * <li key={item.id}>
94
- * {item.text}
95
- * <button
96
- * onClick={() => copyToClipboard(item.text)}
97
- * aria-label={`Copy ${item.name}`}
98
- * >
99
- * {isCopied === item.text ? '✓' : 'Copy'}
100
- * </button>
101
- * </li>
102
- * ))}
103
- * </ul>
104
- * )
105
- * }
106
- *
107
- * // Compare current copied text
108
- * function isCurrentlyCopied(text) {
109
- * return isCopied === text
110
- * }
111
- * ```
112
- *
113
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ With UI Feedback Patterns ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
114
- * ```jsx
115
- * // Tooltip feedback
116
- * function CopyWithTooltip({ text }) {
117
- * const { isCopied, copyToClipboard } = useCopyToClipboard()
118
- *
119
- * return (
120
- * <Tooltip content={isCopied ? 'Copied!' : 'Click to copy'}>
121
- * <button onClick={() => copyToClipboard(text)}>
122
- * {text}
123
- * </button>
124
- * </Tooltip>
125
- * )
126
- * }
127
- *
128
- * // Icon feedback
129
- * function CopyIconButton({ text }) {
130
- * const { isCopied, copyToClipboard } = useCopyToClipboard()
131
- *
132
- * return (
133
- * <button onClick={() => copyToClipboard(text)}>
134
- * {isCopied ? <CheckIcon /> : <CopyIcon />}
135
- * </button>
136
- * )
137
- * }
138
- *
139
- * // Toast notification
140
- * function CopyWithToast({ text }) {
141
- * const { copyToClipboard } = useCopyToClipboard({
142
- * onCopy: () => toast('Copied to clipboard!')
143
- * })
144
- *
145
- * return (
146
- * <button onClick={() => copyToClipboard(text)}>
147
- * Copy
148
- * </button>
149
- * )
150
- * }
151
- * ```
152
- *
153
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Hook Return Values ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
154
- * ```typescript
155
- * interface UseCopyToClipboardReturn {
156
- * // The currently copied text (null if nothing copied or timeout expired)
157
- * isCopied: string | null
158
- *
159
- * // Function to copy text to clipboard
160
- * copyToClipboard: (value: string) => void
161
- * }
162
- *
163
- * // Usage example
164
- * const { isCopied, copyToClipboard } = useCopyToClipboard(options)
165
- *
166
- * // Check if specific text is currently copied
167
- * const isThisCopied = isCopied === 'specific text'
168
- *
169
- * // Check if anything is copied
170
- * const hasCopied = isCopied !== null
171
- * ```
172
- *
173
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Hook Options ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
174
- * ```typescript
175
- * interface UseCopyToClipboardOptions {
176
- * // Time in milliseconds before resetting copied state (default: 4000)
177
- * timeout?: number
178
- *
179
- * // Callback function triggered after successful copy
180
- * onCopy?: () => void
181
- * }
182
- *
183
- * // Examples of different configurations
184
- * const defaultOptions = {} // Uses default 4000ms timeout
185
- *
186
- * const shortFeedback = { timeout: 1000 } // Quick feedback
187
- *
188
- * const withAnalytics = {
189
- * timeout: 5000,
190
- * onCopy: () => trackEvent('copy_action')
191
- * }
192
- *
193
- * const withMultipleCallbacks = {
194
- * onCopy: () => {
195
- * showToast()
196
- * trackAnalytics()
197
- * updateUIState()
198
- * }
199
- * }
200
- * ```
201
- *
202
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Error Handling ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
203
- * ```jsx
204
- * // Safe copy with error handling
205
- * function SafeCopyButton({ text }) {
206
- * const { isCopied, copyToClipboard } = useCopyToClipboard()
207
- *
208
- * const handleCopy = () => {
209
- * try {
210
- * copyToClipboard(text)
211
- * } catch (error) {
212
- * console.error('Failed to copy:', error)
213
- * // Show error message to user
214
- * toast.error('Failed to copy to clipboard')
215
- * }
216
- * }
217
- *
218
- * return (
219
- * <button onClick={handleCopy}>
220
- * {isCopied ? 'Copied!' : 'Copy'}
221
- * </button>
222
- * )
223
- * }
224
- *
225
- * // Check clipboard API support
226
- * function CopyButton({ text }) {
227
- * const { isCopied, copyToClipboard } = useCopyToClipboard()
228
- *
229
- * const isClipboardSupported =
230
- * typeof window !== 'undefined' &&
231
- * navigator?.clipboard?.writeText
232
- *
233
- * if (!isClipboardSupported) {
234
- * return <span>Clipboard not supported in this browser</span>
235
- * }
236
- *
237
- * return (
238
- * <button onClick={() => copyToClipboard(text)}>
239
- * {isCopied ? 'Copied!' : 'Copy'}
240
- * </button>
241
- * )
242
- * }
243
- * ```
244
- *
245
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Advanced Usage Patterns ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
246
- * ```jsx
247
- * // Debounced copy (prevent rapid clicks)
248
- * function DebouncedCopyButton({ text }) {
249
- * const { isCopied, copyToClipboard } = useCopyToClipboard()
250
- * const [isDebouncing, setIsDebouncing] = useState(false)
251
- *
252
- * const handleCopy = () => {
253
- * if (isDebouncing) return
254
- *
255
- * setIsDebouncing(true)
256
- * copyToClipboard(text)
257
- *
258
- * setTimeout(() => {
259
- * setIsDebouncing(false)
260
- * }, 1000)
261
- * }
262
- *
263
- * return (
264
- * <button
265
- * onClick={handleCopy}
266
- * disabled={isDebouncing}
267
- * >
268
- * {isDebouncing ? 'Copying...' : isCopied ? 'Copied!' : 'Copy'}
269
- * </button>
270
- * )
271
- * }
272
- *
273
- * // Copy with confirmation
274
- * function CopyWithConfirmation({ text }) {
275
- * const { isCopied, copyToClipboard } = useCopyToClipboard()
276
- * const [showConfirm, setShowConfirm] = useState(false)
277
- *
278
- * const handleCopy = () => {
279
- * if (text.length > 1000) {
280
- * setShowConfirm(true)
281
- * } else {
282
- * copyToClipboard(text)
283
- * }
284
- * }
285
- *
286
- * return (
287
- * <>
288
- * <button onClick={handleCopy}>
289
- * Copy
290
- * </button>
291
- *
292
- * {showConfirm && (
293
- * <ConfirmationDialog
294
- * onConfirm={() => {
295
- * copyToClipboard(text)
296
- * setShowConfirm(false)
297
- * }}
298
- * onCancel={() => setShowConfirm(false)}
299
- * />
300
- * )}
301
- * </>
302
- * )
303
- * }
304
- * ```
305
- *
306
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Integration Examples ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
307
- * ```jsx
308
- * // In a form field
309
- * function CopyableInput({ value }) {
310
- * const { isCopied, copyToClipboard } = useCopyToClipboard()
311
- *
312
- * return (
313
- * <div className="input-group">
314
- * <input type="text" value={value} readOnly />
315
- * <button
316
- * onClick={() => copyToClipboard(value)}
317
- * className={isCopied ? 'success' : ''}
318
- * >
319
- * {isCopied ? '✓' : 'Copy'}
320
- * </button>
321
- * </div>
322
- * )
323
- * }
324
- *
325
- * // In a data table
326
- * function DataTable({ rows }) {
327
- * const { isCopied, copyToClipboard } = useCopyToClipboard()
328
- *
329
- * return (
330
- * <table>
331
- * <tbody>
332
- * {rows.map(row => (
333
- * <tr key={row.id}>
334
- * <td>{row.value}</td>
335
- * <td>
336
- * <button
337
- * onClick={() => copyToClipboard(row.value)}
338
- * aria-label={`Copy ${row.name}`}
339
- * >
340
- * {isCopied === row.value ? 'Copied' : 'Copy'}
341
- * </button>
342
- * </td>
343
- * </tr>
344
- * ))}
345
- * </tbody>
346
- * </table>
347
- * )
348
- * }
349
- *
350
- * // With rich text/html
351
- * function CopyHTMLContent({ html }) {
352
- * const { isCopied, copyToClipboard } = useCopyToClipboard()
353
- *
354
- * const handleCopyHTML = async () => {
355
- * // Convert HTML to plain text for clipboard
356
- * const plainText = html.replace(/<[^>]*>/g, '')
357
- * copyToClipboard(plainText)
358
- * }
359
- *
360
- * return (
361
- * <div>
362
- * <div dangerouslySetInnerHTML={{ __html: html }} />
363
- * <button onClick={handleCopyHTML}>
364
- * {isCopied ? 'Copied as text' : 'Copy text content'}
365
- * </button>
366
- * </div>
367
- * )
368
- * }
369
- * ```
370
- *
371
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Browser Support Notes ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
372
- * - **Modern Browsers**: Full support in Chrome, Firefox, Safari, Edge
373
- * - **HTTPS Requirement**: Clipboard API requires secure context (HTTPS)
374
- * - **User Permission**: Some browsers may require user permission
375
- * - **Fallback Consideration**: Consider fallback for older browsers
376
- *
377
- * ★ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━ Best Practices ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ☆ ━━━━━━━━━━━━━━ ★
378
- * 1. **Provide Visual Feedback**: Always show when text is copied
379
- * 2. **Use Appropriate Timeout**: Match timeout to user reading speed
380
- * 3. **Handle Empty Values**: Check for empty or null text
381
- * 4. **Add Accessibility**: Include ARIA labels for screen readers
382
- * 5. **Consider Context**: Show what was copied (especially in lists)
383
- * 6. **Error Recovery**: Provide fallback options if clipboard fails
384
- * 7. **Security**: Be cautious with sensitive data in clipboard
385
- *
386
- */
387
-
388
-
389
- export function useCopyToClipboard({
390
- timeout = 4000,
391
- onCopy,
392
- }: {
393
- timeout?: number
394
- onCopy?: () => void
395
- } = {}) {
396
- const [isCopied, setIsCopied] =React.useState<string | null>(null)
397
-
398
- const copyToClipboard = (value: string) => {
399
- if (typeof window === "undefined" || !navigator?.clipboard?.writeText) {
400
- return
401
- }
402
-
403
- if (!value) return
404
-
405
- navigator.clipboard.writeText(value).then(() => {
406
- setIsCopied(value)
407
-
408
- if (onCopy) {
409
- onCopy()
410
- }
411
-
412
- setTimeout(() => {
413
- setIsCopied(null)
414
- }, timeout)
415
- }, console.error)
416
- }
417
-
418
- return { isCopied, copyToClipboard }
419
- }
@@ -1,13 +0,0 @@
1
- // app/hooks/index.ts
2
- import { useState, useEffect, useRef, useCallback } from 'react';
3
-
4
- export function useCounter(initialValue = 0, step = 1) {
5
- const [count, setCount] = useState<number>(initialValue);
6
-
7
- const increment = useCallback(() => setCount(c => c + step), [step]);
8
- const decrement = useCallback(() => setCount(c => c - step), [step]);
9
- const reset = useCallback(() => setCount(initialValue), [initialValue]);
10
- const setValue = useCallback((value: number) => setCount(value), []);
11
-
12
- return { count, increment, decrement, reset, setValue } as const;
13
- }
@@ -1,23 +0,0 @@
1
- import { useEffect, RefObject } from 'react';
2
-
3
- export function useEventListener<K extends keyof HTMLElementEventMap>(
4
- eventName: K,
5
- handler: (event: HTMLElementEventMap[K]) => void,
6
- element?: RefObject<HTMLElement>,
7
- options?: boolean | AddEventListenerOptions
8
- ) {
9
- useEffect(() => {
10
- const targetElement = element?.current || window;
11
-
12
- if (!targetElement?.addEventListener) return;
13
-
14
- const eventListener = (event: HTMLElementEventMap[K]) => handler(event);
15
-
16
- targetElement.addEventListener(eventName, eventListener, options);
17
-
18
- return () => {
19
- targetElement.removeEventListener(eventName, eventListener, options);
20
- };
21
- }, [eventName, handler, element, options]);
22
- }
23
-
@@ -1,47 +0,0 @@
1
- import { useCallback } from 'react';
2
-
3
- export function useExportMarkdown() {
4
- const exportMarkdown = useCallback((content: string, filename: string = 'document.md') => {
5
- try {
6
- if (!content) {
7
- console.warn('No content provided for export');
8
- return;
9
- }
10
-
11
- const blob = new Blob([content], { type: 'text/markdown' });
12
- const url = URL.createObjectURL(blob);
13
- const a = document.createElement('a');
14
- a.href = url;
15
- a.download = filename.endsWith('.md') ? filename : `${filename}.md`;
16
- document.body.appendChild(a);
17
- a.click();
18
- document.body.removeChild(a);
19
-
20
- setTimeout(() => URL.revokeObjectURL(url), 100);
21
- } catch (error) {
22
- console.error('Failed to export markdown:', error);
23
- }
24
- }, []);
25
-
26
- return exportMarkdown;
27
- }
28
-
29
-
30
- /**
31
- * import { useExportMarkdown } from './hooks/useExportMarkdown';
32
-
33
- function MyComponent() {
34
- const exportMarkdown = useExportMarkdown();
35
- const [markdown, setMarkdown] = useState('');
36
-
37
- const handleExport = () => {
38
- exportMarkdown(markdown, 'custom-filename.md');
39
- };
40
-
41
- return (
42
- <button onClick={handleExport}>
43
- Export as Markdown
44
- </button>
45
- );
46
- }
47
- */
@@ -1,17 +0,0 @@
1
- import { FocusProps, useFocus as useAriaFocus } from 'react-aria';
2
- import { useRef } from 'react';
3
-
4
- export interface UseFocusOptions extends FocusProps {
5
- isDisabled?: boolean;
6
- }
7
-
8
- export function useFocus(props: UseFocusOptions = {}) {
9
- const ref = useRef<HTMLElement>(null);
10
- const { focusProps, isFocused } = useAriaFocus(props, ref);
11
-
12
- return {
13
- focusProps,
14
- isFocused,
15
- ref
16
- };
17
- }
@@ -1,23 +0,0 @@
1
- // app/hooks/index.ts
2
- import { useState, useEffect, useRef, useCallback } from 'react';
3
-
4
- export function useInterval(callback: () => void, delay: number | null) {
5
- const savedCallback = useRef<() => void>();
6
-
7
- useEffect(() => {
8
- savedCallback.current = callback;
9
- }, [callback]);
10
-
11
- useEffect(() => {
12
- function tick() {
13
- if (savedCallback.current) {
14
- savedCallback.current();
15
- }
16
- }
17
-
18
- if (delay !== null) {
19
- const id = setInterval(tick, delay);
20
- return () => clearInterval(id);
21
- }
22
- }, [delay]);
23
- }
@@ -1,16 +0,0 @@
1
- import React, { useEffect, useState } from 'react'
2
- import { cn } from '~/components/catalyst-ui/utils'
3
-
4
- function useIsClient(): boolean {
5
- const [isClient, setIsClient] = useState(false)
6
-
7
- useEffect(() => {
8
- setIsClient(true)
9
- }, [])
10
-
11
- return isClient
12
- }
13
-
14
-
15
-
16
- export { useIsClient }
@@ -1,19 +0,0 @@
1
- import * as React from "react"
2
-
3
- export function useMediaQuery(query: string) {
4
- const [value, setValue] = React.useState(false)
5
-
6
- React.useEffect(() => {
7
- function onChange(event: MediaQueryListEvent) {
8
- setValue(event.matches)
9
- }
10
-
11
- const result = matchMedia(query)
12
- result.addEventListener("change", onChange)
13
- setValue(result.matches)
14
-
15
- return () => result.removeEventListener("change", onChange)
16
- }, [query])
17
-
18
- return value
19
- }
@@ -1,19 +0,0 @@
1
- import * as React from "react"
2
-
3
- const MOBILE_BREAKPOINT = 768
4
-
5
- export function useIsMobile() {
6
- const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
-
8
- React.useEffect(() => {
9
- const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
- const onChange = () => {
11
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
- }
13
- mql.addEventListener("change", onChange)
14
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
- return () => mql.removeEventListener("change", onChange)
16
- }, [])
17
-
18
- return !!isMobile
19
- }
@@ -1,81 +0,0 @@
1
- import React, { useEffect, useRef, useState } from 'react'
2
- import { cn } from '~/components/catalyst-ui/utils'
3
-
4
- type BoxModel = 'content-box' | 'border-box' | 'device-pixel-content-box'
5
-
6
- type Size = {
7
- width: number
8
- height: number
9
- }
10
-
11
- type UseResizeObserverOptions<T extends HTMLElement> = {
12
- ref: React.RefObject<T>
13
- onResize?: (size: Size) => void
14
- box?: BoxModel
15
- }
16
-
17
- type UseResizeObserverReturn = {
18
- width: number | undefined
19
- height: number | undefined
20
- }
21
-
22
- function useResizeObserver<T extends HTMLElement = HTMLElement>(
23
- options: UseResizeObserverOptions<T>
24
- ): UseResizeObserverReturn {
25
- const { ref, onResize, box = 'content-box' } = options
26
- const [size, setSize] = useState<Size | undefined>(undefined)
27
-
28
- useEffect(() => {
29
- const element = ref.current
30
- if (!element) return
31
-
32
- if (typeof window === 'undefined' || !window.ResizeObserver) {
33
- return
34
- }
35
-
36
- const resizeObserver = new ResizeObserver((entries) => {
37
- if (!Array.isArray(entries) || !entries.length) {
38
- return
39
- }
40
-
41
- const entry = entries[0]
42
- let width: number
43
- let height: number
44
-
45
- if (box === 'border-box') {
46
- width = entry.borderBoxSize?.[0]?.inlineSize ?? entry.contentRect.width
47
- height = entry.borderBoxSize?.[0]?.blockSize ?? entry.contentRect.height
48
- } else if (box === 'device-pixel-content-box') {
49
- width = entry.devicePixelContentBoxSize?.[0]?.inlineSize ?? entry.contentRect.width
50
- height = entry.devicePixelContentBoxSize?.[0]?.blockSize ?? entry.contentRect.height
51
- } else {
52
- width = entry.contentBoxSize?.[0]?.inlineSize ?? entry.contentRect.width
53
- height = entry.contentBoxSize?.[0]?.blockSize ?? entry.contentRect.height
54
- }
55
-
56
- const newSize = { width, height }
57
-
58
- if (onResize) {
59
- onResize(newSize)
60
- } else {
61
- setSize(newSize)
62
- }
63
- })
64
-
65
- resizeObserver.observe(element, { box })
66
-
67
- return () => {
68
- resizeObserver.disconnect()
69
- }
70
- }, [ref, box, onResize])
71
-
72
- return {
73
- width: size?.width,
74
- height: size?.height,
75
- }
76
- }
77
-
78
-
79
-
80
-
81
- export { useResizeObserver, }