@refraction-ui/astro 0.11.1 → 0.13.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-audio-room/AudioRoom.astro +81 -0
- package/dist/astro-audio-room/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-empty-state/EmptyState.astro +57 -0
- package/dist/astro-empty-state/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-input/Input.astro +5 -1
- 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-mini-map/MiniMap.astro +74 -0
- package/dist/astro-mini-map/index.ts +1 -0
- package/dist/astro-password-input/PasswordInput.astro +102 -0
- package/dist/astro-password-input/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-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-segmented-control/SegmentedControl.astro +106 -0
- package/dist/astro-segmented-control/SegmentedControlItem.astro +32 -0
- package/dist/astro-segmented-control/index.ts +1 -0
- package/dist/astro-separator/Separator.astro +49 -0
- package/dist/astro-separator/index.ts +1 -0
- package/dist/astro-social-auth-button/SocialAuthButton.astro +110 -0
- package/dist/astro-social-auth-button/SocialAuthRow.astro +13 -0
- package/dist/astro-social-auth-button/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/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/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/empty-state/empty-state.styles.ts +42 -0
- package/dist/empty-state/empty-state.ts +27 -0
- package/dist/empty-state/index.ts +14 -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 +45 -17
- 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/input/index.ts +2 -0
- package/dist/input/input.styles.ts +4 -0
- package/dist/input/input.ts +39 -3
- 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/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/password-input/index.ts +9 -0
- package/dist/password-input/password-input.styles.ts +10 -0
- package/dist/password-input/password-input.ts +45 -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/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/segmented-control/index.ts +13 -0
- package/dist/segmented-control/segmented-control.styles.ts +42 -0
- package/dist/segmented-control/segmented-control.ts +80 -0
- package/dist/separator/index.ts +12 -0
- package/dist/separator/separator.styles.ts +34 -0
- package/dist/separator/separator.ts +53 -0
- package/dist/social-auth-button/index.ts +14 -0
- package/dist/social-auth-button/social-auth-button.styles.ts +16 -0
- package/dist/social-auth-button/social-auth-button.ts +51 -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 +47 -19
|
@@ -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 {}
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
createInput,
|
|
4
4
|
inputVariants,
|
|
5
5
|
type InputType,
|
|
6
|
+
type InputValidationState,
|
|
6
7
|
} from '../input/index.ts'
|
|
7
8
|
import { cn } from '../shared/index.ts'
|
|
8
9
|
|
|
@@ -13,6 +14,7 @@ interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
|
13
14
|
readonly?: boolean
|
|
14
15
|
required?: boolean
|
|
15
16
|
'aria-invalid'?: boolean
|
|
17
|
+
validationState?: InputValidationState
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
const {
|
|
@@ -23,6 +25,7 @@ const {
|
|
|
23
25
|
readonly,
|
|
24
26
|
required,
|
|
25
27
|
'aria-invalid': ariaInvalid,
|
|
28
|
+
validationState,
|
|
26
29
|
...props
|
|
27
30
|
} = Astro.props
|
|
28
31
|
|
|
@@ -32,9 +35,10 @@ const api = createInput({
|
|
|
32
35
|
readOnly: readonly,
|
|
33
36
|
required,
|
|
34
37
|
'aria-invalid': ariaInvalid === true ? true : undefined,
|
|
38
|
+
validationState,
|
|
35
39
|
})
|
|
36
40
|
|
|
37
|
-
const classes = cn(inputVariants({ size }), className)
|
|
41
|
+
const classes = cn(inputVariants({ size, validationState }), className)
|
|
38
42
|
---
|
|
39
43
|
|
|
40
44
|
<input
|
|
@@ -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,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,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { inputVariants, type InputValidationState } from '../input/index.ts'
|
|
3
|
+
import {
|
|
4
|
+
createPasswordInput,
|
|
5
|
+
passwordToggleVariants,
|
|
6
|
+
} from '../password-input/index.ts'
|
|
7
|
+
import { cn } from '../shared/index.ts'
|
|
8
|
+
|
|
9
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
10
|
+
size?: 'sm' | 'default' | 'lg'
|
|
11
|
+
disabled?: boolean
|
|
12
|
+
readonly?: boolean
|
|
13
|
+
required?: boolean
|
|
14
|
+
validationState?: InputValidationState
|
|
15
|
+
revealLabel?: string
|
|
16
|
+
hideLabel?: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
size,
|
|
21
|
+
class: className,
|
|
22
|
+
disabled,
|
|
23
|
+
readonly,
|
|
24
|
+
required,
|
|
25
|
+
validationState,
|
|
26
|
+
revealLabel = 'Show password',
|
|
27
|
+
hideLabel = 'Hide password',
|
|
28
|
+
...props
|
|
29
|
+
} = Astro.props
|
|
30
|
+
|
|
31
|
+
// Render masked initially; progressive enhancement toggles it client-side.
|
|
32
|
+
const { inputType, toggleLabel, togglePressed } = createPasswordInput({
|
|
33
|
+
revealed: false,
|
|
34
|
+
revealLabel,
|
|
35
|
+
hideLabel,
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const inputClasses = cn(inputVariants({ size, validationState }), 'pr-10', className)
|
|
39
|
+
const ariaInvalid =
|
|
40
|
+
validationState === 'invalid' ? true : validationState === 'valid' ? false : undefined
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
<div class="relative" data-rfr-password-input>
|
|
44
|
+
<input
|
|
45
|
+
type={inputType}
|
|
46
|
+
class={inputClasses}
|
|
47
|
+
disabled={disabled}
|
|
48
|
+
readonly={readonly}
|
|
49
|
+
required={required}
|
|
50
|
+
aria-invalid={ariaInvalid}
|
|
51
|
+
data-rfr-password-field
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
<button
|
|
55
|
+
type="button"
|
|
56
|
+
aria-label={toggleLabel}
|
|
57
|
+
aria-pressed={togglePressed}
|
|
58
|
+
class={passwordToggleVariants()}
|
|
59
|
+
data-rfr-password-toggle
|
|
60
|
+
data-reveal-label={revealLabel}
|
|
61
|
+
data-hide-label={hideLabel}
|
|
62
|
+
>
|
|
63
|
+
<svg
|
|
64
|
+
aria-hidden="true"
|
|
65
|
+
viewBox="0 0 24 24"
|
|
66
|
+
fill="none"
|
|
67
|
+
stroke="currentColor"
|
|
68
|
+
stroke-width="2"
|
|
69
|
+
stroke-linecap="round"
|
|
70
|
+
stroke-linejoin="round"
|
|
71
|
+
class="size-4"
|
|
72
|
+
>
|
|
73
|
+
<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"></path>
|
|
74
|
+
<circle cx="12" cy="12" r="3"></circle>
|
|
75
|
+
</svg>
|
|
76
|
+
</button>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<script>
|
|
80
|
+
document
|
|
81
|
+
.querySelectorAll<HTMLElement>('[data-rfr-password-input]')
|
|
82
|
+
.forEach((root) => {
|
|
83
|
+
const field = root.querySelector<HTMLInputElement>(
|
|
84
|
+
'[data-rfr-password-field]',
|
|
85
|
+
)
|
|
86
|
+
const toggle = root.querySelector<HTMLButtonElement>(
|
|
87
|
+
'[data-rfr-password-toggle]',
|
|
88
|
+
)
|
|
89
|
+
if (!field || !toggle) return
|
|
90
|
+
|
|
91
|
+
const revealLabel = toggle.dataset.revealLabel ?? 'Show password'
|
|
92
|
+
const hideLabel = toggle.dataset.hideLabel ?? 'Hide password'
|
|
93
|
+
|
|
94
|
+
toggle.addEventListener('click', () => {
|
|
95
|
+
const revealed = field.type === 'text'
|
|
96
|
+
const next = !revealed
|
|
97
|
+
field.type = next ? 'text' : 'password'
|
|
98
|
+
toggle.setAttribute('aria-pressed', String(next))
|
|
99
|
+
toggle.setAttribute('aria-label', next ? hideLabel : revealLabel)
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|