@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.
- package/dist/astro-audience-feature-card/AudienceFeatureCard.astro +53 -0
- package/dist/astro-audience-feature-card/index.ts +1 -0
- package/dist/astro-audio-room/AudioRoom.astro +81 -0
- package/dist/astro-audio-room/index.ts +1 -0
- package/dist/astro-brand-network-cell/BrandNetworkCell.astro +77 -0
- package/dist/astro-brand-network-cell/index.ts +1 -0
- package/dist/astro-browser-chrome-mock/BrowserChromeMock.astro +62 -0
- package/dist/astro-browser-chrome-mock/index.ts +1 -0
- package/dist/astro-call-controls/CallControls.astro +57 -0
- package/dist/astro-call-controls/index.ts +1 -0
- package/dist/astro-checklist/Checklist.astro +76 -0
- package/dist/astro-checklist/index.ts +1 -0
- package/dist/astro-editor-status-bar/EditorStatusBar.astro +92 -0
- package/dist/astro-editor-status-bar/index.ts +1 -0
- package/dist/astro-editor-tabs/EditorTabs.astro +74 -0
- package/dist/astro-editor-tabs/index.ts +1 -0
- package/dist/astro-floating-reactions/FloatingReactions.astro +56 -0
- package/dist/astro-floating-reactions/index.ts +1 -0
- package/dist/astro-flow-editor/FlowEditor.astro +99 -0
- package/dist/astro-flow-editor/index.ts +3 -0
- package/dist/astro-graph-view/GraphView.astro +109 -0
- package/dist/astro-graph-view/index.ts +1 -0
- package/dist/astro-infinite-canvas/InfiniteCanvas.astro +43 -0
- package/dist/astro-infinite-canvas/index.ts +1 -0
- package/dist/astro-live-captions/LiveCaptions.astro +54 -0
- package/dist/astro-live-captions/index.ts +1 -0
- package/dist/astro-live-cursors/LiveCursors.astro +55 -0
- package/dist/astro-live-cursors/index.ts +1 -0
- package/dist/astro-live-transcript/LiveTranscript.astro +55 -0
- package/dist/astro-live-transcript/index.ts +1 -0
- package/dist/astro-marquee-strip/MarqueeStrip.astro +63 -0
- package/dist/astro-marquee-strip/index.ts +1 -0
- package/dist/astro-mastery-bar/MasteryBar.astro +56 -0
- package/dist/astro-mastery-bar/index.ts +1 -0
- package/dist/astro-mini-map/MiniMap.astro +74 -0
- package/dist/astro-mini-map/index.ts +1 -0
- package/dist/astro-numbered-steps/NumberedSteps.astro +47 -0
- package/dist/astro-numbered-steps/index.ts +1 -0
- package/dist/astro-pre-call-lobby/PreCallLobby.astro +202 -0
- package/dist/astro-pre-call-lobby/index.ts +1 -0
- package/dist/astro-pricing-card/PricingCard.astro +114 -0
- package/dist/astro-pricing-card/index.ts +1 -0
- package/dist/astro-radial-gauge/RadialGauge.astro +144 -0
- package/dist/astro-radial-gauge/index.ts +1 -0
- package/dist/astro-rating-scale/RatingScale.astro +73 -0
- package/dist/astro-rating-scale/index.ts +1 -0
- package/dist/astro-section-head/SectionHead.astro +44 -0
- package/dist/astro-section-head/index.ts +1 -0
- package/dist/astro-stat-grid/StatGrid.astro +46 -0
- package/dist/astro-stat-grid/index.ts +1 -0
- package/dist/astro-sticky-note/StickyNote.astro +55 -0
- package/dist/astro-sticky-note/index.ts +1 -0
- package/dist/astro-terminal/Terminal.astro +67 -0
- package/dist/astro-terminal/index.ts +1 -0
- package/dist/astro-test-results/TestResults.astro +76 -0
- package/dist/astro-test-results/index.ts +1 -0
- package/dist/astro-timeline/Timeline.astro +59 -0
- package/dist/astro-timeline/index.ts +1 -0
- package/dist/astro-video-grid/VideoGrid.astro +182 -0
- package/dist/astro-video-grid/index.ts +1 -0
- package/dist/astro-video-tile/VideoTile.astro +104 -0
- package/dist/astro-video-tile/index.ts +1 -0
- package/dist/astro-wizard/Wizard.astro +137 -0
- package/dist/astro-wizard/index.ts +1 -0
- package/dist/audience-feature-card/audience-feature-card.styles.ts +23 -0
- package/dist/audience-feature-card/audience-feature-card.ts +39 -0
- package/dist/audience-feature-card/index.ts +13 -0
- package/dist/audio-room/audio-room.styles.ts +88 -0
- package/dist/audio-room/audio-room.ts +70 -0
- package/dist/audio-room/index.ts +16 -0
- package/dist/brand-network-cell/brand-network-cell.styles.ts +46 -0
- package/dist/brand-network-cell/brand-network-cell.ts +35 -0
- package/dist/brand-network-cell/index.ts +14 -0
- package/dist/browser-chrome-mock/browser-chrome-mock.styles.ts +43 -0
- package/dist/browser-chrome-mock/browser-chrome-mock.ts +52 -0
- package/dist/browser-chrome-mock/index.ts +17 -0
- package/dist/call-controls/call-controls.styles.ts +63 -0
- package/dist/call-controls/call-controls.ts +79 -0
- package/dist/call-controls/index.ts +15 -0
- package/dist/checklist/checklist.styles.ts +76 -0
- package/dist/checklist/checklist.ts +62 -0
- package/dist/checklist/index.ts +18 -0
- package/dist/editor-status-bar/editor-status-bar.styles.ts +40 -0
- package/dist/editor-status-bar/editor-status-bar.ts +78 -0
- package/dist/editor-status-bar/index.ts +15 -0
- package/dist/editor-tabs/editor-tabs.styles.ts +52 -0
- package/dist/editor-tabs/editor-tabs.ts +82 -0
- package/dist/editor-tabs/index.ts +15 -0
- package/dist/floating-reactions/floating-reactions.styles.ts +54 -0
- package/dist/floating-reactions/floating-reactions.ts +85 -0
- package/dist/floating-reactions/index.ts +14 -0
- package/dist/flow-editor/flow-editor.styles.ts +56 -0
- package/dist/flow-editor/flow-editor.ts +126 -0
- package/dist/flow-editor/index.ts +18 -0
- package/dist/graph-view/graph-view.styles.ts +66 -0
- package/dist/graph-view/graph-view.ts +130 -0
- package/dist/graph-view/index.ts +21 -0
- package/dist/index.ts +32 -0
- package/dist/infinite-canvas/index.ts +17 -0
- package/dist/infinite-canvas/infinite-canvas.styles.ts +49 -0
- package/dist/infinite-canvas/infinite-canvas.ts +97 -0
- package/dist/live-captions/index.ts +13 -0
- package/dist/live-captions/live-captions.styles.ts +45 -0
- package/dist/live-captions/live-captions.ts +57 -0
- package/dist/live-cursors/index.ts +14 -0
- package/dist/live-cursors/live-cursors.styles.ts +41 -0
- package/dist/live-cursors/live-cursors.ts +73 -0
- package/dist/live-transcript/index.ts +16 -0
- package/dist/live-transcript/live-transcript.styles.ts +48 -0
- package/dist/live-transcript/live-transcript.ts +82 -0
- package/dist/marquee-strip/index.ts +14 -0
- package/dist/marquee-strip/marquee-strip.styles.ts +61 -0
- package/dist/marquee-strip/marquee-strip.ts +35 -0
- package/dist/mastery-bar/index.ts +15 -0
- package/dist/mastery-bar/mastery-bar.styles.ts +45 -0
- package/dist/mastery-bar/mastery-bar.ts +55 -0
- package/dist/mini-map/index.ts +16 -0
- package/dist/mini-map/mini-map.styles.ts +32 -0
- package/dist/mini-map/mini-map.ts +122 -0
- package/dist/numbered-steps/index.ts +16 -0
- package/dist/numbered-steps/numbered-steps.styles.ts +36 -0
- package/dist/numbered-steps/numbered-steps.ts +64 -0
- package/dist/pre-call-lobby/index.ts +22 -0
- package/dist/pre-call-lobby/pre-call-lobby.styles.ts +108 -0
- package/dist/pre-call-lobby/pre-call-lobby.ts +61 -0
- package/dist/pricing-card/index.ts +19 -0
- package/dist/pricing-card/pricing-card.styles.ts +71 -0
- package/dist/pricing-card/pricing-card.ts +37 -0
- package/dist/radial-gauge/index.ts +26 -0
- package/dist/radial-gauge/radial-gauge.styles.ts +75 -0
- package/dist/radial-gauge/radial-gauge.ts +183 -0
- package/dist/rating-scale/index.ts +16 -0
- package/dist/rating-scale/rating-scale.styles.ts +48 -0
- package/dist/rating-scale/rating-scale.ts +101 -0
- package/dist/section-head/index.ts +13 -0
- package/dist/section-head/section-head.styles.ts +30 -0
- package/dist/section-head/section-head.ts +28 -0
- package/dist/stat-grid/index.ts +13 -0
- package/dist/stat-grid/stat-grid.styles.ts +25 -0
- package/dist/stat-grid/stat-grid.ts +41 -0
- package/dist/sticky-note/index.ts +14 -0
- package/dist/sticky-note/sticky-note.styles.ts +37 -0
- package/dist/sticky-note/sticky-note.ts +47 -0
- package/dist/terminal/index.ts +13 -0
- package/dist/terminal/terminal.styles.ts +56 -0
- package/dist/terminal/terminal.ts +60 -0
- package/dist/test-results/index.ts +19 -0
- package/dist/test-results/test-results.styles.ts +93 -0
- package/dist/test-results/test-results.ts +83 -0
- package/dist/timeline/index.ts +22 -0
- package/dist/timeline/timeline.styles.ts +98 -0
- package/dist/timeline/timeline.ts +86 -0
- package/dist/video-grid/index.ts +16 -0
- package/dist/video-grid/video-grid.styles.ts +38 -0
- package/dist/video-grid/video-grid.ts +93 -0
- package/dist/video-tile/index.ts +17 -0
- package/dist/video-tile/video-tile.styles.ts +59 -0
- package/dist/video-tile/video-tile.ts +74 -0
- package/dist/wizard/index.ts +28 -0
- package/dist/wizard/wizard.styles.ts +147 -0
- package/dist/wizard/wizard.ts +128 -0
- 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,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 {}
|