-
Notifications
You must be signed in to change notification settings - Fork 147
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Draft of how widgets could be organized (#8035)
* Draft of how widgets could be organized * Fix nits * Fix deferred imports
- Loading branch information
Showing
8 changed files
with
184 additions
and
120 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
// TODO: Create a function that can create an instance of Node on the server | ||
// We might need to move a lot of code around since Node is currently | ||
// defined in app/lib/frontend/dom/dom.dart | ||
// It's also possible we can define the helper function somewhere else. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
import 'dart:async'; | ||
import 'dart:js_interop'; | ||
|
||
import 'package:collection/collection.dart'; | ||
import 'package:web/web.dart'; | ||
|
||
import '../web_util.dart'; | ||
import 'completion/widget.dart' deferred as completion; | ||
|
||
/// Function to create an instance of the widget given an element and options. | ||
/// | ||
/// [element] which carries `data-widget="$name"`. | ||
/// [options] a map from options to values, where options are specified as | ||
/// `data-$name-$option="$value"`. | ||
/// | ||
/// Hence, a widget called `completion` is created on an element by adding | ||
/// `data-widget="completion"`. And option `src` is specified with: | ||
/// `data-completion-src="$value"`. | ||
typedef _WidgetFn = FutureOr<void> Function( | ||
Element element, | ||
Map<String, String> options, | ||
); | ||
|
||
/// Function for loading a widget. | ||
typedef _WidgetLoaderFn = FutureOr<_WidgetFn> Function(); | ||
|
||
/// Map from widget name to widget loader | ||
final _widgets = <String, _WidgetLoaderFn>{ | ||
'completion': () => completion.loadLibrary().then((_) => completion.create), | ||
}; | ||
|
||
Future<_WidgetFn> _noSuchWidget() async => | ||
(_, __) => throw AssertionError('no such widget'); | ||
|
||
void setupWidgets() async { | ||
final widgetAndElements = document | ||
// query for all elements with the property `data-widget="..."` | ||
.querySelectorAll('[data-widget]') | ||
.toList() // Convert NodeList to List | ||
// We only care about elements | ||
.where((node) => node.isA<HTMLElement>()) | ||
.map((node) => node as HTMLElement) | ||
// group by widget | ||
.groupListsBy((element) => element.getAttribute('data-widget') ?? ''); | ||
|
||
// For each (widget, elements) load widget and create widgets | ||
await Future.wait(widgetAndElements.entries.map((entry) async { | ||
// Get widget name and elements which it should be created for | ||
final MapEntry(key: name, value: elements) = entry; | ||
|
||
// Find the widget and load it | ||
final widget = await (_widgets[name] ?? _noSuchWidget)(); | ||
|
||
// Create widget for each element | ||
await Future.wait(elements.map((element) async { | ||
try { | ||
final prefix = 'data-$name-'; | ||
final options = Map.fromEntries(element | ||
.getAttributeNames() | ||
.iterable | ||
.where((attr) => attr.startsWith(prefix)) | ||
.map((attr) { | ||
return MapEntry( | ||
attr.substring(prefix.length), | ||
element.getAttribute(attr) ?? '', | ||
); | ||
})); | ||
|
||
await widget(element, options); | ||
} catch (e, st) { | ||
console.error('Failed to initialize data-widget="$name"'.toJS); | ||
console.error('Triggered by element:'.toJS); | ||
console.error(element); | ||
console.error(e.toString().toJS); | ||
console.error(st.toString().toJS); | ||
} | ||
})); | ||
})); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters