Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 35 additions & 6 deletions docs/api-reference/widgets/stats-widget.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,41 @@ const deck = new Deck({

The `StatsWidget` accepts the generic [`WidgetProps`](../core/widget.md#widgetprops) and:

- `type` (string, default `'deck'`) - Type of stats to display: `'deck'`, `'luma'`, `'device'`, or `'custom'`
- `stats` (Stats, optional) - Custom stats object when using `type: 'custom'`
- `title` (string, default `'Stats'`) - Title shown in the widget header
- `framesPerUpdate` (number, default `1`) - Number of frames to wait between updates
- `formatters` (object, default `{}`) - Custom formatters for stat values
- `resetOnUpdate` (object, default `{}`) - Whether to reset particular stats after each update
#### type (string, optional)

Type of stats to display. One of `'deck'`, `'luma'`, `'device'`, or `'custom'`.

* Default: `'deck'`

#### stats (Stats, optional)

A [Stats](https://visgl.github.io/probe.gl/docs/modules/stats) instance to display when using `type: 'custom'`.

#### title (string, optional)

Title shown in the widget header.

* Default: `'Stats'`

#### defaultIsExpanded (boolean, optional)

If `true`, the UI is expanded at start.

* Default: `false`

#### framesPerUpdate (number, optional)

Number of frames to wait between refresh.

* Default: `1`

#### formatters (object, optional)

Custom formatters for stat values.

#### resetOnUpdate (object, optional)

Whether to reset particular stats after each update.

### Built-in Formatters

Expand Down
14 changes: 10 additions & 4 deletions modules/widgets/src/stats-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ import {luma} from '@luma.gl/core';
import {render} from 'preact';
import type {Stats, Stat} from '@probe.gl/stats';

const RIGHT_ARROW = '\u25b6';
const DOWN_ARROW = '\u2b07';

const DEFAULT_COUNT_FORMATTER = (stat: Stat): string => `${stat.name}: ${stat.count}`;

function formatTime(time: number): string {
Expand All @@ -36,6 +33,10 @@ export type StatsWidgetProps = WidgetProps & {
viewId?: string | null;
/** Type of stats to display. */
type?: 'deck' | 'luma' | 'device' | 'custom';
/** Expand the stats UI by default.
* @default false
*/
defaultIsExpanded?: boolean;
/** Stats object to visualize. */
stats?: Stats;
/** Title shown in the header of the pop-up. Defaults to stats.id. */
Expand All @@ -55,6 +56,7 @@ export class StatsWidget extends Widget<StatsWidgetProps> {
type: 'deck',
placement: 'top-left',
viewId: null,
defaultIsExpanded: false,
stats: undefined!,
title: 'Stats',
framesPerUpdate: 1,
Expand All @@ -75,6 +77,7 @@ export class StatsWidget extends Widget<StatsWidgetProps> {
super(props);
this._formatters = {...DEFAULT_FORMATTERS};
this._resetOnUpdate = {...this.props.resetOnUpdate};
this.collapsed = !props.defaultIsExpanded;
this.setProps(props);
}

Expand Down Expand Up @@ -127,7 +130,10 @@ export class StatsWidget extends Widget<StatsWidgetProps> {
style={{cursor: 'pointer', pointerEvents: 'auto'}}
onClick={this._toggleCollapsed}
>
{collapsed ? RIGHT_ARROW : DOWN_ARROW} {title}
<b>{title}</b>
<button className="deck-widget-dropdown-button">
<span className={`deck-widget-dropdown-icon ${collapsed ? '' : 'open'}`} />
</button>
</div>
{!collapsed && <div className="deck-widget-stats-content">{items}</div>}
</div>,
Expand Down
35 changes: 23 additions & 12 deletions modules/widgets/src/stylesheet.css
Original file line number Diff line number Diff line change
Expand Up @@ -416,33 +416,44 @@

/* Stats styles */
.deck-widget-stats-container {
border-radius: var(--button-corner-radius, 4px);
border-radius: var(--button-corner-radius, 8px);
display: inline-flex;
flex-direction: column;
padding: 4px;
font-size: 0.7rem;
/* Approximately 14px */
line-height: 1.6;
font-family:
'SF Mono',
/* macOS */ 'Menlo',
/* macOS */ 'Consolas',
/* Windows */ 'DejaVu Sans Mono',
/* Linux */ 'Liberation Mono',
/* Linux */ monospace;
background-color: var(--button-background, #fff);
color: var(--button-text, rgb(24, 24, 26));
font-family: monospace;
background-color: var(--menu-background, #fff);
color: var(--menu-text, rgb(24, 24, 26));
box-shadow: var(--menu-shadow, 0px 0px 8px 0px rgba(0, 0, 0, 0.25));
}
.deck-widget-stats-header {
color: var(--button-icon-idle, rgba(97, 97, 102, 1));
padding-left: 8px;
display: flex;
align-items: center;
gap: 4px;
}
.deck-widget-stats-header:hover {
color: var(--button-icon-hover, rgb(24, 24, 26));
}
.deck-widget-stats-header .deck-widget-dropdown-button {
background: none;
border: none;
}
.deck-widget-stats-content {
padding: 4px 8px 8px;
}

/* Popup styles */
.deck-widget.deck-widget-popover {
margin: 0 !important;
box-shadow: var(--menu-shadow, 0px 0px 8px 0px rgba(0, 0, 0, 0.25));
}
.deck-widget-popup-content {
border-radius: var(--button-corner-radius, 8px);
background: var(--menu-background, #fff);
color: var(--menu-text, rgb(24, 24, 26));
box-shadow: var(--menu-shadow, 0px 0px 8px 0px rgba(0, 0, 0, 0.25));
padding: 10px;
}
.deck-widget-popup-content .deck-widget-popup-controls {
Expand Down
Loading