sheetloom 0.1.1
sheetloom: ^0.1.1 copied to clipboard
An open-source Flutter package for workbook rendering, sparse cell editing, offline caching, and REST-based sheet synchronization.
import 'package:flutter/material.dart';
import 'package:sheetloom/sheetloom.dart';
void main() {
runApp(const SheetloomExampleApp());
}
class SheetloomExampleApp extends StatelessWidget {
const SheetloomExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF1A7F64)),
useMaterial3: true,
),
home: WorkbookViewerScreen(
fileId: 9,
fileName: 'Farm workbook',
userId: 'demo-user',
repository: _ExampleWorkbookRepository(),
strings: const WorkbookViewerStrings(
workbookSummaryBuilder: _summaryBuilder,
),
),
);
}
}
String _summaryBuilder(int version, int sheetCount) {
return 'Version $version • $sheetCount sheets';
}
class _ExampleWorkbookRepository implements WorkbookRepository {
_ExampleWorkbookRepository()
: _workbook = WorkbookModel(
schemaVersion: 1,
workbookId: 'example_v1',
fileId: 9,
version: 1,
displayName: 'Farm workbook',
locale: 'en',
styles: const [
CellStyleModel(
id: 'header',
fontSize: 14,
fontWeight: 700,
textColor: '#0F172A',
backgroundColor: '#E2F5EE',
horizontalAlign: 'left',
verticalAlign: 'middle',
border: CellBorderModel(),
textDirection: 'ltr',
numberFormat: null,
wrapText: false,
),
CellStyleModel(
id: 'cell',
fontSize: 13,
fontWeight: 400,
textColor: '#111827',
backgroundColor: '#FFFFFF',
horizontalAlign: 'left',
verticalAlign: 'middle',
border: CellBorderModel(),
textDirection: 'ltr',
numberFormat: null,
wrapText: false,
),
],
sheets: const [
SheetModel(
id: 'daily',
name: 'Daily',
rows: 4,
columns: 2,
defaultRowHeight: 42,
defaultColumnWidth: 160,
mergedRanges: [],
rowDimensions: [],
columnDimensions: [],
),
SheetModel(
id: 'inventory',
name: 'Inventory',
rows: 4,
columns: 2,
defaultRowHeight: 42,
defaultColumnWidth: 160,
mergedRanges: [],
rowDimensions: [],
columnDimensions: [],
),
],
),
_sheets = {
'daily': const SheetModel(
id: 'daily',
name: 'Daily',
rows: 4,
columns: 2,
defaultRowHeight: 42,
defaultColumnWidth: 160,
mergedRanges: [],
rowDimensions: [],
columnDimensions: [],
cells: [
CellModel(
row: 1,
col: 1,
type: 'string',
rawValue: 'Metric',
displayValue: 'Metric',
formula: null,
isEditable: false,
styleId: 'header',
),
CellModel(
row: 1,
col: 2,
type: 'string',
rawValue: 'Value',
displayValue: 'Value',
formula: null,
isEditable: false,
styleId: 'header',
),
CellModel(
row: 2,
col: 1,
type: 'string',
rawValue: 'Egg production',
displayValue: 'Egg production',
formula: null,
isEditable: false,
styleId: 'cell',
),
CellModel(
row: 2,
col: 2,
type: 'string',
rawValue: '120',
displayValue: '120',
formula: null,
isEditable: true,
styleId: 'cell',
),
CellModel(
row: 3,
col: 1,
type: 'string',
rawValue: 'Feed usage',
displayValue: 'Feed usage',
formula: null,
isEditable: false,
styleId: 'cell',
),
CellModel(
row: 3,
col: 2,
type: 'string',
rawValue: '38',
displayValue: '38',
formula: null,
isEditable: true,
styleId: 'cell',
),
],
),
'inventory': const SheetModel(
id: 'inventory',
name: 'Inventory',
rows: 4,
columns: 2,
defaultRowHeight: 42,
defaultColumnWidth: 160,
mergedRanges: [],
rowDimensions: [],
columnDimensions: [],
cells: [
CellModel(
row: 1,
col: 1,
type: 'string',
rawValue: 'Item',
displayValue: 'Item',
formula: null,
isEditable: false,
styleId: 'header',
),
CellModel(
row: 1,
col: 2,
type: 'string',
rawValue: 'Stock',
displayValue: 'Stock',
formula: null,
isEditable: false,
styleId: 'header',
),
CellModel(
row: 2,
col: 1,
type: 'string',
rawValue: 'Corn',
displayValue: 'Corn',
formula: null,
isEditable: false,
styleId: 'cell',
),
CellModel(
row: 2,
col: 2,
type: 'string',
rawValue: '12 bags',
displayValue: '12 bags',
formula: null,
isEditable: true,
styleId: 'cell',
),
CellModel(
row: 3,
col: 1,
type: 'string',
rawValue: 'Vaccines',
displayValue: 'Vaccines',
formula: null,
isEditable: false,
styleId: 'cell',
),
CellModel(
row: 3,
col: 2,
type: 'string',
rawValue: '8 units',
displayValue: '8 units',
formula: null,
isEditable: true,
styleId: 'cell',
),
],
),
};
final WorkbookModel _workbook;
final Map<String, SheetModel> _sheets;
final Map<String, WorkbookCellPatch> _patches = {};
@override
Future<WorkbookModel> loadManifest({
required int fileId,
bool forceRefresh = false,
}) async {
return _workbook;
}
@override
Future<SheetModel> loadSheet({
required int fileId,
required int version,
required String sheetId,
required String userId,
bool forceRefresh = false,
}) async {
return _sheets[sheetId]!;
}
@override
Future<WorkbookStateModel> loadState({
required int fileId,
required int version,
required String userId,
bool forceRefresh = false,
}) async {
return WorkbookStateModel(
fileId: fileId,
version: version,
patches: _patches.values.toList(growable: false),
);
}
@override
Future<WorkbookStateModel> saveState({
required int fileId,
required int version,
required String userId,
required List<WorkbookCellPatch> patches,
}) async {
_patches
..clear()
..addEntries(patches.map((patch) => MapEntry(patch.key, patch)));
return WorkbookStateModel(
fileId: fileId,
version: version,
patches: _patches.values.toList(growable: false),
);
}
}