Files
upstream-mirror a774ac673a
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled
snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
2026-09-23 16:12:52 +05:00

180 lines
5.3 KiB
TypeScript

import { z } from 'zod'
import { SimpleShapeIdSchema } from '../types/ids-schema'
import { FocusedColor } from './FocusedColor'
import { FocusedFillSchema } from './FocusedFill'
import { FocusedFontSize } from './FocusedFontSize'
import { FocusedGeoShapeTypeSchema } from './FocusedGeoShapeType'
const FocusedLabel = z.string()
export const FocusedTextAnchorSchema = z.enum([
'bottom-center',
'bottom-left',
'bottom-right',
'center-left',
'center-right',
'center',
'top-center',
'top-left',
'top-right',
])
export type FocusedTextAnchor = z.infer<typeof FocusedTextAnchorSchema>
export const FocusedGeoShape = z.object({
_type: FocusedGeoShapeTypeSchema,
color: FocusedColor,
fill: FocusedFillSchema,
h: z.number(),
note: z.string(),
shapeId: SimpleShapeIdSchema,
text: FocusedLabel.optional(),
textAlign: z.enum(['start', 'middle', 'end']).optional(),
w: z.number(),
x: z.number(),
y: z.number(),
})
export type FocusedGeoShape = z.infer<typeof FocusedGeoShape>
export const FocusedGeoShapePartialSchema = FocusedGeoShape.partial()
export type FocusedGeoShapePartial = z.infer<typeof FocusedGeoShapePartialSchema>
const FocusedLineShape = z.object({
_type: z.literal('line'),
color: FocusedColor,
note: z.string(),
shapeId: SimpleShapeIdSchema,
x1: z.number(),
x2: z.number(),
y1: z.number(),
y2: z.number(),
})
export type FocusedLineShape = z.infer<typeof FocusedLineShape>
const FocusedNoteShape = z.object({
_type: z.literal('note'),
color: FocusedColor,
note: z.string(),
shapeId: SimpleShapeIdSchema,
text: FocusedLabel.optional(),
x: z.number(),
y: z.number(),
})
export type FocusedNoteShape = z.infer<typeof FocusedNoteShape>
const FocusedTextShape = z
.object({
_type: z.literal('text'),
anchor: FocusedTextAnchorSchema,
color: FocusedColor,
fontSize: FocusedFontSize.optional(),
maxWidth: z.number().nullable(),
note: z.string(),
shapeId: SimpleShapeIdSchema,
text: FocusedLabel,
x: z.number(),
y: z.number(),
})
.meta({
title: 'Text Shape',
description:
'A text shape is a shape that contains text. The `anchor` property indicates how the text shape is positioned and aligned. For example, the "top-left" anchor means the text shape\'s x and y coordinates are the top left corner of the text shape, and the text gets left aligned. A shape with the "bottom-center" anchor means the text shape\'s x and y coordinates are the bottom center of the text shape, and the text gets center aligned on the horizontal axis. By default, text shapes auto-size to fit their content. If you provide a `maxWidth`, the text will automatically wrap to the next line if it exceeds that width (there is no need to add manual line breaks for word wrapping).',
})
export type FocusedTextShape = z.infer<typeof FocusedTextShape>
export const FocusedTextShapePartialSchema = FocusedTextShape.partial()
export type FocusedTextShapePartial = z.infer<typeof FocusedTextShapePartialSchema>
const FocusedArrowShape = z.object({
_type: z.literal('arrow'),
color: FocusedColor,
fromId: SimpleShapeIdSchema.nullable(),
note: z.string(),
shapeId: SimpleShapeIdSchema,
text: z.string().optional(),
toId: SimpleShapeIdSchema.nullable(),
x1: z.number(),
x2: z.number(),
y1: z.number(),
y2: z.number(),
bend: z.number().optional(),
})
export type FocusedArrowShape = z.infer<typeof FocusedArrowShape>
const FocusedDrawShape = z
.object({
_type: z.literal('draw'),
color: FocusedColor,
fill: FocusedFillSchema.optional(),
note: z.string(),
shapeId: SimpleShapeIdSchema,
})
.meta({
title: 'Draw Shape',
description:
'A draw shape is a freeform shape that was drawn by the pen tool. IMPORTANT: Do not create draw shapes with the "create" action. To create new draw shapes, the AI must use the pen event because it gives more control.',
})
export type FocusedDrawShape = z.infer<typeof FocusedDrawShape>
const FocusedUnknownShape = z
.object({
_type: z.literal('unknown'),
note: z.string(),
shapeId: SimpleShapeIdSchema,
subType: z.string(),
x: z.number(),
y: z.number(),
})
.meta({
title: 'Unknown Shape',
description:
"A special shape that is not represented by one of the canvas's core shape types. The AI cannot create these shapes, but it *can* interact with them. eg: The AI can move these shapes. The `subType` property contains the internal name of the shape's type.",
})
export type FocusedUnknownShape = z.infer<typeof FocusedUnknownShape>
const FOCUSED_SHAPES = [
FocusedDrawShape,
FocusedGeoShape,
FocusedLineShape,
FocusedTextShape,
FocusedArrowShape,
FocusedNoteShape,
FocusedUnknownShape,
] as const
export const FocusedShapeSchema = z.union(FOCUSED_SHAPES)
export type FocusedShape = z.infer<typeof FocusedShapeSchema>
export type FocusedShapePartial = Partial<FocusedShape>
/**
* Extract all shape type names from the schema
*/
export function getFocusedShapeSchemaNames() {
const typeNames: FocusedShape['_type'][] = []
for (const shapeSchema of FOCUSED_SHAPES) {
const typeField = shapeSchema.shape._type
if (typeField) {
// Handle ZodLiterals (like FocusedDrawShape)
if ('value' in typeField && typeof typeField.value === 'string') {
typeNames.push(typeField.value)
}
// Handle ZodEnums (like FocusedGeoShape)
else if ('options' in typeField && Array.isArray(typeField.options)) {
typeNames.push(...typeField.options)
}
}
}
return typeNames
}