@refraction-ui/astro 0.12.0 → 0.14.0

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 (162) hide show
  1. package/dist/astro-audience-feature-card/AudienceFeatureCard.astro +53 -0
  2. package/dist/astro-audience-feature-card/index.ts +1 -0
  3. package/dist/astro-audio-room/AudioRoom.astro +81 -0
  4. package/dist/astro-audio-room/index.ts +1 -0
  5. package/dist/astro-brand-network-cell/BrandNetworkCell.astro +77 -0
  6. package/dist/astro-brand-network-cell/index.ts +1 -0
  7. package/dist/astro-browser-chrome-mock/BrowserChromeMock.astro +62 -0
  8. package/dist/astro-browser-chrome-mock/index.ts +1 -0
  9. package/dist/astro-call-controls/CallControls.astro +57 -0
  10. package/dist/astro-call-controls/index.ts +1 -0
  11. package/dist/astro-checklist/Checklist.astro +76 -0
  12. package/dist/astro-checklist/index.ts +1 -0
  13. package/dist/astro-editor-status-bar/EditorStatusBar.astro +92 -0
  14. package/dist/astro-editor-status-bar/index.ts +1 -0
  15. package/dist/astro-editor-tabs/EditorTabs.astro +74 -0
  16. package/dist/astro-editor-tabs/index.ts +1 -0
  17. package/dist/astro-floating-reactions/FloatingReactions.astro +56 -0
  18. package/dist/astro-floating-reactions/index.ts +1 -0
  19. package/dist/astro-flow-editor/FlowEditor.astro +99 -0
  20. package/dist/astro-flow-editor/index.ts +3 -0
  21. package/dist/astro-graph-view/GraphView.astro +109 -0
  22. package/dist/astro-graph-view/index.ts +1 -0
  23. package/dist/astro-infinite-canvas/InfiniteCanvas.astro +43 -0
  24. package/dist/astro-infinite-canvas/index.ts +1 -0
  25. package/dist/astro-live-captions/LiveCaptions.astro +54 -0
  26. package/dist/astro-live-captions/index.ts +1 -0
  27. package/dist/astro-live-cursors/LiveCursors.astro +55 -0
  28. package/dist/astro-live-cursors/index.ts +1 -0
  29. package/dist/astro-live-transcript/LiveTranscript.astro +55 -0
  30. package/dist/astro-live-transcript/index.ts +1 -0
  31. package/dist/astro-marquee-strip/MarqueeStrip.astro +63 -0
  32. package/dist/astro-marquee-strip/index.ts +1 -0
  33. package/dist/astro-mastery-bar/MasteryBar.astro +56 -0
  34. package/dist/astro-mastery-bar/index.ts +1 -0
  35. package/dist/astro-mini-map/MiniMap.astro +74 -0
  36. package/dist/astro-mini-map/index.ts +1 -0
  37. package/dist/astro-numbered-steps/NumberedSteps.astro +47 -0
  38. package/dist/astro-numbered-steps/index.ts +1 -0
  39. package/dist/astro-pre-call-lobby/PreCallLobby.astro +202 -0
  40. package/dist/astro-pre-call-lobby/index.ts +1 -0
  41. package/dist/astro-pricing-card/PricingCard.astro +114 -0
  42. package/dist/astro-pricing-card/index.ts +1 -0
  43. package/dist/astro-radial-gauge/RadialGauge.astro +144 -0
  44. package/dist/astro-radial-gauge/index.ts +1 -0
  45. package/dist/astro-rating-scale/RatingScale.astro +73 -0
  46. package/dist/astro-rating-scale/index.ts +1 -0
  47. package/dist/astro-section-head/SectionHead.astro +44 -0
  48. package/dist/astro-section-head/index.ts +1 -0
  49. package/dist/astro-stat-grid/StatGrid.astro +46 -0
  50. package/dist/astro-stat-grid/index.ts +1 -0
  51. package/dist/astro-sticky-note/StickyNote.astro +55 -0
  52. package/dist/astro-sticky-note/index.ts +1 -0
  53. package/dist/astro-terminal/Terminal.astro +67 -0
  54. package/dist/astro-terminal/index.ts +1 -0
  55. package/dist/astro-test-results/TestResults.astro +76 -0
  56. package/dist/astro-test-results/index.ts +1 -0
  57. package/dist/astro-timeline/Timeline.astro +59 -0
  58. package/dist/astro-timeline/index.ts +1 -0
  59. package/dist/astro-video-grid/VideoGrid.astro +182 -0
  60. package/dist/astro-video-grid/index.ts +1 -0
  61. package/dist/astro-video-tile/VideoTile.astro +104 -0
  62. package/dist/astro-video-tile/index.ts +1 -0
  63. package/dist/astro-wizard/Wizard.astro +137 -0
  64. package/dist/astro-wizard/index.ts +1 -0
  65. package/dist/audience-feature-card/audience-feature-card.styles.ts +23 -0
  66. package/dist/audience-feature-card/audience-feature-card.ts +39 -0
  67. package/dist/audience-feature-card/index.ts +13 -0
  68. package/dist/audio-room/audio-room.styles.ts +88 -0
  69. package/dist/audio-room/audio-room.ts +70 -0
  70. package/dist/audio-room/index.ts +16 -0
  71. package/dist/brand-network-cell/brand-network-cell.styles.ts +46 -0
  72. package/dist/brand-network-cell/brand-network-cell.ts +35 -0
  73. package/dist/brand-network-cell/index.ts +14 -0
  74. package/dist/browser-chrome-mock/browser-chrome-mock.styles.ts +43 -0
  75. package/dist/browser-chrome-mock/browser-chrome-mock.ts +52 -0
  76. package/dist/browser-chrome-mock/index.ts +17 -0
  77. package/dist/call-controls/call-controls.styles.ts +63 -0
  78. package/dist/call-controls/call-controls.ts +79 -0
  79. package/dist/call-controls/index.ts +15 -0
  80. package/dist/checklist/checklist.styles.ts +76 -0
  81. package/dist/checklist/checklist.ts +62 -0
  82. package/dist/checklist/index.ts +18 -0
  83. package/dist/editor-status-bar/editor-status-bar.styles.ts +40 -0
  84. package/dist/editor-status-bar/editor-status-bar.ts +78 -0
  85. package/dist/editor-status-bar/index.ts +15 -0
  86. package/dist/editor-tabs/editor-tabs.styles.ts +52 -0
  87. package/dist/editor-tabs/editor-tabs.ts +82 -0
  88. package/dist/editor-tabs/index.ts +15 -0
  89. package/dist/floating-reactions/floating-reactions.styles.ts +54 -0
  90. package/dist/floating-reactions/floating-reactions.ts +85 -0
  91. package/dist/floating-reactions/index.ts +14 -0
  92. package/dist/flow-editor/flow-editor.styles.ts +56 -0
  93. package/dist/flow-editor/flow-editor.ts +126 -0
  94. package/dist/flow-editor/index.ts +18 -0
  95. package/dist/graph-view/graph-view.styles.ts +66 -0
  96. package/dist/graph-view/graph-view.ts +130 -0
  97. package/dist/graph-view/index.ts +21 -0
  98. package/dist/index.ts +32 -0
  99. package/dist/infinite-canvas/index.ts +17 -0
  100. package/dist/infinite-canvas/infinite-canvas.styles.ts +49 -0
  101. package/dist/infinite-canvas/infinite-canvas.ts +97 -0
  102. package/dist/live-captions/index.ts +13 -0
  103. package/dist/live-captions/live-captions.styles.ts +45 -0
  104. package/dist/live-captions/live-captions.ts +57 -0
  105. package/dist/live-cursors/index.ts +14 -0
  106. package/dist/live-cursors/live-cursors.styles.ts +41 -0
  107. package/dist/live-cursors/live-cursors.ts +73 -0
  108. package/dist/live-transcript/index.ts +16 -0
  109. package/dist/live-transcript/live-transcript.styles.ts +48 -0
  110. package/dist/live-transcript/live-transcript.ts +82 -0
  111. package/dist/marquee-strip/index.ts +14 -0
  112. package/dist/marquee-strip/marquee-strip.styles.ts +61 -0
  113. package/dist/marquee-strip/marquee-strip.ts +35 -0
  114. package/dist/mastery-bar/index.ts +15 -0
  115. package/dist/mastery-bar/mastery-bar.styles.ts +45 -0
  116. package/dist/mastery-bar/mastery-bar.ts +55 -0
  117. package/dist/mini-map/index.ts +16 -0
  118. package/dist/mini-map/mini-map.styles.ts +32 -0
  119. package/dist/mini-map/mini-map.ts +122 -0
  120. package/dist/numbered-steps/index.ts +16 -0
  121. package/dist/numbered-steps/numbered-steps.styles.ts +36 -0
  122. package/dist/numbered-steps/numbered-steps.ts +64 -0
  123. package/dist/pre-call-lobby/index.ts +22 -0
  124. package/dist/pre-call-lobby/pre-call-lobby.styles.ts +108 -0
  125. package/dist/pre-call-lobby/pre-call-lobby.ts +61 -0
  126. package/dist/pricing-card/index.ts +19 -0
  127. package/dist/pricing-card/pricing-card.styles.ts +71 -0
  128. package/dist/pricing-card/pricing-card.ts +37 -0
  129. package/dist/radial-gauge/index.ts +26 -0
  130. package/dist/radial-gauge/radial-gauge.styles.ts +75 -0
  131. package/dist/radial-gauge/radial-gauge.ts +183 -0
  132. package/dist/rating-scale/index.ts +16 -0
  133. package/dist/rating-scale/rating-scale.styles.ts +48 -0
  134. package/dist/rating-scale/rating-scale.ts +101 -0
  135. package/dist/section-head/index.ts +13 -0
  136. package/dist/section-head/section-head.styles.ts +30 -0
  137. package/dist/section-head/section-head.ts +28 -0
  138. package/dist/stat-grid/index.ts +13 -0
  139. package/dist/stat-grid/stat-grid.styles.ts +25 -0
  140. package/dist/stat-grid/stat-grid.ts +41 -0
  141. package/dist/sticky-note/index.ts +14 -0
  142. package/dist/sticky-note/sticky-note.styles.ts +37 -0
  143. package/dist/sticky-note/sticky-note.ts +47 -0
  144. package/dist/terminal/index.ts +13 -0
  145. package/dist/terminal/terminal.styles.ts +56 -0
  146. package/dist/terminal/terminal.ts +60 -0
  147. package/dist/test-results/index.ts +19 -0
  148. package/dist/test-results/test-results.styles.ts +93 -0
  149. package/dist/test-results/test-results.ts +83 -0
  150. package/dist/timeline/index.ts +22 -0
  151. package/dist/timeline/timeline.styles.ts +98 -0
  152. package/dist/timeline/timeline.ts +86 -0
  153. package/dist/video-grid/index.ts +16 -0
  154. package/dist/video-grid/video-grid.styles.ts +38 -0
  155. package/dist/video-grid/video-grid.ts +93 -0
  156. package/dist/video-tile/index.ts +17 -0
  157. package/dist/video-tile/video-tile.styles.ts +59 -0
  158. package/dist/video-tile/video-tile.ts +74 -0
  159. package/dist/wizard/index.ts +28 -0
  160. package/dist/wizard/wizard.styles.ts +147 -0
  161. package/dist/wizard/wizard.ts +128 -0
  162. package/package.json +33 -1
@@ -0,0 +1,202 @@
1
+ ---
2
+ import {
3
+ createPreCallLobby,
4
+ micLevelToBars,
5
+ preCallLobbyVariants,
6
+ preCallCameraVariants,
7
+ preCallCameraPlaceholderClass,
8
+ preCallDeviceRowClass,
9
+ preCallDeviceLabelClass,
10
+ preCallDeviceSelectClass,
11
+ preCallMicMeterClass,
12
+ preCallMicBarVariants,
13
+ preCallControlsRowClass,
14
+ preCallToggleVariants,
15
+ preCallJoinButtonClass,
16
+ type MediaDeviceOption,
17
+ } from '../pre-call-lobby/index.ts'
18
+ import { cn } from '../shared/index.ts'
19
+
20
+ const MIC_BAR_COUNT = 8
21
+
22
+ interface Props extends astroHTML.JSX.HTMLAttributes {
23
+ /** Whether the camera is on. */
24
+ cameraOn?: boolean
25
+ /** Whether the microphone is on. */
26
+ micOn?: boolean
27
+ /** Current microphone level (0..1). */
28
+ micLevel?: number
29
+ /** Available cameras. */
30
+ cameras?: MediaDeviceOption[]
31
+ /** Available microphones. */
32
+ microphones?: MediaDeviceOption[]
33
+ /** Available speakers. */
34
+ speakers?: MediaDeviceOption[]
35
+ /** Currently selected camera id. */
36
+ selectedCamera?: string
37
+ /** Currently selected microphone id. */
38
+ selectedMicrophone?: string
39
+ /** Currently selected speaker id. */
40
+ selectedSpeaker?: string
41
+ /** Label for the join button. */
42
+ joinLabel?: string
43
+ }
44
+
45
+ const {
46
+ cameraOn = true,
47
+ micOn = true,
48
+ micLevel = 0,
49
+ cameras = [],
50
+ microphones = [],
51
+ speakers = [],
52
+ selectedCamera,
53
+ selectedMicrophone,
54
+ selectedSpeaker,
55
+ joinLabel = 'Join',
56
+ class: className,
57
+ ...rest
58
+ } = Astro.props
59
+
60
+ const { ariaProps, dataAttributes } = createPreCallLobby({ cameraOn, micOn })
61
+ const litBars = micLevelToBars(micLevel, MIC_BAR_COUNT)
62
+ ---
63
+
64
+ <div class={cn(preCallLobbyVariants(), className)} {...ariaProps} {...dataAttributes} {...rest}>
65
+ <!-- Camera preview -->
66
+ <div class={preCallCameraVariants({ camera: cameraOn ? 'on' : 'off' })}>
67
+ {cameraOn ? (
68
+ <slot name="preview">
69
+ <div class={preCallCameraPlaceholderClass}>
70
+ <span class="text-xs">No preview</span>
71
+ </div>
72
+ </slot>
73
+ ) : (
74
+ <div class={preCallCameraPlaceholderClass}>
75
+ <svg
76
+ xmlns="http://www.w3.org/2000/svg"
77
+ width="40"
78
+ height="40"
79
+ viewBox="0 0 24 24"
80
+ fill="none"
81
+ stroke="currentColor"
82
+ stroke-width="1.5"
83
+ stroke-linecap="round"
84
+ stroke-linejoin="round"
85
+ aria-hidden="true"
86
+ >
87
+ <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
88
+ <circle cx="9" cy="7" r="4" />
89
+ <line x1="2" y1="2" x2="22" y2="22" />
90
+ </svg>
91
+ <span class="text-xs">Camera is off</span>
92
+ </div>
93
+ )}
94
+ </div>
95
+
96
+ <!-- Mic level meter -->
97
+ <div class="flex items-center gap-2">
98
+ <span class="text-xs text-muted-foreground">Mic</span>
99
+ <div class={preCallMicMeterClass} aria-label={`Mic level: ${litBars} of ${MIC_BAR_COUNT}`}>
100
+ {Array.from({ length: MIC_BAR_COUNT }, (_, i) => {
101
+ const isLit = i < litBars
102
+ const heightClass = i < 2 ? 'h-2' : i < 4 ? 'h-3' : i < 6 ? 'h-4' : 'h-5'
103
+ return (
104
+ <div
105
+ class={`${preCallMicBarVariants({ lit: isLit ? 'true' : 'false' })} ${heightClass}`}
106
+ data-lit={isLit ? 'true' : 'false'}
107
+ />
108
+ )
109
+ })}
110
+ </div>
111
+ </div>
112
+
113
+ <!-- Device selectors -->
114
+ {cameras.length > 0 && (
115
+ <div class={preCallDeviceRowClass}>
116
+ <label for="pcl-camera-select" class={preCallDeviceLabelClass}>Camera</label>
117
+ <select id="pcl-camera-select" class={preCallDeviceSelectClass} value={selectedCamera}>
118
+ {cameras.map((d) => (
119
+ <option value={d.id}>{d.label}</option>
120
+ ))}
121
+ </select>
122
+ </div>
123
+ )}
124
+
125
+ {microphones.length > 0 && (
126
+ <div class={preCallDeviceRowClass}>
127
+ <label for="pcl-mic-select" class={preCallDeviceLabelClass}>Microphone</label>
128
+ <select id="pcl-mic-select" class={preCallDeviceSelectClass} value={selectedMicrophone}>
129
+ {microphones.map((d) => (
130
+ <option value={d.id}>{d.label}</option>
131
+ ))}
132
+ </select>
133
+ </div>
134
+ )}
135
+
136
+ {speakers.length > 0 && (
137
+ <div class={preCallDeviceRowClass}>
138
+ <label for="pcl-speaker-select" class={preCallDeviceLabelClass}>Speaker</label>
139
+ <select id="pcl-speaker-select" class={preCallDeviceSelectClass} value={selectedSpeaker}>
140
+ {speakers.map((d) => (
141
+ <option value={d.id}>{d.label}</option>
142
+ ))}
143
+ </select>
144
+ </div>
145
+ )}
146
+
147
+ <!-- Controls row -->
148
+ <div class={preCallControlsRowClass}>
149
+ <button
150
+ type="button"
151
+ aria-label={cameraOn ? 'Turn camera off' : 'Turn camera on'}
152
+ aria-pressed={cameraOn}
153
+ class={preCallToggleVariants({ active: cameraOn ? 'true' : 'false' })}
154
+ >
155
+ <svg
156
+ xmlns="http://www.w3.org/2000/svg"
157
+ width="18"
158
+ height="18"
159
+ viewBox="0 0 24 24"
160
+ fill="none"
161
+ stroke="currentColor"
162
+ stroke-width="2"
163
+ stroke-linecap="round"
164
+ stroke-linejoin="round"
165
+ aria-hidden="true"
166
+ >
167
+ <path d="M23 7l-7 5 7 5V7z" />
168
+ <rect x="1" y="5" width="15" height="14" rx="2" ry="2" />
169
+ </svg>
170
+ </button>
171
+
172
+ <button
173
+ type="button"
174
+ aria-label={micOn ? 'Mute microphone' : 'Unmute microphone'}
175
+ aria-pressed={micOn}
176
+ class={preCallToggleVariants({ active: micOn ? 'true' : 'false' })}
177
+ >
178
+ <svg
179
+ xmlns="http://www.w3.org/2000/svg"
180
+ width="18"
181
+ height="18"
182
+ viewBox="0 0 24 24"
183
+ fill="none"
184
+ stroke="currentColor"
185
+ stroke-width="2"
186
+ stroke-linecap="round"
187
+ stroke-linejoin="round"
188
+ aria-hidden="true"
189
+ >
190
+ <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" />
191
+ <path d="M19 10v2a7 7 0 0 1-14 0v-2" />
192
+ <line x1="12" y1="19" x2="12" y2="23" />
193
+ <line x1="8" y1="23" x2="16" y2="23" />
194
+ </svg>
195
+ </button>
196
+ </div>
197
+
198
+ <!-- Join button -->
199
+ <button type="button" class={preCallJoinButtonClass}>
200
+ {joinLabel}
201
+ </button>
202
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,114 @@
1
+ ---
2
+ import {
3
+ createPricingCard,
4
+ pricingCardVariants,
5
+ pricingCardBadgeClass,
6
+ pricingCardNameClass,
7
+ pricingCardPriceClass,
8
+ pricingCardPeriodClass,
9
+ pricingCardDescriptionClass,
10
+ pricingCardFeatureListClass,
11
+ pricingCardFeatureRowClass,
12
+ pricingCardFeatureTickClass,
13
+ pricingCtaVariants,
14
+ type PricingCtaVariant,
15
+ } from '../pricing-card/index.ts'
16
+ import { cn } from '../shared/index.ts'
17
+
18
+ interface Props extends astroHTML.JSX.HTMLAttributes {
19
+ /** Optional badge label shown above the plan name (e.g. "Most popular"). */
20
+ badge?: string
21
+ /** Plan name (e.g. "Pro", "Starter"). */
22
+ name: string
23
+ /** Price string (e.g. "$29", "Free"). */
24
+ price: string
25
+ /** Billing period or qualifier (e.g. "/ month"). */
26
+ period?: string
27
+ /** Short marketing description. */
28
+ description?: string
29
+ /** List of included features to render as a checklist. */
30
+ features: string[]
31
+ /** CTA button/link label. */
32
+ cta: string
33
+ /** Visual variant for the CTA. */
34
+ ctaVariant?: PricingCtaVariant
35
+ /** When provided, the CTA renders as an `<a>` tag. */
36
+ ctaHref?: string
37
+ /** Highlights the card with a primary ring. */
38
+ featured?: boolean
39
+ }
40
+
41
+ const {
42
+ badge,
43
+ name,
44
+ price,
45
+ period,
46
+ description,
47
+ features,
48
+ cta,
49
+ ctaVariant = 'default',
50
+ ctaHref,
51
+ featured = false,
52
+ class: className,
53
+ ...rest
54
+ } = Astro.props
55
+
56
+ const { ariaProps, dataAttributes } = createPricingCard({ featured })
57
+ const ctaClass = pricingCtaVariants({ variant: ctaVariant })
58
+ ---
59
+
60
+ <div
61
+ class={cn(pricingCardVariants({ featured: featured ? 'true' : 'false' }), className)}
62
+ {...ariaProps}
63
+ {...dataAttributes}
64
+ {...rest}
65
+ >
66
+ {badge && <span class={pricingCardBadgeClass}>{badge}</span>}
67
+
68
+ <p class={pricingCardNameClass}>{name}</p>
69
+
70
+ <div class="mt-4 flex items-baseline gap-1">
71
+ <span class={pricingCardPriceClass}>{price}</span>
72
+ {period && <span class={pricingCardPeriodClass}>{period}</span>}
73
+ </div>
74
+
75
+ {description && <p class={`mt-2 ${pricingCardDescriptionClass}`}>{description}</p>}
76
+
77
+ <ul class={`mt-6 ${pricingCardFeatureListClass}`}>
78
+ {
79
+ features.map((feature) => (
80
+ <li class={pricingCardFeatureRowClass}>
81
+ <svg
82
+ class={pricingCardFeatureTickClass}
83
+ viewBox="0 0 16 16"
84
+ fill="none"
85
+ aria-hidden="true"
86
+ >
87
+ <path
88
+ d="M3 8l3.5 3.5L13 4.5"
89
+ stroke="currentColor"
90
+ stroke-width="1.75"
91
+ stroke-linecap="round"
92
+ stroke-linejoin="round"
93
+ />
94
+ </svg>
95
+ {feature}
96
+ </li>
97
+ ))
98
+ }
99
+ </ul>
100
+
101
+ <div class="mt-6">
102
+ {
103
+ ctaHref ? (
104
+ <a href={ctaHref} class={ctaClass}>
105
+ {cta}
106
+ </a>
107
+ ) : (
108
+ <button type="button" class={ctaClass}>
109
+ {cta}
110
+ </button>
111
+ )
112
+ }
113
+ </div>
114
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,144 @@
1
+ ---
2
+ import {
3
+ clampValue,
4
+ valueToFraction,
5
+ gaugeStrokeDashoffset,
6
+ resolveZoneTone,
7
+ createRadialGauge,
8
+ radialGaugeRootVariants,
9
+ gaugeTrackClass,
10
+ gaugeArcClass,
11
+ gaugeArcToneVariants,
12
+ gaugeLabelClass,
13
+ gaugeSublabelClass,
14
+ GAUGE_SIZE_PX,
15
+ GAUGE_LABEL_FONT_SIZE,
16
+ GAUGE_SUBLABEL_FONT_SIZE,
17
+ type GaugeSize,
18
+ type GaugeZone,
19
+ } from '../radial-gauge/index.ts'
20
+ import { cn } from '../shared/index.ts'
21
+
22
+ interface Props extends astroHTML.JSX.SVGAttributes {
23
+ /** Current value. */
24
+ value: number
25
+ /** Minimum value. Defaults to 0. */
26
+ min?: number
27
+ /** Maximum value. Defaults to 100. */
28
+ max?: number
29
+ /** Visual size of the gauge. Defaults to 'md'. */
30
+ size?: GaugeSize
31
+ /** Stroke thickness in px. Defaults to 8. */
32
+ thickness?: number
33
+ /** Primary center label. When omitted and `showValue` is true, the numeric value is shown. */
34
+ label?: string
35
+ /** Secondary label shown below the primary label. */
36
+ sublabel?: string
37
+ /**
38
+ * Threshold zones that colour the arc based on the current value.
39
+ * List in ascending `upTo` order for clarity (internally sorted).
40
+ */
41
+ zones?: GaugeZone[]
42
+ /** Show the numeric value in the center when no explicit label is given. Defaults to true. */
43
+ showValue?: boolean
44
+ }
45
+
46
+ const {
47
+ value,
48
+ min = 0,
49
+ max = 100,
50
+ size = 'md',
51
+ thickness = 8,
52
+ label,
53
+ sublabel,
54
+ zones,
55
+ showValue = true,
56
+ class: className,
57
+ ...rest
58
+ } = Astro.props
59
+
60
+ const diameter = GAUGE_SIZE_PX[size]
61
+ const cx = diameter / 2
62
+ const cy = diameter / 2
63
+ const r = cx - thickness / 2
64
+
65
+ const clamped = clampValue(value, min, max)
66
+ const fraction = valueToFraction(clamped, min, max)
67
+
68
+ const circumference = 2 * Math.PI * r
69
+ const dashoffset = gaugeStrokeDashoffset(fraction, circumference)
70
+
71
+ const tone = zones && zones.length > 0 ? resolveZoneTone(clamped, zones, max) : 'default'
72
+
73
+ const { ariaProps, dataAttributes } = createRadialGauge({ value, min, max, size })
74
+
75
+ const centerLabel = label ?? (showValue ? String(clamped) : null)
76
+ const labelFontSize = GAUGE_LABEL_FONT_SIZE[size]
77
+ const sublabelFontSize = GAUGE_SUBLABEL_FONT_SIZE[size]
78
+ const labelDy = sublabel ? -sublabelFontSize * 0.8 : 0
79
+ ---
80
+
81
+ <svg
82
+ width={diameter}
83
+ height={diameter}
84
+ viewBox={`0 0 ${diameter} ${diameter}`}
85
+ role="meter"
86
+ aria-valuenow={ariaProps['aria-valuenow']}
87
+ aria-valuemin={ariaProps['aria-valuemin']}
88
+ aria-valuemax={ariaProps['aria-valuemax']}
89
+ class={cn(radialGaugeRootVariants({ size }), className)}
90
+ {...dataAttributes}
91
+ {...rest}
92
+ >
93
+ {/* Background track */}
94
+ <circle
95
+ cx={cx}
96
+ cy={cy}
97
+ r={r}
98
+ stroke-width={thickness}
99
+ class={gaugeTrackClass}
100
+ />
101
+
102
+ {/* Value arc */}
103
+ <circle
104
+ cx={cx}
105
+ cy={cy}
106
+ r={r}
107
+ stroke-width={thickness}
108
+ stroke-dasharray={`${circumference} ${circumference}`}
109
+ stroke-dashoffset={dashoffset}
110
+ stroke-linecap="round"
111
+ transform={`rotate(-90 ${cx} ${cy})`}
112
+ class={cn(gaugeArcClass, gaugeArcToneVariants({ tone }))}
113
+ />
114
+
115
+ {/* Center label */}
116
+ {centerLabel != null && (
117
+ <text
118
+ x={cx}
119
+ y={cy}
120
+ text-anchor="middle"
121
+ dominant-baseline="central"
122
+ font-size={labelFontSize}
123
+ dy={labelDy}
124
+ class={gaugeLabelClass}
125
+ >
126
+ {centerLabel}
127
+ </text>
128
+ )}
129
+
130
+ {/* Sub-label */}
131
+ {sublabel != null && (
132
+ <text
133
+ x={cx}
134
+ y={cy}
135
+ text-anchor="middle"
136
+ dominant-baseline="central"
137
+ font-size={sublabelFontSize}
138
+ dy={labelDy + labelFontSize * 1.1}
139
+ class={gaugeSublabelClass}
140
+ >
141
+ {sublabel}
142
+ </text>
143
+ )}
144
+ </svg>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,73 @@
1
+ ---
2
+ import {
3
+ createRatingScale,
4
+ resolveRatingPoints,
5
+ ratingScaleVariants,
6
+ ratingScaleTrackClass,
7
+ ratingScaleItemVariants,
8
+ ratingScaleLabelClass,
9
+ type RatingScaleSize,
10
+ type RatingScalePoint,
11
+ } from '../rating-scale/index.ts'
12
+ import { cn } from '../shared/index.ts'
13
+
14
+ interface Props extends astroHTML.JSX.HTMLAttributes {
15
+ /** Selected value. */
16
+ value?: number
17
+ /** Number of points (1..count). Ignored when `points` is provided. */
18
+ count?: number
19
+ /** Explicit points with accessible labels. */
20
+ points?: RatingScalePoint[]
21
+ /** Label shown before the scale (low end). */
22
+ minLabel?: string
23
+ /** Label shown after the scale (high end). */
24
+ maxLabel?: string
25
+ /** Visual size. */
26
+ size?: RatingScaleSize
27
+ /** Disables the whole scale. */
28
+ disabled?: boolean
29
+ }
30
+
31
+ const {
32
+ value,
33
+ count = 5,
34
+ points,
35
+ minLabel,
36
+ maxLabel,
37
+ size = 'md',
38
+ disabled = false,
39
+ class: className,
40
+ ...rest
41
+ } = Astro.props
42
+
43
+ const resolved = resolveRatingPoints(points, count)
44
+ const selectedIndex = resolved.findIndex((p) => p.value === value)
45
+ const tabbableIndex = selectedIndex === -1 ? 0 : selectedIndex
46
+ const { ariaProps, dataAttributes } = createRatingScale({ value, size })
47
+ ---
48
+
49
+ <div class={cn(ratingScaleVariants({ size }), className)} {...ariaProps} {...dataAttributes} {...rest}>
50
+ {minLabel && <span class={ratingScaleLabelClass}>{minLabel}</span>}
51
+ <div class={ratingScaleTrackClass}>
52
+ {
53
+ resolved.map((point, index) => {
54
+ const checked = point.value === value
55
+ return (
56
+ <button
57
+ type="button"
58
+ role="radio"
59
+ aria-checked={checked}
60
+ aria-label={point.label ?? String(point.value)}
61
+ tabindex={index === tabbableIndex ? 0 : -1}
62
+ disabled={disabled}
63
+ data-state={checked ? 'checked' : 'unchecked'}
64
+ class={ratingScaleItemVariants({ size, state: checked ? 'checked' : 'unchecked' })}
65
+ >
66
+ {point.label ?? point.value}
67
+ </button>
68
+ )
69
+ })
70
+ }
71
+ </div>
72
+ {maxLabel && <span class={ratingScaleLabelClass}>{maxLabel}</span>}
73
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,44 @@
1
+ ---
2
+ import {
3
+ createSectionHead,
4
+ sectionHeadVariants,
5
+ sectionHeadKickerClass,
6
+ sectionHeadTitleClass,
7
+ sectionHeadLedeClass,
8
+ type SectionHeadAlign,
9
+ } from '../section-head/index.ts'
10
+ import { cn } from '../shared/index.ts'
11
+
12
+ interface Props extends astroHTML.JSX.HTMLAttributes {
13
+ /** Optional eyebrow / kicker rendered above the title. */
14
+ kicker?: string
15
+ /** Primary heading content. Falls back to the default slot when not set. */
16
+ title?: string
17
+ /** Optional lede paragraph rendered below the title. */
18
+ lede?: string
19
+ /** Horizontal alignment of the cluster. */
20
+ align?: SectionHeadAlign
21
+ /** Override the heading element rendered for the title. Defaults to `h2`. */
22
+ as?: 'h1' | 'h2' | 'h3'
23
+ }
24
+
25
+ const {
26
+ kicker,
27
+ title,
28
+ lede,
29
+ align = 'center',
30
+ as: Tag = 'h2',
31
+ class: className,
32
+ ...rest
33
+ } = Astro.props
34
+
35
+ const { dataAttributes } = createSectionHead({ align })
36
+ ---
37
+
38
+ <div class={cn(sectionHeadVariants({ align }), className)} {...dataAttributes} {...rest}>
39
+ {kicker && <p class={sectionHeadKickerClass}>{kicker}</p>}
40
+ <Tag class={sectionHeadTitleClass}>
41
+ {title ?? <slot />}
42
+ </Tag>
43
+ {lede && <p class={sectionHeadLedeClass}>{lede}</p>}
44
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,46 @@
1
+ ---
2
+ import {
3
+ createStatGrid,
4
+ statColumns,
5
+ statGridVariants,
6
+ statItemClass,
7
+ statValueClass,
8
+ statLabelClass,
9
+ type StatItem,
10
+ } from '../stat-grid/index.ts'
11
+ import { cn } from '../shared/index.ts'
12
+
13
+ interface Props extends astroHTML.JSX.HTMLAttributes {
14
+ /** The stat items to display in the grid (value and label as strings). */
15
+ items: StatItem[]
16
+ /**
17
+ * Number of columns. Defaults to statColumns(items.length):
18
+ * 1 item → 1, 2 items → 2, 3+ items → 3.
19
+ */
20
+ columns?: number
21
+ }
22
+
23
+ const { items, columns, class: className, ...rest } = Astro.props
24
+
25
+ const cols = columns ?? statColumns(items.length)
26
+ const colsKey = String(cols) as '1' | '2' | '3'
27
+ const { ariaProps, dataAttributes } = createStatGrid()
28
+ const gridStyle = `grid-template-columns:repeat(${cols}, 1fr)`
29
+ ---
30
+
31
+ <div
32
+ class={cn(statGridVariants({ columns: colsKey }), className)}
33
+ style={gridStyle}
34
+ {...ariaProps}
35
+ {...dataAttributes}
36
+ {...rest}
37
+ >
38
+ {
39
+ items.map((item) => (
40
+ <div role="listitem" class={statItemClass}>
41
+ <span class={statValueClass}>{item.value}</span>
42
+ <span class={statLabelClass}>{item.label}</span>
43
+ </div>
44
+ ))
45
+ }
46
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,55 @@
1
+ ---
2
+ import {
3
+ createStickyNote,
4
+ stickyNoteVariants,
5
+ stickyNoteTextClass,
6
+ stickyNoteAuthorClass,
7
+ type StickyNoteColor,
8
+ } from '../sticky-note/index.ts'
9
+ import { cn } from '../shared/index.ts'
10
+
11
+ interface Props extends astroHTML.JSX.HTMLAttributes {
12
+ /** Color of the sticky note. */
13
+ color?: StickyNoteColor
14
+ /** Text content of the note. */
15
+ text?: string
16
+ /** Optional author name shown in the note footer. */
17
+ author?: string
18
+ /** Absolute x position in pixels (for board/canvas placement). */
19
+ x?: number
20
+ /** Absolute y position in pixels (for board/canvas placement). */
21
+ y?: number
22
+ }
23
+
24
+ const {
25
+ color = 'yellow',
26
+ text,
27
+ author,
28
+ x,
29
+ y,
30
+ class: className,
31
+ ...rest
32
+ } = Astro.props
33
+
34
+ const { ariaProps, dataAttributes } = createStickyNote({ color })
35
+
36
+ const positionStyle =
37
+ x !== undefined && y !== undefined
38
+ ? `position:absolute;left:${x}px;top:${y}px;`
39
+ : ''
40
+ ---
41
+
42
+ <div
43
+ class={cn(stickyNoteVariants({ color }), className)}
44
+ style={positionStyle || undefined}
45
+ {...ariaProps}
46
+ {...dataAttributes}
47
+ {...rest}
48
+ >
49
+ {text ? (
50
+ <p class={`${stickyNoteTextClass} whitespace-pre-wrap`}>{text}</p>
51
+ ) : (
52
+ <p class={`${stickyNoteTextClass} whitespace-pre-wrap`}><slot /></p>
53
+ )}
54
+ {author && <span class={stickyNoteAuthorClass}>{author}</span>}
55
+ </div>
@@ -0,0 +1 @@
1
+ export {}