or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

compilation.mdcomponent-factory.mdcomponent-registration.mdindex.mdmounting-lifecycle.mdplugin-system.mdpure-components.mdutilities.md

component-factory.mddocs/

0

# Component Factory

1

2

Direct component creation without global registration, useful for dynamic components and programmatic component instantiation. This approach bypasses the global registry system.

3

4

## Capabilities

5

6

### Component Factory Function

7

8

Creates a component instance factory from a component wrapper without registering it globally.

9

10

```typescript { .api }

11

/**

12

* Helper method to create component without relying on registered components

13

* @param wrapper - Component implementation wrapper

14

* @returns Function that creates and mounts component instances

15

*/

16

function component<Props extends DefaultProps, State extends DefaultState, Component extends RiotComponent>(

17

wrapper: RiotComponentWrapper<Component>

18

): (

19

el: HTMLElement,

20

initialProps?: Props,

21

meta?: ComponentMeta

22

) => Component;

23

```

24

25

**Usage Example:**

26

27

```javascript

28

import { component } from "riot";

29

30

// Define component without registration

31

const createTimer = component({

32

css: "timer { display: block; color: blue; }",

33

template: (template, expressionTypes, bindingTypes) =>

34

template("<p>Time: { state.seconds }s</p>", [

35

// Template bindings

36

]),

37

exports: {

38

onBeforeMount(props) {

39

this.state = { seconds: props.start || 0 };

40

this.interval = setInterval(() => {

41

this.update({ seconds: this.state.seconds + 1 });

42

}, 1000);

43

},

44

onUnmounted() {

45

clearInterval(this.interval);

46

}

47

}

48

});

49

50

// Create and mount component instance

51

const element = document.getElementById("timer-container");

52

const timerComponent = createTimer(element, { start: 10 });

53

```

54

55

### Component Factory with Metadata

56

57

The factory function accepts optional metadata for advanced component features:

58

59

```typescript { .api }

60

interface ComponentMeta {

61

/** Slot data for child content */

62

slots?: TagSlotData[];

63

64

/** Attribute expression bindings */

65

attributes?: AttributeExpressionData[];

66

67

/** Parent scope for nested components */

68

parentScope?: any;

69

}

70

```

71

72

**Usage Example:**

73

74

```javascript

75

// Create component with slots and attributes

76

const element = document.getElementById("container");

77

const meta = {

78

slots: [

79

{

80

id: "header",

81

html: "<h2>Dynamic Header</h2>",

82

bindings: []

83

}

84

],

85

attributes: [

86

{

87

name: "data-theme",

88

evaluate: () => "dark"

89

}

90

]

91

};

92

93

const componentInstance = createMyComponent(element, { title: "Hello" }, meta);

94

```

95

96

## Enhanced Component Factory (riot+compiler)

97

98

The riot+compiler build provides an enhanced component factory that automatically handles runtime slot creation:

99

100

```typescript { .api }

101

/**

102

* Enhanced component factory that creates slots from DOM content

103

* @param wrapper - Component implementation wrapper

104

* @returns Enhanced factory function with automatic slot handling

105

*/

106

function component(wrapper: RiotComponentWrapper): (

107

el: HTMLElement,

108

props?: any,

109

meta?: ComponentMeta

110

) => RiotComponent;

111

```

112

113

**Usage Example:**

114

115

```javascript

116

import { component } from "riot+compiler";

117

118

const createWidget = component({

119

template: (template, expressionTypes, bindingTypes) =>

120

template(`

121

<div class="widget">

122

<slot name="content"></slot>

123

</div>

124

`, [

125

// Slot bindings are automatically handled

126

]),

127

exports: {

128

onMounted() {

129

console.log("Widget mounted with slots:", this.slots);

130

}

131

}

132

});

133

134

// HTML content becomes slots automatically

135

const element = document.querySelector(".widget-container");

136

// Any existing content in element becomes slot content

137

const widget = createWidget(element, { theme: "modern" });

138

```

139

140

## Dynamic Component Creation

141

142

Component factories are particularly useful for dynamic component creation:

143

144

```javascript

145

import { component } from "riot";

146

147

// Factory for creating different card types

148

function createCardComponent(cardType) {

149

return component({

150

css: `.card-${cardType} { border: 2px solid ${getCardColor(cardType)}; }`,

151

template: (template) => template(`

152

<div class="card-${cardType}">

153

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

154

<p>{ props.content }</p>

155

</div>

156

`),

157

exports: {

158

onMounted() {

159

console.log(`${cardType} card mounted`);

160

}

161

}

162

});

163

}

164

165

// Create different card types dynamically

166

const createInfoCard = createCardComponent("info");

167

const createWarningCard = createCardComponent("warning");

168

169

// Use the factories

170

const infoCard = createInfoCard(document.getElementById("info"), {

171

title: "Information",

172

content: "This is an info card"

173

});

174

175

const warningCard = createWarningCard(document.getElementById("warning"), {

176

title: "Warning",

177

content: "This is a warning card"

178

});

179

```

180

181

## Types

182

183

```typescript { .api }

184

interface ComponentMeta {

185

slots?: TagSlotData[];

186

attributes?: AttributeExpressionData[];

187

parentScope?: any;

188

}

189

190

type TagSlotData = {

191

id: string;

192

html: string;

193

bindings: BindingData[];

194

};

195

196

type AttributeExpressionData = {

197

name: string;

198

evaluate: () => any;

199

};

200

201

type BindingData = {

202

selector: string;

203

type: number;

204

evaluate: () => any;

205

};

206

```