atlas-react-kit 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/COMPONENTS.md +22 -18
  2. package/dist/alert.js +2 -2
  3. package/dist/card.js +2 -1
  4. package/dist/combobox.d.ts +4 -3
  5. package/dist/combobox.js +3 -7
  6. package/dist/dialog.js +2 -1
  7. package/dist/dropdown-menu.js +6 -4
  8. package/dist/form/checkbox-field.d.ts +2 -4
  9. package/dist/form/checkbox-field.js +9 -12
  10. package/dist/form/combobox-field.d.ts +2 -2
  11. package/dist/form/combobox-field.js +5 -6
  12. package/dist/form/control-field.d.ts +5 -5
  13. package/dist/form/control-field.js +9 -7
  14. package/dist/form/date-picker-field.d.ts +1 -1
  15. package/dist/form/date-picker-field.js +3 -10
  16. package/dist/form/date-time-picker-field.d.ts +1 -1
  17. package/dist/form/date-time-picker-field.js +3 -10
  18. package/dist/form/field-error.d.ts +10 -1
  19. package/dist/form/field-shell.d.ts +27 -16
  20. package/dist/form/field-shell.js +27 -2
  21. package/dist/form/focus-first-invalid.d.ts +7 -4
  22. package/dist/form/focus-first-invalid.js +10 -6
  23. package/dist/form/markdown-field.d.ts +1 -1
  24. package/dist/form/markdown-field.js +8 -4
  25. package/dist/form/select-field.d.ts +2 -8
  26. package/dist/form/select-field.js +5 -7
  27. package/dist/form/text-field.d.ts +2 -8
  28. package/dist/form/text-field.js +8 -3
  29. package/dist/form/toggle-group-field.d.ts +2 -2
  30. package/dist/form/toggle-group-field.js +5 -6
  31. package/dist/info-tip.d.ts +3 -1
  32. package/dist/info-tip.js +4 -1
  33. package/dist/internal/form-control.d.ts +6 -0
  34. package/dist/internal/form-control.js +6 -0
  35. package/dist/internal/kanban-layout.js +2 -1
  36. package/dist/internal/listbox-navigation.d.ts +8 -8
  37. package/dist/internal/listbox-navigation.js +23 -23
  38. package/dist/internal/overlay-styles.d.ts +5 -0
  39. package/dist/internal/overlay-styles.js +5 -0
  40. package/dist/internal/styles.d.ts +5 -0
  41. package/dist/internal/styles.js +5 -0
  42. package/dist/kanban.js +1 -1
  43. package/dist/picker-shell.d.ts +3 -1
  44. package/dist/picker-shell.js +3 -3
  45. package/dist/popover.js +4 -4
  46. package/dist/search-picker.js +4 -8
  47. package/dist/select.js +3 -3
  48. package/dist/toggle-group.d.ts +1 -1
  49. package/dist/toggle-group.js +36 -2
  50. package/package.json +1 -1
  51. package/skills/atlas-react-kit/SKILL.md +1 -1
@@ -64,6 +64,8 @@ export type PickerTriggerProps = {
64
64
  "aria-labelledby"?: string;
65
65
  /** Forwarded to the trigger, e.g. the id of a hint or error text. */
66
66
  "aria-describedby"?: string;
67
+ /** Forwarded to the trigger; a form field sets it for `focusFirstInvalid`. */
68
+ "data-field-name"?: string;
67
69
  /** Popover side. Defaults to `bottom`; Radix still flips on collision. */
68
70
  side?: React.ComponentProps<typeof PopoverContent>["side"];
69
71
  /** Month shown when the popover opens; falls back to the selected date. */
@@ -112,5 +114,5 @@ type PickerShellProps = Omit<PickerTriggerProps, "placeholder"> & {
112
114
  * Form-control trigger plus the viewport-clamped popover holding the
113
115
  * calendar, any extra rows, and an optional Clear row.
114
116
  */
115
- export declare function PickerShell({ id, disabled, className, contentClassName, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, side, defaultMonth, minDate, maxDate, calendarProps, empty, label, dialogLabel, open, onOpenChange, calendar, onClear, clearDisabled, children, }: PickerShellProps): React.JSX.Element;
117
+ export declare function PickerShell({ id, disabled, className, contentClassName, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "data-field-name": fieldName, side, defaultMonth, minDate, maxDate, calendarProps, empty, label, dialogLabel, open, onOpenChange, calendar, onClear, clearDisabled, children, }: PickerShellProps): React.JSX.Element;
116
118
  export {};
@@ -4,7 +4,7 @@ import * as React from "react";
4
4
  import { CalendarIcon } from "lucide-react";
5
5
  import { Button } from "./button.js";
6
6
  import { toDate, } from "./internal/date-like.js";
7
- import { PICKER_COLLISION_PADDING, pickerContentClassName, pickerTriggerClassName, pickerValueId, } from "./internal/form-control.js";
7
+ import { fieldNameProps, PICKER_COLLISION_PADDING, pickerContentClassName, pickerTriggerClassName, pickerValueId, } from "./internal/form-control.js";
8
8
  import { LazyCalendar, preloadCalendar } from "./lazy-calendar.js";
9
9
  import { Popover, PopoverContent, PopoverTrigger } from "./popover.js";
10
10
  import { cn } from "./utils.js";
@@ -39,8 +39,8 @@ function limitCalendarProps(calendarProps, minDate, maxDate) {
39
39
  * Form-control trigger plus the viewport-clamped popover holding the
40
40
  * calendar, any extra rows, and an optional Clear row.
41
41
  */
42
- export function PickerShell({ id, disabled, className, contentClassName, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, side, defaultMonth, minDate, maxDate, calendarProps, empty, label, dialogLabel, open, onOpenChange, calendar, onClear, clearDisabled = false, children, }) {
43
- return (_jsxs(Popover, { open: open, onOpenChange: onOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { id: id, type: "button", variant: "outline", disabled: disabled, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "data-empty": empty, className: cn(pickerTriggerClassName, className), onPointerEnter: preloadCalendar, onFocus: preloadCalendar, children: [_jsx(CalendarIcon, { "data-icon": "inline-start" }), _jsx("span", { "data-slot": "date-picker-value", className: "min-w-0 text-left whitespace-normal", id: id ? pickerValueId(id) : undefined, children: label })] }) }), _jsxs(PopoverContent, { align: "start", side: side, collisionPadding: PICKER_COLLISION_PADDING, "aria-label": dialogLabel,
42
+ export function PickerShell({ id, disabled, className, contentClassName, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "data-field-name": fieldName, side, defaultMonth, minDate, maxDate, calendarProps, empty, label, dialogLabel, open, onOpenChange, calendar, onClear, clearDisabled = false, children, }) {
43
+ return (_jsxs(Popover, { open: open, onOpenChange: onOpenChange, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { id: id, type: "button", variant: "outline", disabled: disabled, "aria-invalid": ariaInvalid, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, ...fieldNameProps(fieldName), "data-empty": empty, className: cn(pickerTriggerClassName, className), onPointerEnter: preloadCalendar, onFocus: preloadCalendar, children: [_jsx(CalendarIcon, { "data-icon": "inline-start" }), _jsx("span", { "data-slot": "date-picker-value", className: "min-w-0 text-left whitespace-normal", id: id ? pickerValueId(id) : undefined, children: label })] }) }), _jsxs(PopoverContent, { align: "start", side: side, collisionPadding: PICKER_COLLISION_PADDING, "aria-label": dialogLabel,
44
44
  // The calendar's `autoFocus` puts focus on the selected day (or
45
45
  // today) once it loads, as the APG date picker dialog does; Radix
46
46
  // focusing the popover first would leave it on the container.
package/dist/popover.js CHANGED
@@ -2,8 +2,8 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { Popover as PopoverPrimitive } from "radix-ui";
5
- import { OVERLAY_COLLISION_PADDING, OVERLAY_SIDE_OFFSET, overlayFadeZoom, overlaySideSlide, overlaySurface, } from "./internal/overlay-styles.js";
6
- import { labelText } from "./internal/styles.js";
5
+ import { anchoredPanel, OVERLAY_COLLISION_PADDING, OVERLAY_SIDE_OFFSET, } from "./internal/overlay-styles.js";
6
+ import { descriptionText, labelText } from "./internal/styles.js";
7
7
  import { cn } from "./utils.js";
8
8
  function Popover({ ...props }) {
9
9
  return _jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
@@ -12,7 +12,7 @@ function PopoverTrigger({ ...props }) {
12
12
  return _jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
13
13
  }
14
14
  function PopoverContent({ className, align = "center", sideOffset = OVERLAY_SIDE_OFFSET, collisionPadding = OVERLAY_COLLISION_PADDING, ...props }) {
15
- return (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { "data-slot": "popover-content", align: align, sideOffset: sideOffset, collisionPadding: collisionPadding, className: cn(overlaySurface, overlaySideSlide, overlayFadeZoom, "z-50 flex max-w-(--radix-popover-content-available-width) origin-(--radix-popover-content-transform-origin) flex-col gap-4 p-4 text-sm outline-hidden", className), ...props }) }));
15
+ return (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { "data-slot": "popover-content", align: align, sideOffset: sideOffset, collisionPadding: collisionPadding, className: cn(anchoredPanel, "z-50 flex max-w-(--radix-popover-content-available-width) origin-(--radix-popover-content-transform-origin) flex-col gap-4 p-4 text-sm outline-hidden", className), ...props }) }));
16
16
  }
17
17
  function PopoverAnchor({ ...props }) {
18
18
  return _jsx(PopoverPrimitive.Anchor, { "data-slot": "popover-anchor", ...props });
@@ -24,6 +24,6 @@ function PopoverTitle({ className, ...props }) {
24
24
  return (_jsx("h2", { "data-slot": "popover-title", className: cn(labelText, className), ...props }));
25
25
  }
26
26
  function PopoverDescription({ className, ...props }) {
27
- return (_jsx("p", { "data-slot": "popover-description", className: cn("mt-0.5 text-sm leading-relaxed text-muted-foreground", className), ...props }));
27
+ return (_jsx("p", { "data-slot": "popover-description", className: cn("mt-0.5", descriptionText, className), ...props }));
28
28
  }
29
29
  export { Popover, PopoverAnchor, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, };
@@ -6,7 +6,7 @@ import { Label } from "./label.js";
6
6
  import { handleListboxKey } from "./internal/listbox-navigation.js";
7
7
  import { Listbox, ListboxEmptyStatus, listboxInputAria, PickerOption, } from "./internal/listbox-option.js";
8
8
  import { createSearchIndex, filterSearchIndex, foldSearchText, normalizeSearchQuery, } from "./internal/search.js";
9
- import { cn } from "./utils.js";
9
+ import { cn, onInputChange } from "./utils.js";
10
10
  export { foldSearchText };
11
11
  /**
12
12
  * Default SearchPicker filter: the folded label includes the folded query.
@@ -63,14 +63,10 @@ function SearchPicker({ items, getValue, getLabel, filter = defaultSearchFilter,
63
63
  }, [onSelect]);
64
64
  const onKeyDown = (event) => {
65
65
  const handled = handleListboxKey(event, {
66
+ items: filtered,
66
67
  highlight,
67
- length: filtered.length,
68
68
  setHighlight,
69
- onEnter: (index) => {
70
- const item = filtered[index];
71
- if (item)
72
- selectItem(item);
73
- },
69
+ onPick: selectItem,
74
70
  });
75
71
  if (handled || event.key !== "Escape")
76
72
  return;
@@ -81,6 +77,6 @@ function SearchPicker({ items, getValue, getLabel, filter = defaultSearchFilter,
81
77
  }
82
78
  event.currentTarget.blur();
83
79
  };
84
- return (_jsxs("div", { "data-slot": "search-picker", className: cn("flex flex-col gap-1.5", className), ...props, children: [_jsx(Label, { htmlFor: inputId, children: label }), _jsx(Input, { id: inputId, role: "combobox", "aria-expanded": true, "aria-controls": listId, ...listboxInputAria(listId, active ? highlight : undefined), value: query, disabled: disabled, placeholder: placeholder, onChange: (event) => setQuery(event.target.value), onKeyDown: onKeyDown }), _jsx(Listbox, { id: listId, empty: empty, "aria-label": listLabel ?? label, className: cn(listFrame, listClassName), children: rows.map(({ item, value: itemValue }, index) => (_jsx(PickerOption, { "data-slot": "search-picker-option", listId: listId, index: index, active: index === highlight, selected: itemValue === value, disabled: disabled, item: item, getLabel: getLabel, onHighlight: setHighlight, onSelect: selectItem }, itemValue))) }), _jsx(ListboxEmptyStatus, { "data-slot": "search-picker-empty", empty: empty, className: listFrame, children: emptyText })] }));
80
+ return (_jsxs("div", { "data-slot": "search-picker", className: cn("flex flex-col gap-1.5", className), ...props, children: [_jsx(Label, { htmlFor: inputId, children: label }), _jsx(Input, { id: inputId, role: "combobox", "aria-expanded": true, "aria-controls": listId, ...listboxInputAria(listId, active ? highlight : undefined), value: query, disabled: disabled, placeholder: placeholder, onChange: onInputChange(setQuery), onKeyDown: onKeyDown }), _jsx(Listbox, { id: listId, empty: empty, "aria-label": listLabel ?? label, className: cn(listFrame, listClassName), children: rows.map(({ item, value: itemValue }, index) => (_jsx(PickerOption, { "data-slot": "search-picker-option", listId: listId, index: index, active: index === highlight, selected: itemValue === value, disabled: disabled, item: item, getLabel: getLabel, onHighlight: setHighlight, onSelect: selectItem }, itemValue))) }), _jsx(ListboxEmptyStatus, { "data-slot": "search-picker-empty", empty: empty, className: listFrame, children: emptyText })] }));
85
81
  }
86
82
  export { SearchPicker };
package/dist/select.js CHANGED
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { Select as SelectPrimitive } from "radix-ui";
5
5
  import { dataDisabledState, disabledState, emptyValueText, fieldSurface, focusRing, inlineIcon, invalidState, optionState, } from "./internal/styles.js";
6
- import { menuLabel, optionRow, OVERLAY_COLLISION_PADDING, OVERLAY_SIDE_OFFSET, overlayFadeZoom, overlaySideSlide, overlaySurface, } from "./internal/overlay-styles.js";
6
+ import { anchoredPanel, menuLabel, optionRow, OVERLAY_COLLISION_PADDING, OVERLAY_SIDE_OFFSET, } from "./internal/overlay-styles.js";
7
7
  import { cn } from "./utils.js";
8
8
  import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react";
9
9
  /**
@@ -22,10 +22,10 @@ function SelectValue({ ...props }) {
22
22
  return _jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
23
23
  }
24
24
  function SelectTrigger({ className, size = "default", children, ...props }) {
25
- return (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, className: cn(fieldSurface, focusRing, invalidState, disabledState, emptyValueText, emptyValueText, inlineIcon.default, triggerHeight[size], "flex items-center justify-between gap-1.5 whitespace-nowrap *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5", className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { "data-slot": "select-icon", asChild: true, children: _jsx(ChevronDownIcon, { className: "pointer-events-none size-3.5 text-muted-foreground" }) })] }));
25
+ return (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, className: cn(fieldSurface, focusRing, invalidState, disabledState, emptyValueText, inlineIcon.default, triggerHeight[size], "flex items-center justify-between gap-1.5 whitespace-nowrap *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5", className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { "data-slot": "select-icon", asChild: true, children: _jsx(ChevronDownIcon, { className: "pointer-events-none size-3.5 text-muted-foreground" }) })] }));
26
26
  }
27
27
  function SelectContent({ className, children, position = "popper", align = "center", sideOffset = OVERLAY_SIDE_OFFSET, collisionPadding = OVERLAY_COLLISION_PADDING, ...props }) {
28
- return (_jsx(SelectPrimitive.Portal, { children: _jsxs(SelectPrimitive.Content, { "data-slot": "select-content", "data-align-trigger": position === "item-aligned", className: cn(overlaySurface, overlaySideSlide, overlayFadeZoom, "relative z-50 max-h-(--radix-select-content-available-height) min-w-(--radix-select-trigger-width) origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto data-[align-trigger=true]:animate-none", position === "popper" &&
28
+ return (_jsx(SelectPrimitive.Portal, { children: _jsxs(SelectPrimitive.Content, { "data-slot": "select-content", "data-align-trigger": position === "item-aligned", className: cn(anchoredPanel, "relative z-50 max-h-(--radix-select-content-available-height) min-w-(--radix-select-trigger-width) origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto data-[align-trigger=true]:animate-none", position === "popper" &&
29
29
  "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className), position: position, align: align, sideOffset: sideOffset, collisionPadding: collisionPadding, ...props, children: [_jsx(SelectScrollUpButton, {}), _jsx(SelectPrimitive.Viewport, { "data-slot": "select-viewport", "data-position": position, className: "data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)", children: children }), _jsx(SelectScrollDownButton, {})] }) }));
30
30
  }
31
31
  function SelectLabel({ className, ...props }) {
@@ -12,6 +12,6 @@ type ToggleGroupLayoutProps = {
12
12
  /** Lay items out in a row or a column. Default `horizontal`. */
13
13
  orientation?: "horizontal" | "vertical";
14
14
  };
15
- declare function ToggleGroup({ className, variant, size, spacing, orientation, children, ...props }: React.ComponentProps<typeof ToggleGroupPrimitive.Root> & VariantProps<typeof toggleVariants> & ToggleGroupLayoutProps): React.JSX.Element;
15
+ declare function ToggleGroup({ className, variant, size, spacing, orientation, children, onKeyDown, onPointerDown, onFocus, ...props }: React.ComponentProps<typeof ToggleGroupPrimitive.Root> & VariantProps<typeof toggleVariants> & ToggleGroupLayoutProps): React.JSX.Element;
16
16
  declare function ToggleGroupItem({ className, children, variant, size, ...props }: React.ComponentProps<typeof ToggleGroupPrimitive.Item> & VariantProps<typeof toggleVariants>): React.JSX.Element;
17
17
  export { ToggleGroup, ToggleGroupItem };
@@ -5,15 +5,49 @@ import {} from "class-variance-authority";
5
5
  import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui";
6
6
  import { cn } from "./utils.js";
7
7
  import { toggleVariants } from "./toggle.js";
8
+ /** The keys Radix's roving focus moves between items with. */
9
+ const arrowKeys = new Set(["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"]);
10
+ function isItem(target) {
11
+ return (target instanceof HTMLElement && target.dataset.slot === "toggle-group-item");
12
+ }
8
13
  const ToggleGroupContext = React.createContext({
9
14
  size: "default",
10
15
  variant: "default",
11
16
  spacing: 2,
12
17
  orientation: "horizontal",
13
18
  });
14
- function ToggleGroup({ className, variant, size, spacing = 2, orientation = "horizontal", children, ...props }) {
19
+ function ToggleGroup({ className, variant, size, spacing = 2, orientation = "horizontal", children, onKeyDown, onPointerDown, onFocus, ...props }) {
20
+ // The item an arrow key was pressed on, until focus lands on the next one.
21
+ // A single group's items are radios, and focus that arrives by arrow key
22
+ // selects, as in any radio group; Tab and clicks do not.
23
+ const arrowFrom = React.useRef(null);
24
+ const selectsOnArrow = props.type === "single" && props.rovingFocus !== false;
15
25
  const context = React.useMemo(() => ({ variant, size, spacing, orientation }), [variant, size, spacing, orientation]);
16
- return (_jsx(ToggleGroupPrimitive.Root, { "data-slot": "toggle-group", "data-variant": variant, "data-size": size, "data-spacing": spacing, "data-orientation": orientation, style: { "--gap": spacing }, className: cn("group/toggle-group flex w-fit max-w-full flex-row flex-wrap items-center gap-[--spacing(var(--gap))] data-[spacing=0]:data-[variant=outline]:rounded-none data-vertical:flex-col data-vertical:flex-nowrap data-vertical:items-stretch", className), ...props, children: _jsx(ToggleGroupContext.Provider, { value: context, children: children }) }));
26
+ return (_jsx(ToggleGroupPrimitive.Root, { "data-slot": "toggle-group", "data-variant": variant, "data-size": size, "data-spacing": spacing, "data-orientation": orientation, onKeyDown: (event) => {
27
+ onKeyDown?.(event);
28
+ // Radix moves focus to the next item once the key has bubbled up.
29
+ if (selectsOnArrow &&
30
+ arrowKeys.has(event.key) &&
31
+ isItem(event.target) &&
32
+ !(event.metaKey || event.ctrlKey || event.altKey || event.shiftKey)) {
33
+ arrowFrom.current = event.target;
34
+ }
35
+ }, onPointerDown: (event) => {
36
+ onPointerDown?.(event);
37
+ arrowFrom.current = null;
38
+ }, onFocus: (event) => {
39
+ onFocus?.(event);
40
+ const from = arrowFrom.current;
41
+ arrowFrom.current = null;
42
+ const item = event.target;
43
+ // Clicking runs the selection Radix already owns, onValueChange included.
44
+ if (from &&
45
+ from !== item &&
46
+ isItem(item) &&
47
+ item.getAttribute("aria-checked") !== "true") {
48
+ item.click();
49
+ }
50
+ }, style: { "--gap": spacing }, className: cn("group/toggle-group flex w-fit max-w-full flex-row flex-wrap items-center gap-[--spacing(var(--gap))] data-[spacing=0]:data-[variant=outline]:rounded-none data-vertical:flex-col data-vertical:flex-nowrap data-vertical:items-stretch", className), ...props, children: _jsx(ToggleGroupContext.Provider, { value: context, children: children }) }));
17
51
  }
18
52
  function ToggleGroupItem({ className, children, variant = "default", size = "default", ...props }) {
19
53
  const context = React.useContext(ToggleGroupContext);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atlas-react-kit",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Shared React components and Tailwind theme for Atlas",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -61,7 +61,7 @@ Import each component from its subpath, e.g.
61
61
  | Checkbox, checkbox group, toggle group, combobox in a form | `FormCheckboxField`, `FormCheckboxGroupField`, `FormToggleGroupField`, `FormComboboxField` from `form/*` |
62
62
  | Custom control the kit has no form field for | `FormControlField` from `form/control-field` |
63
63
  | Form-level error (save failed) | `FormFeedbackField` from `form/feedback-field` |
64
- | Focus the first invalid field when a submit fails | `focusFirstInvalid` from `form/focus-first-invalid` |
64
+ | Focus the first invalid field when a submit fails | `focusFirstInvalid` from `form/focus-first-invalid`; fields without a `field` prop take `fieldName={field.name}` |
65
65
  | Content panels on one page | `Tabs` from `tabs` |
66
66
  | View switch that changes the URL | `TabsNav` and `TabsNavLink` from `tabs`; in Next, `next/tabs-nav-link` |
67
67
  | App shell nav (Calendar, Tasks, Settings) | `NavLink` from `nav-link`; in Next, `next/nav-link` |