@viasat/beam-react 2.47.0 → 2.48.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.
@@ -1,74 +1,86 @@
1
- import { SEGMENT_MAX_LENGTH as s } from "./DateField.validation.es.js";
2
- const i = 31, o = 12, f = {
3
- day: i,
4
- month: o,
5
- year: 9999
6
- }, c = (t, e, n) => Math.min(n, Math.max(e, t)), g = (t, e) => ((t - 1) % e + e) % e + 1, d = 2024, h = (t, e) => e == null ? 31 : new Date(t ?? d, e, 0).getDate(), N = () => {
7
- const t = /* @__PURE__ */ new Date();
8
- return { day: t.getDate(), month: t.getMonth() + 1, year: t.getFullYear() };
9
- }, M = (t, e, n, r) => {
10
- if (n === "min") return t === "year" ? null : 1;
1
+ import { SEGMENT_MAX_LENGTH as u } from "./DateField.validation.es.js";
2
+ const c = 31, s = 12, d = 1, y = 9999, f = (e, t, n) => Math.min(n, Math.max(t, e)), S = (e, t) => ((e - 1) % t + t) % t + 1, h = 2024, T = (e, t) => t == null ? 31 : new Date(e ?? h, t, 0).getDate(), A = () => {
3
+ const e = /* @__PURE__ */ new Date();
4
+ return { day: e.getDate(), month: e.getMonth() + 1, year: e.getFullYear() };
5
+ }, o = (e) => e instanceof Date && !Number.isNaN(e.getTime()), Y = (e, t, n, r) => {
6
+ if (n === "min") return e === "year" ? null : 1;
11
7
  if (n === "max")
12
- return t === "year" ? null : t === "day" ? r.daysInMonth : o;
13
- if (e == null) return r.today[t];
14
- if (t === "year") return c(e + n, 1, 9999);
15
- const a = t === "day" ? i : o;
16
- return g(e + n, a);
17
- }, m = { day: "", month: "", year: "" }, u = (t) => t instanceof Date && !Number.isNaN(t.getTime()), y = (t) => {
18
- const { day: e, month: n, year: r } = t;
19
- if (e == null || n == null || r == null) return null;
20
- const a = new Date(r, n - 1, e);
21
- return a.setFullYear(r), Number.isNaN(a.getTime()) || a.getFullYear() !== r || a.getMonth() !== n - 1 || a.getDate() !== e ? null : a;
22
- }, D = (t, e) => t == null && e == null ? !0 : t == null || e == null ? !1 : t.getTime() === e.getTime(), p = (t) => {
23
- if (!u(t)) return "";
24
- const e = String(t.getFullYear()).padStart(4, "0"), n = String(t.getMonth() + 1).padStart(2, "0"), r = String(t.getDate()).padStart(2, "0");
25
- return `${e}-${n}-${r}`;
26
- }, T = (t) => t.filter(
27
- (e) => e.type !== "literal"
28
- ).map((e) => e.type), A = (t) => u(t) ? {
29
- day: String(t.getDate()).padStart(2, "0"),
30
- month: String(t.getMonth() + 1).padStart(2, "0"),
31
- year: String(t.getFullYear()).padStart(4, "0")
32
- } : m, l = (t, e) => {
33
- if (e === "" || t === "year" && e.length < s.year) return null;
34
- const n = parseInt(e, 10);
8
+ return e === "year" ? null : e === "day" ? r.daysInMonth : s;
9
+ if (t == null) {
10
+ if (e === "year") return r.today.year;
11
+ const g = e === "day" ? c : s;
12
+ return n > 0 ? 1 : g;
13
+ }
14
+ if (e === "year") return f(t + n, d, y);
15
+ const l = e === "day" ? c : s;
16
+ return S(t + n, l);
17
+ }, M = { day: "", month: "", year: "" }, m = (e) => {
18
+ const { day: t, month: n, year: r } = e;
19
+ if (t == null || n == null || r == null) return null;
20
+ const l = new Date(r, n - 1, t);
21
+ return l.setFullYear(r), Number.isNaN(l.getTime()) || l.getFullYear() !== r || l.getMonth() !== n - 1 || l.getDate() !== t ? null : l;
22
+ }, F = (e, t) => e == null && t == null ? !0 : e == null || t == null ? !1 : e.getTime() === t.getTime(), a = (e) => e.getFullYear() * 1e4 + (e.getMonth() + 1) * 100 + e.getDate(), w = (e) => o(e) ? a(e) : null, E = (e, t, n) => {
23
+ const r = a(e);
24
+ return !(o(t) && r < a(t) || o(n) && r > a(n));
25
+ }, N = (e, t) => o(e) && o(t) && a(e) > a(t), R = (e, t, n) => {
26
+ if (N(t, n)) return e;
27
+ const r = a(e);
28
+ return o(t) && r < a(t) ? new Date(t.getFullYear(), t.getMonth(), t.getDate()) : o(n) && r > a(n) ? new Date(n.getFullYear(), n.getMonth(), n.getDate()) : e;
29
+ }, _ = (e) => {
30
+ if (!o(e)) return "";
31
+ const t = String(e.getFullYear()).padStart(4, "0"), n = String(e.getMonth() + 1).padStart(2, "0"), r = String(e.getDate()).padStart(2, "0");
32
+ return `${t}-${n}-${r}`;
33
+ }, D = (e) => e.filter(
34
+ (t) => t.type !== "literal"
35
+ ).map((t) => t.type), I = (e) => o(e) ? {
36
+ day: String(e.getDate()).padStart(2, "0"),
37
+ month: String(e.getMonth() + 1).padStart(2, "0"),
38
+ year: String(e.getFullYear()).padStart(4, "0")
39
+ } : M, i = (e, t) => {
40
+ if (t === "" || e === "year" && t.length < u.year) return null;
41
+ const n = parseInt(t, 10);
35
42
  return Number.isNaN(n) || n === 0 ? null : n;
36
- }, E = (t) => y({
37
- day: l("day", t.day),
38
- month: l("month", t.month),
39
- year: l("year", t.year)
40
- }), _ = (t, e) => e === "" ? "" : e.padStart(s[t], "0"), w = (t, e, n) => e === "" ? { displayValue: n, isPlaceholder: !0 } : {
41
- displayValue: e.padStart(s[t], "0"),
43
+ }, V = (e) => m({
44
+ day: i("day", e.day),
45
+ month: i("month", e.month),
46
+ year: i("year", e.year)
47
+ }), P = (e, t) => t === "" ? "" : t.padStart(u[e], "0"), X = (e, t, n) => t === "" ? { displayValue: n, isPlaceholder: !0 } : {
48
+ displayValue: t.padStart(u[e], "0"),
42
49
  isPlaceholder: !1
43
- }, F = (t) => {
44
- const e = window.getSelection();
45
- if (!e) return;
50
+ }, C = (e) => {
51
+ const t = window.getSelection();
52
+ if (!t) return;
46
53
  const n = document.createRange();
47
- n.selectNodeContents(t), e.removeAllRanges(), e.addRange(n);
48
- }, V = (t) => {
54
+ n.selectNodeContents(e), t.removeAllRanges(), t.addRange(n);
55
+ }, L = (e) => {
49
56
  var n;
50
- if (!t) return;
51
- const e = (n = window.getSelection) == null ? void 0 : n.call(window);
52
- e && e.rangeCount > 0 && t.contains(e.anchorNode) && e.removeAllRanges();
57
+ if (!e) return;
58
+ const t = (n = window.getSelection) == null ? void 0 : n.call(window);
59
+ t && t.rangeCount > 0 && e.contains(t.anchorNode) && t.removeAllRanges();
53
60
  };
54
61
  export {
55
- i as DAY_SPIN_MAX,
56
- o as MONTH_MAX,
57
- f as SEGMENT_ARIA_MAX,
58
- M as adjustSegmentValue,
59
- c as clamp,
60
- V as clearSelectionWithin,
61
- y as deriveValue,
62
- E as deriveValueFromText,
63
- h as getDaysInMonth,
64
- w as getSegmentDisplay,
65
- T as getSegmentOrder,
66
- D as isSameDateValue,
67
- _ as normalizeSegmentText,
68
- l as segmentNumber,
69
- A as segmentTextFromValue,
70
- F as selectElementContents,
71
- p as toISODateString,
72
- N as todayParts,
73
- g as wrapInRange
62
+ c as DAY_SPIN_MAX,
63
+ s as MONTH_MAX,
64
+ y as YEAR_MAX,
65
+ d as YEAR_MIN,
66
+ Y as adjustSegmentValue,
67
+ f as clamp,
68
+ R as clampDateToRange,
69
+ L as clearSelectionWithin,
70
+ w as dateKeyOrNull,
71
+ m as deriveValue,
72
+ V as deriveValueFromText,
73
+ T as getDaysInMonth,
74
+ X as getSegmentDisplay,
75
+ D as getSegmentOrder,
76
+ E as isDateInRange,
77
+ N as isMinMaxMisconfigured,
78
+ F as isSameDateValue,
79
+ P as normalizeSegmentText,
80
+ i as segmentNumber,
81
+ I as segmentTextFromValue,
82
+ C as selectElementContents,
83
+ _ as toISODateString,
84
+ A as todayParts,
85
+ S as wrapInRange
74
86
  };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react"),I=require("./DateField.utils.cjs.js");function M({disabled:n,fieldRef:a,segmentRefs:T,partsOrder:o,onSegmentFocusChange:b,onFieldBlur:D}){const[l,i]=e.useState(null),s=o[0],r=e.useRef(b),f=e.useRef(D);e.useEffect(()=>{r.current=b,f.current=D},[b,D]),e.useEffect(()=>{if(l===null||l==="all")return;const t=T.current.get(l);t&&document.activeElement!==t&&t.focus()},[l,T]);const _=e.useCallback(t=>{var u;n||(i(t),(u=r.current)==null||u.call(r,t))},[n]),v=e.useCallback(t=>{var u;n||t.target===a.current&&(i(s),(u=r.current)==null||u.call(r,s))},[n,a,s]),E=e.useCallback(t=>{var u,c;(u=a.current)!=null&&u.contains(t.relatedTarget)||(i(null),(c=f.current)==null||c.call(f),I.clearSelectionWithin(a.current))},[a]),d=e.useCallback(t=>{var c;if(n)return;t.target.closest("[data-segment]")||(t.preventDefault(),i(s),(c=r.current)==null||c.call(r,s))},[n,s]),k=e.useCallback((t,u)=>{var y;const c=o.indexOf(t);if(c===-1)return;const x=o[c+u];x!=null&&(i(x),(y=r.current)==null||y.call(r,x))},[o]),q=e.useCallback(t=>{k(t,1)},[k]),w=e.useCallback(t=>{k(t,-1)},[k]);return{focusedSegment:l,fieldTabIndex:n?-1:l===null?0:-1,handleSegmentFocus:_,handleFieldFocus:v,handleFieldBlur:E,handleFieldMouseDown:d,focusNext:q,focusPrevious:w}}exports.useDateFieldFocus=M;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react"),P=require("./DateField.utils.cjs.js");function j({disabled:l,fieldRef:i,segmentRefs:T,partsOrder:b,onSegmentFocusChange:d,onFieldBlur:x}){const[c,o]=r.useState(null),a=b[0],y=r.useRef(c);y.current=c;const e=r.useRef(d),k=r.useRef(x);r.useEffect(()=>{e.current=d,k.current=x},[d,x]),r.useEffect(()=>{if(c===null||c==="all")return;const t=T.current.get(c);t&&document.activeElement!==t&&t.focus()},[c,T]);const E=r.useCallback(t=>{var u;l||(o(t),(u=e.current)==null||u.call(e,t))},[l]),q=r.useCallback(t=>{var u;l||t.target===i.current&&(o(a),(u=e.current)==null||u.call(e,a))},[l,i,a]),v=r.useCallback(t=>{var n,s,f,_;if((n=i.current)!=null&&n.contains(t.relatedTarget))return;const u=(f=(s=t.target)==null?void 0:s.getAttribute)==null?void 0:f.call(s,"data-segment");u&&u!==y.current||(o(null),(_=k.current)==null||_.call(k),P.clearSelectionWithin(i.current))},[i]),w=r.useCallback(t=>{var n;if(l)return;t.target.closest("[data-segment]")||(t.preventDefault(),o(a),(n=e.current)==null||n.call(e,a))},[l,a]),D=r.useCallback((t,u)=>{var f;const n=b.indexOf(t);if(n===-1)return;const s=b[n+u];s!=null&&(o(s),(f=e.current)==null||f.call(e,s))},[b]),I=r.useCallback(t=>{D(t,1)},[D]),M=r.useCallback(t=>{D(t,-1)},[D]);return{focusedSegment:c,fieldTabIndex:l?-1:c===null?0:-1,handleSegmentFocus:E,handleFieldFocus:q,handleFieldBlur:v,handleFieldMouseDown:w,focusNext:I,focusPrevious:M}}exports.useDateFieldFocus=j;
@@ -1,71 +1,78 @@
1
- import { useState as j, useRef as E, useEffect as I, useCallback as e } from "react";
2
- import { clearSelectionWithin as m } from "./DateField.utils.es.js";
3
- function G({
4
- disabled: n,
5
- fieldRef: i,
6
- segmentRefs: v,
7
- partsOrder: f,
8
- onSegmentFocusChange: T,
9
- onFieldBlur: D
1
+ import { useState as d, useRef as y, useEffect as v, useCallback as o } from "react";
2
+ import { clearSelectionWithin as j } from "./DateField.utils.es.js";
3
+ function H({
4
+ disabled: s,
5
+ fieldRef: l,
6
+ segmentRefs: E,
7
+ partsOrder: x,
8
+ onSegmentFocusChange: m,
9
+ onFieldBlur: p
10
10
  }) {
11
- const [s, l] = j(null), o = f[0], r = E(T), a = E(D);
12
- I(() => {
13
- r.current = T, a.current = D;
14
- }, [T, D]), I(() => {
15
- if (s === null || s === "all") return;
16
- const t = v.current.get(s);
11
+ const [u, f] = d(null), i = x[0], I = y(u);
12
+ I.current = u;
13
+ const r = y(m), T = y(p);
14
+ v(() => {
15
+ r.current = m, T.current = p;
16
+ }, [m, p]), v(() => {
17
+ if (u === null || u === "all") return;
18
+ const t = E.current.get(u);
17
19
  t && document.activeElement !== t && t.focus();
18
- }, [s, v]);
19
- const k = e(
20
+ }, [u, E]);
21
+ const w = o(
20
22
  (t) => {
21
23
  var c;
22
- n || (l(t), (c = r.current) == null || c.call(r, t));
24
+ s || (f(t), (c = r.current) == null || c.call(r, t));
23
25
  },
24
- [n]
25
- ), w = e(
26
+ [s]
27
+ ), A = o(
26
28
  (t) => {
27
29
  var c;
28
- n || t.target === i.current && (l(o), (c = r.current) == null || c.call(r, o));
30
+ s || t.target === l.current && (f(i), (c = r.current) == null || c.call(r, i));
29
31
  },
30
- [n, i, o]
31
- ), M = e(
32
+ [s, l, i]
33
+ ), M = o(
32
34
  (t) => {
33
- var c, u;
34
- (c = i.current) != null && c.contains(t.relatedTarget) || (l(null), (u = a.current) == null || u.call(a), m(i.current));
35
+ var n, e, a, k;
36
+ if ((n = l.current) != null && n.contains(t.relatedTarget)) return;
37
+ const c = (a = (e = t.target) == null ? void 0 : e.getAttribute) == null ? void 0 : a.call(
38
+ e,
39
+ "data-segment"
40
+ );
41
+ c && c !== I.current || (f(null), (k = T.current) == null || k.call(T), j(l.current));
35
42
  },
36
- [i]
37
- ), N = e(
43
+ [l]
44
+ ), N = o(
38
45
  (t) => {
39
- var u;
40
- if (n) return;
41
- t.target.closest("[data-segment]") || (t.preventDefault(), l(o), (u = r.current) == null || u.call(r, o));
46
+ var n;
47
+ if (s) return;
48
+ t.target.closest("[data-segment]") || (t.preventDefault(), f(i), (n = r.current) == null || n.call(r, i));
42
49
  },
43
- [n, o]
44
- ), x = e(
50
+ [s, i]
51
+ ), D = o(
45
52
  (t, c) => {
46
- var y;
47
- const u = f.indexOf(t);
48
- if (u === -1) return;
49
- const p = f[u + c];
50
- p != null && (l(p), (y = r.current) == null || y.call(r, p));
53
+ var a;
54
+ const n = x.indexOf(t);
55
+ if (n === -1) return;
56
+ const e = x[n + c];
57
+ e != null && (f(e), (a = r.current) == null || a.call(r, e));
51
58
  },
52
- [f]
53
- ), P = e(
59
+ [x]
60
+ ), P = o(
54
61
  (t) => {
55
- x(t, 1);
62
+ D(t, 1);
56
63
  },
57
- [x]
58
- ), W = e(
64
+ [D]
65
+ ), W = o(
59
66
  (t) => {
60
- x(t, -1);
67
+ D(t, -1);
61
68
  },
62
- [x]
69
+ [D]
63
70
  );
64
71
  return {
65
- focusedSegment: s,
66
- fieldTabIndex: n ? -1 : s === null ? 0 : -1,
67
- handleSegmentFocus: k,
68
- handleFieldFocus: w,
72
+ focusedSegment: u,
73
+ fieldTabIndex: s ? -1 : u === null ? 0 : -1,
74
+ handleSegmentFocus: w,
75
+ handleFieldFocus: A,
69
76
  handleFieldBlur: M,
70
77
  handleFieldMouseDown: N,
71
78
  focusNext: P,
@@ -73,5 +80,5 @@ function G({
73
80
  };
74
81
  }
75
82
  export {
76
- G as useDateFieldFocus
83
+ H as useDateFieldFocus
77
84
  };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("react");function d({disabled:c,readOnly:u,fieldRef:a,focusNext:o,focusPrevious:n,adjustSegment:t,deleteLastDigit:y,clearSegment:p}){const w=b.useMemo(()=>{const i={ArrowRight:({segment:r,isRTL:e})=>((e?n:o)(r),!0),ArrowLeft:({segment:r,isRTL:e})=>((e?o:n)(r),!0)};return u?i:{...i,ArrowUp:({segment:r})=>t(r,1),ArrowDown:({segment:r})=>t(r,-1),PageUp:({segment:r})=>t(r,5),PageDown:({segment:r})=>t(r,-5),Home:({segment:r})=>t(r,"min"),End:({segment:r})=>t(r,"max"),Backspace:({segment:r})=>(y(r).wasEmpty&&n(r),!0),Delete:({segment:r})=>(p(r),!0)}},[t,p,y,o,n,u]);return b.useCallback((i,r)=>{if(c||r.altKey||r.ctrlKey||r.metaKey||r.shiftKey)return;const e=w[r.key];if(!e)return;const l=a.current,K=!!l&&(getComputedStyle(l).direction==="rtl"||!!l.closest('[dir="rtl"]'));e({segment:i,event:r,isRTL:K})&&r.preventDefault()},[c,w,a])}exports.useDateFieldKeyboard=d;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("react");function d({disabled:a,readOnly:c,fieldRef:y,focusNext:o,focusPrevious:e,adjustSegment:t,clearSegment:l}){const p=w.useMemo(()=>{const n={ArrowRight:({segment:r,isRTL:i})=>((i?e:o)(r),!0),ArrowLeft:({segment:r,isRTL:i})=>((i?o:e)(r),!0)};return c?n:{...n,ArrowUp:({segment:r})=>t(r,1),ArrowDown:({segment:r})=>t(r,-1),PageUp:({segment:r})=>t(r,5),PageDown:({segment:r})=>t(r,-5),Home:({segment:r})=>t(r,"min"),End:({segment:r})=>t(r,"max"),Backspace:({segment:r})=>(l(r).wasEmpty&&e(r),!0),Delete:({segment:r})=>(l(r),!0)}},[t,l,o,e,c]);return w.useCallback((n,r)=>{if(a||r.altKey||r.ctrlKey||r.metaKey||r.shiftKey)return;const i=p[r.key];if(!i)return;const u=y.current,b=!!u&&(getComputedStyle(u).direction==="rtl"||!!u.closest('[dir="rtl"]'));i({segment:n,event:r,isRTL:b})&&r.preventDefault()},[a,p,y])}exports.useDateFieldKeyboard=d;
@@ -41,18 +41,14 @@ export interface UseDateFieldKeyboardArgs {
41
41
  */
42
42
  adjustSegment: (type: SegmentType, amount: SegmentAdjustment) => boolean;
43
43
  /**
44
- * Removes the last raw digit from the segment buffer (Backspace).
45
- * Returns `{ wasEmpty: true }` when the buffer was already empty, signalling
46
- * the keyboard handler to move focus to the previous segment.
44
+ * Clears the entire segment buffer to `''` — shared by Backspace and Delete.
45
+ * Returns `{ wasEmpty: true }` when the buffer was already
46
+ * empty, signalling Backspace to move focus to the previous segment instead;
47
+ * Delete ignores the result and leaves focus on the current segment.
47
48
  * Provided by `useDateFieldValue`.
48
49
  */
49
- deleteLastDigit: (type: SegmentType) => {
50
+ clearSegment: (type: SegmentType) => {
50
51
  wasEmpty: boolean;
51
52
  };
52
- /**
53
- * Clears the entire segment buffer to `''` (Delete). Focus stays on the
54
- * current segment. Provided by `useDateFieldValue`.
55
- */
56
- clearSegment: (type: SegmentType) => void;
57
53
  }
58
- export declare function useDateFieldKeyboard({ disabled, readOnly, fieldRef, focusNext, focusPrevious, adjustSegment, deleteLastDigit, clearSegment, }: UseDateFieldKeyboardArgs): (segment: SegmentType, event: KeyboardEvent<HTMLSpanElement>) => void;
54
+ export declare function useDateFieldKeyboard({ disabled, readOnly, fieldRef, focusNext, focusPrevious, adjustSegment, clearSegment, }: UseDateFieldKeyboardArgs): (segment: SegmentType, event: KeyboardEvent<HTMLSpanElement>) => void;
@@ -1,49 +1,47 @@
1
- import { useMemo as f, useCallback as h } from "react";
2
- function b({
3
- disabled: p,
4
- readOnly: e,
5
- fieldRef: u,
1
+ import { useMemo as D, useCallback as K } from "react";
2
+ function A({
3
+ disabled: e,
4
+ readOnly: u,
5
+ fieldRef: w,
6
6
  focusNext: l,
7
- focusPrevious: i,
8
- adjustSegment: n,
9
- deleteLastDigit: w,
10
- clearSegment: y
7
+ focusPrevious: n,
8
+ adjustSegment: t,
9
+ clearSegment: p
11
10
  }) {
12
- const a = f(
13
- () => {
14
- const o = {
15
- // Nav keys always own the event (arrows are contentEditable caret keys we
16
- // suppress even at the first/last segment), so they always report handled.
17
- ArrowRight: ({ segment: r, isRTL: t }) => ((t ? i : l)(r), !0),
18
- ArrowLeft: ({ segment: r, isRTL: t }) => ((t ? l : i)(r), !0)
19
- };
20
- return e ? o : {
21
- ...o,
22
- ArrowUp: ({ segment: r }) => n(r, 1),
23
- ArrowDown: ({ segment: r }) => n(r, -1),
24
- PageUp: ({ segment: r }) => n(r, 5),
25
- PageDown: ({ segment: r }) => n(r, -5),
26
- Home: ({ segment: r }) => n(r, "min"),
27
- End: ({ segment: r }) => n(r, "max"),
28
- // DF-5: Backspace removes the last digit (empty → focus previous); Delete clears the segment.
29
- // Both always own the key (delete or focus-hop), so they report handled.
30
- Backspace: ({ segment: r }) => (w(r).wasEmpty && i(r), !0),
31
- Delete: ({ segment: r }) => (y(r), !0)
32
- };
33
- },
34
- [n, y, w, l, i, e]
35
- );
36
- return h(
11
+ const y = D(() => {
12
+ const o = {
13
+ // Nav keys always own the event (arrows are contentEditable caret keys we
14
+ // suppress even at the first/last segment), so they always report handled.
15
+ ArrowRight: ({ segment: r, isRTL: i }) => ((i ? n : l)(r), !0),
16
+ ArrowLeft: ({ segment: r, isRTL: i }) => ((i ? l : n)(r), !0)
17
+ };
18
+ return u ? o : {
19
+ ...o,
20
+ ArrowUp: ({ segment: r }) => t(r, 1),
21
+ ArrowDown: ({ segment: r }) => t(r, -1),
22
+ PageUp: ({ segment: r }) => t(r, 5),
23
+ PageDown: ({ segment: r }) => t(r, -5),
24
+ Home: ({ segment: r }) => t(r, "min"),
25
+ End: ({ segment: r }) => t(r, "max"),
26
+ // Backspace and Delete both clear the whole segment to
27
+ // placeholder. Backspace on an already-empty segment moves focus to the
28
+ // previous segment instead (MUI parity); Delete just clears.
29
+ // Both always own the key (clear or focus-hop), so they report handled.
30
+ Backspace: ({ segment: r }) => (p(r).wasEmpty && n(r), !0),
31
+ Delete: ({ segment: r }) => (p(r), !0)
32
+ };
33
+ }, [t, p, l, n, u]);
34
+ return K(
37
35
  (o, r) => {
38
- if (p || r.altKey || r.ctrlKey || r.metaKey || r.shiftKey) return;
39
- const t = a[r.key];
40
- if (!t) return;
41
- const c = u.current, K = !!c && (getComputedStyle(c).direction === "rtl" || !!c.closest('[dir="rtl"]'));
42
- t({ segment: o, event: r, isRTL: K }) && r.preventDefault();
36
+ if (e || r.altKey || r.ctrlKey || r.metaKey || r.shiftKey) return;
37
+ const i = y[r.key];
38
+ if (!i) return;
39
+ const c = w.current, a = !!c && (getComputedStyle(c).direction === "rtl" || !!c.closest('[dir="rtl"]'));
40
+ i({ segment: o, event: r, isRTL: a }) && r.preventDefault();
43
41
  },
44
- [p, a, u]
42
+ [e, y, w]
45
43
  );
46
44
  }
47
45
  export {
48
- b as useDateFieldKeyboard
46
+ A as useDateFieldKeyboard
49
47
  };
@@ -15,9 +15,11 @@ export interface UseDateFieldValidityReturn {
15
15
  allFilled: boolean;
16
16
  hasPartialValue: boolean;
17
17
  /** "Show error?" for value-driven invalidity. True when the user has
18
- * touched the field AND either:
19
- * - all segments are filled but combine to an invalid date (Feb 30), or
20
- * - some segments are filled, others empty, and focus has left the field. */
18
+ * touched the field AND (all segments filled but combine to an invalid
19
+ * date (Feb 30), OR some filled/some empty and focus has left).
20
+ * `minDate`/`maxDate` out-of-range values aren't flagged here — the
21
+ * built-in bound is a blur clamp (see `commitOnBlur`), not a validity
22
+ * constraint; use a `validationRule` for range errors/submit-blocking. */
21
23
  isInvalid: boolean;
22
24
  }
23
25
  export declare function useDateFieldValidity({ segments, currentValue, wasTouched, isFocused, }: UseDateFieldValidityArgs): UseDateFieldValidityReturn;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react"),r=require("./DateField.utils.cjs.js"),E=require("./DateField.validation.cjs.js");function M({value:l,defaultValue:F,onChange:g}){const T=t.useRef(l!==void 0),b=T.current,[i,S]=t.useState(()=>r.segmentTextFromValue(b?l??null:F??null)),[_,h]=t.useState(!1),c=t.useRef(i),d=t.useRef(new Set),o=t.useRef(!1),y={day:r.segmentNumber("day",i.day),month:r.segmentNumber("month",i.month),year:r.segmentNumber("year",i.year)},D=r.deriveValue(y),x=t.useRef(D),R=t.useRef(b?l??null:null),m=t.useRef(g);t.useEffect(()=>{m.current=g},[g]),t.useEffect(()=>{if(!T.current||o.current||r.isSameDateValue(l??null,R.current))return;R.current=l??null;const e=r.segmentTextFromValue(l??null);c.current=e,S(e),x.current=r.deriveValueFromText(e)},[l]);const f=t.useCallback(e=>{var u;const n=r.deriveValueFromText(e);r.isSameDateValue(n,x.current)||(x.current=n,(u=m.current)==null||u.call(m,n))},[]),a=t.useCallback((e,n,{replace:u})=>{const s={...c.current,[e]:n};c.current=s,S(s),h(!0),f(s),u?d.current.add(e):d.current.delete(e)},[f]),N=t.useCallback((e,n)=>{const u=d.current.has(e)?"":c.current[e],s=E.tryAppendDigit(e,u,n);return s.rejected?{advanced:!1,rejected:!0}:(a(e,s.newBuffer,{replace:s.shouldAdvance}),{advanced:s.shouldAdvance,rejected:!1})},[a]),k=t.useCallback((e,n)=>{const u=c.current,s=r.segmentNumber(e,u[e]),p=r.getDaysInMonth(r.segmentNumber("year",u.year),r.segmentNumber("month",u.month)),V=r.adjustSegmentValue(e,s,n,{daysInMonth:p,today:r.todayParts()});return V==null?!1:(o.current=!0,a(e,String(V).padStart(E.SEGMENT_MAX_LENGTH[e],"0"),{replace:!0}),!0)},[a]),C=t.useCallback(e=>{const n=c.current[e];return n===""?{wasEmpty:!0}:(o.current=!0,a(e,n.slice(0,-1),{replace:!1}),{wasEmpty:!1})},[a]),v=t.useCallback(e=>{c.current[e]!==""&&(o.current=!0,a(e,"",{replace:!1}))},[a]),w=t.useCallback(e=>{o.current=!0,d.current.add(e)},[]),j=t.useCallback(()=>{o.current=!1;const e=c.current,n={day:r.normalizeSegmentText("day",e.day),month:r.normalizeSegmentText("month",e.month),year:r.normalizeSegmentText("year",e.year)};c.current=n,S(n),h(!0),f(n)},[f]);return{segmentText:i,segmentValues:y,currentValue:D,isControlled:b,wasTouched:_,appendDigit:N,adjustSegment:k,deleteLastDigit:C,clearSegment:v,beginSegmentEdit:w,commitOnBlur:j}}exports.useDateFieldValue=M;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react"),t=require("./DateField.utils.cjs.js"),j=require("./DateField.validation.cjs.js");function G({value:a,defaultValue:A,onChange:x,minDate:R,maxDate:y,getClampAnnouncement:V}){const N=r.useRef(a!==void 0),F=N.current,[m,h]=r.useState(()=>t.segmentTextFromValue(F?a??null:A??null)),[D,_]=r.useState(!1),[C,M]=r.useState(""),c=r.useRef(m),f=r.useRef(new Set),d=r.useRef(!1),l=r.useRef(null),v={day:t.segmentNumber("day",m.day),month:t.segmentNumber("month",m.month),year:t.segmentNumber("year",m.year)},k=t.deriveValue(v),E=r.useRef(k),p=r.useRef(F?a??null:null),g=r.useRef(x),S=r.useRef(V);r.useEffect(()=>{g.current=x,S.current=V},[x,V]),r.useEffect(()=>()=>{l.current!=null&&cancelAnimationFrame(l.current)},[]),r.useEffect(()=>{if(!N.current||d.current||t.isSameDateValue(a??null,p.current))return;p.current=a??null;const e=t.segmentTextFromValue(a??null);c.current=e,h(e),E.current=t.deriveValueFromText(e)},[a]);const b=r.useCallback(e=>{var n;const s=t.deriveValueFromText(e);t.isSameDateValue(s,E.current)||(E.current=s,(n=g.current)==null||n.call(g,s))},[]),o=r.useCallback((e,s,{replace:n})=>{const u={...c.current,[e]:s};c.current=u,h(u),_(!0),b(u),n?f.current.add(e):f.current.delete(e)},[b]),q=r.useCallback((e,s)=>{const n=f.current.has(e)?"":c.current[e],u=j.tryAppendDigit(e,n,s);return u.rejected?{advanced:!1,rejected:!0}:(o(e,u.newBuffer,{replace:u.shouldAdvance}),{advanced:u.shouldAdvance,rejected:!1})},[o]),z=r.useCallback((e,s)=>{const n=c.current,u=t.segmentNumber(e,n[e]),T=t.getDaysInMonth(t.segmentNumber("year",n.year),t.segmentNumber("month",n.month)),i=t.adjustSegmentValue(e,u,s,{daysInMonth:T,today:t.todayParts()});return i==null?!1:(d.current=!0,o(e,String(i).padStart(j.SEGMENT_MAX_LENGTH[e],"0"),{replace:!0}),!0)},[o]),I=r.useCallback(e=>c.current[e]===""?{wasEmpty:!0}:(d.current=!0,o(e,"",{replace:!1}),{wasEmpty:!1}),[o]),O=r.useCallback(e=>{d.current=!0,f.current.add(e)},[]),B=r.useCallback(()=>{var T;d.current=!1;const e=c.current,s={day:t.normalizeSegmentText("day",e.day),month:t.normalizeSegmentText("month",e.month),year:t.normalizeSegmentText("year",e.year)},n=t.deriveValueFromText(s);let u=s;if(n!=null&&D&&!t.isDateInRange(n,R,y)){const i=t.clampDateToRange(n,R,y);if(u=t.segmentTextFromValue(i),!t.isSameDateValue(i,n)){const w=((T=S.current)==null?void 0:T.call(S,i))??"";w&&(l.current!=null&&cancelAnimationFrame(l.current),l.current=requestAnimationFrame(()=>{l.current=null,M(w)}))}}c.current=u,h(u),_(!0),b(u)},[b,D,t.dateKeyOrNull(R),t.dateKeyOrNull(y)]);return{segmentText:m,segmentValues:v,currentValue:k,isControlled:F,wasTouched:D,appendDigit:q,adjustSegment:z,clearSegment:I,beginSegmentEdit:O,commitOnBlur:B,clampAnnouncement:C}}exports.useDateFieldValue=G;
@@ -5,6 +5,23 @@ export interface UseDateFieldValueArgs {
5
5
  defaultValue?: Nullable<Date>;
6
6
  /** Fires on user-driven value transitions only, never on controlled `value` changes. */
7
7
  onChange?: (value: Nullable<Date>) => void;
8
+ /**
9
+ * Earliest allowed date (inclusive, compared by calendar day). Springs a
10
+ * touched value to this bound on blur (see `commitOnBlur`) — does not bound
11
+ * the year segment's spin/Home/End, which is free (see `adjustSegment`).
12
+ */
13
+ minDate?: Nullable<Date>;
14
+ /**
15
+ * Latest allowed date (inclusive, compared by calendar day). Springs a
16
+ * touched value to this bound on blur (see `commitOnBlur`) — does not bound
17
+ * the year segment's spin/Home/End, which is free (see `adjustSegment`).
18
+ */
19
+ maxDate?: Nullable<Date>;
20
+ /**
21
+ * Called when a touched value springs to a bound on blur; returns a localized
22
+ * message set on the polite live region. Omit → no announcement.
23
+ */
24
+ getClampAnnouncement?: (clampedDate: Date) => string;
8
25
  }
9
26
  export interface UseDateFieldValueReturn {
10
27
  segmentText: SegmentText;
@@ -17,41 +34,40 @@ export interface UseDateFieldValueReturn {
17
34
  * Increments, decrements, or jumps a segment to its min/max boundary.
18
35
  *
19
36
  * - Numeric `amount` (e.g. ±1, ±5): day/month wrap modularly; year clamps
20
- * to [1, 9999]. An empty segment seeds to today's value on the first press.
21
- * - `'min'` / `'max'`: jump to the lower/upper bound. No-op on year (no
22
- * meaningful bound until DF-10 adds minDate/maxDate).
37
+ * to `[YEAR_MIN, YEAR_MAX]` (free-spinning, independent of `minDate`/
38
+ * `maxDate` — see `DateField.utils.adjustSegmentValue`). An empty day/month
39
+ * segment seeds to a direction-based first/last valid value; an empty year
40
+ * seeds to the current year.
41
+ * - `'min'` / `'max'`: jump to the lower/upper bound. No-op on year (Home/End
42
+ * don't bound the year to `minDate`/`maxDate`).
23
43
  *
24
44
  * Follows the `appendDigit` mutation pattern: writes zero-padded `segmentText`,
25
45
  * sets `wasTouched`, calls `emitIfChanged`, and marks the segment in
26
46
  * `replaceNextRef` so a digit typed immediately after replaces rather than
27
47
  * appends.
28
48
  *
29
- * @returns `true` if the segment was adjusted, `false` on a no-op (currently
30
- * only year `'min'`/`'max'`, until DF-10 adds year bounds). The keyboard
31
- * dispatcher uses this to decide whether to `preventDefault` — a no-op leaves
32
- * the key to native (e.g. page scroll).
49
+ * @returns `true` if the segment was adjusted, `false` on a no-op (year
50
+ * `'min'`/`'max'`). The keyboard dispatcher uses this to decide whether to
51
+ * `preventDefault` — a no-op leaves the key to native (e.g. page scroll).
33
52
  */
34
53
  adjustSegment: (type: SegmentType, amount: SegmentAdjustment) => boolean;
35
54
  /**
36
- * Removes the last raw digit from the segment buffer (Backspace behaviour).
55
+ * Clears the entire segment buffer to `''` — the shared Backspace and
56
+ * Delete behaviour.
37
57
  *
38
- * Returns `{ wasEmpty: true }` when the buffer was already empty so the
39
- * caller (keyboard handler) knows to move focus to the previous segment.
40
- * Clears `replaceNextRef` for the segment so a digit typed immediately after
41
- * appends rather than replaces.
58
+ * Returns `{ wasEmpty: true }` when the buffer was already empty, without
59
+ * mutating, so the caller (keyboard handler) knows Backspace should move
60
+ * focus to the previous segment instead of clearing. Otherwise focus stays
61
+ * on the current segment. Fires `onChange(null)` via `emitIfChanged` when
62
+ * the cleared segment was part of a complete date. Clears `replaceNextRef`
63
+ * for the segment so the next digit appends.
42
64
  */
43
- deleteLastDigit: (type: SegmentType) => {
65
+ clearSegment: (type: SegmentType) => {
44
66
  wasEmpty: boolean;
45
67
  };
46
- /**
47
- * Clears the entire segment buffer to `''` (Delete behaviour).
48
- *
49
- * Focus stays on the current segment. Fires `onChange(null)` via
50
- * `emitIfChanged` when the cleared segment was part of a complete date.
51
- * Clears `replaceNextRef` for the segment so the next digit appends.
52
- */
53
- clearSegment: (type: SegmentType) => void;
54
68
  beginSegmentEdit: (type: SegmentType) => void;
55
69
  commitOnBlur: () => void;
70
+ /** Polite live-region message set when the blur clamp springs a value to a bound. */
71
+ clampAnnouncement: string;
56
72
  }
57
- export declare function useDateFieldValue({ value, defaultValue, onChange, }: UseDateFieldValueArgs): UseDateFieldValueReturn;
73
+ export declare function useDateFieldValue({ value, defaultValue, onChange, minDate, maxDate, getClampAnnouncement, }: UseDateFieldValueArgs): UseDateFieldValueReturn;