@refraction-ui/astro 0.17.1 → 0.17.3

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 (38) hide show
  1. package/dist/accordion/accordion.ts +155 -0
  2. package/dist/accordion/index.ts +9 -1
  3. package/dist/analytics/analytics-manager.ts +7 -2
  4. package/dist/analytics/http-sink.ts +3 -1
  5. package/dist/analytics/types.ts +6 -0
  6. package/dist/astro-data-table/DataTable.stories.ts +9 -5
  7. package/dist/astro-diff-viewer/DiffViewer.stories.ts +25 -10
  8. package/dist/astro-file-tree/index.ts +4 -1
  9. package/dist/astro-icon-system/index.ts +4 -1
  10. package/dist/astro-slide-viewer/SlideViewer.stories.ts +11 -5
  11. package/dist/astro-version-selector/VersionSelector.stories.ts +13 -5
  12. package/dist/calendar/calendar.ts +11 -6
  13. package/dist/call-controls/call-controls.ts +2 -4
  14. package/dist/carousel/carousel.ts +45 -0
  15. package/dist/carousel/index.ts +9 -1
  16. package/dist/command-input/command-input.ts +10 -1
  17. package/dist/conversation/conversation.ts +9 -7
  18. package/dist/conversation/types.ts +2 -0
  19. package/dist/date-picker/date-picker.ts +6 -3
  20. package/dist/device-frame/device-frame.ts +2 -4
  21. package/dist/emoji-picker/emoji-picker.ts +2 -3
  22. package/dist/file-upload/file-upload.ts +0 -1
  23. package/dist/footer/footer.ts +4 -1
  24. package/dist/index.ts +239 -126
  25. package/dist/location-selector/location-selector.ts +2 -2
  26. package/dist/logger/telemetry-manager.ts +7 -4
  27. package/dist/logger/types.ts +4 -0
  28. package/dist/pagination/index.ts +14 -1
  29. package/dist/pagination/pagination.styles.ts +33 -0
  30. package/dist/pagination/pagination.ts +160 -0
  31. package/dist/presence-indicator/presence-indicator.ts +2 -4
  32. package/dist/reaction-bar/reaction-bar.ts +2 -3
  33. package/dist/slider/slider.ts +134 -2
  34. package/dist/status-indicator/status-indicator.ts +2 -4
  35. package/dist/thread-view/thread-view.ts +6 -7
  36. package/dist/toast/toast.ts +16 -5
  37. package/dist/voice-pill/voice-pill.ts +2 -4
  38. package/package.json +7 -5
@@ -1,5 +1,3 @@
1
- import type { AccessibilityProps } from '../shared/index.ts'
2
-
3
1
  export type DeviceType = 'iphone' | 'ipad' | 'android-phone' | 'android-tablet'
4
2
  export type DeviceOrientation = 'portrait' | 'landscape'
5
3
 
@@ -27,7 +25,7 @@ export interface DeviceFrameAPI {
27
25
  /** Computed dimensions for the device */
28
26
  dimensions: DeviceDimensions
29
27
  /** ARIA attributes for the device frame */
30
- ariaProps: Partial<AccessibilityProps> & Record<string, unknown>
28
+ ariaProps: Record<string, string | number | boolean>
31
29
  /** Data attributes for styling hooks */
32
30
  dataAttributes: Record<string, string>
33
31
  }
@@ -92,7 +90,7 @@ export function createDeviceFrame(props: DeviceFrameProps): DeviceFrameAPI {
92
90
  homeIndicator: spec.homeIndicator,
93
91
  }
94
92
 
95
- const ariaProps: Partial<AccessibilityProps> & Record<string, unknown> = {
93
+ const ariaProps: Record<string, string | number | boolean> = {
96
94
  role: 'img',
97
95
  'aria-label': `${DEVICE_LABELS[device]} device frame in ${orientation} orientation`,
98
96
  }
@@ -1,4 +1,3 @@
1
- import type { AccessibilityProps } from '../shared/index.ts'
2
1
  import { generateId } from '../shared/index.ts'
3
2
  import {
4
3
  EMOJI_DATA,
@@ -39,7 +38,7 @@ export interface EmojiPickerAPI {
39
38
  /** Category tabs with labels */
40
39
  categoryTabs: { category: EmojiCategory; label: string; emoji: string }[]
41
40
  /** ARIA props for the picker container */
42
- ariaProps: Partial<AccessibilityProps> & Record<string, unknown>
41
+ ariaProps: Record<string, string | number | boolean>
43
42
  /** ARIA props for the search input */
44
43
  searchInputProps: Record<string, unknown>
45
44
  /** Get ARIA props for an emoji button */
@@ -118,7 +117,7 @@ export function createEmojiPicker(props: EmojiPickerProps = {}): EmojiPickerAPI
118
117
  emoji: CATEGORY_ICONS[cat],
119
118
  }))
120
119
 
121
- const ariaProps: Partial<AccessibilityProps> & Record<string, unknown> = {
120
+ const ariaProps: Record<string, string | number | boolean> = {
122
121
  role: 'dialog',
123
122
  'aria-labelledby': labelId,
124
123
  id: containerId,
@@ -208,7 +208,6 @@ export function createFileUpload(props: FileUploadProps = {}): FileUploadAPI {
208
208
  const dropZoneProps: Partial<AccessibilityProps> & Record<string, unknown> = {
209
209
  role: 'button',
210
210
  'aria-label': 'Drop files here or click to upload',
211
- 'aria-describedby': labelId,
212
211
  id: dropZoneId,
213
212
  tabIndex: 0,
214
213
  }
@@ -13,6 +13,8 @@ export interface FooterProps {
13
13
  copyright?: string
14
14
  socialLinks?: SocialLink[]
15
15
  columns?: FooterColumn[]
16
+ /** Year for the default copyrightText. Default: ambient current year — inject to avoid year-boundary SSR/CSR mismatch. */
17
+ year?: number
16
18
  }
17
19
 
18
20
  export interface FooterAPI {
@@ -22,7 +24,8 @@ export interface FooterAPI {
22
24
 
23
25
  export function createFooter(props: FooterProps = {}): FooterAPI {
24
26
  const { copyright } = props
25
- const year = new Date().getFullYear()
27
+ // Injection boundary: ambient year is the default; inject `year` so SSR and client agree.
28
+ const year = props.year ?? new Date().getFullYear()
26
29
  const copyrightText = copyright ?? `© ${year} All rights reserved.`
27
30
 
28
31
  return {
package/dist/index.ts CHANGED
@@ -1,126 +1,239 @@
1
- // Auto-generated meta-package index
2
- export * from './astro-accordion/index.ts';
3
- export * from './shared/index.ts';
4
- export * from './astro-ai/index.ts';
5
- export * from './astro-analytics/index.ts';
6
- export * from './astro-animated-text/index.ts';
7
- export * from './astro-app-shell/index.ts';
8
- export * from './astro-audience-feature-card/index.ts';
9
- export * from './astro-audio-room/index.ts';
10
- export * from './astro-auth/index.ts';
11
- export * from './astro-avatar/index.ts';
12
- export * from './astro-avatar-group/index.ts';
13
- export * from './astro-badge/index.ts';
14
- export * from './astro-bottom-nav/index.ts';
15
- export * from './astro-brand-network-cell/index.ts';
16
- export * from './astro-breadcrumbs/index.ts';
17
- export * from './astro-browser-chrome-mock/index.ts';
18
- export * from './astro-button/index.ts';
19
- export * from './astro-calendar/index.ts';
20
- export * from './astro-call-controls/index.ts';
21
- export * from './astro-callout/index.ts';
22
- export * from './astro-card/index.ts';
23
- export * from './astro-card-grid/index.ts';
24
- export * from './astro-carousel/index.ts';
25
- export * from './astro-charts/index.ts';
26
- export * from './astro-checkbox/index.ts';
27
- export * from './astro-checklist/index.ts';
28
- export * from './astro-code-block/index.ts';
29
- export * from './astro-code-editor/index.ts';
30
- export * from './astro-collapsible/index.ts';
31
- export * from './astro-command/index.ts';
32
- export * from './astro-command-input/index.ts';
33
- export * from './astro-composer/index.ts';
34
- export * from './astro-content-protection/index.ts';
35
- export * from './astro-conversation/index.ts';
36
- export * from './astro-cookie-consent/index.ts';
37
- export * from './astro-data-table/index.ts';
38
- export * from './astro-date-picker/index.ts';
39
- export * from './astro-device-frame/index.ts';
40
- export * from './astro-dialog/index.ts';
41
- export * from './astro-diff-viewer/index.ts';
42
- export * from './astro-dropdown-menu/index.ts';
43
- export * from './astro-editor-status-bar/index.ts';
44
- export * from './astro-editor-tabs/index.ts';
45
- export * from './astro-emoji-picker/index.ts';
46
- export * from './astro-empty-state/index.ts';
47
- export * from './astro-feedback-dialog/index.ts';
48
- export * from './astro-file-tree/index.ts';
49
- export * from './astro-file-upload/index.ts';
50
- export * from './astro-floating-reactions/index.ts';
51
- export * from './astro-flow-editor/index.ts';
52
- export * from './astro-footer/index.ts';
53
- export * from './astro-graph-view/index.ts';
54
- export * from './astro-icon-system/index.ts';
55
- export * from './astro-infinite-canvas/index.ts';
56
- export * from './astro-inline-editor/index.ts';
57
- export * from './astro-input/index.ts';
58
- export * from './astro-input-group/index.ts';
59
- export * from './astro-install-prompt/index.ts';
60
- export * from './astro-kanban-board/index.ts';
61
- export * from './astro-keyboard-shortcut/index.ts';
62
- export * from './astro-language-selector/index.ts';
63
- export * from './astro-link-card/index.ts';
64
- export * from './astro-live-captions/index.ts';
65
- export * from './astro-live-cursors/index.ts';
66
- export * from './astro-live-transcript/index.ts';
67
- export * from './astro-location-selector/index.ts';
68
- export * from './astro-logger/index.ts';
69
- export * from './astro-markdown-renderer/index.ts';
70
- export * from './astro-marquee-strip/index.ts';
71
- export * from './astro-mastery-bar/index.ts';
72
- export * from './astro-mascot/index.ts';
73
- export * from './astro-mini-map/index.ts';
74
- export * from './astro-mobile-nav/index.ts';
75
- export * from './astro-navbar/index.ts';
76
- export * from './astro-numbered-steps/index.ts';
77
- export * from './astro-otp-input/index.ts';
78
- export * from './astro-pagination/index.ts';
79
- export * from './astro-password-input/index.ts';
80
- export * from './astro-payment/index.ts';
81
- export * from './astro-popover/index.ts';
82
- export * from './astro-pre-call-lobby/index.ts';
83
- export * from './astro-presence-indicator/index.ts';
84
- export * from './astro-pricing-card/index.ts';
85
- export * from './astro-progress-display/index.ts';
86
- export * from './astro-radial-gauge/index.ts';
87
- export * from './astro-radio/index.ts';
88
- export * from './astro-rating-scale/index.ts';
89
- export * from './astro-reaction-bar/index.ts';
90
- export * from './astro-resizable-layout/index.ts';
91
- export * from './astro-rich-editor/index.ts';
92
- export * from './astro-search-bar/index.ts';
93
- export * from './astro-section-head/index.ts';
94
- export * from './astro-segmented-control/index.ts';
95
- export * from './astro-select/index.ts';
96
- export * from './astro-separator/index.ts';
97
- export * from './astro-sidebar/index.ts';
98
- export * from './astro-skeleton/index.ts';
99
- export * from './astro-skip-to-content/index.ts';
100
- export * from './astro-slide-viewer/index.ts';
101
- export * from './astro-slider/index.ts';
102
- export * from './astro-slot-picker/index.ts';
103
- export * from './astro-social-auth-button/index.ts';
104
- export * from './astro-sortable-list/index.ts';
105
- export * from './astro-stat-grid/index.ts';
106
- export * from './astro-status-indicator/index.ts';
107
- export * from './astro-steps/index.ts';
108
- export * from './astro-sticky-note/index.ts';
109
- export * from './astro-switch/index.ts';
110
- export * from './astro-table-of-contents/index.ts';
111
- export * from './astro-tabs/index.ts';
112
- export * from './astro-terminal/index.ts';
113
- export * from './astro-test-results/index.ts';
114
- export * from './astro-textarea/index.ts';
115
- export * from './astro-theme/index.ts';
116
- export * from './astro-thread-view/index.ts';
117
- export * from './astro-timeline/index.ts';
118
- export * from './astro-toast/index.ts';
119
- export * from './astro-tooltip/index.ts';
120
- export * from './astro-version-selector/index.ts';
121
- export * from './astro-video-grid/index.ts';
122
- export * from './astro-video-player/index.ts';
123
- export * from './astro-video-tile/index.ts';
124
- export * from './astro-voice-pill/index.ts';
125
- export * from './astro-waveform/index.ts';
126
- export * from './astro-wizard/index.ts';
1
+ // Auto-generated meta-package index (from src/index.ts — edit that file, not this one)
2
+ /**
3
+ * @refraction-ui/astro
4
+ *
5
+ * Meta package that re-exports all @refraction-ui/astro-* component packages,
6
+ * so consumers install a single package and import every component from it.
7
+ */
8
+
9
+ // Embedded shared utilities — `@refraction-ui/shared` is private and copied
10
+ // into the shipped artifact by the meta build, so the meta re-exports it
11
+ // directly instead of referencing the package.
12
+ export * from './shared/index.ts'
13
+
14
+ // Core / theme
15
+ export * from './astro-theme/index.ts'
16
+
17
+ // Components (alphabetical)
18
+ export * from './astro-accordion/index.ts'
19
+ export * from './astro-ai/index.ts'
20
+ export * from './astro-animated-text/index.ts'
21
+ export * from './astro-app-shell/index.ts'
22
+ export * from './astro-auth/index.ts'
23
+ export * from './astro-avatar/index.ts'
24
+ export * from './astro-avatar-group/index.ts'
25
+ export * from './astro-badge/index.ts'
26
+ export * from './astro-bottom-nav/index.ts'
27
+ export * from './astro-breadcrumbs/index.ts'
28
+ export * from './astro-button/index.ts'
29
+ export * from './astro-calendar/index.ts'
30
+ export * from './astro-card/index.ts'
31
+ export * from './astro-charts/index.ts'
32
+ export * from './astro-checkbox/index.ts'
33
+ export * from './astro-code-editor/index.ts'
34
+ export * from './astro-collapsible/index.ts'
35
+ export * from './astro-command/index.ts'
36
+ export * from './astro-composer/index.ts'
37
+ export * from './astro-conversation/index.ts'
38
+ export * from './astro-content-protection/index.ts'
39
+ export * from './astro-cookie-consent/index.ts'
40
+ export * from './astro-data-table/index.ts'
41
+ export * from './astro-date-picker/index.ts'
42
+ export * from './astro-device-frame/index.ts'
43
+ export * from './astro-dialog/index.ts'
44
+ export * from './astro-diff-viewer/index.ts'
45
+ export * from './astro-dropdown-menu/index.ts'
46
+ export * from './astro-emoji-picker/index.ts'
47
+ export * from './astro-feedback-dialog/index.ts'
48
+ export * from './astro-file-upload/index.ts'
49
+ export * from './astro-footer/index.ts'
50
+ export * from './astro-inline-editor/index.ts'
51
+ export * from './astro-input/index.ts'
52
+ export * from './astro-input-group/index.ts'
53
+ export * from './astro-install-prompt/index.ts'
54
+ export * from './astro-keyboard-shortcut/index.ts'
55
+ export * from './astro-language-selector/index.ts'
56
+ export * from './astro-location-selector/index.ts'
57
+ export * from './astro-markdown-renderer/index.ts'
58
+ export * from './astro-mascot/index.ts'
59
+ export * from './astro-mobile-nav/index.ts'
60
+ export * from './astro-navbar/index.ts'
61
+ export * from './astro-otp-input/index.ts'
62
+ export * from './astro-popover/index.ts'
63
+ export * from './astro-presence-indicator/index.ts'
64
+ export * from './astro-progress-display/index.ts'
65
+ export * from './astro-radio/index.ts'
66
+ export * from './astro-rating-scale/index.ts'
67
+ export * from './astro-reaction-bar/index.ts'
68
+ export * from './astro-resizable-layout/index.ts'
69
+ export * from './astro-rich-editor/index.ts'
70
+ export * from './astro-search-bar/index.ts'
71
+ export * from './astro-select/index.ts'
72
+ export * from './astro-sidebar/index.ts'
73
+ export * from './astro-skeleton/index.ts'
74
+ export * from './astro-slide-viewer/index.ts'
75
+ export * from './astro-status-indicator/index.ts'
76
+ export * from './astro-switch/index.ts'
77
+ export * from './astro-tabs/index.ts'
78
+ export * from './astro-textarea/index.ts'
79
+ export * from './astro-thread-view/index.ts'
80
+ export * from './astro-toast/index.ts'
81
+ export * from './astro-tooltip/index.ts'
82
+ export * from './astro-version-selector/index.ts'
83
+ export * from './astro-video-player/index.ts'
84
+
85
+ export * from './astro-table-of-contents/index.ts'
86
+ export * from './astro-carousel/index.ts'
87
+ export * from './astro-slider/index.ts'
88
+ export * from './astro-pagination/index.ts'
89
+
90
+ export * from './astro-callout/index.ts'
91
+ export * from './astro-steps/index.ts'
92
+ export * from './astro-file-tree/index.ts'
93
+ export * from './astro-icon-system/index.ts'
94
+ export * from './astro-skip-to-content/index.ts'
95
+ export * from './astro-code-block/index.ts'
96
+ export * from './astro-link-card/index.ts'
97
+ export * from './astro-card-grid/index.ts'
98
+
99
+
100
+ export * from './astro-payment/index.ts'
101
+
102
+
103
+
104
+ export * from './astro-command-input/index.ts'
105
+ export * from './astro-logger/index.ts'
106
+
107
+ // astro-analytics: selective re-export, not `export *` — astro-logger (above)
108
+ // already surfaces `createConsoleSink`, `createMockSink` and the
109
+ // `ConsoleSinkOptions` type from its own headless core, so a wildcard here
110
+ // collides (TS2308) and, worse, makes all three names unreachable at runtime
111
+ // (ambiguous star exports are dropped from the ESM namespace). Keep the
112
+ // pre-existing logger names stable — the same canonical surface react-meta
113
+ // exposes — and ship the analytics variants under aliases instead.
114
+ export {
115
+ AnalyticsScript,
116
+ createAnalytics,
117
+ createHttpSink,
118
+ createConsoleSink as createAnalyticsConsoleSink,
119
+ createMockSink as createAnalyticsMockSink,
120
+ createSession,
121
+ createIdentity,
122
+ createConsent,
123
+ createRedactor,
124
+ createMemoryStorage,
125
+ createLocalStorageAdapter,
126
+ createCookieAdapter,
127
+ resolveStorage,
128
+ campaignFingerprint,
129
+ uuidv4,
130
+ isUuidV4,
131
+ UUID_V4_RE,
132
+ PII_DENY_LIST,
133
+ PII_EXACT_KEYS,
134
+ REDACTED,
135
+ SCHEMA_VERSION,
136
+ DEFAULT_SESSION_TIMEOUT_MS,
137
+ createGA4Sink,
138
+ createGA4HttpSink,
139
+ createGA4ClientSdkSink,
140
+ createAppInsightsSink,
141
+ createPostHogSink,
142
+ createPostHogHttpSink,
143
+ createPostHogClientSdkSink,
144
+ startSessionReplay,
145
+ type Analytics,
146
+ type AnalyticsConfig,
147
+ type AnalyticsEvent,
148
+ type AnalyticsEventType,
149
+ type AnalyticsProperties,
150
+ type AnalyticsContext,
151
+ type AnalyticsSink,
152
+ type AnalyticsStorage,
153
+ type SinkInitContext,
154
+ type SinkDeliverContext,
155
+ type SessionConfig,
156
+ type SessionAPI,
157
+ type IdentityConfig,
158
+ type ConsentConfig,
159
+ type ConsentAPI,
160
+ type HttpSinkOptions,
161
+ type CallOptions,
162
+ type ConsoleSinkOptions as AnalyticsConsoleSinkOptions,
163
+ type MockSink,
164
+ type CreateMockSinkOptions,
165
+ type Redactor,
166
+ type GA4SinkOptions,
167
+ type GA4HttpOptions,
168
+ type GA4ClientSdkOptions,
169
+ type GA4ConsentBridge,
170
+ type ConsentState,
171
+ type GtagFn,
172
+ type AppInsightsSinkOptions,
173
+ type AppInsightsSinkMode,
174
+ type ClientSdkOptions,
175
+ type HttpOptions,
176
+ type AppInsightsLike,
177
+ type PostHogSinkMode,
178
+ type PostHogSinkOptions,
179
+ type PostHogHttpSinkOptions,
180
+ type PostHogClientSdkSinkOptions,
181
+ type SessionReplayOptions,
182
+ type SessionReplayHandle,
183
+ } from './astro-analytics/index.ts'
184
+
185
+ // Voice primitives — siblings of @refraction-ui/react-voice-pill / -waveform.
186
+ // Issues #191, #192.
187
+ export * from './astro-voice-pill/index.ts'
188
+ export * from './astro-waveform/index.ts'
189
+
190
+ // Issues #330-#334 — auth surface components
191
+ export * from './astro-segmented-control/index.ts'
192
+ export * from './astro-password-input/index.ts'
193
+ export * from './astro-social-auth-button/index.ts'
194
+ export * from './astro-separator/index.ts'
195
+ export * from './astro-empty-state/index.ts'
196
+
197
+ // easyloops design-parity wave 1 (Cluster C + D)
198
+ export * from './astro-wizard/index.ts'
199
+ export * from './astro-radial-gauge/index.ts'
200
+ export * from './astro-timeline/index.ts'
201
+ export * from './astro-checklist/index.ts'
202
+ export * from './astro-editor-tabs/index.ts'
203
+ export * from './astro-terminal/index.ts'
204
+ export * from './astro-test-results/index.ts'
205
+ export * from './astro-editor-status-bar/index.ts'
206
+
207
+ // easyloops design-parity wave 2 (Cluster A — video)
208
+ export * from './astro-video-tile/index.ts'
209
+ export * from './astro-video-grid/index.ts'
210
+ export * from './astro-call-controls/index.ts'
211
+ export * from './astro-live-captions/index.ts'
212
+ export * from './astro-live-transcript/index.ts'
213
+ export * from './astro-audio-room/index.ts'
214
+ export * from './astro-floating-reactions/index.ts'
215
+ export * from './astro-pre-call-lobby/index.ts'
216
+
217
+ // easyloops design-parity wave 3 (Cluster B — canvas)
218
+ export * from './astro-infinite-canvas/index.ts'
219
+ export * from './astro-sticky-note/index.ts'
220
+ export * from './astro-flow-editor/index.ts'
221
+ export * from './astro-graph-view/index.ts'
222
+ export * from './astro-live-cursors/index.ts'
223
+ export * from './astro-mini-map/index.ts'
224
+
225
+ // easyloops marketing components wave
226
+ export * from './astro-section-head/index.ts'
227
+ export * from './astro-stat-grid/index.ts'
228
+ export * from './astro-numbered-steps/index.ts'
229
+ export * from './astro-pricing-card/index.ts'
230
+ export * from './astro-brand-network-cell/index.ts'
231
+ export * from './astro-marquee-strip/index.ts'
232
+ export * from './astro-browser-chrome-mock/index.ts'
233
+ export * from './astro-mastery-bar/index.ts'
234
+ export * from './astro-audience-feature-card/index.ts'
235
+
236
+ // loopwyse pipeline components
237
+ export * from './astro-sortable-list/index.ts'
238
+ export * from './astro-kanban-board/index.ts'
239
+ export * from './astro-slot-picker/index.ts'
@@ -1,4 +1,4 @@
1
- import { COUNTRIES, LANGUAGES, detectCountry, detectLanguage } from '../i18n/index.ts'
1
+ import { COUNTRIES, LANGUAGES } from '../i18n/index.ts'
2
2
  import { generateId } from '../shared/index.ts'
3
3
 
4
4
  export interface LocationSelectorState {
@@ -21,7 +21,7 @@ export function createLocationSelector(options: LocationSelectorOptions = {}) {
21
21
  onLanguageChange,
22
22
  } = options
23
23
 
24
- let state: LocationSelectorState = {
24
+ const state: LocationSelectorState = {
25
25
  country: defaultCountry,
26
26
  language: defaultLanguage,
27
27
  }
@@ -34,6 +34,9 @@ export function createTelemetry(config: TelemetryConfig): Telemetry {
34
34
  const preset = resolvePreset(config.env)
35
35
  const sampleRate = config.sampleRate ?? preset.sampleRate
36
36
  const redactKeys = config.redactKeys ?? []
37
+ // Injection boundary: ambient time/randomness default here; inject `now`/`random` for determinism.
38
+ const now = config.now ?? (() => Date.now())
39
+ const random = config.random ?? (() => Math.random())
37
40
 
38
41
  const sinks = new Map<string, TelemetrySink>()
39
42
  /** Insertion-ordered sink names. */
@@ -71,7 +74,7 @@ export function createTelemetry(config: TelemetryConfig): Telemetry {
71
74
  function shouldSample(): boolean {
72
75
  if (sampleRate >= 1) return true
73
76
  if (sampleRate <= 0) return false
74
- return Math.random() < sampleRate
77
+ return random() < sampleRate
75
78
  }
76
79
 
77
80
  function dispatch(
@@ -134,7 +137,7 @@ export function createTelemetry(config: TelemetryConfig): Telemetry {
134
137
  const record: LogRecord = {
135
138
  level,
136
139
  message,
137
- timestamp: Date.now(),
140
+ timestamp: now(),
138
141
  app: config.app,
139
142
  env: config.env,
140
143
  context: merged,
@@ -164,13 +167,13 @@ export function createTelemetry(config: TelemetryConfig): Telemetry {
164
167
  },
165
168
 
166
169
  startSpan(name: string, attributes?: LogContext): Span {
167
- const startTime = Date.now()
170
+ const startTime = now()
168
171
  let ended = false
169
172
  return {
170
173
  end(opts?: { error?: unknown; attributes?: LogContext }): void {
171
174
  if (ended) return
172
175
  ended = true
173
- const endTime = Date.now()
176
+ const endTime = now()
174
177
  const merged = redact(
175
178
  { ...boundContext, ...attributes, ...opts?.attributes },
176
179
  redactKeys,
@@ -84,6 +84,10 @@ export interface TelemetryConfig {
84
84
  * PII / secrets, e.g. `['password', 'token', 'authorization']`.
85
85
  */
86
86
  redactKeys?: string[]
87
+ /** Clock for record timestamps and span timing (ms epoch). Default: ambient `Date.now()` — inject for deterministic tests. */
88
+ now?: () => number
89
+ /** RNG for sample-rate decisions. Default: ambient `Math.random` — inject for deterministic tests. */
90
+ random?: () => number
87
91
  }
88
92
 
89
93
  /** A logger bound to a context. Child loggers inherit + extend that context. */
@@ -1 +1,14 @@
1
- export {}
1
+ export {
2
+ createPagination,
3
+ clampPage,
4
+ getPaginationItems,
5
+ type PaginationItem,
6
+ type PaginationConfig,
7
+ type PaginationAPI,
8
+ } from './pagination.js'
9
+
10
+ export {
11
+ paginationVariants,
12
+ paginationItemVariants,
13
+ paginationEllipsisClass,
14
+ } from './pagination.styles.js'
@@ -0,0 +1,33 @@
1
+ import { cva } from '../shared/index.ts'
2
+
3
+ /** Row of pagination controls. */
4
+ export const paginationVariants = cva({
5
+ base: 'flex items-center gap-1',
6
+ })
7
+
8
+ /**
9
+ * A pagination button (prev / next / numbered page). The `state` variant
10
+ * carries the current-page treatment so adapters never inline these classes.
11
+ */
12
+ export const paginationItemVariants = cva({
13
+ base: [
14
+ 'inline-flex h-9 min-w-9 items-center justify-center rounded-md border px-3',
15
+ 'text-sm font-medium transition-colors',
16
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
17
+ 'focus-visible:ring-offset-2 focus-visible:ring-offset-background',
18
+ 'disabled:pointer-events-none disabled:opacity-50',
19
+ ].join(' '),
20
+ variants: {
21
+ state: {
22
+ current: 'border-primary bg-primary text-primary-foreground',
23
+ default: 'border-border bg-background text-foreground hover:bg-muted',
24
+ },
25
+ },
26
+ defaultVariants: {
27
+ state: 'default',
28
+ },
29
+ })
30
+
31
+ /** Ellipsis gap between page numbers (not interactive). */
32
+ export const paginationEllipsisClass =
33
+ 'inline-flex h-9 min-w-9 items-center justify-center text-sm text-muted-foreground'