or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcomponent-definition.mdconfiguration.mdindex.mdprops-models.mdsyntax-sugar.md

component-definition.mddocs/

0

# Component Definition

1

2

Core macros for Vue component definition and configuration.

3

4

## Capabilities

5

6

### Define Options

7

8

Define component options within `<script setup>` blocks.

9

10

```typescript { .api }

11

/**

12

* Define component options (Vue 2.7+ / Vue 3.0-3.2)

13

* @param options - Component options object

14

*/

15

declare function defineOptions<

16

RawBindings = {},

17

D = {},

18

C extends ComputedOptions = {},

19

M extends MethodOptions = {},

20

Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,

21

Extends extends ComponentOptionsMixin = ComponentOptionsMixin,

22

>(

23

options?: ComponentOptionsWithoutProps<

24

{},

25

RawBindings,

26

D,

27

C,

28

M,

29

Mixin,

30

Extends

31

> & {

32

emits?: undefined;

33

expose?: undefined;

34

slots?: undefined;

35

}

36

): void;

37

38

// Component options type (from Vue)

39

type ComponentOptionsWithoutProps<

40

V = {},

41

D = {},

42

C extends ComputedOptions = {},

43

M extends MethodOptions = {},

44

Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,

45

Extends extends ComponentOptionsMixin = ComponentOptionsMixin

46

> = ComponentOptionsBase<V, D, C, M, Mixin, Extends> & {

47

props?: undefined;

48

} & ThisType<CreateComponentPublicInstance<{}, RawBindings, D, C, M, Mixin, Extends>>;

49

```

50

51

**Usage Examples:**

52

53

```vue

54

<script setup>

55

import { someDirective } from './directives';

56

import { mixinA, mixinB } from './mixins';

57

58

// Define component options

59

defineOptions({

60

name: "MyComponent",

61

inheritAttrs: false,

62

63

// Local registrations

64

components: {

65

CustomButton: () => import('./CustomButton.vue'),

66

},

67

68

directives: {

69

focus: someDirective,

70

},

71

72

// Mixins and extension

73

mixins: [mixinA, mixinB],

74

extends: BaseComponent,

75

76

// Lifecycle hooks

77

beforeCreate() {

78

console.log('Component being created');

79

},

80

81

created() {

82

console.log('Component created');

83

},

84

85

// Additional options

86

provide() {

87

return {

88

theme: 'dark',

89

};

90

},

91

});

92

93

// Your composition API code

94

const count = ref(0);

95

</script>

96

```

97

98

### Define Slots

99

100

Define component slots with TypeScript support.

101

102

```typescript { .api }

103

/**

104

* Define component slots with types (Vue 2.7+ / Vue 3.0-3.2)

105

* @returns Slots object with type definitions

106

*/

107

declare function defineSlots<

108

S extends Record<string, any> = Record<string, any>

109

>(): UnwrapSlotsType<S>;

110

111

// Slots utility types

112

type UnwrapSlotsType<S> = {

113

[K in keyof S]: S[K] extends (...args: any[]) => any ? S[K] : Slot<S[K]>;

114

};

115

116

type Slot<T = any> = (...args: T extends any ? [T] : []) => VNode[];

117

118

// Slots type inference

119

type SlotsType<T extends Record<string, any>> = {

120

[K in keyof T]: T[K] extends (...args: infer P) => any

121

? (...args: P) => VNode[]

122

: Slot<T[K]>;

123

};

124

```

125

126

**Usage Examples:**

127

128

```vue

129

<script setup>

130

// Define slots with types

131

const slots = defineSlots<{

132

default(): any;

133

header(props: { title: string; level: number }): any;

134

footer(props: { year: number }): any;

135

item(props: { item: any; index: number }): any;

136

}>();

137

138

// Check if slots exist

139

const hasHeader = !!slots.header;

140

const hasFooter = !!slots.footer;

141

142

// Use in render logic

143

function renderContent() {

144

return [

145

slots.header?.({ title: "My Title", level: 1 }),

146

slots.default?.(),

147

slots.footer?.({ year: new Date().getFullYear() }),

148

];

149

}

150

</script>

151

152

<template>

153

<div class="component">

154

<header v-if="hasHeader">

155

<slot name="header" :title="title" :level="1" />

156

</header>

157

158

<main>

159

<slot />

160

</main>

161

162

<footer v-if="hasFooter">

163

<slot name="footer" :year="2024" />

164

</footer>

165

</div>

166

</template>

167

```

168

169

### Define Emit

170

171

Define single emit function with enhanced typing.

172

173

```typescript { .api }

174

/**

175

* Define single emit function with enhanced typing

176

* @param name - Event name

177

* @returns Emit function for the specified event

178

*/

179

declare function defineEmit<T extends (...args: any[]) => any>(

180

name: string

181

): T;

182

183

/**

184

* Define emit with payload type

185

* @param name - Event name

186

* @returns Emit function with typed payload

187

*/

188

declare function defineEmit<T = any>(

189

name: string

190

): (payload: T) => void;

191

192

// Emit function types

193

type EmitFunction<T> = T extends (...args: infer P) => any

194

? (...args: P) => void

195

: (payload: T) => void;

196

```

197

198

**Usage Examples:**

199

200

```vue

201

<script setup>

202

// Define individual emit functions

203

const emitUpdate = defineEmit<(value: string) => void>("update");

204

const emitChange = defineEmit<(oldValue: string, newValue: string) => void>("change");

205

const emitDelete = defineEmit("delete"); // No payload

206

const emitSelect = defineEmit<{ id: number; name: string }>("select");

207

208

// Usage in component logic

209

function handleInput(event: Event) {

210

const value = (event.target as HTMLInputElement).value;

211

emitUpdate(value);

212

}

213

214

function handleChange(oldVal: string, newVal: string) {

215

emitChange(oldVal, newVal);

216

}

217

218

function handleDelete() {

219

emitDelete();

220

}

221

222

function handleSelect(item: { id: number; name: string }) {

223

emitSelect(item);

224

}

225

</script>

226

227

<template>

228

<div>

229

<input @input="handleInput" @change="handleChange" />

230

<button @click="handleDelete">Delete</button>

231

<button @click="handleSelect({ id: 1, name: 'Item' })">Select</button>

232

</div>

233

</template>

234

```

235

236

### Define Render

237

238

Define render function for component.

239

240

```typescript { .api }

241

/**

242

* Define render function for component

243

* @param render - Render function

244

*/

245

declare function defineRender(render: RenderFunction): void;

246

247

/**

248

* Define render function with JSX

249

* @param render - JSX render function

250

*/

251

declare function defineRender(render: () => JSX.Element): void;

252

253

// Render function types

254

type RenderFunction = (

255

props: Record<string, any>,

256

context: SetupContext

257

) => VNode | VNode[] | string | number | null | undefined;

258

259

interface SetupContext<E = EmitsOptions> {

260

attrs: Data;

261

slots: Slots;

262

emit: EmitFunction<E>;

263

expose: (exposed?: Record<string, any>) => void;

264

}

265

```

266

267

**Usage Examples:**

268

269

```vue

270

<script setup>

271

import { h } from 'vue';

272

273

// Props for render function

274

interface Props {

275

title: string;

276

items: Array<{ id: number; name: string }>;

277

}

278

279

const props = defineProps<Props>();

280

281

// Define render function with h()

282

defineRender(() => {

283

return h('div', { class: 'container' }, [

284

h('h1', props.title),

285

h('ul',

286

props.items.map(item =>

287

h('li', { key: item.id }, item.name)

288

)

289

),

290

]);

291

});

292

293

// Alternative: JSX render function

294

// defineRender(() => (

295

// <div class="container">

296

// <h1>{props.title}</h1>

297

// <ul>

298

// {props.items.map(item => (

299

// <li key={item.id}>{item.name}</li>

300

// ))}

301

// </ul>

302

// </div>

303

// ));

304

</script>

305

```

306

307

### Export Expose

308

309

Export values for parent component access.

310

311

```typescript { .api }

312

/**

313

* Export values for parent component access via template refs

314

* @param exposed - Object with exposed values

315

*/

316

declare function exportExpose<T extends Record<string, any>>(

317

exposed: T

318

): void;

319

320

// Alternative syntax using variable names

321

declare function exportExpose<T extends Record<string, any>>(): T;

322

```

323

324

**Usage Examples:**

325

326

```vue

327

<script setup>

328

import { ref, computed } from 'vue';

329

330

const count = ref(0);

331

const message = ref('Hello');

332

333

const doubleCount = computed(() => count.value * 2);

334

335

function increment() {

336

count.value++;

337

}

338

339

function reset() {

340

count.value = 0;

341

message.value = 'Hello';

342

}

343

344

// Export specific methods and values

345

exportExpose({

346

count: readonly(count),

347

message: readonly(message),

348

doubleCount,

349

increment,

350

reset,

351

352

// Can also expose computed or reactive values

353

state: computed(() => ({

354

count: count.value,

355

message: message.value,

356

})),

357

});

358

</script>

359

```

360

361

## Type Definitions

362

363

Supporting types for component definition macros.

364

365

```typescript { .api }

366

// Component option types from Vue

367

interface ComputedOptions {

368

[key: string]: ComputedGetter<any> | WritableComputedOptions<any>;

369

}

370

371

interface MethodOptions {

372

[key: string]: Function;

373

}

374

375

interface ComponentOptionsMixin {

376

[key: string]: any;

377

}

378

379

// Instance types

380

type CreateComponentPublicInstance<

381

P = {},

382

B = {},

383

D = {},

384

C extends ComputedOptions = {},

385

M extends MethodOptions = {},

386

Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,

387

Extends extends ComponentOptionsMixin = ComponentOptionsMixin,

388

PublicProps = P

389

> = ComponentPublicInstance<P, B, D, C, M, Mixin, Extends, PublicProps>;

390

391

// Emit types

392

type EmitsOptions = ObjectEmitsOptions | string[];

393

394

interface ObjectEmitsOptions {

395

[key: string]:

396

| null

397

| ((...args: any[]) => any)

398

| { (...args: any[]): any; };

399

}

400

401

// VNode types

402

type VNodeChild =

403

| VNode

404

| string

405

| number

406

| boolean

407

| null

408

| undefined

409

| VNodeArrayChildren;

410

411

type VNodeArrayChildren = Array<VNodeArrayChildren | VNodeChild>;

412

413

// Data object type

414

type Data = Record<string, unknown>;

415

```