@archetypeai/ds-ui-svelte-labs 0.7.1
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/LICENSE +21 -0
- package/README.md +120 -0
- package/dist/primitives/aspect-ratio/aspect-ratio.svelte +8 -0
- package/dist/primitives/aspect-ratio/aspect-ratio.svelte.d.ts +4 -0
- package/dist/primitives/aspect-ratio/index.d.ts +4 -0
- package/dist/primitives/aspect-ratio/index.js +6 -0
- package/dist/primitives/aspect-ratio/types.d.ts +2 -0
- package/dist/primitives/aspect-ratio/types.js +1 -0
- package/dist/primitives/chart/chart-container.svelte +36 -0
- package/dist/primitives/chart/chart-container.svelte.d.ts +4 -0
- package/dist/primitives/chart/chart-style.svelte +37 -0
- package/dist/primitives/chart/chart-style.svelte.d.ts +8 -0
- package/dist/primitives/chart/chart-tooltip.svelte +136 -0
- package/dist/primitives/chart/chart-tooltip.svelte.d.ts +4 -0
- package/dist/primitives/chart/chart-utils.d.ts +45 -0
- package/dist/primitives/chart/chart-utils.js +52 -0
- package/dist/primitives/chart/index.d.ts +7 -0
- package/dist/primitives/chart/index.js +7 -0
- package/dist/primitives/chart/scatter-tooltip.svelte +40 -0
- package/dist/primitives/chart/scatter-tooltip.svelte.d.ts +4 -0
- package/dist/primitives/chart/types.d.ts +33 -0
- package/dist/primitives/chart/types.js +45 -0
- package/dist/primitives/kbd/index.d.ts +5 -0
- package/dist/primitives/kbd/index.js +7 -0
- package/dist/primitives/kbd/kbd-group.svelte +10 -0
- package/dist/primitives/kbd/kbd-group.svelte.d.ts +4 -0
- package/dist/primitives/kbd/kbd.svelte +10 -0
- package/dist/primitives/kbd/kbd.svelte.d.ts +4 -0
- package/dist/primitives/kbd/types.d.ts +6 -0
- package/dist/primitives/kbd/types.js +8 -0
- package/dist/primitives/logo/index.d.ts +4 -0
- package/dist/primitives/logo/index.js +6 -0
- package/dist/primitives/logo/logo.svelte +22 -0
- package/dist/primitives/logo/logo.svelte.d.ts +4 -0
- package/dist/primitives/logo/types.d.ts +25 -0
- package/dist/primitives/logo/types.js +14 -0
- package/dist/primitives/menubar/index.d.ts +4 -0
- package/dist/primitives/menubar/index.js +6 -0
- package/dist/primitives/menubar/menubar.svelte +67 -0
- package/dist/primitives/menubar/menubar.svelte.d.ts +4 -0
- package/dist/primitives/menubar/types.d.ts +10 -0
- package/dist/primitives/menubar/types.js +5 -0
- package/dist/primitives/scatter-chart/index.d.ts +4 -0
- package/dist/primitives/scatter-chart/index.js +6 -0
- package/dist/primitives/scatter-chart/scatter-chart.svelte +147 -0
- package/dist/primitives/scatter-chart/scatter-chart.svelte.d.ts +5 -0
- package/dist/primitives/scatter-chart/types.d.ts +34 -0
- package/dist/primitives/scatter-chart/types.js +6 -0
- package/dist/primitives/sensor-chart/index.d.ts +4 -0
- package/dist/primitives/sensor-chart/index.js +6 -0
- package/dist/primitives/sensor-chart/sensor-chart.svelte +138 -0
- package/dist/primitives/sensor-chart/sensor-chart.svelte.d.ts +4 -0
- package/dist/primitives/sensor-chart/types.d.ts +27 -0
- package/dist/primitives/sensor-chart/types.js +6 -0
- package/dist/primitives/slider/index.d.ts +4 -0
- package/dist/primitives/slider/index.js +6 -0
- package/dist/primitives/slider/slider.svelte +47 -0
- package/dist/primitives/slider/slider.svelte.d.ts +4 -0
- package/dist/primitives/slider/types.d.ts +7 -0
- package/dist/primitives/slider/types.js +14 -0
- package/dist/primitives/switch/index.d.ts +4 -0
- package/dist/primitives/switch/index.js +6 -0
- package/dist/primitives/switch/switch.svelte +28 -0
- package/dist/primitives/switch/switch.svelte.d.ts +4 -0
- package/dist/primitives/switch/types.d.ts +45 -0
- package/dist/primitives/switch/types.js +27 -0
- package/dist/primitives/toggle/index.d.ts +4 -0
- package/dist/primitives/toggle/index.js +6 -0
- package/dist/primitives/toggle/toggle.svelte +24 -0
- package/dist/primitives/toggle/toggle.svelte.d.ts +4 -0
- package/dist/primitives/toggle/types.d.ts +39 -0
- package/dist/primitives/toggle/types.js +19 -0
- package/dist/primitives/utils.d.ts +4 -0
- package/dist/primitives/utils.js +29 -0
- package/dist/primitives/video-player/index.d.ts +4 -0
- package/dist/primitives/video-player/index.js +6 -0
- package/dist/primitives/video-player/types.d.ts +49 -0
- package/dist/primitives/video-player/types.js +32 -0
- package/dist/primitives/video-player/video-player.svelte +139 -0
- package/dist/primitives/video-player/video-player.svelte.d.ts +4 -0
- package/package.json +127 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type WithElementRef } from '../utils.js';
|
|
2
|
+
import type { Component } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import type { ChartAxis } from '../chart/chart-utils.js';
|
|
5
|
+
export declare const sensorChartVariants: import("tailwind-variants").TVReturnType<{} | {} | {}, undefined, "bg-card text-card-foreground border-border flex flex-col gap-6 rounded-xs border p-4 shadow-sm", {} | {}, undefined, import("tailwind-variants").TVReturnType<unknown, undefined, "bg-card text-card-foreground border-border flex flex-col gap-6 rounded-xs border p-4 shadow-sm", unknown, unknown, undefined>>;
|
|
6
|
+
export type SensorChartProps = WithElementRef<HTMLAttributes<HTMLDivElement>> & {
|
|
7
|
+
/** card header label identifying the sensor; header renders only when title or icon is set */
|
|
8
|
+
title?: string;
|
|
9
|
+
/** lucide icon component for header */
|
|
10
|
+
icon?: Component;
|
|
11
|
+
/** array of data points to chart */
|
|
12
|
+
data?: Record<string, unknown>[];
|
|
13
|
+
/** map of data key to display label */
|
|
14
|
+
signals?: Record<string, string>;
|
|
15
|
+
/** data key for x-axis values */
|
|
16
|
+
xKey?: string;
|
|
17
|
+
/** enables streaming mode with sliding window */
|
|
18
|
+
maxPoints?: number;
|
|
19
|
+
/** minimum y-axis value (required) */
|
|
20
|
+
yMin: number;
|
|
21
|
+
/** maximum y-axis value (required) */
|
|
22
|
+
yMax: number;
|
|
23
|
+
/** explicit y-axis tick values */
|
|
24
|
+
yTicks?: number[];
|
|
25
|
+
/** which axes to display */
|
|
26
|
+
axis?: ChartAxis;
|
|
27
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import {} from '../utils.js';
|
|
2
|
+
import { tv } from 'tailwind-variants';
|
|
3
|
+
// card shell inlined from the retired background-card pattern
|
|
4
|
+
export const sensorChartVariants = tv({
|
|
5
|
+
base: 'bg-card text-card-foreground border-border flex flex-col gap-6 rounded-xs border p-4 shadow-sm'
|
|
6
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Slider as SliderPrimitive } from 'bits-ui';
|
|
3
|
+
import { cn } from '../utils.js';
|
|
4
|
+
import {
|
|
5
|
+
sliderRangeVariants,
|
|
6
|
+
sliderThumbVariants,
|
|
7
|
+
sliderTrackVariants,
|
|
8
|
+
sliderVariants,
|
|
9
|
+
type SliderProps
|
|
10
|
+
} from './types.js';
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
ref = $bindable(null),
|
|
14
|
+
value = $bindable(),
|
|
15
|
+
orientation = 'horizontal',
|
|
16
|
+
class: className,
|
|
17
|
+
'aria-label': ariaLabel,
|
|
18
|
+
...restProps
|
|
19
|
+
}: SliderProps = $props();
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<!--
|
|
23
|
+
Discriminated Unions + Destructing (required for bindable) do not
|
|
24
|
+
get along, so we shut typescript up by casting `value` to `never`.
|
|
25
|
+
-->
|
|
26
|
+
<SliderPrimitive.Root
|
|
27
|
+
bind:ref
|
|
28
|
+
bind:value={value as never}
|
|
29
|
+
data-slot="slider"
|
|
30
|
+
{orientation}
|
|
31
|
+
class={cn(sliderVariants(), className)}
|
|
32
|
+
{...restProps}
|
|
33
|
+
>
|
|
34
|
+
{#snippet children({ thumbs })}
|
|
35
|
+
<span data-orientation={orientation} data-slot="slider-track" class={sliderTrackVariants()}>
|
|
36
|
+
<SliderPrimitive.Range data-slot="slider-range" class={sliderRangeVariants()} />
|
|
37
|
+
</span>
|
|
38
|
+
{#each thumbs as thumb (thumb)}
|
|
39
|
+
<SliderPrimitive.Thumb
|
|
40
|
+
data-slot="slider-thumb"
|
|
41
|
+
index={thumb}
|
|
42
|
+
aria-label={ariaLabel}
|
|
43
|
+
class={sliderThumbVariants()}
|
|
44
|
+
/>
|
|
45
|
+
{/each}
|
|
46
|
+
{/snippet}
|
|
47
|
+
</SliderPrimitive.Root>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Slider as SliderPrimitive } from 'bits-ui';
|
|
2
|
+
import { type WithoutChildrenOrChild } from '../utils.js';
|
|
3
|
+
export declare const sliderVariants: import("tailwind-variants").TVReturnType<{} | {} | {}, undefined, "relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col", {} | {}, undefined, import("tailwind-variants").TVReturnType<unknown, undefined, "relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col", unknown, unknown, undefined>>;
|
|
4
|
+
export declare const sliderTrackVariants: import("tailwind-variants").TVReturnType<{} | {} | {}, undefined, "bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5", {} | {}, undefined, import("tailwind-variants").TVReturnType<unknown, undefined, "bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5", unknown, unknown, undefined>>;
|
|
5
|
+
export declare const sliderRangeVariants: import("tailwind-variants").TVReturnType<{} | {} | {}, undefined, "bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full", {} | {}, undefined, import("tailwind-variants").TVReturnType<unknown, undefined, "bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full", unknown, unknown, undefined>>;
|
|
6
|
+
export declare const sliderThumbVariants: import("tailwind-variants").TVReturnType<{} | {} | {}, undefined, "border-primary ring-ring/50 block size-4 shrink-0 rounded-full border bg-white shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50", {} | {}, undefined, import("tailwind-variants").TVReturnType<unknown, undefined, "border-primary ring-ring/50 block size-4 shrink-0 rounded-full border bg-white shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50", unknown, unknown, undefined>>;
|
|
7
|
+
export type SliderProps = WithoutChildrenOrChild<SliderPrimitive.RootProps>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {} from '../utils.js';
|
|
2
|
+
import { tv } from 'tailwind-variants';
|
|
3
|
+
export const sliderVariants = tv({
|
|
4
|
+
base: 'relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col'
|
|
5
|
+
});
|
|
6
|
+
export const sliderTrackVariants = tv({
|
|
7
|
+
base: 'bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5'
|
|
8
|
+
});
|
|
9
|
+
export const sliderRangeVariants = tv({
|
|
10
|
+
base: 'bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full'
|
|
11
|
+
});
|
|
12
|
+
export const sliderThumbVariants = tv({
|
|
13
|
+
base: 'border-primary ring-ring/50 block size-4 shrink-0 rounded-full border bg-white shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50'
|
|
14
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Switch as SwitchPrimitive } from 'bits-ui';
|
|
3
|
+
import { cn } from '../utils.js';
|
|
4
|
+
import { type SwitchProps, switchThumbVariants, switchVariants } from './types.js';
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
checked = $bindable(false),
|
|
9
|
+
class: className,
|
|
10
|
+
size = 'default',
|
|
11
|
+
...restProps
|
|
12
|
+
}: SwitchProps = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<SwitchPrimitive.Root
|
|
16
|
+
bind:ref
|
|
17
|
+
bind:checked
|
|
18
|
+
data-slot="switch"
|
|
19
|
+
data-size={size}
|
|
20
|
+
class={cn(switchVariants({ size }), className)}
|
|
21
|
+
{...restProps}
|
|
22
|
+
>
|
|
23
|
+
<SwitchPrimitive.Thumb
|
|
24
|
+
data-slot="switch-thumb"
|
|
25
|
+
data-size={size}
|
|
26
|
+
class={cn(switchThumbVariants({ size }))}
|
|
27
|
+
/>
|
|
28
|
+
</SwitchPrimitive.Root>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Switch as SwitchPrimitive } from 'bits-ui';
|
|
2
|
+
import type { WithoutChildrenOrChild } from '../utils.js';
|
|
3
|
+
import { type VariantProps } from 'tailwind-variants';
|
|
4
|
+
export declare const switchVariants: import("tailwind-variants").TVReturnType<{
|
|
5
|
+
size: {
|
|
6
|
+
sm: string;
|
|
7
|
+
default: string;
|
|
8
|
+
lg: string;
|
|
9
|
+
};
|
|
10
|
+
}, undefined, "peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-xs transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input", {
|
|
11
|
+
size: {
|
|
12
|
+
sm: string;
|
|
13
|
+
default: string;
|
|
14
|
+
lg: string;
|
|
15
|
+
};
|
|
16
|
+
}, undefined, import("tailwind-variants").TVReturnType<{
|
|
17
|
+
size: {
|
|
18
|
+
sm: string;
|
|
19
|
+
default: string;
|
|
20
|
+
lg: string;
|
|
21
|
+
};
|
|
22
|
+
}, undefined, "peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-xs transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input", unknown, unknown, undefined>>;
|
|
23
|
+
export declare const switchThumbVariants: import("tailwind-variants").TVReturnType<{
|
|
24
|
+
size: {
|
|
25
|
+
sm: string;
|
|
26
|
+
default: string;
|
|
27
|
+
lg: string;
|
|
28
|
+
};
|
|
29
|
+
}, undefined, "pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0", {
|
|
30
|
+
size: {
|
|
31
|
+
sm: string;
|
|
32
|
+
default: string;
|
|
33
|
+
lg: string;
|
|
34
|
+
};
|
|
35
|
+
}, undefined, import("tailwind-variants").TVReturnType<{
|
|
36
|
+
size: {
|
|
37
|
+
sm: string;
|
|
38
|
+
default: string;
|
|
39
|
+
lg: string;
|
|
40
|
+
};
|
|
41
|
+
}, undefined, "pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0", unknown, unknown, undefined>>;
|
|
42
|
+
export type SwitchSize = VariantProps<typeof switchVariants>['size'];
|
|
43
|
+
export type SwitchProps = WithoutChildrenOrChild<SwitchPrimitive.RootProps> & {
|
|
44
|
+
size?: SwitchSize;
|
|
45
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
export const switchVariants = tv({
|
|
3
|
+
base: 'peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-xs transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
|
|
4
|
+
variants: {
|
|
5
|
+
size: {
|
|
6
|
+
sm: 'h-4 w-7',
|
|
7
|
+
default: 'h-5 w-9',
|
|
8
|
+
lg: 'h-6 w-11'
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
defaultVariants: {
|
|
12
|
+
size: 'default'
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
export const switchThumbVariants = tv({
|
|
16
|
+
base: 'pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0',
|
|
17
|
+
variants: {
|
|
18
|
+
size: {
|
|
19
|
+
sm: 'h-3 w-3 data-[state=checked]:translate-x-3',
|
|
20
|
+
default: 'h-4 w-4 data-[state=checked]:translate-x-4',
|
|
21
|
+
lg: 'h-5 w-5 data-[state=checked]:translate-x-5'
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: {
|
|
25
|
+
size: 'default'
|
|
26
|
+
}
|
|
27
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Toggle as TogglePrimitive } from 'bits-ui';
|
|
3
|
+
import { cn } from '../utils.js';
|
|
4
|
+
import { type ToggleProps, toggleVariants } from './types.js';
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
ref = $bindable(null),
|
|
8
|
+
pressed = $bindable(false),
|
|
9
|
+
class: className,
|
|
10
|
+
size = 'default',
|
|
11
|
+
variant = 'default',
|
|
12
|
+
...restProps
|
|
13
|
+
}: ToggleProps = $props();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<TogglePrimitive.Root
|
|
17
|
+
bind:ref
|
|
18
|
+
bind:pressed
|
|
19
|
+
data-slot="toggle"
|
|
20
|
+
data-variant={variant}
|
|
21
|
+
data-size={size}
|
|
22
|
+
class={cn(toggleVariants({ variant, size }), className)}
|
|
23
|
+
{...restProps}
|
|
24
|
+
/>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Toggle as TogglePrimitive } from 'bits-ui';
|
|
2
|
+
import { type VariantProps } from 'tailwind-variants';
|
|
3
|
+
export declare const toggleVariants: import("tailwind-variants").TVReturnType<{
|
|
4
|
+
variant: {
|
|
5
|
+
default: string;
|
|
6
|
+
outline: string;
|
|
7
|
+
};
|
|
8
|
+
size: {
|
|
9
|
+
default: string;
|
|
10
|
+
sm: string;
|
|
11
|
+
lg: string;
|
|
12
|
+
};
|
|
13
|
+
}, undefined, "hover:bg-muted hover:text-muted-foreground data-[state=on]:bg-accent data-[state=on]:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex items-center justify-center gap-2 rounded-xs text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
|
|
14
|
+
variant: {
|
|
15
|
+
default: string;
|
|
16
|
+
outline: string;
|
|
17
|
+
};
|
|
18
|
+
size: {
|
|
19
|
+
default: string;
|
|
20
|
+
sm: string;
|
|
21
|
+
lg: string;
|
|
22
|
+
};
|
|
23
|
+
}, undefined, import("tailwind-variants").TVReturnType<{
|
|
24
|
+
variant: {
|
|
25
|
+
default: string;
|
|
26
|
+
outline: string;
|
|
27
|
+
};
|
|
28
|
+
size: {
|
|
29
|
+
default: string;
|
|
30
|
+
sm: string;
|
|
31
|
+
lg: string;
|
|
32
|
+
};
|
|
33
|
+
}, undefined, "hover:bg-muted hover:text-muted-foreground data-[state=on]:bg-accent data-[state=on]:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex items-center justify-center gap-2 rounded-xs text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", unknown, unknown, undefined>>;
|
|
34
|
+
export type ToggleVariant = VariantProps<typeof toggleVariants>['variant'];
|
|
35
|
+
export type ToggleSize = VariantProps<typeof toggleVariants>['size'];
|
|
36
|
+
export type ToggleProps = TogglePrimitive.RootProps & {
|
|
37
|
+
variant?: ToggleVariant;
|
|
38
|
+
size?: ToggleSize;
|
|
39
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { tv } from 'tailwind-variants';
|
|
2
|
+
export const toggleVariants = tv({
|
|
3
|
+
base: "hover:bg-muted hover:text-muted-foreground data-[state=on]:bg-accent data-[state=on]:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex items-center justify-center gap-2 rounded-xs text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
4
|
+
variants: {
|
|
5
|
+
variant: {
|
|
6
|
+
default: 'bg-transparent',
|
|
7
|
+
outline: 'border-input hover:bg-accent hover:text-accent-foreground border bg-transparent shadow-xs'
|
|
8
|
+
},
|
|
9
|
+
size: {
|
|
10
|
+
default: 'h-9 min-w-9 px-2',
|
|
11
|
+
sm: 'h-8 min-w-8 px-1.5',
|
|
12
|
+
lg: 'h-10 min-w-10 px-2.5'
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
variant: 'default',
|
|
17
|
+
size: 'default'
|
|
18
|
+
}
|
|
19
|
+
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { cn, type WithoutChild, type WithoutChildren, type WithoutChildrenOrChild, type WithElementRef } from '@archetypeai/ds-ui-svelte-console/primitives/utils';
|
|
2
|
+
export declare function clamp(value: number, min?: number, max?: number): number;
|
|
3
|
+
export declare function healthTier(score: number, variant?: 'bg' | 'text'): "bg-atai-good" | "text-atai-good" | "bg-atai-warning" | "text-atai-warning" | "bg-atai-critical" | "text-atai-critical";
|
|
4
|
+
export declare function formatMMSS(totalSeconds: number): string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// class merging + element-ref type helpers come from the console tier so a
|
|
2
|
+
// single cn/twMerge instance (with console's extended class groups) exists
|
|
3
|
+
// in the tree; labs keeps only its domain helpers below.
|
|
4
|
+
export { cn } from '@archetypeai/ds-ui-svelte-console/primitives/utils';
|
|
5
|
+
// constants: health tiers
|
|
6
|
+
const HEALTH_TIERS = {
|
|
7
|
+
good: { bg: 'bg-atai-good', text: 'text-atai-good' },
|
|
8
|
+
warning: { bg: 'bg-atai-warning', text: 'text-atai-warning' },
|
|
9
|
+
critical: { bg: 'bg-atai-critical', text: 'text-atai-critical' }
|
|
10
|
+
};
|
|
11
|
+
// utility: clamp a value between a minimum and maximum
|
|
12
|
+
export function clamp(value, min = 0, max = 100) {
|
|
13
|
+
return Math.max(min, Math.min(max, value));
|
|
14
|
+
}
|
|
15
|
+
// utility: get the health tier for a score
|
|
16
|
+
export function healthTier(score, variant = 'bg') {
|
|
17
|
+
if (score >= 67)
|
|
18
|
+
return HEALTH_TIERS.good[variant];
|
|
19
|
+
if (score >= 34)
|
|
20
|
+
return HEALTH_TIERS.warning[variant];
|
|
21
|
+
return HEALTH_TIERS.critical[variant];
|
|
22
|
+
}
|
|
23
|
+
// utility: format a total seconds into MM:SS
|
|
24
|
+
export function formatMMSS(totalSeconds) {
|
|
25
|
+
const s = Math.floor(totalSeconds);
|
|
26
|
+
const m = Math.floor(s / 60);
|
|
27
|
+
const sec = s % 60;
|
|
28
|
+
return `${String(m).padStart(2, '0')}:${String(sec).padStart(2, '0')}`;
|
|
29
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type WithElementRef } from '../utils.js';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
export declare const videoPlayerVariants: import("tailwind-variants").TVReturnType<{} | {} | {}, undefined, "relative overflow-hidden p-0", {} | {}, undefined, import("tailwind-variants").TVReturnType<unknown, undefined, "relative overflow-hidden p-0", unknown, unknown, undefined>>;
|
|
4
|
+
export declare const videoPlayerOverlayVariants: import("tailwind-variants").TVReturnType<{
|
|
5
|
+
visible: {
|
|
6
|
+
true: string;
|
|
7
|
+
false: string;
|
|
8
|
+
};
|
|
9
|
+
}, undefined, "absolute inset-0 flex cursor-pointer items-center justify-center transition-opacity duration-300", {
|
|
10
|
+
visible: {
|
|
11
|
+
true: string;
|
|
12
|
+
false: string;
|
|
13
|
+
};
|
|
14
|
+
}, undefined, import("tailwind-variants").TVReturnType<{
|
|
15
|
+
visible: {
|
|
16
|
+
true: string;
|
|
17
|
+
false: string;
|
|
18
|
+
};
|
|
19
|
+
}, undefined, "absolute inset-0 flex cursor-pointer items-center justify-center transition-opacity duration-300", unknown, unknown, undefined>>;
|
|
20
|
+
export declare const videoPlayerControlsVariants: import("tailwind-variants").TVReturnType<{
|
|
21
|
+
visible: {
|
|
22
|
+
true: string;
|
|
23
|
+
false: string;
|
|
24
|
+
};
|
|
25
|
+
}, undefined, "bg-card/20 absolute inset-x-0 bottom-0 flex items-center justify-between gap-4 px-3 py-1.5 backdrop-blur-xs transition-opacity duration-300", {
|
|
26
|
+
visible: {
|
|
27
|
+
true: string;
|
|
28
|
+
false: string;
|
|
29
|
+
};
|
|
30
|
+
}, undefined, import("tailwind-variants").TVReturnType<{
|
|
31
|
+
visible: {
|
|
32
|
+
true: string;
|
|
33
|
+
false: string;
|
|
34
|
+
};
|
|
35
|
+
}, undefined, "bg-card/20 absolute inset-x-0 bottom-0 flex items-center justify-between gap-4 px-3 py-1.5 backdrop-blur-xs transition-opacity duration-300", unknown, unknown, undefined>>;
|
|
36
|
+
export type VideoPlayerProps = WithElementRef<HTMLAttributes<HTMLElement>> & {
|
|
37
|
+
/** video source URL (remote or static path) */
|
|
38
|
+
src: string;
|
|
39
|
+
/** thumbnail image shown before playback */
|
|
40
|
+
poster?: string;
|
|
41
|
+
/** auto-start playback on mount */
|
|
42
|
+
autoplay?: boolean;
|
|
43
|
+
/** mute audio */
|
|
44
|
+
muted?: boolean;
|
|
45
|
+
/** show custom controls overlay */
|
|
46
|
+
controls?: boolean;
|
|
47
|
+
/** aspect ratio for the video container */
|
|
48
|
+
ratio?: number;
|
|
49
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {} from '../utils.js';
|
|
2
|
+
import { tv } from 'tailwind-variants';
|
|
3
|
+
// extra root classes layered onto console's card shell
|
|
4
|
+
export const videoPlayerVariants = tv({
|
|
5
|
+
base: 'relative overflow-hidden p-0'
|
|
6
|
+
});
|
|
7
|
+
// center play/pause overlay shown when custom controls are disabled
|
|
8
|
+
export const videoPlayerOverlayVariants = tv({
|
|
9
|
+
base: 'absolute inset-0 flex cursor-pointer items-center justify-center transition-opacity duration-300',
|
|
10
|
+
variants: {
|
|
11
|
+
visible: {
|
|
12
|
+
true: 'opacity-100',
|
|
13
|
+
false: 'pointer-events-none opacity-0'
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
visible: true
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
// bottom control bar with play/pause, seek and time display
|
|
21
|
+
export const videoPlayerControlsVariants = tv({
|
|
22
|
+
base: 'bg-card/20 absolute inset-x-0 bottom-0 flex items-center justify-between gap-4 px-3 py-1.5 backdrop-blur-xs transition-opacity duration-300',
|
|
23
|
+
variants: {
|
|
24
|
+
visible: {
|
|
25
|
+
true: 'opacity-100',
|
|
26
|
+
false: 'pointer-events-none opacity-0'
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: {
|
|
30
|
+
visible: true
|
|
31
|
+
}
|
|
32
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn, formatMMSS } from '../utils.js';
|
|
3
|
+
import { Card } from '@archetypeai/ds-ui-svelte-console/primitives/card';
|
|
4
|
+
import { Button } from '@archetypeai/ds-ui-svelte-console/primitives/button';
|
|
5
|
+
import { AspectRatio } from '../aspect-ratio/index.js';
|
|
6
|
+
import Slider from '../slider/index.js';
|
|
7
|
+
import {
|
|
8
|
+
videoPlayerControlsVariants,
|
|
9
|
+
videoPlayerOverlayVariants,
|
|
10
|
+
videoPlayerVariants,
|
|
11
|
+
type VideoPlayerProps
|
|
12
|
+
} from './types.js';
|
|
13
|
+
import PlayIcon from '@lucide/svelte/icons/play';
|
|
14
|
+
import PauseIcon from '@lucide/svelte/icons/pause';
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
ref = $bindable(null),
|
|
18
|
+
src,
|
|
19
|
+
poster,
|
|
20
|
+
autoplay = false,
|
|
21
|
+
muted = false,
|
|
22
|
+
controls = true,
|
|
23
|
+
ratio = 16 / 9,
|
|
24
|
+
class: className,
|
|
25
|
+
...restProps
|
|
26
|
+
}: VideoPlayerProps = $props();
|
|
27
|
+
|
|
28
|
+
let time = $state(0);
|
|
29
|
+
let duration = $state(0);
|
|
30
|
+
let paused = $state(true);
|
|
31
|
+
let controlsVisible = $state(true);
|
|
32
|
+
let hideTimer: ReturnType<typeof setTimeout> | undefined;
|
|
33
|
+
|
|
34
|
+
function resetControls() {
|
|
35
|
+
controlsVisible = true;
|
|
36
|
+
clearTimeout(hideTimer);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function scheduleHide(delay: number) {
|
|
40
|
+
hideTimer = setTimeout(() => {
|
|
41
|
+
controlsVisible = false;
|
|
42
|
+
}, delay);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function showControls() {
|
|
46
|
+
resetControls();
|
|
47
|
+
if (!paused) scheduleHide(2500);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function handleMouseLeave() {
|
|
51
|
+
if (!paused) scheduleHide(1000);
|
|
52
|
+
}
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<Card
|
|
56
|
+
bind:ref
|
|
57
|
+
data-slot="video-player"
|
|
58
|
+
class={cn(videoPlayerVariants(), className)}
|
|
59
|
+
onmouseenter={showControls}
|
|
60
|
+
onmousemove={showControls}
|
|
61
|
+
onmouseleave={handleMouseLeave}
|
|
62
|
+
{...restProps}
|
|
63
|
+
>
|
|
64
|
+
<AspectRatio {ratio}>
|
|
65
|
+
<video
|
|
66
|
+
data-slot="video-player-video"
|
|
67
|
+
{src}
|
|
68
|
+
{poster}
|
|
69
|
+
{autoplay}
|
|
70
|
+
{muted}
|
|
71
|
+
bind:currentTime={time}
|
|
72
|
+
bind:duration
|
|
73
|
+
bind:paused
|
|
74
|
+
class="absolute inset-0 h-full w-full rounded-xs object-cover"
|
|
75
|
+
onplay={showControls}
|
|
76
|
+
onpause={resetControls}
|
|
77
|
+
onended={resetControls}
|
|
78
|
+
></video>
|
|
79
|
+
|
|
80
|
+
{#if !controls && (paused || controlsVisible)}
|
|
81
|
+
<button
|
|
82
|
+
data-slot="video-player-overlay"
|
|
83
|
+
class={videoPlayerOverlayVariants({ visible: paused || controlsVisible })}
|
|
84
|
+
onclick={() => (paused = !paused)}
|
|
85
|
+
aria-label={paused ? 'Play' : 'Pause'}
|
|
86
|
+
>
|
|
87
|
+
<span
|
|
88
|
+
class="bg-background/30 hover:bg-background/40 flex size-14 items-center justify-center rounded-full backdrop-blur-xs transition-colors"
|
|
89
|
+
>
|
|
90
|
+
{#if paused}
|
|
91
|
+
<PlayIcon strokeWidth={1.25} class="text-foreground size-7" aria-hidden="true" />
|
|
92
|
+
{:else}
|
|
93
|
+
<PauseIcon strokeWidth={1.25} class="text-foreground size-7" aria-hidden="true" />
|
|
94
|
+
{/if}
|
|
95
|
+
</span>
|
|
96
|
+
</button>
|
|
97
|
+
{/if}
|
|
98
|
+
|
|
99
|
+
{#if controls}
|
|
100
|
+
<div
|
|
101
|
+
data-slot="video-player-controls"
|
|
102
|
+
class={videoPlayerControlsVariants({ visible: controlsVisible })}
|
|
103
|
+
>
|
|
104
|
+
<Button
|
|
105
|
+
variant="floating"
|
|
106
|
+
size="icon"
|
|
107
|
+
class="bg-background/30 hover:bg-background/40 cursor-pointer rounded-full"
|
|
108
|
+
onclick={() => (paused = !paused)}
|
|
109
|
+
aria-label={paused ? 'Play' : 'Pause'}
|
|
110
|
+
>
|
|
111
|
+
{#if paused}
|
|
112
|
+
<PlayIcon strokeWidth={2} class="text-foreground size-4" aria-hidden="true" />
|
|
113
|
+
{:else}
|
|
114
|
+
<PauseIcon strokeWidth={2} class="text-foreground size-4" aria-hidden="true" />
|
|
115
|
+
{/if}
|
|
116
|
+
</Button>
|
|
117
|
+
|
|
118
|
+
<Slider
|
|
119
|
+
type="multiple"
|
|
120
|
+
value={[time]}
|
|
121
|
+
max={duration || 1}
|
|
122
|
+
step={0.1}
|
|
123
|
+
aria-label="Seek"
|
|
124
|
+
class="**:data-[slot=slider-track]:bg-background/60 **:data-[slot=slider-range]:bg-foreground/90 **:data-[slot=slider-thumb]:bg-foreground max-w-100 min-w-0 flex-1 **:data-[slot=slider-thumb]:size-3.5 **:data-[slot=slider-thumb]:cursor-grab **:data-[slot=slider-thumb]:border-0 **:data-[slot=slider-thumb]:shadow-md **:data-[slot=slider-track]:h-1.5"
|
|
125
|
+
onValueCommit={(v) => {
|
|
126
|
+
time = v[0];
|
|
127
|
+
}}
|
|
128
|
+
/>
|
|
129
|
+
|
|
130
|
+
<span
|
|
131
|
+
data-slot="video-player-time"
|
|
132
|
+
class="bg-background/30 text-foreground rounded-full px-3 py-1.5 whitespace-nowrap"
|
|
133
|
+
>
|
|
134
|
+
{formatMMSS(time)} / {formatMMSS(duration)}
|
|
135
|
+
</span>
|
|
136
|
+
</div>
|
|
137
|
+
{/if}
|
|
138
|
+
</AspectRatio>
|
|
139
|
+
</Card>
|