view-stack.svelte (4219B)
1 <script lang="ts"> 2 import type { Snippet } from "svelte"; 3 import { set_context } from "$lib/utils/app"; 4 import { writable } from "svelte/store"; 5 import { 6 VIEW_CONTEXT_KEY, 7 type ViewContext, 8 type ViewMode, 9 type ViewPointerEvents, 10 } from "./view-context"; 11 12 const DEFAULT_TRANSITION_MS = 260; 13 const DEFAULT_OPACITY_INACTIVE = 0; 14 const DEFAULT_SCALE_INACTIVE = 0.98; 15 const DEFAULT_OFFSET_X = "0px"; 16 const DEFAULT_OFFSET_Y = "12px"; 17 const DEFAULT_BLUR_INACTIVE_PX = 0; 18 const DEFAULT_POINTER_EVENTS_INACTIVE: ViewPointerEvents = "none"; 19 const DEFAULT_Z_INDEX_ACTIVE = 2; 20 const DEFAULT_Z_INDEX_INACTIVE = 1; 21 22 type ViewStackBasis<T extends string> = { 23 active_view: T; 24 mode?: ViewMode; 25 width?: string; 26 height?: string; 27 min_height?: string; 28 padding?: string; 29 gap?: string; 30 direction?: string; 31 align?: string; 32 justify?: string; 33 overflow?: string; 34 background?: string; 35 style?: string; 36 fade?: boolean; 37 transition_ms?: number; 38 opacity_inactive?: number; 39 scale_inactive?: number; 40 offset_x?: string; 41 offset_y?: string; 42 blur_inactive_px?: number; 43 pointer_events_inactive?: ViewPointerEvents; 44 z_index_active?: number; 45 z_index_inactive?: number; 46 }; 47 48 let { 49 basis, 50 children, 51 }: { 52 basis: ViewStackBasis<string>; 53 children: Snippet; 54 } = $props(); 55 56 const view_context = writable<ViewContext<string>>({ 57 active_view: basis.active_view, 58 mode: "stack", 59 fade: true, 60 transition_ms: DEFAULT_TRANSITION_MS, 61 opacity_inactive: DEFAULT_OPACITY_INACTIVE, 62 scale_inactive: DEFAULT_SCALE_INACTIVE, 63 offset_x: DEFAULT_OFFSET_X, 64 offset_y: DEFAULT_OFFSET_Y, 65 blur_inactive_px: DEFAULT_BLUR_INACTIVE_PX, 66 pointer_events_inactive: DEFAULT_POINTER_EVENTS_INACTIVE, 67 z_index_active: DEFAULT_Z_INDEX_ACTIVE, 68 z_index_inactive: DEFAULT_Z_INDEX_INACTIVE, 69 }); 70 71 const view_context_value = $derived({ 72 active_view: basis.active_view, 73 mode: basis.mode ?? "stack", 74 fade: basis.fade ?? true, 75 transition_ms: basis.transition_ms ?? DEFAULT_TRANSITION_MS, 76 opacity_inactive: basis.opacity_inactive ?? DEFAULT_OPACITY_INACTIVE, 77 scale_inactive: basis.scale_inactive ?? DEFAULT_SCALE_INACTIVE, 78 offset_x: basis.offset_x ?? DEFAULT_OFFSET_X, 79 offset_y: basis.offset_y ?? DEFAULT_OFFSET_Y, 80 blur_inactive_px: basis.blur_inactive_px ?? DEFAULT_BLUR_INACTIVE_PX, 81 pointer_events_inactive: 82 basis.pointer_events_inactive ?? DEFAULT_POINTER_EVENTS_INACTIVE, 83 z_index_active: basis.z_index_active ?? DEFAULT_Z_INDEX_ACTIVE, 84 z_index_inactive: basis.z_index_inactive ?? DEFAULT_Z_INDEX_INACTIVE, 85 }); 86 87 set_context(VIEW_CONTEXT_KEY, view_context); 88 89 $effect(() => { 90 view_context.set(view_context_value); 91 }); 92 93 const mode = $derived(basis.mode ?? "stack"); 94 const width = $derived(basis.width ?? "100%"); 95 const height = $derived(basis.height ?? "100%"); 96 const min_height = $derived(basis.min_height ?? "0px"); 97 const padding = $derived(basis.padding ?? "0px"); 98 const gap = $derived(basis.gap ?? "0px"); 99 const direction = $derived(basis.direction ?? "column"); 100 const align = $derived(basis.align ?? "stretch"); 101 const justify = $derived(basis.justify ?? "flex-start"); 102 const overflow = $derived(basis.overflow ?? "hidden"); 103 const background = $derived(basis.background ?? "transparent"); 104 const display = $derived(mode === "flow" ? "flex" : "block"); 105 106 const style = $derived( 107 `position: relative; width: ${width}; height: ${height}; min-height: ${min_height}; padding: ${padding}; display: ${display}; flex-direction: ${direction}; align-items: ${align}; justify-content: ${justify}; gap: ${gap}; overflow: ${overflow}; background: ${background}; isolation: isolate; contain: layout paint style; ${basis.style ?? ""}`, 108 ); 109 </script> 110 111 <div style={style}> 112 {@render children()} 113 </div>