@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,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
import {
|
|
3
|
+
createAudioRoom,
|
|
4
|
+
getInitials,
|
|
5
|
+
orbColumns,
|
|
6
|
+
audioRoomVariants,
|
|
7
|
+
audioRoomOrbCellVariants,
|
|
8
|
+
speakingOrbVariants,
|
|
9
|
+
audioRoomNameLabelClass,
|
|
10
|
+
audioRoomMutedBadgeClass,
|
|
11
|
+
audioRoomHandBadgeClass,
|
|
12
|
+
type AudioParticipant,
|
|
13
|
+
} from '../audio-room/index.ts'
|
|
14
|
+
import { cn } from '../shared/index.ts'
|
|
15
|
+
|
|
16
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
17
|
+
/** Participants to render as speaking orbs. */
|
|
18
|
+
participants: AudioParticipant[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { participants, class: className, ...rest } = Astro.props
|
|
22
|
+
|
|
23
|
+
const cols = orbColumns(participants.length)
|
|
24
|
+
const { ariaProps, dataAttributes } = createAudioRoom()
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
<div
|
|
28
|
+
class={cn(audioRoomVariants(), className)}
|
|
29
|
+
style={`grid-template-columns: repeat(${cols}, minmax(0, 1fr))`}
|
|
30
|
+
{...ariaProps}
|
|
31
|
+
{...dataAttributes}
|
|
32
|
+
{...rest}
|
|
33
|
+
>
|
|
34
|
+
{
|
|
35
|
+
participants.map((participant) => {
|
|
36
|
+
const initials = getInitials(participant.name)
|
|
37
|
+
const speaking = participant.speaking ?? false
|
|
38
|
+
const muted = participant.muted ?? false
|
|
39
|
+
const handRaised = participant.handRaised ?? false
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div class={audioRoomOrbCellVariants()}>
|
|
43
|
+
<div
|
|
44
|
+
role="img"
|
|
45
|
+
aria-label={participant.name}
|
|
46
|
+
data-speaking={speaking ? 'true' : 'false'}
|
|
47
|
+
data-muted={muted ? 'true' : 'false'}
|
|
48
|
+
data-hand-raised={handRaised ? 'true' : 'false'}
|
|
49
|
+
class={speakingOrbVariants({
|
|
50
|
+
speaking: speaking ? 'true' : 'false',
|
|
51
|
+
muted: muted ? 'true' : 'false',
|
|
52
|
+
})}
|
|
53
|
+
>
|
|
54
|
+
{participant.avatarUrl ? (
|
|
55
|
+
<img
|
|
56
|
+
src={participant.avatarUrl}
|
|
57
|
+
alt={participant.name}
|
|
58
|
+
class="absolute inset-0 size-full object-cover"
|
|
59
|
+
/>
|
|
60
|
+
) : (
|
|
61
|
+
<span aria-hidden="true">{initials}</span>
|
|
62
|
+
)}
|
|
63
|
+
|
|
64
|
+
{muted && (
|
|
65
|
+
<span class={audioRoomMutedBadgeClass} aria-label="Muted">
|
|
66
|
+
🔇
|
|
67
|
+
</span>
|
|
68
|
+
)}
|
|
69
|
+
|
|
70
|
+
{handRaised && (
|
|
71
|
+
<span class={audioRoomHandBadgeClass} aria-label="Hand raised">
|
|
72
|
+
✋
|
|
73
|
+
</span>
|
|
74
|
+
)}
|
|
75
|
+
</div>
|
|
76
|
+
<span class={audioRoomNameLabelClass}>{participant.name}</span>
|
|
77
|
+
</div>
|
|
78
|
+
)
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
import {
|
|
3
|
+
createCallControls,
|
|
4
|
+
callControlsVariants,
|
|
5
|
+
callControlButtonVariants,
|
|
6
|
+
callControlLabelClass,
|
|
7
|
+
type CallControlTone,
|
|
8
|
+
type CallControlItem,
|
|
9
|
+
} from '../call-controls/index.ts'
|
|
10
|
+
import { cn } from '../shared/index.ts'
|
|
11
|
+
|
|
12
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
13
|
+
/**
|
|
14
|
+
* Array of control descriptors to render as buttons.
|
|
15
|
+
* If omitted, the default <slot /> is used instead (composable usage).
|
|
16
|
+
*/
|
|
17
|
+
controls?: CallControlItem[]
|
|
18
|
+
/** Visual size of the toolbar and its buttons. */
|
|
19
|
+
size?: 'sm' | 'md'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const {
|
|
23
|
+
controls,
|
|
24
|
+
size = 'md',
|
|
25
|
+
class: className,
|
|
26
|
+
...rest
|
|
27
|
+
} = Astro.props
|
|
28
|
+
|
|
29
|
+
const { ariaProps, dataAttributes } = createCallControls({ controls })
|
|
30
|
+
|
|
31
|
+
function toneClass(tone: CallControlTone | undefined): string {
|
|
32
|
+
return callControlButtonVariants({ tone: tone ?? 'default', size })
|
|
33
|
+
}
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
<div
|
|
37
|
+
class={cn(callControlsVariants({ size }), className)}
|
|
38
|
+
role={ariaProps.role}
|
|
39
|
+
aria-label={ariaProps['aria-label']}
|
|
40
|
+
{...dataAttributes}
|
|
41
|
+
{...rest}
|
|
42
|
+
>
|
|
43
|
+
{controls
|
|
44
|
+
? controls.map((ctrl) => (
|
|
45
|
+
<button
|
|
46
|
+
type="button"
|
|
47
|
+
aria-label={ctrl.label}
|
|
48
|
+
aria-pressed={ctrl.pressed !== undefined ? ctrl.pressed : undefined}
|
|
49
|
+
class={toneClass(ctrl.tone)}
|
|
50
|
+
>
|
|
51
|
+
{ctrl.icon && <span aria-hidden="true">{ctrl.icon}</span>}
|
|
52
|
+
<span class={callControlLabelClass}>{ctrl.label}</span>
|
|
53
|
+
</button>
|
|
54
|
+
))
|
|
55
|
+
: <slot />
|
|
56
|
+
}
|
|
57
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
import {
|
|
3
|
+
createChecklist,
|
|
4
|
+
checklistProgress,
|
|
5
|
+
checklistContainerClass,
|
|
6
|
+
checklistListClass,
|
|
7
|
+
checklistItemVariants,
|
|
8
|
+
checklistBoxVariants,
|
|
9
|
+
checklistLabelWrapClass,
|
|
10
|
+
checklistLabelVariants,
|
|
11
|
+
checklistDescriptionClass,
|
|
12
|
+
checklistProgressClass,
|
|
13
|
+
type ChecklistItemData,
|
|
14
|
+
} from '../checklist/index.ts'
|
|
15
|
+
import { cn } from '../shared/index.ts'
|
|
16
|
+
|
|
17
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
18
|
+
/** List of checklist items. */
|
|
19
|
+
items: ChecklistItemData[]
|
|
20
|
+
/** Show a "{completed}/{total}" progress summary below the list. */
|
|
21
|
+
showProgress?: boolean
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const { items, showProgress = false, class: className, ...rest } = Astro.props
|
|
25
|
+
|
|
26
|
+
const { ariaProps, dataAttributes } = createChecklist()
|
|
27
|
+
const progress = showProgress ? checklistProgress(items) : null
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
<div class={cn(checklistContainerClass, className)} {...dataAttributes} {...rest}>
|
|
31
|
+
<ul class={checklistListClass} {...ariaProps}>
|
|
32
|
+
{
|
|
33
|
+
items.map((item) => {
|
|
34
|
+
const checked = Boolean(item.checked)
|
|
35
|
+
return (
|
|
36
|
+
<li role="presentation">
|
|
37
|
+
<button
|
|
38
|
+
type="button"
|
|
39
|
+
role="checkbox"
|
|
40
|
+
aria-checked={checked}
|
|
41
|
+
data-state={checked ? 'checked' : 'unchecked'}
|
|
42
|
+
class={checklistItemVariants({ checked: checked ? 'true' : 'false' })}
|
|
43
|
+
>
|
|
44
|
+
<span aria-hidden="true" class={checklistBoxVariants({ checked: checked ? 'true' : 'false' })}>
|
|
45
|
+
{checked && (
|
|
46
|
+
<svg viewBox="0 0 12 12" fill="none" class="h-3 w-3" aria-hidden="true">
|
|
47
|
+
<path
|
|
48
|
+
d="M2 6l3 3 5-5"
|
|
49
|
+
stroke="currentColor"
|
|
50
|
+
stroke-width="1.5"
|
|
51
|
+
stroke-linecap="round"
|
|
52
|
+
stroke-linejoin="round"
|
|
53
|
+
/>
|
|
54
|
+
</svg>
|
|
55
|
+
)}
|
|
56
|
+
</span>
|
|
57
|
+
<span class={checklistLabelWrapClass}>
|
|
58
|
+
<span class={checklistLabelVariants({ checked: checked ? 'true' : 'false' })}>{item.label}</span>
|
|
59
|
+
{item.description && (
|
|
60
|
+
<span class={checklistDescriptionClass}>{item.description}</span>
|
|
61
|
+
)}
|
|
62
|
+
</span>
|
|
63
|
+
</button>
|
|
64
|
+
</li>
|
|
65
|
+
)
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
</ul>
|
|
69
|
+
{
|
|
70
|
+
progress !== null && (
|
|
71
|
+
<p class={checklistProgressClass}>
|
|
72
|
+
{progress.completed}/{progress.total} completed
|
|
73
|
+
</p>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
import {
|
|
3
|
+
createEditorStatusBar,
|
|
4
|
+
formatCursorPosition,
|
|
5
|
+
partitionSegments,
|
|
6
|
+
editorStatusBarVariants,
|
|
7
|
+
statusBarGroupClass,
|
|
8
|
+
statusBarSegmentVariants,
|
|
9
|
+
type StatusSegment,
|
|
10
|
+
type StatusSegmentTone,
|
|
11
|
+
} from '../editor-status-bar/index.ts'
|
|
12
|
+
import { cn } from '../shared/index.ts'
|
|
13
|
+
|
|
14
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
15
|
+
/**
|
|
16
|
+
* Explicit list of segments. When provided, all convenience props are
|
|
17
|
+
* ignored.
|
|
18
|
+
*/
|
|
19
|
+
segments?: StatusSegment[]
|
|
20
|
+
/** Current line number (1-indexed). */
|
|
21
|
+
line?: number
|
|
22
|
+
/** Current column number (1-indexed). */
|
|
23
|
+
col?: number
|
|
24
|
+
/** Indentation descriptor, e.g. `'Spaces: 4'`. */
|
|
25
|
+
indentation?: string
|
|
26
|
+
/** Language / runtime label, e.g. `'Python 3.11.4'`. */
|
|
27
|
+
language?: string
|
|
28
|
+
/** File encoding, e.g. `'UTF-8'`. */
|
|
29
|
+
encoding?: string
|
|
30
|
+
/** End-of-line sequence, e.g. `'LF'` or `'CRLF'`. */
|
|
31
|
+
eol?: string
|
|
32
|
+
/** Persistence status label, e.g. `'Auto-saved'`. */
|
|
33
|
+
status?: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const {
|
|
37
|
+
segments: segmentsProp,
|
|
38
|
+
line,
|
|
39
|
+
col,
|
|
40
|
+
indentation,
|
|
41
|
+
language,
|
|
42
|
+
encoding,
|
|
43
|
+
eol,
|
|
44
|
+
status,
|
|
45
|
+
class: className,
|
|
46
|
+
...rest
|
|
47
|
+
} = Astro.props
|
|
48
|
+
|
|
49
|
+
function buildSegments(): StatusSegment[] {
|
|
50
|
+
const segs: StatusSegment[] = []
|
|
51
|
+
if (line !== undefined && col !== undefined) {
|
|
52
|
+
segs.push({ id: 'cursor', label: formatCursorPosition(line, col), align: 'left', tone: 'default' })
|
|
53
|
+
}
|
|
54
|
+
if (indentation) {
|
|
55
|
+
segs.push({ id: 'indentation', label: indentation, align: 'left', tone: 'muted' })
|
|
56
|
+
}
|
|
57
|
+
if (language) {
|
|
58
|
+
segs.push({ id: 'language', label: language, align: 'right', tone: 'accent' })
|
|
59
|
+
}
|
|
60
|
+
if (encoding) {
|
|
61
|
+
segs.push({ id: 'encoding', label: encoding, align: 'right', tone: 'muted' })
|
|
62
|
+
}
|
|
63
|
+
if (eol) {
|
|
64
|
+
segs.push({ id: 'eol', label: eol, align: 'right', tone: 'muted' })
|
|
65
|
+
}
|
|
66
|
+
if (status) {
|
|
67
|
+
segs.push({ id: 'status', label: status, align: 'right', tone: 'muted' })
|
|
68
|
+
}
|
|
69
|
+
return segs
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const segments = segmentsProp ?? buildSegments()
|
|
73
|
+
const { left, right } = partitionSegments(segments)
|
|
74
|
+
const { ariaProps, dataAttributes } = createEditorStatusBar()
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
<div class={cn(editorStatusBarVariants(), className)} {...ariaProps} {...dataAttributes} {...rest}>
|
|
78
|
+
<div class={statusBarGroupClass}>
|
|
79
|
+
{left.map((seg) => (
|
|
80
|
+
<span class={statusBarSegmentVariants({ tone: (seg.tone ?? 'default') as StatusSegmentTone })}>
|
|
81
|
+
{seg.label}
|
|
82
|
+
</span>
|
|
83
|
+
))}
|
|
84
|
+
</div>
|
|
85
|
+
<div class={statusBarGroupClass}>
|
|
86
|
+
{right.map((seg) => (
|
|
87
|
+
<span class={statusBarSegmentVariants({ tone: (seg.tone ?? 'default') as StatusSegmentTone })}>
|
|
88
|
+
{seg.label}
|
|
89
|
+
</span>
|
|
90
|
+
))}
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
import {
|
|
3
|
+
createEditorTabs,
|
|
4
|
+
editorTabsVariants,
|
|
5
|
+
editorTabVariants,
|
|
6
|
+
editorTabDirtyDotClass,
|
|
7
|
+
editorTabCloseButtonClass,
|
|
8
|
+
editorTabIconClass,
|
|
9
|
+
type EditorTabData,
|
|
10
|
+
} from '../editor-tabs/index.ts'
|
|
11
|
+
import { cn } from '../shared/index.ts'
|
|
12
|
+
|
|
13
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
14
|
+
/** The list of tab entries to render. */
|
|
15
|
+
tabs: EditorTabData[]
|
|
16
|
+
/** The id of the currently active tab. */
|
|
17
|
+
activeId: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
tabs,
|
|
22
|
+
activeId,
|
|
23
|
+
class: className,
|
|
24
|
+
...rest
|
|
25
|
+
} = Astro.props
|
|
26
|
+
|
|
27
|
+
const activeIndex = tabs.findIndex((t) => t.id === activeId)
|
|
28
|
+
const tabbableIndex = activeIndex === -1 ? 0 : activeIndex
|
|
29
|
+
const { ariaProps, dataAttributes } = createEditorTabs({ activeId })
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
<div class={cn(editorTabsVariants(), className)} {...ariaProps} {...dataAttributes} {...rest}>
|
|
33
|
+
{
|
|
34
|
+
tabs.map((tab, index) => {
|
|
35
|
+
const isActive = tab.id === activeId
|
|
36
|
+
return (
|
|
37
|
+
<button
|
|
38
|
+
type="button"
|
|
39
|
+
role="tab"
|
|
40
|
+
aria-selected={isActive}
|
|
41
|
+
aria-controls={`tabpanel-${tab.id}`}
|
|
42
|
+
id={`tab-${tab.id}`}
|
|
43
|
+
tabindex={index === tabbableIndex ? 0 : -1}
|
|
44
|
+
data-state={isActive ? 'active' : 'inactive'}
|
|
45
|
+
class={editorTabVariants({ state: isActive ? 'active' : 'inactive' })}
|
|
46
|
+
>
|
|
47
|
+
{tab.icon && (
|
|
48
|
+
<span class={editorTabIconClass} aria-hidden="true">
|
|
49
|
+
{tab.icon}
|
|
50
|
+
</span>
|
|
51
|
+
)}
|
|
52
|
+
<span>{tab.label}</span>
|
|
53
|
+
{tab.dirty && (
|
|
54
|
+
<span
|
|
55
|
+
class={editorTabDirtyDotClass}
|
|
56
|
+
aria-label="unsaved changes"
|
|
57
|
+
role="status"
|
|
58
|
+
/>
|
|
59
|
+
)}
|
|
60
|
+
{tab.closable && (
|
|
61
|
+
<span
|
|
62
|
+
role="button"
|
|
63
|
+
aria-label={`Close ${tab.label}`}
|
|
64
|
+
tabindex="-1"
|
|
65
|
+
class={editorTabCloseButtonClass}
|
|
66
|
+
>
|
|
67
|
+
×
|
|
68
|
+
</span>
|
|
69
|
+
)}
|
|
70
|
+
</button>
|
|
71
|
+
)
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { cn } from '../shared/index.ts'
|
|
3
|
+
import {
|
|
4
|
+
createEmptyState,
|
|
5
|
+
emptyStateVariants,
|
|
6
|
+
emptyStateIconChipVariants,
|
|
7
|
+
emptyStateTitleClass,
|
|
8
|
+
emptyStateDescriptionClass,
|
|
9
|
+
emptyStateActionsClass,
|
|
10
|
+
type EmptyStateTone,
|
|
11
|
+
} from '../empty-state/index.ts'
|
|
12
|
+
|
|
13
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
14
|
+
/** Tone that tints the icon chip. Defaults to `neutral`. */
|
|
15
|
+
tone?: EmptyStateTone
|
|
16
|
+
/** Wrap the content in a bordered card surface. */
|
|
17
|
+
bordered?: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
tone = 'neutral',
|
|
22
|
+
bordered = false,
|
|
23
|
+
class: className,
|
|
24
|
+
...props
|
|
25
|
+
} = Astro.props
|
|
26
|
+
|
|
27
|
+
const api = createEmptyState({ tone })
|
|
28
|
+
const classes = cn(
|
|
29
|
+
emptyStateVariants({ bordered: bordered ? 'true' : 'false' }),
|
|
30
|
+
className,
|
|
31
|
+
)
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
<div class={classes} {...api.dataAttributes} {...props}>
|
|
35
|
+
{
|
|
36
|
+
Astro.slots.has('icon') && (
|
|
37
|
+
<div aria-hidden="true" class={emptyStateIconChipVariants({ tone })}>
|
|
38
|
+
<slot name="icon" />
|
|
39
|
+
</div>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
<h3 class={emptyStateTitleClass}><slot name="title" /></h3>
|
|
43
|
+
{
|
|
44
|
+
Astro.slots.has('description') && (
|
|
45
|
+
<p class={emptyStateDescriptionClass}>
|
|
46
|
+
<slot name="description" />
|
|
47
|
+
</p>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
{
|
|
51
|
+
Astro.slots.has('actions') && (
|
|
52
|
+
<div class={emptyStateActionsClass}>
|
|
53
|
+
<slot name="actions" />
|
|
54
|
+
</div>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
import {
|
|
3
|
+
createFloatingReactions,
|
|
4
|
+
laneOffsetPercent,
|
|
5
|
+
floatingReactionsVariants,
|
|
6
|
+
floatingReactionItemClass,
|
|
7
|
+
floatingReactionLabelClass,
|
|
8
|
+
type FloatingReaction,
|
|
9
|
+
} from '../floating-reactions/index.ts'
|
|
10
|
+
import { cn } from '../shared/index.ts'
|
|
11
|
+
|
|
12
|
+
interface Props extends astroHTML.JSX.HTMLAttributes {
|
|
13
|
+
/**
|
|
14
|
+
* Reactions to render at SSR time. For animated runtime usage, use the
|
|
15
|
+
* React adapter which manages auto-expiry via useFloatingReactions().
|
|
16
|
+
*/
|
|
17
|
+
reactions?: FloatingReaction[]
|
|
18
|
+
/**
|
|
19
|
+
* Total number of horizontal lane buckets used to spread reactions.
|
|
20
|
+
* @default 5
|
|
21
|
+
*/
|
|
22
|
+
lanes?: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const {
|
|
26
|
+
reactions = [],
|
|
27
|
+
lanes = 5,
|
|
28
|
+
class: className,
|
|
29
|
+
...rest
|
|
30
|
+
} = Astro.props
|
|
31
|
+
|
|
32
|
+
const { ariaProps, dataAttributes } = createFloatingReactions()
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
<div
|
|
36
|
+
class={cn(floatingReactionsVariants({ active: reactions.length > 0 ? 'true' : 'false' }), className)}
|
|
37
|
+
{...ariaProps}
|
|
38
|
+
{...dataAttributes}
|
|
39
|
+
{...rest}
|
|
40
|
+
>
|
|
41
|
+
{
|
|
42
|
+
reactions.map((reaction) => {
|
|
43
|
+
const left = laneOffsetPercent(reaction.lane ?? 0, lanes)
|
|
44
|
+
return (
|
|
45
|
+
<span
|
|
46
|
+
class={floatingReactionItemClass}
|
|
47
|
+
style={`left:${left}%`}
|
|
48
|
+
aria-hidden="true"
|
|
49
|
+
>
|
|
50
|
+
{reaction.emoji}
|
|
51
|
+
<span class={floatingReactionLabelClass}>{reaction.emoji}</span>
|
|
52
|
+
</span>
|
|
53
|
+
)
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -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>
|