TypeScript Types
Complete type reference for Sliced Areas.
Import
// Web Component types
import type {
SlicedAreasElement,
AreasLayout,
AreasGraph,
AreaResolver,
AreaResolverResult,
AreaId,
AreaTag,
AreaRect,
AreaAddedDetail,
AreaRemovedDetail,
AreaUpdatedDetail,
SlicedAreasOperation,
SlicedAreasOperationsConfig,
CornerId,
CornerClickDetail,
GraphVert,
GraphEdge,
GraphArea
} from 'sliced-areas'
// Vue types (includes Web Component types)
import type {
AreasLayout,
AreaResolver,
AreaResolverResult,
// ... all Web Component types
} from 'sliced-areas/vue'Layout Types
AreasLayout
Serializable layout object.
type AreasLayout = {
areas: Array<{
id?: AreaId
tag: AreaTag
rect: AreaRect
}>
}id is optional. When omitted, the component auto-assigns a stable identifier.
Usage:
const layout: AreasLayout = {
areas: [
{
id: 'editor',
tag: 'editor',
rect: { left: 0, right: 0.5, top: 1, bottom: 0 }
},
{
id: 'preview',
tag: 'preview',
rect: { left: 0.5, right: 1, top: 1, bottom: 0 }
}
]
}AreaRect
Normalized rectangle in 0..1 coordinate space.
type AreaRect = {
left: number // 0..1
right: number // 0..1
top: number // 0..1 (1 = top, 0 = bottom)
bottom: number // 0..1
}Example:
// Full screen
const fullScreen: AreaRect = {
left: 0,
right: 1,
top: 1,
bottom: 0
}
// Top-left quadrant
const topLeft: AreaRect = {
left: 0,
right: 0.5,
top: 1,
bottom: 0.5
}AreaId
Stable internal identifier for an area.
type AreaId = stringNote: Area IDs are managed internally and should be obtained from the graph or events.
AreaTag
External identifier for area content.
type AreaTag = stringUsage:
const tag: AreaTag = 'editor'
// Tags are user-defined and map to content via the resolverCornerId
Area corner identifiers.
type CornerId = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'Usage:
const corner: CornerId = 'top-left'
// Used in CornerClickDetail eventGraph Types
AreasGraph
Internal planar graph representation.
type AreasGraph = {
verts: Record<VertId, GraphVert>
edges: Record<EdgeId, GraphEdge>
areas: Record<AreaId, GraphArea>
}Usage:
const graph: AreasGraph = element.graph
// Access vertices
Object.values(graph.verts).forEach(vert => {
console.log(`Vertex ${vert.id} at (${vert.x}, ${vert.y})`)
})GraphVert
Graph vertex with normalized coordinates.
type GraphVert = {
id: VertId
x: number // 0..1
y: number // 0..1
}GraphEdge
Graph edge connecting two vertices.
type GraphEdge = {
id: EdgeId
v1: VertId // First vertex
v2: VertId // Second vertex
border: boolean // True if on container border
}GraphArea
Area represented by four ordered vertices.
type GraphArea = {
id: AreaId
v1: VertId // Top-left
v2: VertId // Top-right
v3: VertId // Bottom-right
v4: VertId // Bottom-left
}Note: Vertices are ordered clockwise starting from top-left.
Function Types
AreaResolverResult
Content resolver return type.
type AreaResolverResult =
| HTMLElement
| {
element: HTMLElement
cleanup?: () => void
}
| null
| undefinedNotes:
- When you return
{ element, cleanup }, the cleanup callback runs when the area is removed or replaced. - The
elementfield must be anHTMLElement; non-elements are treated asnull. - Returning
nullorundefinedskips resolving content for that call.
AreaResolver
Content resolver function.
type AreaResolver = {
(tag: AreaTag, areaId: AreaId): AreaResolverResult
(tag: AreaTag): AreaResolverResult
}Parameters:
tag: The area tag to resolveareaId: Stable identifier for the specific area instance
Returns:
HTMLElementor{ element, cleanup }: Content to display in the areanullorundefined: Skip rendering for this tag
Example:
const resolver: AreaResolver = (tag: AreaTag, areaId: AreaId): AreaResolverResult => {
if (tag === 'editor') {
const textarea = document.createElement('textarea')
textarea.style.cssText = 'width: 100%; height: 100%;'
return {
element: textarea,
cleanup: () => {
console.log(`Dispose editor for ${areaId}`)
},
}
}
if (tag === 'preview') {
const div = document.createElement('div')
div.textContent = 'Preview'
return div
}
return null
}SlicedAreasOperation
Operation identifiers for enabling or disabling behavior.
type SlicedAreasOperation =
| 'resize'
| 'split'
| 'join'
| 'replace'
| 'swap'
| 'move'
| 'maximize'
| 'restore'SlicedAreasOperationsConfig
Configuration for which operations are enabled.
type SlicedAreasOperationsConfig = {
enable?: SlicedAreasOperation[]
disable?: SlicedAreasOperation[]
}Event Types
CornerClickDetail
Event detail for corner click events.
type CornerClickDetail = {
areaId: AreaId
corner: CornerId
clientX: number
clientY: number
}Usage:
element.addEventListener('sliced-areas:cornerclick', (e: CustomEvent<CornerClickDetail>) => {
const { areaId, corner, clientX, clientY } = e.detail
console.log(`Area ${areaId}, corner ${corner} clicked at (${clientX}, ${clientY})`)
})AreaAddedDetail
Event detail for new areas.
type AreaAddedDetail = {
areaId: AreaId
tag: AreaTag
rect: AreaRect
}AreaRemovedDetail
Event detail for removed areas.
type AreaRemovedDetail = {
areaId: AreaId
tag: AreaTag
}AreaUpdatedDetail
Event detail for updated areas.
type AreaUpdatedDetail = {
areaId: AreaId
tag: AreaTag
oldRect: AreaRect
newRect: AreaRect
}Element Types
SlicedAreasElement
The Web Component element class.
class SlicedAreasElement extends HTMLElement {
// Properties
layout: AreasLayout | null
operations: SlicedAreasOperationsConfig | null
readonly graph: AreasGraph | null
// Methods
setResolver(resolver: AreaResolver | null): void
split(sourceAreaId: AreaId, zone?: string, clientX?: number, clientY?: number): void
join(sourceAreaId: AreaId, targetAreaId: AreaId): void
replace(sourceAreaId: AreaId, targetAreaId: AreaId): void
swap(sourceAreaId: AreaId, targetAreaId: AreaId): void
close(areaId: AreaId): void
retag(areaId: AreaId, tag: AreaTag): void
maximize(areaId: AreaId): void
restore(): void
// Lifecycle
connectedCallback(): void
disconnectedCallback(): void
}Usage:
const element = document.querySelector('sliced-areas') as SlicedAreasElement
element.layout = { areas: [...] }
element.setResolver((tag) => ...)Internal Types
These types are exported but intended for advanced use cases.
VertId
Internal vertex identifier.
type VertId = stringEdgeId
Internal edge identifier.
type EdgeId = stringType Guards
Check if layout is valid
function isValidLayout(layout: unknown): layout is AreasLayout {
if (!layout || typeof layout !== 'object') return false
const l = layout as AreasLayout
return (
Array.isArray(l.areas) &&
l.areas.every(area =>
typeof area.tag === 'string' &&
typeof area.rect === 'object' &&
typeof area.rect.left === 'number' &&
typeof area.rect.right === 'number' &&
typeof area.rect.top === 'number' &&
typeof area.rect.bottom === 'number'
)
)
}Check if rect is normalized
function isNormalizedRect(rect: AreaRect): boolean {
return (
rect.left >= 0 && rect.left <= 1 &&
rect.right >= 0 && rect.right <= 1 &&
rect.top >= 0 && rect.top <= 1 &&
rect.bottom >= 0 && rect.bottom <= 1 &&
rect.left < rect.right &&
rect.bottom < rect.top
)
}Utility Types
Extract area tags
type ExtractTags<T extends AreasLayout> = T['areas'][number]['tag']
// Usage
type MyLayout = {
areas: Array<{ tag: 'editor' | 'preview', rect: AreaRect }>
}
type MyTags = ExtractTags<MyLayout> // 'editor' | 'preview'Typed resolver
type TypedResolver<T extends string> = (tag: T, areaId: AreaId) => AreaResolverResult
// Usage
type MyTags = 'editor' | 'preview'
const resolver: TypedResolver<MyTags> = (tag, areaId) => {
// tag is strongly typed as 'editor' | 'preview'
switch (tag) {
case 'editor': return { element: createEditor(), cleanup: () => disposeEditor(areaId) }
case 'preview': return createPreview()
}
}Examples
Full typed component
import type {
SlicedAreasElement,
AreasLayout,
AreaResolver,
AreaResolverResult,
AreaId,
CornerClickDetail
} from 'sliced-areas'
class MyApp {
private element: SlicedAreasElement
private layout: AreasLayout
constructor() {
this.element = document.querySelector('sliced-areas')!
this.layout = {
areas: [
{ tag: 'main', rect: { left: 0, right: 1, top: 1, bottom: 0 } }
]
}
this.setup()
}
private setup(): void {
this.element.layout = this.layout
this.element.setResolver(this.createResolver())
this.element.addEventListener('sliced-areas:layoutchange', this.handleLayoutChange)
this.element.addEventListener('sliced-areas:cornerclick', this.handleCornerClick)
}
private createResolver(): AreaResolver {
return (tag: string, areaId: AreaId): AreaResolverResult => {
const div = document.createElement('div')
div.textContent = `Area: ${tag}`
return { element: div, cleanup: () => console.log(`Cleanup ${areaId}`) }
}
}
private handleLayoutChange = (e: CustomEvent<{ layout: AreasLayout }>): void => {
this.layout = e.detail.layout
localStorage.setItem('layout', JSON.stringify(this.layout))
}
private handleCornerClick = (e: CustomEvent<CornerClickDetail>): void => {
const { areaId, corner, clientX, clientY } = e.detail
console.log(`Corner ${corner} of area ${areaId} clicked`)
}
}Vue typed component
<script setup lang="ts">
import { ref } from 'vue'
import { SlicedAreas } from 'sliced-areas/vue'
import type { AreasLayout, AreaResolver, CornerClickDetail } from 'sliced-areas/vue'
const layout = ref<AreasLayout>({
areas: [
{ tag: 'editor', rect: { left: 0, right: 0.5, top: 1, bottom: 0 } },
{ tag: 'preview', rect: { left: 0.5, right: 1, top: 1, bottom: 0 } }
]
})
const resolveArea: AreaResolver = (tag: string, areaId: string) => {
const div = document.createElement('div')
div.textContent = `${tag} (${areaId})`
return div
}
const handleLayoutChange = (detail: { layout: AreasLayout }): void => {
layout.value = detail.layout
}
const handleCornerClick = (detail: CornerClickDetail): void => {
console.log(`Corner ${detail.corner} clicked on area ${detail.areaId}`)
}
</script>
<template>
<SlicedAreas
:layout="layout"
:resolver="resolveArea"
@layoutchange="handleLayoutChange"
@cornerclick="handleCornerClick"
/>
</template>See Also
- Web Component API - Web Component methods and properties
- Vue API - Vue component reference
- Core Concepts - Understanding the types in context