parent
5895f9d8b8
commit
bdaae718ad
@ -0,0 +1,36 @@
|
|||||||
|
// Slider — eidos compound API, disciplined option C.
|
||||||
|
//
|
||||||
|
// import { Slider } from '$uix/eidos/components/slider';
|
||||||
|
//
|
||||||
|
// <Slider bind:value aria-label="Volume">
|
||||||
|
// <Slider.Range />
|
||||||
|
// <Slider.Thumb />
|
||||||
|
// </Slider>
|
||||||
|
import SliderRoot from './slider.svelte';
|
||||||
|
import Range from './slider-range.svelte';
|
||||||
|
import Thumb from './slider-thumb.svelte';
|
||||||
|
import Tick from './slider-tick.svelte';
|
||||||
|
|
||||||
|
type SliderNamespace = typeof SliderRoot & {
|
||||||
|
Range: typeof Range;
|
||||||
|
Thumb: typeof Thumb;
|
||||||
|
Tick: typeof Tick;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Slider = SliderRoot as SliderNamespace;
|
||||||
|
Slider.Range = Range;
|
||||||
|
Slider.Thumb = Thumb;
|
||||||
|
Slider.Tick = Tick;
|
||||||
|
|
||||||
|
export { Slider };
|
||||||
|
|
||||||
|
export default Slider;
|
||||||
|
|
||||||
|
export type {
|
||||||
|
SliderProps,
|
||||||
|
SliderRangeProps as RangeProps,
|
||||||
|
SliderThumbProps as ThumbProps,
|
||||||
|
SliderTickProps as TickProps,
|
||||||
|
SliderSize,
|
||||||
|
SliderType
|
||||||
|
} from './types';
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Range as SomaSliderRange } from '$soma/components/slider';
|
||||||
|
import type { SliderRangeProps } from './types';
|
||||||
|
|
||||||
|
let { children, ...rest }: SliderRangeProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SomaSliderRange {...rest}>
|
||||||
|
{@render children?.()}
|
||||||
|
</SomaSliderRange>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Thumb as SomaSliderThumb } from '$soma/components/slider';
|
||||||
|
import type { SliderThumbProps } from './types';
|
||||||
|
|
||||||
|
let { children, ...rest }: SliderThumbProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SomaSliderThumb {...rest}>
|
||||||
|
{@render children?.()}
|
||||||
|
</SomaSliderThumb>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Tick as SomaSliderTick } from '$soma/components/slider';
|
||||||
|
import type { SliderTickProps } from './types';
|
||||||
|
|
||||||
|
let { children, ...rest }: SliderTickProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SomaSliderTick {...rest}>
|
||||||
|
{@render children?.()}
|
||||||
|
</SomaSliderTick>
|
||||||
@ -0,0 +1,133 @@
|
|||||||
|
[data-slider] {
|
||||||
|
--_slider-track-size: var(--slider-track-size-md);
|
||||||
|
--_slider-thumb-size: var(--slider-thumb-size-md);
|
||||||
|
--_slider-hit-size: var(--slider-hit-size-md);
|
||||||
|
--_slider-tick-size: var(--slider-tick-size-md);
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider][data-size='sm'] {
|
||||||
|
--_slider-track-size: var(--slider-track-size-sm);
|
||||||
|
--_slider-thumb-size: var(--slider-thumb-size-sm);
|
||||||
|
--_slider-hit-size: var(--slider-hit-size-sm);
|
||||||
|
--_slider-tick-size: var(--slider-tick-size-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider][data-size='lg'] {
|
||||||
|
--_slider-track-size: var(--slider-track-size-lg);
|
||||||
|
--_slider-thumb-size: var(--slider-thumb-size-lg);
|
||||||
|
--_slider-hit-size: var(--slider-hit-size-lg);
|
||||||
|
--_slider-tick-size: var(--slider-tick-size-lg);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider][data-disabled] {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: var(--slider-disabled-opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider][data-orientation='horizontal'] {
|
||||||
|
inline-size: 100%;
|
||||||
|
block-size: var(--_slider-hit-size);
|
||||||
|
min-inline-size: var(--slider-min-inline-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider][data-orientation='vertical'] {
|
||||||
|
inline-size: var(--_slider-hit-size);
|
||||||
|
block-size: var(--slider-min-block-size);
|
||||||
|
min-block-size: var(--slider-min-block-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider]::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
border-radius: var(--slider-track-radius);
|
||||||
|
background: var(--slider-track-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider][data-orientation='horizontal']::before {
|
||||||
|
inset-inline: 0;
|
||||||
|
inset-block-start: 50%;
|
||||||
|
block-size: var(--_slider-track-size);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider][data-orientation='vertical']::before {
|
||||||
|
inset-block: 0;
|
||||||
|
inset-inline-start: 50%;
|
||||||
|
inline-size: var(--_slider-track-size);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider-range] {
|
||||||
|
border-radius: var(--slider-track-radius);
|
||||||
|
background: var(--slider-range-bg);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider-range][data-orientation='horizontal'] {
|
||||||
|
inset-block-start: 50%;
|
||||||
|
block-size: var(--_slider-track-size);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider-range][data-orientation='vertical'] {
|
||||||
|
inset-inline-start: 50%;
|
||||||
|
inline-size: var(--_slider-track-size);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider-thumb] {
|
||||||
|
inline-size: var(--_slider-thumb-size);
|
||||||
|
block-size: var(--_slider-thumb-size);
|
||||||
|
border: var(--slider-thumb-border-width) solid var(--slider-thumb-border);
|
||||||
|
border-radius: var(--slider-thumb-radius);
|
||||||
|
background: var(--slider-thumb-bg);
|
||||||
|
box-shadow: var(--slider-thumb-shadow);
|
||||||
|
cursor: grab;
|
||||||
|
outline: none;
|
||||||
|
transition:
|
||||||
|
background var(--slider-transition-duration) var(--slider-transition-ease),
|
||||||
|
border-color var(--slider-transition-duration) var(--slider-transition-ease),
|
||||||
|
box-shadow var(--slider-transition-duration) var(--slider-transition-ease);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider-thumb]:active {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider-thumb]:focus-visible {
|
||||||
|
box-shadow: var(--slider-thumb-focus-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider-thumb][data-disabled] {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider-tick] {
|
||||||
|
inline-size: var(--_slider-tick-size);
|
||||||
|
block-size: var(--_slider-tick-size);
|
||||||
|
border-radius: var(--slider-tick-radius);
|
||||||
|
background: var(--slider-tick-bg);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider-tick][data-orientation='horizontal'] {
|
||||||
|
inset-block-start: 50%;
|
||||||
|
margin-block-start: calc(var(--_slider-tick-size) / -2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider-tick][data-orientation='vertical'] {
|
||||||
|
inset-inline-start: 50%;
|
||||||
|
margin-inline-start: calc(var(--_slider-tick-size) / -2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-slider-tick][data-active] {
|
||||||
|
background: var(--slider-tick-bg-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
[data-slider-thumb] {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
/**
|
||||||
|
* Eidos `<Slider>` — visual wrapper over Soma's slider primitive.
|
||||||
|
* Soma owns pointer/keyboard/value behavior; Eidos adds `size`.
|
||||||
|
*/
|
||||||
|
import { ActiveEidos } from '$uix/eidos';
|
||||||
|
import { Provider as SomaSliderProvider } from '$soma/components/slider';
|
||||||
|
import type { SliderProps } from './types';
|
||||||
|
|
||||||
|
let { size = 'md', value = $bindable([0]), children, ...rest }: SliderProps = $props();
|
||||||
|
|
||||||
|
const eidos = ActiveEidos.require();
|
||||||
|
const resolvedSize = $derived(eidos.resolve(size, 'md'));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<SomaSliderProvider {...rest} bind:value data-size={resolvedSize}>
|
||||||
|
{@render children?.()}
|
||||||
|
</SomaSliderProvider>
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
import type {
|
||||||
|
ProviderProps as SomaSliderProviderProps,
|
||||||
|
RangeProps as SomaSliderRangeProps,
|
||||||
|
SliderType,
|
||||||
|
ThumbProps as SomaSliderThumbProps,
|
||||||
|
TickProps as SomaSliderTickProps
|
||||||
|
} from '$soma/components/slider';
|
||||||
|
import type { ResponsiveProp, Size } from '$uix/eidos/lib/types';
|
||||||
|
|
||||||
|
export type SliderSize = Extract<Size, 'sm' | 'md' | 'lg'>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Props for the eidos `<Slider>`.
|
||||||
|
*
|
||||||
|
* Extends Soma's slider with visual sizing only. Orientation, disabled state,
|
||||||
|
* range position, thumb position and ARIA are owned by Soma.
|
||||||
|
*/
|
||||||
|
export type SliderProps = SomaSliderProviderProps & {
|
||||||
|
/** Visual size. Accepts a responsive map resolved by ActiveEidos. @default 'md' */
|
||||||
|
size?: ResponsiveProp<SliderSize>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SliderRangeProps = SomaSliderRangeProps;
|
||||||
|
export type SliderThumbProps = SomaSliderThumbProps;
|
||||||
|
export type SliderTickProps = SomaSliderTickProps;
|
||||||
|
export type { SliderType };
|
||||||
Loading…
Reference in new issue