or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdmachine-creation.mdtype-system.mdutilities.md

machine-creation.mddocs/

0

# Machine Creation

1

2

Core machine creation and setup utilities for defining finite state machines with typed schemas, guards, and transition logic.

3

4

## Capabilities

5

6

### Create Machine

7

8

Creates a new finite state machine from configuration with full type safety and schema validation.

9

10

```typescript { .api }

11

/**

12

* Creates a new finite state machine from configuration

13

* @param config - Machine configuration defining states, transitions, context, and behavior

14

* @returns Machine configuration (use with a runtime service to execute)

15

*/

16

function createMachine<T extends MachineSchema>(config: Machine<T>): Machine<T>;

17

18

interface Machine<T extends MachineSchema> {

19

/** Enable debug logging for state transitions */

20

debug?: boolean | undefined;

21

/** Function that returns props object for the machine */

22

props?: ((params: PropsParams<T>) => T["props"]) | undefined;

23

/** Function that returns bindable context values */

24

context?: ((params: ContextParams<T>) => {

25

[K in keyof T["context"]]: Bindable<T["context"][K]>

26

}) | undefined;

27

/** Computed values derived from context and props */

28

computed?: {

29

[K in keyof T["computed"]]: (params: ComputedParams<T>) => T["computed"][K]

30

} | undefined;

31

/** Function that returns the initial state based on props */

32

initialState: (params: { prop: PropFn<T> }) => T["state"];

33

/** Actions to execute when entering the machine */

34

entry?: ActionsOrFn<T> | undefined;

35

/** Actions to execute when exiting the machine */

36

exit?: ActionsOrFn<T> | undefined;

37

/** Effects to run while the machine is active */

38

effects?: EffectsOrFn<T> | undefined;

39

/** Function that returns refs object for DOM elements */

40

refs?: ((params: RefsParams<T>) => T["refs"]) | undefined;

41

/** Watch function called on every state change */

42

watch?: ((params: Params<T>) => void) | undefined;

43

/** Global event handlers (fallback when state doesn't handle event) */

44

on?: {

45

[E in T["event"]["type"]]?: Transition<T> | Array<Transition<T>>

46

} | undefined;

47

/** State node definitions */

48

states: {

49

[K in T["state"]]: {

50

/** Tags associated with this state */

51

tags?: T["tag"][] | undefined;

52

/** Actions to execute when entering this state */

53

entry?: ActionsOrFn<T> | undefined;

54

/** Actions to execute when exiting this state */

55

exit?: ActionsOrFn<T> | undefined;

56

/** Effects to run while in this state */

57

effects?: EffectsOrFn<T> | undefined;

58

/** Event handlers for this state */

59

on?: {

60

[E in T["event"]["type"]]?: Transition<T> | Array<Transition<T>>

61

} | undefined;

62

}

63

};

64

/** Implementation functions for guards, actions, and effects */

65

implementations?: {

66

guards?: {

67

[K in T["guard"]]: (params: Params<T>) => boolean

68

} | undefined;

69

actions?: {

70

[K in T["action"]]: (params: Params<T>) => void

71

} | undefined;

72

effects?: {

73

[K in T["effect"]]: (params: Params<T>) => void | VoidFunction

74

} | undefined;

75

} | undefined;

76

}

77

```

78

79

**Usage Examples:**

80

81

```typescript

82

import { createMachine, MachineSchema } from "@zag-js/core";

83

84

// Simple toggle machine

85

interface ToggleMachine extends MachineSchema {

86

state: "inactive" | "active";

87

event: { type: "TOGGLE" };

88

}

89

90

const toggleMachine = createMachine<ToggleMachine>({

91

initialState: () => "inactive",

92

states: {

93

inactive: {

94

on: { TOGGLE: { target: "active" } }

95

},

96

active: {

97

on: { TOGGLE: { target: "inactive" } }

98

}

99

}

100

});

101

102

// Machine with context and actions

103

interface CounterMachine extends MachineSchema {

104

state: "idle" | "counting";

105

context: { count: number; step: number };

106

event: { type: "INCREMENT" } | { type: "DECREMENT" } | { type: "SET_STEP"; step: number };

107

action: "increment" | "decrement" | "setStep";

108

}

109

110

const counterMachine = createMachine<CounterMachine>({

111

initialState: () => "idle",

112

context: ({ bindable }) => ({

113

count: bindable(() => ({ defaultValue: 0 })),

114

step: bindable(() => ({ defaultValue: 1 }))

115

}),

116

states: {

117

idle: {

118

on: {

119

INCREMENT: { target: "counting", actions: ["increment"] },

120

DECREMENT: { target: "counting", actions: ["decrement"] },

121

SET_STEP: { actions: ["setStep"] }

122

}

123

},

124

counting: {

125

on: {

126

INCREMENT: { actions: ["increment"] },

127

DECREMENT: { actions: ["decrement"] }

128

}

129

}

130

},

131

implementations: {

132

actions: {

133

increment: ({ context }) => context.set("count", (prev) => prev + context.get("step")),

134

decrement: ({ context }) => context.set("count", (prev) => prev - context.get("step")),

135

setStep: ({ context, event }) => context.set("step", event.step)

136

}

137

}

138

});

139

```

140

141

### Setup Function

142

143

Returns setup utilities for machine creation with typed guards and transition choosers.

144

145

```typescript { .api }

146

/**

147

* Returns setup utilities for machine creation with typed guards and choosers

148

* @returns Object with guards, createMachine, and choose utilities

149

*/

150

function setup<T extends MachineSchema>(): {

151

guards: GuardUtilities<T>;

152

createMachine: (config: Machine<T>) => Machine<T>;

153

choose: (transitions: Transition<T> | Transition<T>[]) => (params: Params<T>) => T["action"][] | undefined;

154

};

155

156

interface GuardUtilities<T extends MachineSchema> {

157

/** Logical AND combination of guards */

158

and(...guards: Array<GuardFn<T> | T["guard"]>): GuardFn<T>;

159

/** Logical OR combination of guards */

160

or(...guards: Array<GuardFn<T> | T["guard"]>): GuardFn<T>;

161

/** Logical NOT negation of guard */

162

not(guard: GuardFn<T> | T["guard"]): GuardFn<T>;

163

}

164

```

165

166

**Usage Examples:**

167

168

```typescript

169

import { setup, MachineSchema } from "@zag-js/core";

170

171

interface FormMachine extends MachineSchema {

172

state: "idle" | "validating" | "valid" | "invalid";

173

context: { email: string; isValid: boolean };

174

guard: "isEmailValid" | "isEmailEmpty";

175

action: "validate" | "clear";

176

}

177

178

const { guards, createMachine } = setup<FormMachine>();

179

180

const formMachine = createMachine({

181

initialState: () => "idle",

182

states: {

183

idle: {

184

on: {

185

VALIDATE: {

186

target: "validating",

187

guard: guards.not("isEmailEmpty")

188

}

189

}

190

},

191

validating: {

192

entry: ["validate"],

193

on: {

194

VALIDATION_COMPLETE: [

195

{ target: "valid", guard: "isEmailValid" },

196

{ target: "invalid", guard: guards.not("isEmailValid") }

197

]

198

}

199

},

200

valid: {

201

on: { CLEAR: { target: "idle", actions: ["clear"] } }

202

},

203

invalid: {

204

on: { CLEAR: { target: "idle", actions: ["clear"] } }

205

}

206

},

207

implementations: {

208

guards: {

209

isEmailValid: ({ context }) => /\S+@\S+\.\S+/.test(context.get("email")),

210

isEmailEmpty: ({ context }) => context.get("email").trim() === ""

211

},

212

actions: {

213

validate: ({ context, send }) => {

214

// Simulate async validation

215

setTimeout(() => send({ type: "VALIDATION_COMPLETE" }), 100);

216

},

217

clear: ({ context }) => context.set("email", "")

218

}

219

}

220

});

221

```

222

223

### Create Guards

224

225

Creates logical guard combinations for complex conditional logic in state transitions.

226

227

```typescript { .api }

228

/**

229

* Creates logical guard combinations (and, or, not)

230

* @returns Object with logical guard combination functions

231

*/

232

function createGuards<T extends MachineSchema>(): GuardUtilities<T>;

233

```

234

235

**Usage Examples:**

236

237

```typescript

238

import { createGuards, MachineSchema } from "@zag-js/core";

239

240

interface AuthMachine extends MachineSchema {

241

state: "idle" | "loading" | "success" | "error";

242

context: { user: User | null; attempts: number };

243

guard: "isLoggedIn" | "hasMaxAttempts" | "isValidUser";

244

action: "login" | "logout" | "incrementAttempts";

245

}

246

247

const guards = createGuards<AuthMachine>();

248

249

// Using guard combinations

250

const loginGuard = guards.and("isValidUser", guards.not("hasMaxAttempts"));

251

const logoutGuard = guards.or("isLoggedIn", guards.not("isValidUser"));

252

```

253

254

## Supporting Types

255

256

```typescript { .api }

257

interface Transition<T extends MachineSchema> {

258

/** Target state to transition to */

259

target?: T["state"] | undefined;

260

/** Actions to execute during transition */

261

actions?: T["action"][] | undefined;

262

/** Guard condition that must pass for transition */

263

guard?: T["guard"] | GuardFn<T> | undefined;

264

/** Allow re-entering the same state */

265

reenter?: boolean | undefined;

266

}

267

268

type ActionsOrFn<T extends MachineSchema> =

269

T["action"][] | ((params: Params<T>) => T["action"][] | undefined);

270

271

type EffectsOrFn<T extends MachineSchema> =

272

T["effect"][] | ((params: Params<T>) => T["effect"][] | undefined);

273

274

type GuardFn<T extends MachineSchema> = (params: Params<T>) => boolean;

275

276

interface PropsParams<T extends MachineSchema> {

277

props: Partial<T["props"]>;

278

scope: Scope;

279

}

280

281

interface ContextParams<T extends MachineSchema> {

282

prop: PropFn<T>;

283

bindable: BindableFn;

284

scope: Scope;

285

getContext: () => BindableContext<T>;

286

getComputed: () => ComputedFn<T>;

287

getRefs: () => BindableRefs<T>;

288

getEvent: () => EventType<T["event"]>;

289

flush: (fn: VoidFunction) => void;

290

}

291

292

interface ComputedParams<T extends MachineSchema> {

293

context: BindableContext<T>;

294

event: EventType<T["event"]>;

295

prop: PropFn<T>;

296

refs: BindableRefs<T>;

297

scope: Scope;

298

computed: ComputedFn<T>;

299

}

300

301

interface RefsParams<T extends MachineSchema> {

302

prop: PropFn<T>;

303

context: BindableContext<T>;

304

}

305

```