or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-widgets.mdcomponents.mdforms.mdicons.mdindex.mdtoolbars.mdutilities.mdwidgets.md
tile.json

widgets.mddocs/

0

# Lumino Widgets

1

2

Lumino widget classes that provide JupyterLab-compatible components with signals, lifecycle management, and integration with the Lumino widget framework. These widgets can be used in both traditional Lumino applications and modern React-based interfaces.

3

4

## Capabilities

5

6

### ReactWidget Base Class

7

8

Abstract base class for creating Lumino widgets that render React components.

9

10

```typescript { .api }

11

/**

12

* Abstract Lumino widget that renders React components

13

* Bridges React components with Lumino's widget system

14

*/

15

abstract class ReactWidget extends Widget {

16

/**

17

* Create a ReactWidget from a React element

18

* @param element - React element to render

19

* @returns ReactWidget instance

20

*/

21

static create(element: ReactRenderElement): ReactWidget;

22

23

/**

24

* Abstract method to define React content

25

* @returns React element to render or null

26

*/

27

protected abstract render(): ReactRenderElement | null;

28

29

/** Promise that resolves when render is complete */

30

renderPromise?: Promise<void>;

31

}

32

```

33

34

**Usage Examples:**

35

36

```typescript

37

import { ReactWidget } from '@jupyterlab/ui-components';

38

import React from 'react';

39

40

// Custom widget with React content

41

class MyWidget extends ReactWidget {

42

constructor() {

43

super();

44

this.addClass('my-custom-widget');

45

this.title.label = 'My Widget';

46

}

47

48

protected render() {

49

return (

50

<div>

51

<h2>Hello from React!</h2>

52

<button onClick={() => this.handleClick()}>

53

Click me

54

</button>

55

</div>

56

);

57

}

58

59

private handleClick() {

60

console.log('Button clicked in widget');

61

}

62

}

63

64

// Create widget from React element

65

const quickWidget = ReactWidget.create(

66

<div>

67

<p>Quick widget content</p>

68

</div>

69

);

70

```

71

72

### VDomRenderer and VDomModel

73

74

Advanced ReactWidget with model support and automatic re-rendering on model changes.

75

76

```typescript { .api }

77

/**

78

* Abstract ReactWidget with a model that triggers re-renders

79

*/

80

abstract class VDomRenderer<T extends VDomRenderer.IModel | null = null> extends ReactWidget {

81

/**

82

* Create a VDomRenderer with optional model

83

* @param model - Model instance or null

84

*/

85

constructor(model?: T);

86

87

/** Signal emitted when model changes */

88

get modelChanged(): ISignal<this, void>;

89

90

/** Current model instance */

91

set model(newValue: T);

92

get model(): T;

93

}

94

95

namespace VDomRenderer {

96

/**

97

* Interface for VDomRenderer models

98

*/

99

interface IModel extends IDisposable {

100

/** Signal emitted when state changes */

101

readonly stateChanged: ISignal<this, void>;

102

}

103

}

104

105

/**

106

* Concrete implementation of VDomRenderer model

107

*/

108

class VDomModel implements VDomRenderer.IModel {

109

/** Signal for state changes */

110

readonly stateChanged: Signal<this, void>;

111

112

/** Check if model is disposed */

113

get isDisposed(): boolean;

114

115

/** Dispose of the model */

116

dispose(): void;

117

}

118

```

119

120

**Usage Examples:**

121

122

```typescript

123

import { VDomRenderer, VDomModel, ISignal } from '@jupyterlab/ui-components';

124

125

// Custom model for widget data

126

class CounterModel extends VDomModel {

127

constructor() {

128

super();

129

this._count = 0;

130

}

131

132

get count(): number {

133

return this._count;

134

}

135

136

increment(): void {

137

this._count++;

138

this.stateChanged.emit();

139

}

140

141

private _count: number;

142

}

143

144

// Widget that uses the model

145

class CounterWidget extends VDomRenderer<CounterModel> {

146

constructor() {

147

super(new CounterModel());

148

this.addClass('counter-widget');

149

}

150

151

protected render() {

152

return (

153

<div>

154

<p>Count: {this.model.count}</p>

155

<button onClick={() => this.model.increment()}>

156

Increment

157

</button>

158

</div>

159

);

160

}

161

}

162

163

// Widget automatically re-renders when model changes

164

const counter = new CounterWidget();

165

```

166

167

### UseSignal React Component

168

169

React component for connecting to Lumino signals within React components.

170

171

```typescript { .api }

172

/**

173

* React component for listening to Lumino signals

174

*/

175

interface IUseSignalProps<SENDER, ARGS> {

176

/** Signal to listen to */

177

signal: ISignal<SENDER, ARGS>;

178

/** Initial sender value */

179

initialSender?: SENDER;

180

/** Initial arguments value */

181

initialArgs?: ARGS;

182

/** Render function called with signal data */

183

children: (sender?: SENDER, args?: ARGS) => React.ReactNode;

184

/** Function to determine if component should update */

185

shouldUpdate?: (sender: SENDER, args: ARGS) => boolean;

186

}

187

188

class UseSignal<SENDER, ARGS> extends React.Component<

189

IUseSignalProps<SENDER, ARGS>,

190

IUseSignalState<SENDER, ARGS>

191

>;

192

```

193

194

**Usage Examples:**

195

196

```typescript

197

import React from 'react';

198

import { UseSignal, ReactWidget } from '@jupyterlab/ui-components';

199

import { Signal } from '@lumino/signaling';

200

201

// Widget with signal

202

class DataWidget extends ReactWidget {

203

constructor() {

204

super();

205

this._dataChanged = new Signal(this);

206

}

207

208

get dataChanged(): ISignal<this, string[]> {

209

return this._dataChanged;

210

}

211

212

updateData(newData: string[]): void {

213

this._dataChanged.emit(newData);

214

}

215

216

protected render() {

217

return (

218

<div>

219

<UseSignal signal={this.dataChanged}>

220

{(sender, data) => (

221

<ul>

222

{data?.map((item, i) => (

223

<li key={i}>{item}</li>

224

))}

225

</ul>

226

)}

227

</UseSignal>

228

</div>

229

);

230

}

231

232

private _dataChanged: Signal<this, string[]>;

233

}

234

235

// Usage with shouldUpdate

236

<UseSignal

237

signal={mySignal}

238

shouldUpdate={(sender, args) => args.length > 0}

239

>

240

{(sender, args) => <div>Items: {args?.length}</div>}

241

</UseSignal>

242

```

243

244

### Switch Widget

245

246

Toggle switch widget with value tracking and change signals.

247

248

```typescript { .api }

249

/**

250

* Switch widget for boolean toggle functionality

251

*/

252

class Switch extends Widget {

253

constructor();

254

255

/** Current switch value */

256

get value(): boolean;

257

set value(newValue: boolean);

258

259

/** Signal emitted when value changes */

260

get valueChanged(): ISignal<this, IChangedArgs<boolean, boolean, 'value'>>;

261

262

/** Switch label text */

263

get label(): string;

264

set label(x: string);

265

266

/** Switch caption text */

267

get caption(): string;

268

set caption(x: string);

269

}

270

```

271

272

**Usage Examples:**

273

274

```typescript

275

import { Switch } from '@jupyterlab/ui-components';

276

277

// Basic switch usage

278

const debugSwitch = new Switch();

279

debugSwitch.label = 'Enable Debug Mode';

280

debugSwitch.caption = 'Shows additional debugging information';

281

debugSwitch.value = false;

282

283

// Listen for changes

284

debugSwitch.valueChanged.connect((sender, args) => {

285

console.log(`Debug mode ${args.newValue ? 'enabled' : 'disabled'}`);

286

updateDebugMode(args.newValue);

287

});

288

289

// Programmatically toggle

290

function toggleDebug() {

291

debugSwitch.value = !debugSwitch.value;

292

}

293

294

// Add to layout

295

const panel = new Panel();

296

panel.addWidget(debugSwitch);

297

```

298

299

### Collapser Widget

300

301

Collapsible container widget for expandable content sections.

302

303

```typescript { .api }

304

/**

305

* Collapsible panel widget that can contain other widgets

306

*/

307

class Collapser<T extends Widget = Widget> extends Widget {

308

/**

309

* Create a Collapser widget

310

* @param options - Configuration options

311

*/

312

constructor(options: Collapser.IOptions<T>);

313

314

/** The contained widget */

315

get widget(): T;

316

set widget(widget: T);

317

318

/** Whether the collapser is collapsed */

319

get collapsed(): boolean;

320

set collapsed(value: boolean);

321

322

/** Signal emitted when collapse state changes */

323

get collapseChanged(): ISignal<Collapser, void>;

324

325

/** Toggle the collapse state */

326

toggle(): void;

327

328

/** Dispose of the widget and its contents */

329

dispose(): void;

330

}

331

332

namespace Collapser {

333

interface IOptions<T extends Widget = Widget> extends Widget.IOptions {

334

/** Widget to contain */

335

widget: T;

336

/** Initial collapsed state */

337

collapsed?: boolean;

338

}

339

}

340

```

341

342

**Usage Examples:**

343

344

```typescript

345

import { Collapser, ReactWidget } from '@jupyterlab/ui-components';

346

347

// Create content widget

348

const contentWidget = ReactWidget.create(

349

<div>

350

<h3>Expandable Content</h3>

351

<p>This content can be collapsed.</p>

352

</div>

353

);

354

355

// Create collapser

356

const collapser = new Collapser({

357

widget: contentWidget,

358

collapsed: true

359

});

360

361

// Listen for collapse changes

362

collapser.collapseChanged.connect(() => {

363

console.log(`Panel ${collapser.collapsed ? 'collapsed' : 'expanded'}`);

364

});

365

366

// Control programmatically

367

function expandPanel() {

368

collapser.collapsed = false;

369

}

370

371

function collapsePanel() {

372

collapser.collapsed = true;

373

}

374

375

// Toggle with animation

376

function animatedToggle() {

377

collapser.toggle();

378

}

379

```

380

381

### Spinner Widget

382

383

Loading spinner widget for indicating progress.

384

385

```typescript { .api }

386

/**

387

* Spinner widget for showing loading states

388

*/

389

class Spinner extends Widget {

390

constructor();

391

}

392

```

393

394

**Usage Examples:**

395

396

```typescript

397

import { Spinner, Panel } from '@jupyterlab/ui-components';

398

399

// Basic spinner

400

const loadingSpinner = new Spinner();

401

loadingSpinner.addClass('my-loading-spinner');

402

403

// Add to layout

404

const container = new Panel();

405

container.addWidget(loadingSpinner);

406

407

// Show/hide spinner based on loading state

408

async function loadData() {

409

container.addWidget(loadingSpinner);

410

411

try {

412

const data = await fetchData();

413

processData(data);

414

} finally {

415

loadingSpinner.parent = null; // Remove from layout

416

}

417

}

418

```

419

420

### IFrame Widget

421

422

Widget that wraps an HTML iframe element with security and loading options.

423

424

```typescript { .api }

425

/**

426

* Lumino widget that wraps an IFrame with security options

427

*/

428

class IFrame extends Widget {

429

/**

430

* Create an IFrame widget

431

* @param options - IFrame configuration options

432

*/

433

constructor(options?: IFrame.IOptions);

434

435

/** Referrer policy for the iframe */

436

get referrerPolicy(): IFrame.ReferrerPolicy;

437

set referrerPolicy(value: IFrame.ReferrerPolicy);

438

439

/** Loading behavior for the iframe */

440

get loading(): IFrame.Loading;

441

set loading(value: IFrame.Loading);

442

443

/** Sandbox restrictions for the iframe */

444

get sandbox(): IFrame.SandboxExceptions[];

445

set sandbox(values: IFrame.SandboxExceptions[]);

446

447

/** URL to load in the iframe */

448

get url(): string;

449

set url(url: string);

450

}

451

452

namespace IFrame {

453

type ReferrerPolicy =

454

| 'no-referrer'

455

| 'no-referrer-when-downgrade'

456

| 'origin'

457

| 'origin-when-cross-origin'

458

| 'same-origin'

459

| 'strict-origin'

460

| 'strict-origin-when-cross-origin'

461

| 'unsafe-url';

462

463

type SandboxExceptions =

464

| 'allow-downloads'

465

| 'allow-forms'

466

| 'allow-modals'

467

| 'allow-orientation-lock'

468

| 'allow-pointer-lock'

469

| 'allow-popups'

470

| 'popups-to-escape-sandbox'

471

| 'allow-presentation'

472

| 'allow-same-origin'

473

| 'allow-scripts'

474

| 'allow-storage-access-by-user-activation'

475

| 'allow-top-navigation'

476

| 'allow-top-navigation-by-user-activation';

477

478

type Loading = 'eager' | 'lazy';

479

480

interface IOptions {

481

/** Sandbox exceptions to allow */

482

sandbox?: SandboxExceptions[];

483

/** Referrer policy */

484

referrerPolicy?: ReferrerPolicy;

485

/** Loading behavior */

486

loading?: Loading;

487

}

488

}

489

```

490

491

**Usage Examples:**

492

493

```typescript

494

import { IFrame } from '@jupyterlab/ui-components';

495

496

// Basic iframe

497

const docViewer = new IFrame({

498

loading: 'lazy',

499

referrerPolicy: 'strict-origin-when-cross-origin'

500

});

501

docViewer.url = 'https://jupyter.org/documentation';

502

503

// Secure iframe with restricted sandbox

504

const secureFrame = new IFrame({

505

sandbox: ['allow-scripts', 'allow-same-origin'],

506

referrerPolicy: 'no-referrer'

507

});

508

secureFrame.url = 'https://trusted-content.example.com';

509

510

// Iframe for user-generated content

511

const userContentFrame = new IFrame({

512

sandbox: [], // No exceptions - maximum security

513

loading: 'lazy'

514

});

515

516

// Update URL dynamically

517

function loadDocument(url: string) {

518

docViewer.url = url;

519

}

520

521

// Modify security settings

522

function allowForms() {

523

const current = secureFrame.sandbox;

524

secureFrame.sandbox = [...current, 'allow-forms'];

525

}

526

```