or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collections.mdconfiguration.mdindex.mdnavigation-utilities.mdnavigation.mdpreview.mdquerying.mdrendering.mdruntime-utilities.md

preview.mddocs/

0

# Preview System

1

2

Live content editing system with field definitions, authentication, and real-time preview capabilities for content management workflows.

3

4

## Capabilities

5

6

### Field Definition

7

8

Creates preview-compatible field configurations for content editing interfaces.

9

10

```typescript { .api }

11

/**

12

* Helper to build preview-compatible field configuration

13

* @param config - Field configuration object

14

* @returns Configured preview field

15

*/

16

function field(config: FieldConfig): PreviewField;

17

18

interface FieldConfig {

19

/** Field input type */

20

type: PickerTypes;

21

/** Field identifier */

22

name: string;

23

/** Display label for field */

24

label?: string;

25

/** Whether field is required */

26

required?: boolean;

27

/** Default value */

28

default?: unknown;

29

/** Field validation rules */

30

validation?: ValidationRule[];

31

/** Field-specific options */

32

options?: FieldOptions;

33

}

34

35

interface PreviewField {

36

type: PickerTypes;

37

name: string;

38

label: string;

39

required: boolean;

40

default?: unknown;

41

validation: ValidationRule[];

42

options: FieldOptions;

43

}

44

```

45

46

**Usage Examples:**

47

48

```typescript

49

import { field } from '@nuxt/content/preview';

50

51

// Text input field

52

const titleField = field({

53

type: 'text',

54

name: 'title',

55

label: 'Article Title',

56

required: true,

57

validation: [

58

{ type: 'minLength', value: 5, message: 'Title must be at least 5 characters' },

59

{ type: 'maxLength', value: 100, message: 'Title must not exceed 100 characters' }

60

]

61

});

62

63

// Rich text editor

64

const contentField = field({

65

type: 'richtext',

66

name: 'content',

67

label: 'Article Content',

68

required: true,

69

options: {

70

toolbar: ['bold', 'italic', 'link', 'code'],

71

placeholder: 'Write your article content...'

72

}

73

});

74

75

// Select dropdown

76

const categoryField = field({

77

type: 'select',

78

name: 'category',

79

label: 'Category',

80

required: true,

81

options: {

82

choices: [

83

{ label: 'Technology', value: 'tech' },

84

{ label: 'Design', value: 'design' },

85

{ label: 'Business', value: 'business' }

86

]

87

}

88

});

89

90

// Date picker

91

const publishDateField = field({

92

type: 'date',

93

name: 'publishedAt',

94

label: 'Publish Date',

95

default: new Date(),

96

options: {

97

format: 'YYYY-MM-DD',

98

minDate: new Date()

99

}

100

});

101

```

102

103

### Group Definition

104

105

Groups preview fields with schema validation and organization.

106

107

```typescript { .api }

108

/**

109

* Groups preview fields with schema validation

110

* @param config - Group configuration object

111

* @returns Configured preview group

112

*/

113

function group(config: GroupConfig): PreviewGroup;

114

115

interface GroupConfig {

116

/** Group identifier */

117

name: string;

118

/** Display label for group */

119

label?: string;

120

/** Fields within this group */

121

fields: PreviewField[];

122

/** Group validation schema */

123

schema?: PartialSchema;

124

/** Group display options */

125

options?: GroupOptions;

126

}

127

128

interface PreviewGroup {

129

name: string;

130

label: string;

131

fields: PreviewField[];

132

schema: PartialSchema;

133

options: GroupOptions;

134

}

135

```

136

137

**Usage Examples:**

138

139

```typescript

140

import { field, group } from '@nuxt/content/preview';

141

142

// Article metadata group

143

const metadataGroup = group({

144

name: 'metadata',

145

label: 'Article Metadata',

146

fields: [

147

field({

148

type: 'text',

149

name: 'title',

150

label: 'Title',

151

required: true

152

}),

153

field({

154

type: 'textarea',

155

name: 'description',

156

label: 'Description',

157

options: { rows: 3 }

158

}),

159

field({

160

type: 'select',

161

name: 'status',

162

label: 'Status',

163

default: 'draft',

164

options: {

165

choices: [

166

{ label: 'Draft', value: 'draft' },

167

{ label: 'Published', value: 'published' },

168

{ label: 'Archived', value: 'archived' }

169

]

170

}

171

})

172

],

173

options: {

174

collapsible: true,

175

expanded: true

176

}

177

});

178

179

// Author information group

180

const authorGroup = group({

181

name: 'author',

182

label: 'Author Information',

183

fields: [

184

field({

185

type: 'text',

186

name: 'name',

187

label: 'Author Name',

188

required: true

189

}),

190

field({

191

type: 'email',

192

name: 'email',

193

label: 'Author Email'

194

}),

195

field({

196

type: 'image',

197

name: 'avatar',

198

label: 'Author Avatar',

199

options: {

200

accept: 'image/*',

201

maxSize: '2MB'

202

}

203

})

204

]

205

});

206

```

207

208

## Field Types

209

210

### Text Input Types

211

212

```typescript { .api }

213

type TextFieldTypes = 'text' | 'textarea' | 'email' | 'url' | 'password';

214

215

interface TextFieldOptions {

216

/** Placeholder text */

217

placeholder?: string;

218

/** Maximum character length */

219

maxLength?: number;

220

/** Minimum character length */

221

minLength?: number;

222

/** Input pattern regex */

223

pattern?: string;

224

/** Number of rows (textarea only) */

225

rows?: number;

226

/** Auto-resize textarea */

227

autoResize?: boolean;

228

}

229

```

230

231

### Rich Content Types

232

233

```typescript { .api }

234

type RichContentTypes = 'richtext' | 'markdown' | 'code';

235

236

interface RichTextOptions {

237

/** Toolbar buttons to show */

238

toolbar?: string[];

239

/** Editor placeholder */

240

placeholder?: string;

241

/** Enable code blocks */

242

codeBlocks?: boolean;

243

/** Custom editor extensions */

244

extensions?: EditorExtension[];

245

}

246

247

interface MarkdownOptions {

248

/** Enable live preview */

249

preview?: boolean;

250

/** Syntax highlighting theme */

251

theme?: string;

252

/** Supported languages for code blocks */

253

languages?: string[];

254

}

255

256

interface CodeOptions {

257

/** Programming language */

258

language?: string;

259

/** Show line numbers */

260

lineNumbers?: boolean;

261

/** Editor theme */

262

theme?: string;

263

/** Tab size */

264

tabSize?: number;

265

}

266

```

267

268

### Selection Types

269

270

```typescript { .api }

271

type SelectionTypes = 'select' | 'multiselect' | 'radio' | 'checkbox' | 'toggle';

272

273

interface SelectionOptions {

274

/** Available choices */

275

choices: Choice[];

276

/** Allow multiple selections */

277

multiple?: boolean;

278

/** Enable search/filtering */

279

searchable?: boolean;

280

/** Maximum selections (multiselect) */

281

maxSelections?: number;

282

}

283

284

interface Choice {

285

/** Display label */

286

label: string;

287

/** Option value */

288

value: string | number;

289

/** Option description */

290

description?: string;

291

/** Option disabled state */

292

disabled?: boolean;

293

/** Option group */

294

group?: string;

295

}

296

```

297

298

### Media Types

299

300

```typescript { .api }

301

type MediaTypes = 'image' | 'file' | 'video' | 'audio';

302

303

interface MediaOptions {

304

/** Accepted file types */

305

accept?: string;

306

/** Maximum file size */

307

maxSize?: string;

308

/** Image dimensions */

309

dimensions?: {

310

width?: number;

311

height?: number;

312

aspectRatio?: string;

313

};

314

/** Generate thumbnails */

315

thumbnails?: boolean;

316

/** Upload destination */

317

destination?: string;

318

}

319

```

320

321

### Date and Time Types

322

323

```typescript { .api }

324

type DateTimeTypes = 'date' | 'datetime' | 'time';

325

326

interface DateTimeOptions {

327

/** Date format */

328

format?: string;

329

/** Minimum date */

330

minDate?: Date;

331

/** Maximum date */

332

maxDate?: Date;

333

/** Enable time picker */

334

enableTime?: boolean;

335

/** Time format (12/24 hour) */

336

timeFormat?: '12' | '24';

337

/** Default timezone */

338

timezone?: string;

339

}

340

```

341

342

## Validation

343

344

### Validation Rules

345

346

```typescript { .api }

347

interface ValidationRule {

348

/** Validation type */

349

type: ValidationType;

350

/** Validation value/parameter */

351

value?: unknown;

352

/** Error message */

353

message: string;

354

/** Custom validation function */

355

validator?: (value: unknown) => boolean | Promise<boolean>;

356

}

357

358

type ValidationType =

359

| 'required' | 'minLength' | 'maxLength'

360

| 'min' | 'max' | 'email' | 'url'

361

| 'pattern' | 'custom';

362

```

363

364

**Usage Examples:**

365

366

```typescript

367

// Complex validation rules

368

const emailField = field({

369

type: 'email',

370

name: 'email',

371

label: 'Email Address',

372

required: true,

373

validation: [

374

{

375

type: 'required',

376

message: 'Email is required'

377

},

378

{

379

type: 'email',

380

message: 'Must be a valid email address'

381

},

382

{

383

type: 'custom',

384

message: 'Email domain not allowed',

385

validator: async (email) => {

386

const domain = email.split('@')[1];

387

const allowedDomains = ['company.com', 'partner.com'];

388

return allowedDomains.includes(domain);

389

}

390

}

391

]

392

});

393

```

394

395

## Preview Integration

396

397

### Content Form Configuration

398

399

```typescript

400

// content/blog/preview.config.ts

401

import { field, group } from '@nuxt/content/preview';

402

403

export default {

404

// Field groups for content editing

405

groups: [

406

group({

407

name: 'content',

408

label: 'Content',

409

fields: [

410

field({

411

type: 'text',

412

name: 'title',

413

label: 'Title',

414

required: true

415

}),

416

field({

417

type: 'richtext',

418

name: 'content',

419

label: 'Content',

420

required: true

421

})

422

]

423

}),

424

425

group({

426

name: 'meta',

427

label: 'Metadata',

428

fields: [

429

field({

430

type: 'date',

431

name: 'publishedAt',

432

label: 'Publish Date'

433

}),

434

field({

435

type: 'multiselect',

436

name: 'tags',

437

label: 'Tags',

438

options: {

439

choices: [

440

{ label: 'Vue.js', value: 'vue' },

441

{ label: 'Nuxt.js', value: 'nuxt' },

442

{ label: 'JavaScript', value: 'js' }

443

]

444

}

445

})

446

]

447

})

448

]

449

};

450

```

451

452

## Types

453

454

```typescript { .api }

455

type PickerTypes =

456

| 'text' | 'textarea' | 'email' | 'url' | 'password'

457

| 'richtext' | 'markdown' | 'code'

458

| 'select' | 'multiselect' | 'radio' | 'checkbox' | 'toggle'

459

| 'image' | 'file' | 'video' | 'audio'

460

| 'date' | 'datetime' | 'time'

461

| 'number' | 'range' | 'color';

462

463

interface PreviewFieldData {

464

/** Field type */

465

type: PickerTypes;

466

/** Field value */

467

value: unknown;

468

/** Field metadata */

469

meta: FieldMeta;

470

/** Validation state */

471

validation: ValidationState;

472

}

473

474

interface ConfigInputsTypes {

475

[fieldName: string]: PickerTypes;

476

}

477

478

interface PartialSchema {

479

/** Schema validation function */

480

validate: (data: unknown) => ValidationResult;

481

/** Schema transformation function */

482

transform?: (data: unknown) => unknown;

483

}

484

485

interface GroupOptions {

486

/** Group is collapsible */

487

collapsible?: boolean;

488

/** Group is expanded by default */

489

expanded?: boolean;

490

/** Group display order */

491

order?: number;

492

/** Group CSS classes */

493

className?: string;

494

/** Group conditional display */

495

conditional?: ConditionalRule;

496

}

497

498

interface ConditionalRule {

499

/** Field to watch for condition */

500

field: string;

501

/** Condition operator */

502

operator: '=' | '!=' | 'in' | 'not_in';

503

/** Condition value */

504

value: unknown;

505

}

506

```