@jobber/components 9.6.0 → 9.6.2

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.
Files changed (187) hide show
  1. package/dist/ActivityIndicator-cjs.js +1 -0
  2. package/dist/ActivityIndicator-es.js +1 -0
  3. package/dist/Autocomplete/index.cjs +2 -0
  4. package/dist/Autocomplete/index.mjs +2 -0
  5. package/dist/Autocomplete-cjs.js +6 -4
  6. package/dist/Autocomplete-es.js +3 -1
  7. package/dist/Banner-cjs.js +1 -0
  8. package/dist/Banner-es.js +1 -0
  9. package/dist/Card/index.cjs +2 -1
  10. package/dist/Card/index.mjs +2 -1
  11. package/dist/Chip/index.cjs +2 -0
  12. package/dist/Chip/index.mjs +2 -0
  13. package/dist/Chip-cjs.js +1 -0
  14. package/dist/Chip-es.js +1 -0
  15. package/dist/Chips/InternalChipDismissible/hooks/index.cjs +2 -0
  16. package/dist/Chips/InternalChipDismissible/hooks/index.mjs +2 -0
  17. package/dist/Chips/InternalChipDismissible/index.cjs +2 -0
  18. package/dist/Chips/InternalChipDismissible/index.mjs +2 -0
  19. package/dist/Chips/index.cjs +2 -0
  20. package/dist/Chips/index.mjs +2 -0
  21. package/dist/Combobox/index.cjs +4 -2
  22. package/dist/Combobox/index.mjs +4 -2
  23. package/dist/{ComboboxSeparator-cjs.js → ComboboxChipRemove-cjs.js} +455 -501
  24. package/dist/{ComboboxSeparator-es.js → ComboboxChipRemove-es.js} +456 -500
  25. package/dist/ComboboxPrimitive-cjs.js +30 -29
  26. package/dist/ComboboxPrimitive-es.js +3 -2
  27. package/dist/ConfirmationModal/index.cjs +2 -0
  28. package/dist/ConfirmationModal/index.mjs +2 -0
  29. package/dist/ConfirmationModal-cjs.js +1 -0
  30. package/dist/ConfirmationModal-es.js +1 -0
  31. package/dist/DataDump/index.cjs +2 -1
  32. package/dist/DataDump/index.mjs +2 -1
  33. package/dist/DataDump-cjs.js +1 -0
  34. package/dist/DataDump-es.js +1 -0
  35. package/dist/DataList/components/DataListActions/index.cjs +2 -0
  36. package/dist/DataList/components/DataListActions/index.mjs +2 -0
  37. package/dist/DataList/components/DataListBulkActions/index.cjs +2 -0
  38. package/dist/DataList/components/DataListBulkActions/index.mjs +2 -0
  39. package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +2 -0
  40. package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +2 -0
  41. package/dist/DataList/components/DataListFilters/index.cjs +2 -0
  42. package/dist/DataList/components/DataListFilters/index.mjs +2 -0
  43. package/dist/DataList/components/DataListHeader/index.cjs +2 -0
  44. package/dist/DataList/components/DataListHeader/index.mjs +2 -0
  45. package/dist/DataList/components/DataListItem/index.cjs +2 -0
  46. package/dist/DataList/components/DataListItem/index.mjs +2 -0
  47. package/dist/DataList/components/DataListItemActions/index.cjs +2 -0
  48. package/dist/DataList/components/DataListItemActions/index.mjs +2 -0
  49. package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +2 -0
  50. package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +2 -0
  51. package/dist/DataList/components/DataListItems/index.cjs +2 -0
  52. package/dist/DataList/components/DataListItems/index.mjs +2 -0
  53. package/dist/DataList/components/DataListLayout/index.cjs +2 -0
  54. package/dist/DataList/components/DataListLayout/index.mjs +2 -0
  55. package/dist/DataList/components/DataListLayoutActions/index.cjs +2 -0
  56. package/dist/DataList/components/DataListLayoutActions/index.mjs +2 -0
  57. package/dist/DataList/index.cjs +2 -0
  58. package/dist/DataList/index.mjs +2 -0
  59. package/dist/DataTable-cjs.js +1 -0
  60. package/dist/DataTable-es.js +1 -0
  61. package/dist/DatePicker/index.cjs +2 -0
  62. package/dist/DatePicker/index.mjs +2 -0
  63. package/dist/DatePicker-cjs.js +8 -7
  64. package/dist/DatePicker-es.js +6 -5
  65. package/dist/Dialog/index.cjs +2 -1
  66. package/dist/Dialog/index.mjs +2 -1
  67. package/dist/DrawerDescription-cjs.js +99 -268
  68. package/dist/DrawerDescription-es.js +103 -270
  69. package/dist/DrawerGrid-cjs.js +1 -0
  70. package/dist/DrawerGrid-es.js +1 -0
  71. package/dist/DrawerTitle-cjs.js +6 -2
  72. package/dist/DrawerTitle-es.js +7 -3
  73. package/dist/FeatureSwitch-cjs.js +1 -0
  74. package/dist/FeatureSwitch-es.js +1 -0
  75. package/dist/FieldDescription-cjs.js +181 -184
  76. package/dist/FieldDescription-es.js +184 -187
  77. package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +2 -0
  78. package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +2 -0
  79. package/dist/FilterPicker/components/FilterPickerContent/index.cjs +2 -0
  80. package/dist/FilterPicker/components/FilterPickerContent/index.mjs +2 -0
  81. package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +2 -0
  82. package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +2 -0
  83. package/dist/FilterPicker/index.cjs +2 -0
  84. package/dist/FilterPicker/index.mjs +2 -0
  85. package/dist/FilterPickerContent-cjs.js +5 -4
  86. package/dist/FilterPickerContent-es.js +2 -1
  87. package/dist/FormFieldWrapper-cjs.js +1 -0
  88. package/dist/FormFieldWrapper-es.js +1 -0
  89. package/dist/FormatFile/index.cjs +2 -0
  90. package/dist/FormatFile/index.mjs +2 -0
  91. package/dist/FormatFile-cjs.js +1 -0
  92. package/dist/FormatFile-es.js +1 -0
  93. package/dist/Gallery/index.cjs +2 -0
  94. package/dist/Gallery/index.mjs +2 -0
  95. package/dist/InputAvatar-cjs.js +1 -0
  96. package/dist/InputAvatar-es.js +1 -0
  97. package/dist/InputDate/index.cjs +2 -0
  98. package/dist/InputDate/index.mjs +2 -0
  99. package/dist/InputDate-cjs.js +1 -0
  100. package/dist/InputDate-es.js +1 -0
  101. package/dist/InputNumber/index.cjs +2 -1
  102. package/dist/InputNumber/index.mjs +2 -1
  103. package/dist/InternalChipDismissible-cjs.js +1 -0
  104. package/dist/InternalChipDismissible-es.js +1 -0
  105. package/dist/LightBox/index.cjs +2 -0
  106. package/dist/LightBox/index.mjs +2 -0
  107. package/dist/LightBox-cjs.js +1 -0
  108. package/dist/LightBox-es.js +1 -0
  109. package/dist/Menu/index.cjs +2 -1
  110. package/dist/Menu/index.mjs +2 -1
  111. package/dist/Menu-cjs.js +6 -4
  112. package/dist/Menu-es.js +3 -1
  113. package/dist/MenuSubmenuTrigger-cjs.js +164 -206
  114. package/dist/MenuSubmenuTrigger-es.js +152 -194
  115. package/dist/Modal/index.cjs +3 -1
  116. package/dist/Modal/index.mjs +4 -2
  117. package/dist/NumberFieldInput-cjs.js +308 -187
  118. package/dist/NumberFieldInput-es.js +308 -187
  119. package/dist/Page/index.cjs +2 -1
  120. package/dist/Page/index.mjs +2 -1
  121. package/dist/Page-cjs.js +1 -0
  122. package/dist/Page-es.js +1 -0
  123. package/dist/Popover/index.cjs +2 -0
  124. package/dist/Popover/index.mjs +2 -0
  125. package/dist/Popover-cjs.js +9 -7
  126. package/dist/Popover-es.js +3 -1
  127. package/dist/ProgressBar-cjs.js +1 -0
  128. package/dist/ProgressBar-es.js +1 -0
  129. package/dist/ScrollAreaViewport-cjs.js +1093 -747
  130. package/dist/ScrollAreaViewport-es.js +1081 -734
  131. package/dist/Select/index.cjs +2 -1
  132. package/dist/Select/index.mjs +2 -1
  133. package/dist/SelectGroupLabel-cjs.js +306 -207
  134. package/dist/SelectGroupLabel-es.js +302 -203
  135. package/dist/SideDrawer-cjs.js +1 -0
  136. package/dist/SideDrawer-es.js +1 -0
  137. package/dist/Spinner-cjs.js +1 -0
  138. package/dist/Spinner-es.js +1 -0
  139. package/dist/Tooltip/index.cjs +2 -0
  140. package/dist/Tooltip/index.mjs +2 -0
  141. package/dist/Tooltip-cjs.js +7 -6
  142. package/dist/Tooltip-es.js +2 -1
  143. package/dist/dialogReturnFocus-cjs.js +1 -1
  144. package/dist/dialogReturnFocus-es.js +2 -2
  145. package/dist/floating-ui.react-cjs.js +192 -2564
  146. package/dist/floating-ui.react-dom-cjs.js +2103 -0
  147. package/dist/floating-ui.react-dom-es.js +2072 -0
  148. package/dist/floating-ui.react-es.js +156 -2519
  149. package/dist/floating-ui.utils-cjs.js +342 -0
  150. package/dist/floating-ui.utils-es.js +300 -0
  151. package/dist/index.cjs +4 -3
  152. package/dist/index.mjs +4 -3
  153. package/dist/primitives/BottomSheet/index.cjs +1 -1
  154. package/dist/primitives/BottomSheet/index.mjs +1 -1
  155. package/dist/primitives/ComboboxPrimitive/index.cjs +4 -2
  156. package/dist/primitives/ComboboxPrimitive/index.mjs +4 -2
  157. package/dist/primitives/SelectPrimitive/index.cjs +2 -0
  158. package/dist/primitives/SelectPrimitive/index.mjs +2 -0
  159. package/dist/primitives/index.cjs +3 -2
  160. package/dist/primitives/index.mjs +3 -2
  161. package/dist/scrollEdges-cjs.js +11 -1
  162. package/dist/scrollEdges-es.js +11 -1
  163. package/dist/sharedHelpers/i18n/index.cjs +1 -0
  164. package/dist/sharedHelpers/i18n/index.d.ts +1 -0
  165. package/dist/sharedHelpers/i18n/index.mjs +1 -1
  166. package/dist/sharedHelpers/i18n/releasedLanguages.d.ts +12 -0
  167. package/dist/sharedHelpers/i18n/useReleasedLocale.d.ts +6 -0
  168. package/dist/showToast-cjs.js +1 -1
  169. package/dist/showToast-es.js +1 -1
  170. package/dist/testUtils/releasedLanguages.d.ts +16 -0
  171. package/dist/unstyledPrimitives/index.cjs +478 -720
  172. package/dist/unstyledPrimitives/index.mjs +421 -663
  173. package/dist/useAtlantisI18n-cjs.js +44 -11
  174. package/dist/useAtlantisI18n-es.js +44 -12
  175. package/dist/useCompositeListItem-cjs.js +361 -2108
  176. package/dist/useCompositeListItem-es.js +331 -2076
  177. package/dist/useLabel-cjs.js +3 -2
  178. package/dist/useLabel-es.js +3 -2
  179. package/dist/useRenderElement-cjs.js +7 -9
  180. package/dist/useRenderElement-es.js +7 -9
  181. package/dist/useScrollLock-cjs.js +344 -819
  182. package/dist/useScrollLock-es.js +296 -732
  183. package/dist/useScrollToActive-cjs.js +5 -4
  184. package/dist/useScrollToActive-es.js +2 -1
  185. package/package.json +3 -3
  186. package/dist/scrollable-cjs.js +0 -58
  187. package/dist/scrollable-es.js +0 -54
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
- import { q as useTimeout, d as useStableCallback, u as useBaseUiId, c as useIsoLayoutEffect, S as SafeReact, r as error, t as transitionStatusMapping, s as useTransitionStatus, l as useOpenChangeComplete } from './useScrollLock-es.js';
3
- import { a as useFormContext, u as useLabelableContext, D as DEFAULT_VALIDITY_STATE, L as LabelableContext, f as fieldValidityMapping, F as FieldRootContext, b as useFieldRootContext } from './useCompositeListItem-es.js';
4
- import { a as useRefWithInit, m as mergeProps, E as EMPTY_OBJECT, f as formatErrorMessage, u as useRenderElement } from './useRenderElement-es.js';
2
+ import { u as useBaseUiId, b as useStableCallback, k as useTimeout, a as useIsoLayoutEffect, S as SafeReact, l as error, t as transitionStatusMapping, m as useTransitionStatus, f as useOpenChangeComplete } from './useScrollLock-es.js';
3
+ import { u as useLabelableContext, L as LabelableContext, a as useFormContext, D as DEFAULT_VALIDITY_STATE, f as fieldValidityMapping, F as FieldRootContext, b as useFieldRootContext } from './useCompositeListItem-es.js';
4
+ import { f as formatErrorMessage, a as useRefWithInit, m as mergeProps, E as EMPTY_OBJECT, u as useRenderElement } from './useRenderElement-es.js';
5
5
  import { jsx } from 'react/jsx-runtime';
6
6
  import { u as useLabel } from './useLabel-es.js';
7
7
 
@@ -14,6 +14,77 @@ function useFieldItemContext() {
14
14
  return context;
15
15
  }
16
16
 
17
+ const FieldsetRootContext = /*#__PURE__*/React.createContext(undefined);
18
+ if (process.env.NODE_ENV !== "production") FieldsetRootContext.displayName = "FieldsetRootContext";
19
+ function useFieldsetRootContext(optional = false) {
20
+ const context = React.useContext(FieldsetRootContext);
21
+ if (!context && !optional) {
22
+ throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: FieldsetRootContext is missing. Fieldset parts must be placed within <Fieldset.Root>.' : formatErrorMessage(86));
23
+ }
24
+ return context;
25
+ }
26
+
27
+ const LabelableProvider = function LabelableProvider(props) {
28
+ const defaultId = useBaseUiId();
29
+ const initialControlId = props.controlId === undefined ? defaultId : props.controlId;
30
+ const [controlId, setControlIdState] = React.useState(initialControlId);
31
+ const [labelId, setLabelId] = React.useState(props.labelId);
32
+ const [messageIds, setMessageIds] = React.useState([]);
33
+ const registrationsRef = useRefWithInit(() => new Map());
34
+ const {
35
+ messageIds: parentMessageIds
36
+ } = useLabelableContext();
37
+ const registerControlId = useStableCallback((source, nextId) => {
38
+ const registrations = registrationsRef.current;
39
+ if (nextId === undefined) {
40
+ registrations.delete(source);
41
+ return;
42
+ }
43
+ registrations.set(source, nextId);
44
+
45
+ // Only flush when registering, not when unregistering.
46
+ // This prevents loops during rapid unmount/remount cycles (e.g. React Activity).
47
+ // The next registration will pick up the correct state.
48
+ setControlIdState(prev => {
49
+ if (registrations.size === 0) {
50
+ return undefined;
51
+ }
52
+ let nextControlId;
53
+ for (const id of registrations.values()) {
54
+ if (prev !== undefined && id === prev) {
55
+ return prev;
56
+ }
57
+ if (nextControlId === undefined) {
58
+ nextControlId = id;
59
+ }
60
+ }
61
+ return nextControlId;
62
+ });
63
+ });
64
+ const getDescriptionProps = React.useCallback(externalProps => {
65
+ const ids = externalProps['aria-describedby'] ? externalProps['aria-describedby'].split(' ') : [];
66
+ ids.push(...parentMessageIds, ...messageIds);
67
+ return {
68
+ ...externalProps,
69
+ 'aria-describedby': Array.from(new Set(ids)).join(' ') || undefined
70
+ };
71
+ }, [parentMessageIds, messageIds]);
72
+ const contextValue = React.useMemo(() => ({
73
+ controlId,
74
+ registerControlId,
75
+ labelId,
76
+ setLabelId,
77
+ messageIds,
78
+ setMessageIds,
79
+ getDescriptionProps
80
+ }), [controlId, registerControlId, labelId, setLabelId, messageIds, setMessageIds, getDescriptionProps]);
81
+ return /*#__PURE__*/jsx(LabelableContext.Provider, {
82
+ value: contextValue,
83
+ children: props.children
84
+ });
85
+ };
86
+ if (process.env.NODE_ENV !== "production") LabelableProvider.displayName = "LabelableProvider";
87
+
17
88
  /**
18
89
  * Combines the field's client-side, stateful validity data with the external invalid state to
19
90
  * determine the field's true validity.
@@ -29,35 +100,34 @@ function getCombinedFieldValidityData(validityData, invalid) {
29
100
  }
30
101
 
31
102
  const validityKeys = Object.keys(DEFAULT_VALIDITY_STATE);
32
- /**
33
- * Whether an input participates in the surrounding Base UI Form. Inputs that are effectively
34
- * disabled, or whose `form` attribute explicitly associates them with another form, are excluded.
35
- * DOM position only matters when it associates the input with a different form. Otherwise, field
36
- * registration is context-driven, so portaled inputs (for example inside a dialog) still belong to
37
- * the form for both validation and values projected into `onFormSubmit`.
38
- */
39
- function isEligibleInput(input, formElement) {
40
- if (input.matches(':disabled')) {
103
+ function isOnlyValueMissing(state) {
104
+ if (!state || state.valid || !state.valueMissing) {
41
105
  return false;
42
106
  }
43
- if (!formElement || input.form === formElement) {
44
- return true;
107
+ let onlyValueMissing = false;
108
+ for (const key of validityKeys) {
109
+ if (key === 'valid') {
110
+ continue;
111
+ }
112
+ if (key === 'valueMissing') {
113
+ onlyValueMissing = state[key];
114
+ } else if (state[key]) {
115
+ onlyValueMissing = false;
116
+ }
45
117
  }
46
-
47
- // React context crosses portal boundaries. An unassociated portaled input still participates in
48
- // contextual validation, unless an explicit `form` attribute opts it out of the surrounding Form.
49
- return input.form === null && !input.hasAttribute('form');
118
+ return onlyValueMissing;
50
119
  }
51
120
 
52
121
  /**
53
122
  * Picks the input whose native validity should represent a field that owns several inputs (such as a
54
- * checkbox or radio group). Prefers the first eligible currently-invalid input, where "first" follows
55
- * registration order (mount order), and otherwise returns the first eligible input.
123
+ * checkbox group). Prefers the first enabled currently-invalid input, where "first" follows Set
124
+ * insertion order (mount order), and otherwise returns the first enabled input. Disabled inputs are
125
+ * skipped because they don't participate in native constraint validation.
56
126
  */
57
- function findRepresentativeInput(inputs, formElement) {
127
+ function findRepresentativeInput(inputs) {
58
128
  let fallback = null;
59
- for (const input of inputs.keys()) {
60
- if (!isEligibleInput(input, formElement)) {
129
+ for (const input of inputs) {
130
+ if (input.disabled) {
61
131
  continue;
62
132
  }
63
133
  if (!input.validity.valid) {
@@ -68,14 +138,17 @@ function findRepresentativeInput(inputs, formElement) {
68
138
  return fallback;
69
139
  }
70
140
  function clearCustomValidity(element, inputs) {
71
- for (const input of inputs.keys()) {
141
+ let didClearElement = false;
142
+ for (const input of inputs) {
72
143
  input.setCustomValidity('');
144
+ didClearElement ||= input === element;
145
+ }
146
+ if (!didClearElement) {
147
+ element.setCustomValidity('');
73
148
  }
74
- element?.setCustomValidity('');
75
149
  }
76
150
  function useFieldValidation(params) {
77
151
  const {
78
- elementRef,
79
152
  formRef
80
153
  } = useFormContext();
81
154
  const {
@@ -87,7 +160,7 @@ function useFieldValidation(params) {
87
160
  markedDirtyRef,
88
161
  state,
89
162
  shouldValidateOnChange,
90
- registeredFieldIdRef
163
+ getRegisteredFieldId
91
164
  } = params;
92
165
  const {
93
166
  controlId,
@@ -95,27 +168,32 @@ function useFieldValidation(params) {
95
168
  } = useLabelableContext();
96
169
  const timeout = useTimeout();
97
170
  const inputRef = React.useRef(null);
98
- const registeredInputs = useRefWithInit(() => new Map()).current;
171
+ const registeredInputs = useRefWithInit(() => new Set()).current;
99
172
  const validationCommitIdRef = React.useRef(0);
100
173
 
101
- // Groups register several inputs against a single field so focus, validation, and form-value
102
- // projection can use the same live controls. This also ensures a `required` checkbox can't be
103
- // satisfied by another input in the group, matching native per-checkbox behavior.
104
- const registerInput = React.useCallback((element, registration) => {
105
- registeredInputs.set(element, registration);
174
+ // Checkbox groups register several inputs against a single field. Track them so a `required`
175
+ // checkbox can't be satisfied by another input in the group, matching native per-checkbox behavior.
176
+ const registerInput = React.useCallback(element => {
177
+ if (!element) {
178
+ return undefined;
179
+ }
180
+ registeredInputs.add(element);
106
181
  return () => {
107
182
  registeredInputs.delete(element);
108
183
  };
109
184
  }, [registeredInputs]);
110
- const getInputControl = useStableCallback(() => {
111
- const element = findRepresentativeInput(registeredInputs, elementRef.current);
112
- return element && registeredInputs.get(element)?.controlRef.current || null;
113
- });
114
185
  const commit = useStableCallback(async (value, revalidate = false) => {
186
+ // A field can own several inputs (a checkbox group), but only the last-mounted one wins the shared
187
+ // `inputRef`. Validate against the registry instead so every input counts; `inputRef` is the
188
+ // fallback only when no registered input applies (none registered, or all of them disabled).
189
+ const element = findRepresentativeInput(registeredInputs) ?? inputRef.current;
190
+ if (!element) {
191
+ return;
192
+ }
115
193
  validationCommitIdRef.current += 1;
116
194
  const validationCommitId = validationCommitIdRef.current;
117
195
  function updateRegisteredFieldValidity(nextValidityData, externalInvalid = invalid) {
118
- const fieldId = registeredFieldIdRef.current ?? controlId;
196
+ const fieldId = getRegisteredFieldId() ?? controlId;
119
197
  if (fieldId == null) {
120
198
  return;
121
199
  }
@@ -129,31 +207,8 @@ function useFieldValidation(params) {
129
207
  validityData: validityDataWithFormErrors
130
208
  });
131
209
  }
132
- function publishAllValid(input, externalInvalid) {
133
- const nextValidityData = {
134
- value,
135
- state: {
136
- ...DEFAULT_VALIDITY_STATE,
137
- valid: true
138
- },
139
- error: '',
140
- errors: [],
141
- initialValue: validityData.initialValue
142
- };
143
- clearCustomValidity(input, registeredInputs);
144
- updateRegisteredFieldValidity(nextValidityData, externalInvalid);
145
- setValidityData(nextValidityData);
146
- }
147
-
148
- // A field can own several inputs (such as a checkbox or radio group), but only the last-mounted
149
- // one wins the shared `inputRef`. Validate against the registry instead so every input counts;
150
- // `inputRef` is the fallback only when no inputs are registered.
151
- const element = registeredInputs.size > 0 ? findRepresentativeInput(registeredInputs, elementRef.current) : inputRef.current;
152
- // A field with no eligible input has no native constraint, but its custom validator still
153
- // applies to the logical value at the configured validation boundary.
154
-
155
210
  if (revalidate) {
156
- if (state.valid !== false || !element) {
211
+ if (state.valid !== false) {
157
212
  return;
158
213
  }
159
214
  const currentNativeValidity = element.validity;
@@ -161,20 +216,39 @@ function useFieldValidation(params) {
161
216
  // The 'valueMissing' (required) condition has been resolved by the user typing.
162
217
  // Temporarily mark the field as valid for this onChange event.
163
218
  // Other native errors (e.g., typeMismatch) will be caught by full validation on blur or submit.
219
+ const nextValidityData = {
220
+ value,
221
+ state: {
222
+ ...DEFAULT_VALIDITY_STATE,
223
+ valid: true
224
+ },
225
+ error: '',
226
+ errors: [],
227
+ initialValue: validityData.initialValue
228
+ };
229
+ clearCustomValidity(element, registeredInputs);
230
+
164
231
  // The required value is now present; ignore stale external invalid state for this pass.
165
- publishAllValid(element, false);
232
+ updateRegisteredFieldValidity(nextValidityData, false);
233
+ setValidityData(nextValidityData);
166
234
  return;
167
235
  }
168
236
 
169
- // A stale custom error can coexist with valueMissing, but defer any other native errors.
170
- for (const key of validityKeys) {
171
- if (key !== 'valid' && key !== 'valueMissing' && key !== 'customError' && currentNativeValidity[key]) {
172
- return;
173
- }
237
+ // Value is still missing, or other conditions apply.
238
+ // Let's use a representation of current validity for isOnlyValueMissing.
239
+ const currentNativeValidityObject = validityKeys.reduce((acc, key) => {
240
+ acc[key] = currentNativeValidity[key];
241
+ return acc;
242
+ }, {});
243
+
244
+ // If it's (still) natively invalid due to something other than just valueMissing,
245
+ // then bail from this revalidation on change to avoid "scolding" for other errors.
246
+ if (!currentNativeValidityObject.valid && !isOnlyValueMissing(currentNativeValidityObject)) {
247
+ return;
174
248
  }
175
249
 
176
- // Value is still missing: publish the current native state so valueMissing and the changed
177
- // value are observable immediately. Full custom validation still waits for its boundary.
250
+ // If valueMissing is still true AND it's the only issue, or if the field is now natively valid,
251
+ // let it fall through to the main validation logic below.
178
252
  }
179
253
  function getState(el) {
180
254
  const computedState = validityKeys.reduce((acc, key) => {
@@ -204,16 +278,10 @@ function useFieldValidation(params) {
204
278
  timeout.clear();
205
279
  let result = null;
206
280
  let validationErrors = [];
207
-
208
- // With no representative input the field carries no native constraint, so start from an
209
- // all-valid native state and let the custom `validate` result below decide the outcome.
210
- const nextState = element ? getState(element) : {
211
- ...DEFAULT_VALIDITY_STATE,
212
- valid: true
213
- };
281
+ const nextState = getState(element);
214
282
  let defaultValidationMessage;
215
283
  const isValidatingOnChange = shouldValidateOnChange();
216
- if (element && element.validationMessage && !isValidatingOnChange) {
284
+ if (element.validationMessage && !isValidatingOnChange) {
217
285
  // not validating on change, if there is a `validationMessage` from
218
286
  // native validity, set errors and skip calling the custom validate fn
219
287
  defaultValidationMessage = element.validationMessage;
@@ -242,20 +310,20 @@ function useFieldValidation(params) {
242
310
  nextState.customError = true;
243
311
  if (Array.isArray(result)) {
244
312
  validationErrors = result;
245
- element?.setCustomValidity(result.join('\n'));
313
+ element.setCustomValidity(result.join('\n'));
246
314
  } else if (result) {
247
315
  validationErrors = [result];
248
- element?.setCustomValidity(result);
316
+ element.setCustomValidity(result);
249
317
  }
250
318
  } else if (isValidatingOnChange) {
251
319
  // validate function returned no errors, if validating on change
252
320
  // we need to clear the custom validity state
253
321
  clearCustomValidity(element, registeredInputs);
254
322
  nextState.customError = false;
255
- if (element && element.validationMessage) {
323
+ if (element.validationMessage) {
256
324
  defaultValidationMessage = element.validationMessage;
257
325
  validationErrors = [element.validationMessage];
258
- } else if ((!element || element.validity.valid) && !nextState.valid) {
326
+ } else if (element.validity.valid && !nextState.valid) {
259
327
  nextState.valid = true;
260
328
  }
261
329
  }
@@ -290,85 +358,12 @@ function useFieldValidation(params) {
290
358
  return React.useMemo(() => ({
291
359
  getValidationProps,
292
360
  inputRef,
293
- registeredInputs,
294
361
  registerInput,
295
- getInputControl,
296
362
  commit,
297
363
  change
298
- }), [getValidationProps, registeredInputs, registerInput, getInputControl, commit, change]);
364
+ }), [getValidationProps, registerInput, commit, change]);
299
365
  }
300
366
 
301
- const FieldsetRootContext = /*#__PURE__*/React.createContext(undefined);
302
- if (process.env.NODE_ENV !== "production") FieldsetRootContext.displayName = "FieldsetRootContext";
303
- function useFieldsetRootContext(optional = false) {
304
- const context = React.useContext(FieldsetRootContext);
305
- if (!context && !optional) {
306
- throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: FieldsetRootContext is missing. Fieldset parts must be placed within <Fieldset.Root>.' : formatErrorMessage(86));
307
- }
308
- return context;
309
- }
310
-
311
- const LabelableProvider = function LabelableProvider(props) {
312
- const defaultId = useBaseUiId();
313
- const initialControlId = props.controlId === undefined ? defaultId : props.controlId;
314
- const [controlId, setControlIdState] = React.useState(initialControlId);
315
- const [labelId, setLabelId] = React.useState(props.labelId);
316
- const [messageIds, setMessageIds] = React.useState([]);
317
- const registrationsRef = useRefWithInit(() => new Map());
318
- const {
319
- messageIds: parentMessageIds
320
- } = useLabelableContext();
321
- const registerControlId = useStableCallback((source, nextId) => {
322
- const registrations = registrationsRef.current;
323
- if (nextId === undefined) {
324
- registrations.delete(source);
325
- return;
326
- }
327
- registrations.set(source, nextId);
328
-
329
- // Only flush when registering, not when unregistering.
330
- // This prevents loops during rapid unmount/remount cycles (e.g. React Activity).
331
- // The next registration will pick up the correct state.
332
- setControlIdState(prev => {
333
- if (registrations.size === 0) {
334
- return undefined;
335
- }
336
- let nextControlId;
337
- for (const id of registrations.values()) {
338
- if (prev !== undefined && id === prev) {
339
- return prev;
340
- }
341
- if (nextControlId === undefined) {
342
- nextControlId = id;
343
- }
344
- }
345
- return nextControlId;
346
- });
347
- });
348
- const getDescriptionProps = React.useCallback(externalProps => {
349
- const ids = externalProps['aria-describedby'] ? externalProps['aria-describedby'].split(' ') : [];
350
- ids.push(...parentMessageIds, ...messageIds);
351
- return {
352
- ...externalProps,
353
- 'aria-describedby': Array.from(new Set(ids)).join(' ') || undefined
354
- };
355
- }, [parentMessageIds, messageIds]);
356
- const contextValue = React.useMemo(() => ({
357
- controlId,
358
- registerControlId,
359
- labelId,
360
- setLabelId,
361
- messageIds,
362
- setMessageIds,
363
- getDescriptionProps
364
- }), [controlId, registerControlId, labelId, setLabelId, messageIds, setMessageIds, getDescriptionProps]);
365
- return /*#__PURE__*/jsx(LabelableContext.Provider, {
366
- value: contextValue,
367
- children: props.children
368
- });
369
- };
370
- if (process.env.NODE_ENV !== "production") LabelableProvider.displayName = "LabelableProvider";
371
-
372
367
  function useFieldControlRegistration(params) {
373
368
  const {
374
369
  commit,
@@ -376,7 +371,7 @@ function useFieldControlRegistration(params) {
376
371
  markedDirtyRef,
377
372
  name,
378
373
  setRegisteredFieldName,
379
- registeredFieldIdRef,
374
+ setRegisteredFieldId,
380
375
  setValidityData,
381
376
  validityData
382
377
  } = params;
@@ -385,7 +380,7 @@ function useFieldControlRegistration(params) {
385
380
  } = useFormContext();
386
381
  const activeFieldControlSourceRef = React.useRef(null);
387
382
  const registrationRef = React.useRef(null);
388
- const initialValueCapturedRef = React.useRef(false);
383
+ const fallbackControlRef = React.useRef(null);
389
384
  const getValueForForm = useStableCallback(() => {
390
385
  const registration = registrationRef.current;
391
386
  if (!registration) {
@@ -416,7 +411,7 @@ function useFieldControlRegistration(params) {
416
411
  formRef.current.fields.set(registration.id, {
417
412
  getValue: getValueForForm,
418
413
  name: name ?? registration.name,
419
- controlRef: registration.controlRef,
414
+ controlRef: registration.controlRef ?? fallbackControlRef,
420
415
  validityData: getCombinedFieldValidityData(validityData, invalid),
421
416
  validate
422
417
  });
@@ -426,23 +421,18 @@ function useFieldControlRegistration(params) {
426
421
  formRef.current.fields.delete(id);
427
422
  }
428
423
  }
429
-
430
- // The baseline belongs to the field, not to a control instance: registration re-runs on every
431
- // value change, and a control that unmounts and remounts (or is swapped for another one) comes
432
- // back as a brand new registration. Capturing more than once would turn whichever value the
433
- // control happens to hold at that point into the initial value, so a modified field would read
434
- // pristine and its real initial value would read dirty. Consumers that want a fresh baseline
435
- // remount or key `<Field.Root>` itself.
436
- function captureInitialValue(registration) {
437
- if (initialValueCapturedRef.current) {
424
+ function syncInitialValue() {
425
+ const registration = registrationRef.current;
426
+ if (!registration) {
438
427
  return;
439
428
  }
440
- initialValueCapturedRef.current = true;
441
429
  const initialValue = getRegistrationValue(registration);
442
- setValidityData(prev => prev.initialValue === initialValue ? prev : {
443
- ...prev,
444
- initialValue
445
- });
430
+ if (validityData.initialValue === null && initialValue !== null) {
431
+ setValidityData(prev => ({
432
+ ...prev,
433
+ initialValue
434
+ }));
435
+ }
446
436
  }
447
437
  useIsoLayoutEffect(() => {
448
438
  const registration = registrationRef.current;
@@ -453,7 +443,7 @@ function useFieldControlRegistration(params) {
453
443
  formRef.current.fields.set(registration.id, {
454
444
  getValue: getValueForForm,
455
445
  name: name ?? registration.name,
456
- controlRef: registration.controlRef,
446
+ controlRef: registration.controlRef ?? fallbackControlRef,
457
447
  validityData: getCombinedFieldValidityData(validityData, invalid),
458
448
  validate
459
449
  });
@@ -474,7 +464,7 @@ function useFieldControlRegistration(params) {
474
464
  deleteRegistration();
475
465
  registrationRef.current = null;
476
466
  setRegisteredFieldName(undefined);
477
- registeredFieldIdRef.current = undefined;
467
+ setRegisteredFieldId(undefined);
478
468
  }
479
469
  return;
480
470
  }
@@ -484,11 +474,11 @@ function useFieldControlRegistration(params) {
484
474
  if (!name) {
485
475
  setRegisteredFieldName(registration.name);
486
476
  }
487
- registeredFieldIdRef.current = registration.id;
477
+ setRegisteredFieldId(registration.id);
488
478
  if (previousId && previousId !== registration.id) {
489
479
  deleteRegistration(previousId);
490
480
  }
491
- captureInitialValue(registration);
481
+ syncInitialValue();
492
482
  refreshRegistration();
493
483
  });
494
484
  return [validate, register];
@@ -533,6 +523,10 @@ const FieldRootInner = /*#__PURE__*/React.forwardRef(function FieldRootInner(com
533
523
  markedDirtyRef.current = dirtyProp;
534
524
  }
535
525
  }, [dirtyProp]);
526
+ const getRegisteredFieldId = React.useCallback(() => registeredFieldIdRef.current, []);
527
+ const setRegisteredFieldId = React.useCallback(id => {
528
+ registeredFieldIdRef.current = id;
529
+ }, []);
536
530
  const setDirty = useStableCallback(value => {
537
531
  if (dirtyProp !== undefined) {
538
532
  return;
@@ -559,11 +553,7 @@ const FieldRootInner = /*#__PURE__*/React.forwardRef(function FieldRootInner(com
559
553
  value: null,
560
554
  initialValue: null
561
555
  });
562
-
563
- // App-controlled invalidity (the `invalid` prop and `<Form>` errors) keeps the field marked
564
- // invalid even while disabled. Only computed validity (native constraints and `validate`)
565
- // is suppressed when disabled, matching `:disabled` not participating in constraint validation.
566
- const valid = !invalid && (disabled ? null : validityData.state.valid);
556
+ const valid = disabled ? null : !invalid && validityData.state.valid;
567
557
  const state = React.useMemo(() => ({
568
558
  disabled,
569
559
  touched,
@@ -581,7 +571,7 @@ const FieldRootInner = /*#__PURE__*/React.forwardRef(function FieldRootInner(com
581
571
  markedDirtyRef,
582
572
  state,
583
573
  shouldValidateOnChange,
584
- registeredFieldIdRef
574
+ getRegisteredFieldId
585
575
  });
586
576
  const [validateFieldControl, registerFieldControl] = useFieldControlRegistration({
587
577
  commit: validation.commit,
@@ -589,7 +579,7 @@ const FieldRootInner = /*#__PURE__*/React.forwardRef(function FieldRootInner(com
589
579
  markedDirtyRef,
590
580
  name,
591
581
  setRegisteredFieldName,
592
- registeredFieldIdRef,
582
+ setRegisteredFieldId,
593
583
  setValidityData,
594
584
  validityData
595
585
  });
@@ -602,16 +592,23 @@ const FieldRootInner = /*#__PURE__*/React.forwardRef(function FieldRootInner(com
602
592
  validityData,
603
593
  setValidityData,
604
594
  disabled,
595
+ touched,
605
596
  setTouched,
597
+ dirty,
606
598
  setDirty,
599
+ filled,
607
600
  setFilled,
601
+ focused,
608
602
  setFocused,
603
+ validate,
609
604
  validationMode,
605
+ validationDebounceTime,
610
606
  shouldValidateOnChange,
611
607
  state,
608
+ markedDirtyRef,
612
609
  registerFieldControl,
613
610
  validation
614
- }), [invalid, effectiveName, validityData, disabled, setTouched, setDirty, setFilled, setFocused, validationMode, shouldValidateOnChange, state, registerFieldControl, validation]);
611
+ }), [invalid, effectiveName, validityData, disabled, touched, setTouched, dirty, setDirty, filled, setFilled, focused, setFocused, validate, validationMode, validationDebounceTime, shouldValidateOnChange, state, registerFieldControl, validation]);
615
612
  const element = useRenderElement('div', componentProps, {
616
613
  ref: forwardedRef,
617
614
  state,
@@ -768,13 +765,13 @@ const FieldError = /*#__PURE__*/React.forwardRef(function FieldError(componentPr
768
765
  } else if (validityData.errors.length > 1) {
769
766
  error = validityData.errors;
770
767
  }
771
- let errorMessage = error;
768
+ let errorMessage = error ?? '';
772
769
  if (Array.isArray(error)) {
773
770
  errorMessage = error.length > 1 ? /*#__PURE__*/jsx("ul", {
774
771
  children: error.map(message => /*#__PURE__*/jsx("li", {
775
772
  children: message
776
773
  }, message))
777
- }) : error[0];
774
+ }) : error[0] ?? '';
778
775
  }
779
776
  const errorKey = Array.isArray(error) ? JSON.stringify(error) : error;
780
777
  if (rendered && errorKey !== lastRenderedMessageKey) {
@@ -18,8 +18,10 @@ require('../../../useAtlantisI18n-cjs.js');
18
18
  require('../../../AtlantisContext-cjs.js');
19
19
  require('../../../Tooltip-cjs.js');
20
20
  require('../../../floating-ui.react-cjs.js');
21
+ require('../../../floating-ui.utils-cjs.js');
21
22
  require('react/jsx-runtime');
22
23
  require('react-dom');
24
+ require('../../../floating-ui.react-dom-cjs.js');
23
25
  require('framer-motion');
24
26
  require('../../../FilterPickerProvider-cjs.js');
25
27
  require('../../../constants-cjs.js');
@@ -16,8 +16,10 @@ import '../../../useAtlantisI18n-es.js';
16
16
  import '../../../AtlantisContext-es.js';
17
17
  import '../../../Tooltip-es.js';
18
18
  import '../../../floating-ui.react-es.js';
19
+ import '../../../floating-ui.utils-es.js';
19
20
  import 'react/jsx-runtime';
20
21
  import 'react-dom';
22
+ import '../../../floating-ui.react-dom-es.js';
21
23
  import 'framer-motion';
22
24
  import '../../../FilterPickerProvider-es.js';
23
25
  import '../../../constants-es.js';
@@ -4,8 +4,10 @@ var FilterPickerContent = require('../../../FilterPickerContent-cjs.js');
4
4
  require('react');
5
5
  require('classnames');
6
6
  require('../../../floating-ui.react-cjs.js');
7
+ require('../../../floating-ui.utils-cjs.js');
7
8
  require('react/jsx-runtime');
8
9
  require('react-dom');
10
+ require('../../../floating-ui.react-dom-cjs.js');
9
11
  require('../../../FilterPickerContentSearch-cjs.js');
10
12
  require('../../../Icon-cjs.js');
11
13
  require('@jobber/design');
@@ -2,8 +2,10 @@ export { F as FilterPickerContent } from '../../../FilterPickerContent-es.js';
2
2
  import 'react';
3
3
  import 'classnames';
4
4
  import '../../../floating-ui.react-es.js';
5
+ import '../../../floating-ui.utils-es.js';
5
6
  import 'react/jsx-runtime';
6
7
  import 'react-dom';
8
+ import '../../../floating-ui.react-dom-es.js';
7
9
  import '../../../FilterPickerContentSearch-es.js';
8
10
  import '../../../Icon-es.js';
9
11
  import '@jobber/design';
@@ -16,8 +16,10 @@ require('../../../AtlantisContext-cjs.js');
16
16
  require('../../../Typography-cjs.js');
17
17
  require('../../../Tooltip-cjs.js');
18
18
  require('../../../floating-ui.react-cjs.js');
19
+ require('../../../floating-ui.utils-cjs.js');
19
20
  require('react/jsx-runtime');
20
21
  require('react-dom');
22
+ require('../../../floating-ui.react-dom-cjs.js');
21
23
  require('framer-motion');
22
24
  require('../../../FilterPickerProvider-cjs.js');
23
25
 
@@ -14,7 +14,9 @@ import '../../../AtlantisContext-es.js';
14
14
  import '../../../Typography-es.js';
15
15
  import '../../../Tooltip-es.js';
16
16
  import '../../../floating-ui.react-es.js';
17
+ import '../../../floating-ui.utils-es.js';
17
18
  import 'react/jsx-runtime';
18
19
  import 'react-dom';
20
+ import '../../../floating-ui.react-dom-es.js';
19
21
  import 'framer-motion';
20
22
  import '../../../FilterPickerProvider-es.js';