schema and interactive store

This commit is contained in:
wass08
2026-03-06 13:06:33 +01:00
parent 3e40c1dde0
commit 927ecba054
6 changed files with 168 additions and 7 deletions
+73 -1
View File
@@ -2,6 +2,77 @@ import dedent from 'dedent'
import { z } from 'zod'
import { BaseNode, nodeType, objectId } from '../base'
// --- Control descriptors ---
const toggleControlSchema = z.object({
kind: z.literal('toggle'),
label: z.string().optional(),
})
const sliderControlSchema = z.object({
kind: z.literal('slider'),
label: z.string(),
min: z.number(),
max: z.number(),
step: z.number().default(1),
unit: z.string().optional(),
displayMode: z.enum(['slider', 'stepper', 'dial']).default('slider'),
})
const temperatureControlSchema = z.object({
kind: z.literal('temperature'),
label: z.string().default('Temperature'),
min: z.number().default(16),
max: z.number().default(30),
unit: z.enum(['C', 'F']).default('C'),
})
const controlSchema = z.discriminatedUnion('kind', [
toggleControlSchema,
sliderControlSchema,
temperatureControlSchema,
])
// --- Effect descriptors ---
const animationEffectSchema = z.object({
kind: z.literal('animation'),
clips: z.object({
on: z.string().optional(),
off: z.string().optional(),
loop: z.string().optional(),
}),
})
const lightEffectSchema = z.object({
kind: z.literal('light'),
color: z.string().default('#ffffff'),
intensityRange: z.tuple([z.number(), z.number()]),
distance: z.number().optional(),
offset: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
})
const effectSchema = z.discriminatedUnion('kind', [
animationEffectSchema,
lightEffectSchema,
])
// --- Interactive descriptor ---
const interactiveSchema = z.object({
controls: z.array(controlSchema).default([]),
effects: z.array(effectSchema).default([]),
})
export type ToggleControl = z.infer<typeof toggleControlSchema>
export type SliderControl = z.infer<typeof sliderControlSchema>
export type TemperatureControl = z.infer<typeof temperatureControlSchema>
export type Control = z.infer<typeof controlSchema>
export type AnimationEffect = z.infer<typeof animationEffectSchema>
export type LightEffect = z.infer<typeof lightEffectSchema>
export type Effect = z.infer<typeof effectSchema>
export type Interactive = z.infer<typeof interactiveSchema>
const assetSchema = z.object({
id: z.string(),
category: z.string(),
@@ -17,9 +88,10 @@ const assetSchema = z.object({
scale: z.tuple([z.number(), z.number(), z.number()]).default([1, 1, 1]),
surface: z
.object({
height: z.number(), // where things rest
height: z.number(), // where things rest
})
.optional(), // undefined = can't place things on it
interactive: interactiveSchema.optional(),
})
export type AssetInput = z.input<typeof assetSchema>