@radix-ng/primitives 1.1.0 → 1.1.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.
- package/fesm2022/radix-ng-primitives-autocomplete.mjs +66 -7
- package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-checkbox.mjs +147 -125
- package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-combobox.mjs +171 -37
- package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-core.mjs +173 -5
- package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-number-field.mjs +38 -7
- package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-radio.mjs +49 -2
- package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-select.mjs +35 -3
- package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-slider.mjs +17 -2
- package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-switch.mjs +60 -7
- package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toggle-group.mjs +25 -3
- package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
- package/package.json +1 -1
- package/types/radix-ng-primitives-autocomplete.d.ts +10 -1
- package/types/radix-ng-primitives-checkbox.d.ts +56 -43
- package/types/radix-ng-primitives-combobox.d.ts +46 -2
- package/types/radix-ng-primitives-core.d.ts +62 -4
- package/types/radix-ng-primitives-number-field.d.ts +12 -5
- package/types/radix-ng-primitives-radio.d.ts +6 -1
- package/types/radix-ng-primitives-select.d.ts +8 -1
- package/types/radix-ng-primitives-slider.d.ts +2 -1
- package/types/radix-ng-primitives-switch.d.ts +19 -3
- package/types/radix-ng-primitives-toggle-group.d.ts +5 -1
|
@@ -153,6 +153,7 @@ function injectNgControlState() {
|
|
|
153
153
|
const touched = signal(false, { debugName: 'RdxNgControlState.touched' });
|
|
154
154
|
let destroyed = false;
|
|
155
155
|
let unsubscribe;
|
|
156
|
+
let resetControl;
|
|
156
157
|
const connect = () => {
|
|
157
158
|
if (destroyed) {
|
|
158
159
|
return;
|
|
@@ -164,6 +165,7 @@ function injectNgControlState() {
|
|
|
164
165
|
if (!control || typeof control.events?.subscribe !== 'function') {
|
|
165
166
|
return;
|
|
166
167
|
}
|
|
168
|
+
resetControl = (nextValue) => control.reset(nextValue);
|
|
167
169
|
const sync = () => {
|
|
168
170
|
name.set(ngControl.name == null ? undefined : String(ngControl.name));
|
|
169
171
|
value.set(control.value);
|
|
@@ -197,7 +199,14 @@ function injectNgControlState() {
|
|
|
197
199
|
disabled: disabled.asReadonly(),
|
|
198
200
|
errors,
|
|
199
201
|
dirty: dirty.asReadonly(),
|
|
200
|
-
touched: touched.asReadonly()
|
|
202
|
+
touched: touched.asReadonly(),
|
|
203
|
+
reset: (nextValue) => {
|
|
204
|
+
if (!resetControl) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
resetControl(nextValue);
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
201
210
|
};
|
|
202
211
|
}
|
|
203
212
|
|
|
@@ -1987,11 +1996,30 @@ function itemToStringLabel(value) {
|
|
|
1987
1996
|
return String(value);
|
|
1988
1997
|
}
|
|
1989
1998
|
/**
|
|
1990
|
-
* Converts an item value to the string used for form serialization.
|
|
1991
|
-
*
|
|
1999
|
+
* Converts an item value to the string used for form serialization. A conventional `{ value, label }`
|
|
2000
|
+
* item serializes its `value` member; other non-string values use Base UI-compatible JSON serialization
|
|
2001
|
+
* with `String()` as a fallback. Kept separate so a primitive can diverge label vs. value.
|
|
1992
2002
|
*/
|
|
1993
2003
|
function itemToStringValue(value) {
|
|
1994
|
-
|
|
2004
|
+
if (value !== null && typeof value === 'object' && 'value' in value && 'label' in value) {
|
|
2005
|
+
return serializeValue(value.value);
|
|
2006
|
+
}
|
|
2007
|
+
return serializeValue(value);
|
|
2008
|
+
}
|
|
2009
|
+
/** Base UI-compatible serialization fallback for native form values. */
|
|
2010
|
+
function serializeValue(value) {
|
|
2011
|
+
if (isNullish(value)) {
|
|
2012
|
+
return '';
|
|
2013
|
+
}
|
|
2014
|
+
if (typeof value === 'string') {
|
|
2015
|
+
return value;
|
|
2016
|
+
}
|
|
2017
|
+
try {
|
|
2018
|
+
return JSON.stringify(value) ?? String(value);
|
|
2019
|
+
}
|
|
2020
|
+
catch {
|
|
2021
|
+
return String(value);
|
|
2022
|
+
}
|
|
1995
2023
|
}
|
|
1996
2024
|
/**
|
|
1997
2025
|
* Compares two item values for equality using an optional {@link ItemValueComparator}.
|
|
@@ -2364,6 +2392,14 @@ class RdxFormUiControlBase {
|
|
|
2364
2392
|
formUiTouchTarget() {
|
|
2365
2393
|
return null;
|
|
2366
2394
|
}
|
|
2395
|
+
/**
|
|
2396
|
+
* Resets a same-host Reactive/template-driven control without reporting the reset as a user edit.
|
|
2397
|
+
* Returns `false` when no Angular `NgControl` is connected, so a control can fall back to its CVA
|
|
2398
|
+
* change callback for an unusually early native reset.
|
|
2399
|
+
*/
|
|
2400
|
+
resetNgControl(value) {
|
|
2401
|
+
return this.ngControlState.reset(value);
|
|
2402
|
+
}
|
|
2367
2403
|
/**
|
|
2368
2404
|
* Reset control-owned interaction state. Angular Signal Forms calls this optional custom-control
|
|
2369
2405
|
* hook from `FieldState.reset()` after restoring the field value.
|
|
@@ -3367,6 +3403,138 @@ function getActiveElement(root = document) {
|
|
|
3367
3403
|
return activeElement;
|
|
3368
3404
|
}
|
|
3369
3405
|
|
|
3406
|
+
/**
|
|
3407
|
+
* Converts a scalar or array model to HTML form values. `null` and `undefined` represent no
|
|
3408
|
+
* successful control; arrays deliberately become repeated entries under the same field name.
|
|
3409
|
+
*/
|
|
3410
|
+
function serializeNativeFormValue(value, itemToStringValue$1 = itemToStringValue) {
|
|
3411
|
+
const values = Array.isArray(value) ? value : [value];
|
|
3412
|
+
return values.flatMap((entry) => (entry == null ? [] : [itemToStringValue$1(entry)]));
|
|
3413
|
+
}
|
|
3414
|
+
const NOOP_NATIVE_FORM_CONTROL = {
|
|
3415
|
+
ownerForm: () => null,
|
|
3416
|
+
sync: () => undefined,
|
|
3417
|
+
requestSubmit: () => undefined
|
|
3418
|
+
};
|
|
3419
|
+
/**
|
|
3420
|
+
* Adds native form semantics to a composite control, rendering hidden inputs only when the control
|
|
3421
|
+
* has no native successful control of its own.
|
|
3422
|
+
*
|
|
3423
|
+
* A hidden input is necessary for a headless root to enter the platform's successful-controls tree
|
|
3424
|
+
* (including older engines that do not dispatch `formdata` for `new FormData(form)`). One input is
|
|
3425
|
+
* created per serialized value, preserving repeated-field semantics; controls with their own native
|
|
3426
|
+
* input use this solely for reset and imperative-submit coordination.
|
|
3427
|
+
*
|
|
3428
|
+
* Generated inputs are browser-only. Rendering imperative sibling nodes on the server would put DOM
|
|
3429
|
+
* outside Angular's hydration graph; the client creates them after its view has been claimed instead.
|
|
3430
|
+
*/
|
|
3431
|
+
function useNativeFormControl(options) {
|
|
3432
|
+
const host = inject(ElementRef).nativeElement;
|
|
3433
|
+
const ownerDocument = host.ownerDocument;
|
|
3434
|
+
const destroyRef = inject(DestroyRef);
|
|
3435
|
+
if (!ownerDocument || !isPlatformBrowser(inject(PLATFORM_ID))) {
|
|
3436
|
+
return NOOP_NATIVE_FORM_CONTROL;
|
|
3437
|
+
}
|
|
3438
|
+
const inputs = [];
|
|
3439
|
+
let defaultValue;
|
|
3440
|
+
let defaultValues = [];
|
|
3441
|
+
let hasDefaultValue = false;
|
|
3442
|
+
let alive = true;
|
|
3443
|
+
let viewClaimed = false;
|
|
3444
|
+
const ownerForm = () => {
|
|
3445
|
+
const formId = options.form();
|
|
3446
|
+
const candidate = formId
|
|
3447
|
+
? ownerDocument.getElementById(formId)
|
|
3448
|
+
: typeof host.closest === 'function'
|
|
3449
|
+
? host.closest('form')
|
|
3450
|
+
: host.parentElement?.closest('form');
|
|
3451
|
+
return candidate?.localName === 'form' ? candidate : null;
|
|
3452
|
+
};
|
|
3453
|
+
const sync = () => {
|
|
3454
|
+
options.syncNativeControl?.();
|
|
3455
|
+
const name = options.name();
|
|
3456
|
+
const form = options.form();
|
|
3457
|
+
const disabled = options.disabled();
|
|
3458
|
+
const nativeControlOwnsValue = options.hasNativeControl?.() ?? false;
|
|
3459
|
+
const values = options.value && options.serialize ? options.serialize(options.value()) : [];
|
|
3460
|
+
// During hydration Angular must claim every server-rendered sibling before an imperative input
|
|
3461
|
+
// can be inserted. The after-render callback below performs the first DOM synchronization.
|
|
3462
|
+
if (!viewClaimed) {
|
|
3463
|
+
return;
|
|
3464
|
+
}
|
|
3465
|
+
const shouldRender = Boolean(name && options.serialize && !nativeControlOwnsValue);
|
|
3466
|
+
const count = shouldRender ? values.length : 0;
|
|
3467
|
+
while (inputs.length > count) {
|
|
3468
|
+
inputs.pop()?.remove();
|
|
3469
|
+
}
|
|
3470
|
+
while (inputs.length < count) {
|
|
3471
|
+
const input = ownerDocument.createElement('input');
|
|
3472
|
+
input.type = 'hidden';
|
|
3473
|
+
const previous = inputs.at(-1);
|
|
3474
|
+
host.parentNode?.insertBefore(input, previous ? previous.nextSibling : host.nextSibling);
|
|
3475
|
+
inputs.push(input);
|
|
3476
|
+
}
|
|
3477
|
+
for (let index = 0; index < inputs.length; index++) {
|
|
3478
|
+
const input = inputs[index];
|
|
3479
|
+
input.name = name;
|
|
3480
|
+
input.value = values[index];
|
|
3481
|
+
input.disabled = disabled;
|
|
3482
|
+
if (form) {
|
|
3483
|
+
input.setAttribute('form', form);
|
|
3484
|
+
}
|
|
3485
|
+
else {
|
|
3486
|
+
input.removeAttribute('form');
|
|
3487
|
+
}
|
|
3488
|
+
// Native reset reads `defaultValue`; retain the original default rather than accidentally
|
|
3489
|
+
// promoting later user edits to the reset baseline.
|
|
3490
|
+
if (!input.hasAttribute('data-rdx-native-form-control')) {
|
|
3491
|
+
input.defaultValue = defaultValues[index] ?? values[index];
|
|
3492
|
+
input.setAttribute('data-rdx-native-form-control', '');
|
|
3493
|
+
}
|
|
3494
|
+
}
|
|
3495
|
+
};
|
|
3496
|
+
effect(() => {
|
|
3497
|
+
if (!hasDefaultValue && options.defaultValue) {
|
|
3498
|
+
defaultValue = options.defaultValue();
|
|
3499
|
+
defaultValues = options.serialize ? options.serialize(defaultValue) : [];
|
|
3500
|
+
hasDefaultValue = true;
|
|
3501
|
+
}
|
|
3502
|
+
});
|
|
3503
|
+
effect(sync);
|
|
3504
|
+
afterNextRender(() => {
|
|
3505
|
+
viewClaimed = true;
|
|
3506
|
+
untracked(sync);
|
|
3507
|
+
});
|
|
3508
|
+
const onReset = (event) => {
|
|
3509
|
+
if (event.target !== ownerForm() || !options.onReset || !hasDefaultValue) {
|
|
3510
|
+
return;
|
|
3511
|
+
}
|
|
3512
|
+
// Native controls reset after the event. Check `defaultPrevented` in the microtask so a later
|
|
3513
|
+
// bubble listener can still cancel the reset before the model follows it.
|
|
3514
|
+
queueMicrotask(() => {
|
|
3515
|
+
if (alive && !event.defaultPrevented) {
|
|
3516
|
+
untracked(() => options.onReset(defaultValue));
|
|
3517
|
+
}
|
|
3518
|
+
});
|
|
3519
|
+
};
|
|
3520
|
+
ownerDocument.addEventListener('reset', onReset, true);
|
|
3521
|
+
destroyRef.onDestroy(() => {
|
|
3522
|
+
alive = false;
|
|
3523
|
+
ownerDocument.removeEventListener('reset', onReset, true);
|
|
3524
|
+
for (const input of inputs) {
|
|
3525
|
+
input.remove();
|
|
3526
|
+
}
|
|
3527
|
+
});
|
|
3528
|
+
return {
|
|
3529
|
+
ownerForm,
|
|
3530
|
+
sync,
|
|
3531
|
+
requestSubmit: () => {
|
|
3532
|
+
untracked(sync);
|
|
3533
|
+
ownerForm()?.requestSubmit();
|
|
3534
|
+
}
|
|
3535
|
+
};
|
|
3536
|
+
}
|
|
3537
|
+
|
|
3370
3538
|
/**
|
|
3371
3539
|
* Creates a resize observer effect for element
|
|
3372
3540
|
*
|
|
@@ -4444,5 +4612,5 @@ var RdxPositionAlign;
|
|
|
4444
4612
|
* Generated bundle index. Do not edit.
|
|
4445
4613
|
*/
|
|
4446
4614
|
|
|
4447
|
-
export { A, ALT, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, ASTERISK, BACKSPACE, CAPS_LOCK, CONTROL, CTRL, DELETE, DOCS_BASE_URL, END, ENTER, ESCAPE, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, HOME, META, P, PAGE_DOWN, PAGE_UP, RDX_DEFAULT_VALIDATION_MODE, RDX_FIELD_VALIDITY, RDX_FLOATING_REGISTRATION, RDX_FLOATING_ROOT_CONTEXT, RDX_FLOATING_TREE, RDX_FORM_UI_STATE, RDX_INTERNAL_BACKDROP_ATTR, RDX_SCROLL_LOCKED_ATTR, RdxControlValueAccessor, RdxFloatingNode, RdxFloatingNodeRegistration, RdxFloatingRegistrationContext, RdxFloatingRootContext, RdxFloatingTree, RdxFormUiControlBase, RdxFormUiStateHost, RdxIdGenerator, RdxLiveAnnouncer, RdxPositionAlign, RdxPositionSide, RdxTriggerRegistry, SHIFT, SPACE, SPACE_CODE, TAB, TIME_GRANULARITIES, a, areAllDaysBetweenValid, clamp, createCancelableChangeEventDetails, createContent, createContext, createFloatingEvents, createFloatingRootContext, createFormUiState, createFormatter, createMonth, createMonths, docsUrl, elementSize, formUiStateContext, getActiveElement, getDaysBetween, getDaysInMonth, getDefaultDate, getDefaultTime, getLastFirstDayOfWeek, getMaxTransitionDuration, getNextLastDayOfWeek, getOptsByGranularity, getPlaceholder, getSegmentElements, getWeekNumber, handleAndDispatchCustomEvent, handleCalendarInitialFocus, hasTime, initializeSegmentValues, injectControlValueAccessor, injectDocument, injectFloatingRootContext, injectId, injectNgControlState, isAcceptableSegmentKey, isAfter, isAfterOrSame, isBefore, isBeforeOrSame, isBetween, isBetweenInclusive, isCalendarDateTime, isEqual, isItemEqualToValue, isNullish, isNumberString, isSegmentNavigationKey, isValidationRevealed, isZonedDateTime, itemToStringLabel, itemToStringValue, j, k, n, normalizeDateStep, normalizeHour12, normalizeHourCycle, p, provideExistingToken, provideFloatingRegistration, provideFloatingRootContext, provideFloatingTree, provideFormUiState, provideValueAccessor, rdxCheckLabelElement, rdxCheckTriggerElement, rdxDevError, rdxDevWarning, resetRdxDevWarnings, resizeEffect, resolveDisplayValid, resolveFloatingTree, roundToStepPrecision, segmentBuilders, setupInternalBackdrop, snapValueToStep, syncSegmentValues, syncTimeSegmentValues, toDate, useAnchoredScrollLock, useArrowNavigation, useDateField, useFilter, useGraceArea, useListHighlight, usePointerDrag, useScrollLock, useTransitionStatus, watch };
|
|
4615
|
+
export { A, ALT, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, ASTERISK, BACKSPACE, CAPS_LOCK, CONTROL, CTRL, DELETE, DOCS_BASE_URL, END, ENTER, ESCAPE, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, HOME, META, P, PAGE_DOWN, PAGE_UP, RDX_DEFAULT_VALIDATION_MODE, RDX_FIELD_VALIDITY, RDX_FLOATING_REGISTRATION, RDX_FLOATING_ROOT_CONTEXT, RDX_FLOATING_TREE, RDX_FORM_UI_STATE, RDX_INTERNAL_BACKDROP_ATTR, RDX_SCROLL_LOCKED_ATTR, RdxControlValueAccessor, RdxFloatingNode, RdxFloatingNodeRegistration, RdxFloatingRegistrationContext, RdxFloatingRootContext, RdxFloatingTree, RdxFormUiControlBase, RdxFormUiStateHost, RdxIdGenerator, RdxLiveAnnouncer, RdxPositionAlign, RdxPositionSide, RdxTriggerRegistry, SHIFT, SPACE, SPACE_CODE, TAB, TIME_GRANULARITIES, a, areAllDaysBetweenValid, clamp, createCancelableChangeEventDetails, createContent, createContext, createFloatingEvents, createFloatingRootContext, createFormUiState, createFormatter, createMonth, createMonths, docsUrl, elementSize, formUiStateContext, getActiveElement, getDaysBetween, getDaysInMonth, getDefaultDate, getDefaultTime, getLastFirstDayOfWeek, getMaxTransitionDuration, getNextLastDayOfWeek, getOptsByGranularity, getPlaceholder, getSegmentElements, getWeekNumber, handleAndDispatchCustomEvent, handleCalendarInitialFocus, hasTime, initializeSegmentValues, injectControlValueAccessor, injectDocument, injectFloatingRootContext, injectId, injectNgControlState, isAcceptableSegmentKey, isAfter, isAfterOrSame, isBefore, isBeforeOrSame, isBetween, isBetweenInclusive, isCalendarDateTime, isEqual, isItemEqualToValue, isNullish, isNumberString, isSegmentNavigationKey, isValidationRevealed, isZonedDateTime, itemToStringLabel, itemToStringValue, j, k, n, normalizeDateStep, normalizeHour12, normalizeHourCycle, p, provideExistingToken, provideFloatingRegistration, provideFloatingRootContext, provideFloatingTree, provideFormUiState, provideValueAccessor, rdxCheckLabelElement, rdxCheckTriggerElement, rdxDevError, rdxDevWarning, resetRdxDevWarnings, resizeEffect, resolveDisplayValid, resolveFloatingTree, roundToStepPrecision, segmentBuilders, serializeNativeFormValue, setupInternalBackdrop, snapValueToStep, syncSegmentValues, syncTimeSegmentValues, toDate, useAnchoredScrollLock, useArrowNavigation, useDateField, useFilter, useGraceArea, useListHighlight, useNativeFormControl, usePointerDrag, useScrollLock, useTransitionStatus, watch };
|
|
4448
4616
|
//# sourceMappingURL=radix-ng-primitives-core.mjs.map
|