From b86670032bfde3fc88ecfdb13e207ef347b80437 Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Mon, 17 Jul 2017 12:29:37 -0700 Subject: [PATCH] Improve some doc comments + That were discovered while doing the memory leak audit --- lib/src/component/resize_sensor.dart | 3 +- .../component_declaration/component_base.dart | 175 +++++++++++++----- .../component_type_checking.dart | 52 +++++- .../component_declaration/flux_component.dart | 8 +- lib/src/util/class_names.dart | 134 ++++++++++---- lib/src/util/css_value_util.dart | 15 +- lib/src/util/dom_util.dart | 7 +- lib/src/util/event_helpers.dart | 26 +-- lib/src/util/key_constants.dart | 6 +- lib/src/util/map_util.dart | 21 ++- lib/src/util/pretty_print.dart | 2 + lib/src/util/prop_errors.dart | 8 +- lib/src/util/prop_key_util.dart | 4 +- lib/src/util/react_wrappers.dart | 35 ++-- lib/src/util/rem_util.dart | 49 ++--- lib/src/util/string_util.dart | 11 +- 16 files changed, 386 insertions(+), 170 deletions(-) diff --git a/lib/src/component/resize_sensor.dart b/lib/src/component/resize_sensor.dart index 28d95788a3..112f8eebad 100644 --- a/lib/src/component/resize_sensor.dart +++ b/lib/src/component/resize_sensor.dart @@ -21,7 +21,6 @@ import 'dart:html'; import 'package:meta/meta.dart'; import 'package:platform_detect/platform_detect.dart'; -import 'package:react/react.dart' as react; import 'package:over_react/over_react.dart'; /// A wrapper component that detects when its parent is resized. @@ -189,7 +188,7 @@ class ResizeSensorComponent extends UiComponent with _SafeAni /// When the expand or collapse sensors are resized, builds a [ResizeSensorEvent] and calls /// props.onResize with it. Then, calls through to [_reset()]. - void _handleSensorScroll(react.SyntheticEvent _) { + void _handleSensorScroll(SyntheticEvent _) { if (_scrollEventsToIgnore > 0) { _scrollEventsToIgnore--; return; diff --git a/lib/src/component_declaration/component_base.dart b/lib/src/component_declaration/component_base.dart index e2093f35ae..1dbb8404ca 100644 --- a/lib/src/component_declaration/component_base.dart +++ b/lib/src/component_declaration/component_base.dart @@ -31,6 +31,7 @@ import 'package:over_react/over_react.dart' show import 'package:over_react/src/component_declaration/component_type_checking.dart'; import 'package:over_react/src/util/ddc_emulated_function_name_bug.dart' as ddc_emulated_function_name_bug; +import 'package:over_react/src/util/test_mode.dart'; import 'package:react/react.dart' as react; import 'package:react/react_client.dart'; import 'package:w_common/disposable.dart'; @@ -91,29 +92,71 @@ typedef TProps UiFactory([Map backingProps]); /// For use as a Function variable type when the `backingProps` argument is not required. typedef TProps BuilderOnlyUiFactory(); -/// The basis for a over_react component. +/// The basis for an over_react component. /// -/// Includes support for strongly-typed props and utilities for prop and CSS classname forwarding. +/// Includes support for strongly-typed [UiProps] and utilities for prop and CSS classname forwarding. /// -/// Extends [react.Component]. +/// __Prop and CSS className forwarding when your component renders a composite component:__ /// -/// Implements [DisposableManagerV3] +/// @Component() +/// class YourComponent extends UiComponent { +/// Map getDefaultProps() => (newProps() +/// ..aPropOnYourComponent = /* default value */ +/// ); /// -/// Related: [UiStatefulComponent] +/// @override +/// render() { +/// var classes = forwardingClassNameBuilder() +/// ..add('your-component-base-class') +/// ..add('a-conditional-class', shouldApplyConditionalClass); +/// +/// return (SomeChildComponent() +/// ..addProps(copyUnconsumedProps()) +/// ..className = classes.toClassName() +/// )(props.children); +/// } +/// } +/// +/// __Prop and CSS className forwarding when your component renders a DOM component:__ +/// +/// @Component() +/// class YourComponent extends UiComponent { +/// @override +/// render() { +/// var classes = forwardingClassNameBuilder() +/// ..add('your-component-base-class') +/// ..add('a-conditional-class', shouldApplyConditionalClass); +/// +/// return (Dom.div() +/// ..addProps(copyUnconsumedDomProps()) +/// ..className = classes.toClassName() +/// )(props.children); +/// } +/// } +/// +/// > Related: [UiStatefulComponent] abstract class UiComponent extends react.Component implements DisposableManagerV3 { Disposable _disposableProxy; /// The props for the non-forwarding props defined in this component. Iterable get consumedProps => null; - /// Returns a copy of this component's props with [consumedPropKeys] omitted. + /// Returns a copy of this component's props with keys found in [consumedProps] omitted. + /// + /// > Should be used alongside [forwardingClassNameBuilder]. + /// + /// > Related [copyUnconsumedDomProps] Map copyUnconsumedProps() { var consumedPropKeys = consumedProps?.map((ConsumedProps consumedProps) => consumedProps.keys) ?? const []; return copyProps(keySetsToOmit: consumedPropKeys); } - /// Returns a copy of this component's props with [consumedPropKeys] and non-DOM props omitted. + /// Returns a copy of this component's props with keys found in [consumedProps] and non-DOM props omitted. + /// + /// > Should be used alongside [forwardingClassNameBuilder]. + /// + /// > Related [copyUnconsumedProps] Map copyUnconsumedDomProps() { var consumedPropKeys = consumedProps?.map((ConsumedProps consumedProps) => consumedProps.keys) ?? const []; @@ -143,18 +186,20 @@ abstract class UiComponent extends react.Component imple }); } - /// Returns a new ClassNameBuilder with className and blacklist values added from [CssClassProps.className] and - /// [CssClassProps.classNameBlackList], if they are specified. + /// Returns a new ClassNameBuilder with className and blacklist values added from [CssClassPropsMixin.className] and + /// [CssClassPropsMixin.classNameBlacklist], if they are specified. /// /// This method should be used as the basis for the classNames of components receiving forwarded props. + /// + /// > Should be used alongside [copyUnconsumedProps] or [copyUnconsumedDomProps]. ClassNameBuilder forwardingClassNameBuilder() { return new ClassNameBuilder.fromProps(this.props); } @override @mustCallSuper - void componentWillReceiveProps(Map newProps) { - validateRequiredProps(newProps); + void componentWillReceiveProps(Map nextProps) { + validateRequiredProps(nextProps); } @override @@ -179,7 +224,7 @@ abstract class UiComponent extends react.Component imple /// A typed props object corresponding to the current untyped props Map ([unwrappedProps]). /// - /// Created using [typedPropsFactory] and cached for each Map instance. + /// Created using [typedPropsFactory] and cached for each Map instance within [_typedPropsCache]. @override TProps get props { var unwrappedProps = this.unwrappedProps; @@ -269,13 +314,31 @@ abstract class UiComponent extends react.Component imple // ---------------------------------------------------------------------- } -/// The basis for a stateful over_react component. +/// The basis for a _stateful_ over_react component. +/// +/// Includes support for strongly-typed [UiState] in-addition-to the +/// strongly-typed props and utilities for prop and CSS classname forwarding provided by [UiComponent]. /// -/// Includes support for strongly-typed props and state and utilities for prop and CSS classname forwarding. +/// __Initializing state:__ /// -/// Extends [react.Component]. +/// @Component() +/// class YourComponent extends UiStatefulComponent { +/// Map getInitialState() => (newState() +/// ..aStateKeyWithinYourStateClass = /* default value */ +/// ); /// -/// Related: [UiComponent] +/// @override +/// render() { +/// var classes = forwardingClassNameBuilder() +/// ..add('your-component-base-class') +/// ..add('a-conditional-class', state.aStateKeyWithinYourStateClass); +/// +/// return (SomeChildComponent() +/// ..addProps(copyUnconsumedProps()) +/// ..className = classes.toClassName() +/// )(props.children); +/// } +/// } abstract class UiStatefulComponent extends UiComponent { // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- @@ -286,7 +349,7 @@ abstract class UiStatefulComponent super.state = value; @@ -322,9 +385,9 @@ abstract class UiStatefulComponent Note: Implements MapViewMixin instead of extending it so that the abstract state declarations /// don't need a constructor. The generated implementations can mix that functionality in. abstract class UiState extends Object implements StateMapViewMixin, MapViewMixin, Map { // Manually implement members from `StateMapViewMixin`, @@ -360,13 +423,13 @@ const defaultTestIdKey = 'data-test-id'; /// Used in [UiProps.modifyProps]. typedef PropsModifier(Map props); -/// A [dart.collection.MapView]-like class with strongly-typed getters/setters for React props that +/// A `dart.collection.MapView`-like class with strongly-typed getters/setters for React props that /// is also capable of creating React component instances. /// -/// For use as a typed view into existing props [Maps], or as a builder to create new component +/// For use as a typed view into existing props [Map]s, or as a builder to create new component /// instances via a fluent-style interface. /// -/// Note: Implements MapViewMixin instead of extending it so that the abstract [Props] declarations +/// > Note: Implements MapViewMixin instead of extending it so that the abstract [Props] declarations /// don't need a constructor. The generated implementations can mix that functionality in. abstract class UiProps extends Object with ReactPropsMixin, UbiquitousDomPropsMixin, CssClassPropsMixin @@ -403,21 +466,33 @@ abstract class UiProps extends Object @override Map get _map => this.props; @override String toString() => '$runtimeType: ${prettyPrintMap(_map)}'; - /// Adds an arbitrary prop key-value pair if [shouldAdd] is true, otherwise, does nothing. + /// Adds an arbitrary [propKey]/[value] pair if [shouldAdd] is `true`. + /// + /// Is a noop if [shouldAdd] is `false`. + /// + /// > Related: [addProps] void addProp(propKey, value, [bool shouldAdd = true]) { if (!shouldAdd) return; - props[propKey] = value; + this[propKey] = value; } - /// Adds a Map of arbitrary props if [shouldAdd] is true and [propMap] is not null. + /// Adds an arbitrary [propMap] of arbitrary props if [shouldAdd] is true. + /// + /// Is a noop if [shouldAdd] is `false` or [propMap] is `null`. + /// + /// > Related: [addProp], [modifyProps] void addProps(Map propMap, [bool shouldAdd = true]) { if (!shouldAdd || propMap == null) return; - props.addAll(propMap); + this.addAll(propMap); } - /// Allows [modifier] to alter this instance of props if [shouldModify] is true and [modifier] is not null. + /// Allows [modifier] to alter the instance if [shouldModify] is true. + /// + /// Is a noop if [shouldModify] is `false` or [modifier] is `null`. + /// + /// > Related: [addProps] void modifyProps(PropsModifier modifier, [bool shouldModify = true]){ if (!shouldModify || modifier == null) return; @@ -425,6 +500,8 @@ abstract class UiProps extends Object } /// Whether [UiProps] is in a testing environment. + /// + /// Do not set this directly; Call [enableTestMode] or [disableTestMode] instead. static bool testMode = false; /// Whether [UiProps] is in a testing environment at build time. @@ -438,9 +515,11 @@ abstract class UiProps extends Object /// See: . bool get _inTestMode => testMode || _testModeFromEnvironment; - /// Adds [value] to the prop [key] for use in a testing environment by using space-delimiting. + /// Adds [value] to the prop [key] _(delimited with a single space)_. /// /// Allows for an element to have multiple test IDs to prevent overwriting when cloning elements or components. + /// + /// > For use in a testing environment (when [testMode] is true). void addTestId(String value, {String key: defaultTestIdKey}) { if (!_inTestMode || value == null) { return; @@ -455,19 +534,22 @@ abstract class UiProps extends Object } } - /// Gets the `data-test-id` prop or one testId from the prop (or custom [key] prop value) for use in a testing - /// environment. + /// Gets the [defaultTestIdKey] prop value, or one testId from the prop _(or custom [key] prop value)_. + /// + /// > For use in a testing environment (when [testMode] is true). String getTestId({String key: defaultTestIdKey}) { return props[key]; } - /// Gets the `data-test-id` prop key to [value] for use in a testing environment. + /// Gets the `data-test-id` prop key for use in a testing environment. + /// + /// DEPRECATED. Use [getTestId] instead. @Deprecated('2.0.0') String get testId { return getTestId(); } - /// Returns a new component with this builder's props and the specified children. + /// Returns a new component with this builder's [props] and the specified [children]. ReactElement build([dynamic children]) { assert(_validateChildren(children)); @@ -475,7 +557,8 @@ abstract class UiProps extends Object } /// Creates a new component with this builder's props and the specified [children]. - /// (alias for [build] with support for variadic children) + /// + /// _(alias for [build] with support for variadic children)_ /// /// This method actually takes any number of children as arguments ([c2], [c3], ...) via [noSuchMethod]. /// @@ -552,8 +635,10 @@ abstract class _OverReactMapViewBase { Map get _map; } -/// Works in conjunction with [MapViewMixin] to provide [dart.collection.MapView]-like +/// Works in conjunction with [MapViewMixin] to provide `dart.collection.MapView`-like /// functionality to [UiProps] subclasses. +/// +/// > Related: [StateMapViewMixin] abstract class PropsMapViewMixin implements _OverReactMapViewBase { /// The props maintained by this builder and used passed into the component when built. /// In this case, it's the current MapView object. @@ -566,8 +651,10 @@ abstract class PropsMapViewMixin implements _OverReactMapViewBase { String toString() => '$runtimeType: ${prettyPrintMap(_map)}'; } -/// Works in conjunction with [MapViewMixin] to provide [dart.collection.MapView]-like +/// Works in conjunction with [MapViewMixin] to provide `dart.collection.MapView`-like /// functionality to [UiState] subclasses. +/// +/// > Related: [PropsMapViewMixin] abstract class StateMapViewMixin implements _OverReactMapViewBase { Map get state; @@ -578,7 +665,7 @@ abstract class StateMapViewMixin implements _OverReactMapViewBase { String toString() => '$runtimeType: ${prettyPrintMap(_map)}'; } -/// Provides [dart.collection.MapView]-like behavior by proxying an internal map. +/// Provides `dart.collection.MapView`-like behavior by proxying an internal map. /// /// Works in conjunction with [PropsMapViewMixin] and [StateMapViewMixin] to implement [Map] /// in [UiProps] and [UiState] subclasses. @@ -602,7 +689,9 @@ abstract class MapViewMixin implements _OverReactMapViewBase { Iterable get values => _map.values; } -/// Provides a representation of a single `prop`. +/// Provides a representation of a single `prop` declared within a [UiProps] subclass or props mixin. +/// +/// > Related: [StateDescriptor] class PropDescriptor { /// The string key associated with the `prop`. final String key; @@ -616,7 +705,9 @@ class PropDescriptor { const PropDescriptor(this.key, {this.isRequired: false, this.isNullable: false, this.errorMessage: ''}); } -/// Provides a representation of a single `state`. +/// Provides a representation of a single `state` declared within a [UiState] subclass or state mixin. +/// +/// > Related: [PropDescriptor] class StateDescriptor { /// The string key associated with the `state`. final String key; @@ -636,13 +727,13 @@ class StateDescriptor { const StateDescriptor(this.key, {this.isRequired: false, this.isNullable: false, this.errorMessage}); } -/// Provides a list of [PropDescriptor] and a top-level list of their keys, for easy access. +/// Provides a list of [PropDescriptor]s and a top-level list of their keys, for easy access. class ConsumedProps { - /// Rich views of props. + /// Rich views of prop declarations. /// /// This includes string keys, and required prop validation related fields. final List props; - /// Top-level acessor of string keys of props stored in [props]. + /// Top-level accessor of string keys of props stored in [props]. final List keys; const ConsumedProps(this.props, this.keys); diff --git a/lib/src/component_declaration/component_type_checking.dart b/lib/src/component_declaration/component_type_checking.dart index 1baeeae9f5..7794149ba8 100644 --- a/lib/src/component_declaration/component_type_checking.dart +++ b/lib/src/component_declaration/component_type_checking.dart @@ -16,9 +16,11 @@ library over_react.component_declaration.component_type_checking; import 'package:over_react/src/component_declaration/component_base.dart' show UiFactory; +import 'package:over_react/src/component_declaration/annotations.dart' as annotations show Component; import 'package:over_react/src/util/react_wrappers.dart'; import 'package:react/react_client.dart'; import 'package:react/react_client/js_interop_helpers.dart'; +import 'package:react/react_client/react_interop.dart'; // ---------------------------------------------------------------------- // Component type registration and internal type metadata management @@ -73,10 +75,40 @@ class ComponentTypeMeta { /// /// Used to enable inheritance in component type-checking in [isComponentOfType]. /// - /// E.g., if component `Bar` is a subtype of component `Foo`, then: + /// E.g., if component `Bar` is a subtype of component `Foo`: + /// + /// // + /// // foo.dart + /// // + /// + /// @Factory() + /// UiFactory Foo; + /// + /// @Component() + /// class FooComponent extends UiComponent { + /// // ... + /// } + /// + /// // + /// // bar.dart + /// // + /// + /// @Factory() + /// UiFactory Foo; + /// + /// @Component(subtypeOf: FooComponent) + /// class BarComponent extends UiComponent { + /// // ... + /// } + /// + /// // + /// // app.dart + /// // /// /// isComponentOfType(Bar()(), Bar); // true (due to normal type-checking) /// isComponentOfType(Bar()(), Foo); // true (due to parent type-checking) + /// + /// > See: `subtypeOf` (within [annotations.Component]) final ReactDartComponentFactoryProxy parentType; ComponentTypeMeta(this.isWrapper, this.parentType); @@ -108,7 +140,7 @@ class ComponentTypeMeta { /// /// Consumers of this function should be sure to take the latter case into consideration. /// -/// __CAVEAT:__ Due to type-checking limitations on JS-interop types, when [typeAlias] is a [Function], +/// > __CAVEAT:__ Due to type-checking limitations on JS-interop types, when [typeAlias] is a [Function], /// and it is not found to be an alias for another type, it will be returned as if it were a valid type. dynamic getComponentTypeFromAlias(dynamic typeAlias) { /// If `typeAlias` is a factory, return its type. @@ -143,19 +175,19 @@ dynamic getComponentTypeFromAlias(dynamic typeAlias) { /// * [String] tag name (DOM components) /// * [Function] ([ReactClass]) factory (Dart/JS composite components) /// -/// Note: It's impossible to determine know whether something is a ReactClass due to type-checking restrictions -/// for JS-interop classes, so a Function type-check is the best we can do. +/// > __NOTE:__ It's impossible to determine know whether something is a [ReactClass] due to type-checking restrictions +/// for JS-interop classes, so a Function type-check is the best we can do. bool isPotentiallyValidComponentType(dynamic type) { return type is Function || type is String; } -/// Returns an [Iterable] of all component types that are ancestors of [typeAlias]. +/// Returns an [Iterable] of all component types that are ancestors of [type]. /// /// For example, given components A, B, and C, where B subtypes A and C subtypes B: /// -/// getParentTypes(getTypeFromAlias(A)); // [] -/// getParentTypes(getTypeFromAlias(B)); // [A].map(getTypeFromAlias) -/// getParentTypes(getTypeFromAlias(C)); // [B, A].map(getTypeFromAlias) +/// getParentTypes(getComponentTypeFromAlias(A)); // [] +/// getParentTypes(getComponentTypeFromAlias(B)); // [A].map(getTypeFromAlias) +/// getParentTypes(getComponentTypeFromAlias(C)); // [B, A].map(getTypeFromAlias) Iterable getParentTypes(dynamic type) sync* { assert(isPotentiallyValidComponentType(type) && '`type` should be a valid component type (and not null or a type alias).' is String); @@ -182,6 +214,8 @@ Iterable getParentTypes(dynamic type) sync* { /// * [ReactComponentFactoryProxy] /// * [ReactClass] component factory /// * [String] tag name (DOM components only) +/// +/// > Related: [isValidElementOfType] bool isComponentOfType(ReactElement instance, dynamic typeAlias, { bool traverseWrappers: true, bool matchParentTypes: true @@ -228,6 +262,8 @@ bool isComponentOfType(ReactElement instance, dynamic typeAlias, { /// * [ReactComponentFactoryProxy] /// * [ReactClass] component factory /// * [String] tag name (DOM components only) +/// +/// > Related: [isComponentOfType] bool isValidElementOfType(dynamic instance, dynamic typeAlias) { return isValidElement(instance) && isComponentOfType(instance, typeAlias); } diff --git a/lib/src/component_declaration/flux_component.dart b/lib/src/component_declaration/flux_component.dart index 0e3614fb92..ddfdd45fa1 100644 --- a/lib/src/component_declaration/flux_component.dart +++ b/lib/src/component_declaration/flux_component.dart @@ -66,6 +66,8 @@ abstract class FluxUiProps extends UiProps { /// the resulting component. /// /// Use with the over_react transformer via the `@Component()` ([annotations.Component]) annotation. +/// +/// > Related: [FluxUiStatefulComponent] abstract class FluxUiComponent extends UiComponent with _FluxComponentMixin, BatchedRedraws { // Redeclare these lifecycle methods with `mustCallSuper`, since `mustCallSuper` added to methods within @@ -102,6 +104,8 @@ abstract class FluxUiComponent extends UiComponent Related: [FluxUiComponent] abstract class FluxUiStatefulComponent extends UiStatefulComponent with _FluxComponentMixin, BatchedRedraws { @@ -156,9 +160,9 @@ abstract class _FluxComponentMixin implements Batche handlers.forEach((store, handler) { String message = 'Cannot listen to a disposed/disposing Store.'; - + var isDisposedOrDisposing = store.isDisposedOrDisposing ?? false; - + assert(!isDisposedOrDisposing, '$message This can be caused by BatchedRedraws ' 'mounting the component asynchronously after the store has been disposed. If you are ' 'in a test environment, try adding an `await window.animationFrame;` before disposing your ' diff --git a/lib/src/util/class_names.dart b/lib/src/util/class_names.dart index dfbed5be66..11b09d0f30 100644 --- a/lib/src/util/class_names.dart +++ b/lib/src/util/class_names.dart @@ -17,14 +17,15 @@ library over_react.class_names; import 'dart:collection'; -// Must import these consts because they are used in the transformed code. -// ignore: unused_import -import 'package:over_react/over_react.dart' show PropDescriptor, ConsumedProps; +import 'package:over_react/over_react.dart' show + // Must import these consts because they are used in the transformed code. + PropDescriptor, ConsumedProps, // ignore: unused_shown_name + UiComponent, UiProps; import 'package:over_react/src/component_declaration/annotations.dart'; -/// Typed getters/setters for props related to CSS class manipulation, and used by all over_react components. +/// Typed getters/setters for props related to CSS class manipulation. /// -/// To be used as a mixin for React components and builders. +/// Universally available on all OverReact components via [UiProps]. @PropsMixin(keyNamespace: '') abstract class CssClassPropsMixin { Map get props; @@ -42,39 +43,44 @@ abstract class CssClassPropsMixin { String classNameBlacklist; } -/// A MapView with the typed getters/setters for all CSS-class-related props. +/// A `MapView` with typed getters/setters for all CSS-class-related props. class CssClassPropsMapView extends MapView with CssClassPropsMixin { /// Create a new instance backed by the specified map. CssClassPropsMapView(Map map) : super(map); /// The props to be manipulated via the getters/setters. - /// In this case, it's the current MapView object. + /// + /// In this case, it's the current [MapView] object. @override Map get props => this; } -/// StringBuffer-backed className builder optimized for adding classNames, with support for blacklisting CSS classes. +/// A [StringBuffer]-backed CSS class builder optimized for adding classNames, +/// with support for blacklisting CSS classes. class ClassNameBuilder { StringBuffer _classNamesBuffer = new StringBuffer(); StringBuffer _blacklistBuffer; - /// Creates a new, empty ClassNameBuilder. + /// Creates a new, empty `ClassNameBuilder` instance. + /// + /// > Related: [UiComponent.forwardingClassNameBuilder] ClassNameBuilder(); - /// Creates a new ClassNameBuilder with className and blacklist values added from [CssClassProps.className] and - /// [CssClassProps.classNameBlackList], if they are specified. + /// Creates a new `ClassNameBuilder` with the [CssClassPropsMixin.className] values and + /// excludes the [CssClassPropsMixin.classNameBlacklist] values if specified within the + /// provided [props] Map. /// /// This method gracefully handles null [props], as well as unspecified/null prop values. ClassNameBuilder.fromProps(Map props) { addFromProps(props); } - /// Adds the className and blacklist values from a [props] Map, using the - /// [CssClassProps.className] and [CssClassProps.classNameBlackList] values. + /// Adds the [CssClassPropsMixin.className] and excludes the [CssClassPropsMixin.classNameBlacklist] values + /// if specified within the provided [props] Map. /// /// This method gracefully handles null [props], as well as unspecified/null prop values. /// - /// This method, along with [toProps], is useful for merging sets of className/blacklist props. + /// > This method, along with [toProps], are useful for merging sets of className/blacklist props. void addFromProps(Map props) { if (props == null) { return; @@ -87,12 +93,31 @@ class ClassNameBuilder { ..blacklist(cssClassProps.classNameBlacklist); } - /// Adds a className string. May be a single CSS class 'token', or multiple space-delimited classes, - /// IF [should] is true, otherwise, does nothing (convenience for helping to inline addition conditionals). + /// Adds all of the CSS classes represented by a space-delimited list of [className]s + /// if [shouldAdd] is `true`. + /// + /// Does not check for / remove duplicate CSS classes. + /// + /// Is a noop if [shouldAdd] is `false`, [className] is `null` or [className] is an empty string. + /// + /// __[shouldAdd] makes conditional CSS classes a breeze:__ /// - /// There is no checking for duplicate CSS classes. - void add(String className, [bool should = true]) { - if (!should || className == null || className == '') { + /// @override + /// render() { + /// var classes = forwardingClassNameBuilder() + /// ..add('foo') + /// ..add('foo--is-active', state.isActive) + /// ..add('foo--is-disabled', state.isDisabled); + /// + /// return (Dom.div() + /// ..addProps(copyUnconsumedDomProps()) + /// ..className = classes.toClassName() + /// )(props.children); + /// } + /// + /// > Related: [blacklist] + void add(String className, [bool shouldAdd = true]) { + if (!shouldAdd || className == null || className == '') { return; } @@ -102,12 +127,16 @@ class ClassNameBuilder { _classNamesBuffer.write(className); } - /// Adds all of the CSS classes represented by [className] (a space-delimited list) to the blacklist, - /// IF [should] is true, otherwise, does nothing (convenience for helping to inline blacklisting conditionals). + /// Blacklists all of the CSS classes represented by a space-delimited list of [className]s + /// if [shouldBlacklist] is `true`. /// /// Classes added to the blacklist will not appear in the result of [toClassName]. - void blacklist(String className, [bool should = true]) { - if (!should || className == null || className == '') { + /// + /// Is a noop if [shouldBlacklist] is `false`, [className] is `null` or [className] is an empty string. + /// + /// > Related: [add] + void blacklist(String className, [bool shouldBlacklist = true]) { + if (!shouldBlacklist || className == null || className == '') { return; } @@ -121,9 +150,27 @@ class ClassNameBuilder { _blacklistBuffer.write(className); } - /// Returns a String representation of the built className, which includes any added classes, and none of the blacklisted classes. + /// Returns a String representation of the built className, which includes any added classes, + /// and none of the blacklisted classes. /// - /// Duplicate classes will be added. + /// Does not check for / remove duplicate CSS classes. + /// + /// __Necessary to convert a `ClassNameBuilder` instance into a valid [CssClassPropsMixin.className] value:__ + /// + /// @override + /// render() { + /// var classes = forwardingClassNameBuilder() + /// ..add('foo') + /// ..add('foo--is-active', state.isActive) + /// ..add('foo--is-disabled', state.isDisabled); + /// + /// return (Dom.div() + /// ..addProps(copyUnconsumedDomProps()) + /// ..className = classes.toClassName() + /// )(props.children); + /// } + /// + /// > Related: [toClassNameBlacklist] String toClassName() { String className = _classNamesBuffer.toString(); @@ -131,27 +178,42 @@ class ClassNameBuilder { List blacklistedClasses = splitSpaceDelimitedString(_blacklistBuffer.toString()); className = splitSpaceDelimitedString(className) - .where((String cssClass) => !blacklistedClasses.contains(cssClass)) - .join(' '); + .where((String cssClass) => !blacklistedClasses.contains(cssClass)) + .join(' '); } return className; } /// Returns a String representation of only the blacklisted classes. - /// Useful for blacklist forwarding. /// - /// Duplicate classes will be added. + /// Does not check for / remove duplicate CSS classes. + /// + /// __Useful for blacklist forwarding:__ + /// + /// @override + /// render() { + /// var classes = forwardingClassNameBuilder() + /// ..blacklist('some-class-found-in-the-forwarding-builder', state.becauseReasons); + /// + /// return (NestedComponent() + /// ..addProps(copyUnconsumedProps()) + /// ..className = classes.toClassName() + /// ..classNameBlacklist = classes.toClassNameBlacklist() + /// )(props.children); + /// } + /// + /// > Related: [toClassName] String toClassNameBlacklist() { return _blacklistBuffer == null || _blacklistBuffer.isEmpty - ? null - : _blacklistBuffer.toString(); + ? null + : _blacklistBuffer.toString(); } - /// Returns a Map with the [CssClassProps.className] and [CssClassProps.classNameBlackList] props + /// Returns a Map with the [CssClassPropsMixin.className] and [CssClassPropsMixin.classNameBlacklist] props /// populated from the return values of [toClassName] and [toClassNameBlacklist], respectively. /// - /// This method, along with [addFromProps], is useful for merging sets of className/blacklist props. + /// > This method, along with [addFromProps], are useful for merging sets of className/blacklist props. Map toProps() { return new CssClassPropsMapView({}) ..className = toClassName() @@ -164,13 +226,13 @@ class ClassNameBuilder { } } -/// Returns a List of space-delimited tokens efficiently split from the specified string. +/// Returns a List of space-delimited tokens efficiently split from the specified [string]. /// -/// Useful for splitting CSS class name strings into class tokens, or `data-test-id` values into individual test IDs. +/// Useful for splitting CSS className strings into class tokens, or `data-test-id` values into individual test IDs. /// /// Handles leading and trailing spaces, as well as token separated by multiple spaces. /// -/// Example: +/// __Example:__ /// /// splitSpaceDelimitedString(' foo bar baz') // ['foo', 'bar', 'baz'] List splitSpaceDelimitedString(String string) { diff --git a/lib/src/util/css_value_util.dart b/lib/src/util/css_value_util.dart index d6e1b04d22..74967a2222 100644 --- a/lib/src/util/css_value_util.dart +++ b/lib/src/util/css_value_util.dart @@ -16,7 +16,8 @@ library over_react.css_value_util; import 'package:quiver/core.dart'; -/// A CSS length value, with a number and unit component, for use in CSS properties such as `width`, `top`, `padding`, etc. +/// A CSS length value, with a number and unit component, +/// for use in CSS properties such as `width`, `top`, `padding`, etc. class CssValue implements Comparable { /// The number component of this CSS value. /// @@ -28,14 +29,20 @@ class CssValue implements Comparable { /// E.g., 'px' for '1px' final String unit; - /// Creates a new [CssValue]. If no [unit] is specified, `'px'` is used instead. + /// Creates a new [CssValue]. + /// + /// If no [unit] is specified, `'px'` is used instead. const CssValue(this.number, [this.unit = 'px']); /// Parse [source] and return its [CssValue] representation. /// - /// Accepts a number optionally followed by a CSS length unit. If no unit is present, `'px'` is used as the unit instead. + /// Accepts a number optionally followed by a CSS length unit. + /// If no unit is present, `'px'` is used as the unit instead. /// - /// If `source` is not a valid CSS value, the [onError] callback is called with [source] and an error object, and its return value is used instead. If no `onError` is provided, `null` is returned. + /// If `source` is not a valid CSS value, the [onError] callback + /// is called with [source] and an error object, and its return + /// value is used instead. If no `onError` is provided, `null` + /// is returned. /// /// Examples of accepted values: /// diff --git a/lib/src/util/dom_util.dart b/lib/src/util/dom_util.dart index f77d40ad0c..340e60b58a 100644 --- a/lib/src/util/dom_util.dart +++ b/lib/src/util/dom_util.dart @@ -38,7 +38,7 @@ Iterable _hierarchy(Element element) sync* { } /// Returns the closest element in the hierarchy of [lowerBound] up to an optional [upperBound] (both inclusive) -/// that matches [selector], or `null if no matches are found. +/// that matches [selector], or `null` if no matches are found. Element closest(Element lowerBound, String selector, {Element upperBound}) { for (var element in _hierarchy(lowerBound)) { if (element.matches(selector)) return element; @@ -48,7 +48,8 @@ Element closest(Element lowerBound, String selector, {Element upperBound}) { return null; } -/// Returns the currently focused element, or `null` if there is none. +/// Returns the currently focused element ([HtmlDocument.activeElement]), +/// or `null` if nothing is focused (e.g. [HtmlDocument.activeElement] is [BodyElement]). Element getActiveElement() { var activeElement = document.activeElement; @@ -62,8 +63,6 @@ Element getActiveElement() { /// Necessary because of the circular inheritance hierarchy in Dart's [InputElement] class structure. /// /// See: -/// -/// Related: [isTextInputElementBase] const List inputTypesWithSelectionRangeSupport = const [ 'search', 'text', diff --git a/lib/src/util/event_helpers.dart b/lib/src/util/event_helpers.dart index c82e8e6852..e2b131466f 100644 --- a/lib/src/util/event_helpers.dart +++ b/lib/src/util/event_helpers.dart @@ -16,13 +16,13 @@ library over_react.event_helpers; import 'dart:html'; -import 'package:react/react.dart' as react; +import 'package:over_react/over_react.dart'; -/// Helper util that wraps a native [KeyboardEvent] in a [react.SyntheticKeyboardEvent]. +/// Helper util that wraps a native [KeyboardEvent] in a [SyntheticKeyboardEvent]. /// -/// Used where a native [KeyboardEvent] is given and a [react.SyntheticKeyboardEvent] is needed. -react.SyntheticKeyboardEvent wrapNativeKeyboardEvent(KeyboardEvent nativeKeyboardEvent) { - return new react.SyntheticKeyboardEvent( +/// Used where a native [KeyboardEvent] is given and a [SyntheticKeyboardEvent] is needed. +SyntheticKeyboardEvent wrapNativeKeyboardEvent(KeyboardEvent nativeKeyboardEvent) { + return new SyntheticKeyboardEvent( nativeKeyboardEvent.bubbles, nativeKeyboardEvent.cancelable, nativeKeyboardEvent.currentTarget, @@ -48,11 +48,11 @@ react.SyntheticKeyboardEvent wrapNativeKeyboardEvent(KeyboardEvent nativeKeyboar nativeKeyboardEvent.shiftKey); } -/// Helper util that wraps a native [MouseEvent] in a [react.MouseEvent]. +/// Helper util that wraps a native [MouseEvent] in a [SyntheticMouseEvent]. /// -/// Used where a native [MouseEvent] is given and a [react.MouseEvent] is needed. -react.SyntheticMouseEvent wrapNativeMouseEvent(MouseEvent nativeMouseEvent) { - return new react.SyntheticMouseEvent( +/// Used where a native [MouseEvent] is given and a [SyntheticMouseEvent] is needed. +SyntheticMouseEvent wrapNativeMouseEvent(MouseEvent nativeMouseEvent) { + return new SyntheticMouseEvent( nativeMouseEvent.bubbles, nativeMouseEvent.cancelable, nativeMouseEvent.currentTarget, @@ -83,12 +83,12 @@ react.SyntheticMouseEvent wrapNativeMouseEvent(MouseEvent nativeMouseEvent) { } /// If the consumer specifies a callback like `onChange` on one of our custom form components that are not *actually* -/// form elements - we still need a valid [react.SyntheticFormEvent] to pass as the expected parameter to that callback. +/// form elements - we still need a valid [SyntheticFormEvent] to pass as the expected parameter to that callback. /// -/// This helper method generates a "fake" [react.SyntheticFormEvent], with nothing but the `target` set to [element], +/// This helper method generates a "fake" [SyntheticFormEvent], with nothing but the `target` set to [element], /// `type` set to [type] and `timeStamp` set to the current time. All other arguments are `noop`, `false` or `null`. -react.SyntheticFormEvent fakeSyntheticFormEvent(Element element, String type) { - return new react.SyntheticFormEvent( +SyntheticFormEvent fakeSyntheticFormEvent(Element element, String type) { + return new SyntheticFormEvent( false, false, element, diff --git a/lib/src/util/key_constants.dart b/lib/src/util/key_constants.dart index 310f1f7bc3..a6c18384f8 100644 --- a/lib/src/util/key_constants.dart +++ b/lib/src/util/key_constants.dart @@ -14,9 +14,11 @@ library key_constants; -/// Key values that are returned from [react.SyntheticKeyboardEvent.key]. +import 'package:over_react/over_react.dart'; + +/// Key values that are returned from [SyntheticKeyboardEvent.key]. /// -///See: . +/// > See: . abstract class KeyValue { static const String BACKSPACE = 'Backspace'; static const String TAB = 'Tab'; diff --git a/lib/src/util/map_util.dart b/lib/src/util/map_util.dart index 583b372364..7bf6c62236 100644 --- a/lib/src/util/map_util.dart +++ b/lib/src/util/map_util.dart @@ -20,11 +20,18 @@ import 'package:over_react/src/component_declaration/transformer_helpers.dart'; import 'package:over_react/src/component/dom_components.dart'; import 'package:over_react/src/component/prop_mixins.dart'; -/// Returns a copy of the specified props map, omitting reserved React props by default, -/// in addition to any specified keys. +/// Returns a copy of the specified [props] map, omitting reserved React props by default, +/// in addition to any specified [keysToOmit] or [keySetsToOmit]. +/// +/// If [onlyCopyDomProps] is `true`, only the keys found within [DomPropsMixin] and [SvgPropsMixin] will be forwarded. /// /// Useful for prop forwarding. -Map getPropsToForward(Map props, {bool omitReactProps: true, bool onlyCopyDomProps: false, Iterable keysToOmit, Iterable keySetsToOmit}) { +Map getPropsToForward(Map props, { + bool omitReactProps: true, + bool onlyCopyDomProps: false, + Iterable keysToOmit, + Iterable keySetsToOmit +}) { Map propsToForward = new Map.from(props); if (omitReactProps) { @@ -61,14 +68,14 @@ Map getPropsToForward(Map props, {bool omitReactProps: true, bool onlyCopyDomPro return propsToForward; } -/// Returns a copy of the style map found in [props]. +/// Returns a copy of the [DomPropsMixin.style] map found in [props]. /// -/// Returns an empty map if [props] or its style map are null. +/// Returns an empty map if [props] or its style map are `null`. Map newStyleFromProps(Map props) { - if (props == null) return {}; + if (props == null) return {}; var existingStyle = domProps(props).style; - return existingStyle == null ? {} : new Map.from(existingStyle); + return existingStyle == null ? {} : new Map.from(existingStyle); } SplayTreeSet _validDomProps = new SplayTreeSet() diff --git a/lib/src/util/pretty_print.dart b/lib/src/util/pretty_print.dart index 7cfd56dbf1..a93caf3814 100644 --- a/lib/src/util/pretty_print.dart +++ b/lib/src/util/pretty_print.dart @@ -14,6 +14,8 @@ library over_react.pretty_print; +import 'package:over_react/over_react.dart'; + /// Returns a pretty-printed version of [map], with namespaced keys grouped together. /// /// Useful for debugging props/state maps (and build in to [UiProps.toString]/[UiState.toString]). diff --git a/lib/src/util/prop_errors.dart b/lib/src/util/prop_errors.dart index 15bd2921dd..f9fbe799db 100644 --- a/lib/src/util/prop_errors.dart +++ b/lib/src/util/prop_errors.dart @@ -14,7 +14,9 @@ library over_react.prop_errors; -/// Error thrown dues to a prop being set incorrectly. +import 'package:over_react/over_react.dart'; + +/// Errors thrown due to a value within [UiComponent.props] being set incorrectly. class PropError extends Error { static const String defaultPrefix = 'PropError: '; static const String requiredPrefix = 'RequiredPropError: '; @@ -27,13 +29,15 @@ class PropError extends Error { final String prop2Name; final message; - /// Create a new [PropError], with the given [propName] and [message]. + /// Create a new [PropError], with the given [propName] and optional [message]. PropError(this.propName, [this.message = '']) : invalidValue = null, prop2Name = null, _messagePrefix = defaultPrefix; /// Create a new [PropError] that signifies the given [propName] is required to be set. + /// + /// > See: [requiredProp] annotation PropError.required(this.propName, [this.message = '']) : invalidValue = null, prop2Name = null, diff --git a/lib/src/util/prop_key_util.dart b/lib/src/util/prop_key_util.dart index fde65d5ae4..6ec34377ba 100644 --- a/lib/src/util/prop_key_util.dart +++ b/lib/src/util/prop_key_util.dart @@ -18,7 +18,7 @@ import 'dart:collection'; /// Returns the string key of the [factory] prop accessed in [accessProp]. /// -/// Example usage: +/// __Example:__ /// /// var valuePropKey = getPropKey((props) => props.value, TextInput); String getPropKey(void accessProp(Map keySpy), Map factory(Map props)) { @@ -35,7 +35,7 @@ dynamic _getKey(void accessKey(Map keySpy)) { return keySpy.key; } -/// Helper class that stores the key accessed while getting a value of a map. +/// Helper class that stores the key accessed while getting a value within a Map. class _SingleKeyAccessMapSpy extends MapView { _SingleKeyAccessMapSpy(Map map) : super(map); diff --git a/lib/src/util/react_wrappers.dart b/lib/src/util/react_wrappers.dart index 3618fdd5e6..0dccd5ba04 100644 --- a/lib/src/util/react_wrappers.dart +++ b/lib/src/util/react_wrappers.dart @@ -19,6 +19,7 @@ import 'dart:collection'; import 'dart:html'; import 'package:js/js.dart'; +import 'package:over_react/over_react.dart'; import 'package:over_react/src/component_declaration/component_type_checking.dart'; import 'package:react/react.dart' as react; import 'package:react/react_client.dart'; @@ -49,22 +50,18 @@ ReactDartComponentInternal _getInternal(/* ReactElement|ReactComponent */ insta /// Returns the internal representation of a Dart component's props as maintained by react-dart. /// -/// Similar to ReactElement.props in JS, but also includes `children`. +/// Similar to `ReactElement.props` in JS, but also includes `props.children`. Map _getExtendedProps(/* ReactElement|ReactComponent */ instance) { return _getInternal(instance).props; } -/// Returns 'key' associated with the specified React instance. -dynamic getInstanceKey(ReactElement instance) { - return instance.key; -} +/// Returns the [ReactElement.key] associated with the specified [instance]. +dynamic getInstanceKey(ReactElement instance) => instance.key; -/// Returns 'ref' associated with the specified React instance. -dynamic getInstanceRef(ReactElement instance) { - return instance.ref; -} +/// Returns the [ReactElement.ref] associated with the specified [instance]. +dynamic getInstanceRef(ReactElement instance) => instance.ref; -/// Returns whether a component is a native Dart component (react-dart [ReactElement] or [ReactComponent]). +/// Returns whether an [instance] is a native Dart component (react-dart [ReactElement] or [ReactComponent]). bool isDartComponent(/* [1] */ instance) { // Don't try to access internal on a DOM component if (instance is Element) { @@ -120,7 +117,7 @@ final bool _canUseExpandoOnReactElement = (() { return true; })(); -/// A cache of props for a given [ReactElement]. +/// A cache of [UiComponent.props] for a given [ReactElement]. /// /// If caching isn't possible due to [_canUseExpandoOnReactElement] being false, /// then this will be initialized to `null`, and caching will be disabled. @@ -211,15 +208,14 @@ bool _isCompositeComponent(dynamic object) { } /// Returns a new JS map with the specified props and children changes, properly prepared for consumption by -/// React JS methods such as cloneWithProps(), setProps(), and other methods that accept changesets of props to be +/// React JS methods such as `cloneElement`, `setProps`, and other methods that accept changesets of props to be /// merged into existing props. /// /// Handles both Dart and JS React components, returning the appropriate props structure for each type: /// /// * For Dart components, existing props are read from [InteropProps.internal], which are then merged with /// the new [newProps] and saved in a new [InteropProps] with the expected [ReactDartComponentInternal] structure. -/// Children are likewise copied/overwritten as expected. -/// +/// * Children are likewise copied and potentially overwritten with [newChildren] as expected. /// * For JS components, a copy of [newProps] is returned, since React will merge the props without any special handling. dynamic preparePropsChangeset(ReactElement element, Map newProps, [Iterable newChildren]) { var propsChangeset; @@ -277,7 +273,8 @@ ReactElement cloneElement(ReactElement element, [Map props, Iterable children]) } } -/// Returns the native Dart component associated with a React JS component instance, or null if the component is not Dart-based. +/// Returns the native Dart [ReactDartComponentInternal.component] associated with a [ReactComponent] +/// [instance], or `null` if the component is not Dart-based _(an [Element] or a JS composite component)_. react.Component getDartComponent(/* [1] */ instance) { if (instance is Element) { return null; @@ -286,12 +283,13 @@ react.Component getDartComponent(/* [1] */ instance) { return _getInternal(instance)?.component; } -/// A function that, when supplied as the `ref` prop, is called with the component instance +/// A function that, when supplied as [ReactPropsMixin.ref], is called with the component instance /// as soon as it is mounted. /// /// This instance can be used to retrieve a component's DOM node or to call a component's public API methods. /// /// The component instance will be of the type: +/// /// * [react.Component] for Dart components /// * [ReactComponent] for JS composite components /// * [Element] for DOM components @@ -313,9 +311,10 @@ react.Component getDartComponent(/* [1] */ instance) { /// See: . typedef CallbackRef(ref); -/// Returns a function that chains [element]'s callback ref (if one exists) with [newCallbackRef]. +/// Returns a function that chains the callback ref of the provided [element] _(if one exists)_ +/// using [newCallbackRef]. /// -/// Throws [ArgumentError] if [element.ref] is a `String` ref or otherwise not a [CallbackRef]. +/// > Throws an [ArgumentError] if [ReactElement.ref] is a `String` ref or otherwise not a [CallbackRef]. /// /// TODO: This method makes assumptions about how react-dart does callback refs for dart components, so this method should be moved there (UIP-1118). CallbackRef chainRef(ReactElement element, CallbackRef newCallbackRef) { diff --git a/lib/src/util/rem_util.dart b/lib/src/util/rem_util.dart index 10dfd8ba0f..bd094369f7 100644 --- a/lib/src/util/rem_util.dart +++ b/lib/src/util/rem_util.dart @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// Utilities for working with CSS `rem` units and detecting changes to the root font size. +/// Utilities for working with CSS `rem` units and detecting changes to the font size +/// of the [HtmlDocument]. library over_react.rem_util; import 'dart:async'; @@ -74,7 +75,9 @@ double get rootFontSize => _rootFontSize; /// Stream data is the latest value, in pixels. final Stream onRemChange = _remChange.stream; -/// Forces re-computation of the root font size. Not necessary when using [onRemChange]. +/// Forces re-computation of the font size of the [HtmlDocument]. +/// +/// Not necessary when using [onRemChange]. void recomputeRootFontSize() { var latestRootFontSize = _computeRootFontSize(); @@ -84,7 +87,8 @@ void recomputeRootFontSize() { } } -/// Converts a pixel (`px`) [value] to its `rem` equivalent using the current root font size. +/// Converts a pixel (`px`) [value] to its `rem` equivalent using the current font size +/// found on the [HtmlDocument]. /// /// * If [value] is a [String] or [CssValue]: /// * And [value] already has the correct unit, it will not be converted. @@ -93,18 +97,16 @@ void recomputeRootFontSize() { /// * If [value] is a [num], it will be treated as a `px` and converted, unless [treatNumAsRem] is `true`. /// * If [value] is `null`, `null` will be returned. /// -/// Example input: -/// -/// * `'15px'` -/// * `new CssValue(15, 'px')` -/// * `15` -/// * `1.5, treatNumAsRem: true` -/// * `'1.5rem'` -/// * `new CssValue(1.5, 'rem')` +/// Examples _(all will output `1.5rem` assuming `1rem == 10px`)_: /// -/// Example output (assuming 1rem = 10px): +/// toRem('15px'); +/// toRem(new CssValue(15, 'px')); +/// toRem(15); +/// toRem(1.5, treatNumAsRem: true); +/// toRem('1.5rem'); +/// new CssValue(1.5, 'rem'); /// -/// * `1.5rem` +/// > Related: [toPx] CssValue toRem(dynamic value, {bool treatNumAsRem: false, bool passThroughUnsupportedUnits: false}) { if (value == null) return null; @@ -129,7 +131,8 @@ CssValue toRem(dynamic value, {bool treatNumAsRem: false, bool passThroughUnsupp return new CssValue(remValueNum, 'rem'); } -/// Converts a rem [value] to its pixel (`px`) equivalent using the current root font size. +/// Converts a rem [value] to its pixel (`px`) equivalent using the current font size +/// found on the [HtmlDocument]. /// /// * If [value] is a [String] or [CssValue]: /// * And [value] already has the correct unit, it will not be converted. @@ -138,18 +141,16 @@ CssValue toRem(dynamic value, {bool treatNumAsRem: false, bool passThroughUnsupp /// * If [value] is a [num], it will be treated as a `rem` and converted, unless [treatNumAsPx] is `true`. /// * If [value] is `null`, `null` will be returned. /// -/// Example input: -/// -/// * `'1.5rem'` -/// * `new CssValue(1.5, 'rem')` -/// * `1.5` -/// * `15, treatNumAsPx: true` -/// * `15px` -/// * `new CssValue(15, 'px')` +/// Examples _(all will output `15px` assuming `1rem == 10px`)_: /// -/// Example output (assuming 1rem = 10px): +/// toPx('1.5rem'); +/// toPx(new CssValue(1.5, 'rem')); +/// toPx(1.5); +/// toPx(15, treatNumAsPx: true); +/// toPx(15px); +/// toPx(new CssValue(15, 'px')); /// -/// * `15px` +/// > Related: [toRem] CssValue toPx(dynamic value, {bool treatNumAsPx: false, bool passThroughUnsupportedUnits: false}) { if (value == null) return null; diff --git a/lib/src/util/string_util.dart b/lib/src/util/string_util.dart index cb104e0e15..bfae4c42f3 100644 --- a/lib/src/util/string_util.dart +++ b/lib/src/util/string_util.dart @@ -14,12 +14,14 @@ library over_react.string_util; -/// Allows the use of `'''` string blocks, without having to unindent them when used within something like the -/// [markdown] method. +/// Allows the use of `'''` string blocks, without having to unindent them when used within +/// something like markdown's +/// [markdownToHtml](https://www.dartdocs.org/documentation/markdown/latest/markdown/markdownToHtml.html) function. /// /// __Replace this:__ +/// /// (Component() -/// ..description = markdown( +/// ..description = markdownToHtml( /// ''' /// Yuck... I'm indented all funky. /// ''' @@ -27,8 +29,9 @@ library over_react.string_util; /// )() /// /// __With this:__ +/// /// (Component() -/// ..description = markdown(unindent( +/// ..description = markdownToHtml(unindent( /// ''' /// Proper indentation is yummy... /// '''