or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

adapter.mdbreakpoints.mdcomposition-hooks.mdcss-utilities.mddesign-system.mdindex.mdsetup.mdsvg-icons.mdtheme-mode.md

composition-hooks.mddocs/

0

# Core Composition Hooks

1

2

The Core Composition Hooks provide essential Vue composition utilities for component relationships, slot management, and performance optimization. These hooks are built on top of the adapter system and work seamlessly across Vue 2 and Vue 3.

3

4

## Capabilities

5

6

### Instance Slots Hook

7

8

Hook for managing component slots with cross-framework compatibility and reactive updates.

9

10

```typescript { .api }

11

/**

12

* Create instance slots manager with cross-framework compatibility

13

* @param hooks - Adapter hooks system

14

* @returns Instance slots manager

15

*/

16

function useInstanceSlots(hooks: AdapterHooks): any;

17

```

18

19

**Usage Examples:**

20

21

```typescript

22

import { useInstanceSlots, hooks } from "@opentiny/vue-common";

23

24

export default {

25

setup(props, context) {

26

const instanceSlots = useInstanceSlots(hooks);

27

28

// Access slots reactively

29

const hasDefaultSlot = hooks.computed(() => {

30

return !!instanceSlots.default;

31

});

32

33

const hasHeaderSlot = hooks.computed(() => {

34

return !!instanceSlots.header;

35

});

36

37

return {

38

instanceSlots,

39

hasDefaultSlot,

40

hasHeaderSlot

41

};

42

},

43

template: `

44

<div class="component">

45

<header v-if="hasHeaderSlot">

46

<slot name="header" />

47

</header>

48

<main v-if="hasDefaultSlot">

49

<slot />

50

</main>

51

</div>

52

`

53

};

54

```

55

56

### Component Relation Hook

57

58

Hook for managing parent-child component relationships and communication patterns.

59

60

```typescript { .api }

61

/**

62

* Create component relation manager for parent-child communication

63

* @param hooks - Adapter hooks system

64

* @returns Component relation manager

65

*/

66

function useRelation(hooks: AdapterHooks): any;

67

```

68

69

**Usage Examples:**

70

71

```typescript

72

import { useRelation, hooks } from "@opentiny/vue-common";

73

74

// Parent component

75

export default {

76

name: 'ParentComponent',

77

setup() {

78

const relation = useRelation(hooks);

79

80

const children = hooks.ref([]);

81

82

const registerChild = (child) => {

83

children.value.push(child);

84

};

85

86

const unregisterChild = (child) => {

87

const index = children.value.indexOf(child);

88

if (index > -1) {

89

children.value.splice(index, 1);

90

}

91

};

92

93

// Provide registration methods to children

94

hooks.provide('parentRelation', {

95

registerChild,

96

unregisterChild

97

});

98

99

return {

100

children,

101

relation

102

};

103

}

104

};

105

106

// Child component

107

export default {

108

name: 'ChildComponent',

109

setup() {

110

const relation = useRelation(hooks);

111

const parentRelation = hooks.inject('parentRelation', null);

112

113

const instance = hooks.getCurrentInstance();

114

115

hooks.onMounted(() => {

116

if (parentRelation) {

117

parentRelation.registerChild(instance);

118

}

119

});

120

121

hooks.onBeforeUnmount(() => {

122

if (parentRelation) {

123

parentRelation.unregisterChild(instance);

124

}

125

});

126

127

return {

128

relation

129

};

130

}

131

};

132

```

133

134

### Deferred Rendering Hook

135

136

Performance optimization hook for progressive component rendering with frame-based control.

137

138

```typescript { .api }

139

/**

140

* Create deferred rendering controller for performance optimization

141

* @param maxCount - Maximum frame count before stopping (default: 100)

142

* @returns Deferred rendering controller

143

*/

144

function useDefer(maxCount?: number): {

145

/** Check if rendering should be deferred for given frame number */

146

defer(n: number): boolean;

147

/** Reset frame counter to start over */

148

reset(): void;

149

/** Cancel animation frames and stop counting */

150

cancel(): void;

151

};

152

```

153

154

**Usage Examples:**

155

156

```typescript

157

import { useDefer, hooks } from "@opentiny/vue-common";

158

159

export default {

160

setup() {

161

const deferrer = useDefer(50); // Limit to 50 frames

162

163

// Progressive rendering of list items

164

const items = hooks.ref(Array.from({ length: 1000 }, (_, i) => `Item ${i}`));

165

166

const visibleItems = hooks.computed(() => {

167

return items.value.filter((_, index) => {

168

// Show first 10 items immediately

169

if (index < 10) return true;

170

171

// Progressive reveal based on frame count

172

const frameThreshold = Math.floor(index / 10) + 1;

173

return deferrer.defer(frameThreshold);

174

});

175

});

176

177

// Reset deferred rendering on data change

178

hooks.watch(items, () => {

179

deferrer.reset();

180

});

181

182

return {

183

visibleItems,

184

deferrer

185

};

186

},

187

template: `

188

<div class="large-list">

189

<div v-for="item in visibleItems" :key="item" class="list-item">

190

{{ item }}

191

</div>

192

</div>

193

`

194

};

195

```

196

197

## Advanced Usage Patterns

198

199

### Slot-Based Component Composition

200

201

Using instance slots for flexible component composition.

202

203

```typescript

204

import { useInstanceSlots, hooks } from "@opentiny/vue-common";

205

206

export default {

207

setup() {

208

const slots = useInstanceSlots(hooks);

209

210

// Dynamic slot analysis

211

const slotAnalysis = hooks.computed(() => {

212

const analysis = {

213

hasContent: false,

214

hasActions: false,

215

hasCustom: false,

216

customSlots: []

217

};

218

219

if (slots.default) analysis.hasContent = true;

220

if (slots.actions) analysis.hasActions = true;

221

222

// Find custom slots

223

Object.keys(slots).forEach(slotName => {

224

if (!['default', 'actions'].includes(slotName)) {

225

analysis.hasCustom = true;

226

analysis.customSlots.push(slotName);

227

}

228

});

229

230

return analysis;

231

});

232

233

return {

234

slots,

235

slotAnalysis

236

};

237

},

238

template: `

239

<div class="flexible-component">

240

<div v-if="slotAnalysis.hasContent" class="content">

241

<slot />

242

</div>

243

244

<div v-for="customSlot in slotAnalysis.customSlots"

245

:key="customSlot"

246

:class="'custom-' + customSlot">

247

<slot :name="customSlot" />

248

</div>

249

250

<div v-if="slotAnalysis.hasActions" class="actions">

251

<slot name="actions" />

252

</div>

253

</div>

254

`

255

};

256

```

257

258

### Parent-Child Communication System

259

260

Building a comprehensive parent-child communication system.

261

262

```typescript

263

import { useRelation, hooks } from "@opentiny/vue-common";

264

265

// Communication mixin

266

const useParentChildComm = () => {

267

const relation = useRelation(hooks);

268

269

// For parent components

270

const createParentComm = () => {

271

const children = hooks.ref(new Map());

272

273

const addChild = (id, child) => {

274

children.value.set(id, child);

275

};

276

277

const removeChild = (id) => {

278

children.value.delete(id);

279

};

280

281

const broadcastToChildren = (message, data) => {

282

children.value.forEach(child => {

283

if (child.receiveMessage) {

284

child.receiveMessage(message, data);

285

}

286

});

287

};

288

289

hooks.provide('parentComm', {

290

addChild,

291

removeChild,

292

broadcastToChildren

293

});

294

295

return {

296

children,

297

broadcastToChildren

298

};

299

};

300

301

// For child components

302

const createChildComm = (childId) => {

303

const parentComm = hooks.inject('parentComm', null);

304

const messages = hooks.ref([]);

305

306

const receiveMessage = (message, data) => {

307

messages.value.push({ message, data, timestamp: Date.now() });

308

};

309

310

const sendToParent = (message, data) => {

311

if (parentComm) {

312

parentComm.receiveFromChild?.(childId, message, data);

313

}

314

};

315

316

hooks.onMounted(() => {

317

if (parentComm) {

318

parentComm.addChild(childId, { receiveMessage });

319

}

320

});

321

322

hooks.onBeforeUnmount(() => {

323

if (parentComm) {

324

parentComm.removeChild(childId);

325

}

326

});

327

328

return {

329

messages,

330

receiveMessage,

331

sendToParent

332

};

333

};

334

335

return {

336

createParentComm,

337

createChildComm

338

};

339

};

340

```

341

342

### Performance-Optimized List Rendering

343

344

Using deferred rendering for large datasets.

345

346

```typescript

347

import { useDefer, hooks } from "@opentiny/vue-common";

348

349

export default {

350

props: {

351

items: Array,

352

chunkSize: {

353

type: Number,

354

default: 20

355

}

356

},

357

setup(props) {

358

const deferrer = useDefer();

359

360

// Chunk items for progressive rendering

361

const itemChunks = hooks.computed(() => {

362

const chunks = [];

363

for (let i = 0; i < props.items.length; i += props.chunkSize) {

364

chunks.push(props.items.slice(i, i + props.chunkSize));

365

}

366

return chunks;

367

});

368

369

// Progressive chunk rendering

370

const visibleChunks = hooks.computed(() => {

371

return itemChunks.value.filter((_, chunkIndex) => {

372

return deferrer.defer(chunkIndex + 1);

373

});

374

});

375

376

const visibleItems = hooks.computed(() => {

377

return visibleChunks.value.flat();

378

});

379

380

// Loading state

381

const isLoading = hooks.computed(() => {

382

return visibleItems.value.length < props.items.length;

383

});

384

385

// Reset on items change

386

hooks.watch(() => props.items, () => {

387

deferrer.reset();

388

});

389

390

return {

391

visibleItems,

392

isLoading,

393

totalItems: hooks.computed(() => props.items.length),

394

loadedItems: hooks.computed(() => visibleItems.value.length)

395

};

396

}

397

};

398

```

399

400

## Integration with Component Setup

401

402

These hooks integrate seamlessly with the component setup system:

403

404

```typescript

405

import { setup, useInstanceSlots, useRelation, useDefer } from "@opentiny/vue-common";

406

407

export default {

408

setup(props, context) {

409

return setup({

410

props,

411

context,

412

renderless: (props, hooks, utils) => {

413

// Use composition hooks within renderless functions

414

const slots = useInstanceSlots(hooks);

415

const relation = useRelation(hooks);

416

const deferrer = useDefer(30);

417

418

return {

419

slots,

420

relation,

421

deferrer

422

};

423

},

424

api: ['slots', 'relation', 'deferrer']

425

});

426

}

427

};

428

```