RFC: Add view layout compiler#10269
Conversation
014dfcb to
2d959b8
Compare
e823ae1 to
798c003
Compare
On the ViewLayoutItem class:
|
|
If the intention is to be able to pass the descriptor to |
|
JSON or a chained builder would be nicer than class instances import { layout as l } from ...
l.view(new OrthographicView({id: 'sidebar', controller: false}))
l.column([])
l.row([])
l.overlay() |
d460b77 to
4bf7668
Compare
👍 Technically, it is not an issue, JSON uses
|
|
|
4bf7668 to
6aa1503
Compare
I was able to get codex to split this into stacked PRs. |
6aa1503 to
c5c3f5c
Compare
Fair enough, the JSON looks pretty reasonable |
chrisgervang
left a comment
There was a problem hiding this comment.
Seems like a useful feature in-line with summit attendee requests to have more JSON/declarative APIs, and clearly adds value to multi-view applications.
See my comments about where this lives.. I think the json module would make a nicer home for this.
| }; | ||
|
|
||
| function parseViewLayout(root: ViewLayout): ManagedViewLayout[] { | ||
| function parseViewLayout(root: SplitterWidgetViewLayout): ManagedViewLayout[] { |
There was a problem hiding this comment.
Is there overlap between this parser implementation and the extracted one? I think this PR's use case is missing for me.. is this PR adding a function to help me implement a widget, or is it a utility to use by an application to fill the top-level views prop?
I think at the root of this is a question of discoverability.. is the widgets module where I'd look for a view builder function?
We don't really have a good module for this.. a @deck.gl/views or /utils would be more intuitive, though I don't think this change alone warrants the addition of a new module.
/extensions has meant layer extensions up until now, but we could call this is a view extension of sorts..
I'll take a closer look at your examples and maybe that'll clear the use case up for me
There was a problem hiding this comment.
See comment in the examples PR.. my preference is to put the ViewLayout compiler in @deck.gl/json.. it seems like the natural home for a JSON utility like this.
What do you think?
There was a problem hiding this comment.
my preference is to put the ViewLayout compiler in @deck.gl/json
As I thought about this, it struck me that one problem is dependency chains. If we have the widgets module using the types exported here, then we get a dependency from widgets on the json or experimental modules, which seems undesirable.
FWIW, This was not created as something JSON specific. I developed this for a real use case, a big non-geospatial application that composes a lot of views (headersm legends, overviews, separate timelines etc, and the views can be reconfigured by the user. Changing those views around with offsets and heights etc was a pain, and this system makes it effortless.
I personally think we could make advanced view support a "tentpole" of the 9.4 release:
- Multicanvas Views, this dynamic View Layout system, GlobeView graduation (tons of improvements there) and a bunch of extra things in the view tracker.
- The JSON/pydeck bindings and the new widgets would just be icing on that cake.
I think landing it in the widgets module for now would not be unreasonable, then we have a bit more time to consider how to make this work with multi-canvas views and maybe other improvements to the views we want to make.
But if the temperature is lukewarm, I can always land it in community instead.
There was a problem hiding this comment.
No, I think that'd be a very compelling theme for 9.4 and this adds of value towards it.
We can always move where this lives up until 9.4 is released.
@Pessimistress I read your feedback around this being placed outside of core because it's self-contained, but I'm starting to see this as a branch that leaf modules are depending on in JSON and widgets
We could even consider this for a core API change: deck.setProps({ views: ViewLayout | ... })
Curious to get more perspective on how you're seeing it fit in
|
@Pessimistress asked for a comparison between the view layout system in the existing splitter widget The PR description has been updated with the syntax discussion |
|
I like the direction a lot, and the following are feature requests / design details:
|
Yes, I asked Codex to do this, let's see how it looks.
Not a strong objection... I considered splitter nodes, but leaning away from them for now.
|
|
PR description is updated to reflect the current direction and with a section on the proposed syntax and how it compares with the 9.3 SplitterWidget's view props syntaz. |
| * @param props - Resolved props for the compiled view. | ||
| * @returns Fresh deck view instance with resolved numeric bounds. | ||
| */ | ||
| function instantiateView(view: View, props: Record<string, unknown>): View { |
There was a problem hiding this comment.
There is already a view.clone method.
| x: resolvedRect.x, | ||
| y: resolvedRect.y, | ||
| width: resolvedRect.width, | ||
| height: resolvedRect.height |
There was a problem hiding this comment.
Any plan to support padding? The current resolution of relative padding in core is super awkward, as they are relative to the whole canvas instead of each view, so I have to adjust the padding along with width/height if I have a splitter.
|
|
||
| Raw deck.gl `View` instances are leaf nodes in `children`. Put layout-only `width`, `height`, `x`, and `y` props directly on the `View` when a leaf needs fixed sizing or overlay positioning. | ||
|
|
||
| For split layouts, `ViewLayout` also accepts the `SplitterWidgetViewLayout`-style aliases `orientation: 'horizontal' | 'vertical'` and `views`. A horizontal orientation is equivalent to `type: 'row'`; a vertical orientation is equivalent to `type: 'column'`. |
There was a problem hiding this comment.
I don't think that's necessary... We just need a helper inside SplitterWidget to convert the old format to the new one.
| export type SplitterWidgetProps<ViewsT extends View[] = View[]> = WidgetProps & { | ||
| /** Stacking views descriptor */ | ||
| viewLayout: ViewLayout; | ||
| viewLayout: SplitterWidgetViewLayout; |
There was a problem hiding this comment.
I would personally prefer not to. It is a more complex layout system not focused on widgets.
I would keep this SplitterWidget.views props as compatibility only for now and if we can't find a better way to integrate widgets with views we can always add it later.
Summary
Adds the declarative view layout compiler and public types to
@deck.gl/widgetsDeck.props.views) when audited and stamped.Changes
buildViewsFromViewLayout, including view reuse, length parsing, split metadata, andviewPropsByIdbounds overrides.@deck.gl/widgetsanddeck.gl.View Layout Syntax Audit
We do have a point of reference in existing 9.3 splitter widget which provides a minimal layout syntax for its
viewspropThe closest change would be to let the new compiler accept a split-container shape that mirrors
<item>.orientation<item>.layout<item>.orientation: horizontal<item>.layout: row<item>.layout: 'horizontal'<item>: verticallayout: columnSplitterWidgetProps.views<item>.childrenchildrencan be layout items not just viewsSplitterWidgetViewLayout:
This would map internally to the proposed:
How to align?
Use views instead of children for row, column, and overlay.
Split containers use orientation.
ViewLayout Compared To CSS
CSS is a useful benchmark for whether the
ViewLayoutAPI feels obvious. The current API maps most closely to a constrained subset of Flexbox plus absolute-positioned overlays.display: flex; flex-direction: row/columnororientation`width/heightminPixels/maxPixelsposition: absoluteinside parentoverlay+ childx/y/width/heightpaddinginsetpaddinggapflex-grow/frunitsminmax()/clamp()width: '50%'+minPixels/maxPixelssubgridviewPropsById/ overlay offsetssplitId+splittersByIdThe biggest CSS-like gaps are:
No
gapSpacer works, but it is verbose. A
gap: 8prop on row/column would feel natural and map directly to CSS flex/grid.No flex weights
Today unspecified children divide remaining space equally. CSS users may expect something like
flex: 2orweight: 2.Axis-dependent
minPixels/maxPixelsThis is pragmatic, but CSS would likely spell this as
minWidth/maxWidthandminHeight/maxHeight, orminSize/maxSizefor stack-axis sizing.No named grid/areas
If the API wants to compete with CSS Grid, it would need named cells or areas. That may be too much for the current PR.
Generated split ids are less CSS-like than line names
CSS Grid has named lines. A closer model might be
splitIds: ['sidebar-main', 'main-inspector']for multi-child splits. Generated ids are simpler, but less authored and less semantic.Suggested docs language:
For future CSS-inspired API additions, the highest-value options are
gapandflex/weight.CSS
gridCSS grids could be nice, to make a number of views for different cities etc. For “N city views” the current row/column API gets awkward because you either manually nest rows/columns or generate a tree. A grid layout would be more natural:
Stacked PRs
The Follow-up "PoC" PR adds a number experimental widgets, website example, playground JSON sample, and widget docs, this is mainly for exposition at the moment, to show the system working and things that could be built by users.