or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

components.mdcontext.mdelement-creation.mdhooks.mdindex.mdreact-compatibility.mdrendering.md

react-compatibility.mddocs/

0

# React Compatibility Utilities

1

2

Additional utilities for React compatibility, including children manipulation, element validation, and element cloning functions. These utilities are provided through the compatibility layer and external packages to ensure full React API compatibility.

3

4

## Capabilities

5

6

### Children Utilities

7

8

Comprehensive utilities for working with component children, similar to React.Children.

9

10

```javascript { .api }

11

/**

12

* Children utility object with methods for manipulating component children

13

*/

14

const Children: {

15

/**

16

* Maps over children and returns a new array

17

* @param children - Component children to map over

18

* @param fn - Function to apply to each child

19

* @param ctx - Optional context for the function call

20

* @returns Array of mapped children

21

*/

22

map(children: RaxNode, fn: (child: RaxNode, index: number) => RaxNode, ctx?: any): RaxNode[];

23

24

/**

25

* Iterates over children without returning anything

26

* @param children - Component children to iterate over

27

* @param fn - Function to apply to each child

28

* @param ctx - Optional context for the function call

29

*/

30

forEach(children: RaxNode, fn: (child: RaxNode, index: number) => void, ctx?: any): void;

31

32

/**

33

* Counts the number of children

34

* @param children - Component children to count

35

* @returns Number of children

36

*/

37

count(children: RaxNode): number;

38

39

/**

40

* Ensures children contains only one child and returns it

41

* @param children - Component children (must be exactly one)

42

* @returns The single child element

43

* @throws Error if children count is not exactly 1

44

*/

45

only(children: RaxNode): RaxElement;

46

47

/**

48

* Converts children to a flat array

49

* @param children - Component children to convert

50

* @returns Array representation of children

51

*/

52

toArray(children: RaxNode): RaxNode[];

53

};

54

```

55

56

**Usage Examples:**

57

58

```javascript

59

import { createElement, Children } from 'rax/src/compat';

60

61

function List({ children }) {

62

// Map over children to add list item wrappers

63

const listItems = Children.map(children, (child, index) => {

64

return createElement('li', { key: index }, child);

65

});

66

67

return createElement('ul', null, ...listItems);

68

}

69

70

function TabContainer({ children }) {

71

// Ensure only one active tab

72

let activeChild = null;

73

74

Children.forEach(children, (child) => {

75

if (child.props && child.props.active) {

76

activeChild = child;

77

}

78

});

79

80

return createElement('div', { className: 'tab-container' },

81

activeChild || Children.only(children)

82

);

83

}

84

85

function ChildCounter({ children }) {

86

const count = Children.count(children);

87

const childArray = Children.toArray(children);

88

89

return createElement('div', null,

90

createElement('p', null, `This component has ${count} children`),

91

createElement('div', null, ...childArray)

92

);

93

}

94

95

// Usage

96

const app = createElement(List, null,

97

createElement('span', null, 'Item 1'),

98

createElement('span', null, 'Item 2'),

99

createElement('span', null, 'Item 3')

100

);

101

```

102

103

### Element Validation

104

105

Validates whether a value is a valid Rax element.

106

107

```javascript { .api }

108

/**

109

* Checks if a value is a valid Rax element

110

* @param object - Value to check

111

* @returns true if the value is a valid Rax element, false otherwise

112

*/

113

function isValidElement(object: any): boolean;

114

```

115

116

**Usage Examples:**

117

118

```javascript

119

import { createElement, isValidElement } from 'rax/src/compat';

120

121

function SafeRender({ content }) {

122

// Only render if content is a valid element

123

if (isValidElement(content)) {

124

return content;

125

}

126

127

// Fallback for non-element content

128

if (typeof content === 'string' || typeof content === 'number') {

129

return createElement('span', null, content);

130

}

131

132

return createElement('div', null, 'Invalid content');

133

}

134

135

function ElementChecker({ items }) {

136

const validItems = items.filter(isValidElement);

137

const invalidCount = items.length - validItems.length;

138

139

return createElement('div', null,

140

createElement('p', null, `Valid elements: ${validItems.length}`),

141

createElement('p', null, `Invalid items: ${invalidCount}`),

142

createElement('div', null, ...validItems)

143

);

144

}

145

146

// Usage examples

147

const validElement = createElement('div', null, 'Hello');

148

const invalidElement = { notAnElement: true };

149

150

console.log(isValidElement(validElement)); // true

151

console.log(isValidElement(invalidElement)); // false

152

console.log(isValidElement('string')); // false

153

console.log(isValidElement(42)); // false

154

```

155

156

### Element Factory

157

158

Creates a factory function for a specific element type, reducing the need to repeatedly specify the type.

159

160

```javascript { .api }

161

/**

162

* Creates a factory function for creating elements of a specific type

163

* @param type - Element type (string for DOM elements, function/class for components)

164

* @returns Factory function that creates elements of the specified type

165

*/

166

function createFactory(type: string | Function): Function;

167

```

168

169

**Usage Examples:**

170

171

```javascript

172

import { createFactory } from 'rax/src/compat';

173

174

// Create factories for commonly used elements

175

const div = createFactory('div');

176

const span = createFactory('span');

177

const button = createFactory('button');

178

179

// Create factory for custom component

180

function CustomButton(props) {

181

return button({

182

className: 'custom-button',

183

...props

184

}, props.children);

185

}

186

const customButton = createFactory(CustomButton);

187

188

// Using factories (more concise than createElement)

189

function App() {

190

return div({ className: 'app' },

191

div({ className: 'header' },

192

span(null, 'Welcome to the App')

193

),

194

div({ className: 'content' },

195

button({

196

onClick: () => alert('Clicked!')

197

}, 'Click Me'),

198

customButton({

199

variant: 'primary'

200

}, 'Custom Button')

201

)

202

);

203

}

204

205

// Factory functions accept (props, ...children) just like createElement

206

const navigation = div({ className: 'nav' },

207

button({ onClick: () => {} }, 'Home'),

208

button({ onClick: () => {} }, 'About'),

209

button({ onClick: () => {} }, 'Contact')

210

);

211

```

212

213

### Element Cloning

214

215

Clones existing elements with modified props and/or children.

216

217

```javascript { .api }

218

/**

219

* Clones a Rax element with new props and/or children

220

* @param element - Element to clone

221

* @param props - New props to merge with existing props

222

* @param children - New children to replace existing children

223

* @returns New cloned element with merged props and new children

224

*/

225

function cloneElement(element: RaxElement, props?: Object, ...children: RaxNode[]): RaxElement;

226

```

227

228

**Usage Examples:**

229

230

```javascript

231

import { createElement, cloneElement, Children } from 'rax/src/compat';

232

233

function EnhanceButton({ children, enhancement, ...props }) {

234

// Clone each child button with enhanced props

235

const enhancedChildren = Children.map(children, (child) => {

236

if (child.type === 'button') {

237

return cloneElement(child, {

238

className: `${child.props.className || ''} enhanced`,

239

'data-enhancement': enhancement,

240

onClick: (e) => {

241

// Call original onClick first

242

if (child.props.onClick) {

243

child.props.onClick(e);

244

}

245

// Add enhancement behavior

246

console.log(`Enhanced click: ${enhancement}`);

247

}

248

});

249

}

250

return child;

251

});

252

253

return createElement('div', props, ...enhancedChildren);

254

}

255

256

function Modal({ isOpen, children }) {

257

if (!isOpen) return null;

258

259

// Clone children with modal-specific props

260

const modalChildren = Children.map(children, (child) => {

261

return cloneElement(child, {

262

'data-in-modal': true,

263

className: `${child.props.className || ''} modal-content`

264

});

265

});

266

267

return createElement('div', { className: 'modal-overlay' },

268

createElement('div', { className: 'modal' }, ...modalChildren)

269

);

270

}

271

272

function FormField({ label, children }) {

273

// Clone input element to add form-specific props

274

const enhancedInput = cloneElement(children, {

275

id: label.toLowerCase().replace(/\s+/g, '-'),

276

'aria-label': label,

277

className: `${children.props.className || ''} form-input`

278

});

279

280

return createElement('div', { className: 'form-field' },

281

createElement('label', {

282

htmlFor: label.toLowerCase().replace(/\s+/g, '-')

283

}, label),

284

enhancedInput

285

);

286

}

287

288

// Usage

289

const originalButton = createElement('button', {

290

onClick: () => alert('Original')

291

}, 'Click Me');

292

293

const enhancedForm = createElement(FormField, { label: 'Email Address' },

294

createElement('input', {

295

type: 'email',

296

placeholder: 'Enter email'

297

})

298

);

299

```

300

301

### Compatibility Layer Integration

302

303

The compatibility layer integrates all utilities into a single default export that mimics React's API:

304

305

```javascript { .api }

306

/**

307

* Default export that provides React-like API

308

*/

309

const Rax: {

310

// All core Rax exports

311

createElement: Function;

312

render: Function;

313

Component: ComponentConstructor;

314

PureComponent: ComponentConstructor;

315

// ... all other core exports

316

317

// Additional compatibility utilities

318

Children: ChildrenUtilities;

319

isValidElement: Function;

320

createFactory: Function;

321

cloneElement: Function;

322

323

// React compatibility flag

324

Component.prototype.isReactComponent: {};

325

};

326

```

327

328

**Full Compatibility Usage:**

329

330

```javascript

331

// Import as default to get React-like API

332

import Rax from 'rax/src/compat';

333

334

class ReactLikeComponent extends Rax.Component {

335

render() {

336

const { children } = this.props;

337

338

// Use React-like APIs

339

const validChildren = Rax.Children.toArray(children)

340

.filter(Rax.isValidElement);

341

342

const enhancedChildren = Rax.Children.map(validChildren, (child, index) => {

343

return Rax.cloneElement(child, { key: index });

344

});

345

346

return Rax.createElement('div', null, ...enhancedChildren);

347

}

348

}

349

350

// Component has React compatibility flag

351

console.log(ReactLikeComponent.prototype.isReactComponent); // {}

352

```

353

354

## Types

355

356

```javascript { .api }

357

// Children utilities type

358

interface ChildrenUtilities {

359

map<T, C>(children: C, fn: (child: C, index: number) => T, ctx?: any): T[];

360

forEach<C>(children: C, fn: (child: C, index: number) => void, ctx?: any): void;

361

count(children: RaxNode): number;

362

only(children: RaxNode): RaxElement;

363

toArray(children: RaxNode): RaxNode[];

364

}

365

366

// Element validation type

367

type IsValidElementFunction = (object: any) => object is RaxElement;

368

369

// Factory function types

370

type ElementFactory<P = {}> = (props?: P, ...children: RaxNode[]) => RaxElement;

371

type CreateFactoryFunction = <P = {}>(type: string | ComponentType<P>) => ElementFactory<P>;

372

373

// Clone element types

374

type CloneElementFunction = <P = {}>(

375

element: RaxElement<P>,

376

props?: Partial<P>,

377

...children: RaxNode[]

378

) => RaxElement<P>;

379

380

// Compatibility layer type

381

interface RaxCompat {

382

[key: string]: any;

383

Children: ChildrenUtilities;

384

isValidElement: IsValidElementFunction;

385

createFactory: CreateFactoryFunction;

386

cloneElement: CloneElementFunction;

387

}

388

389

// Node types (children can be various types)

390

type RaxNode = RaxElement | string | number | boolean | null | undefined | RaxNode[];

391

```