Repository navigation
Conversation
Select (the choices widget), array/tokens, number, file, email, password and URL widgets, built against the widget contract and its tests. File and image fields now upload the file instead of storing an image URL. A widget registered for a vocabulary takes precedence over the choices widget. Co-Authored-By: Claude <noreply@anthropic.com>
This was referenced Oct 9, 2026
Drop registerChoicesWidget: registerWidget takes the choices slot, which holds one widget. It now tells a widget component from a map of widgets even when the component has keys of its own, such as displayName. Co-Authored-By: Claude <noreply@anthropic.com>
Member
Author
|
LGTM, with room to improve, I guess |
… feat/missing-widgets * origin/feat/typed-widget-registry: Restore files the pre-commit hook reformatted Validate schema-driven forms (#256) Move the recurrence modal off TanStack Form (#254) Move the forms onto the helpers form store (#253) Add a Jotai-native form layer to helpers (#252) Render every schema form through one field renderer (#251) Document and type the form widget contract (#97) Match utility dependencies exactly in the registry (#259)
… feat/missing-widgets * origin/feat/typed-widget-registry: Add the components changelog entry for the picker rename
sneridagh
added this pull request to stack #270
October 10, 2026 22:48
pnicolli
approved these changes
Oct 11, 2026
| const { data: vocabulary } = await cli.getVocabulary({ | ||
| path: name, | ||
| title, | ||
| b_size: -1, |
Collaborator
There was a problem hiding this comment.
Maybe this should be an optional parameter?
Member
Author
There was a problem hiding this comment.
-1 does not mean "give them all to me", no pagination? I can see the definition is optional in zod schema.
Member
Author
There was a problem hiding this comment.
Now I get you, you were referring to the route, not the client! Implementing!
The route no longer returns every term: callers pass b_size, and without it the content API returns its default batch. The select asks for all the terms, and the array widget for 25 suggestions. Co-Authored-By: Claude <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Step 7 of #243: the missing core widgets. Each one is built against the widget contract and runs
describeWidgetContract.Stacked on #262. Part of the review guide in #244 (comment).
Closes #243
Widgets
SelectWidgetchoicesorvocabulary),widget: 'select'nullArrayWidgettype: 'array',widget: 'array',widget: 'token'NumberWidgettype: 'number',type: 'integer'nullFileWidgetfactory: 'File',factory: 'Image',widget: 'file'nullEmailWidget,PasswordWidget,UrlWidgetwidget: 'email','password','url'config.widgets.choicesis now registered withconfig.registerWidget({ key: 'choices', definition: SelectWidget }).registerWidgetnow accepts thechoicesslot, which holds one widget, and tells a component from a map of widgets even when the component has adisplayName(before, counting its keys made it a map). The options come from the schema'schoices, or from the field's vocabulary through a new@vocabularyresource route. Optional fields get a "No value" option.widgetOptions. A closed list whenitemshaschoicesor avocabulary.NumberFieldcontrol. It readsminimumandmaximum, and takes whole numbers only forinteger.ImageWidget, which stores a URL that the content API can't save. They now getFileWidget, which uploads the file (base64) and keeps a stored file as it is.ImageWidgetstays the widget of URL-valuedwidget: 'image'fields, such as the image block'surl.TextFieldwith the right input type. The validators forwidget: 'email'andwidget: 'url'already existed (Validate schema-driven forms #256).Changes found along the way
plone.app.vocabularies.Catalogfields would get a select that loads the whole catalog instead of the object browser. The guide documents the new order.{token, title}objects (language,sort_tabs_on,displayed_types). Select and array read terms and write tokens. Before, these values crashed the render as "Objects are not valid as a React child".@plone/clientcontent schemas.allow_discussionnow accepts its choice tokens"True"/"False", which the backend accepts. Before, Zod rejected the save.preview_imageaccepts a stored file.null.getVocabularytakes ab_size(-1returns all the terms).Contract gap
SelectWidgetskips the contract'srequiredcheck, with the reason recorded in the test. React Aria's Select marks a required field withdata-requiredand the label's marker, not witharia-required, which a button can't have.Tests
registerWidget(a component with adisplayName; fails with the old key counting).core-widgets.test.ts). Each one fails when the old widget registrations are restored:allow_discussion(stored as a boolean) is read and saved.smtp_portas a number and has a password input.Docs