parent
bdaae718ad
commit
f62b32677c
@ -0,0 +1,45 @@
|
||||
// Pagination — eidos compound API, disciplined option C.
|
||||
//
|
||||
// import { Pagination } from '$uix/eidos/components/pagination';
|
||||
//
|
||||
// <Pagination count={120} let:pages>
|
||||
// <Pagination.PrevTrigger>Previous</Pagination.PrevTrigger>
|
||||
// {#each pages as page}
|
||||
// ...
|
||||
// {/each}
|
||||
// <Pagination.NextTrigger>Next</Pagination.NextTrigger>
|
||||
// </Pagination>
|
||||
import PaginationRoot from './pagination.svelte';
|
||||
import PrevTrigger from './pagination-prev-trigger.svelte';
|
||||
import NextTrigger from './pagination-next-trigger.svelte';
|
||||
import Item from './pagination-item.svelte';
|
||||
import Ellipsis from './pagination-ellipsis.svelte';
|
||||
|
||||
type PaginationNamespace = typeof PaginationRoot & {
|
||||
PrevTrigger: typeof PrevTrigger;
|
||||
NextTrigger: typeof NextTrigger;
|
||||
Item: typeof Item;
|
||||
Ellipsis: typeof Ellipsis;
|
||||
};
|
||||
|
||||
const Pagination = PaginationRoot as PaginationNamespace;
|
||||
Pagination.PrevTrigger = PrevTrigger;
|
||||
Pagination.NextTrigger = NextTrigger;
|
||||
Pagination.Item = Item;
|
||||
Pagination.Ellipsis = Ellipsis;
|
||||
|
||||
export { Pagination };
|
||||
|
||||
export default Pagination;
|
||||
|
||||
export type {
|
||||
EllipsisItem,
|
||||
PageItem,
|
||||
PageRange,
|
||||
PaginationProps,
|
||||
PaginationPrevTriggerProps as PrevTriggerProps,
|
||||
PaginationNextTriggerProps as NextTriggerProps,
|
||||
PaginationItemProps as ItemProps,
|
||||
PaginationEllipsisProps as EllipsisProps,
|
||||
PaginationSize
|
||||
} from './types';
|
||||
@ -0,0 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { Ellipsis as SomaPaginationEllipsis } from '$soma/components/pagination';
|
||||
import type { PaginationEllipsisProps } from './types';
|
||||
|
||||
let { children, ...rest }: PaginationEllipsisProps = $props();
|
||||
</script>
|
||||
|
||||
<SomaPaginationEllipsis {...rest}>
|
||||
{@render children?.()}
|
||||
</SomaPaginationEllipsis>
|
||||
@ -0,0 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { Item as SomaPaginationItem } from '$soma/components/pagination';
|
||||
import type { PaginationItemProps } from './types';
|
||||
|
||||
let { children, ...rest }: PaginationItemProps = $props();
|
||||
</script>
|
||||
|
||||
<SomaPaginationItem {...rest}>
|
||||
{@render children?.()}
|
||||
</SomaPaginationItem>
|
||||
@ -0,0 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { NextTrigger as SomaPaginationNextTrigger } from '$soma/components/pagination';
|
||||
import type { PaginationNextTriggerProps } from './types';
|
||||
|
||||
let { children, ...rest }: PaginationNextTriggerProps = $props();
|
||||
</script>
|
||||
|
||||
<SomaPaginationNextTrigger {...rest}>
|
||||
{@render children?.()}
|
||||
</SomaPaginationNextTrigger>
|
||||
@ -0,0 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { PrevTrigger as SomaPaginationPrevTrigger } from '$soma/components/pagination';
|
||||
import type { PaginationPrevTriggerProps } from './types';
|
||||
|
||||
let { children, ...rest }: PaginationPrevTriggerProps = $props();
|
||||
</script>
|
||||
|
||||
<SomaPaginationPrevTrigger {...rest}>
|
||||
{@render children?.()}
|
||||
</SomaPaginationPrevTrigger>
|
||||
@ -0,0 +1,105 @@
|
||||
[data-pagination] {
|
||||
--_pagination-control-size: var(--pagination-control-size-md);
|
||||
--_pagination-control-px: var(--pagination-control-px-md);
|
||||
--_pagination-font-size: var(--pagination-font-size-md);
|
||||
--_pagination-gap: var(--pagination-gap-md);
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--_pagination-gap);
|
||||
font-family: var(--pagination-font-family);
|
||||
font-size: var(--_pagination-font-size);
|
||||
line-height: var(--pagination-line-height);
|
||||
}
|
||||
|
||||
[data-pagination][data-size='sm'] {
|
||||
--_pagination-control-size: var(--pagination-control-size-sm);
|
||||
--_pagination-control-px: var(--pagination-control-px-sm);
|
||||
--_pagination-font-size: var(--pagination-font-size-sm);
|
||||
--_pagination-gap: var(--pagination-gap-sm);
|
||||
}
|
||||
|
||||
[data-pagination][data-size='lg'] {
|
||||
--_pagination-control-size: var(--pagination-control-size-lg);
|
||||
--_pagination-control-px: var(--pagination-control-px-lg);
|
||||
--_pagination-font-size: var(--pagination-font-size-lg);
|
||||
--_pagination-gap: var(--pagination-gap-lg);
|
||||
}
|
||||
|
||||
[data-pagination][data-disabled] {
|
||||
opacity: var(--pagination-disabled-opacity);
|
||||
}
|
||||
|
||||
[data-pagination-prev-trigger],
|
||||
[data-pagination-next-trigger],
|
||||
[data-pagination-item] {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-inline-size: var(--_pagination-control-size);
|
||||
block-size: var(--_pagination-control-size);
|
||||
padding-inline: var(--_pagination-control-px);
|
||||
border: var(--pagination-control-border-width) solid var(--pagination-control-border);
|
||||
border-radius: var(--pagination-control-radius);
|
||||
background: var(--pagination-control-bg);
|
||||
color: var(--pagination-control-color);
|
||||
font: inherit;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
transition:
|
||||
background var(--pagination-transition-duration) var(--pagination-transition-ease),
|
||||
border-color var(--pagination-transition-duration) var(--pagination-transition-ease),
|
||||
color var(--pagination-transition-duration) var(--pagination-transition-ease),
|
||||
box-shadow var(--pagination-transition-duration) var(--pagination-transition-ease);
|
||||
}
|
||||
|
||||
[data-pagination-prev-trigger]:hover:not([data-disabled]),
|
||||
[data-pagination-next-trigger]:hover:not([data-disabled]),
|
||||
[data-pagination-item]:hover:not([data-disabled]) {
|
||||
border-color: var(--pagination-control-border-hover);
|
||||
background: var(--pagination-control-bg-hover);
|
||||
color: var(--pagination-control-color-hover);
|
||||
}
|
||||
|
||||
[data-pagination-prev-trigger]:focus-visible,
|
||||
[data-pagination-next-trigger]:focus-visible,
|
||||
[data-pagination-item]:focus-visible {
|
||||
box-shadow: var(--pagination-focus-shadow);
|
||||
}
|
||||
|
||||
[data-pagination-prev-trigger][data-disabled],
|
||||
[data-pagination-next-trigger][data-disabled],
|
||||
[data-pagination-item][data-disabled] {
|
||||
cursor: not-allowed;
|
||||
opacity: var(--pagination-disabled-opacity);
|
||||
}
|
||||
|
||||
[data-pagination-item][data-selected] {
|
||||
border-color: var(--pagination-selected-border);
|
||||
background: var(--pagination-selected-bg);
|
||||
color: var(--pagination-selected-color);
|
||||
}
|
||||
|
||||
[data-pagination-item][data-selected]:hover {
|
||||
border-color: var(--pagination-selected-border-hover);
|
||||
background: var(--pagination-selected-bg-hover);
|
||||
color: var(--pagination-selected-color);
|
||||
}
|
||||
|
||||
[data-pagination-ellipsis] {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-inline-size: var(--_pagination-control-size);
|
||||
block-size: var(--_pagination-control-size);
|
||||
color: var(--pagination-ellipsis-color);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
[data-pagination-prev-trigger],
|
||||
[data-pagination-next-trigger],
|
||||
[data-pagination-item] {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
/**
|
||||
* Eidos `<Pagination>` — visual wrapper over Soma's pagination primitive.
|
||||
* Soma owns page range calculation and navigation; Eidos adds `size`.
|
||||
*/
|
||||
import { ActiveEidos } from '$uix/eidos';
|
||||
import { Provider as SomaPaginationProvider } from '$soma/components/pagination';
|
||||
import type { PaginationProps } from './types';
|
||||
|
||||
let { size = 'md', page = $bindable(1), children, ...rest }: PaginationProps = $props();
|
||||
|
||||
const eidos = ActiveEidos.require();
|
||||
const resolvedSize = $derived(eidos.resolve(size, 'md'));
|
||||
</script>
|
||||
|
||||
<SomaPaginationProvider {...rest} bind:page data-size={resolvedSize}>
|
||||
{#snippet children(snippetProps)}
|
||||
{@render children?.(snippetProps)}
|
||||
{/snippet}
|
||||
</SomaPaginationProvider>
|
||||
@ -0,0 +1,30 @@
|
||||
import type {
|
||||
EllipsisItem,
|
||||
EllipsisProps as SomaPaginationEllipsisProps,
|
||||
ItemProps as SomaPaginationItemProps,
|
||||
NextTriggerProps as SomaPaginationNextTriggerProps,
|
||||
PageItem,
|
||||
PageRange,
|
||||
PrevTriggerProps as SomaPaginationPrevTriggerProps,
|
||||
ProviderProps as SomaPaginationProviderProps
|
||||
} from '$soma/components/pagination';
|
||||
import type { ResponsiveProp, Size } from '$uix/eidos/lib/types';
|
||||
|
||||
export type PaginationSize = Extract<Size, 'sm' | 'md' | 'lg'>;
|
||||
|
||||
/**
|
||||
* Props for the eidos `<Pagination>`.
|
||||
*
|
||||
* Extends Soma's pagination with visual sizing only. Page calculation,
|
||||
* selected state and disabled state are owned by Soma.
|
||||
*/
|
||||
export type PaginationProps = SomaPaginationProviderProps & {
|
||||
/** Visual size. Accepts a responsive map resolved by ActiveEidos. @default 'md' */
|
||||
size?: ResponsiveProp<PaginationSize>;
|
||||
};
|
||||
|
||||
export type PaginationPrevTriggerProps = SomaPaginationPrevTriggerProps;
|
||||
export type PaginationNextTriggerProps = SomaPaginationNextTriggerProps;
|
||||
export type PaginationItemProps = SomaPaginationItemProps;
|
||||
export type PaginationEllipsisProps = SomaPaginationEllipsisProps;
|
||||
export type { EllipsisItem, PageItem, PageRange };
|
||||
Loading…
Reference in new issue