@radix-ng/primitives 0.39.5 → 0.41.0

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 (30) hide show
  1. package/core/src/date-time/formatter.d.ts +1 -1
  2. package/core/src/date-time/types.d.ts +13 -0
  3. package/core/src/date-time/useDateField.d.ts +4 -3
  4. package/core/src/date-time/utils.d.ts +4 -1
  5. package/date-field/src/date-field-context.token.d.ts +2 -1
  6. package/date-field/src/date-field-root.directive.d.ts +7 -2
  7. package/dismissible-layer/README.md +1 -0
  8. package/dismissible-layer/index.d.ts +1 -0
  9. package/dismissible-layer/src/utils.d.ts +38 -0
  10. package/editable/README.md +1 -0
  11. package/editable/index.d.ts +1 -0
  12. package/editable/src/editable-root.d.ts +67 -0
  13. package/fesm2022/radix-ng-primitives-core.mjs +88 -46
  14. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  15. package/fesm2022/radix-ng-primitives-date-field.mjs +11 -3
  16. package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
  17. package/fesm2022/radix-ng-primitives-dismissible-layer.mjs +211 -0
  18. package/fesm2022/radix-ng-primitives-dismissible-layer.mjs.map +1 -0
  19. package/fesm2022/radix-ng-primitives-editable.mjs +118 -0
  20. package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -0
  21. package/fesm2022/radix-ng-primitives-number-field.mjs +7 -7
  22. package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
  23. package/fesm2022/radix-ng-primitives-time-field.mjs +12 -4
  24. package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
  25. package/hover-card/src/hover-card-root.directive.d.ts +4 -4
  26. package/package.json +11 -3
  27. package/popover/src/popover-root.directive.d.ts +4 -4
  28. package/time-field/src/time-field-context.token.d.ts +2 -1
  29. package/time-field/src/time-field-root.directive.d.ts +7 -2
  30. package/tooltip/src/tooltip-root.directive.d.ts +4 -4
@@ -27,4 +27,4 @@ export type Formatter = {
27
27
  *
28
28
  * @see [DateFormatter](https://react-spectrum.adobe.com/internationalized/date/DateFormatter.html)
29
29
  */
30
- export declare function createFormatter(initialLocale: string): Formatter;
30
+ export declare function createFormatter(initialLocale: string, opts?: DateFormatterOptions): Formatter;
@@ -1,6 +1,19 @@
1
1
  import type { DateValue } from '@internationalized/date';
2
2
  import { DATE_SEGMENT_PARTS, EDITABLE_SEGMENT_PARTS, NON_EDITABLE_SEGMENT_PARTS, TIME_SEGMENT_PARTS } from './parts';
3
3
  export type DateMatcher = (date: DateValue) => boolean;
4
+ export type DateStep = {
5
+ year?: number;
6
+ month?: number;
7
+ day?: number;
8
+ hour?: number;
9
+ minute?: number;
10
+ second?: number;
11
+ millisecond?: number;
12
+ };
13
+ export type DateRange = {
14
+ start: DateValue | undefined;
15
+ end: DateValue | undefined;
16
+ };
4
17
  export type HourCycle = 12 | 24 | undefined;
5
18
  export type Month<T> = {
6
19
  /**
@@ -1,7 +1,7 @@
1
- import { InputSignal, ModelSignal, WritableSignal } from '@angular/core';
1
+ import { InputSignal, ModelSignal, Signal, WritableSignal } from '@angular/core';
2
2
  import { DateValue } from '@internationalized/date';
3
3
  import { Formatter } from './formatter';
4
- import { HourCycle, SegmentPart, SegmentValueObj } from './types';
4
+ import { DateStep, HourCycle, SegmentPart, SegmentValueObj } from './types';
5
5
  export type UseDateFieldProps = {
6
6
  hasLeftFocus: WritableSignal<boolean>;
7
7
  lastKeyZero: WritableSignal<boolean>;
@@ -9,6 +9,7 @@ export type UseDateFieldProps = {
9
9
  hourCycle: HourCycle;
10
10
  formatter: Formatter;
11
11
  segmentValues: WritableSignal<SegmentValueObj>;
12
+ step: Signal<DateStep>;
12
13
  disabled: InputSignal<boolean>;
13
14
  readonly: InputSignal<boolean>;
14
15
  part: SegmentPart;
@@ -136,6 +137,6 @@ export declare const segmentBuilders: {
136
137
  export declare function useDateField(props: UseDateFieldProps): {
137
138
  handleSegmentClick: (e: MouseEvent) => void;
138
139
  handleSegmentKeydown: (e: KeyboardEvent) => void;
139
- attributes: import("@angular/core").Signal<{}>;
140
+ attributes: Signal<{}>;
140
141
  };
141
142
  export {};
@@ -1,4 +1,7 @@
1
1
  import { Granularity } from './comparators';
2
- import { HourCycle } from './types';
2
+ import { DateStep, HourCycle } from './types';
3
3
  export declare function getOptsByGranularity(granularity: Granularity, hourCycle: HourCycle, isTimeValue?: boolean): Intl.DateTimeFormatOptions;
4
+ export declare function normalizeDateStep(step?: DateStep): DateStep;
4
5
  export declare function handleCalendarInitialFocus(calendar: HTMLElement): void;
6
+ export declare function normalizeHourCycle(hourCycle: HourCycle): "h11" | "h23" | undefined;
7
+ export declare function normalizeHour12(hourCycle: HourCycle): boolean | undefined;
@@ -1,6 +1,6 @@
1
1
  import { InjectionToken, InputSignal, ModelSignal, Signal, WritableSignal } from '@angular/core';
2
2
  import { DateValue } from '@internationalized/date';
3
- import { Formatter, HourCycle, SegmentValueObj } from '@radix-ng/primitives/core';
3
+ import { DateStep, Formatter, HourCycle, SegmentValueObj } from '@radix-ng/primitives/core';
4
4
  export interface DateFieldContextToken {
5
5
  locale: InputSignal<string>;
6
6
  value: ModelSignal<DateValue | undefined>;
@@ -9,6 +9,7 @@ export interface DateFieldContextToken {
9
9
  isInvalid: Signal<boolean>;
10
10
  placeholder: ModelSignal<DateValue>;
11
11
  hourCycle: InputSignal<HourCycle>;
12
+ step$: Signal<DateStep>;
12
13
  formatter: Formatter;
13
14
  segmentValues: WritableSignal<SegmentValueObj>;
14
15
  focusNext: () => void;
@@ -2,7 +2,7 @@ import { Direction } from '@angular/cdk/bidi';
2
2
  import { BooleanInput } from '@angular/cdk/coercion';
3
3
  import { AfterViewInit, OnInit } from '@angular/core';
4
4
  import { DateValue } from '@internationalized/date';
5
- import { DateMatcher, Formatter, Granularity, HourCycle, SegmentValueObj } from '@radix-ng/primitives/core';
5
+ import { DateMatcher, DateStep, Formatter, Granularity, HourCycle, SegmentValueObj } from '@radix-ng/primitives/core';
6
6
  import * as i0 from "@angular/core";
7
7
  export declare class RdxDateFieldRootDirective implements OnInit, AfterViewInit {
8
8
  private readonly elementRef;
@@ -45,6 +45,11 @@ export declare class RdxDateFieldRootDirective implements OnInit, AfterViewInit
45
45
  * Whether or not the field is readonly.
46
46
  */
47
47
  readonly readonly: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
48
+ /**
49
+ * The stepping interval for the time fields. Defaults to 1
50
+ */
51
+ readonly step: import("@angular/core").InputSignal<DateStep | undefined>;
52
+ readonly step$: import("@angular/core").Signal<DateStep>;
48
53
  /**
49
54
  * @ignore
50
55
  */
@@ -122,5 +127,5 @@ export declare class RdxDateFieldRootDirective implements OnInit, AfterViewInit
122
127
  */
123
128
  setFocusedElement(el: HTMLElement): void;
124
129
  static ɵfac: i0.ɵɵFactoryDeclaration<RdxDateFieldRootDirective, never>;
125
- static ɵdir: i0.ɵɵDirectiveDeclaration<RdxDateFieldRootDirective, "[rdxDateFieldRoot]", ["rdxDateFieldRoot"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; "isDateUnavailable": { "alias": "isDateUnavailable"; "required": false; "isSignal": true; }; "hourCycle": { "alias": "hourCycle"; "required": false; "isSignal": true; }; "granularity": { "alias": "granularity"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "dir": { "alias": "dir"; "required": false; "isSignal": true; }; "minValue": { "alias": "minValue"; "required": false; "isSignal": true; }; "maxValue": { "alias": "maxValue"; "required": false; "isSignal": true; }; "hideTimeZone": { "alias": "hideTimeZone"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "placeholder": "placeholderChange"; }, never, never, true, never>;
130
+ static ɵdir: i0.ɵɵDirectiveDeclaration<RdxDateFieldRootDirective, "[rdxDateFieldRoot]", ["rdxDateFieldRoot"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; "isDateUnavailable": { "alias": "isDateUnavailable"; "required": false; "isSignal": true; }; "hourCycle": { "alias": "hourCycle"; "required": false; "isSignal": true; }; "granularity": { "alias": "granularity"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "dir": { "alias": "dir"; "required": false; "isSignal": true; }; "minValue": { "alias": "minValue"; "required": false; "isSignal": true; }; "maxValue": { "alias": "maxValue"; "required": false; "isSignal": true; }; "hideTimeZone": { "alias": "hideTimeZone"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "placeholder": "placeholderChange"; }, never, never, true, never>;
126
131
  }
@@ -0,0 +1 @@
1
+ # @radix-ng/primitives/dismissible-layer
@@ -0,0 +1 @@
1
+ export * from './src/utils';
@@ -0,0 +1,38 @@
1
+ import { BooleanInput } from '@angular/cdk/coercion';
2
+ import * as i0 from "@angular/core";
3
+ /**
4
+ * Listens for when focus happens outside a DOM subtree.
5
+ * Returns props to pass to the root (node) of the subtree we want to check.
6
+ */
7
+ export declare class RdxFocusOutside {
8
+ #private;
9
+ readonly enabledInput: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
10
+ set enabled(value: boolean);
11
+ get enabled(): boolean;
12
+ readonly focusOutside: import("@angular/core").OutputEmitterRef<FocusEvent>;
13
+ private readonly isFocusInsideDOMTree;
14
+ private readonly focusCaptureHandler;
15
+ private readonly blurCaptureHandler;
16
+ constructor();
17
+ static ɵfac: i0.ɵɵFactoryDeclaration<RdxFocusOutside, never>;
18
+ static ɵdir: i0.ɵɵDirectiveDeclaration<RdxFocusOutside, "[rdxFocusOutside]", ["rdxFocusOutside"], { "enabledInput": { "alias": "enabled"; "required": false; "isSignal": true; }; }, { "focusOutside": "focusOutside"; }, never, never, true, never>;
19
+ }
20
+ /**
21
+ * Listens for `pointerdown` outside a DOM subtree. We use `pointerdown` rather than `pointerup`
22
+ * to mimic layer dismissing behavior present in OS.
23
+ * Returns props to pass to the node we want to check for outside events.
24
+ */
25
+ export declare class RdxPointerDownOutside {
26
+ #private;
27
+ private readonly elementRef;
28
+ readonly enabledInput: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
29
+ set enabled(value: boolean);
30
+ get enabled(): boolean;
31
+ readonly pointerDownOutside: import("@angular/core").OutputEmitterRef<PointerEvent>;
32
+ private readonly isPointerInsideDOMTree;
33
+ private readonly handleAndDispatchPointerDownOutsideEvent;
34
+ private handleClick;
35
+ constructor();
36
+ static ɵfac: i0.ɵɵFactoryDeclaration<RdxPointerDownOutside, never>;
37
+ static ɵdir: i0.ɵɵDirectiveDeclaration<RdxPointerDownOutside, "[rdxPointerDownOutside]", ["rdxPointerDownOutside"], { "enabledInput": { "alias": "enabled"; "required": false; "isSignal": true; }; }, { "pointerDownOutside": "pointerDownOutside"; }, never, never, true, never>;
38
+ }
@@ -0,0 +1 @@
1
+ # @radix-ng/primitives/editable
@@ -0,0 +1 @@
1
+ export * from './src/editable-root';
@@ -0,0 +1,67 @@
1
+ import { BooleanInput, NumberInput } from '@angular/cdk/coercion';
2
+ import { Signal, WritableSignal } from '@angular/core';
3
+ import { RdxPointerDownOutside } from '@radix-ng/primitives/dismissible-layer';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@radix-ng/primitives/dismissible-layer";
6
+ type EditableRootContext = {
7
+ disabled: Signal<boolean>;
8
+ value: Signal<string | null | undefined>;
9
+ inputValue: WritableSignal<string | undefined>;
10
+ placeholder: Signal<{
11
+ edit: string;
12
+ preview: string;
13
+ }>;
14
+ isEditing: Signal<boolean>;
15
+ submitMode: Signal<SubmitMode>;
16
+ activationMode: Signal<ActivationMode>;
17
+ edit: () => void;
18
+ cancel: () => void;
19
+ submit: () => void;
20
+ maxLength: Signal<number | undefined>;
21
+ startWithEditMode: Signal<boolean>;
22
+ isEmpty: Signal<boolean>;
23
+ readonly: Signal<boolean>;
24
+ selectOnFocus: Signal<boolean>;
25
+ autoResize: Signal<boolean>;
26
+ inputRef: WritableSignal<HTMLInputElement | undefined>;
27
+ };
28
+ export declare const injectEditableRootContext: (optional?: boolean) => EditableRootContext | null, provideEditableRootContext: (useFactory: () => EditableRootContext) => import("@angular/core").Provider;
29
+ type ActivationMode = 'focus' | 'dblclick' | 'none';
30
+ type SubmitMode = 'blur' | 'enter' | 'none' | 'both';
31
+ /**
32
+ * @group Components
33
+ */
34
+ export declare class RdxEditableRoot {
35
+ private readonly focusOutside;
36
+ readonly pointerDownOutside: RdxPointerDownOutside;
37
+ readonly value: import("@angular/core").ModelSignal<string | undefined>;
38
+ readonly placeholder: import("@angular/core").InputSignal<string>;
39
+ readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
40
+ readonly readonly: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
41
+ readonly selectOnFocus: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
42
+ readonly submitMode: import("@angular/core").InputSignal<SubmitMode>;
43
+ readonly maxLength: import("@angular/core").InputSignalWithTransform<number | undefined, NumberInput>;
44
+ /**
45
+ * Whether to start with the edit mode active
46
+ */
47
+ readonly startWithEditMode: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
48
+ readonly activationMode: import("@angular/core").InputSignal<ActivationMode>;
49
+ readonly autoResize: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
50
+ readonly required: import("@angular/core").InputSignalWithTransform<boolean, BooleanInput>;
51
+ readonly isEmpty: Signal<boolean>;
52
+ readonly $placeholder: Signal<string | {
53
+ edit: string;
54
+ preview: string;
55
+ }>;
56
+ readonly isEditing: WritableSignal<boolean>;
57
+ readonly inputValue: WritableSignal<string | undefined>;
58
+ readonly inputRef: WritableSignal<HTMLInputElement | undefined>;
59
+ constructor();
60
+ handleDismiss(): void;
61
+ submit(): void;
62
+ cancel(): void;
63
+ edit(): void;
64
+ static ɵfac: i0.ɵɵFactoryDeclaration<RdxEditableRoot, never>;
65
+ static ɵdir: i0.ɵɵDirectiveDeclaration<RdxEditableRoot, "[rdxEditableRoot]", ["rdxEditableRoot"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "selectOnFocus": { "alias": "selectOnFocus"; "required": false; "isSignal": true; }; "submitMode": { "alias": "submitMode"; "required": false; "isSignal": true; }; "maxLength": { "alias": "maxLength"; "required": false; "isSignal": true; }; "startWithEditMode": { "alias": "startWithEditMode"; "required": false; "isSignal": true; }; "activationMode": { "alias": "activationMode"; "required": false; "isSignal": true; }; "autoResize": { "alias": "autoResize"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, [{ directive: typeof i1.RdxFocusOutside; inputs: {}; outputs: {}; }, { directive: typeof i1.RdxPointerDownOutside; inputs: {}; outputs: {}; }]>;
66
+ }
67
+ export {};
@@ -987,7 +987,7 @@ const defaultPartOptions = {
987
987
  *
988
988
  * @see [DateFormatter](https://react-spectrum.adobe.com/internationalized/date/DateFormatter.html)
989
989
  */
990
- function createFormatter(initialLocale) {
990
+ function createFormatter(initialLocale, opts = {}) {
991
991
  let locale = initialLocale;
992
992
  function setLocale(newLocale) {
993
993
  locale = newLocale;
@@ -996,7 +996,7 @@ function createFormatter(initialLocale) {
996
996
  return locale;
997
997
  }
998
998
  function custom(date, options) {
999
- return new DateFormatter(locale, options).format(date);
999
+ return new DateFormatter(locale, { ...opts, ...options }).format(date);
1000
1000
  }
1001
1001
  function selectedDate(date, includeTime = true) {
1002
1002
  if (hasTime(date) && includeTime) {
@@ -1011,31 +1011,33 @@ function createFormatter(initialLocale) {
1011
1011
  });
1012
1012
  }
1013
1013
  }
1014
- function fullMonthAndYear(date) {
1015
- return new DateFormatter(locale, { month: 'long', year: 'numeric' }).format(date);
1014
+ function fullMonthAndYear(date, options = {}) {
1015
+ return new DateFormatter(locale, { ...opts, month: 'long', year: 'numeric', ...options }).format(date);
1016
1016
  }
1017
- function fullMonth(date) {
1018
- return new DateFormatter(locale, { month: 'long' }).format(date);
1017
+ function fullMonth(date, options = {}) {
1018
+ return new DateFormatter(locale, { ...opts, month: 'long', ...options }).format(date);
1019
1019
  }
1020
- function fullYear(date) {
1021
- return new DateFormatter(locale, { year: 'numeric' }).format(date);
1020
+ function fullYear(date, options = {}) {
1021
+ return new DateFormatter(locale, { ...opts, year: 'numeric', ...options }).format(date);
1022
1022
  }
1023
1023
  function toParts(date, options) {
1024
1024
  if (isZonedDateTime(date)) {
1025
1025
  return new DateFormatter(locale, {
1026
+ ...opts,
1026
1027
  ...options,
1027
1028
  timeZone: date.timeZone
1028
1029
  }).formatToParts(toDate(date));
1029
1030
  }
1030
1031
  else {
1031
- return new DateFormatter(locale, options).formatToParts(toDate(date));
1032
+ return new DateFormatter(locale, { ...opts, ...options }).formatToParts(toDate(date));
1032
1033
  }
1033
1034
  }
1034
1035
  function dayOfWeek(date, length = 'narrow') {
1035
- return new DateFormatter(locale, { weekday: length }).format(date);
1036
+ return new DateFormatter(locale, { ...opts, weekday: length }).format(date);
1036
1037
  }
1037
1038
  function dayPeriod(date, hourCycle = undefined) {
1038
1039
  const parts = new DateFormatter(locale, {
1040
+ ...opts,
1039
1041
  hour: 'numeric',
1040
1042
  minute: 'numeric',
1041
1043
  hourCycle: hourCycle === 24 ? 'h23' : undefined
@@ -1238,8 +1240,8 @@ function getOptsByGranularity(granularity, hourCycle, isTimeValue = false) {
1238
1240
  minute: '2-digit',
1239
1241
  second: '2-digit',
1240
1242
  timeZoneName: 'short',
1241
- hourCycle: hourCycle === 24 ? 'h23' : undefined,
1242
- hour12: hourCycle === 24 ? false : undefined
1243
+ hourCycle: normalizeHourCycle(hourCycle),
1244
+ hour12: normalizeHour12(hourCycle)
1243
1245
  };
1244
1246
  if (isTimeValue) {
1245
1247
  delete opts.year;
@@ -1260,6 +1262,17 @@ function getOptsByGranularity(granularity, hourCycle, isTimeValue = false) {
1260
1262
  delete opts.second;
1261
1263
  return opts;
1262
1264
  }
1265
+ function normalizeDateStep(step) {
1266
+ return {
1267
+ year: step?.year ?? 1,
1268
+ month: step?.month ?? 1,
1269
+ day: step?.day ?? 1,
1270
+ hour: step?.hour ?? 1,
1271
+ minute: step?.minute ?? 1,
1272
+ second: step?.second ?? 1,
1273
+ millisecond: step?.millisecond ?? 1
1274
+ };
1275
+ }
1263
1276
  function handleCalendarInitialFocus(calendar) {
1264
1277
  const selectedDay = calendar.querySelector('[data-selected]');
1265
1278
  if (selectedDay)
@@ -1271,6 +1284,20 @@ function handleCalendarInitialFocus(calendar) {
1271
1284
  if (firstDay)
1272
1285
  return firstDay.focus();
1273
1286
  }
1287
+ function normalizeHourCycle(hourCycle) {
1288
+ if (hourCycle === 24)
1289
+ return 'h23';
1290
+ if (hourCycle === 12)
1291
+ return 'h11';
1292
+ return undefined;
1293
+ }
1294
+ function normalizeHour12(hourCycle) {
1295
+ if (hourCycle === 24)
1296
+ return false;
1297
+ if (hourCycle === 12)
1298
+ return true;
1299
+ return undefined;
1300
+ }
1274
1301
 
1275
1302
  const calendarDateTimeGranularities = ['hour', 'minute', 'second'];
1276
1303
  function syncTimeSegmentValues(props) {
@@ -1316,16 +1343,23 @@ function createContentObj(props) {
1316
1343
  if ('hour' in segmentValues) {
1317
1344
  const value = segmentValues[part];
1318
1345
  if (value !== null) {
1319
- /**
1320
- * Edge case for when the month field is filled and the day field snaps to the maximum value of the value of the placeholder month
1321
- */
1322
- if (part === 'day' && segmentValues.month !== null) {
1323
- return formatter.part(props.dateRef.set({ [part]: value, month: segmentValues.month }), part, {
1324
- hourCycle: props.hourCycle === 24 ? 'h23' : undefined
1325
- });
1346
+ if (part === 'day') {
1347
+ return formatter.part(props.dateRef.set({
1348
+ [part]: value,
1349
+ /**
1350
+ * Edge case for the day field:
1351
+ *
1352
+ * 1. If the month is filled,
1353
+ * we need to ensure that the day snaps to the maximum value of that month.
1354
+ * 2. If the month is not filled,
1355
+ * we default to the month with the maximum number of days (here just using January, 31 days),
1356
+ * so that user can input any possible day.
1357
+ */
1358
+ month: segmentValues.month ?? 1
1359
+ }), part, { hourCycle: normalizeHourCycle(props.hourCycle) });
1326
1360
  }
1327
1361
  return formatter.part(props.dateRef.set({ [part]: value }), part, {
1328
- hourCycle: props.hourCycle === 24 ? 'h23' : undefined
1362
+ hourCycle: normalizeHourCycle(props.hourCycle)
1329
1363
  });
1330
1364
  }
1331
1365
  else {
@@ -1336,11 +1370,13 @@ function createContentObj(props) {
1336
1370
  if (isDateSegmentPart(part)) {
1337
1371
  const value = segmentValues[part];
1338
1372
  if (value !== null) {
1339
- if (part === 'day' && segmentValues.month !== null)
1340
- /**
1341
- * As described above, same function
1342
- */
1343
- return formatter.part(props.dateRef.set({ [part]: value, month: segmentValues.month }), part);
1373
+ if (part === 'day') {
1374
+ return formatter.part(props.dateRef.set({
1375
+ [part]: value,
1376
+ // Same logic as above for the day field
1377
+ month: segmentValues.month ?? 1
1378
+ }), part);
1379
+ }
1344
1380
  return formatter.part(props.dateRef.set({ [part]: value }), part);
1345
1381
  }
1346
1382
  else {
@@ -1670,7 +1706,8 @@ function useDateField(props) {
1670
1706
  return Number.parseInt(str.slice(0, -1));
1671
1707
  }
1672
1708
  function dateTimeValueIncrementation({ e, part, dateRef, prevValue, hourCycle }) {
1673
- const sign = e.key === ARROW_UP ? 1 : -1;
1709
+ const step = props.step()[part] ?? 1;
1710
+ const sign = e.key === ARROW_UP ? step : -step;
1674
1711
  if (prevValue === null)
1675
1712
  return dateRef[part];
1676
1713
  if (part === 'hour' && 'hour' in dateRef) {
@@ -1924,7 +1961,8 @@ function useDateField(props) {
1924
1961
  return { value: total, moveToNext };
1925
1962
  }
1926
1963
  function minuteSecondIncrementation({ e, part, dateRef, prevValue }) {
1927
- const sign = e.key === ARROW_UP ? 1 : -1;
1964
+ const step = props.step()[part] ?? 1;
1965
+ const sign = e.key === ARROW_UP ? step : -step;
1928
1966
  const min = 0;
1929
1967
  const max = 59;
1930
1968
  if (prevValue === null)
@@ -2081,15 +2119,17 @@ function useDateField(props) {
2081
2119
  !('minute' in values))
2082
2120
  return;
2083
2121
  const prevValue = values.minute;
2084
- props.segmentValues.update((prev) => ({
2085
- ...prev,
2086
- minute: minuteSecondIncrementation({
2087
- e,
2088
- part: 'minute',
2089
- dateRef: props.placeholder(),
2090
- prevValue
2091
- })
2092
- }));
2122
+ if (e.key === ARROW_UP || e.key === ARROW_DOWN) {
2123
+ props.segmentValues.update((prev) => ({
2124
+ ...prev,
2125
+ minute: minuteSecondIncrementation({
2126
+ e,
2127
+ part: 'minute',
2128
+ dateRef: props.placeholder(),
2129
+ prevValue
2130
+ })
2131
+ }));
2132
+ }
2093
2133
  if (isNumberString(e.key)) {
2094
2134
  const num = Number.parseInt(e.key);
2095
2135
  const { value, moveToNext } = updateMinuteOrSecond(num, prevValue);
@@ -2111,15 +2151,17 @@ function useDateField(props) {
2111
2151
  !('second' in values))
2112
2152
  return;
2113
2153
  const prevValue = values.second;
2114
- props.segmentValues.update((prev) => ({
2115
- ...prev,
2116
- second: minuteSecondIncrementation({
2117
- e,
2118
- part: 'second',
2119
- dateRef: props.placeholder(),
2120
- prevValue
2121
- })
2122
- }));
2154
+ if (e.key === ARROW_UP || e.key === ARROW_DOWN) {
2155
+ props.segmentValues.update((prev) => ({
2156
+ ...prev,
2157
+ second: minuteSecondIncrementation({
2158
+ e,
2159
+ part: 'second',
2160
+ dateRef: props.placeholder(),
2161
+ prevValue
2162
+ })
2163
+ }));
2164
+ }
2123
2165
  if (isNumberString(e.key)) {
2124
2166
  const num = Number.parseInt(e.key);
2125
2167
  const { value, moveToNext } = updateMinuteOrSecond(num, prevValue);
@@ -2560,5 +2602,5 @@ function watch(deps, fn, options) {
2560
2602
  * Generated bundle index. Do not edit.
2561
2603
  */
2562
2604
 
2563
- export { A, ALT, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, ASTERISK, BACKSPACE, CAPS_LOCK, CONTROL, CTRL, DELETE, END, ENTER, ESCAPE, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, HOME, META, P, PAGE_DOWN, PAGE_UP, RDX_POSITIONING_DEFAULTS, RDX_POSITIONS, RdxAutoFocusDirective, RdxControlValueAccessor, RdxFocusInitialDirective, RdxPositionAlign, RdxPositionSide, SHIFT, SPACE, SPACE_CODE, TAB, WINDOW, _IdGenerator, a, areAllDaysBetweenValid, clamp, createContent, createContext, createFormatter, createMonth, createMonths, getActiveElement, getAllPossibleConnectedPositions, getArrowPositionParams, getContentPosition, getDaysBetween, getDaysInMonth, getDefaultDate, getDefaultTime, getLastFirstDayOfWeek, getNextLastDayOfWeek, getOptsByGranularity, getPlaceholder, getSegmentElements, getSideAndAlignFromAllPossibleConnectedPositions, handleCalendarInitialFocus, hasTime, initializeSegmentValues, injectControlValueAccessor, injectDocument, injectIsClient, injectNgControl, injectWindow, isAcceptableSegmentKey, isAfter, isAfterOrSame, isBefore, isBeforeOrSame, isBetween, isBetweenInclusive, isCalendarDateTime, isEqual, isInsideForm, isNullish, isNumber, isNumberString, isSegmentNavigationKey, isValueEqualOrExist, isZonedDateTime, j, k, n, p, provideToken, provideValueAccessor, resizeEffect, roundToStepPrecision, segmentBuilders, snapValueToStep, syncSegmentValues, syncTimeSegmentValues, toDate, useArrowNavigation, useDateField, watch };
2605
+ export { A, ALT, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, ASTERISK, BACKSPACE, CAPS_LOCK, CONTROL, CTRL, DELETE, END, ENTER, ESCAPE, F1, F10, F11, F12, F2, F3, F4, F5, F6, F7, F8, F9, HOME, META, P, PAGE_DOWN, PAGE_UP, RDX_POSITIONING_DEFAULTS, RDX_POSITIONS, RdxAutoFocusDirective, RdxControlValueAccessor, RdxFocusInitialDirective, RdxPositionAlign, RdxPositionSide, SHIFT, SPACE, SPACE_CODE, TAB, WINDOW, _IdGenerator, a, areAllDaysBetweenValid, clamp, createContent, createContext, createFormatter, createMonth, createMonths, getActiveElement, getAllPossibleConnectedPositions, getArrowPositionParams, getContentPosition, getDaysBetween, getDaysInMonth, getDefaultDate, getDefaultTime, getLastFirstDayOfWeek, getNextLastDayOfWeek, getOptsByGranularity, getPlaceholder, getSegmentElements, getSideAndAlignFromAllPossibleConnectedPositions, handleCalendarInitialFocus, hasTime, initializeSegmentValues, injectControlValueAccessor, injectDocument, injectIsClient, injectNgControl, injectWindow, isAcceptableSegmentKey, isAfter, isAfterOrSame, isBefore, isBeforeOrSame, isBetween, isBetweenInclusive, isCalendarDateTime, isEqual, isInsideForm, isNullish, isNumber, isNumberString, isSegmentNavigationKey, isValueEqualOrExist, isZonedDateTime, j, k, n, normalizeDateStep, normalizeHour12, normalizeHourCycle, p, provideToken, provideValueAccessor, resizeEffect, roundToStepPrecision, segmentBuilders, snapValueToStep, syncSegmentValues, syncTimeSegmentValues, toDate, useArrowNavigation, useDateField, watch };
2564
2606
  //# sourceMappingURL=radix-ng-primitives-core.mjs.map