@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,99 @@
1
+ ---
2
+ import {
3
+ createFlowEditor,
4
+ edgePath,
5
+ nodeById,
6
+ flowEditorVariants,
7
+ flowNodeVariants,
8
+ flowNodeLabelClass,
9
+ flowEdgePathClass,
10
+ flowEdgeLabelClass,
11
+ type FlowNode,
12
+ type FlowEdge,
13
+ } from '../flow-editor/index.ts'
14
+ import { cn } from '../shared/index.ts'
15
+
16
+ interface Props extends astroHTML.JSX.HTMLAttributes {
17
+ /** The nodes to render. */
18
+ nodes: FlowNode[]
19
+ /** The directed edges connecting nodes. */
20
+ edges: FlowEdge[]
21
+ /** Id of the selected node. */
22
+ selectedId?: string
23
+ }
24
+
25
+ const {
26
+ nodes,
27
+ edges,
28
+ selectedId,
29
+ class: className,
30
+ ...rest
31
+ } = Astro.props
32
+
33
+ const { ariaProps, dataAttributes } = createFlowEditor()
34
+
35
+ const DEFAULT_W = 160
36
+ const DEFAULT_H = 48
37
+ ---
38
+
39
+ <!--
40
+ Astro renders a static snapshot of the graph. The outer div uses a relative
41
+ bg-grid container (no InfiniteCanvas import — the .astro canvas is not trivial
42
+ to SSR without its own island machinery). Pan/zoom is a React-only feature.
43
+ -->
44
+ <div
45
+ class={cn(flowEditorVariants(), 'bg-[size:24px_24px] bg-[image:linear-gradient(to_right,hsl(var(--border))_1px,transparent_1px),linear-gradient(to_bottom,hsl(var(--border))_1px,transparent_1px)]', className)}
46
+ {...ariaProps}
47
+ {...dataAttributes}
48
+ {...rest}
49
+ >
50
+ <!-- SVG edge layer -->
51
+ <svg
52
+ class="absolute inset-0 w-full h-full overflow-visible text-muted-foreground pointer-events-none"
53
+ aria-hidden="true"
54
+ >
55
+ {
56
+ edges.map((edge) => {
57
+ const src = nodeById(nodes, edge.source)
58
+ const tgt = nodeById(nodes, edge.target)
59
+ if (!src || !tgt) return null
60
+ const d = edgePath(src, tgt)
61
+ const midX = (src.x + (src.width ?? DEFAULT_W) + tgt.x) / 2
62
+ const midY = (src.y + (src.height ?? DEFAULT_H) / 2 + tgt.y + (tgt.height ?? DEFAULT_H) / 2) / 2
63
+ return (
64
+ <g>
65
+ <path d={d} class={flowEdgePathClass} />
66
+ {edge.label != null && (
67
+ <text
68
+ x={midX}
69
+ y={midY - 4}
70
+ text-anchor="middle"
71
+ class={flowEdgeLabelClass}
72
+ >
73
+ {edge.label}
74
+ </text>
75
+ )}
76
+ </g>
77
+ )
78
+ })
79
+ }
80
+ </svg>
81
+
82
+ <!-- Node layer -->
83
+ {
84
+ nodes.map((node) => {
85
+ const isSelected = node.selected || node.id === selectedId
86
+ const w = node.width ?? DEFAULT_W
87
+ const h = node.height ?? DEFAULT_H
88
+ return (
89
+ <div
90
+ class={cn(flowNodeVariants({ selected: isSelected ? 'true' : 'false' }))}
91
+ style={`left:${node.x}px;top:${node.y}px;width:${w}px;height:${h}px`}
92
+ aria-label={node.label}
93
+ >
94
+ <span class={flowNodeLabelClass}>{node.label}</span>
95
+ </div>
96
+ )
97
+ })
98
+ }
99
+ </div>
@@ -0,0 +1,3 @@
1
+ // Astro components are imported directly as .astro files; this barrel is a
2
+ // conventional entry-point placeholder for the package.
3
+ export {}
@@ -0,0 +1,109 @@
1
+ ---
2
+ import {
3
+ createGraphView,
4
+ graphEdgePath,
5
+ summarizeStates,
6
+ graphViewVariants,
7
+ graphNodeVariants,
8
+ graphNodeLabelClass,
9
+ graphEdgeClass,
10
+ graphLegendChipVariants,
11
+ type GraphNode,
12
+ type GraphEdge,
13
+ type GraphNodeState,
14
+ } from '../graph-view/index.ts'
15
+ import { cn } from '../shared/index.ts'
16
+
17
+ interface Props extends astroHTML.JSX.HTMLAttributes {
18
+ /** Nodes to render. */
19
+ nodes: GraphNode[]
20
+ /** Directed edges connecting nodes. */
21
+ edges: GraphEdge[]
22
+ /** Show a legend summarising mastery-state counts. */
23
+ showLegend?: boolean
24
+ }
25
+
26
+ const { nodes, edges, showLegend = false, class: className, ...rest } = Astro.props
27
+
28
+ const api = createGraphView()
29
+ const summary = summarizeStates(nodes)
30
+
31
+ const STATE_LABELS: Record<GraphNodeState, string> = {
32
+ mastered: 'Mastered',
33
+ 'in-progress': 'In Progress',
34
+ 'not-started': 'Not Started',
35
+ highlight: 'Highlight',
36
+ }
37
+
38
+ const LEGEND_ORDER: GraphNodeState[] = ['mastered', 'in-progress', 'not-started', 'highlight']
39
+
40
+ const padding = 80
41
+ const xs = nodes.map((n) => n.x)
42
+ const ys = nodes.map((n) => n.y)
43
+ const svgWidth = nodes.length === 0 ? 400 : Math.max(...xs) + padding * 2
44
+ const svgHeight = nodes.length === 0 ? 300 : Math.max(...ys) + padding * 2
45
+
46
+ // Build node lookup for edge resolution
47
+ const nodeMap = new Map<string, GraphNode>(nodes.map((n) => [n.id, n]))
48
+ ---
49
+
50
+ <div
51
+ class={cn(graphViewVariants(), className)}
52
+ {...api.ariaProps}
53
+ {...api.dataAttributes}
54
+ {...rest}
55
+ >
56
+ <div class="relative" style={`width:${svgWidth}px;height:${svgHeight}px;`}>
57
+ <!-- SVG edge layer -->
58
+ <svg
59
+ width={svgWidth}
60
+ height={svgHeight}
61
+ aria-hidden="true"
62
+ style="position:absolute;top:0;left:0;pointer-events:none;"
63
+ >
64
+ {
65
+ edges.map((edge) => {
66
+ const source = nodeMap.get(edge.source)
67
+ const target = nodeMap.get(edge.target)
68
+ if (!source || !target) return null
69
+ return <path d={graphEdgePath(source, target)} class={graphEdgeClass} />
70
+ })
71
+ }
72
+ </svg>
73
+
74
+ <!-- Node chips -->
75
+ {
76
+ nodes.map((node) => {
77
+ const state: GraphNodeState = node.state ?? 'not-started'
78
+ return (
79
+ <span
80
+ data-state={state}
81
+ aria-label={node.label}
82
+ class={graphNodeVariants({ state, interactive: 'false' })}
83
+ style={`left:${node.x}px;top:${node.y}px;`}
84
+ >
85
+ <span class={graphNodeLabelClass}>{node.label}</span>
86
+ </span>
87
+ )
88
+ })
89
+ }
90
+ </div>
91
+
92
+ <!-- Optional legend -->
93
+ {
94
+ showLegend && (
95
+ <div
96
+ role="list"
97
+ aria-label="Graph legend"
98
+ class="flex flex-wrap gap-1.5 p-3"
99
+ >
100
+ {LEGEND_ORDER.filter((s) => summary[s] > 0).map((s) => (
101
+ <span role="listitem" class={graphLegendChipVariants({ state: s })}>
102
+ {STATE_LABELS[s]}
103
+ <span class="opacity-70">{summary[s]}</span>
104
+ </span>
105
+ ))}
106
+ </div>
107
+ )
108
+ }
109
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,43 @@
1
+ ---
2
+ import {
3
+ createInfiniteCanvas,
4
+ transformToCss,
5
+ infiniteCanvasVariants,
6
+ canvasContentClass,
7
+ } from '../infinite-canvas/index.ts'
8
+ import { cn } from '../shared/index.ts'
9
+
10
+ interface Props extends astroHTML.JSX.HTMLAttributes {
11
+ /** Zoom level (default 1). */
12
+ zoom?: number
13
+ /** Pan offset x (default 0). */
14
+ x?: number
15
+ /** Pan offset y (default 0). */
16
+ y?: number
17
+ /** Show a dot-grid background. */
18
+ showGrid?: boolean
19
+ }
20
+
21
+ const {
22
+ zoom = 1,
23
+ x = 0,
24
+ y = 0,
25
+ showGrid = false,
26
+ class: className,
27
+ ...rest
28
+ } = Astro.props
29
+
30
+ const { ariaProps, dataAttributes } = createInfiniteCanvas({ zoom })
31
+ const transform = transformToCss({ zoom, x, y })
32
+ ---
33
+
34
+ <div
35
+ class={cn(infiniteCanvasVariants({ grid: showGrid ? 'true' : 'false' }), className)}
36
+ {...ariaProps}
37
+ {...dataAttributes}
38
+ {...rest}
39
+ >
40
+ <div class={canvasContentClass} style={`transform:${transform};transform-origin:0 0`}>
41
+ <slot />
42
+ </div>
43
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,54 @@
1
+ ---
2
+ import {
3
+ visibleCues,
4
+ createLiveCaptions,
5
+ liveCaptionsVariants,
6
+ liveCaptionsCueVariants,
7
+ liveCaptionsSpeakerClass,
8
+ type CaptionCue,
9
+ } from '../live-captions/index.ts'
10
+ import { cn } from '../shared/index.ts'
11
+
12
+ interface Props extends astroHTML.JSX.HTMLAttributes {
13
+ /** The full ordered list of caption cues. */
14
+ cues: CaptionCue[]
15
+ /**
16
+ * Maximum number of cue lines to display at once.
17
+ * @default 2
18
+ */
19
+ maxLines?: number
20
+ /**
21
+ * How the container is positioned in the layout.
22
+ * @default 'static'
23
+ */
24
+ position?: 'static' | 'absolute'
25
+ }
26
+
27
+ const {
28
+ cues,
29
+ maxLines = 2,
30
+ position = 'static',
31
+ class: className,
32
+ ...rest
33
+ } = Astro.props
34
+
35
+ const shown = visibleCues(cues, maxLines)
36
+ const { ariaProps, dataAttributes } = createLiveCaptions()
37
+ ---
38
+
39
+ <div class={cn(liveCaptionsVariants({ position }), className)} {...ariaProps} {...dataAttributes} {...rest}>
40
+ {
41
+ shown.map((cue) => (
42
+ <p class={liveCaptionsCueVariants({ interim: cue.final === false ? 'true' : 'false' })}>
43
+ {cue.speaker ? (
44
+ <>
45
+ <span class={liveCaptionsSpeakerClass}>{cue.speaker}</span>
46
+ {`: ${cue.text}`}
47
+ </>
48
+ ) : (
49
+ cue.text
50
+ )}
51
+ </p>
52
+ ))
53
+ }
54
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,55 @@
1
+ ---
2
+ import {
3
+ createLiveCursors,
4
+ assignCursorColor,
5
+ liveCursorsVariants,
6
+ cursorWrapperClass,
7
+ cursorArrowClass,
8
+ cursorLabelClass,
9
+ type CursorData,
10
+ } from '../live-cursors/index.ts'
11
+ import { cn } from '../shared/index.ts'
12
+
13
+ interface Props extends astroHTML.JSX.HTMLAttributes {
14
+ /** Array of collaborator cursor data to render. */
15
+ cursors: CursorData[]
16
+ }
17
+
18
+ const { cursors, class: className, ...rest } = Astro.props
19
+
20
+ const { ariaProps, dataAttributes } = createLiveCursors()
21
+ ---
22
+
23
+ <div class={cn(liveCursorsVariants(), className)} {...ariaProps} {...dataAttributes} {...rest}>
24
+ {
25
+ cursors.map((cursor, index) => {
26
+ const color = cursor.color ?? assignCursorColor(cursor.id, index)
27
+ return (
28
+ <div
29
+ class={cursorWrapperClass}
30
+ style={`left:${cursor.x}px;top:${cursor.y}px`}
31
+ data-cursor-name={cursor.name}
32
+ >
33
+ <svg
34
+ class={cursorArrowClass}
35
+ viewBox="0 0 20 20"
36
+ fill="none"
37
+ xmlns="http://www.w3.org/2000/svg"
38
+ aria-hidden="true"
39
+ style={`fill:${color}`}
40
+ >
41
+ <path
42
+ d="M3 2L17 9.5L10.5 11.5L8 18L3 2Z"
43
+ stroke="white"
44
+ stroke-width="1.5"
45
+ stroke-linejoin="round"
46
+ />
47
+ </svg>
48
+ <span class={cursorLabelClass} style={`background-color:${color}`}>
49
+ {cursor.name}
50
+ </span>
51
+ </div>
52
+ )
53
+ })
54
+ }
55
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,55 @@
1
+ ---
2
+ import {
3
+ createLiveTranscript,
4
+ groupConsecutiveBySpeaker,
5
+ liveTranscriptVariants,
6
+ transcriptBlockVariants,
7
+ transcriptSpeakerRowClass,
8
+ transcriptSpeakerNameClass,
9
+ transcriptTimestampClass,
10
+ transcriptTextLineClass,
11
+ type TranscriptEntry,
12
+ } from '../live-transcript/index.ts'
13
+ import { cn } from '../shared/index.ts'
14
+
15
+ interface Props extends astroHTML.JSX.HTMLAttributes {
16
+ /** The ordered list of transcript entries to display. */
17
+ entries: TranscriptEntry[]
18
+ /** Tightens spacing between speaker blocks. */
19
+ compact?: boolean
20
+ }
21
+
22
+ const { entries, compact = false, class: className, ...rest } = Astro.props
23
+
24
+ const compactVariant = compact ? 'true' : 'false'
25
+ const blocks = groupConsecutiveBySpeaker(entries)
26
+ const { ariaProps, dataAttributes } = createLiveTranscript()
27
+ ---
28
+
29
+ <div
30
+ class={cn(liveTranscriptVariants({ compact: compactVariant }), className)}
31
+ {...ariaProps}
32
+ {...dataAttributes}
33
+ {...rest}
34
+ >
35
+ {
36
+ blocks.map((block, blockIndex) => (
37
+ <div class={transcriptBlockVariants({ compact: compactVariant })}>
38
+ <div class={transcriptSpeakerRowClass}>
39
+ <span
40
+ class={transcriptSpeakerNameClass}
41
+ style={block.speakerColor ? `color:${block.speakerColor}` : undefined}
42
+ >
43
+ {block.speaker}
44
+ </span>
45
+ {block.timestamp && (
46
+ <span class={transcriptTimestampClass}>{block.timestamp}</span>
47
+ )}
48
+ </div>
49
+ {block.texts.map((text) => (
50
+ <p class={transcriptTextLineClass}>{text}</p>
51
+ ))}
52
+ </div>
53
+ ))
54
+ }
55
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,63 @@
1
+ ---
2
+ import {
3
+ createMarqueeStrip,
4
+ marqueeStripVariants,
5
+ marqueeStripInnerClass,
6
+ marqueeStripScrollOuterClass,
7
+ marqueeStripScrollTrackClass,
8
+ marqueeStripLabelClass,
9
+ marqueeStripItemClass,
10
+ } from '../marquee-strip/index.ts'
11
+ import { cn } from '../shared/index.ts'
12
+
13
+ interface Props extends astroHTML.JSX.HTMLAttributes {
14
+ /** Eyebrow label shown before the items (static mode only). */
15
+ label?: string
16
+ /** List of text items to display. */
17
+ items: string[]
18
+ /**
19
+ * When `true` the items scroll continuously using a CSS `marquee` keyframe.
20
+ * Define the keyframe in your global CSS:
21
+ *
22
+ * ```css
23
+ * @keyframes marquee {
24
+ * from { transform: translateX(0); }
25
+ * to { transform: translateX(-50%); }
26
+ * }
27
+ * ```
28
+ *
29
+ * @default false
30
+ */
31
+ scroll?: boolean
32
+ }
33
+
34
+ const {
35
+ label,
36
+ items,
37
+ scroll = false,
38
+ class: className,
39
+ ...rest
40
+ } = Astro.props
41
+
42
+ const { ariaProps, dataAttributes } = createMarqueeStrip({ scroll })
43
+ const scrollVariant = scroll ? 'true' : 'false'
44
+ ---
45
+
46
+ <div class={cn(marqueeStripVariants({ scroll: scrollVariant }), className)} {...ariaProps} {...dataAttributes} {...rest}>
47
+ {scroll ? (
48
+ <div class={marqueeStripScrollOuterClass}>
49
+ <div class={marqueeStripScrollTrackClass}>
50
+ {[...items, ...items].map((item) => (
51
+ <span class={marqueeStripItemClass}>{item}</span>
52
+ ))}
53
+ </div>
54
+ </div>
55
+ ) : (
56
+ <div class={marqueeStripInnerClass}>
57
+ {label && <span class={marqueeStripLabelClass}>{label}</span>}
58
+ {items.map((item) => (
59
+ <span class={marqueeStripItemClass}>{item}</span>
60
+ ))}
61
+ </div>
62
+ )}
63
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,56 @@
1
+ ---
2
+ import {
3
+ clampPercent,
4
+ createMasteryBar,
5
+ masteryBarVariants,
6
+ masteryBarFillVariants,
7
+ masteryBarLabelClass,
8
+ masteryBarLeadingLabelClass,
9
+ masteryBarHeaderClass,
10
+ type MasteryBarSize,
11
+ } from '../mastery-bar/index.ts'
12
+ import { cn } from '../shared/index.ts'
13
+
14
+ interface Props extends astroHTML.JSX.HTMLAttributes {
15
+ /** Progress value (0–100). Values outside this range are clamped. */
16
+ value: number
17
+ /** Label shown on the right side of the header row. */
18
+ label?: string
19
+ /** Label shown on the left side of the header row. */
20
+ leadingLabel?: string
21
+ /** Visual size of the track. */
22
+ size?: MasteryBarSize
23
+ /** Renders the fill at reduced opacity to indicate a muted/secondary state. */
24
+ muted?: boolean
25
+ }
26
+
27
+ const {
28
+ value,
29
+ label,
30
+ leadingLabel,
31
+ size = 'md',
32
+ muted = false,
33
+ class: className,
34
+ ...rest
35
+ } = Astro.props
36
+
37
+ const clamped = clampPercent(value)
38
+ const { ariaProps, dataAttributes } = createMasteryBar({ value })
39
+ const hasHeader = leadingLabel != null || label != null
40
+ const fillWidth = `${clamped}%`
41
+ ---
42
+
43
+ <div class={cn('w-full', className)} {...rest}>
44
+ {hasHeader && (
45
+ <div class={masteryBarHeaderClass}>
46
+ {leadingLabel != null && <span class={masteryBarLeadingLabelClass}>{leadingLabel}</span>}
47
+ {label != null && <span class={masteryBarLabelClass}>{label}</span>}
48
+ </div>
49
+ )}
50
+ <div class={masteryBarVariants({ size })} {...ariaProps} {...dataAttributes}>
51
+ <div
52
+ class={masteryBarFillVariants({ muted: muted ? 'true' : 'false' })}
53
+ style={`width:${fillWidth}`}
54
+ />
55
+ </div>
56
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,74 @@
1
+ ---
2
+ import {
3
+ contentBounds,
4
+ miniScale,
5
+ worldToMini,
6
+ viewportRectInMini,
7
+ createMiniMap,
8
+ miniMapVariants,
9
+ miniMapDotClass,
10
+ miniMapViewportClass,
11
+ type MiniMapItem,
12
+ type Rect,
13
+ } from '../mini-map/index.ts'
14
+ import { cn } from '../shared/index.ts'
15
+
16
+ interface Props extends astroHTML.JSX.HTMLAttributes {
17
+ /** Items to render as dots on the minimap. */
18
+ items: MiniMapItem[]
19
+ /** Current viewport in world coordinates. Renders a viewport indicator rect. */
20
+ viewport?: Rect
21
+ /** Width of the minimap box in px. */
22
+ width?: number
23
+ /** Height of the minimap box in px. */
24
+ height?: number
25
+ /** Padding inset in px (applied to all sides). */
26
+ padding?: number
27
+ }
28
+
29
+ const {
30
+ items,
31
+ viewport,
32
+ width = 200,
33
+ height = 140,
34
+ padding = 8,
35
+ class: className,
36
+ ...rest
37
+ } = Astro.props
38
+
39
+ const bounds = contentBounds(items)
40
+ const scale = miniScale(bounds, width, height, padding)
41
+ const { ariaProps, dataAttributes } = createMiniMap()
42
+
43
+ const viewportRect = viewport != null
44
+ ? viewportRectInMini(viewport, bounds, scale, padding)
45
+ : null
46
+ ---
47
+
48
+ <div
49
+ class={cn(miniMapVariants({ interactive: 'false' }), className)}
50
+ style={`width:${width}px;height:${height}px;position:relative`}
51
+ {...ariaProps}
52
+ {...dataAttributes}
53
+ {...rest}
54
+ >
55
+ {items.map((item) => {
56
+ const pos = worldToMini(item, bounds, scale, padding)
57
+ const w = Math.max(4, (item.width ?? 8) * scale)
58
+ const h = Math.max(4, (item.height ?? 8) * scale)
59
+ return (
60
+ <span
61
+ class={miniMapDotClass}
62
+ style={`position:absolute;left:${pos.x}px;top:${pos.y}px;width:${w}px;height:${h}px`}
63
+ aria-hidden="true"
64
+ />
65
+ )
66
+ })}
67
+ {viewportRect != null && (
68
+ <span
69
+ class={miniMapViewportClass}
70
+ style={`position:absolute;left:${viewportRect.x}px;top:${viewportRect.y}px;width:${viewportRect.width}px;height:${viewportRect.height}px`}
71
+ aria-hidden="true"
72
+ />
73
+ )}
74
+ </div>
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,47 @@
1
+ ---
2
+ import {
3
+ createNumberedSteps,
4
+ padOrdinal,
5
+ stepColumns,
6
+ numberedStepsItemClass,
7
+ numberedStepsOrdinalClass,
8
+ numberedStepsTitleClass,
9
+ numberedStepsBodyClass,
10
+ type NumberedStepItem,
11
+ } from '../numbered-steps/index.ts'
12
+ import { cn } from '../shared/index.ts'
13
+
14
+ interface Props extends astroHTML.JSX.HTMLAttributes {
15
+ /** The step items to display (3–5 recommended). */
16
+ items: NumberedStepItem[]
17
+ /**
18
+ * Override the number of grid columns. Defaults to clamping item count to
19
+ * 2–5 via `stepColumns`.
20
+ */
21
+ columns?: number
22
+ }
23
+
24
+ const { items, columns, class: className, ...rest } = Astro.props
25
+
26
+ const cols = columns ?? stepColumns(items.length)
27
+ const gridStyle = `grid-template-columns:repeat(${cols},minmax(0,1fr))`
28
+ const { ariaProps, dataAttributes } = createNumberedSteps()
29
+ ---
30
+
31
+ <div
32
+ class={cn('grid gap-6', className)}
33
+ style={gridStyle}
34
+ {...ariaProps}
35
+ {...dataAttributes}
36
+ {...rest}
37
+ >
38
+ {
39
+ items.map((item, index) => (
40
+ <div role="listitem" class={numberedStepsItemClass}>
41
+ <span class={numberedStepsOrdinalClass}>{padOrdinal(index + 1)}</span>
42
+ <p class={numberedStepsTitleClass}>{item.title}</p>
43
+ <p class={numberedStepsBodyClass}>{item.body}</p>
44
+ </div>
45
+ ))
46
+ }
47
+ </div>
@@ -0,0 +1 @@
1
+ export {}