@astryxdesign/core 0.1.0-canary.e2d38fb → 0.1.0-canary.eb78210

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 +1 @@
1
- {"version":3,"file":"ChatLayoutScrollButton.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatLayoutScrollButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAO5C,MAAM,WAAW,2BAA4B,SAAQ,IAAI,CACvD,SAAS,CAAC,cAAc,CAAC,EACzB,SAAS,CACV;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAwDD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,GAAG,EACH,SAAS,EACT,KAAK,EACL,OAAO,EACP,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,2BAA2B,qBAwB7B;yBAhCe,sBAAsB"}
1
+ {"version":3,"file":"ChatLayoutScrollButton.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatLayoutScrollButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAO5C,MAAM,WAAW,2BAA4B,SAAQ,IAAI,CACvD,SAAS,CAAC,cAAc,CAAC,EACzB,SAAS,CACV;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAkDD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,GAAG,EACH,SAAS,EACT,KAAK,EACL,OAAO,EACP,MAAM,EACN,SAAS,EACT,KAAK,GACN,EAAE,2BAA2B,qBAwB7B;yBAhCe,sBAAsB"}
@@ -43,10 +43,6 @@ const styles = {
43
43
  khDVqt: "xuxw1ft",
44
44
  kg3NbH: "xf314gf",
45
45
  $$css: true
46
- },
47
- buttonWithLabel: {
48
- kwRFfy: "x1t818jl",
49
- $$css: true
50
46
  }
51
47
  };
52
48
 
@@ -99,7 +95,7 @@ export function ChatLayoutScrollButton({
99
95
  variant: "ghost",
100
96
  size: "md",
101
97
  onClick: onClick,
102
- xstyle: [styles.button, label ? styles.buttonWithLabel : null],
98
+ xstyle: styles.button,
103
99
  children: label ?? undefined
104
100
  })
105
101
  })
@@ -1 +1 @@
1
- {"version":3,"file":"dateParser.d.ts","sourceRoot":"","sources":["../../src/utils/dateParser.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAqC,MAAM,aAAa,CAAC;AAE/E,OAAO,EACL,gBAAgB,IAAI,QAAQ,EAC5B,cAAc,IAAI,SAAS,GAC5B,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAK1C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAsG9D"}
1
+ {"version":3,"file":"dateParser.d.ts","sourceRoot":"","sources":["../../src/utils/dateParser.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAqC,MAAM,aAAa,CAAC;AAE/E,OAAO,EACL,gBAAgB,IAAI,QAAQ,EAC5B,cAAc,IAAI,SAAS,GAC5B,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAK1C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAwF9D"}
@@ -112,23 +112,10 @@ export function parseDateInput(input) {
112
112
  return parseNumericDate(+first, +second, currentYear);
113
113
  }
114
114
 
115
- // 6. Fall back to native Date parsing for other formats.
116
- //
117
- // Skip bare numeric input (e.g. "0", "1", "01", "2026"). These are
118
- // in-progress values a user is still typing, not complete dates. Native
119
- // `Date` parsing coerces them into arbitrary dates ("0" -> year 2000 in V8,
120
- // year 0 in some engines), which is both surprising and — when the year
121
- // resolves to 0 — produces an out-of-range date that throws downstream.
122
- // Treat them as not-yet-a-valid-date instead.
123
- if (/^\d+$/.test(trimmed)) {
124
- return null;
125
- }
115
+ // 6. Fall back to native Date parsing for other formats
126
116
  const parsed = new Date(trimmed);
127
117
  if (!isNaN(parsed.getTime())) {
128
- const fromDate = plainDateFromDate(parsed);
129
- // Validate the result so we never return an out-of-range date (e.g. a
130
- // year of 0), which would throw when later re-parsed.
131
- return tryCreatePlainDate(fromDate.year, fromDate.month, fromDate.day);
118
+ return plainDateFromDate(parsed);
132
119
  }
133
120
  return null;
134
121
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/core",
3
- "version": "0.1.0-canary.e2d38fb",
3
+ "version": "0.1.0-canary.eb78210",
4
4
  "displayName": "XDS Core",
5
5
  "description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
6
6
  "author": "Meta Open Source",
@@ -15,7 +15,7 @@
15
15
  "url": "https://github.com/facebook/astryx/issues"
16
16
  },
17
17
  "keywords": [
18
- "astryx",
18
+ "xds",
19
19
  "design-system",
20
20
  "react",
21
21
  "components",
@@ -90,12 +90,6 @@ const styles = stylex.create({
90
90
  whiteSpace: 'nowrap',
91
91
  paddingInline: spacingVars['--spacing-2'],
92
92
  },
93
- // When a label is shown, the icon sits on the leading edge and the text on
94
- // the trailing edge. Symmetric padding leaves the text cramped against the
95
- // pill's rounded edge, so give the trailing side extra breathing room.
96
- buttonWithLabel: {
97
- paddingInlineEnd: spacingVars['--spacing-3'],
98
- },
99
93
  });
100
94
 
101
95
  // =============================================================================
@@ -136,7 +130,7 @@ export function ChatLayoutScrollButton({
136
130
  variant="ghost"
137
131
  size="md"
138
132
  onClick={onClick}
139
- xstyle={[styles.button, label ? styles.buttonWithLabel : null]}>
133
+ xstyle={styles.button}>
140
134
  {label ?? undefined}
141
135
  </Button>
142
136
  </div>
@@ -21,13 +21,19 @@ describe('DateInput', () => {
21
21
 
22
22
  it('renders with placeholder', () => {
23
23
  render(
24
- <DateInput label="Date" onChange={() => {}} placeholder="Pick a date" />,
24
+ <DateInput
25
+ label="Date"
26
+ onChange={() => {}}
27
+ placeholder="Pick a date"
28
+ />,
25
29
  );
26
30
  expect(screen.getByPlaceholderText('Pick a date')).toBeInTheDocument();
27
31
  });
28
32
 
29
33
  it('displays formatted date when value is provided', () => {
30
- render(<DateInput label="Date" value="2026-01-25" onChange={() => {}} />);
34
+ render(
35
+ <DateInput label="Date" value="2026-01-25" onChange={() => {}} />,
36
+ );
31
37
  expect(screen.getByDisplayValue('January 25, 2026')).toBeInTheDocument();
32
38
  });
33
39
 
@@ -112,7 +118,9 @@ describe('DateInput', () => {
112
118
 
113
119
  it('reverts to previous value on blur when input is invalid', async () => {
114
120
  const onChange = vi.fn();
115
- render(<DateInput label="Date" value="2026-01-25" onChange={onChange} />);
121
+ render(
122
+ <DateInput label="Date" value="2026-01-25" onChange={onChange} />,
123
+ );
116
124
 
117
125
  const input = screen.getByRole('combobox');
118
126
  fireEvent.change(input, {target: {value: 'not a date'}});
@@ -291,7 +299,9 @@ describe('DateInput', () => {
291
299
  // --- P1: Tab order: calendar button first, then input ---
292
300
 
293
301
  it('renders calendar button before input in DOM order', () => {
294
- const {container} = render(<DateInput label="Date" onChange={() => {}} />);
302
+ const {container} = render(
303
+ <DateInput label="Date" onChange={() => {}} />,
304
+ );
295
305
  const input = container.querySelector('input');
296
306
  const button = container.querySelector('button');
297
307
  // Calendar button should come before input in the DOM
@@ -379,7 +389,9 @@ describe('DateInput', () => {
379
389
 
380
390
  it('calls onChange with undefined when input is cleared and blurred', () => {
381
391
  const onChange = vi.fn();
382
- render(<DateInput label="Date" value="2026-01-25" onChange={onChange} />);
392
+ render(
393
+ <DateInput label="Date" value="2026-01-25" onChange={onChange} />,
394
+ );
383
395
 
384
396
  const input = screen.getByRole('combobox');
385
397
  fireEvent.change(input, {target: {value: ''}});
@@ -464,7 +476,9 @@ describe('DateInput', () => {
464
476
  });
465
477
 
466
478
  it('does not show clear button when hasClear is false', () => {
467
- render(<DateInput label="Date" value="2026-01-15" onChange={() => {}} />);
479
+ render(
480
+ <DateInput label="Date" value="2026-01-15" onChange={() => {}} />,
481
+ );
468
482
  expect(
469
483
  screen.queryByRole('button', {name: 'Clear Date'}),
470
484
  ).not.toBeInTheDocument();
@@ -500,68 +514,6 @@ describe('DateInput', () => {
500
514
  });
501
515
  });
502
516
 
503
- // --- Regression: in-progress / leading-zero input must not crash ---
504
-
505
- describe('incomplete typed input', () => {
506
- it('does not crash or fire onChange when first digit typed is 0', () => {
507
- const onChange = vi.fn();
508
- render(<DateInput label="Date" onChange={onChange} />);
509
-
510
- const input = screen.getByRole('combobox');
511
- // Typing a leading "0" (e.g. starting "01" for January) must be treated
512
- // as incomplete input, not coerced into an (invalid) date that crashes.
513
- expect(() =>
514
- fireEvent.change(input, {target: {value: '0'}}),
515
- ).not.toThrow();
516
-
517
- expect(onChange).not.toHaveBeenCalled();
518
- expect(input).toHaveValue('0');
519
- });
520
-
521
- it('does not crash or fire onChange when first digit typed is 1', () => {
522
- const onChange = vi.fn();
523
- render(<DateInput label="Date" onChange={onChange} />);
524
-
525
- const input = screen.getByRole('combobox');
526
- expect(() =>
527
- fireEvent.change(input, {target: {value: '1'}}),
528
- ).not.toThrow();
529
-
530
- expect(onChange).not.toHaveBeenCalled();
531
- expect(input).toHaveValue('1');
532
- });
533
-
534
- it('does not crash while progressively typing a numeric date', () => {
535
- const onChange = vi.fn();
536
- render(<DateInput label="Date" onChange={onChange} />);
537
-
538
- const input = screen.getByRole('combobox');
539
- // Simulate keystroke-by-keystroke entry of "01/15/2026". The leading
540
- // single-digit keystrokes must not crash (the original bug).
541
- for (const partial of ['0', '01', '01/', '01/1', '01/15', '01/15/']) {
542
- expect(() =>
543
- fireEvent.change(input, {target: {value: partial}}),
544
- ).not.toThrow();
545
- }
546
-
547
- // Completing the date commits it without error.
548
- expect(() =>
549
- fireEvent.change(input, {target: {value: '01/15/2026'}}),
550
- ).not.toThrow();
551
- expect(onChange).toHaveBeenCalledWith('2026-01-15');
552
- });
553
-
554
- it('does not crash on blur after typing an incomplete value', () => {
555
- const onChange = vi.fn();
556
- render(<DateInput label="Date" onChange={onChange} />);
557
-
558
- const input = screen.getByRole('combobox');
559
- fireEvent.change(input, {target: {value: '0'}});
560
- expect(() => fireEvent.blur(input)).not.toThrow();
561
- expect(onChange).not.toHaveBeenCalled();
562
- });
563
- });
564
-
565
517
  describe('external value changes', () => {
566
518
  it('clears pending input when value changes externally', () => {
567
519
  const onChange = vi.fn();
@@ -320,31 +320,5 @@ describe('parseDateInput', () => {
320
320
  it('rejects mixed separators', () => {
321
321
  expect(parseDateInput('1/25.2026')).toBeNull();
322
322
  });
323
-
324
- it('treats a single typed digit as incomplete, not a date', () => {
325
- // A user starting to type a month (e.g. "0" or "1" for January) should
326
- // not produce a date. Native Date parsing would otherwise coerce these
327
- // into arbitrary dates (and a year of 0 in some engines).
328
- expect(parseDateInput('0')).toBeNull();
329
- expect(parseDateInput('1')).toBeNull();
330
- });
331
-
332
- it('treats bare numeric input as incomplete, not a date', () => {
333
- expect(parseDateInput('00')).toBeNull();
334
- expect(parseDateInput('01')).toBeNull();
335
- expect(parseDateInput('12')).toBeNull();
336
- expect(parseDateInput('2026')).toBeNull();
337
- });
338
-
339
- it('never returns an out-of-range date for partial input', () => {
340
- // Regression: partial input must never yield a date with year < 1,
341
- // which would throw when later re-parsed and crash the page.
342
- for (const input of ['0', '1', '01', '00', '9', '99']) {
343
- const result = parseDateInput(input);
344
- if (result !== null) {
345
- expect(result.year).toBeGreaterThanOrEqual(1);
346
- }
347
- }
348
- });
349
323
  });
350
324
  });
@@ -124,24 +124,10 @@ export function parseDateInput(input: string): PlainDate | null {
124
124
  return parseNumericDate(+first, +second, currentYear);
125
125
  }
126
126
 
127
- // 6. Fall back to native Date parsing for other formats.
128
- //
129
- // Skip bare numeric input (e.g. "0", "1", "01", "2026"). These are
130
- // in-progress values a user is still typing, not complete dates. Native
131
- // `Date` parsing coerces them into arbitrary dates ("0" -> year 2000 in V8,
132
- // year 0 in some engines), which is both surprising and — when the year
133
- // resolves to 0 — produces an out-of-range date that throws downstream.
134
- // Treat them as not-yet-a-valid-date instead.
135
- if (/^\d+$/.test(trimmed)) {
136
- return null;
137
- }
138
-
127
+ // 6. Fall back to native Date parsing for other formats
139
128
  const parsed = new Date(trimmed);
140
129
  if (!isNaN(parsed.getTime())) {
141
- const fromDate = plainDateFromDate(parsed);
142
- // Validate the result so we never return an out-of-range date (e.g. a
143
- // year of 0), which would throw when later re-parsed.
144
- return tryCreatePlainDate(fromDate.year, fromDate.month, fromDate.day);
130
+ return plainDateFromDate(parsed);
145
131
  }
146
132
 
147
133
  return null;