createFlintApp function

void createFlintApp(
  1. String selector, {
  2. Map<String, FlintPageBuilder>? pages,
  3. FlintComponentRegistry? registry,
  4. List<FlintPageMiddleware> middlewares = const [],
  5. List<StyleSheet> stylesheets = const [],
  6. RootDesign? rootDesign,
  7. FlintComponent missingPage(
    1. String component
    )?,
})

Mounts a Flint UI app into the element matching selector.

The host element must contain a data-flint-page payload generated by FlintDart's page response helpers.

Implementation

void createFlintApp(
  String selector, {
  Map<String, FlintPageBuilder>? pages,
  FlintComponentRegistry? registry,
  List<FlintPageMiddleware> middlewares = const [],
  List<StyleSheet> stylesheets = const [],
  RootDesign? rootDesign,
  FlintComponent Function(String component)? missingPage,
}) {
  final host = web.document.querySelector(selector);

  if (host == null) {
    throw StateError('No element found for selector "$selector".');
  }

  registerRootDesign(
    RootDesign(
      name: 'flint-animations',
      keyframes: [StyleKeyframes.spin(), StyleKeyframes.fadeIn()],
    ),
  );

  if (rootDesign != null) {
    registerRootDesign(rootDesign);
  }

  for (final stylesheet in stylesheets) {
    registerStyleSheet(stylesheet);
  }

  final page = _readPage(host);
  final root = createRootForElement(host);
  var navigationRequest = 0;

  void renderPage(FlintPage page) {
    final context = FlintPageContext(host: host, page: page);

    for (final middleware in middlewares) {
      middleware(context);
      if (context.stopped) return;
    }

    final builder = registry?[page.component] ?? pages?[page.component];
    final component =
        builder?.call(page.props) ??
        missingPage?.call(page.component) ??
        MissingFlintPage(page.component);

    root.render(component);
  }

  Future<void> renderCurrentLocation() async {
    final requestId = ++navigationRequest;
    try {
      final next = await _fetchPageForCurrentLocation(selector);
      if (requestId != navigationRequest) return;
      host.setAttribute('data-flint-page', jsonEncode(next.page));
      if (next.title != null && next.title!.isNotEmpty) {
        web.document.title = next.title!;
      }
      renderPage(FlintPage.fromJson(next.page));
    } catch (_) {
      web.window.location.assign(
        '${web.window.location.pathname}${web.window.location.search}',
      );
    }
  }

  renderPage(page);
  web.window.addEventListener(
    'flint:navigate',
    ((web.Event _) {
      renderCurrentLocation();
    }).toJS,
  );
  web.window.addEventListener(
    'popstate',
    ((web.Event _) {
      renderCurrentLocation();
    }).toJS,
  );
}