This issue surfaced 📌 Add a route for PATCHing both a config entity and its auto-saved version together Active which I think the rest of the stuff that's here is blocked on until that's resolved.
effulgentsia → created an issue.
Adding important info to the issue title per #7.
wim leers → credited effulgentsia → .
Thanks for testing this, @mayur-sose, and posting what your found!
I believe both of your findings are "works as designed", so I'm setting this back to Fixed.
<!-- xb-region-start-content -->
<!-- xb-region-end-content -->
This is about the content region, which is not a global region. Global regions are all the ones except for the one named "content". The reason it's okay (in fact, desired) for the content region to have those comments, even if otherwise empty, is those comments identify where you would drop something into, and the UI does allow dragging and dropping into the content region, even when the content region is empty, so we need those comments there. The reason this issue removed the comments from the global regions, is that unlike the content region, the UI does not allow dragging and dropping into an empty global region: to put something into an empty global region, you can only do it via the context menu (right click), not with drag-and-drop.
<!-- xb-region-content-end-primary_menu -->
<!-- xb-region-end-primary_menu -->
Here, "content" is in the middle of the name, not the end of the name, so this isn't referring to the content region, but is referring to the content of the primary_menu region (yeah, it's confusing for the word "content" to mean different things in different contexts). So what this is saying is that the primary_menu region ends immediately after the content of that region ends. In other words, the primary_region doesn't have any wrapper markup around its content. That's perfectly normal.
<!-- xb-region-end-primary_menu -->
<!-- xb-region-start-secondary_menu -->
This is saying that the secondary_menu region starts immediately after the primary_menu region ends. Also perfectly normal.
So, all of the above cases are fine and expected, but great that you called them out so that we double checked to make sure. The ones we want to make sure aren't happening are:
<!-- xb-region-start-ANYTHING_OTHER_THAN_"content" -->
<!-- xb-region-end-ANYTHING_OTHER_THAN_"content" -->
or
<!-- xb-region-content-start-ANYTHING_OTHER_THAN_"content" -->
<!-- xb-region-content-end-ANYTHING_OTHER_THAN_"content" -->
If you find either of those, please re-open this.
Thanks for the typo fix!
effulgentsia → made their first commit to this issue’s fork.
Changing tag from "sprint" to "spike", because we're not planning on completing this issue this sprint, we're just trying to get a handle on what Claude Code prompted by @grasmash created here.
This landed in the prior sprint, so untagging.
wim leers → credited effulgentsia → .
Did any of the experience builder work introduce a Twig namespace equivalent?
Nope. Sorry to disappoint. XB uses SDCs but does not use namespaced non-SDC Twig files.
For #11.1, you should be able to just do this:
'@/components/': Drupal.url('xb/api/auto-saves/js/js_component/')
And thereby not need a separate import map entry for every component.
I think we need to ensure that we are at least outputting an HTML tag that can have the XB UUID attached so the front end can find something to receive the click/be draggable/etc.
Now that we have 📌 Investigate drag-and-drop solution that removes the need to drop items into the preview iFrame Active , do we really need this? I think what's receiving the click now is a transparent box over the iframe, so we shouldn't need to wrap the bare text that's inside the iframe, or at least I hope we don't have to. It would be great to keep our previews accurate regardless of what CSS people happen to have by not having to insert any wrappers.
I want to make sure we don't forget about #11/#14. Did that make it already into what was merged? If not, is there a follow-up for it?
wim leers → credited effulgentsia → .
wim leers → credited effulgentsia → .
Re #26, I opened ✨ Real-time preview for props changes of JS components Active .
Re #28, this issue still has child issues for CLI tooling, but maybe we should open a new Meta/Plan issue for that and move those to there? Especially since this issue even has "in-browser" in its title :)
Very nice!
wim leers → credited effulgentsia → .
Opera Mini's key feature (not available in Opera Mobile as far as I know) is data compression for low bandwidth connections, which makes its lack of support for avif and responsive images disappointing.
According to https://investor.opera.com/node/9466, Opera Mini has 100 million users, but I don't know if there's any other source that corroborates that.
x-formatting-context: inline won't be possible to support without allowing
s
Wouldn't it be possible to hack around this though? For example, implement a plugin that responds to events (keyUp?, maybe others?) by checking if any <br>
s made their way in, and if so, remove them?
balintbrews → credited effulgentsia → .
enabled but also empty
I think this might be hitting on a general problem we need to figure out what to do about. It's common for Drupal themes to conditionally render wrapper elements (like the <div class="sidebar-grid grid-full">
example above) only if there's content to put into them, and to omit them if the content is empty, and the theme's CSS then is based on that assumption and might not handle the case of the wrapper elements existing with empty content because the HTML "never" exists in that state.
Never, that is, until XB puts an HTML comment there, making it no longer empty as far as Twig is concerned, but making it empty as far as the DOM is concerned.
We can make XB omit the HTML comment identifying the slot in the case where the content is empty, which would then let the Twig conditionals work and the wrapper element not be added, but if we did that, then how would you drag something into that slot?
So there's a conflict here between wanting the preview to be accurate, but also wanting the ability to drag content into an empty slot. I don't have any ideas at the moment for how to solve for both.
This is now incorporated into the MR in 📌 Investigate drag-and-drop solution that removes the need to drop items into the preview iFrame Active .
This is still an important issue to get done, but we started a shorter-than-usual sprint following DrupalCon, and are choosing to prioritize some other issues ahead of this one. We'll pick it up again in an upcoming sprint.
This is still an important issue to get done, but we started a shorter-than-usual sprint following DrupalCon, and are choosing to prioritize some other issues ahead of this one. @larowlan: if you come up with any ideas in the meantime, fantastic! Otherwise, we'll likely pick it up again in an upcoming sprint.
The issue summary now lists 80 of the 110 issues tagged "stable blocker". I still need to go through these 30 → .
Adding another level of hierarchy
wim leers → credited effulgentsia → .
balintbrews → credited effulgentsia → .
Ok, so that makes sense that that's a core bug, but why does that matter to XB's shape matching? What are we doing that varies by what isComputed() returns?
Yes, once we implement dynamic prop sources at all, it should be possible to "link" (the terminology that the UI will use for this) component props to computed fields as well as to computed properties of field items.
I think we need a core issue to flag those comment fields as computed
Oh, is the core bug that it's a computed field but not declared as such (isComputed() returns false)?
The comment_last_name field is computed, so marked that as unsupported (core bug).
What's the core bug? Is "core" referring to Drupal core, or some other meaning of "core"?
I started writing up 🌱 Milestone 1.0.0-beta1: Start creating non-throwaway sites Active . Note that that summary is very much a work in progress. Half the issues there probably don't really need to block a beta and possibly 80% of the stuff that we do want to get into the beta milestone isn't yet on that list. But hey, it's a start. Hopefully it will start resembling a proper roadmap within the next few weeks.
effulgentsia → created an issue.
#32.2 would leave room for also being able to identify the model of the slot distinctly from either the containing component or the slotted component. For example:
name: Table
model: [table]
slots:
rows:
model: [tbody]
slotted:
model: [tr]
Don't know if there's practical use cases for that though.
Other terminology brainstorming...
We could shorten intendedFor
to just for
:
name: "(Table Row)"
is: [tr]
slots:
cells:
for: [td]
Or, if we like the idea of using model
in both places, we could qualify the one for the slot with slotted
:
name: "(Table Row)"
model: [tr]
slots:
cells:
slotted:
model: [td]
I like #29, but I think it's confusing for the same word, model
, to mean something different for a component (what the component is) than for a slot (what the slot is intended to contain).
Personally, I'd suggest renaming it to something like is
at the component level and intendedFor
at the slot level.
I think the keywords within each can also include HTML tags where appropriate. For example:
name: "(Table Row)"
is: [table_row, tr]
slots:
cells:
title: "Row cells"
description: "A sequence of cell components."
intendedFor: [table_cell, td]
The above example might seem redundant, but something like [card, div]
might not be.
Responding to earlier comments, not #29...
It's totally possible for XB to add an extra yml file to SDCs
+1. I moved my proposal, with this suggestion incorporated, into #3513563-12: [later phase] Component slot restrictions ("which?") + limits ("how many?") → .
intendedFor
Love it! I incorporated it into that issue comment.
Traits with conditions I'm not so sure about.
I think we need it to support use cases like #14, because whether a component is wide or narrow, light or dark, often depends on prop values. From an Experience Builder perspective, what this would mean is as long as the component has some prop values that are compatible with the policies, we'd let you put the component into the slot and then restrict the props form to only the policy-compatible values.
A simpler structure
I agree with simplifying how to express the conditions. I incorporated that into #3513563-12: [later phase] Component slot restrictions ("which?") + limits ("how many?") → .
One downside to such a flexible system is we are bordering on violating the concept that everything you need to know about a component is in the directory
The key to #19 /
#3513563-12: [later phase] Component slot restrictions ("which?") + limits ("how many?") →
is that everything that's about the component is still in the SDC's directory. Whereas the policies aren't about individual components, they're about component traits. For example, a policy about contrast ratios or width compatibilities is based purely on comparing the slot's computed traits (its own traits plus ones inherited by ancestors in the layout tree) with the component's computed traits. Even a policy that says "there must be an intersection between a component's is
trait and a slot's intendedFor
trait" isn't about a specific component, just about that general rule.
Here's a proposal that continues the line of thinking in #3514072-19: Define how to handle SDC component filtering in the different display builder UIs (aka. What is possible to add in a SDC slot) → (read that comment for details), but makes the following changes:
- Moves all the new keys proposed in that comment into a new file
COMPONENT.traits.yml
in the same directory as the SDC. - Renames
slotted
tointendedFor
. - Simplifies the condition syntax by starting with the prop and within that nesting the trait values for a given prop value.
accordion_group.traits.yml
slots:
items:
width: full
luminance: 80
intendedFor: [accordion_item]
accordion_item.traits.yml
is: [accordion_item]
width: full
luminance: 20
heading.traits.yml
is: [heading, text]
props:
color:
light:
luminance: 80
dark:
luminance: 20
thumbs up from me
I think I missed some IRL discussions somewhere.
Maybe, but not in relation to comment #19. My proposal in that comment came directly from reading this issue's comments.
The issue summary gives the example of an accordion_group component containing a slot into which only accordion_item components make sense to be slotted. The IS also points out that the concept of an accordion_item isn't unique to just one SDC: you can have multiple SDCs (e.g., one from a module, one from a theme) that are all accordion items. #18 provides a similar use case of 'cards', but is even more explicit about the concept that multiple SDCs can be "card-like". I think #19's suggestion of is
and slotted
addresses those use cases: a components can identify what it is
, and a slot can identify what kind of slotted
content it's designed for.
That addresses the direct slot/slotted relationship, but comment #14 mentions additional use cases of context that should affect more distant descendants. #19 proposes traits
as the way to represent that.
#9 argues for the restriction rules to live in a different level than the SDCs, so #19 incorporates that via the separation between SDCs just declaring information about themselves, while the policies
that act on that information being defined in Drupal config.
Additionally I'm thinking that adding all this at the slot level in SDC will make it very hard share SDCs across themes/modules.
The is
, slotted
, and traits
keys I'm proposing in #19 would all be optional. SDCs that are designed to be super generic and flexible don't need to populate those keys. But what other than the SDC itself should be declaring that it's an accordion item, or card-like, or that it's full-width, or has a certain luminance, for the cases where the SDC author knows that information and wants to make that information available, so that policies can be created around that information?
doesn't belong on the SDC layer for me, especially now that we agree this is a UI concern, not a technical (as in render-time validation) concern
The SDC YAML already provides information about itself that isn't a render-time concern. For example, examples
and description
. A big selling point of SDCs is that everything about the SDC is colocated: the YAML, the Twig, the JS, the CSS. What's proposed in #19 is additional optional metadata about the SDC: why break the colocation advantage of SDCs by forcing that additional metadata to be somewhere else?
Trying to synthesize all the comments here, here's a proposal. I hope the terminology is clear enough to convey the concepts, but we can refine the terminology as needed.
Within the SDC's YML, we introduce two new top-level keys (i.e., information about the component):
is
traits
And for each slot, we also introduce two keys:
slotted
traits
And we define a set of traits. This can grow over time, but to give some examples:
width
luminance
An example of what an accordion_group
component might look like:
name: Accordion
props:
...
slots:
items:
title: ...
description: ...
slotted:
- accordion_item
traits:
width: full
luminance: 80
An example of what an accordion_item
component might look like:
name: Accordion Item
is:
- accordion_item
traits:
width: full
luminance: 20
props:
...
slots:
...
Traits, at the component level, or at the slot level, can also be conditional on the values of enum and boolean props. For example:
name: Heading
is:
- text
traits:
luminance:
-
condition:
prop: color
value: light
value: 80
-
condition:
prop: color
value: dark
value: 20
props:
color:
type: string
enum:
- light
- dark
slots:
...
Trait values descend. Meaning, if a slot doesn't specify a trait, it inherits the value from its component. If a component doesn't specify a trait, it inherits the value from the slot that it's in.
All of the above is info that's in the SDC's YAML. In addition, we define a Drupal config entity type that can store policies. Themes (or modules, recipes, etc.) can include these policies within their config/install
directory, just like any other default config. Exact syntax for these policies TBD, but for example, there could be:
- A policy that says: a component can only be placed in a slot if there's an intersection between the component's
is
and the slot'sslotted
. - Another policy that says: a component can only be placed in a slot if its luminance has a contrast of at least 4.5 with the slot's luminance.
Policies can be enabled/disabled, and they're only applied by builder tools (e.g., Experience Builder), not when rendering.
What do you all think? Is this a reasonable partitioning of concerns?
I don't see how #3514910: Real-time preview for props changes of JS components would A) help this issue...Yes, the resolved value is currently not yet actively used on the client-side, and we could in theory remove it.
My thinking was that the help it would offer this issue is by having an implemented use case (with tests) of the resolved values being used. So that, a) it prevents them from being removed, and b) it allows refactoring of where they're kept if such refactoring is desired per #20 while continuing to ensure that such refactoring is compatible with the use-case they need to serve.
But I'm totally okay with this issue being worked on first and not postponing it on ✨ Real-time preview for props changes of JS components Active .
Is there a reason we don't include the preview HTML in the undo stack? Thereby allowing all undo operations (regardless of what kinds of components are on the page) to optimistically render before the server response?
Even though my quote referenced in the issue summary was in the issue about the "page data" form, it was actually a statement about the component inputs form and just used as a point of comparison. So, re-titling this issue accordingly.
Currently, there is no client-side transformation that runs when widget inputs are updated on the page data form, so this issue isn't applicable there, though it's possible that at some point we'll want to open a separate issue to add client-side transformations on the page data form. I don't think there's currently a use-case for that though, since the fields on the page data form are intentionally the ones that (for the most part) don't have any representation in or impact on the preview (with the exception of potentially changing the content of Blocks, such as the page title block).
If we're starting to Drupalify the term "slot" by adding some implicit features
I don't think that specifying rules for which components can go into which slots is about Drupalifying, I think it's about encoding the rules of a design system. If you're building a design system for broad consumption, like Bootstrap, DaisyUI, etc., then you probably don't want to be overly prescriptive, and instead leave as much creative freedom to put almost any component into almost any slot as possible to the users of the design system. However, what if you're building a design system for a single customer, such as a university (or any other type of organization with different units within it), and that university wants every department's website to have some creative freedom, but also stay on brand. So even though functionally you could put any component into any slot, because after all, it's all just HTML, the creator of this type of design system wants to impose some rules. Where should those rules be encoded? It could be in Drupal config entities, but I don't think these are Drupal-related rules, they are an aspect of the design system. Should they be in the SDC's YAML files? Or at some other level, but if some other level, what is that level?
Do we only need resolved values for component preview and final render? I have concerns that if we are storing/sending both raw and resolved then there is a chance of them getting out of sync
I agree. Ideally only the raw values would need to be passed from the client to the server. As to where within the React code the resolved values are needed at all, as well as whether or not it's needed for resolved values (in addition to raw values) to be passed from server to client, I opened ✨ Real-time preview for props changes of JS components Active . That issue should be relatively straightforward to do, and I wonder if it would help with this issue's implementation to do that one first, to make sure resolved values are being used somewhere within the React code, even if not as part of the HTTP API.
effulgentsia → created an issue.
wim leers → credited effulgentsia → .
I don't think we have an issue for it yet, but one feature we still need to add is the ability for a JS component to import from another JS component. So, for example, if you have a Card
component, and it wants to include a Button
(as part of its design, not as something a content editor places into a slot), the code for the Card component would have:
import Button from '@/components/button'
...
// Now in my code I can do: <Button ...>
The string following the last '/' in the import statement is similar to a machine name. One possibility is we use the config entity's machine name instead of needing yet another identifier. However, if we do this, we'd want it to be mutable. Just like when you're editing code in an IDE it's nice to be able to refactor your file names / class names / function names, as you gain more clarity on what purpose that file/class/function is fulfilling.
I don't know if this is the only use case for wanting a mutable machine name, but it's potentially one of the use cases.
The approach proposed in the issue summary looks great to me, except for 3 minor points:
Follow-up: later still: detailed customization
I agree with #39 that we shouldn't do this for the same reasons as explained in that comment. But since it's listed as a follow-up that's even later than all the other follow-ups, we don't need to come to a consensus on it here.
x-format
May I suggest changing it to x-formatting-context? Although that's more verbose, it grounds it in a specification with a precise meaning. And if it's not specified, we should default to block
. @pdureau: Would that resolve your concern with it? If not, why not? Why do you see it as violating separation of concerns for the component author to specify that the component is designed for HTML prop foo to be contained in an inline formatting context?
xb_inline text format (restricted to
<strong> <em> <u> <a href>
)
I think we should allow <br>
as well, since that's an inline-level element and example 1 in comment #10 seems to have one between "Developers" and "Download", unless those are intended to be two different props.
MR looks great, but needs a test.
probably add a test calling \Drupal\Core\Validation\ConstraintManager::getDefinitionsByType to verify no crash?
Yep, that would be a good one.
Is this a known bug that the header and primary menu don't come with the
wrapping element in Olivero? Or is it omitted on purpose for a specific reason?
It's due to some of Olivero's region--*.html.twig files adding a wrapping <div>
and some not. I don't know if the ones without a wrapping div had a reason to be like that, but I think in general, whether to add wrapping elements or not is a per-theme decision so we can't rely on themes to follow a single root element for each region rule.
It makes it difficult do the "focus mode" on the header if the header has more than one component since there's no wrapping div I can target.
Is this a unique challenge for regions, or do we run into a similar issue (maybe not "focus mode" specifically but similar issues with selection) for components? We similarly can't assume that components follow a single root element for each component rule. How did we solve it there?
This will improve the accuracy of the preview, because the markup structure would no longer be changed. The subtle difference in markup structure can currently cause CSS to not apply, resulting in inaccurate previews!
Yep. See #3507631-11: Page mangled and warning from block components when enabling for global template → for an example.
I'm not able to reproduce the block_theme_suggestions_block()
warning.
I do see the page mangling when I enable "Use Experience Builder for page templates in this theme." in Olivero's settings, especially the page title block getting all skinny like in the issue summary's screenshot. I think that's due to the extra <div>
that XB is adding around regions that
📌
Implement HTML comment annotations for Regions, replace HTML wrappers
Active
aims to remove, so I think this issue is a duplicate of that one.
When the checkbox above is not enabled, the markup around the <main>
element is:
<div class="main-content__container container">
<main role="main" class="site-main">
When the checkbox is enabled, that markup is:
<div class="main-content__container container">
<div class="sidebar-grid grid-full">
<main role="main" class="site-main">
In Chrome inspector, if I remove the classes from that middle div, it fixes the mangling of the page title.
I want to correct what I wrote in #25:
Widget::massageFormValues() is a server-side widget-to-field (W->F) transform.
Reviewing this MR reminded me how wrong this is. If the above were true, then the denormalizers in this MR could just call the widget's massageFormValues() method. But the reason they can't is that W->F is actually client-side widget values -> server-side widget values -> field values, or WC->WS->F. WS->F
is massageFormValues(), but WC->WS
is spread throughout Form API callbacks (#process, #value_callback, #element_validate, and possibly others). That's why the denormalizers in this MR duplicate logic that's in the widget and the form elements created by the widget, but can't easily de-duplicate it. And that's why if we want the denormalizers to be optional, we need to figure out how to make the programmatic form submission approach work.
I really wanted to like this MR, especially after #28 and the related conversation that @larowlan and I had in Slack about it. However:
The reliance on normalizers (and having to define custom ones for some widgets) is kinda breaking the promise that @lauriii and @effulgentsia wanted XB to uphold: that your existing widgets would continue to work.
Ouch. Yeah, that's a deal breaker for me, unless we've exhausted every other option.
Of course, the client-side transforms we introduced [in #3499554] already is sort of breaking that, but this feels … worse/a bigger burden.
I think what's worse about this MR is that at least in-theory the client-side transforms should be optional. If a contrib/custom widget doesn't include one (or opt into using the no-op one), the system should fall back to a server request that uses Form API + Widget API to go from widget input to field value and then the prop expression to go from field value to prop value. In this way, Drupal's existing ecosystem of widgets continue to work, and ones that include client-side transforms (or can use the no-op one) just work faster (without a network request once we implement 📌 Implement endpoint for realtime preview Active ). Note that I don't know if the current state of 0.x implements this automatic fallback to server, but even if it doesn't currently, in principle we should be able to do this.
Whereas this MR makes server-side (de)normalizers required for every widget that requires any transformation from widget input to field value, and it's not clear from this MR how we'd be able to add a fallback to Form API + Widget API for widgets for which we lack that (de)normalizer.
This sidesteps a number of issues we've experienced in previous attempts here AND a big one that we haven't even started on yet which is to do with multi-users publishing in bulk. The form system relies on tokens. Tokens are session specific. To get form API working, we were having to store the form build ID (And keep it up to date)
I want to look into this. I don't see what's so bad about storing the form build ID and keeping it up to date. And I don't see why CSRF tokens are required when doing a programmatic form submission. Access checks, however, might be an issue, if the person publishing has different permissions than the person who last triggered an autosave.
If we can make the Form API approach work, I'd prefer we start with that. But that wouldn't make the normalizer work in this MR wasted. I think we can still add those in later, as optional improvements for widgets for which we write them. For example, widgets that come with normalizers could perhaps support concurrent editing (or rather, the anti-concurrent lock could be just for the widget, not the entire entity form) whereas widgets without normalizers would have to anti-concurrent lock the entire form. That would be a nice way to gently incentivize widget maintainers to add normalizers rather than flat out making them not work in XB.
In Slack, @larowlan confirmed that just like in #3509528-2: Adding to components doesn't appear to update component list - show loading indicator → , this only happens when the Redux dev tools browser extension is in use (though for both Chrome and Firefox). Re-titling accordingly and downgrading to Normal. We could potentially decide to "won't fix" this, except not being able to use Redux dev tools would be an annoyance for any React developers wanting to contribute to XB.
This would be helpful, for example, on Experience Builder, where we do 2-week sprints, and we start the sprint by tagging the issues we planned with the "sprint" tag, then at the end of the sprint it would be great to be able to untag all of them before tagging the next set. It's not so bad doing this manually when there's 10 issues to untag, but sometimes there can be 20 or more, so bulk untagging via VBO or similar would be really nice.
wim leers → credited effulgentsia → .
wim leers → credited effulgentsia → .
Ah yes, #28 sounds right. However, does it let you side step the Form API problems entirely, or do you still have many of those same problems for AJAX interactions? For example, doesn't interacting with the Media Library still require the form build ID and all that? Or did you come up with a way to side step it there as well?
Oh ok, yeah the scope of #26 makes sense, and given that scope, server-side makes sense too. But in that case, are you proposing:
- client has W
- client makes call to server to convert W to F
- client gets back F and makes another call to server to save F to entity
If so, what's the benefit of that vs.
- client has W
- client submits W to server
- server saves W to entity using Form/Widget API
I'm assuming the latter of the above is what was tried earlier in this issue and it ran into problems? If so, is there a way to quickly summarize what those problems were? I think the former is a fine way to go if there are compelling reasons why that's superior to the latter.
I hope the following comment makes sense. I'm basing it on what I've been able to glean from issue comments, but I haven't yet inspected the code that's in 0.x or in this MR, so it's possible that some of what I write here is incorrect, in which case, apologies for that.
Backing up a bit, here's what we have in Drupal core, outside of XB:
Widget::formElement()
is a server-side field-to-widget (F->W
) transform.Widget::massageFormValues()
is a server-side widget-to-field (W->F
) transform.Formatter::viewElements()
is a server-side field-to-html (F->H
) transform.
XB aims to enable component-based design, and component-based design is about ditching the F->H concept (i.e., formatters), and replacing it with components, which are props-to-html (P->H) transforms, which then means we need field-to-props (F->P) transforms, which XB implements server-side as "prop expressions". So, with XB, the above becomes:
Widget::formElement()
is a server-side field-to-widget (F->W
) transform.Widget::massageFormValues()
is a server-side widget-to-field (W->F
) transform.- Prop expressions are server-side field-to-prop (
F->P
) transforms. - Components are server-side (if SDCs) or client-side (if JS components) props-to-html (
P->H
) transforms.
What I think (please correct me if I'm wrong)
📌
Move clientside assumptions about prop form data shape into a series of prop specific transforms
Active
added is client-side widget-to-prop (W->P
) transforms. Note that this doesn't have any server-side analog in the above lists.
What I think #23.2 is suggesting is to add client-side widget-to-field (W->F
) transforms, which if feasible, would be nice in terms of parity with what happens server-side.
If we do #23.3, then do we still need the W->P transforms, or could we replace those with client-side prop expression evaluators, i.e., F->P transforms, so that W->P could be refactored as W->F, then F->P? Because if we can do that, then that will result in full parity between client-side and server-side for everything except F->W (Widget::formElement()
), which we don't yet have a use case for needing a client-side version of (or do we?).
I think the MR looks great. Should we upgrade to React 19 and take advantage of the nicer syntax for refs?
Is the intent of this to make sure that the component you're currently editing is re-autosaved when global css is changed? But other components don't automatically get recompiled with the new global css, right? I think that's fine if that's what we want the scope of this issue to be, but just want to make sure that's explicit if that's the case.