@lablup/ui-common 0.2.0-alpha.18 → 0.2.0-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/astryx/components/Form.doc.mjs +1 -1
- package/dist/assets/components/Form/FormItemVisual.css +1 -1
- package/dist/astryx/DateInput/tokens.stylex.d.ts +1 -0
- package/dist/astryx/DateInput/tokens.stylex.js +1 -0
- package/dist/astryx/Icon/IconSize.stylex.d.ts +1 -0
- package/dist/astryx/Icon/IconSize.stylex.js +1 -0
- package/dist/astryx/Indicator/indicator.markers.stylex.d.ts +1 -0
- package/dist/astryx/Indicator/indicator.markers.stylex.js +1 -0
- package/dist/astryx/Layer/layerAnimations.stylex.d.ts +1 -0
- package/dist/astryx/Layer/layerAnimations.stylex.js +1 -0
- package/dist/astryx/Layer/layerTextReset.stylex.d.ts +1 -0
- package/dist/astryx/Layer/layerTextReset.stylex.js +1 -0
- package/dist/astryx/Layer/layerViewportInset.stylex.d.ts +1 -0
- package/dist/astryx/Layer/layerViewportInset.stylex.js +1 -0
- package/dist/astryx/Layout/container.stylex.d.ts +1 -0
- package/dist/astryx/Layout/container.stylex.js +1 -0
- package/dist/astryx/Layout/edgeCompensation.stylex.d.ts +1 -0
- package/dist/astryx/Layout/edgeCompensation.stylex.js +1 -0
- package/dist/astryx/Layout/padding.stylex.d.ts +1 -0
- package/dist/astryx/Layout/padding.stylex.js +1 -0
- package/dist/astryx/Markdown/plugin-renderer.d.ts +1 -0
- package/dist/astryx/Markdown/plugin-renderer.js +1 -0
- package/dist/astryx/NavItem/navItemStyles.stylex.d.ts +1 -0
- package/dist/astryx/NavItem/navItemStyles.stylex.js +1 -0
- package/dist/astryx/Selector/selectorPresentation.stylex.d.ts +1 -0
- package/dist/astryx/Selector/selectorPresentation.stylex.js +1 -0
- package/dist/astryx/Stack/stack.stylex.d.ts +1 -0
- package/dist/astryx/Stack/stack.stylex.js +1 -0
- package/dist/astryx/Stack/stackItem.stylex.d.ts +1 -0
- package/dist/astryx/Stack/stackItem.stylex.js +1 -0
- package/dist/astryx/Text/text.stylex.d.ts +1 -0
- package/dist/astryx/Text/text.stylex.js +1 -0
- package/dist/astryx/theme/dataTokens.stylex.d.ts +1 -0
- package/dist/astryx/theme/dataTokens.stylex.js +1 -0
- package/dist/astryx/theme/neutral/fonts.css +3 -0
- package/dist/astryx/utils/focusOutline.stylex.d.ts +1 -0
- package/dist/astryx/utils/focusOutline.stylex.js +1 -0
- package/dist/astryx/utils/interactionOverlay.stylex.d.ts +1 -0
- package/dist/astryx/utils/interactionOverlay.stylex.js +1 -0
- package/dist/components/Form/FormItem.d.ts +5 -0
- package/dist/components/Form/FormItem.js +68 -67
- package/dist/components/Form/FormItem.js.map +1 -1
- package/dist/components/Form/FormItemVisual.d.ts +7 -0
- package/dist/components/Form/FormItemVisual2.js +60 -55
- package/dist/components/Form/FormItemVisual2.js.map +1 -1
- package/dist/components/NotificationStack/NotificationStack2.js +1 -0
- package/dist/components/NotificationStack/NotificationStack2.js.map +1 -1
- package/dist/components/PagedSelector/PagedSelector.d.ts +1 -1
- package/dist/components/PagedSelector/PagedSelector2.js.map +1 -1
- package/dist/forks/ComplexSelector/ComplexSelector.d.ts +82 -6
- package/dist/forks/ComplexSelector/ComplexSelector.js +170 -114
- package/dist/forks/ComplexSelector/ComplexSelector.js.map +1 -1
- package/dist/forks/ComplexSelector/ComplexSelector.styles.d.ts +40 -0
- package/dist/forks/ComplexSelector/ComplexSelector.styles.js +46 -6
- package/dist/forks/ComplexSelector/ComplexSelector.styles.js.map +1 -1
- package/dist/forks/ComplexSelector/index.d.ts +1 -1
- package/dist/forks/Drawer/Drawer.d.ts +21 -3
- package/dist/forks/Drawer/Drawer.js +70 -65
- package/dist/forks/Drawer/Drawer.js.map +1 -1
- package/dist/forks/Drawer/Drawer.styles.d.ts +16 -0
- package/dist/forks/Drawer/Drawer.styles.js +16 -0
- package/dist/forks/Drawer/Drawer.styles.js.map +1 -1
- package/dist/forks/Drawer/useDrawerDialogPresence.js.map +1 -1
- package/dist/forks/Tour/Tour.js +38 -40
- package/dist/forks/Tour/Tour.js.map +1 -1
- package/dist/forks/Tour/TourContext.js.map +1 -1
- package/dist/forks/Tour/TourStep.js.map +1 -1
- package/dist/forks/Tour/TourStep.styles.js.map +1 -1
- package/dist/forks/Tour/useTour.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -2
- package/dist/instance.js +2 -2
- package/dist/locales/en.generated.js +34 -0
- package/dist/locales/en.json +136 -0
- package/dist/locales/pseudo.generated.js +34 -0
- package/dist/locales/pseudo.json +102 -0
- package/dist/theme/lablup/built/lablup.d.ts +3 -3
- package/dist/theme/lablup/built/lablup.js +24 -5
- package/dist/theme/lablup/built/lablup.variants.d.ts +2 -2
- package/dist/theme/lablup/built/theme.css +70 -63
- package/dist/theme/lablup/built/theme.css.d.ts +9 -0
- package/package.json +86 -6
package/README.md
CHANGED
|
@@ -102,14 +102,14 @@ there):
|
|
|
102
102
|
|
|
103
103
|
```yaml
|
|
104
104
|
overrides:
|
|
105
|
-
"@astryxdesign/lab>@astryxdesign/core": "0.
|
|
105
|
+
"@astryxdesign/lab>@astryxdesign/core": "0.7.0"
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
npm, in the root `package.json`:
|
|
109
109
|
|
|
110
110
|
```json
|
|
111
111
|
"overrides": {
|
|
112
|
-
"@astryxdesign/lab": { "@astryxdesign/core": "0.
|
|
112
|
+
"@astryxdesign/lab": { "@astryxdesign/core": "0.7.0" }
|
|
113
113
|
}
|
|
114
114
|
```
|
|
115
115
|
|
|
@@ -102,7 +102,7 @@ export default {
|
|
|
102
102
|
],
|
|
103
103
|
usage: {
|
|
104
104
|
description:
|
|
105
|
-
"Data-entry screens whose state, validation and submit need more than a few controlled fields. Style hooks: .uic-form-item and its __label, __control, __explain-error, __extra elements, and --form-item-margin-bottom, --form-item-gap and --form-item-line-height. Help, extra and the tooltip glyph take the theme's --color-text-description when it declares one (default --color-text-secondary). A control reaches its item's status through Form.Item.useStatus() or FormItemInputContext.",
|
|
105
|
+
"Data-entry screens whose state, validation and submit need more than a few controlled fields. Form.Item's labelExtra puts actions (a filter or sort toggle) in the label row, outside the <label> so they stay out of the control's accessible name: at the far end in vertical layout, right after the label otherwise. Style hooks: .uic-form-item and its __label, __label-extra, __control, __explain-error, __extra elements, and --form-item-margin-bottom, --form-item-gap and --form-item-line-height. Help, extra and the tooltip glyph take the theme's --color-text-description when it declares one (default --color-text-secondary). A control reaches its item's status through Form.Item.useStatus() or FormItemInputContext.",
|
|
106
106
|
},
|
|
107
107
|
examples: [
|
|
108
108
|
{
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
@layer reset, theme, base, astryx-base, astryx-theme, ui-common, components, utilities;
|
|
2
|
-
@layer ui-common{.uic-form[data-layout=inline]{flex-wrap:wrap;display:flex}.uic-form[data-layout=inline]>.uic-form-item,.uic-form[data-layout=inline] .uic-form-item[data-layout=inline]{flex:none;margin-inline-end:var(--spacing-4)}.uic-form-item{box-sizing:border-box;vertical-align:top;margin-bottom:var(--form-item-margin-bottom,var(--spacing-6));font-size:var(--font-size-base);line-height:var(--form-item-line-height,var(--text-body-leading))}.uic-form-item[data-layout=inline]{margin-bottom:0}.uic-form-item[data-hidden]{display:none}.uic-form-item__row{flex-flow:wrap;min-width:0;display:flex}.uic-form-item[data-layout=vertical] .uic-form-item__row{flex-direction:column}.uic-form-item[data-layout=inline] .uic-form-item__row{flex-wrap:nowrap}.uic-form-item__label-col{white-space:nowrap;text-align:end;vertical-align:middle;box-sizing:border-box;flex-grow:0;max-width:100%;overflow:hidden}.uic-form-item__label-col[data-align=left]{text-align:start}.uic-form-item__label-col[data-wrap]{overflow:unset;line-height:var(--form-item-line-height,var(--text-body-leading));white-space:unset}.uic-form-item__label-col[data-wrap]>.uic-form-item__label{vertical-align:middle;text-wrap:balance}.uic-form-item[data-layout=vertical] .uic-form-item__label-col{padding:0 0 var(--form-item-gap,var(--spacing-2));white-space:initial;text-align:start;margin:0}.uic-form-item[data-layout=inline] .uic-form-item__label-col{flex:none}.uic-form-item__label{max-width:100%;height:var(--size-element-md);color:var(--color-text-primary);font-size:var(--font-size-base);line-height:var(--form-item-line-height,var(--text-body-leading));align-items:center;display:inline-flex;position:relative}.uic-form-item[data-layout=vertical] .uic-form-item__label{height:auto;margin:0}.uic-form-item[data-size=small] .uic-form-item__label{height:var(--size-element-sm)}.uic-form-item[data-size=large] .uic-form-item__label{height:var(--size-element-lg)}.uic-form-item__label--required:before{color:var(--color-error);font-size:var(--font-size-base);content:"*";margin-inline-end:var(--spacing-1);font-family:sans-serif;line-height:1;display:inline-block}.uic-form-item__label[data-required-mark]:before{display:none}.uic-form-item__label:after{content:":";margin-block:0;margin-inline-start:var(--spacing-0-5);margin-inline-end:var(--spacing-2);position:relative}.uic-form-item__label[data-no-colon]:after{content:" "}.uic-form-item[data-layout=vertical] .uic-form-item__label:after{visibility:hidden}.uic-form-item__optional{color:var(--color-text-description,var(--color-text-secondary));margin-inline-start:var(--spacing-1);display:inline-block}.uic-form-item__tooltip{color:var(--color-text-description,var(--color-text-secondary));cursor:help;writing-mode:horizontal-tb;align-items:center;margin-inline-start:var(--spacing-1);display:inline-flex}.uic-form-item__control{box-sizing:border-box;flex-direction:column;flex-grow:1;min-width:0;display:flex}.uic-form-item__row>.uic-form-item__control:first-child:not([data-span]){width:100%}.uic-form-item:not([data-layout=vertical]) .uic-form-item__label-col+.uic-form-item__control{flex:1 1 0}.uic-form-item[data-layout=vertical] .uic-form-item__control{width:100%}.uic-form-item__control-input{min-height:var(--size-element-md);align-items:center;display:flex;position:relative}.uic-form-item[data-size=small] .uic-form-item__control-input{min-height:var(--size-element-sm)}.uic-form-item[data-size=large] .uic-form-item__control-input{min-height:var(--size-element-lg)}.uic-form-item__control-input-content{flex:auto;max-width:100%}.uic-form-item__additional{flex-direction:column;display:flex}.uic-form-item__explain,.uic-form-item__extra{clear:both;color:var(--color-text-description,var(--color-text-secondary));font-size:var(--font-size-base);line-height:var(--form-item-line-height,var(--text-body-leading))}.uic-form-item__extra{min-height:var(--size-element-sm)}.uic-form-item__explain-error{color:var(--color-error)}.uic-form-item__explain-warning{color:var(--color-warning)}.uic-form-item__feedback-icon{inset-inline-end:var(--spacing-3);height:calc(var(--font-size-base) * var(--form-item-line-height,var(--text-body-leading)));color:var(--color-accent);font-size:var(--font-size-base);pointer-events:none;justify-content:center;align-items:center;display:inline-flex;position:absolute;top:50%;transform:translateY(-50%)}.uic-form-item__feedback-icon[data-status=success]{color:var(--color-success)}.uic-form-item__feedback-icon[data-status=warning]{color:var(--color-warning)}.uic-form-item__feedback-icon[data-status=error]{color:var(--color-error)}.uic-form-item__feedback-glyph[data-status=validating]{animation:1s linear infinite uic-form-item-feedback-spin}@keyframes uic-form-item-feedback-spin{to{transform:rotate(360deg)}}}
|
|
2
|
+
@layer ui-common{.uic-form[data-layout=inline]{flex-wrap:wrap;display:flex}.uic-form[data-layout=inline]>.uic-form-item,.uic-form[data-layout=inline] .uic-form-item[data-layout=inline]{flex:none;margin-inline-end:var(--spacing-4)}.uic-form-item{box-sizing:border-box;vertical-align:top;margin-bottom:var(--form-item-margin-bottom,var(--spacing-6));font-size:var(--font-size-base);line-height:var(--form-item-line-height,var(--text-body-leading))}.uic-form-item[data-layout=inline]{margin-bottom:0}.uic-form-item[data-hidden]{display:none}.uic-form-item__row{flex-flow:wrap;min-width:0;display:flex}.uic-form-item[data-layout=vertical] .uic-form-item__row{flex-direction:column}.uic-form-item[data-layout=inline] .uic-form-item__row{flex-wrap:nowrap}.uic-form-item__label-col{white-space:nowrap;text-align:end;vertical-align:middle;box-sizing:border-box;flex-grow:0;max-width:100%;overflow:hidden}.uic-form-item__label-col[data-align=left]{text-align:start}.uic-form-item__label-col[data-wrap]{overflow:unset;line-height:var(--form-item-line-height,var(--text-body-leading));white-space:unset}.uic-form-item__label-col[data-wrap]>.uic-form-item__label{vertical-align:middle;text-wrap:balance}.uic-form-item[data-layout=vertical] .uic-form-item__label-col{padding:0 0 var(--form-item-gap,var(--spacing-2));white-space:initial;text-align:start;margin:0}.uic-form-item[data-layout=inline] .uic-form-item__label-col{flex:none}.uic-form-item__label{max-width:100%;height:var(--size-element-md);color:var(--color-text-primary);font-size:var(--font-size-base);line-height:var(--form-item-line-height,var(--text-body-leading));align-items:center;display:inline-flex;position:relative}.uic-form-item[data-layout=vertical] .uic-form-item__label{height:auto;margin:0}.uic-form-item[data-size=small] .uic-form-item__label{height:var(--size-element-sm)}.uic-form-item[data-size=large] .uic-form-item__label{height:var(--size-element-lg)}.uic-form-item__label--required:before{color:var(--color-error);font-size:var(--font-size-base);content:"*";margin-inline-end:var(--spacing-1);font-family:sans-serif;line-height:1;display:inline-block}.uic-form-item__label[data-required-mark]:before{display:none}.uic-form-item__label:after{content:":";margin-block:0;margin-inline-start:var(--spacing-0-5);margin-inline-end:var(--spacing-2);position:relative}.uic-form-item__label[data-no-colon]:after{content:" "}.uic-form-item[data-layout=vertical] .uic-form-item__label:after{visibility:hidden}.uic-form-item__label-col[data-has-label-extra]{justify-content:flex-end;align-items:center;display:flex}.uic-form-item__label-col[data-has-label-extra][data-align=left]{justify-content:flex-start}.uic-form-item[data-layout=vertical] .uic-form-item__label-col[data-has-label-extra]{justify-content:space-between;overflow:visible}.uic-form-item__label-col[data-has-label-extra]>.uic-form-item__label{min-width:0}.uic-form-item__label-col[data-has-label-extra]:not([data-wrap])>.uic-form-item__label{overflow:hidden}.uic-form-item__label-col[data-has-label-extra]>.uic-form-item__label:after{content:none}.uic-form-item__label-extra{flex:none;align-items:center;margin-inline-start:var(--spacing-1);display:inline-flex}.uic-form-item__label-extra:after{content:":";margin-inline-start:var(--spacing-0-5);margin-inline-end:var(--spacing-2)}.uic-form-item__label-extra[data-no-colon]:after{content:" "}.uic-form-item[data-layout=vertical] .uic-form-item__label-extra:after{content:none}.uic-form-item__optional{color:var(--color-text-description,var(--color-text-secondary));margin-inline-start:var(--spacing-1);display:inline-block}.uic-form-item__tooltip{color:var(--color-text-description,var(--color-text-secondary));cursor:help;writing-mode:horizontal-tb;align-items:center;margin-inline-start:var(--spacing-1);display:inline-flex}.uic-form-item__control{box-sizing:border-box;flex-direction:column;flex-grow:1;min-width:0;display:flex}.uic-form-item__row>.uic-form-item__control:first-child:not([data-span]){width:100%}.uic-form-item:not([data-layout=vertical]) .uic-form-item__label-col+.uic-form-item__control{flex:1 1 0}.uic-form-item[data-layout=vertical] .uic-form-item__control{width:100%}.uic-form-item__control-input{min-height:var(--size-element-md);align-items:center;display:flex;position:relative}.uic-form-item[data-size=small] .uic-form-item__control-input{min-height:var(--size-element-sm)}.uic-form-item[data-size=large] .uic-form-item__control-input{min-height:var(--size-element-lg)}.uic-form-item__control-input-content{flex:auto;max-width:100%}.uic-form-item__additional{flex-direction:column;display:flex}.uic-form-item__explain,.uic-form-item__extra{clear:both;color:var(--color-text-description,var(--color-text-secondary));font-size:var(--font-size-base);line-height:var(--form-item-line-height,var(--text-body-leading))}.uic-form-item__extra{min-height:var(--size-element-sm)}.uic-form-item__explain-error{color:var(--color-error)}.uic-form-item__explain-warning{color:var(--color-warning)}.uic-form-item__feedback-icon{inset-inline-end:var(--spacing-3);height:calc(var(--font-size-base) * var(--form-item-line-height,var(--text-body-leading)));color:var(--color-accent);font-size:var(--font-size-base);pointer-events:none;justify-content:center;align-items:center;display:inline-flex;position:absolute;top:50%;transform:translateY(-50%)}.uic-form-item__feedback-icon[data-status=success]{color:var(--color-success)}.uic-form-item__feedback-icon[data-status=warning]{color:var(--color-warning)}.uic-form-item__feedback-icon[data-status=error]{color:var(--color-error)}.uic-form-item__feedback-glyph[data-status=validating]{animation:1s linear infinite uic-form-item-feedback-spin}@keyframes uic-form-item-feedback-spin{to{transform:rotate(360deg)}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/DateInput/tokens.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/DateInput/tokens.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Icon/IconSize.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Icon/IconSize.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Indicator/indicator.markers.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Indicator/indicator.markers.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Layer/layerAnimations.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Layer/layerAnimations.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Layer/layerTextReset.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Layer/layerTextReset.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Layer/layerViewportInset.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Layer/layerViewportInset.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Layout/container.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Layout/container.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Layout/edgeCompensation.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Layout/edgeCompensation.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Layout/padding.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Layout/padding.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Markdown/plugin-renderer';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Markdown/plugin-renderer";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/NavItem/navItemStyles.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/NavItem/navItemStyles.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Selector/selectorPresentation.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Selector/selectorPresentation.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Stack/stack.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Stack/stack.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Stack/stackItem.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Stack/stackItem.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/Text/text.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/Text/text.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/theme/dataTokens.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/theme/dataTokens.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/utils/focusOutline.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/utils/focusOutline.stylex";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@astryxdesign/core/utils/interactionOverlay.stylex';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@astryxdesign/core/utils/interactionOverlay.stylex";
|
|
@@ -14,6 +14,11 @@ export interface FormItemProps<Values = any> extends Omit<FieldProps, "children"
|
|
|
14
14
|
* overlay and are ignored.
|
|
15
15
|
*/
|
|
16
16
|
tooltip?: React.ReactNode | FormItemTooltipConfig;
|
|
17
|
+
/**
|
|
18
|
+
* Actions for the label row: far end in vertical layout, right after the
|
|
19
|
+
* label in horizontal / inline layout. Needs a `label`.
|
|
20
|
+
*/
|
|
21
|
+
labelExtra?: React.ReactNode;
|
|
17
22
|
extra?: React.ReactNode;
|
|
18
23
|
/** `false` also suppresses meta bubbling to an ancestor item. */
|
|
19
24
|
help?: React.ReactNode;
|
|
@@ -2,17 +2,17 @@ import { useUicTranslator as e } from "../../i18n/useUicTranslator.js";
|
|
|
2
2
|
import { FieldContext as t, FormConfigContext as n, FormItemInputContext as r, FormItemLayoutContext as i, ListContext as a, NoStyleItemContext as o } from "./context.js";
|
|
3
3
|
import { toArray as s } from "./namePath.js";
|
|
4
4
|
import c from "./Field.js";
|
|
5
|
-
import { FormItemVisual as
|
|
6
|
-
import * as
|
|
7
|
-
import { Fragment as
|
|
5
|
+
import { FormItemVisual as l } from "./FormItemVisual2.js";
|
|
6
|
+
import * as u from "react";
|
|
7
|
+
import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
8
8
|
//#region src/components/Form/FormItem.tsx
|
|
9
|
-
var
|
|
10
|
-
function
|
|
9
|
+
var ee = "__SPLIT__", m = ["parentNode"];
|
|
10
|
+
function h(e, t) {
|
|
11
11
|
if (!e.length) return;
|
|
12
12
|
let n = e.join("_");
|
|
13
|
-
return t ? `${t}_${n}` :
|
|
13
|
+
return t ? `${t}_${n}` : m.includes(n) ? `form_item_${n}` : n;
|
|
14
14
|
}
|
|
15
|
-
function
|
|
15
|
+
function g() {
|
|
16
16
|
return {
|
|
17
17
|
errors: [],
|
|
18
18
|
warnings: [],
|
|
@@ -22,115 +22,116 @@ function h() {
|
|
|
22
22
|
validated: !1
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
-
function
|
|
25
|
+
function te(e, t, n, r, i) {
|
|
26
26
|
return i === void 0 ? n.validating ? "validating" : e.length ? "error" : t.length ? "warning" : n.touched || r && n.validated ? "success" : "" : i;
|
|
27
27
|
}
|
|
28
|
-
var
|
|
29
|
-
function
|
|
30
|
-
return
|
|
28
|
+
var _ = (e) => !!e && typeof e == "object" && !u.isValidElement(e) && "title" in e;
|
|
29
|
+
function ne(e) {
|
|
30
|
+
return _(e) ? e.title : e;
|
|
31
31
|
}
|
|
32
|
-
function
|
|
33
|
-
return
|
|
32
|
+
function re(e) {
|
|
33
|
+
return _(e) ? e.icon : void 0;
|
|
34
34
|
}
|
|
35
|
-
var v = (
|
|
36
|
-
let { name:
|
|
37
|
-
...
|
|
35
|
+
var v = (d) => {
|
|
36
|
+
let { name: p, label: m, tooltip: _, labelExtra: v, extra: y, help: b, required: x, noStyle: S, hidden: C, layout: oe, className: se, style: ce, hasFeedback: w, validateStatus: le, children: T, rules: E, dependencies: D, shouldUpdate: O, messageVariables: k, trigger: A = "onChange", validateTrigger: j, colon: ue, labelAlign: de, labelCol: M, wrapperCol: N, labelWrap: fe, htmlFor: pe, fieldKey: me, id: he, __values: ge, ...P } = d, F = u.useContext(t), { optionalLabel: I } = u.useContext(n), L = e(), { layout: R, requiredMark: z, name: _e, disabled: ve, size: ye, colon: be, labelAlign: xe, labelCol: B, wrapperCol: V, labelWrap: Se } = u.useContext(i), H = u.useContext(o), Ce = u.useContext(a), we = oe || R, Te = M ?? B, U = N ?? V, Ee = m === null && !M && !N && B?.span !== void 0 && B.span < 24 ? {
|
|
37
|
+
...U,
|
|
38
38
|
offset: B.span
|
|
39
|
-
} :
|
|
39
|
+
} : U, W = j === void 0 ? F.validateTrigger : j, [G, De] = u.useState(g), [K, Oe] = u.useState({}), q = u.useRef(null), ke = (e) => {
|
|
40
40
|
let t = Ce?.getKey(e.name);
|
|
41
|
-
if (De(e.destroy ?
|
|
41
|
+
if (De(e.destroy ? g() : e), S && b !== !1 && H) {
|
|
42
42
|
let n = e.name;
|
|
43
|
-
if (e.destroy) n =
|
|
43
|
+
if (e.destroy) n = q.current || n;
|
|
44
44
|
else if (t !== void 0) {
|
|
45
45
|
let [e, r] = t;
|
|
46
|
-
n = [e, ...r],
|
|
46
|
+
n = [e, ...r], q.current = n;
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
H(e, n);
|
|
49
49
|
}
|
|
50
|
-
},
|
|
50
|
+
}, Ae = (e, t) => {
|
|
51
51
|
Oe((n) => {
|
|
52
|
-
let r = { ...n }, i = [...e.name.slice(0, -1), ...t].join(
|
|
52
|
+
let r = { ...n }, i = [...e.name.slice(0, -1), ...t].join(ee);
|
|
53
53
|
return e.destroy ? delete r[i] : r[i] = e, r;
|
|
54
54
|
});
|
|
55
|
-
}, J = [...
|
|
55
|
+
}, J = [...G.errors, ...Object.values(K).flatMap((e) => e.errors ?? [])], Y = [...G.warnings, ...Object.values(K).flatMap((e) => e.warnings ?? [])], X = (e, t, n, i) => {
|
|
56
56
|
let a = {
|
|
57
|
-
status:
|
|
57
|
+
status: te(J, Y, G, w, le),
|
|
58
58
|
errors: J,
|
|
59
59
|
warnings: Y,
|
|
60
|
-
hasFeedback:
|
|
60
|
+
hasFeedback: w,
|
|
61
61
|
isFormItemInput: !0
|
|
62
62
|
};
|
|
63
|
-
if (
|
|
63
|
+
if (S && !C) return /* @__PURE__ */ f(r.Provider, {
|
|
64
64
|
value: a,
|
|
65
65
|
children: e
|
|
66
66
|
});
|
|
67
|
-
let s = z === !1 ? "hidden" : z === "optional" || typeof z == "function" ? "optional" : void 0, c =
|
|
68
|
-
return /* @__PURE__ */
|
|
67
|
+
let s = z === !1 ? "hidden" : z === "optional" || typeof z == "function" ? "optional" : void 0, c = x === void 0 ? !!n : x, u = ae(m, c, z, I ?? L("uic.Form.optional"));
|
|
68
|
+
return /* @__PURE__ */ f(r.Provider, {
|
|
69
69
|
value: a,
|
|
70
|
-
children: /* @__PURE__ */
|
|
71
|
-
label:
|
|
72
|
-
labelTitle: typeof
|
|
73
|
-
tooltip:
|
|
74
|
-
tooltipIcon: _
|
|
75
|
-
|
|
76
|
-
|
|
70
|
+
children: /* @__PURE__ */ f(l, {
|
|
71
|
+
label: u,
|
|
72
|
+
labelTitle: typeof m == "string" ? m : void 0,
|
|
73
|
+
tooltip: ne(_),
|
|
74
|
+
tooltipIcon: re(_),
|
|
75
|
+
labelExtra: v,
|
|
76
|
+
extra: y,
|
|
77
|
+
help: b,
|
|
77
78
|
required: c,
|
|
78
79
|
requiredMarkType: s,
|
|
79
80
|
layout: we,
|
|
80
|
-
size:
|
|
81
|
-
colon: ue ??
|
|
82
|
-
labelAlign: de ??
|
|
81
|
+
size: ye,
|
|
82
|
+
colon: ue ?? be,
|
|
83
|
+
labelAlign: de ?? xe,
|
|
83
84
|
labelCol: Te,
|
|
84
85
|
wrapperCol: Ee,
|
|
85
86
|
labelWrap: fe ?? Se,
|
|
86
87
|
status: a.status,
|
|
87
|
-
hasFeedback:
|
|
88
|
+
hasFeedback: w,
|
|
88
89
|
className: se,
|
|
89
90
|
style: ce,
|
|
90
|
-
hidden:
|
|
91
|
+
hidden: C,
|
|
91
92
|
fieldId: t,
|
|
92
93
|
fieldHandle: i,
|
|
93
|
-
htmlFor:
|
|
94
|
+
htmlFor: pe,
|
|
94
95
|
errors: J,
|
|
95
96
|
warnings: Y,
|
|
96
|
-
children: /* @__PURE__ */
|
|
97
|
-
value:
|
|
97
|
+
children: /* @__PURE__ */ f(o.Provider, {
|
|
98
|
+
value: Ae,
|
|
98
99
|
children: e
|
|
99
100
|
})
|
|
100
101
|
})
|
|
101
102
|
});
|
|
102
|
-
}, Z =
|
|
103
|
-
if (!Z && !Q && !
|
|
103
|
+
}, Z = p != null, Q = typeof T == "function";
|
|
104
|
+
if (!Z && !Q && !D) return X(T);
|
|
104
105
|
let $ = {};
|
|
105
|
-
return typeof
|
|
106
|
+
return typeof m == "string" ? $.label = m : p && ($.label = String(p)), k && ($ = {
|
|
106
107
|
...$,
|
|
107
|
-
...
|
|
108
|
-
}), /* @__PURE__ */
|
|
108
|
+
...k
|
|
109
|
+
}), /* @__PURE__ */ f(c, {
|
|
109
110
|
...P,
|
|
110
|
-
name:
|
|
111
|
-
rules:
|
|
112
|
-
dependencies:
|
|
113
|
-
shouldUpdate:
|
|
111
|
+
name: p,
|
|
112
|
+
rules: E,
|
|
113
|
+
dependencies: D,
|
|
114
|
+
shouldUpdate: O,
|
|
114
115
|
messageVariables: $,
|
|
115
|
-
trigger:
|
|
116
|
-
validateTrigger:
|
|
117
|
-
onMetaChange:
|
|
116
|
+
trigger: A,
|
|
117
|
+
validateTrigger: W,
|
|
118
|
+
onMetaChange: ke,
|
|
118
119
|
children: (e, t, n) => {
|
|
119
|
-
let r = s(
|
|
120
|
-
if (Q && (
|
|
121
|
-
else if (
|
|
122
|
-
let t =
|
|
120
|
+
let r = s(p).length ? t.name : [], i = h(r, _e), a = x === void 0 ? ie(E, n) : x, o = null;
|
|
121
|
+
if (Q && (O || D) && !Z) o = T(n);
|
|
122
|
+
else if (u.isValidElement(T)) {
|
|
123
|
+
let t = T, n = {
|
|
123
124
|
...t.props,
|
|
124
125
|
...e
|
|
125
126
|
};
|
|
126
|
-
n.id ||= i, r.length && (n["data-uic-field-id"] = r.join("_")),
|
|
127
|
+
n.id ||= i, r.length && (n["data-uic-field-id"] = r.join("_")), ve && n.disabled === void 0 && (n.disabled = !0);
|
|
127
128
|
let c = [];
|
|
128
|
-
(
|
|
129
|
+
(b || J.length > 0) && c.push(`${i}_help`), y && c.push(`${i}_extra`), c.length && (n["aria-describedby"] = c.join(" ")), J.length > 0 && (n["aria-invalid"] = "true"), a && (n["aria-required"] = "true"), (/* @__PURE__ */ new Set([...s(A), ...s(W)])).forEach((r) => {
|
|
129
130
|
n[r] = (...n) => {
|
|
130
131
|
e[r]?.(...n), t.props[r]?.(...n);
|
|
131
132
|
};
|
|
132
|
-
}), o =
|
|
133
|
-
} else o =
|
|
133
|
+
}), o = u.cloneElement(t, n);
|
|
134
|
+
} else o = T;
|
|
134
135
|
return X(o, i, a, r.length ? r.join("_") : void 0);
|
|
135
136
|
}
|
|
136
137
|
});
|
|
@@ -145,13 +146,13 @@ function ie(e, t) {
|
|
|
145
146
|
});
|
|
146
147
|
}
|
|
147
148
|
function ae(e, t, n, r) {
|
|
148
|
-
return e == null ? e : typeof n == "function" ? n(e, { required: t }) : n === "optional" && !t ? /* @__PURE__ */
|
|
149
|
+
return e == null ? e : typeof n == "function" ? n(e, { required: t }) : n === "optional" && !t ? /* @__PURE__ */ p(d, { children: [e, /* @__PURE__ */ f("span", {
|
|
149
150
|
className: "uic-form-item__optional",
|
|
150
151
|
children: r
|
|
151
152
|
})] }) : e;
|
|
152
153
|
}
|
|
153
154
|
var y = () => {
|
|
154
|
-
let { status: e, errors: t = [], warnings: n = [] } =
|
|
155
|
+
let { status: e, errors: t = [], warnings: n = [] } = u.useContext(r);
|
|
155
156
|
return {
|
|
156
157
|
status: e,
|
|
157
158
|
errors: t,
|
|
@@ -159,6 +160,6 @@ var y = () => {
|
|
|
159
160
|
};
|
|
160
161
|
};
|
|
161
162
|
//#endregion
|
|
162
|
-
export { v as default,
|
|
163
|
+
export { v as default, h as getFieldId, y as useFormItemStatus };
|
|
163
164
|
|
|
164
165
|
//# sourceMappingURL=FormItem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormItem.js","names":[],"sources":["../../../src/components/Form/FormItem.tsx"],"sourcesContent":["/**\n * `Form.Item`: the visual shell (`FormItemVisual`) bound to a `Field`.\n *\n * Four behaviours are load-bearing:\n *\n * 1. `required` is not derived from `rules` naively. Function rules\n * (`({ getFieldValue }) => ({ required: … })`) are evaluated against the\n * live form to decide whether the marker shows; a `warningOnly` required\n * rule does not show it.\n * 2. Layout-only items aggregate their children's errors. An item with no\n * `name` wrapping `noStyle` children collects their metas through\n * `NoStyleItemContext`; without it their messages disappear.\n * 3. `help={false}` opts out of bubbling, so a nested item that renders its\n * own help does not report into an ancestor as well.\n * 4. `noStyle` is a pure passthrough: state only, no shell.\n */\nimport Field, { type FieldProps } from \"./Field\";\nimport FormItemVisual from \"./FormItemVisual\";\nimport {\n FieldContext,\n FormConfigContext,\n FormItemInputContext,\n FormItemLayoutContext,\n ListContext,\n NoStyleItemContext,\n type FormItemCol,\n type FormItemStatusContextValue,\n type FormLayout,\n type RequiredMark,\n} from \"./context\";\nimport type {\n InternalFormInstance,\n Meta,\n Rule,\n RuleObject,\n StoreValue,\n} from \"./interface\";\nimport { toArray, type InternalNamePath, type NamePath } from \"./namePath\";\nimport * as React from \"react\";\n\nimport { useUicTranslator } from \"../../i18n/useUicTranslator\";\n\nconst NAME_SPLIT = \"__SPLIT__\";\n\n/** antd's id scheme: `formName_a_b`, with a guard for a reserved DOM name. */\nconst ID_BLACKLIST = [\"parentNode\"];\nfunction getFieldId(namePath: InternalNamePath, formName?: string): string | undefined {\n if (!namePath.length) return undefined;\n const mergedId = namePath.join(\"_\");\n if (formName) return `${formName}_${mergedId}`;\n return ID_BLACKLIST.includes(mergedId) ? `form_item_${mergedId}` : mergedId;\n}\n\nfunction genEmptyMeta(): Meta {\n return {\n errors: [],\n warnings: [],\n touched: false,\n validating: false,\n name: [],\n validated: false,\n };\n}\n\nfunction getStatus(\n errors: React.ReactNode[],\n warnings: React.ReactNode[],\n meta: Meta,\n hasFeedback?: boolean,\n validateStatus?: FormItemStatusContextValue[\"status\"],\n): FormItemStatusContextValue[\"status\"] {\n if (validateStatus !== undefined) return validateStatus;\n if (meta.validating) return \"validating\";\n if (errors.length) return \"error\";\n if (warnings.length) return \"warning\";\n if (meta.touched || (hasFeedback && meta.validated)) return \"success\";\n return \"\";\n}\n\nexport interface FormItemProps<Values = any> extends Omit<\n FieldProps,\n \"children\" | \"name\" | \"onMetaChange\" | \"isList\"\n> {\n name?: NamePath;\n label?: React.ReactNode;\n /**\n * A node, or antd's `{ title, icon, placement, ... }` object form. `title`\n * becomes the tooltip body and `icon` the trigger glyph, rendered behind a\n * hover/focus target after the label. The other keys describe antd's\n * overlay and are ignored.\n */\n tooltip?: React.ReactNode | FormItemTooltipConfig;\n extra?: React.ReactNode;\n /** `false` also suppresses meta bubbling to an ancestor item. */\n help?: React.ReactNode;\n /** Overrides the asterisk derived from `rules`. */\n required?: boolean;\n /** Render no wrapper; bubble this field's meta to the nearest ancestor item. */\n noStyle?: boolean;\n hidden?: boolean;\n layout?: FormLayout;\n className?: string;\n style?: React.CSSProperties;\n hasFeedback?: boolean;\n validateStatus?: FormItemStatusContextValue[\"status\"];\n colon?: boolean;\n labelAlign?: \"left\" | \"right\";\n labelCol?: FormItemCol;\n wrapperCol?: FormItemCol;\n labelWrap?: boolean;\n htmlFor?: string;\n id?: string;\n fieldKey?: React.Key | React.Key[];\n children?: React.ReactNode | ((form: InternalFormInstance) => React.ReactNode);\n __values?: Values;\n}\n\nexport interface FormItemTooltipConfig {\n title?: React.ReactNode;\n icon?: React.ReactNode;\n placement?: string;\n [key: string]: unknown;\n}\n\nconst isTooltipConfig = (\n tooltip: FormItemProps[\"tooltip\"],\n): tooltip is FormItemTooltipConfig =>\n !!tooltip &&\n typeof tooltip === \"object\" &&\n !React.isValidElement(tooltip) &&\n \"title\" in tooltip;\n\n/** The tooltip BODY — antd's `tooltip` node, or the config object's `title`. */\nfunction normalizeTooltip(tooltip: FormItemProps[\"tooltip\"]): React.ReactNode {\n return isTooltipConfig(tooltip) ? tooltip.title : (tooltip as React.ReactNode);\n}\n\n/** The tooltip TRIGGER glyph — antd's `tooltip.icon`, when supplied. */\nfunction tooltipIcon(tooltip: FormItemProps[\"tooltip\"]): React.ReactNode {\n return isTooltipConfig(tooltip) ? tooltip.icon : undefined;\n}\n\ntype SubMetaMap = Record<\n string,\n {\n errors?: React.ReactNode[];\n warnings?: React.ReactNode[];\n name?: InternalNamePath;\n }\n>;\n\nconst FormItem = <Values,>(props: FormItemProps<Values>) => {\n const {\n name,\n label,\n tooltip,\n extra,\n help,\n required,\n noStyle,\n hidden,\n layout: propsLayout,\n className,\n style,\n hasFeedback,\n validateStatus,\n children,\n rules,\n dependencies,\n shouldUpdate,\n messageVariables,\n trigger = \"onChange\",\n validateTrigger,\n colon,\n labelAlign,\n labelCol,\n wrapperCol,\n labelWrap,\n htmlFor,\n fieldKey: _fieldKey,\n id: _id,\n __values: _values,\n ...restFieldProps\n } = props;\n\n const fieldContext = React.useContext(FieldContext);\n const { optionalLabel } = React.useContext(FormConfigContext);\n const t = useUicTranslator();\n const {\n layout: formLayout,\n requiredMark,\n name: formName,\n disabled: formDisabled,\n size: formSize,\n colon: formColon,\n labelAlign: formLabelAlign,\n labelCol: formLabelCol,\n wrapperCol: formWrapperCol,\n labelWrap: formLabelWrap,\n } = React.useContext(FormItemLayoutContext);\n const notifyParentMetaChange = React.useContext(NoStyleItemContext);\n const listContext = React.useContext(ListContext);\n\n const layout = propsLayout || formLayout;\n const mergedLabelCol = labelCol ?? formLabelCol;\n const mergedWrapperColProp = wrapperCol ?? formWrapperCol;\n /**\n * antd's `FormItemInput`: a LABEL-LESS item in a form that declares a\n * `labelCol` gets that span as a wrapper OFFSET, so its control still lines\n * up with the labelled rows above it.\n */\n const mergedWrapperCol =\n label === null &&\n !labelCol &&\n !wrapperCol &&\n formLabelCol?.span !== undefined &&\n formLabelCol.span < 24\n ? { ...mergedWrapperColProp, offset: formLabelCol.span }\n : mergedWrapperColProp;\n const mergedValidateTrigger =\n validateTrigger !== undefined ? validateTrigger : fieldContext.validateTrigger;\n\n const [meta, setMeta] = React.useState<Meta>(genEmptyMeta);\n const [subFieldErrors, setSubFieldErrors] = React.useState<SubMetaMap>({});\n // A removed list row no longer resolves through the key manager, so the\n // path used to unpublish it has to be the one we published under.\n const fieldKeyPathRef = React.useRef<InternalNamePath | null>(null);\n\n const onMetaChange = (nextMeta: Meta & { destroy?: boolean }) => {\n const keyInfo = listContext?.getKey(nextMeta.name);\n setMeta(nextMeta.destroy ? genEmptyMeta() : nextMeta);\n\n if (noStyle && help !== false && notifyParentMetaChange) {\n let namePath: InternalNamePath = nextMeta.name;\n if (!nextMeta.destroy) {\n if (keyInfo !== undefined) {\n const [fieldKey, restPath] = keyInfo;\n namePath = [fieldKey as string | number, ...restPath];\n fieldKeyPathRef.current = namePath;\n }\n } else {\n namePath = fieldKeyPathRef.current || namePath;\n }\n notifyParentMetaChange(nextMeta, namePath as React.Key[]);\n }\n };\n\n const onSubItemMetaChange = (\n subMeta: SubMetaMap[string] & { name: InternalNamePath; destroy?: boolean },\n uniqueKeys: React.Key[],\n ) => {\n setSubFieldErrors((prev) => {\n const clone = { ...prev };\n // name: ['user', 1] + key: [4] => 'user__SPLIT__4' — keyed by ROW\n // IDENTITY, so removing a list row drops the right entry.\n const mergedNameKey = [...subMeta.name.slice(0, -1), ...uniqueKeys].join(\n NAME_SPLIT,\n );\n if (subMeta.destroy) {\n delete clone[mergedNameKey];\n } else {\n clone[mergedNameKey] = subMeta;\n }\n return clone;\n });\n };\n\n const mergedErrors: React.ReactNode[] = [\n ...meta.errors,\n ...Object.values(subFieldErrors).flatMap((sub) => sub.errors ?? []),\n ];\n const mergedWarnings: React.ReactNode[] = [\n ...meta.warnings,\n ...Object.values(subFieldErrors).flatMap((sub) => sub.warnings ?? []),\n ];\n\n const renderLayout = (\n baseChildren: React.ReactNode,\n fieldId?: string,\n isRequired?: boolean,\n fieldHandle?: string,\n ) => {\n const status: FormItemStatusContextValue = {\n status: getStatus(\n mergedErrors,\n mergedWarnings,\n meta,\n hasFeedback,\n validateStatus,\n ),\n errors: mergedErrors,\n warnings: mergedWarnings,\n hasFeedback,\n isFormItemInput: true,\n };\n\n // A `noStyle` item contributes state only. Its errors were already sent\n // upward through `notifyParentMetaChange`.\n if (noStyle && !hidden) {\n return (\n <FormItemInputContext.Provider value={status}>\n {baseChildren}\n </FormItemInputContext.Provider>\n );\n }\n\n // antd keeps `-required` on the label in every case and hides the GLYPH\n // for `false` / `'optional'` / a function mark, because the label itself\n // then carries the hint. Mirrored so `.uic-form-item__label--required`\n // stays a stable anchor while the asterisk obeys the same rule.\n const requiredMarkType =\n requiredMark === false\n ? (\"hidden\" as const)\n : requiredMark === \"optional\" || typeof requiredMark === \"function\"\n ? (\"optional\" as const)\n : undefined;\n // An explicit `required` wins over the rules-derived value, and it is the\n // ONLY source on a layout-only item (no `name`, so no rules to derive\n // from). `BulkEditFormItem` renders exactly that shape — it drops\n // `name` from the item and drives the marker by hand.\n const mergedRequired = required !== undefined ? required : !!isRequired;\n const mergedLabel = applyRequiredMark(\n label,\n mergedRequired,\n requiredMark,\n optionalLabel ?? t(\"uic.Form.optional\"),\n );\n\n return (\n <FormItemInputContext.Provider value={status}>\n <FormItemVisual\n label={mergedLabel}\n labelTitle={typeof label === \"string\" ? label : undefined}\n tooltip={normalizeTooltip(tooltip)}\n tooltipIcon={tooltipIcon(tooltip)}\n extra={extra}\n help={help}\n required={mergedRequired}\n requiredMarkType={requiredMarkType}\n layout={layout}\n size={formSize}\n colon={colon ?? formColon}\n labelAlign={labelAlign ?? formLabelAlign}\n labelCol={mergedLabelCol}\n wrapperCol={mergedWrapperCol}\n labelWrap={labelWrap ?? formLabelWrap}\n status={status.status}\n hasFeedback={hasFeedback}\n className={className}\n style={style}\n hidden={hidden}\n fieldId={fieldId}\n fieldHandle={fieldHandle}\n htmlFor={htmlFor}\n errors={mergedErrors}\n warnings={mergedWarnings}\n >\n <NoStyleItemContext.Provider value={onSubItemMetaChange}>\n {baseChildren}\n </NoStyleItemContext.Provider>\n </FormItemVisual>\n </FormItemInputContext.Provider>\n );\n };\n\n const hasName = name !== undefined && name !== null;\n const isRenderProps = typeof children === \"function\";\n\n // Pure layout item: no field is registered, but the shell still renders and\n // still aggregates the `noStyle` children nested inside it.\n if (!hasName && !isRenderProps && !dependencies) {\n return renderLayout(children as React.ReactNode);\n }\n\n // `${label}` in a validate message resolves to the item's label when it is\n // a plain string, else to its name — matching antd's `messageVariables`.\n let variables: Record<string, string> = {};\n if (typeof label === \"string\") {\n variables.label = label;\n } else if (name) {\n variables.label = String(name);\n }\n if (messageVariables) {\n variables = { ...variables, ...messageVariables };\n }\n\n return (\n <Field\n {...restFieldProps}\n name={name}\n rules={rules}\n dependencies={dependencies}\n shouldUpdate={shouldUpdate}\n messageVariables={variables}\n trigger={trigger}\n validateTrigger={mergedValidateTrigger}\n onMetaChange={onMetaChange}\n >\n {(control, renderMeta, context) => {\n const mergedName = toArray(name as any).length ? renderMeta.name : [];\n const fieldId = getFieldId(mergedName, formName);\n const isRequired =\n required !== undefined ? required : isRuleRequired(rules, context);\n\n let childNode: React.ReactNode = null;\n\n if (isRenderProps && (shouldUpdate || dependencies) && !hasName) {\n childNode = (children as (form: InternalFormInstance) => React.ReactNode)(\n context,\n );\n } else if (React.isValidElement(children)) {\n const element = children as React.ReactElement<Record<string, any>>;\n const childProps: Record<string, any> = {\n ...element.props,\n ...control,\n };\n if (!childProps.id) {\n childProps.id = fieldId;\n }\n // Astryx controls replace `id` with their own `useId()` but pass\n // `data-*` through; this is what `FormStore.getFieldDOMNode` finds.\n if (mergedName.length) {\n childProps[\"data-uic-field-id\"] = mergedName.join(\"_\");\n }\n if (formDisabled && childProps.disabled === undefined) {\n childProps.disabled = true;\n }\n\n const describedbyArr: string[] = [];\n if (help || mergedErrors.length > 0) {\n describedbyArr.push(`${fieldId}_help`);\n }\n if (extra) {\n describedbyArr.push(`${fieldId}_extra`);\n }\n if (describedbyArr.length) {\n childProps[\"aria-describedby\"] = describedbyArr.join(\" \");\n }\n if (mergedErrors.length > 0) {\n childProps[\"aria-invalid\"] = \"true\";\n }\n if (isRequired) {\n childProps[\"aria-required\"] = \"true\";\n }\n\n // Keep the child's own handlers: `control[trigger]` writes to the\n // store, then the author's handler runs.\n const triggers = new Set<string>([\n ...toArray(trigger),\n ...toArray(mergedValidateTrigger as string | string[]),\n ]);\n triggers.forEach((eventName) => {\n childProps[eventName] = (...args: any[]) => {\n control[eventName]?.(...args);\n (element.props as any)[eventName]?.(...args);\n };\n });\n\n childNode = React.cloneElement(element, childProps);\n } else {\n childNode = children as React.ReactNode;\n }\n\n return renderLayout(\n childNode,\n fieldId,\n isRequired,\n mergedName.length ? mergedName.join(\"_\") : undefined,\n );\n }}\n </Field>\n );\n};\n\n/**\n * Evaluate `rules` — INCLUDING function rules, against the live form — to\n * decide whether the required marker shows. A `warningOnly` required rule\n * does not count: it is advice, not a requirement.\n */\nfunction isRuleRequired(\n rules: Rule[] | undefined,\n form: InternalFormInstance,\n): boolean {\n return !!rules?.some((rule) => {\n if (typeof rule === \"function\") {\n const resolved = rule(form) as RuleObject | undefined;\n return !!resolved?.required && !resolved?.warningOnly;\n }\n return !!rule?.required && !rule?.warningOnly;\n });\n}\n\n/**\n * `requiredMark` decorates the LABEL. A function or `'optional'` mark replaces\n * the asterisk entirely, as in antd: the label itself then carries the hint.\n */\nfunction applyRequiredMark(\n label: React.ReactNode,\n required: boolean,\n requiredMark: RequiredMark | undefined,\n optionalLabel: React.ReactNode,\n): React.ReactNode {\n if (label === undefined || label === null) return label;\n if (typeof requiredMark === \"function\") {\n return requiredMark(label, { required });\n }\n if (requiredMark === \"optional\" && !required) {\n // antd renders the bare locale string and spaces it with\n // `margin-inline-start: marginXXS`, so the gap survives text selection and\n // copy. The engine had baked a literal leading space into the string,\n // which put \" (optional)\" in `label.textContent` where antd has\n // \"(optional)\".\n return (\n <>\n {label}\n <span className=\"uic-form-item__optional\">{optionalLabel}</span>\n </>\n );\n }\n return label;\n}\n\n/** Errors/warnings of the nearest enclosing `Form.Item`. */\nexport const useFormItemStatus = () => {\n const { status, errors = [], warnings = [] } = React.useContext(FormItemInputContext);\n return { status, errors, warnings };\n};\n\nexport { getFieldId };\nexport default FormItem;\nexport type { StoreValue };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FormItem.js","names":[],"sources":["../../../src/components/Form/FormItem.tsx"],"sourcesContent":["/**\n * `Form.Item`: the visual shell (`FormItemVisual`) bound to a `Field`.\n *\n * Four behaviours are load-bearing:\n *\n * 1. `required` is not derived from `rules` naively. Function rules\n * (`({ getFieldValue }) => ({ required: … })`) are evaluated against the\n * live form to decide whether the marker shows; a `warningOnly` required\n * rule does not show it.\n * 2. Layout-only items aggregate their children's errors. An item with no\n * `name` wrapping `noStyle` children collects their metas through\n * `NoStyleItemContext`; without it their messages disappear.\n * 3. `help={false}` opts out of bubbling, so a nested item that renders its\n * own help does not report into an ancestor as well.\n * 4. `noStyle` is a pure passthrough: state only, no shell.\n */\nimport Field, { type FieldProps } from \"./Field\";\nimport FormItemVisual from \"./FormItemVisual\";\nimport {\n FieldContext,\n FormConfigContext,\n FormItemInputContext,\n FormItemLayoutContext,\n ListContext,\n NoStyleItemContext,\n type FormItemCol,\n type FormItemStatusContextValue,\n type FormLayout,\n type RequiredMark,\n} from \"./context\";\nimport type {\n InternalFormInstance,\n Meta,\n Rule,\n RuleObject,\n StoreValue,\n} from \"./interface\";\nimport { toArray, type InternalNamePath, type NamePath } from \"./namePath\";\nimport * as React from \"react\";\n\nimport { useUicTranslator } from \"../../i18n/useUicTranslator\";\n\nconst NAME_SPLIT = \"__SPLIT__\";\n\n/** antd's id scheme: `formName_a_b`, with a guard for a reserved DOM name. */\nconst ID_BLACKLIST = [\"parentNode\"];\nfunction getFieldId(namePath: InternalNamePath, formName?: string): string | undefined {\n if (!namePath.length) return undefined;\n const mergedId = namePath.join(\"_\");\n if (formName) return `${formName}_${mergedId}`;\n return ID_BLACKLIST.includes(mergedId) ? `form_item_${mergedId}` : mergedId;\n}\n\nfunction genEmptyMeta(): Meta {\n return {\n errors: [],\n warnings: [],\n touched: false,\n validating: false,\n name: [],\n validated: false,\n };\n}\n\nfunction getStatus(\n errors: React.ReactNode[],\n warnings: React.ReactNode[],\n meta: Meta,\n hasFeedback?: boolean,\n validateStatus?: FormItemStatusContextValue[\"status\"],\n): FormItemStatusContextValue[\"status\"] {\n if (validateStatus !== undefined) return validateStatus;\n if (meta.validating) return \"validating\";\n if (errors.length) return \"error\";\n if (warnings.length) return \"warning\";\n if (meta.touched || (hasFeedback && meta.validated)) return \"success\";\n return \"\";\n}\n\nexport interface FormItemProps<Values = any> extends Omit<\n FieldProps,\n \"children\" | \"name\" | \"onMetaChange\" | \"isList\"\n> {\n name?: NamePath;\n label?: React.ReactNode;\n /**\n * A node, or antd's `{ title, icon, placement, ... }` object form. `title`\n * becomes the tooltip body and `icon` the trigger glyph, rendered behind a\n * hover/focus target after the label. The other keys describe antd's\n * overlay and are ignored.\n */\n tooltip?: React.ReactNode | FormItemTooltipConfig;\n /**\n * Actions for the label row: far end in vertical layout, right after the\n * label in horizontal / inline layout. Needs a `label`.\n */\n labelExtra?: React.ReactNode;\n extra?: React.ReactNode;\n /** `false` also suppresses meta bubbling to an ancestor item. */\n help?: React.ReactNode;\n /** Overrides the asterisk derived from `rules`. */\n required?: boolean;\n /** Render no wrapper; bubble this field's meta to the nearest ancestor item. */\n noStyle?: boolean;\n hidden?: boolean;\n layout?: FormLayout;\n className?: string;\n style?: React.CSSProperties;\n hasFeedback?: boolean;\n validateStatus?: FormItemStatusContextValue[\"status\"];\n colon?: boolean;\n labelAlign?: \"left\" | \"right\";\n labelCol?: FormItemCol;\n wrapperCol?: FormItemCol;\n labelWrap?: boolean;\n htmlFor?: string;\n id?: string;\n fieldKey?: React.Key | React.Key[];\n children?: React.ReactNode | ((form: InternalFormInstance) => React.ReactNode);\n __values?: Values;\n}\n\nexport interface FormItemTooltipConfig {\n title?: React.ReactNode;\n icon?: React.ReactNode;\n placement?: string;\n [key: string]: unknown;\n}\n\nconst isTooltipConfig = (\n tooltip: FormItemProps[\"tooltip\"],\n): tooltip is FormItemTooltipConfig =>\n !!tooltip &&\n typeof tooltip === \"object\" &&\n !React.isValidElement(tooltip) &&\n \"title\" in tooltip;\n\n/** The tooltip BODY — antd's `tooltip` node, or the config object's `title`. */\nfunction normalizeTooltip(tooltip: FormItemProps[\"tooltip\"]): React.ReactNode {\n return isTooltipConfig(tooltip) ? tooltip.title : (tooltip as React.ReactNode);\n}\n\n/** The tooltip TRIGGER glyph — antd's `tooltip.icon`, when supplied. */\nfunction tooltipIcon(tooltip: FormItemProps[\"tooltip\"]): React.ReactNode {\n return isTooltipConfig(tooltip) ? tooltip.icon : undefined;\n}\n\ntype SubMetaMap = Record<\n string,\n {\n errors?: React.ReactNode[];\n warnings?: React.ReactNode[];\n name?: InternalNamePath;\n }\n>;\n\nconst FormItem = <Values,>(props: FormItemProps<Values>) => {\n const {\n name,\n label,\n tooltip,\n labelExtra,\n extra,\n help,\n required,\n noStyle,\n hidden,\n layout: propsLayout,\n className,\n style,\n hasFeedback,\n validateStatus,\n children,\n rules,\n dependencies,\n shouldUpdate,\n messageVariables,\n trigger = \"onChange\",\n validateTrigger,\n colon,\n labelAlign,\n labelCol,\n wrapperCol,\n labelWrap,\n htmlFor,\n fieldKey: _fieldKey,\n id: _id,\n __values: _values,\n ...restFieldProps\n } = props;\n\n const fieldContext = React.useContext(FieldContext);\n const { optionalLabel } = React.useContext(FormConfigContext);\n const t = useUicTranslator();\n const {\n layout: formLayout,\n requiredMark,\n name: formName,\n disabled: formDisabled,\n size: formSize,\n colon: formColon,\n labelAlign: formLabelAlign,\n labelCol: formLabelCol,\n wrapperCol: formWrapperCol,\n labelWrap: formLabelWrap,\n } = React.useContext(FormItemLayoutContext);\n const notifyParentMetaChange = React.useContext(NoStyleItemContext);\n const listContext = React.useContext(ListContext);\n\n const layout = propsLayout || formLayout;\n const mergedLabelCol = labelCol ?? formLabelCol;\n const mergedWrapperColProp = wrapperCol ?? formWrapperCol;\n /**\n * antd's `FormItemInput`: a LABEL-LESS item in a form that declares a\n * `labelCol` gets that span as a wrapper OFFSET, so its control still lines\n * up with the labelled rows above it.\n */\n const mergedWrapperCol =\n label === null &&\n !labelCol &&\n !wrapperCol &&\n formLabelCol?.span !== undefined &&\n formLabelCol.span < 24\n ? { ...mergedWrapperColProp, offset: formLabelCol.span }\n : mergedWrapperColProp;\n const mergedValidateTrigger =\n validateTrigger !== undefined ? validateTrigger : fieldContext.validateTrigger;\n\n const [meta, setMeta] = React.useState<Meta>(genEmptyMeta);\n const [subFieldErrors, setSubFieldErrors] = React.useState<SubMetaMap>({});\n // A removed list row no longer resolves through the key manager, so the\n // path used to unpublish it has to be the one we published under.\n const fieldKeyPathRef = React.useRef<InternalNamePath | null>(null);\n\n const onMetaChange = (nextMeta: Meta & { destroy?: boolean }) => {\n const keyInfo = listContext?.getKey(nextMeta.name);\n setMeta(nextMeta.destroy ? genEmptyMeta() : nextMeta);\n\n if (noStyle && help !== false && notifyParentMetaChange) {\n let namePath: InternalNamePath = nextMeta.name;\n if (!nextMeta.destroy) {\n if (keyInfo !== undefined) {\n const [fieldKey, restPath] = keyInfo;\n namePath = [fieldKey as string | number, ...restPath];\n fieldKeyPathRef.current = namePath;\n }\n } else {\n namePath = fieldKeyPathRef.current || namePath;\n }\n notifyParentMetaChange(nextMeta, namePath as React.Key[]);\n }\n };\n\n const onSubItemMetaChange = (\n subMeta: SubMetaMap[string] & { name: InternalNamePath; destroy?: boolean },\n uniqueKeys: React.Key[],\n ) => {\n setSubFieldErrors((prev) => {\n const clone = { ...prev };\n // name: ['user', 1] + key: [4] => 'user__SPLIT__4' — keyed by ROW\n // IDENTITY, so removing a list row drops the right entry.\n const mergedNameKey = [...subMeta.name.slice(0, -1), ...uniqueKeys].join(\n NAME_SPLIT,\n );\n if (subMeta.destroy) {\n delete clone[mergedNameKey];\n } else {\n clone[mergedNameKey] = subMeta;\n }\n return clone;\n });\n };\n\n const mergedErrors: React.ReactNode[] = [\n ...meta.errors,\n ...Object.values(subFieldErrors).flatMap((sub) => sub.errors ?? []),\n ];\n const mergedWarnings: React.ReactNode[] = [\n ...meta.warnings,\n ...Object.values(subFieldErrors).flatMap((sub) => sub.warnings ?? []),\n ];\n\n const renderLayout = (\n baseChildren: React.ReactNode,\n fieldId?: string,\n isRequired?: boolean,\n fieldHandle?: string,\n ) => {\n const status: FormItemStatusContextValue = {\n status: getStatus(\n mergedErrors,\n mergedWarnings,\n meta,\n hasFeedback,\n validateStatus,\n ),\n errors: mergedErrors,\n warnings: mergedWarnings,\n hasFeedback,\n isFormItemInput: true,\n };\n\n // A `noStyle` item contributes state only. Its errors were already sent\n // upward through `notifyParentMetaChange`.\n if (noStyle && !hidden) {\n return (\n <FormItemInputContext.Provider value={status}>\n {baseChildren}\n </FormItemInputContext.Provider>\n );\n }\n\n // antd keeps `-required` on the label in every case and hides the GLYPH\n // for `false` / `'optional'` / a function mark, because the label itself\n // then carries the hint. Mirrored so `.uic-form-item__label--required`\n // stays a stable anchor while the asterisk obeys the same rule.\n const requiredMarkType =\n requiredMark === false\n ? (\"hidden\" as const)\n : requiredMark === \"optional\" || typeof requiredMark === \"function\"\n ? (\"optional\" as const)\n : undefined;\n // An explicit `required` wins over the rules-derived value, and it is the\n // ONLY source on a layout-only item (no `name`, so no rules to derive\n // from). `BulkEditFormItem` renders exactly that shape — it drops\n // `name` from the item and drives the marker by hand.\n const mergedRequired = required !== undefined ? required : !!isRequired;\n const mergedLabel = applyRequiredMark(\n label,\n mergedRequired,\n requiredMark,\n optionalLabel ?? t(\"uic.Form.optional\"),\n );\n\n return (\n <FormItemInputContext.Provider value={status}>\n <FormItemVisual\n label={mergedLabel}\n labelTitle={typeof label === \"string\" ? label : undefined}\n tooltip={normalizeTooltip(tooltip)}\n tooltipIcon={tooltipIcon(tooltip)}\n labelExtra={labelExtra}\n extra={extra}\n help={help}\n required={mergedRequired}\n requiredMarkType={requiredMarkType}\n layout={layout}\n size={formSize}\n colon={colon ?? formColon}\n labelAlign={labelAlign ?? formLabelAlign}\n labelCol={mergedLabelCol}\n wrapperCol={mergedWrapperCol}\n labelWrap={labelWrap ?? formLabelWrap}\n status={status.status}\n hasFeedback={hasFeedback}\n className={className}\n style={style}\n hidden={hidden}\n fieldId={fieldId}\n fieldHandle={fieldHandle}\n htmlFor={htmlFor}\n errors={mergedErrors}\n warnings={mergedWarnings}\n >\n <NoStyleItemContext.Provider value={onSubItemMetaChange}>\n {baseChildren}\n </NoStyleItemContext.Provider>\n </FormItemVisual>\n </FormItemInputContext.Provider>\n );\n };\n\n const hasName = name !== undefined && name !== null;\n const isRenderProps = typeof children === \"function\";\n\n // Pure layout item: no field is registered, but the shell still renders and\n // still aggregates the `noStyle` children nested inside it.\n if (!hasName && !isRenderProps && !dependencies) {\n return renderLayout(children as React.ReactNode);\n }\n\n // `${label}` in a validate message resolves to the item's label when it is\n // a plain string, else to its name — matching antd's `messageVariables`.\n let variables: Record<string, string> = {};\n if (typeof label === \"string\") {\n variables.label = label;\n } else if (name) {\n variables.label = String(name);\n }\n if (messageVariables) {\n variables = { ...variables, ...messageVariables };\n }\n\n return (\n <Field\n {...restFieldProps}\n name={name}\n rules={rules}\n dependencies={dependencies}\n shouldUpdate={shouldUpdate}\n messageVariables={variables}\n trigger={trigger}\n validateTrigger={mergedValidateTrigger}\n onMetaChange={onMetaChange}\n >\n {(control, renderMeta, context) => {\n const mergedName = toArray(name as any).length ? renderMeta.name : [];\n const fieldId = getFieldId(mergedName, formName);\n const isRequired =\n required !== undefined ? required : isRuleRequired(rules, context);\n\n let childNode: React.ReactNode = null;\n\n if (isRenderProps && (shouldUpdate || dependencies) && !hasName) {\n childNode = (children as (form: InternalFormInstance) => React.ReactNode)(\n context,\n );\n } else if (React.isValidElement(children)) {\n const element = children as React.ReactElement<Record<string, any>>;\n const childProps: Record<string, any> = {\n ...element.props,\n ...control,\n };\n if (!childProps.id) {\n childProps.id = fieldId;\n }\n // Astryx controls replace `id` with their own `useId()` but pass\n // `data-*` through; this is what `FormStore.getFieldDOMNode` finds.\n if (mergedName.length) {\n childProps[\"data-uic-field-id\"] = mergedName.join(\"_\");\n }\n if (formDisabled && childProps.disabled === undefined) {\n childProps.disabled = true;\n }\n\n const describedbyArr: string[] = [];\n if (help || mergedErrors.length > 0) {\n describedbyArr.push(`${fieldId}_help`);\n }\n if (extra) {\n describedbyArr.push(`${fieldId}_extra`);\n }\n if (describedbyArr.length) {\n childProps[\"aria-describedby\"] = describedbyArr.join(\" \");\n }\n if (mergedErrors.length > 0) {\n childProps[\"aria-invalid\"] = \"true\";\n }\n if (isRequired) {\n childProps[\"aria-required\"] = \"true\";\n }\n\n // Keep the child's own handlers: `control[trigger]` writes to the\n // store, then the author's handler runs.\n const triggers = new Set<string>([\n ...toArray(trigger),\n ...toArray(mergedValidateTrigger as string | string[]),\n ]);\n triggers.forEach((eventName) => {\n childProps[eventName] = (...args: any[]) => {\n control[eventName]?.(...args);\n (element.props as any)[eventName]?.(...args);\n };\n });\n\n childNode = React.cloneElement(element, childProps);\n } else {\n childNode = children as React.ReactNode;\n }\n\n return renderLayout(\n childNode,\n fieldId,\n isRequired,\n mergedName.length ? mergedName.join(\"_\") : undefined,\n );\n }}\n </Field>\n );\n};\n\n/**\n * Evaluate `rules` — INCLUDING function rules, against the live form — to\n * decide whether the required marker shows. A `warningOnly` required rule\n * does not count: it is advice, not a requirement.\n */\nfunction isRuleRequired(\n rules: Rule[] | undefined,\n form: InternalFormInstance,\n): boolean {\n return !!rules?.some((rule) => {\n if (typeof rule === \"function\") {\n const resolved = rule(form) as RuleObject | undefined;\n return !!resolved?.required && !resolved?.warningOnly;\n }\n return !!rule?.required && !rule?.warningOnly;\n });\n}\n\n/**\n * `requiredMark` decorates the LABEL. A function or `'optional'` mark replaces\n * the asterisk entirely, as in antd: the label itself then carries the hint.\n */\nfunction applyRequiredMark(\n label: React.ReactNode,\n required: boolean,\n requiredMark: RequiredMark | undefined,\n optionalLabel: React.ReactNode,\n): React.ReactNode {\n if (label === undefined || label === null) return label;\n if (typeof requiredMark === \"function\") {\n return requiredMark(label, { required });\n }\n if (requiredMark === \"optional\" && !required) {\n // antd renders the bare locale string and spaces it with\n // `margin-inline-start: marginXXS`, so the gap survives text selection and\n // copy. The engine had baked a literal leading space into the string,\n // which put \" (optional)\" in `label.textContent` where antd has\n // \"(optional)\".\n return (\n <>\n {label}\n <span className=\"uic-form-item__optional\">{optionalLabel}</span>\n </>\n );\n }\n return label;\n}\n\n/** Errors/warnings of the nearest enclosing `Form.Item`. */\nexport const useFormItemStatus = () => {\n const { status, errors = [], warnings = [] } = React.useContext(FormItemInputContext);\n return { status, errors, warnings };\n};\n\nexport { getFieldId };\nexport default FormItem;\nexport type { StoreValue };\n"],"mappings":"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"}
|
|
@@ -22,6 +22,13 @@ export interface FormItemVisualProps {
|
|
|
22
22
|
tooltip?: React.ReactNode;
|
|
23
23
|
/** The tooltip trigger glyph. Defaults to a question mark in a circle. */
|
|
24
24
|
tooltipIcon?: React.ReactNode;
|
|
25
|
+
/**
|
|
26
|
+
* Actions that belong to the label row (e.g. a filter button). Rendered
|
|
27
|
+
* outside the `<label>`, so they stay out of the control's accessible name:
|
|
28
|
+
* at the far end of the row in vertical layout, right after the label
|
|
29
|
+
* otherwise. Needs a `label`.
|
|
30
|
+
*/
|
|
31
|
+
labelExtra?: React.ReactNode;
|
|
25
32
|
extra?: React.ReactNode;
|
|
26
33
|
help?: React.ReactNode;
|
|
27
34
|
/** Renders the required marker. Independent of the `required` rule. */
|