@astryxdesign/core 0.6.3-canary.db52d98 → 0.6.3-canary.db80a3a

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":"Tokenizer.d.ts","sourceRoot":"","sources":["../../src/Tokenizer/Tokenizer.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Tokenizer.d.ts","sourceRoot":"","sources":["../../src/Tokenizer/Tokenizer.tsx"],"names":[],"mappings":"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"}
@@ -62,13 +62,6 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
62
62
  // How far the end lane sits from the field's inline-end border, named once
63
63
  // because the input's reserve is derived from the same value.
64
64
  const END_LANE_INSET = spacingVars['--spacing-2'];
65
- const TOKEN_ROW_INSET = `calc(${spacingVars['--spacing-1']} - 1px)`;
66
- // InputClearButton grows 2px past its visible box under `(pointer: coarse)`.
67
- // Keep this maximum reserve in sync with Field/InputClearButton.tsx.
68
- const INPUT_CLEAR_COARSE_POINTER_OUTSET = '2px';
69
- // Kept in sync with useEndLaneReserve: inputCompact reads the custom property
70
- // directly so its empty-query pseudo-class can suppress the inner reserve.
71
- const END_LANE_RESERVE_VAR = '--_tokenizer-end-lane-reserve';
72
65
  const styles = {
73
66
  wrapper: {
74
67
  kVAEAm: "x1n2onr6",
@@ -87,8 +80,6 @@ const styles = {
87
80
  token: {
88
81
  k1xSpc: "x78zum5",
89
82
  kmuXW: "x2lah0s",
90
- kVAEAm: "x1n2onr6",
91
- kY2c9j: "x1vjfegm",
92
83
  $$css: true
93
84
  },
94
85
  endSection: {
@@ -98,7 +89,6 @@ const styles = {
98
89
  kGNEyG: "x6s0dn4",
99
90
  kOIVth: "x1txdalj",
100
91
  kmuXW: "x2lah0s",
101
- kY2c9j: "x1vjfegm",
102
92
  $$css: true
103
93
  },
104
94
  inputAtMax: {
@@ -111,16 +101,10 @@ const styles = {
111
101
  $$css: true
112
102
  },
113
103
  inputCompact: {
114
- kVAEAm: "x1n2onr6 x1utg46d",
115
- kB7OPa: "x9f619",
116
- kLqNvP: "xhi6v0a x1cs7wtd",
117
- kY2c9j: "x1ja2u2z",
118
- k7Eaqz: "x1fns5xo xcax4zt",
119
- kUk6DE: "xfoc8du xf0xpto",
120
- kzqmXN: "xnalus7 xbuu7xz",
121
- kZCmMZ: "x2a0j69 xf0ofad",
122
- kwRFfy: "x1p6hqjl x1wg34a1",
123
- k9WMMc: "x1yc453h x75j1tr",
104
+ k7Eaqz: "x1fns5xo",
105
+ kUk6DE: "xfoc8du",
106
+ kzqmXN: "xnalus7",
107
+ kZCmMZ: "x2a0j69",
124
108
  $$css: true
125
109
  },
126
110
  truncatedWrapper: {
@@ -164,23 +148,6 @@ const endSectionSizeStyles = {
164
148
  $$css: true
165
149
  }
166
150
  };
167
- const compactInputSizeStyles = {
168
- sm: {
169
- k87sOh: "x80663w x1a21zuh",
170
- k3aq6I: "x1c071of xv6p7n0",
171
- $$css: true
172
- },
173
- md: {
174
- k87sOh: "x80663w x811pv0",
175
- k3aq6I: "x1c071of xv6p7n0",
176
- $$css: true
177
- },
178
- lg: {
179
- k87sOh: "x80663w x1o13q2w",
180
- k3aq6I: "x1c071of xv6p7n0",
181
- $$css: true
182
- }
183
- };
184
151
  const truncatedSizeStyles = {
185
152
  sm: {
186
153
  kZKoxP: "x6k0iem",
@@ -377,8 +344,7 @@ export function Tokenizer({
377
344
  // is the leaf's own business — folding it in here would mean reading the
378
345
  // busy state during this render, which is exactly the re-render the store
379
346
  // exists to avoid.
380
- const hasClearButton = hasClear && value.length > 0 && !isDisabled;
381
- const hasStaticEndLane = Boolean(endContent || hasClearButton);
347
+ const hasStaticEndLane = Boolean(endContent || hasClear && value.length > 0 && !isDisabled);
382
348
  const [isFocusedWithin, setIsFocusedWithin] = useState(false);
383
349
  const isTruncated = !isFocusedWithin && tokenOverflowBehavior !== 'none' && value.length > 0;
384
350
 
@@ -596,7 +562,7 @@ export function Tokenizer({
596
562
  if (renderToken) {
597
563
  return /*#__PURE__*/_jsx("span", {
598
564
  ...{
599
- className: "x78zum5 x2lah0s x1n2onr6 x1vjfegm"
565
+ className: "x78zum5 x2lah0s"
600
566
  },
601
567
  children: renderToken(item, onRemoveItem)
602
568
  }, item.id);
@@ -641,7 +607,7 @@ export function Tokenizer({
641
607
  ...{
642
608
  0: {},
643
609
  1: {
644
- className: "x1xrm450 x1n2onr6 x1vjfegm"
610
+ className: "x1xrm450"
645
611
  }
646
612
  }[!!(value.length > 0) << 0],
647
613
  children: renderIconSlot(startIcon, {
@@ -665,11 +631,8 @@ export function Tokenizer({
665
631
  searchSource: isAtMax ? emptySource : filteredSource,
666
632
  value: null,
667
633
  onChange: handleAdd,
668
- renderItem: renderItem
669
- // A space keeps :placeholder-shown available as the CSS-only empty
670
- // query signal without painting placeholder text beside tokens.
671
- ,
672
- placeholder: value.length === 0 ? placeholder : ' ',
634
+ renderItem: renderItem,
635
+ placeholder: value.length === 0 ? placeholder : '',
673
636
  hasEntriesOnFocus: isAtMax ? false : hasEntriesOnFocus,
674
637
  maxMenuItems: maxMenuItems,
675
638
  menuWidth: menuWidth,
@@ -686,11 +649,13 @@ export function Tokenizer({
686
649
  onKeyDown: handleKeyDown,
687
650
  anchorRef: wrapperRef,
688
651
  size: size,
689
- inputXStyle: [isAtMax || isTruncated ? styles.inputAtMax : value.length > 0 ? [styles.inputCompact, compactInputSizeStyles[size]] : undefined,
690
- // The compact-token style owns the same reserve with an empty-query
691
- // exception. This standalone rule is only for an empty Tokenizer;
692
- // it still resolves to zero until the lane publishes a width.
693
- !(isAtMax || isTruncated || value.length > 0) && laneReserve]
652
+ inputXStyle: [isAtMax || isTruncated ? styles.inputAtMax : value.length > 0 ? styles.inputCompact : undefined,
653
+ // Not for the collapsed states above: those give the input no width
654
+ // to pad, and `inputAtMax` zeroes its padding outright.
655
+ // Applied whether or not a lane is up: the reserve resolves to
656
+ // zero until the lane publishes a width, so this does not need to
657
+ // know about the busy state.
658
+ !(isAtMax || isTruncated) && laneReserve]
694
659
  })
695
660
  }), htmlName != null && value.map(item => /*#__PURE__*/_jsx("input", {
696
661
  type: "hidden",
@@ -706,7 +671,7 @@ export function Tokenizer({
706
671
  laneXStyle: [styles.endSection, endSectionSizeStyles[size]],
707
672
  loadingLabel: t('@astryx.typeahead.loading'),
708
673
  hasStaticContent: hasStaticEndLane,
709
- children: [endContent, hasClearButton && /*#__PURE__*/_jsx(InputClearButton, {
674
+ children: [endContent, hasClear && value.length > 0 && !isDisabled && /*#__PURE__*/_jsx(InputClearButton, {
710
675
  label: t('@astryx.tokenizer.clearAll'),
711
676
  onClick: e => {
712
677
  e.stopPropagation();
@@ -23,10 +23,9 @@ import * as stylex from '@stylexjs/stylex';
23
23
  *
24
24
  * Takes the lane's inset from the field's inline-end border, as the CSS
25
25
  * expression that positions it. Returns a ref callback for the lane, and the
26
- * ordinary input reserve style. Tokenizer's compact input reads the same custom
27
- * property directly so its empty-query hit surface can stop before the lane.
28
- * With no lane mounted the variable is absent and either rule resolves to its
29
- * no-lane fallback, so neither path needs to know whether a search is running.
26
+ * style for the input — which the caller applies unconditionally: with no lane
27
+ * mounted the variable is absent and the padding resolves to zero, so the
28
+ * caller never has to know whether a search is running.
30
29
  */
31
30
  export declare function useEndLaneReserve(laneInset: string): [(node: HTMLElement | null) => void, stylex.StyleXStyles];
32
31
  //# sourceMappingURL=useEndLaneReserve.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useEndLaneReserve.d.ts","sourceRoot":"","sources":["../../src/Tokenizer/useEndLaneReserve.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AA+B3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAChB,CAAC,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,CAuD3D"}
1
+ {"version":3,"file":"useEndLaneReserve.d.ts","sourceRoot":"","sources":["../../src/Tokenizer/useEndLaneReserve.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAgC3C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAChB,CAAC,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,CAuD3D"}
@@ -47,8 +47,9 @@ const LANE_RESERVE_VAR = '--_tokenizer-end-lane-reserve';
47
47
  // The variable carries the WHOLE reserve, not just the width, so its absence
48
48
  // means "no lane" rather than "a lane of zero width": with no lane up, the
49
49
  // fallback resolves the padding to 0 and the input keeps its full content box.
50
- // That is what lets every input state read the property without knowing whether
51
- // a search is running. The rule stays static either way — it is never
50
+ // That is what lets the caller apply this style unconditionally, which in turn
51
+ // is what keeps the field from having to know whether a search is running.
52
+ // The rule stays static either way — one class, generated once, never
52
53
  // regenerated as the lane changes.
53
54
  const reserveStyles = {
54
55
  reserve: {
@@ -81,10 +82,9 @@ const reserveStyles = {
81
82
  *
82
83
  * Takes the lane's inset from the field's inline-end border, as the CSS
83
84
  * expression that positions it. Returns a ref callback for the lane, and the
84
- * ordinary input reserve style. Tokenizer's compact input reads the same custom
85
- * property directly so its empty-query hit surface can stop before the lane.
86
- * With no lane mounted the variable is absent and either rule resolves to its
87
- * no-lane fallback, so neither path needs to know whether a search is running.
85
+ * style for the input — which the caller applies unconditionally: with no lane
86
+ * mounted the variable is absent and the padding resolves to zero, so the
87
+ * caller never has to know whether a search is running.
88
88
  */
89
89
  export function useEndLaneReserve(laneInset) {
90
90
  const laneRef = useCallback(node => {
package/dist/astryx.css CHANGED
@@ -584,7 +584,6 @@
584
584
  .x1dordxg:focus-within:not(#\#):not(#\#){overflow:visible}
585
585
  .xb0m1lw:has(> div > .astryx-layout-content):not(#\#):not(#\#){margin-inline:0}
586
586
  .x16s19ga:has(:focus-visible):not(#\#):not(#\#){outline:var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color)}
587
- .xf0xpto:placeholder-shown:not(#\#):not(#\#){flex:0 0 auto}
588
587
  .x64lkcz:focus:not(#\#):not(#\#){border-color:var(--color-error)}
589
588
  .x1lglk5v:focus:not(#\#):not(#\#){border-color:var(--color-success)}
590
589
  .x12sck4v:focus:not(#\#):not(#\#){border-color:var(--color-warning)}
@@ -992,7 +991,6 @@
992
991
  .x9p6ekw:not(#\#):not(#\#):not(#\#){inset-inline-start:14px}
993
992
  .xaoy8p5:not(#\#):not(#\#):not(#\#){inset-inline-start:2px}
994
993
  .xbudbmw:not(#\#):not(#\#):not(#\#){inset-inline-start:50%}
995
- .xhi6v0a:not(#\#):not(#\#):not(#\#){inset-inline-start:auto}
996
994
  .xmt1zuk:not(#\#):not(#\#):not(#\#){inset-inline-start:calc(-1 * (var(--spacing-1) - 1px))}
997
995
  .x1kiyvbf:not(#\#):not(#\#):not(#\#){inset-inline-start:var(--_textarea-inline-padding)}
998
996
  .x1ybfrjj:not(#\#):not(#\#):not(#\#){inset-inline-start:var(--spacing-3)}
@@ -1442,12 +1440,6 @@
1442
1440
  .x1dnou9g:nth-child(even):not(#\#):not(#\#):not(#\#){background-color:var(--color-background-muted)}
1443
1441
  .xjl7jj:empty:not(#\#):not(#\#):not(#\#){display:none}
1444
1442
  .x1e0d1ib:empty:not(#\#):not(#\#):not(#\#){padding-inline-start:0}
1445
- .x1cs7wtd:placeholder-shown:not(#\#):not(#\#):not(#\#){inset-inline-start:calc(var(--spacing-1) - 1px)}
1446
- .x1wg34a1:placeholder-shown:not(#\#):not(#\#):not(#\#){padding-inline-end:var(--spacing-1)}
1447
- .xf0ofad:placeholder-shown:not(#\#):not(#\#):not(#\#){padding-inline-start:0}
1448
- .x1utg46d:placeholder-shown:not(#\#):not(#\#):not(#\#){position:absolute}
1449
- .x75j1tr:placeholder-shown:not(#\#):not(#\#):not(#\#){text-align:end}
1450
- .xv6p7n0:placeholder-shown:not(#\#):not(#\#):not(#\#){transform:translateY(-50%)}
1451
1443
  .x1c52tdz:focus:not(#\#):not(#\#):not(#\#){background-color:var(--color-overlay-hover)}
1452
1444
  .x1rsz1da:focus:not(#\#):not(#\#):not(#\#){clip-path:none}
1453
1445
  .xodanix:focus:not(#\#):not(#\#):not(#\#){inset-inline-start:var(--spacing-2)}
@@ -1806,7 +1798,6 @@
1806
1798
  .xs7f9wi:not(#\#):not(#\#):not(#\#):not(#\#){top:2px}
1807
1799
  .xwa60dl:not(#\#):not(#\#):not(#\#):not(#\#){top:50%}
1808
1800
  .x1ltwjim:not(#\#):not(#\#):not(#\#):not(#\#){top:anchor(--outline-active top,0px)}
1809
- .x80663w:not(#\#):not(#\#):not(#\#):not(#\#){top:auto}
1810
1801
  .x7rbydg:not(#\#):not(#\#):not(#\#):not(#\#){top:calc(50% - (28px / 2))}
1811
1802
  .x1oysc8t:not(#\#):not(#\#):not(#\#):not(#\#){top:calc(var(--size-element-lg) / 2 - 1px)}
1812
1803
  .xkmsrut:not(#\#):not(#\#):not(#\#):not(#\#){top:calc(var(--size-element-md) / 2 - 1px)}
@@ -1891,11 +1882,6 @@
1891
1882
  .x1t1lzn6:last-child:not(#\#):not(#\#):not(#\#):not(#\#){border-bottom-width:0}
1892
1883
  .xlayyun:last-child:not(#\#):not(#\#):not(#\#):not(#\#){margin-bottom:calc(-1 * var(--container-padding-block-end,0px))}
1893
1884
  .xup0pd7:last-child:not(#\#):not(#\#):not(#\#):not(#\#){padding-bottom:0}
1894
- .xcax4zt:placeholder-shown:not(#\#):not(#\#):not(#\#):not(#\#){min-width:1px}
1895
- .x1o13q2w:placeholder-shown:not(#\#):not(#\#):not(#\#):not(#\#){top:calc(var(--size-element-lg) / 2 - 1px)}
1896
- .x811pv0:placeholder-shown:not(#\#):not(#\#):not(#\#):not(#\#){top:calc(var(--size-element-md) / 2 - 1px)}
1897
- .x1a21zuh:placeholder-shown:not(#\#):not(#\#):not(#\#):not(#\#){top:calc(var(--size-element-sm) / 2 - 1px)}
1898
- .xbuu7xz:placeholder-shown:not(#\#):not(#\#):not(#\#):not(#\#){width:calc(100% - calc(var(--spacing-1) - 1px) - var(--_tokenizer-end-lane-reserve,calc(var(--spacing-1) - 1px)) - 2px - 1px)}
1899
1885
  .x15cytp8:focus:not(#\#):not(#\#):not(#\#):not(#\#){height:auto}
1900
1886
  .x1rw3289:focus:not(#\#):not(#\#):not(#\#):not(#\#){top:var(--spacing-2)}
1901
1887
  .x1jqxupm:focus:not(#\#):not(#\#):not(#\#):not(#\#){width:auto}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/core",
3
- "version": "0.6.3-canary.db52d98",
3
+ "version": "0.6.3-canary.db80a3a",
4
4
  "displayName": "Astryx 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",
@@ -692,8 +692,8 @@
692
692
  "react-dom": ">=19.0.0"
693
693
  },
694
694
  "devDependencies": {
695
- "@astryxdesign/a11y-spec": "0.6.3-canary.db52d98",
696
- "@astryxdesign/cli": "0.6.3-canary.db52d98",
695
+ "@astryxdesign/a11y-spec": "0.6.3-canary.db80a3a",
696
+ "@astryxdesign/cli": "0.6.3-canary.db80a3a",
697
697
  "@babel/cli": "^7.29.7",
698
698
  "@babel/core": "^7.29.7",
699
699
  "@babel/preset-react": "^7.29.7",
@@ -416,29 +416,6 @@ describe('Tokenizer', () => {
416
416
  expect(input).not.toHaveAttribute('placeholder', 'Search people...');
417
417
  });
418
418
 
419
- it('uses a non-painting placeholder to collapse only an empty trailing input', () => {
420
- const onChangeQuery = vi.fn();
421
- render(
422
- <Tokenizer
423
- label="Members"
424
- searchSource={userSource}
425
- value={[users[0]]}
426
- onChange={() => {}}
427
- onChangeQuery={onChangeQuery}
428
- hasClear
429
- />,
430
- );
431
- const input = screen.getByRole('combobox');
432
- expect(input).toHaveAttribute('placeholder', ' ');
433
-
434
- fireEvent.change(input, {target: {value: 'Al'}});
435
- expect(input).toHaveValue('Al');
436
- expect(onChangeQuery).toHaveBeenLastCalledWith('Al');
437
-
438
- fireEvent.change(input, {target: {value: ''}});
439
- expect(onChangeQuery).toHaveBeenLastCalledWith('');
440
- });
441
-
442
419
  it('shows placeholder when no tokens are present', () => {
443
420
  render(
444
421
  <Tokenizer
@@ -243,13 +243,6 @@ export interface TokenizerProps<T extends SearchableItem> extends Omit<
243
243
  // How far the end lane sits from the field's inline-end border, named once
244
244
  // because the input's reserve is derived from the same value.
245
245
  const END_LANE_INSET = spacingVars['--spacing-2'];
246
- const TOKEN_ROW_INSET = `calc(${spacingVars['--spacing-1']} - 1px)`;
247
- // InputClearButton grows 2px past its visible box under `(pointer: coarse)`.
248
- // Keep this maximum reserve in sync with Field/InputClearButton.tsx.
249
- const INPUT_CLEAR_COARSE_POINTER_OUTSET = '2px';
250
- // Kept in sync with useEndLaneReserve: inputCompact reads the custom property
251
- // directly so its empty-query pseudo-class can suppress the inner reserve.
252
- const END_LANE_RESERVE_VAR = '--_tokenizer-end-lane-reserve';
253
246
 
254
247
  const styles = stylex.create({
255
248
  wrapper: {
@@ -267,23 +260,19 @@ const styles = stylex.create({
267
260
  // (radius-1: 4px) sits concentric with wrapper border-radius
268
261
  // (radius-2: 8px) when inset = radius-2 - radius-1 - border
269
262
  // = 8 - 4 - 1 = 3px.
270
- paddingBlock: TOKEN_ROW_INSET,
271
- paddingInline: TOKEN_ROW_INSET,
263
+ paddingBlock: `calc(${spacingVars['--spacing-1']} - 1px)`,
264
+ paddingInline: `calc(${spacingVars['--spacing-1']} - 1px)`,
272
265
  // Row gap must match paddingBlock so wrapped rows look evenly spaced.
273
- rowGap: TOKEN_ROW_INSET,
266
+ rowGap: `calc(${spacingVars['--spacing-1']} - 1px)`,
274
267
  },
275
268
  startIconWithTokens: {
276
269
  // Restore the default 8px inline-start inset when tokens are present,
277
270
  // since wrapperWithTokens reduces padding to 3px for border concentricity.
278
271
  marginInlineStart: `calc(${spacingVars['--spacing-2']} - ${spacingVars['--spacing-1']} + 1px)`,
279
- position: 'relative',
280
- zIndex: 1,
281
272
  },
282
273
  token: {
283
274
  display: 'flex',
284
275
  flexShrink: 0,
285
- position: 'relative',
286
- zIndex: 1,
287
276
  },
288
277
  endSection: {
289
278
  position: 'absolute',
@@ -295,7 +284,6 @@ const styles = stylex.create({
295
284
  alignItems: 'center',
296
285
  gap: spacingVars['--spacing-2'],
297
286
  flexShrink: 0,
298
- zIndex: 1,
299
287
  },
300
288
  inputAtMax: {
301
289
  width: 0,
@@ -306,46 +294,12 @@ const styles = stylex.create({
306
294
  position: 'absolute',
307
295
  },
308
296
  inputCompact: {
309
- position: {
310
- default: 'relative',
311
- ':placeholder-shown': 'absolute',
312
- },
313
- boxSizing: 'border-box',
314
- insetInlineStart: {
315
- default: 'auto',
316
- ':placeholder-shown': TOKEN_ROW_INSET,
317
- },
318
- zIndex: 0,
319
- minWidth: {
320
- default: '40px',
321
- ':placeholder-shown': '1px',
322
- },
323
- flex: {
324
- default: '1 1 40px',
325
- ':placeholder-shown': '0 0 auto',
326
- },
327
- width: {
328
- default: 0,
329
- ':placeholder-shown': `calc(100% - ${TOKEN_ROW_INSET} - var(${END_LANE_RESERVE_VAR}, ${TOKEN_ROW_INSET}) - ${INPUT_CLEAR_COARSE_POINTER_OUTSET} - 1px)`,
330
- },
331
- // The empty input is a first-row background hit surface. Taking it out of
332
- // flex layout means it can neither become a blank final row nor compete
333
- // with the pills for width. Logical insets stop it before the measured end
334
- // lane plus InputClearButton's maximum invisible pointer outset; tokens and
335
- // controls sit above it, leaving only genuine whitespace clickable as
336
- // search. Typing restores the ordinary in-flow input.
337
- paddingInlineStart: {
338
- default: `calc(${spacingVars['--spacing-2']} - ${spacingVars['--spacing-1']} + 1px)`,
339
- ':placeholder-shown': 0,
340
- },
341
- paddingInlineEnd: {
342
- default: `var(${END_LANE_RESERVE_VAR}, 0px)`,
343
- ':placeholder-shown': spacingVars['--spacing-1'],
344
- },
345
- textAlign: {
346
- default: 'start',
347
- ':placeholder-shown': 'end',
348
- },
297
+ minWidth: '40px',
298
+ flex: '1 1 40px',
299
+ width: 0,
300
+ // Restore normal text inset when input follows tokens, since the
301
+ // wrapper padding is reduced for border concentricity.
302
+ paddingInlineStart: `calc(${spacingVars['--spacing-2']} - ${spacingVars['--spacing-1']} + 1px)`,
349
303
  },
350
304
  truncatedWrapper: {
351
305
  flexWrap: 'nowrap',
@@ -387,39 +341,6 @@ const endSectionSizeStyles = stylex.create({
387
341
  },
388
342
  });
389
343
 
390
- const compactInputSizeStyles = stylex.create({
391
- sm: {
392
- insetBlockStart: {
393
- default: 'auto',
394
- ':placeholder-shown': `calc(${sizeVars['--size-element-sm']} / 2 - 1px)`,
395
- },
396
- transform: {
397
- default: 'none',
398
- ':placeholder-shown': 'translateY(-50%)',
399
- },
400
- },
401
- md: {
402
- insetBlockStart: {
403
- default: 'auto',
404
- ':placeholder-shown': `calc(${sizeVars['--size-element-md']} / 2 - 1px)`,
405
- },
406
- transform: {
407
- default: 'none',
408
- ':placeholder-shown': 'translateY(-50%)',
409
- },
410
- },
411
- lg: {
412
- insetBlockStart: {
413
- default: 'auto',
414
- ':placeholder-shown': `calc(${sizeVars['--size-element-lg']} / 2 - 1px)`,
415
- },
416
- transform: {
417
- default: 'none',
418
- ':placeholder-shown': 'translateY(-50%)',
419
- },
420
- },
421
- });
422
-
423
344
  const truncatedSizeStyles = stylex.create({
424
345
  sm: {height: sizeVars['--size-element-sm']},
425
346
  md: {height: sizeVars['--size-element-md']},
@@ -606,8 +527,9 @@ export function Tokenizer<T extends SearchableItem>({
606
527
  // is the leaf's own business — folding it in here would mean reading the
607
528
  // busy state during this render, which is exactly the re-render the store
608
529
  // exists to avoid.
609
- const hasClearButton = hasClear && value.length > 0 && !isDisabled;
610
- const hasStaticEndLane = Boolean(endContent || hasClearButton);
530
+ const hasStaticEndLane = Boolean(
531
+ endContent || (hasClear && value.length > 0 && !isDisabled),
532
+ );
611
533
  const [isFocusedWithin, setIsFocusedWithin] = useState(false);
612
534
  const isTruncated =
613
535
  !isFocusedWithin && tokenOverflowBehavior !== 'none' && value.length > 0;
@@ -952,9 +874,7 @@ export function Tokenizer<T extends SearchableItem>({
952
874
  value={null}
953
875
  onChange={handleAdd}
954
876
  renderItem={renderItem}
955
- // A space keeps :placeholder-shown available as the CSS-only empty
956
- // query signal without painting placeholder text beside tokens.
957
- placeholder={value.length === 0 ? placeholder : ' '}
877
+ placeholder={value.length === 0 ? placeholder : ''}
958
878
  hasEntriesOnFocus={isAtMax ? false : hasEntriesOnFocus}
959
879
  maxMenuItems={maxMenuItems}
960
880
  menuWidth={menuWidth}
@@ -975,12 +895,14 @@ export function Tokenizer<T extends SearchableItem>({
975
895
  isAtMax || isTruncated
976
896
  ? styles.inputAtMax
977
897
  : value.length > 0
978
- ? [styles.inputCompact, compactInputSizeStyles[size]]
898
+ ? styles.inputCompact
979
899
  : undefined,
980
- // The compact-token style owns the same reserve with an empty-query
981
- // exception. This standalone rule is only for an empty Tokenizer;
982
- // it still resolves to zero until the lane publishes a width.
983
- !(isAtMax || isTruncated || value.length > 0) && laneReserve,
900
+ // Not for the collapsed states above: those give the input no width
901
+ // to pad, and `inputAtMax` zeroes its padding outright.
902
+ // Applied whether or not a lane is up: the reserve resolves to
903
+ // zero until the lane publishes a width, so this does not need to
904
+ // know about the busy state.
905
+ !(isAtMax || isTruncated) && laneReserve,
984
906
  ]}
985
907
  />
986
908
  </BusyIndicatorLaneProvider>
@@ -1003,7 +925,7 @@ export function Tokenizer<T extends SearchableItem>({
1003
925
  loadingLabel={t('@astryx.typeahead.loading')}
1004
926
  hasStaticContent={hasStaticEndLane}>
1005
927
  {endContent}
1006
- {hasClearButton && (
928
+ {hasClear && value.length > 0 && !isDisabled && (
1007
929
  <InputClearButton
1008
930
  label={t('@astryx.tokenizer.clearAll')}
1009
931
  onClick={e => {
@@ -48,8 +48,9 @@ const LANE_RESERVE_VAR = '--_tokenizer-end-lane-reserve';
48
48
  // The variable carries the WHOLE reserve, not just the width, so its absence
49
49
  // means "no lane" rather than "a lane of zero width": with no lane up, the
50
50
  // fallback resolves the padding to 0 and the input keeps its full content box.
51
- // That is what lets every input state read the property without knowing whether
52
- // a search is running. The rule stays static either way — it is never
51
+ // That is what lets the caller apply this style unconditionally, which in turn
52
+ // is what keeps the field from having to know whether a search is running.
53
+ // The rule stays static either way — one class, generated once, never
53
54
  // regenerated as the lane changes.
54
55
  const reserveStyles = stylex.create({
55
56
  reserve: {
@@ -81,10 +82,9 @@ const reserveStyles = stylex.create({
81
82
  *
82
83
  * Takes the lane's inset from the field's inline-end border, as the CSS
83
84
  * expression that positions it. Returns a ref callback for the lane, and the
84
- * ordinary input reserve style. Tokenizer's compact input reads the same custom
85
- * property directly so its empty-query hit surface can stop before the lane.
86
- * With no lane mounted the variable is absent and either rule resolves to its
87
- * no-lane fallback, so neither path needs to know whether a search is running.
85
+ * style for the input — which the caller applies unconditionally: with no lane
86
+ * mounted the variable is absent and the padding resolves to zero, so the
87
+ * caller never has to know whether a search is running.
88
88
  */
89
89
  export function useEndLaneReserve(
90
90
  laneInset: string,