or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-build.mdclicks-interactions.mdcode-execution.mdconfig-frontmatter.mdcontext-menu.mdindex.mdmarkdown-transform.mdoptions-system.mdsetup-plugins.mdslide-data.mdtable-of-contents.md

clicks-interactions.mddocs/

0

# Click and Interaction System

1

2

Types for managing slide interactions, animations, and click-based progression through presentation content.

3

4

## Capabilities

5

6

### Click Value Types

7

8

Types for defining click values and ranges for slide interactions.

9

10

```typescript { .api }

11

/**

12

* Raw single value types for 'at' attribute

13

*/

14

type RawSingleAtValue = null | undefined | boolean | string | number;

15

16

/**

17

* Raw range value types for 'at' attribute

18

*/

19

type RawRangeAtValue = null | undefined | false | [string | number, string | number];

20

21

/**

22

* Combined raw 'at' value type

23

*/

24

type RawAtValue = RawSingleAtValue | RawRangeAtValue;

25

26

/**

27

* Normalized single click value types

28

*/

29

type NormalizedSingleClickValue =

30

| number // since absolute click

31

| string // since relative click

32

| null; // disabled

33

34

/**

35

* Normalized range click value types

36

*/

37

type NormalizedRangeClickValue =

38

| [number, number] // [absolute start, absolute end]

39

| [number, string] // [absolute start, absolute end based on start]

40

| [string, number] // [relative start, absolute end]

41

| [string, string] // [relative start, relative end]

42

| [string | number, string | number] // make TypeScript happy

43

| null; // disabled

44

45

/**

46

* Combined normalized value type

47

*/

48

type NormalizedAtValue =

49

| NormalizedSingleClickValue // since

50

| NormalizedRangeClickValue; // range

51

52

/**

53

* Click element type

54

*/

55

type ClicksElement = Element | string;

56

```

57

58

### Clicks Information Interface

59

60

Information structure for click states and calculations.

61

62

```typescript { .api }

63

/**

64

* Click information interface providing state and calculations

65

*/

66

interface ClicksInfo {

67

/** The absolute start click num */

68

start: number;

69

/** The absolute end click num */

70

end: number;

71

/** The required total click num */

72

max: number;

73

/** The delta for relative clicks */

74

delta: number;

75

/** currentClicks - start */

76

currentOffset: ComputedRef<number>;

77

/** currentOffset === 0 */

78

isCurrent: ComputedRef<boolean>;

79

/** Computed ref of whether the click is active */

80

isActive: ComputedRef<boolean>;

81

}

82

```

83

84

### Clicks Context Interface

85

86

Main interface for managing clicks within a slide.

87

88

```typescript { .api }

89

/**

90

* Clicks context interface for managing slide interactions

91

*/

92

interface ClicksContext {

93

/** Current click position */

94

current: number;

95

/** Starting click position for the slide */

96

readonly clicksStart: number;

97

/** Map of elements to their relative sizes */

98

readonly relativeSizeMap: Map<ClicksElement, number>;

99

/** Map of elements to their maximum click values */

100

readonly maxMap: Map<ClicksElement, number>;

101

/** Calculate click info for since-style values */

102

calculateSince: (at: RawSingleAtValue, size?: number) => ClicksInfo | null;

103

/** Calculate click info for range-style values */

104

calculateRange: (at: RawRangeAtValue) => ClicksInfo | null;

105

/** Calculate click info for any at value */

106

calculate: (at: RawAtValue) => ClicksInfo | null;

107

/** Register an element with click information */

108

register: (el: ClicksElement, info: Pick<ClicksInfo, 'delta' | 'max'> | null) => void;

109

/** Unregister an element */

110

unregister: (el: ClicksElement) => void;

111

/** Whether the context is mounted */

112

readonly isMounted: boolean;

113

/** Setup the clicks context */

114

setup: () => void;

115

/** Current offset from start */

116

readonly currentOffset: number;

117

/** Total clicks for the slide */

118

readonly total: number;

119

}

120

```

121

122

## Usage Examples

123

124

**Basic Click Usage:**

125

126

```typescript

127

import type { ClicksContext, ClicksInfo } from "@slidev/types";

128

129

// Using clicks context in a component

130

function useSlideClicks(clicksContext: ClicksContext) {

131

// Register an element for clicks

132

const element = document.querySelector('.animated-element');

133

134

clicksContext.register(element, {

135

delta: 1, // This element needs 1 click

136

max: 3 // Maximum 3 clicks total for this element

137

});

138

139

// Calculate click info for specific values

140

const sinceInfo = clicksContext.calculateSince(2); // Show since click 2

141

const rangeInfo = clicksContext.calculateRange([1, 3]); // Show from click 1 to 3

142

143

return {

144

isVisible: sinceInfo?.isActive,

145

currentClick: clicksContext.current

146

};

147

}

148

```

149

150

**Click Info Calculations:**

151

152

```typescript

153

// Example of working with click information

154

function handleClickInfo(clicksInfo: ClicksInfo | null) {

155

if (!clicksInfo) return;

156

157

console.log(`Click range: ${clicksInfo.start} to ${clicksInfo.end}`);

158

console.log(`Total clicks needed: ${clicksInfo.max}`);

159

console.log(`Current offset: ${clicksInfo.currentOffset.value}`);

160

161

// React to click state changes

162

watch(clicksInfo.isActive, (active) => {

163

if (active) {

164

console.log('Element is now active');

165

} else {

166

console.log('Element is now inactive');

167

}

168

});

169

170

watch(clicksInfo.isCurrent, (current) => {

171

if (current) {

172

console.log('Element is at current click position');

173

}

174

});

175

}

176

```

177

178

**Dynamic Click Registration:**

179

180

```typescript

181

function dynamicClickRegistration(clicksContext: ClicksContext) {

182

const elements = document.querySelectorAll('.click-element');

183

184

elements.forEach((element, index) => {

185

// Register each element with different click requirements

186

clicksContext.register(element, {

187

delta: 1,

188

max: index + 1

189

});

190

});

191

192

// Later, unregister elements if needed

193

const cleanup = () => {

194

elements.forEach(element => {

195

clicksContext.unregister(element);

196

});

197

};

198

199

return cleanup;

200

}

201

```

202

203

**Advanced Click Calculations:**

204

205

```typescript

206

function advancedClickUsage(clicksContext: ClicksContext) {

207

// Calculate different types of click ranges

208

const examples = [

209

clicksContext.calculate(1), // Show since click 1

210

clicksContext.calculate([2, 4]), // Show from click 2 to 4

211

clicksContext.calculate(["+1", 3]), // Relative start, absolute end

212

clicksContext.calculate(["1", "+2"]), // Relative start and end

213

clicksContext.calculate(null), // Disabled

214

clicksContext.calculate(false) // Disabled range

215

];

216

217

examples.forEach((info, index) => {

218

if (info) {

219

console.log(`Example ${index}:`, {

220

start: info.start,

221

end: info.end,

222

max: info.max,

223

delta: info.delta

224

});

225

} else {

226

console.log(`Example ${index}: Disabled`);

227

}

228

});

229

}

230

```

231

232

**Reactive Click State:**

233

234

```typescript

235

import { computed, watch } from 'vue';

236

237

function reactiveClickState(clicksContext: ClicksContext) {

238

// Create reactive computations based on click state

239

const progress = computed(() => {

240

if (clicksContext.total === 0) return 0;

241

return (clicksContext.current - clicksContext.clicksStart) / clicksContext.total;

242

});

243

244

const isComplete = computed(() => {

245

return clicksContext.current >= clicksContext.clicksStart + clicksContext.total;

246

});

247

248

const remainingClicks = computed(() => {

249

return Math.max(0, clicksContext.clicksStart + clicksContext.total - clicksContext.current);

250

});

251

252

// Watch for click changes

253

watch(() => clicksContext.current, (newClick, oldClick) => {

254

console.log(`Click changed from ${oldClick} to ${newClick}`);

255

console.log(`Progress: ${Math.round(progress.value * 100)}%`);

256

257

if (isComplete.value) {

258

console.log('All clicks completed for this slide');

259

} else {

260

console.log(`${remainingClicks.value} clicks remaining`);

261

}

262

});

263

264

return {

265

progress,

266

isComplete,

267

remainingClicks

268

};

269

}

270

```