or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcomponent-utilities.mdcomputed.mddependency-injection.mdindex.mdlifecycle.mdreactive-state.mdtypes.mdwatchers.md

component-utilities.mddocs/

0

# Component Utilities

1

2

Utilities for component definition, setup context access, and Vue 3 compatibility features. These utilities provide enhanced component creation with better TypeScript support and composition API integration.

3

4

## Capabilities

5

6

### Component Definition

7

8

Enhanced component definition with better TypeScript inference and composition API support.

9

10

```typescript { .api }

11

/**

12

* Defines a component with enhanced type inference for the composition API

13

* @param setup - Setup function or component options with setup

14

* @returns Component options with proper typing

15

*/

16

function defineComponent<Props, RawBindings = object>(

17

setup: SetupFunction<Props, RawBindings>

18

): ComponentOptions<Vue>;

19

20

/**

21

* Defines a component with options object

22

* @param options - Component options including setup function

23

* @returns Component options with proper typing

24

*/

25

function defineComponent<

26

Props = {},

27

RawBindings = {},

28

D = {},

29

C extends ComputedOptions = {},

30

M extends MethodOptions = {}

31

>(options: ComponentOptionsWithoutProps<Props, RawBindings, D, C, M>): ComponentOptions<Vue>;

32

33

/**

34

* Defines an async component with lazy loading

35

* @param source - Async component loader function

36

* @returns Async component definition

37

*/

38

function defineAsyncComponent<T extends Component = any>(

39

source: AsyncComponentLoader<T>

40

): T;

41

42

/**

43

* Defines an async component with options

44

* @param options - Async component options

45

* @returns Async component definition

46

*/

47

function defineAsyncComponent<T extends Component = any>(

48

options: AsyncComponentOptions<T>

49

): T;

50

51

types SetupFunction<Props, RawBindings> = (

52

props: Readonly<Props>,

53

ctx: SetupContext

54

) => RawBindings | (() => VNode | null) | void;

55

```

56

57

**Usage Examples:**

58

59

```typescript

60

import { defineComponent, ref, computed } from "@vue/composition-api";

61

62

// Simple setup function

63

const MyComponent = defineComponent({

64

props: {

65

message: {

66

type: String,

67

required: true,

68

},

69

count: {

70

type: Number,

71

default: 0,

72

},

73

},

74

setup(props, { emit }) {

75

const localCount = ref(props.count);

76

77

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

78

79

const increment = () => {

80

localCount.value++;

81

emit("update:count", localCount.value);

82

};

83

84

return {

85

localCount,

86

doubleCount,

87

increment,

88

};

89

},

90

});

91

92

// Component with render function

93

const RenderComponent = defineComponent({

94

props: {

95

tag: {

96

type: String,

97

default: "div",

98

},

99

},

100

setup(props, { slots }) {

101

return () => {

102

const Tag = props.tag;

103

return <Tag>{slots.default?.()}</Tag>;

104

};

105

},

106

});

107

108

// Async component

109

const AsyncComponent = defineAsyncComponent(() => import("./HeavyComponent.vue"));

110

111

// Async component with options

112

const AsyncComponentWithOptions = defineAsyncComponent({

113

loader: () => import("./HeavyComponent.vue"),

114

loadingComponent: LoadingSpinner,

115

errorComponent: ErrorDisplay,

116

delay: 200,

117

timeout: 3000,

118

});

119

```

120

121

### Instance Context

122

123

Access to the current component instance and setup context utilities.

124

125

```typescript { .api }

126

/**

127

* Gets the current component instance (only available during setup)

128

* @returns Current component instance or null

129

*/

130

function getCurrentInstance(): ComponentInternalInstance | null;

131

132

/**

133

* Accesses component attributes in setup function

134

* @returns Component attrs object

135

*/

136

function useAttrs(): SetupContext["attrs"];

137

138

/**

139

* Accesses component slots in setup function

140

* @returns Component slots object

141

*/

142

function useSlots(): SetupContext["slots"];

143

144

interface ComponentInternalInstance {

145

proxy: ComponentInstance | null;

146

setupState: Record<string, any>;

147

ctx: Record<string, any>;

148

scope: EffectScope;

149

}

150

151

interface SetupContext<E extends EmitsOptions = {}> {

152

attrs: Record<string, any>;

153

slots: Slots;

154

emit: EmitFn<E>;

155

}

156

```

157

158

**Usage Examples:**

159

160

```typescript

161

import { defineComponent, getCurrentInstance, useAttrs, useSlots } from "@vue/composition-api";

162

163

export default defineComponent({

164

setup() {

165

// Get current instance

166

const instance = getCurrentInstance();

167

168

if (instance) {

169

console.log("Component name:", instance.proxy?.$options.name);

170

}

171

172

// Access attrs reactively

173

const attrs = useAttrs();

174

175

// Access slots

176

const slots = useSlots();

177

178

const hasDefaultSlot = computed(() => !!slots.default);

179

const hasHeaderSlot = computed(() => !!slots.header);

180

181

return {

182

attrs,

183

hasDefaultSlot,

184

hasHeaderSlot,

185

};

186

},

187

});

188

```

189

190

### DOM and Timing Utilities

191

192

Utilities for DOM manipulation timing and element creation.

193

194

```typescript { .api }

195

/**

196

* Defers callback execution to the next DOM update cycle

197

* @param callback - Optional callback to execute

198

* @returns Promise that resolves after next DOM update

199

*/

200

function nextTick(callback?: () => void): Promise<void>;

201

202

/**

203

* Creates virtual DOM elements (alias for createElement)

204

* @param tag - Element tag or component

205

* @param props - Element props

206

* @param children - Element children

207

* @returns Virtual DOM node

208

*/

209

function h(

210

tag: string | Component,

211

props?: Record<string, any> | null,

212

children?: any

213

): VNode;

214

215

/**

216

* Development warning utility

217

* @param message - Warning message

218

* @param args - Additional arguments

219

*/

220

function warn(message: string, ...args: any[]): void;

221

```

222

223

**Usage Examples:**

224

225

```typescript

226

import { defineComponent, ref, nextTick, h } from "@vue/composition-api";

227

228

export default defineComponent({

229

setup() {

230

const showMessage = ref(false);

231

const messageEl = ref<HTMLElement | null>(null);

232

233

const toggleMessage = async () => {

234

showMessage.value = !showMessage.value;

235

236

// Wait for DOM update

237

await nextTick();

238

239

if (showMessage.value && messageEl.value) {

240

messageEl.value.focus();

241

}

242

};

243

244

// Using h() for render function

245

return () => h("div", [

246

h("button", { onClick: toggleMessage }, "Toggle Message"),

247

showMessage.value

248

? h("p", { ref: messageEl, tabindex: -1 }, "Hello World!")

249

: null,

250

]);

251

},

252

});

253

254

// NextTick with callback

255

export default defineComponent({

256

setup() {

257

const updateData = () => {

258

// Update reactive data

259

someData.value = newValue;

260

261

// Execute after DOM update

262

nextTick(() => {

263

console.log("DOM has been updated");

264

document.getElementById("updated-element")?.scrollIntoView();

265

});

266

};

267

268

return {

269

updateData,

270

};

271

},

272

});

273

```

274

275

### CSS Modules Integration

276

277

Access to CSS modules within composition API setup functions.

278

279

```typescript { .api }

280

/**

281

* Accesses CSS module classes

282

* @param name - Optional CSS module name

283

* @returns Object mapping class names to CSS module classes

284

*/

285

function useCssModule(name?: string): Record<string, string>;

286

287

/**

288

* Alternative spelling for useCssModule

289

* @param name - Optional CSS module name

290

* @returns Object mapping class names to CSS module classes

291

*/

292

function useCSSModule(name?: string): Record<string, string>;

293

```

294

295

**Usage Examples:**

296

297

```typescript

298

import { defineComponent, useCssModule } from "@vue/composition-api";

299

300

export default defineComponent({

301

setup() {

302

// Access default CSS module

303

const styles = useCssModule();

304

305

// Access named CSS module

306

const buttonStyles = useCssModule("button");

307

308

return {

309

styles,

310

buttonStyles,

311

};

312

},

313

314

template: `

315

<div :class="styles.container">

316

<button :class="buttonStyles.primary">

317

Click me

318

</button>

319

</div>

320

`,

321

});

322

323

// In component with CSS modules

324

// styles.module.css

325

/*

326

.container {

327

padding: 1rem;

328

}

329

*/

330

331

// button.module.css

332

/*

333

.primary {

334

background: blue;

335

color: white;

336

}

337

*/

338

```

339

340

### Props Type Utilities

341

342

Utilities for working with component props and type extraction.

343

344

```typescript { .api }

345

/**

346

* Extracts prop types from props definition

347

*/

348

type ExtractPropTypes<O> = O extends object

349

? { [K in keyof O]?: O[K] extends PropOptions<infer T> ? T : any }

350

: {};

351

352

/**

353

* Extracts default prop types from props definition

354

*/

355

type ExtractDefaultPropTypes<O> = O extends object

356

? { [K in keyof O]: O[K] extends { default: infer D } ? D : never }

357

: {};

358

359

interface PropOptions<T = any> {

360

type?: PropType<T> | true | null;

361

required?: boolean;

362

default?: T | null | undefined | (() => T | null | undefined);

363

validator?(value: T): boolean;

364

}

365

366

type PropType<T> = { new (...args: any[]): T & object } | { (): T } | PropType<T>[];

367

```

368

369

**Usage Examples:**

370

371

```typescript

372

import { defineComponent, PropType } from "@vue/composition-api";

373

374

interface User {

375

id: number;

376

name: string;

377

email: string;

378

}

379

380

export default defineComponent({

381

props: {

382

user: {

383

type: Object as PropType<User>,

384

required: true,

385

},

386

theme: {

387

type: String as PropType<"light" | "dark">,

388

default: "light",

389

},

390

count: {

391

type: Number,

392

default: 0,

393

validator: (value: number) => value >= 0,

394

},

395

},

396

setup(props) {

397

// props are fully typed based on the props definition

398

console.log(props.user.name); // TypeScript knows this is string

399

console.log(props.theme); // TypeScript knows this is "light" | "dark"

400

console.log(props.count); // TypeScript knows this is number

401

402

return {};

403

},

404

});

405

406

// Type extraction utility

407

type MyComponentProps = ExtractPropTypes<{

408

user: { type: PropType<User>; required: true };

409

theme: { type: PropType<"light" | "dark">; default: "light" };

410

count: { type: Number; default: 0 };

411

}>;

412

413

// MyComponentProps is:

414

// {

415

// user?: User;

416

// theme?: "light" | "dark";

417

// count?: number;

418

// }

419

```

420

421

### Event Handling

422

423

Enhanced event handling with TypeScript support.

424

425

```typescript { .api }

426

type EmitsOptions = ObjectEmitsOptions | string[];

427

428

type ObjectEmitsOptions = Record<

429

string,

430

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

431

>;

432

433

type EmitFn<

434

Options = ObjectEmitsOptions,

435

Event extends keyof Options = keyof Options

436

> = Options extends Array<infer V>

437

? (event: V, ...args: any[]) => void

438

: {} extends Options

439

? (event: string, ...args: any[]) => void

440

: Options extends ObjectEmitsOptions

441

? {

442

[K in Event]: Options[K] extends (...args: infer Args) => any

443

? (event: K, ...args: Args) => void

444

: (event: K, ...args: any[]) => void;

445

}[Event]

446

: never;

447

```

448

449

**Usage Examples:**

450

451

```typescript

452

import { defineComponent } from "@vue/composition-api";

453

454

export default defineComponent({

455

emits: {

456

// Typed event with validation

457

click: (payload: { x: number; y: number }) => {

458

return payload.x >= 0 && payload.y >= 0;

459

},

460

// Simple event

461

close: null,

462

// Event with multiple arguments

463

update: (id: string, value: any) => true,

464

},

465

setup(props, { emit }) {

466

const handleClick = (event: MouseEvent) => {

467

// emit is fully typed based on emits definition

468

emit("click", { x: event.clientX, y: event.clientY });

469

};

470

471

const handleClose = () => {

472

emit("close");

473

};

474

475

const handleUpdate = () => {

476

emit("update", "item-id", { data: "new value" });

477

};

478

479

return {

480

handleClick,

481

handleClose,

482

handleUpdate,

483

};

484

},

485

});

486

```

487

488

## Types

489

490

```typescript { .api }

491

interface ComponentOptions<V extends Vue> {

492

name?: string;

493

props?: ComponentPropsOptions<Data>;

494

setup?: SetupFunction<Data, Data>;

495

data?: ComponentOptionsData<V>;

496

computed?: Accessors<V>;

497

methods?: Methods<V>;

498

watch?: ComponentWatchOptions<V>;

499

// ... other Vue component options

500

}

501

502

interface ComponentInternalInstance {

503

proxy: ComponentInstance | null;

504

setupState: Record<string, any>;

505

ctx: Record<string, any>;

506

scope: EffectScope;

507

}

508

509

interface SetupContext<E extends EmitsOptions = {}> {

510

attrs: Record<string, any>;

511

slots: Slots;

512

emit: EmitFn<E>;

513

}

514

515

type Slots = Readonly<InternalSlots>;

516

517

interface InternalSlots {

518

[name: string]: Slot | undefined;

519

}

520

521

type Slot = (...args: any[]) => VNode[];

522

523

type AsyncComponentLoader<T = any> = () => Promise<T>;

524

525

interface AsyncComponentOptions<T = any> {

526

loader: AsyncComponentLoader<T>;

527

loadingComponent?: Component;

528

errorComponent?: Component;

529

delay?: number;

530

timeout?: number;

531

suspensible?: boolean;

532

onError?(error: Error, retry: () => void, fail: () => void, attempts: number): any;

533

}

534

535

type Component<

536

Props = any,

537

RawBindings = any,

538

D = any,

539

C extends ComputedOptions = ComputedOptions,

540

M extends MethodOptions = MethodOptions

541

> = ComponentOptions<Vue, Props, RawBindings, D, C, M> | ComponentConstructor<Vue>;

542

```