@jobber/components 8.23.0 → 8.23.1
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/dist/Autocomplete/index.cjs +1 -1
- package/dist/Autocomplete/index.mjs +1 -1
- package/dist/Card/index.cjs +4 -4
- package/dist/Card/index.mjs +4 -4
- package/dist/Chip/index.cjs +1 -1
- package/dist/Chip/index.mjs +1 -1
- package/dist/Chips/InternalChipDismissible/hooks/index.cjs +1 -1
- package/dist/Chips/InternalChipDismissible/hooks/index.mjs +1 -1
- package/dist/Chips/InternalChipDismissible/index.cjs +1 -1
- package/dist/Chips/InternalChipDismissible/index.mjs +1 -1
- package/dist/Chips/index.cjs +1 -1
- package/dist/Chips/index.mjs +1 -1
- package/dist/ComboboxChipRemove-cjs.js +668 -379
- package/dist/ComboboxChipRemove-es.js +508 -219
- package/dist/ConfirmationModal/index.cjs +1 -1
- package/dist/ConfirmationModal/index.mjs +1 -1
- package/dist/DataDump/index.cjs +4 -4
- package/dist/DataDump/index.mjs +4 -4
- package/dist/DataList/components/DataListActions/index.cjs +1 -1
- package/dist/DataList/components/DataListActions/index.mjs +1 -1
- package/dist/DataList/components/DataListBulkActions/index.cjs +1 -1
- package/dist/DataList/components/DataListBulkActions/index.mjs +1 -1
- package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +1 -1
- package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +1 -1
- package/dist/DataList/components/DataListFilters/index.cjs +1 -1
- package/dist/DataList/components/DataListFilters/index.mjs +1 -1
- package/dist/DataList/components/DataListHeader/index.cjs +1 -1
- package/dist/DataList/components/DataListHeader/index.mjs +1 -1
- package/dist/DataList/components/DataListItem/index.cjs +1 -1
- package/dist/DataList/components/DataListItem/index.mjs +1 -1
- package/dist/DataList/components/DataListItemActions/index.cjs +1 -1
- package/dist/DataList/components/DataListItemActions/index.mjs +1 -1
- package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +1 -1
- package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +1 -1
- package/dist/DataList/components/DataListItems/index.cjs +1 -1
- package/dist/DataList/components/DataListItems/index.mjs +1 -1
- package/dist/DataList/components/DataListLayout/index.cjs +1 -1
- package/dist/DataList/components/DataListLayout/index.mjs +1 -1
- package/dist/DataList/components/DataListLayoutActions/index.cjs +1 -1
- package/dist/DataList/components/DataListLayoutActions/index.mjs +1 -1
- package/dist/DataList/index.cjs +1 -1
- package/dist/DataList/index.mjs +1 -1
- package/dist/DatePicker/index.cjs +1 -1
- package/dist/DatePicker/index.mjs +1 -1
- package/dist/Dialog/index.cjs +3 -3
- package/dist/Dialog/index.mjs +3 -3
- package/dist/DrawerDescription-cjs.js +32 -33
- package/dist/DrawerDescription-es.js +19 -20
- package/dist/DrawerTitle-cjs.js +7 -5
- package/dist/DrawerTitle-es.js +7 -5
- package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +1 -1
- package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +1 -1
- package/dist/FilterPicker/components/FilterPickerContent/index.cjs +1 -1
- package/dist/FilterPicker/components/FilterPickerContent/index.mjs +1 -1
- package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +1 -1
- package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +1 -1
- package/dist/FilterPicker/index.cjs +1 -1
- package/dist/FilterPicker/index.mjs +1 -1
- package/dist/FormFieldWrapper-cjs.js +2 -2
- package/dist/FormFieldWrapper-es.js +2 -2
- package/dist/FormatFile/index.cjs +1 -1
- package/dist/FormatFile/index.mjs +1 -1
- package/dist/Gallery/index.cjs +1 -1
- package/dist/Gallery/index.mjs +1 -1
- package/dist/InputDate/index.cjs +1 -1
- package/dist/InputDate/index.mjs +1 -1
- package/dist/InputNumberExperimental-cjs.js +319 -102
- package/dist/InputNumberExperimental-es.js +321 -104
- package/dist/LightBox/index.cjs +1 -1
- package/dist/LightBox/index.mjs +1 -1
- package/dist/Menu/index.cjs +4 -4
- package/dist/Menu/index.mjs +4 -4
- package/dist/MenuSubmenuTrigger-cjs.js +545 -498
- package/dist/MenuSubmenuTrigger-es.js +490 -443
- package/dist/Modal/index.cjs +1 -1
- package/dist/Modal/index.mjs +1 -1
- package/dist/NumberFieldInput-cjs.js +609 -496
- package/dist/NumberFieldInput-es.js +612 -498
- package/dist/Page/index.cjs +4 -4
- package/dist/Page/index.mjs +4 -4
- package/dist/Popover/index.cjs +1 -1
- package/dist/Popover/index.mjs +1 -1
- package/dist/ScrollAreaViewport-cjs.js +326 -601
- package/dist/ScrollAreaViewport-es.js +278 -548
- package/dist/SelectGroupLabel-cjs.js +494 -528
- package/dist/SelectGroupLabel-es.js +411 -445
- package/dist/Separator-cjs.js +1 -0
- package/dist/Separator-es.js +1 -0
- package/dist/Tooltip/index.cjs +1 -1
- package/dist/Tooltip/index.mjs +1 -1
- package/dist/docs/InputTime/InputTime.md +8 -0
- package/dist/docs/SelectPrimitive/SelectPrimitive.md +38 -25
- package/dist/floating-ui.react-cjs.js +586 -10
- package/dist/floating-ui.react-dom-cjs.js +92 -92
- package/dist/floating-ui.react-dom-es.js +1 -1
- package/dist/floating-ui.react-es.js +580 -4
- package/dist/floating-ui.utils-cjs.js +159 -0
- package/dist/floating-ui.utils-es.js +136 -0
- package/dist/index.cjs +4 -4
- package/dist/index.mjs +4 -4
- package/dist/{ToolbarRootContext-cjs.js → isElementDisabled-cjs.js} +5 -0
- package/dist/{ToolbarRootContext-es.js → isElementDisabled-es.js} +5 -1
- package/dist/primitives/BottomSheet/index.cjs +3 -3
- package/dist/primitives/BottomSheet/index.mjs +3 -3
- package/dist/primitives/ComboboxPrimitive/index.cjs +2 -2
- package/dist/primitives/ComboboxPrimitive/index.mjs +2 -2
- package/dist/primitives/InputNumberExperimental/index.cjs +1 -1
- package/dist/primitives/InputNumberExperimental/index.mjs +1 -1
- package/dist/primitives/SelectPrimitive/index.cjs +5 -5
- package/dist/primitives/SelectPrimitive/index.mjs +5 -5
- package/dist/primitives/index.cjs +4 -4
- package/dist/primitives/index.mjs +4 -4
- package/dist/resolveAriaLabelledBy-cjs.js +5 -0
- package/dist/resolveAriaLabelledBy-es.js +5 -1
- package/dist/{CSPContext-cjs.js → scrollEdges-cjs.js} +30 -2
- package/dist/{CSPContext-es.js → scrollEdges-es.js} +28 -3
- package/dist/styles.css +9 -3
- package/dist/unstyledPrimitives/index.cjs +1217 -639
- package/dist/unstyledPrimitives/index.mjs +1163 -585
- package/dist/useButton-cjs.js +283 -317
- package/dist/useButton-es.js +277 -298
- package/dist/useCompositeListItem-cjs.js +328 -279
- package/dist/useCompositeListItem-es.js +293 -246
- package/dist/useLabel-cjs.js +11 -1
- package/dist/useLabel-es.js +11 -2
- package/dist/useLabelableId-cjs.js +37 -91
- package/dist/useLabelableId-es.js +37 -90
- package/dist/useRenderElement-cjs.js +81 -26
- package/dist/useRenderElement-es.js +81 -27
- package/dist/{InternalBackdrop-cjs.js → useScrollLock-cjs.js} +1286 -1220
- package/dist/{InternalBackdrop-es.js → useScrollLock-es.js} +1250 -1207
- package/package.json +3 -3
- package/dist/index.esm-cjs.js +0 -738
- package/dist/index.esm-es.js +0 -712
|
@@ -32,11 +32,16 @@ function _interopNamespaceDefault(e) {
|
|
|
32
32
|
|
|
33
33
|
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
34
34
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
setLegendId: () => {},
|
|
38
|
-
disabled: undefined
|
|
35
|
+
const FieldItemContext = /*#__PURE__*/React__namespace.createContext({
|
|
36
|
+
disabled: false
|
|
39
37
|
});
|
|
38
|
+
if (process.env.NODE_ENV !== "production") FieldItemContext.displayName = "FieldItemContext";
|
|
39
|
+
function useFieldItemContext() {
|
|
40
|
+
const context = React__namespace.useContext(FieldItemContext);
|
|
41
|
+
return context;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const FieldsetRootContext = /*#__PURE__*/React__namespace.createContext(undefined);
|
|
40
45
|
if (process.env.NODE_ENV !== "production") FieldsetRootContext.displayName = "FieldsetRootContext";
|
|
41
46
|
function useFieldsetRootContext(optional = false) {
|
|
42
47
|
const context = React__namespace.useContext(FieldsetRootContext);
|
|
@@ -84,9 +89,12 @@ const LabelableProvider = function LabelableProvider(props) {
|
|
|
84
89
|
});
|
|
85
90
|
});
|
|
86
91
|
const getDescriptionProps = React__namespace.useCallback(externalProps => {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
const ids = externalProps['aria-describedby'] ? externalProps['aria-describedby'].split(' ') : [];
|
|
93
|
+
ids.push(...parentMessageIds, ...messageIds);
|
|
94
|
+
return {
|
|
95
|
+
...externalProps,
|
|
96
|
+
'aria-describedby': Array.from(new Set(ids)).join(' ') || undefined
|
|
97
|
+
};
|
|
90
98
|
}, [parentMessageIds, messageIds]);
|
|
91
99
|
const contextValue = React__namespace.useMemo(() => ({
|
|
92
100
|
controlId,
|
|
@@ -104,6 +112,20 @@ const LabelableProvider = function LabelableProvider(props) {
|
|
|
104
112
|
};
|
|
105
113
|
if (process.env.NODE_ENV !== "production") LabelableProvider.displayName = "LabelableProvider";
|
|
106
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Combines the field's client-side, stateful validity data with the external invalid state to
|
|
117
|
+
* determine the field's true validity.
|
|
118
|
+
*/
|
|
119
|
+
function getCombinedFieldValidityData(validityData, invalid) {
|
|
120
|
+
return {
|
|
121
|
+
...validityData,
|
|
122
|
+
state: {
|
|
123
|
+
...validityData.state,
|
|
124
|
+
valid: !invalid && validityData.state.valid
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
107
129
|
const validityKeys = Object.keys(useLabelableId.DEFAULT_VALIDITY_STATE);
|
|
108
130
|
function isOnlyValueMissing(state) {
|
|
109
131
|
if (!state || state.valid || !state.valueMissing) {
|
|
@@ -116,17 +138,45 @@ function isOnlyValueMissing(state) {
|
|
|
116
138
|
}
|
|
117
139
|
if (key === 'valueMissing') {
|
|
118
140
|
onlyValueMissing = state[key];
|
|
119
|
-
}
|
|
120
|
-
if (state[key]) {
|
|
141
|
+
} else if (state[key]) {
|
|
121
142
|
onlyValueMissing = false;
|
|
122
143
|
}
|
|
123
144
|
}
|
|
124
145
|
return onlyValueMissing;
|
|
125
146
|
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Picks the input whose native validity should represent a field that owns several inputs (such as a
|
|
150
|
+
* checkbox group). Prefers the first enabled currently-invalid input, where "first" follows Set
|
|
151
|
+
* insertion order (mount order), and otherwise returns the first enabled input. Disabled inputs are
|
|
152
|
+
* skipped because they don't participate in native constraint validation.
|
|
153
|
+
*/
|
|
154
|
+
function findRepresentativeInput(inputs) {
|
|
155
|
+
let fallback = null;
|
|
156
|
+
for (const input of inputs) {
|
|
157
|
+
if (input.disabled) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (!input.validity.valid) {
|
|
161
|
+
return input;
|
|
162
|
+
}
|
|
163
|
+
fallback ??= input;
|
|
164
|
+
}
|
|
165
|
+
return fallback;
|
|
166
|
+
}
|
|
167
|
+
function clearCustomValidity(element, inputs) {
|
|
168
|
+
let didClearElement = false;
|
|
169
|
+
for (const input of inputs) {
|
|
170
|
+
input.setCustomValidity('');
|
|
171
|
+
didClearElement ||= input === element;
|
|
172
|
+
}
|
|
173
|
+
if (!didClearElement) {
|
|
174
|
+
element.setCustomValidity('');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
126
177
|
function useFieldValidation(params) {
|
|
127
178
|
const {
|
|
128
|
-
formRef
|
|
129
|
-
clearErrors
|
|
179
|
+
formRef
|
|
130
180
|
} = useLabelableId.useFormContext();
|
|
131
181
|
const {
|
|
132
182
|
setValidityData,
|
|
@@ -136,8 +186,8 @@ function useFieldValidation(params) {
|
|
|
136
186
|
invalid,
|
|
137
187
|
markedDirtyRef,
|
|
138
188
|
state,
|
|
139
|
-
|
|
140
|
-
|
|
189
|
+
shouldValidateOnChange,
|
|
190
|
+
getRegisteredFieldId
|
|
141
191
|
} = params;
|
|
142
192
|
const {
|
|
143
193
|
controlId,
|
|
@@ -145,11 +195,45 @@ function useFieldValidation(params) {
|
|
|
145
195
|
} = useLabelableId.useLabelableContext();
|
|
146
196
|
const timeout = useButton.useTimeout();
|
|
147
197
|
const inputRef = React__namespace.useRef(null);
|
|
198
|
+
const registeredInputs = useRenderElement.useRefWithInit(() => new Set()).current;
|
|
199
|
+
const validationCommitIdRef = React__namespace.useRef(0);
|
|
200
|
+
|
|
201
|
+
// Checkbox groups register several inputs against a single field. Track them so a `required`
|
|
202
|
+
// checkbox can't be satisfied by another input in the group, matching native per-checkbox behavior.
|
|
203
|
+
const registerInput = React__namespace.useCallback(element => {
|
|
204
|
+
if (!element) {
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
registeredInputs.add(element);
|
|
208
|
+
return () => {
|
|
209
|
+
registeredInputs.delete(element);
|
|
210
|
+
};
|
|
211
|
+
}, [registeredInputs]);
|
|
148
212
|
const commit = useButton.useStableCallback(async (value, revalidate = false) => {
|
|
149
|
-
|
|
213
|
+
// A field can own several inputs (a checkbox group), but only the last-mounted one wins the shared
|
|
214
|
+
// `inputRef`. Validate against the registry instead so every input counts; `inputRef` is the
|
|
215
|
+
// fallback only when no registered input applies (none registered, or all of them disabled).
|
|
216
|
+
const element = findRepresentativeInput(registeredInputs) ?? inputRef.current;
|
|
150
217
|
if (!element) {
|
|
151
218
|
return;
|
|
152
219
|
}
|
|
220
|
+
validationCommitIdRef.current += 1;
|
|
221
|
+
const validationCommitId = validationCommitIdRef.current;
|
|
222
|
+
function updateRegisteredFieldValidity(nextValidityData, externalInvalid = invalid) {
|
|
223
|
+
const fieldId = getRegisteredFieldId() ?? controlId;
|
|
224
|
+
if (fieldId == null) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const currentFieldData = formRef.current.fields.get(fieldId);
|
|
228
|
+
if (!currentFieldData) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const validityDataWithFormErrors = getCombinedFieldValidityData(nextValidityData, externalInvalid);
|
|
232
|
+
formRef.current.fields.set(fieldId, {
|
|
233
|
+
...currentFieldData,
|
|
234
|
+
validityData: validityDataWithFormErrors
|
|
235
|
+
});
|
|
236
|
+
}
|
|
153
237
|
if (revalidate) {
|
|
154
238
|
if (state.valid !== false) {
|
|
155
239
|
return;
|
|
@@ -169,16 +253,10 @@ function useFieldValidation(params) {
|
|
|
169
253
|
errors: [],
|
|
170
254
|
initialValue: validityData.initialValue
|
|
171
255
|
};
|
|
172
|
-
element
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
formRef.current.fields.set(controlId, {
|
|
177
|
-
...currentFieldData,
|
|
178
|
-
...useLabelableId.getCombinedFieldValidityData(nextValidityData, false) // invalid = false
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
}
|
|
256
|
+
clearCustomValidity(element, registeredInputs);
|
|
257
|
+
|
|
258
|
+
// The required value is now present; ignore stale external invalid state for this pass.
|
|
259
|
+
updateRegisteredFieldValidity(nextValidityData, false);
|
|
182
260
|
setValidityData(nextValidityData);
|
|
183
261
|
return;
|
|
184
262
|
}
|
|
@@ -229,8 +307,8 @@ function useFieldValidation(params) {
|
|
|
229
307
|
let validationErrors = [];
|
|
230
308
|
const nextState = getState(element);
|
|
231
309
|
let defaultValidationMessage;
|
|
232
|
-
const
|
|
233
|
-
if (element.validationMessage && !
|
|
310
|
+
const isValidatingOnChange = shouldValidateOnChange();
|
|
311
|
+
if (element.validationMessage && !isValidatingOnChange) {
|
|
234
312
|
// not validating on change, if there is a `validationMessage` from
|
|
235
313
|
// native validity, set errors and skip calling the custom validate fn
|
|
236
314
|
defaultValidationMessage = element.validationMessage;
|
|
@@ -248,6 +326,9 @@ function useFieldValidation(params) {
|
|
|
248
326
|
const resultOrPromise = validate(value, formValues);
|
|
249
327
|
if (typeof resultOrPromise === 'object' && resultOrPromise !== null && 'then' in resultOrPromise) {
|
|
250
328
|
result = await resultOrPromise;
|
|
329
|
+
if (validationCommitId !== validationCommitIdRef.current) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
251
332
|
} else {
|
|
252
333
|
result = resultOrPromise;
|
|
253
334
|
}
|
|
@@ -261,10 +342,10 @@ function useFieldValidation(params) {
|
|
|
261
342
|
validationErrors = [result];
|
|
262
343
|
element.setCustomValidity(result);
|
|
263
344
|
}
|
|
264
|
-
} else if (
|
|
345
|
+
} else if (isValidatingOnChange) {
|
|
265
346
|
// validate function returned no errors, if validating on change
|
|
266
347
|
// we need to clear the custom validity state
|
|
267
|
-
element
|
|
348
|
+
clearCustomValidity(element, registeredInputs);
|
|
268
349
|
nextState.customError = false;
|
|
269
350
|
if (element.validationMessage) {
|
|
270
351
|
defaultValidationMessage = element.validationMessage;
|
|
@@ -281,57 +362,153 @@ function useFieldValidation(params) {
|
|
|
281
362
|
errors: validationErrors,
|
|
282
363
|
initialValue: validityData.initialValue
|
|
283
364
|
};
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
formRef.current.fields.set(controlId, {
|
|
288
|
-
...currentFieldData,
|
|
289
|
-
// Keep Form-level errors part of overall field validity for submit blocking/focus logic.
|
|
290
|
-
...useLabelableId.getCombinedFieldValidityData(nextValidityData, invalid)
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
}
|
|
365
|
+
|
|
366
|
+
// Keep Form-level errors part of overall field validity for submit blocking/focus logic.
|
|
367
|
+
updateRegisteredFieldValidity(nextValidityData);
|
|
294
368
|
setValidityData(nextValidityData);
|
|
295
369
|
});
|
|
296
|
-
const
|
|
370
|
+
const change = useButton.useStableCallback(value => {
|
|
371
|
+
timeout.clear();
|
|
372
|
+
const validateOnChange = shouldValidateOnChange();
|
|
373
|
+
if (validateOnChange && value !== '' && validationDebounceTime) {
|
|
374
|
+
validationCommitIdRef.current += 1;
|
|
375
|
+
timeout.start(validationDebounceTime, () => {
|
|
376
|
+
commit(value);
|
|
377
|
+
});
|
|
378
|
+
} else {
|
|
379
|
+
commit(value, !validateOnChange);
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
const getValidationProps = React__namespace.useCallback((disabled, externalProps = {}) => useRenderElement.mergeProps(getDescriptionProps(externalProps), state.valid === false && !state.disabled && !disabled ? {
|
|
297
383
|
'aria-invalid': true
|
|
298
|
-
} : useRenderElement.EMPTY_OBJECT
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
commit(event.currentTarget.value, true);
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
384
|
+
} : useRenderElement.EMPTY_OBJECT), [getDescriptionProps, state.disabled, state.valid]);
|
|
385
|
+
return React__namespace.useMemo(() => ({
|
|
386
|
+
getValidationProps,
|
|
387
|
+
inputRef,
|
|
388
|
+
registerInput,
|
|
389
|
+
commit,
|
|
390
|
+
change
|
|
391
|
+
}), [getValidationProps, registerInput, commit, change]);
|
|
392
|
+
}
|
|
310
393
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
394
|
+
function useFieldControlRegistration(params) {
|
|
395
|
+
const {
|
|
396
|
+
commit,
|
|
397
|
+
invalid,
|
|
398
|
+
markedDirtyRef,
|
|
399
|
+
name,
|
|
400
|
+
setRegisteredFieldName,
|
|
401
|
+
setRegisteredFieldId,
|
|
402
|
+
setValidityData,
|
|
403
|
+
validityData
|
|
404
|
+
} = params;
|
|
405
|
+
const {
|
|
406
|
+
formRef
|
|
407
|
+
} = useLabelableId.useFormContext();
|
|
408
|
+
const activeFieldControlSourceRef = React__namespace.useRef(null);
|
|
409
|
+
const registrationRef = React__namespace.useRef(null);
|
|
410
|
+
const fallbackControlRef = React__namespace.useRef(null);
|
|
411
|
+
const getValueForForm = useButton.useStableCallback(() => {
|
|
412
|
+
const registration = registrationRef.current;
|
|
413
|
+
if (!registration) {
|
|
414
|
+
return undefined;
|
|
415
|
+
}
|
|
416
|
+
if (registration.getValue) {
|
|
417
|
+
return registration.getValue();
|
|
418
|
+
}
|
|
419
|
+
return registration.value;
|
|
420
|
+
});
|
|
421
|
+
function getRegistrationValue(registration) {
|
|
422
|
+
return registration.value === undefined ? getValueForForm() : registration.value;
|
|
423
|
+
}
|
|
424
|
+
const validate = useButton.useStableCallback(() => {
|
|
425
|
+
const registration = registrationRef.current;
|
|
426
|
+
markedDirtyRef.current = true;
|
|
427
|
+
if (!registration) {
|
|
428
|
+
commit(validityData.value);
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
commit(getRegistrationValue(registration));
|
|
432
|
+
});
|
|
433
|
+
function refreshRegistration() {
|
|
434
|
+
const registration = registrationRef.current;
|
|
435
|
+
if (!registration || !registration.id) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
formRef.current.fields.set(registration.id, {
|
|
439
|
+
getValue: getValueForForm,
|
|
440
|
+
name: name ?? registration.name,
|
|
441
|
+
controlRef: registration.controlRef ?? fallbackControlRef,
|
|
442
|
+
validityData: getCombinedFieldValidityData(validityData, invalid),
|
|
443
|
+
validate
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
function deleteRegistration(id = registrationRef.current?.id) {
|
|
447
|
+
if (id) {
|
|
448
|
+
formRef.current.fields.delete(id);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
function syncInitialValue() {
|
|
452
|
+
const registration = registrationRef.current;
|
|
453
|
+
if (!registration) {
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
const initialValue = getRegistrationValue(registration);
|
|
457
|
+
if (validityData.initialValue === null && initialValue !== null) {
|
|
458
|
+
setValidityData(prev => ({
|
|
459
|
+
...prev,
|
|
460
|
+
initialValue
|
|
461
|
+
}));
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
useButton.useIsoLayoutEffect(() => {
|
|
465
|
+
const registration = registrationRef.current;
|
|
466
|
+
if (!registration || !registration.id) {
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
setRegisteredFieldName(name ? undefined : registration.name);
|
|
470
|
+
formRef.current.fields.set(registration.id, {
|
|
471
|
+
getValue: getValueForForm,
|
|
472
|
+
name: name ?? registration.name,
|
|
473
|
+
controlRef: registration.controlRef ?? fallbackControlRef,
|
|
474
|
+
validityData: getCombinedFieldValidityData(validityData, invalid),
|
|
475
|
+
validate
|
|
476
|
+
});
|
|
477
|
+
}, [formRef, getValueForForm, invalid, name, setRegisteredFieldName, validate, validityData]);
|
|
478
|
+
useButton.useIsoLayoutEffect(() => {
|
|
479
|
+
const fields = formRef.current.fields;
|
|
480
|
+
return () => {
|
|
481
|
+
const id = registrationRef.current?.id;
|
|
482
|
+
if (id) {
|
|
483
|
+
fields.delete(id);
|
|
318
484
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
485
|
+
};
|
|
486
|
+
}, [formRef]);
|
|
487
|
+
const register = useButton.useStableCallback((source, registration) => {
|
|
488
|
+
if (!registration) {
|
|
489
|
+
if (activeFieldControlSourceRef.current === source) {
|
|
490
|
+
activeFieldControlSourceRef.current = null;
|
|
491
|
+
deleteRegistration();
|
|
492
|
+
registrationRef.current = null;
|
|
493
|
+
setRegisteredFieldName(undefined);
|
|
494
|
+
setRegisteredFieldId(undefined);
|
|
326
495
|
}
|
|
496
|
+
return;
|
|
327
497
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
498
|
+
const previousId = registrationRef.current?.id;
|
|
499
|
+
activeFieldControlSourceRef.current = source;
|
|
500
|
+
registrationRef.current = registration;
|
|
501
|
+
if (!name) {
|
|
502
|
+
setRegisteredFieldName(registration.name);
|
|
503
|
+
}
|
|
504
|
+
setRegisteredFieldId(registration.id);
|
|
505
|
+
if (previousId && previousId !== registration.id) {
|
|
506
|
+
deleteRegistration(previousId);
|
|
507
|
+
}
|
|
508
|
+
syncInitialValue();
|
|
509
|
+
refreshRegistration();
|
|
510
|
+
});
|
|
511
|
+
return [validate, register];
|
|
335
512
|
}
|
|
336
513
|
|
|
337
514
|
const FieldRootInner = /*#__PURE__*/React__namespace.forwardRef(function FieldRootInner(componentProps, forwardedRef) {
|
|
@@ -352,11 +529,10 @@ const FieldRootInner = /*#__PURE__*/React__namespace.forwardRef(function FieldRo
|
|
|
352
529
|
dirty: dirtyProp,
|
|
353
530
|
touched: touchedProp,
|
|
354
531
|
actionsRef,
|
|
532
|
+
style,
|
|
355
533
|
...elementProps
|
|
356
534
|
} = componentProps;
|
|
357
|
-
const
|
|
358
|
-
disabled: disabledFieldset
|
|
359
|
-
} = useFieldsetRootContext();
|
|
535
|
+
const disabledFieldset = useFieldsetRootContext(true)?.disabled;
|
|
360
536
|
const validate = useButton.useStableCallback(validateProp || (() => null));
|
|
361
537
|
const disabled = disabledFieldset || disabledProp;
|
|
362
538
|
const [touchedState, setTouchedUnwrapped] = React__namespace.useState(false);
|
|
@@ -365,7 +541,19 @@ const FieldRootInner = /*#__PURE__*/React__namespace.forwardRef(function FieldRo
|
|
|
365
541
|
const [focused, setFocused] = React__namespace.useState(false);
|
|
366
542
|
const dirty = dirtyProp ?? dirtyState;
|
|
367
543
|
const touched = touchedProp ?? touchedState;
|
|
368
|
-
const markedDirtyRef = React__namespace.useRef(
|
|
544
|
+
const markedDirtyRef = React__namespace.useRef(dirty);
|
|
545
|
+
const registeredFieldIdRef = React__namespace.useRef(undefined);
|
|
546
|
+
const [registeredFieldName, setRegisteredFieldName] = React__namespace.useState();
|
|
547
|
+
const effectiveName = name ?? registeredFieldName;
|
|
548
|
+
useButton.useIsoLayoutEffect(() => {
|
|
549
|
+
if (dirtyProp !== undefined) {
|
|
550
|
+
markedDirtyRef.current = dirtyProp;
|
|
551
|
+
}
|
|
552
|
+
}, [dirtyProp]);
|
|
553
|
+
const getRegisteredFieldId = React__namespace.useCallback(() => registeredFieldIdRef.current, []);
|
|
554
|
+
const setRegisteredFieldId = React__namespace.useCallback(id => {
|
|
555
|
+
registeredFieldIdRef.current = id;
|
|
556
|
+
}, []);
|
|
369
557
|
const setDirty = useButton.useStableCallback(value => {
|
|
370
558
|
if (dirtyProp !== undefined) {
|
|
371
559
|
return;
|
|
@@ -382,7 +570,8 @@ const FieldRootInner = /*#__PURE__*/React__namespace.forwardRef(function FieldRo
|
|
|
382
570
|
setTouchedUnwrapped(value);
|
|
383
571
|
});
|
|
384
572
|
const shouldValidateOnChange = useButton.useStableCallback(() => validationMode === 'onChange' || validationMode === 'onSubmit' && submitAttemptedRef.current);
|
|
385
|
-
const
|
|
573
|
+
const formError = effectiveName && Object.hasOwn(errors, effectiveName) ? errors[effectiveName] : null;
|
|
574
|
+
const hasFormError = !!(Array.isArray(formError) ? formError.length : formError);
|
|
386
575
|
const invalid = invalidProp === true || hasFormError;
|
|
387
576
|
const [validityData, setValidityData] = React__namespace.useState({
|
|
388
577
|
state: useLabelableId.DEFAULT_VALIDITY_STATE,
|
|
@@ -391,7 +580,7 @@ const FieldRootInner = /*#__PURE__*/React__namespace.forwardRef(function FieldRo
|
|
|
391
580
|
value: null,
|
|
392
581
|
initialValue: null
|
|
393
582
|
});
|
|
394
|
-
const valid = !invalid && validityData.state.valid;
|
|
583
|
+
const valid = disabled ? null : !invalid && validityData.state.valid;
|
|
395
584
|
const state = React__namespace.useMemo(() => ({
|
|
396
585
|
disabled,
|
|
397
586
|
touched,
|
|
@@ -408,19 +597,25 @@ const FieldRootInner = /*#__PURE__*/React__namespace.forwardRef(function FieldRo
|
|
|
408
597
|
invalid,
|
|
409
598
|
markedDirtyRef,
|
|
410
599
|
state,
|
|
600
|
+
shouldValidateOnChange,
|
|
601
|
+
getRegisteredFieldId
|
|
602
|
+
});
|
|
603
|
+
const [validateFieldControl, registerFieldControl] = useFieldControlRegistration({
|
|
604
|
+
commit: validation.commit,
|
|
605
|
+
invalid,
|
|
606
|
+
markedDirtyRef,
|
|
411
607
|
name,
|
|
412
|
-
|
|
608
|
+
setRegisteredFieldName,
|
|
609
|
+
setRegisteredFieldId,
|
|
610
|
+
setValidityData,
|
|
611
|
+
validityData
|
|
413
612
|
});
|
|
414
|
-
const handleImperativeValidate = React__namespace.useCallback(() => {
|
|
415
|
-
markedDirtyRef.current = true;
|
|
416
|
-
validation.commit(validityData.value);
|
|
417
|
-
}, [validation, validityData]);
|
|
418
613
|
React__namespace.useImperativeHandle(actionsRef, () => ({
|
|
419
|
-
validate:
|
|
420
|
-
}), [
|
|
614
|
+
validate: validateFieldControl
|
|
615
|
+
}), [validateFieldControl]);
|
|
421
616
|
const contextValue = React__namespace.useMemo(() => ({
|
|
422
617
|
invalid,
|
|
423
|
-
name,
|
|
618
|
+
name: effectiveName,
|
|
424
619
|
validityData,
|
|
425
620
|
setValidityData,
|
|
426
621
|
disabled,
|
|
@@ -438,8 +633,9 @@ const FieldRootInner = /*#__PURE__*/React__namespace.forwardRef(function FieldRo
|
|
|
438
633
|
shouldValidateOnChange,
|
|
439
634
|
state,
|
|
440
635
|
markedDirtyRef,
|
|
636
|
+
registerFieldControl,
|
|
441
637
|
validation
|
|
442
|
-
}), [invalid,
|
|
638
|
+
}), [invalid, effectiveName, validityData, disabled, touched, setTouched, dirty, setDirty, filled, setFilled, focused, setFocused, validate, validationMode, validationDebounceTime, shouldValidateOnChange, state, registerFieldControl, validation]);
|
|
443
639
|
const element = useRenderElement.useRenderElement('div', componentProps, {
|
|
444
640
|
ref: forwardedRef,
|
|
445
641
|
state,
|
|
@@ -479,14 +675,20 @@ const FieldLabel = /*#__PURE__*/React__namespace.forwardRef(function FieldLabel(
|
|
|
479
675
|
const {
|
|
480
676
|
render,
|
|
481
677
|
className,
|
|
678
|
+
style,
|
|
482
679
|
id: idProp,
|
|
483
680
|
nativeLabel = true,
|
|
484
681
|
...elementProps
|
|
485
682
|
} = componentProps;
|
|
486
683
|
const fieldRootContext = useLabelableId.useFieldRootContext(false);
|
|
684
|
+
const fieldItemContext = useFieldItemContext();
|
|
487
685
|
const {
|
|
488
686
|
labelId
|
|
489
687
|
} = useLabelableId.useLabelableContext();
|
|
688
|
+
const state = {
|
|
689
|
+
...fieldRootContext.state,
|
|
690
|
+
disabled: fieldRootContext.disabled || fieldItemContext.disabled
|
|
691
|
+
};
|
|
490
692
|
const labelRef = React__namespace.useRef(null);
|
|
491
693
|
const labelProps = useLabel.useLabel({
|
|
492
694
|
id: labelId ?? idProp,
|
|
@@ -514,7 +716,7 @@ const FieldLabel = /*#__PURE__*/React__namespace.forwardRef(function FieldLabel(
|
|
|
514
716
|
}
|
|
515
717
|
const element = useRenderElement.useRenderElement('label', componentProps, {
|
|
516
718
|
ref: [forwardedRef, labelRef],
|
|
517
|
-
state
|
|
719
|
+
state,
|
|
518
720
|
props: [labelProps, elementProps],
|
|
519
721
|
stateAttributesMapping: useLabelableId.fieldValidityMapping
|
|
520
722
|
});
|
|
@@ -539,6 +741,7 @@ const FieldError = /*#__PURE__*/React__namespace.forwardRef(function FieldError(
|
|
|
539
741
|
id: idProp,
|
|
540
742
|
className,
|
|
541
743
|
match,
|
|
744
|
+
style,
|
|
542
745
|
...elementProps
|
|
543
746
|
} = componentProps;
|
|
544
747
|
const id = useButton.useBaseUiId(idProp);
|
|
@@ -553,14 +756,18 @@ const FieldError = /*#__PURE__*/React__namespace.forwardRef(function FieldError(
|
|
|
553
756
|
const {
|
|
554
757
|
errors
|
|
555
758
|
} = useLabelableId.useFormContext();
|
|
556
|
-
const formError = name ? errors[name] : null;
|
|
759
|
+
const formError = name && Object.hasOwn(errors, name) ? errors[name] : null;
|
|
760
|
+
const hasFormError = !!(Array.isArray(formError) ? formError.length : formError);
|
|
761
|
+
const hasSpecificMatch = typeof match === 'string';
|
|
557
762
|
let rendered = false;
|
|
558
|
-
if (
|
|
763
|
+
if (match === true) {
|
|
559
764
|
rendered = true;
|
|
560
|
-
} else if (
|
|
765
|
+
} else if (fieldState.disabled) {
|
|
766
|
+
rendered = false;
|
|
767
|
+
} else if (hasSpecificMatch) {
|
|
561
768
|
rendered = Boolean(validityData.state[match]);
|
|
562
769
|
} else {
|
|
563
|
-
rendered = validityData.state.valid === false;
|
|
770
|
+
rendered = hasFormError || validityData.state.valid === false;
|
|
564
771
|
}
|
|
565
772
|
const {
|
|
566
773
|
mounted,
|
|
@@ -579,17 +786,21 @@ const FieldError = /*#__PURE__*/React__namespace.forwardRef(function FieldError(
|
|
|
579
786
|
const errorRef = React__namespace.useRef(null);
|
|
580
787
|
const [lastRenderedMessage, setLastRenderedMessage] = React__namespace.useState(null);
|
|
581
788
|
const [lastRenderedMessageKey, setLastRenderedMessageKey] = React__namespace.useState(null);
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
}, message))
|
|
586
|
-
}) : validityData.error);
|
|
587
|
-
let errorKey = validityData.error;
|
|
588
|
-
if (formError != null) {
|
|
589
|
-
errorKey = Array.isArray(formError) ? JSON.stringify(formError) : formError;
|
|
789
|
+
let error = validityData.error;
|
|
790
|
+
if (!hasSpecificMatch && hasFormError) {
|
|
791
|
+
error = formError;
|
|
590
792
|
} else if (validityData.errors.length > 1) {
|
|
591
|
-
|
|
793
|
+
error = validityData.errors;
|
|
794
|
+
}
|
|
795
|
+
let errorMessage = error ?? '';
|
|
796
|
+
if (Array.isArray(error)) {
|
|
797
|
+
errorMessage = error.length > 1 ? /*#__PURE__*/jsxRuntime.jsx("ul", {
|
|
798
|
+
children: error.map(message => /*#__PURE__*/jsxRuntime.jsx("li", {
|
|
799
|
+
children: message
|
|
800
|
+
}, message))
|
|
801
|
+
}) : error[0] ?? '';
|
|
592
802
|
}
|
|
803
|
+
const errorKey = Array.isArray(error) ? JSON.stringify(error) : error;
|
|
593
804
|
if (rendered && errorKey !== lastRenderedMessageKey) {
|
|
594
805
|
setLastRenderedMessageKey(errorKey);
|
|
595
806
|
setLastRenderedMessage(errorMessage);
|
|
@@ -635,13 +846,19 @@ const FieldDescription = /*#__PURE__*/React__namespace.forwardRef(function Field
|
|
|
635
846
|
render,
|
|
636
847
|
id: idProp,
|
|
637
848
|
className,
|
|
849
|
+
style,
|
|
638
850
|
...elementProps
|
|
639
851
|
} = componentProps;
|
|
640
852
|
const id = useButton.useBaseUiId(idProp);
|
|
641
853
|
const fieldRootContext = useLabelableId.useFieldRootContext(false);
|
|
854
|
+
const fieldItemContext = useFieldItemContext();
|
|
642
855
|
const {
|
|
643
856
|
setMessageIds
|
|
644
857
|
} = useLabelableId.useLabelableContext();
|
|
858
|
+
const state = {
|
|
859
|
+
...fieldRootContext.state,
|
|
860
|
+
disabled: fieldRootContext.disabled || fieldItemContext.disabled
|
|
861
|
+
};
|
|
645
862
|
useButton.useIsoLayoutEffect(() => {
|
|
646
863
|
if (!id) {
|
|
647
864
|
return undefined;
|
|
@@ -653,7 +870,7 @@ const FieldDescription = /*#__PURE__*/React__namespace.forwardRef(function Field
|
|
|
653
870
|
}, [id, setMessageIds]);
|
|
654
871
|
const element = useRenderElement.useRenderElement('p', componentProps, {
|
|
655
872
|
ref: forwardedRef,
|
|
656
|
-
state
|
|
873
|
+
state,
|
|
657
874
|
props: [{
|
|
658
875
|
id
|
|
659
876
|
}, elementProps],
|