diff --git a/packages/atomic-elements/src/components/Dropdowns/ListBox/ListBox.component.tsx b/packages/atomic-elements/src/components/Dropdowns/ListBox/ListBox.component.tsx
index 2c373304..bc527929 100644
--- a/packages/atomic-elements/src/components/Dropdowns/ListBox/ListBox.component.tsx
+++ b/packages/atomic-elements/src/components/Dropdowns/ListBox/ListBox.component.tsx
@@ -17,7 +17,7 @@ import { Label } from "@components/Fields";
import { Divider } from "@components/Layout/Divider";
import { Provider } from "@components/Internal/Provider";
import { ItemContext, ItemProps, SectionContext } from "@components/Collection";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { List, ListItem, SectionTitle, SubList } from "./ListBox.styles";
import { ListBoxProps } from "./ListBox.types";
@@ -35,7 +35,7 @@ export const ListBox = forwardRef(function ListBox
(
ref: React.Ref
) {
const state = useContext(ListStateContext);
- [props, ref] = useContextPropsV2(ListBoxContext, props, ref);
+ [props, ref] = useContextProps(ListBoxContext, props, ref);
// When used within a SelectField or similar component,
// the state will be provided by the parent component
diff --git a/packages/atomic-elements/src/components/Dropdowns/Menu/Menu.component.tsx b/packages/atomic-elements/src/components/Dropdowns/Menu/Menu.component.tsx
index 054992b4..8362a5b1 100644
--- a/packages/atomic-elements/src/components/Dropdowns/Menu/Menu.component.tsx
+++ b/packages/atomic-elements/src/components/Dropdowns/Menu/Menu.component.tsx
@@ -24,7 +24,7 @@ import { Provider } from "@components/Internal/Provider";
import { useCollectionRenderer } from "@hooks/useCollectionRenderer";
import { useRenderProps } from "@hooks";
import { useFocusRing } from "@hooks/useFocusRing";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { ItemContext, ItemProps, SectionContext } from "@components/Collection";
import { MenuContext, MenuStateContext } from "./Menu.context";
@@ -58,7 +58,7 @@ export const Menu = forwardRef(function Menu(
props: MenuProps,
ref: React.Ref
) {
- [props, ref] = useContextPropsV2(MenuContext, props, ref);
+ [props, ref] = useContextProps(MenuContext, props, ref);
return (
}>
diff --git a/packages/atomic-elements/src/components/Dropdowns/Menu/MenuTrigger.tsx b/packages/atomic-elements/src/components/Dropdowns/Menu/MenuTrigger.tsx
index d80df8c0..294fa6f1 100644
--- a/packages/atomic-elements/src/components/Dropdowns/Menu/MenuTrigger.tsx
+++ b/packages/atomic-elements/src/components/Dropdowns/Menu/MenuTrigger.tsx
@@ -7,7 +7,7 @@ import {
} from "react-stately";
import { HasChildren } from "../../../types";
import { Provider } from "../../Internal/Provider";
-import { PopoverContext } from "../../Overlays/Popover/context";
+import { PopoverContext } from "../../Overlays/Popover/Popover.context";
import { MenuContext } from "./Menu.context";
import { OverlayTriggerStateContext } from "../../Overlays/OverlayTrigger/context";
diff --git a/packages/atomic-elements/src/components/Fields/Atoms/ErrorMessage/ErrorMessage.component.tsx b/packages/atomic-elements/src/components/Fields/Atoms/ErrorMessage/ErrorMessage.component.tsx
index 45f92454..2084d12a 100644
--- a/packages/atomic-elements/src/components/Fields/Atoms/ErrorMessage/ErrorMessage.component.tsx
+++ b/packages/atomic-elements/src/components/Fields/Atoms/ErrorMessage/ErrorMessage.component.tsx
@@ -2,7 +2,7 @@ import React from "react";
import styled from "styled-components";
import mixins from "../../../../styles/mixins";
import { ElementWrapperProps } from "../../../../types";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { useRenderProps } from "@hooks";
import { ErrorMessageContext } from "./ErrorMessage.context";
@@ -25,7 +25,7 @@ export const ErrorMessage = React.forwardRef(function ErrorMessage(
props: ErrorMessageProps,
ref: React.Ref
) {
- [props, ref] = useContextPropsV2(ErrorMessageContext, props, ref);
+ [props, ref] = useContextProps(ErrorMessageContext, props, ref);
const { className, size = "medium", as = "p", isInvalid, ...rest } = props;
const renderProps = useRenderProps({
diff --git a/packages/atomic-elements/src/components/Fields/Atoms/ErrorMessage/ErrorMessage.context.ts b/packages/atomic-elements/src/components/Fields/Atoms/ErrorMessage/ErrorMessage.context.ts
index 3502f7bd..1d62605c 100644
--- a/packages/atomic-elements/src/components/Fields/Atoms/ErrorMessage/ErrorMessage.context.ts
+++ b/packages/atomic-elements/src/components/Fields/Atoms/ErrorMessage/ErrorMessage.context.ts
@@ -1,6 +1,4 @@
import { createComponentContext } from "@utils/index";
import { ErrorMessageProps } from "./ErrorMessage.component";
-export const ErrorMessageContext = createComponentContext(
- {} as any
-);
+export const ErrorMessageContext = createComponentContext();
diff --git a/packages/atomic-elements/src/components/Fields/Atoms/Input/Input.component.tsx b/packages/atomic-elements/src/components/Fields/Atoms/Input/Input.component.tsx
index ec0bd7eb..192a7cf4 100644
--- a/packages/atomic-elements/src/components/Fields/Atoms/Input/Input.component.tsx
+++ b/packages/atomic-elements/src/components/Fields/Atoms/Input/Input.component.tsx
@@ -2,7 +2,7 @@ import React, { forwardRef } from "react";
import styled from "styled-components";
import mixins from "../../../../styles/mixins";
import { ElementWrapperProps } from "../../../../types";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { useRenderProps } from "@hooks";
import { InputContext } from "./Input.context";
import { SlotProps } from "@hooks/useSlottedContext";
@@ -25,7 +25,7 @@ export const Input = forwardRef(function Input(
props: InputProps,
ref: React.Ref
) {
- [props, ref] = useContextPropsV2(InputContext, props, ref);
+ [props, ref] = useContextProps(InputContext, props, ref);
const { className, size, style, ...rest } = props;
diff --git a/packages/atomic-elements/src/components/Fields/Atoms/Label/Label.component.tsx b/packages/atomic-elements/src/components/Fields/Atoms/Label/Label.component.tsx
index 6975e3ce..3503d557 100644
--- a/packages/atomic-elements/src/components/Fields/Atoms/Label/Label.component.tsx
+++ b/packages/atomic-elements/src/components/Fields/Atoms/Label/Label.component.tsx
@@ -2,7 +2,7 @@ import React from "react";
import styled from "styled-components";
import mixins from "../../../../styles/mixins";
import { ElementWrapperProps } from "../../../../types";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { LabelContext } from "./Label.context";
import { useRenderProps } from "@hooks";
@@ -28,7 +28,7 @@ export const Label = React.forwardRef(function Label(
props: LabelProps,
ref: React.Ref
) {
- [props, ref] = useContextPropsV2(LabelContext, props, ref);
+ [props, ref] = useContextProps(LabelContext, props, ref);
const { className, size, as = "label", ...rest } = props;
diff --git a/packages/atomic-elements/src/components/Fields/Atoms/Message/Message.component.tsx b/packages/atomic-elements/src/components/Fields/Atoms/Message/Message.component.tsx
index 20da9f37..3f324e00 100644
--- a/packages/atomic-elements/src/components/Fields/Atoms/Message/Message.component.tsx
+++ b/packages/atomic-elements/src/components/Fields/Atoms/Message/Message.component.tsx
@@ -2,7 +2,7 @@ import React from "react";
import styled from "styled-components";
import mixins from "../../../../styles/mixins";
import { ElementWrapperProps } from "../../../../types";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { useRenderProps } from "@hooks";
import { MessageContext } from "./Message.context";
@@ -24,7 +24,7 @@ export const Message = React.forwardRef(function Message(
props: MessageProps,
ref: React.Ref
) {
- [props, ref] = useContextPropsV2(MessageContext, props, ref);
+ [props, ref] = useContextProps(MessageContext, props, ref);
const { as, className, size = "auto", ...rest } = props;
const renderProps = useRenderProps({
diff --git a/packages/atomic-elements/src/components/Fields/Atoms/Message/Message.context.ts b/packages/atomic-elements/src/components/Fields/Atoms/Message/Message.context.ts
index e5dfc1e0..cd21091b 100644
--- a/packages/atomic-elements/src/components/Fields/Atoms/Message/Message.context.ts
+++ b/packages/atomic-elements/src/components/Fields/Atoms/Message/Message.context.ts
@@ -1,4 +1,4 @@
import { createComponentContext } from "@utils/index";
import { MessageProps } from "./Message.component";
-export const MessageContext = createComponentContext({});
+export const MessageContext = createComponentContext();
diff --git a/packages/atomic-elements/src/components/Fields/Atoms/TextArea/TextArea.component.tsx b/packages/atomic-elements/src/components/Fields/Atoms/TextArea/TextArea.component.tsx
index 54c06010..343710a8 100644
--- a/packages/atomic-elements/src/components/Fields/Atoms/TextArea/TextArea.component.tsx
+++ b/packages/atomic-elements/src/components/Fields/Atoms/TextArea/TextArea.component.tsx
@@ -1,7 +1,7 @@
import React, { forwardRef } from "react";
import { ElementWrapperProps } from "../../../../types";
import { StyledTextArea } from "./TextArea.styles";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { useRenderProps } from "@hooks";
import { filterDOMProps } from "@react-aria/utils";
import { TextAreaContext } from "./TextArea.context";
@@ -16,7 +16,7 @@ export const TextArea = forwardRef(function TextArea(
props: TextAreaProps,
ref: React.Ref
) {
- [props, ref] = useContextPropsV2(TextAreaContext, props, ref);
+ [props, ref] = useContextProps(TextAreaContext, props, ref);
const { className, size, style, ...rest } = props;
diff --git a/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.component.tsx b/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.component.tsx
new file mode 100644
index 00000000..7944943c
--- /dev/null
+++ b/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.component.tsx
@@ -0,0 +1,185 @@
+import React, {
+ DOMAttributes,
+ forwardRef,
+ RefAttributes,
+ useContext,
+} from "react";
+import { useTagGroup } from "@react-aria/tag";
+import { useListState } from "react-stately";
+import {
+ BaseCollection,
+ Collection,
+ CollectionBuilder,
+} from "@react-aria/collections";
+import {
+ CollectionBase,
+ FocusableElement,
+ Key,
+ MultipleSelection,
+ SelectionBehavior,
+} from "@react-types/shared";
+
+import {
+ FieldErrorContext,
+ FieldLabelContext,
+ FieldMessageContext,
+ FieldProps,
+} from "@components/Fields";
+import { useRenderProps } from "@hooks";
+import { useContextProps } from "@hooks/useContextProps";
+import { Provider } from "@components/Internal/Provider";
+import { useCollectionRenderer } from "@hooks/useCollectionRenderer";
+
+import { ChipsWrapper, ChipGroupWrapper } from "./ChipGroupField.styles";
+import {
+ ChipGroupFieldContext,
+ ChipGroupListContext,
+ ChipGroupStateContext,
+} from "./ChipGroupField.context";
+import {
+ AriaLabelProps,
+ DomProps,
+ ExtendedSize,
+ FieldStatusProps,
+ RenderStyleProps,
+} from "../../../types";
+import { ItemContext } from "@components/Collection";
+import { ChipLeaf } from "@components/Chips/Chip";
+
+export interface ChipGroupFieldProps
+ extends MultipleSelection,
+ RenderStyleProps,
+ DomProps,
+ AriaLabelProps,
+ Omit {
+ children: React.ReactNode;
+ /** Handler called when a user deletes a chip */
+ onRemove?: (removed: Set) => void;
+ /** How multiple selection should behave in the collection. */
+ selectionBehavior?: SelectionBehavior;
+ /** Size of the chip group */
+ size?: ExtendedSize;
+}
+
+interface ForwardedChipGroupField {
+ (props: ChipGroupFieldProps & RefAttributes): JSX.Element;
+ displayName: string;
+
+ /** The list of chips within a ChipGroupField */
+ List: typeof ChipGroupFieldList;
+}
+
+/** Building blocks for constructing a ChipGroup field. */
+export const ChipGroupField = forwardRef(function ChipGroupField<
+ T extends object
+>(props: ChipGroupFieldProps, ref: React.ForwardedRef) {
+ [props, ref] = useContextProps(ChipGroupFieldContext, props, ref);
+
+ return (
+
+ {(collection: BaseCollection) => (
+
+ )}
+
+ );
+}) as unknown as ForwardedChipGroupField;
+
+ChipGroupField.displayName = "ChipFieldGroup";
+
+interface ChipGroupFieldInnerProps
+ extends ChipGroupFieldProps {
+ collection: BaseCollection;
+ chipGroupRef: React.RefObject;
+}
+
+function ChipGroupFieldInner(
+ props: ChipGroupFieldInnerProps
+) {
+ const { isInvalid, isDisabled, isRequired, chipGroupRef } = props;
+
+ const state = useListState({
+ ...props,
+ children: undefined,
+ });
+
+ const { gridProps, labelProps, descriptionProps, errorMessageProps } =
+ useTagGroup({ ...props, label: true }, state, chipGroupRef);
+
+ const renderProps = useRenderProps({
+ componentClassName: "aje-chip-group",
+ ...props,
+ selectors: {
+ "data-disabled": isDisabled,
+ "data-invalid": isInvalid,
+ "data-required": isRequired,
+ },
+ });
+
+ return (
+
+
+ {renderProps.children}
+
+
+ );
+}
+
+export interface ChipGroupFieldListProps
+ extends CollectionBase,
+ Omit, "children"> {
+ beforeChildren?: React.ReactNode;
+}
+
+interface ForwardedChipGroupFieldList {
+ (
+ props: ChipGroupFieldListProps & RefAttributes
+ ): JSX.Element;
+ displayName: string;
+}
+
+const ChipGroupFieldList = forwardRef(function ChipGroupFieldList<
+ T extends object
+>(props: ChipGroupFieldListProps, ref: React.ForwardedRef) {
+ [props, ref] = useContextProps(ChipGroupListContext, props, ref);
+ const state = useContext(ChipGroupStateContext);
+
+ // We're building the collection in the ChipGroupField component
+ if (!state) return ;
+
+ // We're rendering a built collection
+ return ;
+}) as ForwardedChipGroupFieldList;
+
+ChipGroupFieldList.displayName = "ChipGroupField.List";
+ChipGroupField.List = ChipGroupFieldList;
+
+const ChipGroupFieldListInner = forwardRef(function ChipGroupFieldListInner(
+ props: ChipGroupFieldListProps,
+ ref: React.ForwardedRef
+) {
+ const { items, children, beforeChildren, ...rest } = props;
+ const state = useContext(ChipGroupStateContext)!;
+ const { CollectionRenderer } = useCollectionRenderer();
+
+ return (
+
+ {beforeChildren}
+ }
+ />
+
+ );
+});
diff --git a/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.context.ts b/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.context.ts
new file mode 100644
index 00000000..58193fb0
--- /dev/null
+++ b/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.context.ts
@@ -0,0 +1,15 @@
+import { ListState } from "react-stately";
+import { createComponentContext } from "@utils/index";
+import {
+ ChipGroupFieldListProps,
+ ChipGroupFieldProps,
+} from "./ChipGroupField.component";
+import { createContext } from "react";
+
+export const ChipGroupFieldContext =
+ createComponentContext();
+
+export const ChipGroupStateContext = createContext | null>(null);
+
+export const ChipGroupListContext =
+ createComponentContext>();
diff --git a/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.spec.tsx b/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.spec.tsx
new file mode 100644
index 00000000..1067f6e8
--- /dev/null
+++ b/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.spec.tsx
@@ -0,0 +1,118 @@
+import { describe, test, expect, vi } from "vitest";
+import { fireEvent, render, screen } from "@testing-library/react";
+import { ChipGroupField } from ".";
+import { Chip } from "@components/Chips/Chip";
+import { Label } from "../Atoms/Label";
+
+describe("ChipGroupField", () => {
+ const chips = [
+ { id: "1", rendered: "Chip 1" },
+ { id: "2", rendered: "Chip 2" },
+ { id: "3", rendered: "Chip 3" },
+ ];
+
+ test("matches snapshot", () => {
+ const result = render(
+
+
+ Item 1
+ Item 2
+ Item 3
+
+
+ );
+ expect(result.asFragment()).toMatchSnapshot();
+ });
+
+ test("renders label", () => {
+ render(
+
+
+
+ Item 1
+ Item 2
+ Item 3
+
+
+ );
+
+ expect(screen.getByText("My Chip Group")).not.toBeNull();
+ });
+
+ test("renders chips", () => {
+ render(
+
+
+ {({ rendered }) => {rendered}}
+
+
+ );
+
+ chips.forEach((chip) => {
+ expect(screen.getByText(chip.rendered)).not.toBeNull();
+ });
+ });
+
+ test("onRemove", () => {
+ const onRemove = vi.fn();
+
+ render(
+
+
+ {({ rendered }) => {rendered}}
+
+
+ );
+
+ const buttons = screen.getAllByRole("button");
+ expect(buttons.length).toEqual(3);
+ const button = buttons[0];
+ fireEvent.click(button);
+
+ expect(onRemove).toHaveBeenCalledOnce();
+ expect(onRemove).toHaveBeenCalledWith(new Set(["1"]));
+ });
+
+ test("selection", () => {
+ const onSelectionChange = vi.fn();
+
+ render(
+
+
+ {({ rendered }) => {rendered}}
+
+
+ );
+
+ const rows = screen.getAllByRole("row");
+
+ rows.forEach((row, index) => {
+ fireEvent.focus(row);
+ fireEvent.keyDown(row, { key: "Enter", code: "Enter", charCode: 13 });
+ expect(onSelectionChange).toHaveBeenCalledTimes(index + 1);
+ });
+ });
+
+ test("disabledKeys", () => {
+ render(
+
+
+ {({ rendered }) => {rendered}}
+
+
+ );
+
+ const rows = screen.getAllByRole("row");
+
+ rows.forEach((row, index) => {
+ if (index > 3) {
+ expect(row.dataset["aria-disabled"]).toEqual("true");
+ } else {
+ expect(row.dataset["aria-disabled"]).toBeUndefined();
+ }
+ });
+ });
+});
diff --git a/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.stories.tsx b/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.stories.tsx
new file mode 100644
index 00000000..12344d23
--- /dev/null
+++ b/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.stories.tsx
@@ -0,0 +1,27 @@
+import { Meta, StoryObj } from "@storybook/react";
+import { ChipGroupField } from ".";
+import { Label } from "../Atoms/Label";
+import { Chip } from "@components/Chips/Chip";
+
+export default {
+ title: "Fields/ChipGroupField",
+ component: ChipGroupField,
+ parameters: {
+ layout: "centered",
+ },
+} as Meta;
+
+type Story = StoryObj;
+
+export const Primary: Story = {
+ args: {
+ children: [
+ ,
+
+ Chip 1
+ Chip 2
+ Chip 3
+ ,
+ ],
+ },
+};
diff --git a/packages/atomic-elements/src/components/Chips/ChipGroup/ChipGroup.styles.ts b/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.styles.ts
similarity index 78%
rename from packages/atomic-elements/src/components/Chips/ChipGroup/ChipGroup.styles.ts
rename to packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.styles.ts
index ec5ce386..f653ff58 100644
--- a/packages/atomic-elements/src/components/Chips/ChipGroup/ChipGroup.styles.ts
+++ b/packages/atomic-elements/src/components/Fields/ChipGroupField/ChipGroupField.styles.ts
@@ -1,8 +1,7 @@
import styled from "styled-components";
import mixins from "../../../styles/mixins";
-import { FieldWrapper } from "../../Internal/FieldWrapper";
-export const ChipGroupWrapper = styled(FieldWrapper)`
+export const ChipGroupWrapper = styled.div`
${mixins.FieldStatus}
${mixins.SizingX}
diff --git a/packages/atomic-elements/src/components/Fields/ChipGroupField/__snapshots__/ChipGroupField.spec.tsx.snap b/packages/atomic-elements/src/components/Fields/ChipGroupField/__snapshots__/ChipGroupField.spec.tsx.snap
new file mode 100644
index 00000000..e26d2426
--- /dev/null
+++ b/packages/atomic-elements/src/components/Fields/ChipGroupField/__snapshots__/ChipGroupField.spec.tsx.snap
@@ -0,0 +1,69 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`ChipGroupField > matches snapshot 1`] = `
+
+
+
+`;
diff --git a/packages/atomic-elements/src/components/Fields/ChipGroupField/index.ts b/packages/atomic-elements/src/components/Fields/ChipGroupField/index.ts
new file mode 100644
index 00000000..b022ea3c
--- /dev/null
+++ b/packages/atomic-elements/src/components/Fields/ChipGroupField/index.ts
@@ -0,0 +1,3 @@
+export { ChipGroupField } from "./ChipGroupField.component";
+export * from "./ChipGroupField.context";
+export type { ChipGroupFieldProps } from "./ChipGroupField.component";
diff --git a/packages/atomic-elements/src/components/Fields/ComboBoxField/ComboBoxField.component.tsx b/packages/atomic-elements/src/components/Fields/ComboBoxField/ComboBoxField.component.tsx
index 1970362f..23fb4820 100644
--- a/packages/atomic-elements/src/components/Fields/ComboBoxField/ComboBoxField.component.tsx
+++ b/packages/atomic-elements/src/components/Fields/ComboBoxField/ComboBoxField.component.tsx
@@ -1,5 +1,5 @@
import React, { forwardRef, useRef } from "react";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { PressResponder } from "@react-aria/interactions";
import { CollectionBuilder } from "@react-aria/collections";
import { useComboBoxState } from "react-stately";
@@ -9,7 +9,7 @@ import { Provider } from "@components/Internal/Provider";
import { useFilter } from "@react-aria/i18n";
import { OverlayTriggerStateContext } from "@components/Overlays/OverlayTrigger/context";
-import { PopoverContext } from "@components/Overlays/Popover/context";
+import { PopoverContext } from "@components/Overlays/Popover/Popover.context";
import {
ListBoxContext,
ListStateContext,
@@ -34,9 +34,9 @@ import { ComboInputContext } from "../ComboInput";
import { ComboBoxFieldWrapper } from "./ComboBoxField.styles";
export const ComboBoxField = forwardRef(function ComboBoxField<
- T extends object,
+ T extends object
>(props: ComboBoxFieldProps, ref: React.Ref) {
- [props, ref] = useContextPropsV2(ComboBoxFieldContext, props, ref);
+ [props, ref] = useContextProps(ComboBoxFieldContext, props, ref);
return (
diff --git a/packages/atomic-elements/src/components/Fields/ComboInput/ComboInput.component.tsx b/packages/atomic-elements/src/components/Fields/ComboInput/ComboInput.component.tsx
index 5404f483..33ccf2f1 100644
--- a/packages/atomic-elements/src/components/Fields/ComboInput/ComboInput.component.tsx
+++ b/packages/atomic-elements/src/components/Fields/ComboInput/ComboInput.component.tsx
@@ -2,7 +2,7 @@ import React from "react";
import classNames from "classnames";
import { ComboInputProps } from "./ComboInput.types";
import { StyledComboInput } from "./ComboInput.styles";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { ComboInputContext } from "./ComboInput.context";
/**
@@ -15,7 +15,7 @@ export const ComboInput = React.forwardRef(function ComboInput(
props: ComboInputProps,
ref: React.Ref
) {
- [props, ref] = useContextPropsV2(ComboInputContext, props, ref);
+ [props, ref] = useContextProps(ComboInputContext, props, ref);
const { className, padding = [], children, inputRef, ...rest } = props;
diff --git a/packages/atomic-elements/src/components/Fields/MultiSelectField/MultiSelectField.component.tsx b/packages/atomic-elements/src/components/Fields/MultiSelectField/MultiSelectField.component.tsx
index 91f90bbd..972120a1 100644
--- a/packages/atomic-elements/src/components/Fields/MultiSelectField/MultiSelectField.component.tsx
+++ b/packages/atomic-elements/src/components/Fields/MultiSelectField/MultiSelectField.component.tsx
@@ -4,10 +4,10 @@ import { PressResponder } from "@react-aria/interactions";
import { ListBoxContext, ListStateContext } from "../../Dropdowns/ListBox";
import { OverlayTriggerStateContext } from "@components/Overlays/OverlayTrigger/context";
import { useRenderProps } from "@hooks/useRenderProps";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { BaseCollection, CollectionBuilder } from "@react-aria/collections";
import { Provider } from "@components/Internal/Provider";
-import { PopoverContext } from "@components/Overlays/Popover/context";
+import { PopoverContext } from "@components/Overlays/Popover/Popover.context";
import { ButtonContext } from "@components/Buttons/Button/Button.context";
import { DropdownButton } from "@components/Internal/DropdownButton";
import {
@@ -38,7 +38,7 @@ export interface MultiSelectFieldComponent
export const MultiSelectField = forwardRef(function MultiSelectField<
T extends object
>(props: MultiSelectFieldProps, ref: React.Ref) {
- [props, ref] = useContextPropsV2(MultiSelectFieldContext, props, ref);
+ [props, ref] = useContextProps(MultiSelectFieldContext, props, ref);
return (
diff --git a/packages/atomic-elements/src/components/Fields/SelectField/SelectField.component.tsx b/packages/atomic-elements/src/components/Fields/SelectField/SelectField.component.tsx
index 53c6505f..3d5779a8 100644
--- a/packages/atomic-elements/src/components/Fields/SelectField/SelectField.component.tsx
+++ b/packages/atomic-elements/src/components/Fields/SelectField/SelectField.component.tsx
@@ -11,14 +11,14 @@ import {
} from "@components/Dropdowns/ListBox";
import { OverlayTriggerStateContext } from "../../Overlays/OverlayTrigger/context";
import { useRenderProps } from "@hooks/useRenderProps";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { Provider } from "@components/Internal/Provider";
import {
FieldErrorContext,
FieldLabelContext,
FieldMessageContext,
} from "@components/Fields";
-import { PopoverContext } from "@components/Overlays/Popover/context";
+import { PopoverContext } from "@components/Overlays/Popover/Popover.context";
import { ButtonContext } from "@components/Buttons/Button/Button.context";
import { ButtonText, SelectFieldWrapper } from "./SelectField.styles";
@@ -51,7 +51,7 @@ export const SelectField = forwardRef(function SelectField(
props: SelectFieldProps,
ref: React.Ref
) {
- [props, ref] = useContextPropsV2(SelectFieldContext, props, ref);
+ [props, ref] = useContextProps(SelectFieldContext, props, ref);
return (
diff --git a/packages/atomic-elements/src/components/Format/FormatTable/FormatTable.component.tsx b/packages/atomic-elements/src/components/Format/FormatTable/FormatTable.component.tsx
index 8988a68a..3d7c7f7e 100644
--- a/packages/atomic-elements/src/components/Format/FormatTable/FormatTable.component.tsx
+++ b/packages/atomic-elements/src/components/Format/FormatTable/FormatTable.component.tsx
@@ -20,8 +20,10 @@ export function FormatTable(props: FormatTableProps) {
{(item) => (
-
- {(colKey) => {item[colKey]}}
+
+ {(column) => (
+ {item[column.key]}
+ )}
)}
diff --git a/packages/atomic-elements/src/components/Inputs/Checkbox/Checkbox.component.tsx b/packages/atomic-elements/src/components/Inputs/Checkbox/Checkbox.component.tsx
index e38b9ba9..bac5dc24 100644
--- a/packages/atomic-elements/src/components/Inputs/Checkbox/Checkbox.component.tsx
+++ b/packages/atomic-elements/src/components/Inputs/Checkbox/Checkbox.component.tsx
@@ -7,7 +7,7 @@ import { AriaProps, FieldInputProps } from "../../../types";
import { ChooseInput, ChooseLabel } from "../Inputs.styles";
import { CheckboxWrapper } from "./Checkbox.styles";
import { ErrorMessage, Message } from "../../Fields";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { CheckBoxContext } from "./Checkbox.context";
import { SlotProps } from "@hooks/useSlottedContext";
@@ -19,7 +19,7 @@ export interface CheckBoxProps
/** Checkbox Component. Accepts a `ref` */
export const CheckBox = React.forwardRef(
(props, ref) => {
- [props, ref] = useContextPropsV2(CheckBoxContext, props, ref);
+ [props, ref] = useContextProps(CheckBoxContext, props, ref);
const {
children,
diff --git a/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.component.tsx b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.component.tsx
index 7d86a849..9de19c2b 100644
--- a/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.component.tsx
+++ b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.component.tsx
@@ -1,42 +1,37 @@
import { useRef } from "react";
-import classNames from "classnames";
import {
useCalendar,
- AriaCalendarGridProps,
AriaCalendarProps,
DateValue,
- useCalendarGrid,
- useCalendarCell,
} from "@react-aria/calendar";
import { useLocale } from "@react-aria/i18n";
-import {
- getWeeksInMonth,
- CalendarDate,
- createCalendar,
- today,
- getLocalTimeZone,
-} from "@internationalized/date";
-import { CalendarState, useCalendarState } from "react-stately";
+import { createCalendar } from "@internationalized/date";
+import { useCalendarState } from "react-stately";
+
+import { AriaProps, ExtendedSize, RenderBaseProps } from "../../../../types";
+import { useRenderProps } from "@hooks";
+import { Provider } from "@components/Internal/Provider";
+import { ButtonContext } from "@components/Buttons/Button/Button.context";
+import { DEFAULT_SLOT } from "@hooks/useSlottedContext";
+import { useContextProps } from "@hooks/useContextProps";
+import { ErrorMessageContext } from "@components/Fields/Atoms/ErrorMessage";
-import { IconButton } from "../../../Buttons/IconButton";
-import { Button } from "../../../Buttons/Button";
-import { AriaProps, BaseProps, Size } from "../../../../types";
+import { CalendarTitle } from "./components/CalendarTitle";
+import { CalendarGrid } from "./components/CalendarGrid";
+import { CalendarCell } from "./components/CalendarCell";
+import { CalendarWrapper } from "./Calendar.styles";
import {
- CalendarContent,
- StyledCalendarCell,
- CalendarFooter,
- CalendarHeader,
- CalendarWrapper,
- CalendarCellButton,
- CalendarWeekDay,
- CalendarHeaderButtons,
- CalendarHeaderTitle,
-} from "./Calendar.styles";
+ CalendarContext,
+ CalendarStateContext,
+ CalendarTitleContext,
+} from "./Calendar.context";
export interface CalendarProps
extends AriaProps>,
- BaseProps {
- size?: Size;
+ RenderBaseProps {
+ size?: ExtendedSize;
+ isDisabled?: boolean;
+ isInvalid?: boolean;
}
/**
@@ -50,9 +45,20 @@ export interface CalendarProps
* import { parseDate } from "@internationalized/date";
*
* const [date, setDate] = useState(parseDate("2021-01-01"));
- *
+ *
+ *
+ *
+ *
+ * {(date) => }
+ *
+ *
*/
export function Calendar(props: CalendarProps) {
+ let ref = useRef(null);
+ // TS is getting confused because react-aria uses some conditional types that
+ // it doesn't understand how to resolve when using useContextProps
+ [props, ref] = useContextProps(CalendarContext as any, props, ref);
+
const { size = "medium" } = props;
const { locale } = useLocale();
const state = useCalendarState({
@@ -61,130 +67,55 @@ export function Calendar(props: CalendarProps) {
createCalendar,
});
- const { calendarProps, prevButtonProps, nextButtonProps, title } =
- useCalendar(props, state);
-
- const className = classNames("aje-calendar", `is-${size}`);
-
- return (
-
-
- {title}
-
-
-
-
-
-
-
- {/* TODO: useCalendar doesn't appear to have the ability to set the value
- to null, check if there's a way to do this? */}
- {/* */}
-
-
-
- );
-}
-
-interface CalendarGridProps extends AriaCalendarGridProps {
- state: CalendarState;
-}
-
-function CalendarGrid(props: CalendarGridProps) {
- const { state, ...rest } = props;
- const { locale } = useLocale();
- const { gridProps, headerProps, weekDays } = useCalendarGrid(rest, state);
-
- // Get the number of weeks in the month so we can render the proper number of rows.
- const weeksInMonth = getWeeksInMonth(state.visibleRange.start, locale);
-
- return (
-
-
-
- {weekDays.map((day, index) => (
- {day}
- ))}
-
-
-
- {[...new Array(weeksInMonth).keys()].map((weekIndex) => (
-
- {state
- .getDatesInWeek(weekIndex)
- .map((date, i) =>
- date ? (
-
- ) : (
- |
- )
- )}
-
- ))}
-
-
- );
-}
-
-interface CalendarCellProps {
- state: CalendarState;
- date: CalendarDate;
-}
-
-function CalendarCell(props: CalendarCellProps) {
- const { state, date } = props;
- const ref = useRef(null);
const {
- cellProps,
- buttonProps,
- isSelected,
- isOutsideVisibleRange,
- isDisabled,
- isUnavailable,
- formattedDate,
- } = useCalendarCell({ date }, state, ref);
+ calendarProps,
+ prevButtonProps,
+ nextButtonProps,
+ title,
+ errorMessageProps,
+ } = useCalendar(props, state);
- const cellClassName = classNames("aje-calendar__cell", {
- "is-selected": isSelected,
- "is-disabled": isDisabled,
- "is-unavailable": isUnavailable,
+ const renderProps = useRenderProps({
+ componentClassName: "aje-calendar",
+ ...props,
+ size,
+ selectors: {
+ "data-disabled": props.isDisabled,
+ "data-invalid": props.isInvalid,
+ },
});
return (
-
-
+
- {formattedDate}
-
-
+ {renderProps.children}
+
+
);
}
-export default Calendar;
+/** The current Month & Year formatted & localized */
+Calendar.Title = CalendarTitle;
+/** The grid of days in the calendar */
+Calendar.Grid = CalendarGrid;
+/** A cell in the calendar grid */
+Calendar.Cell = CalendarCell;
diff --git a/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.context.ts b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.context.ts
new file mode 100644
index 00000000..75633317
--- /dev/null
+++ b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.context.ts
@@ -0,0 +1,13 @@
+import { createContext } from "react";
+import { CalendarState } from "react-stately";
+
+import { createComponentContext } from "@utils/index";
+import { CalendarProps } from "./Calendar.component";
+
+export const CalendarContext = createComponentContext>();
+
+export const CalendarStateContext = createContext(null);
+
+export const CalendarTitleContext = createContext<{ title: string } | null>(
+ null
+);
diff --git a/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.stories.tsx b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.stories.tsx
index 49287ef0..084870af 100644
--- a/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.stories.tsx
+++ b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.stories.tsx
@@ -1,6 +1,10 @@
import { Meta, StoryObj } from "@storybook/react";
import { today, getLocalTimeZone } from "@internationalized/date";
import { Calendar } from ".";
+import { IconButton } from "@components/Buttons/IconButton";
+import { Flex } from "@components/Layout/Flex/Flex";
+import { FieldStateControls, RenderPropsArgTypes } from "@sb/helpers";
+import { ErrorMessage } from "@components/Fields";
const meta: Meta = {
title: "Inputs/Date & Time/Calendar",
@@ -9,25 +13,32 @@ const meta: Meta = {
layout: "centered",
},
argTypes: {
+ ...RenderPropsArgTypes,
+ children: {
+ control: false,
+ table: {
+ disable: true,
+ },
+ },
value: {
control: false,
description:
- "The current value of the input. Accepts a object from the `@internationalized/date` library.",
+ "The current value of the calendar. Accepts a object from the `@internationalized/date` library.",
},
defaultValue: {
control: false,
description:
- "Set the initial value of an uncontrolled input. Accepts a object from the `@internationalized/date` library.",
+ "Set the initial value of an uncontrolled calendar. Accepts a object from the `@internationalized/date` library.",
},
defaultFocusedValue: {
control: false,
description:
- "Set the initial focused value of an uncontrolled input. Accepts a object from the `@internationalized/date` library.",
+ "Set the initial focused value of an uncontrolled calendar. Accepts a object from the `@internationalized/date` library.",
},
focusedValue: {
control: false,
description:
- "The current focused value of the input. Accepts a object from the `@internationalized/date` library.",
+ "The current focused value of the calendary. Accepts a object from the `@internationalized/date` library.",
},
isDateUnavailable: {
control: false,
@@ -44,9 +55,27 @@ const meta: Meta = {
description:
"The minimum date that can be selected. Accepts a object from the `@internationalized/date` library.",
},
+ isDisabled: {
+ control: "boolean",
+ description: "Whether the calendar is disabled.",
+ },
+ isInvalid: {
+ control: "boolean",
+ description: "Whether the calendar is in an invalid state.",
+ },
onFocusChange: {
control: false,
description: "Callback for when the focus date changes.",
+ table: {
+ category: "Events",
+ },
+ },
+ onChange: {
+ control: false,
+ description: "Callback for when the selected date changes.",
+ table: {
+ category: "Events",
+ },
},
},
};
@@ -55,24 +84,53 @@ export default meta;
type Story = StoryObj;
-export const Primary: Story = {
- args: {
- size: "medium",
- },
-};
-
const date = today(getLocalTimeZone());
const minValue = date.set({ month: date.month - 1 });
const maxValue = date.set({ month: date.month + 1 });
-export const WithDefaultValue: Story = {
+export const Primary: Story = {
args: {
- ...Primary.args,
+ size: "medium",
defaultValue: date,
+ children: [
+
+
+
+
+ ,
+
+ {(date) => }
+ ,
+ ],
+ },
+ parameters: {
+ docs: {
+ source: {
+ language: "jsx",
+ code: `
+
+
+
+
+
+
+
+ {(date) => }
+
+
+ `,
+ },
+ },
},
};
export const WithMaxAndMinValues: Story = {
+ ...Primary,
args: {
...Primary.args,
defaultValue: date,
@@ -80,3 +138,47 @@ export const WithMaxAndMinValues: Story = {
maxValue,
},
};
+
+export const WithErrorMessage: Story = {
+ ...Primary,
+ args: {
+ ...Primary.args,
+ isInvalid: true,
+ children: [
+
+
+
+
+ ,
+
+ {(date) => }
+ ,
+ The Selected Date is Invalid,
+ ],
+ },
+ parameters: {
+ docs: {
+ source: {
+ language: "jsx",
+ code: `
+
+
+
+
+
+
+
+ {(date) => }
+
+ The Selected Date is Invalid,
+
+ `,
+ },
+ },
+ },
+};
diff --git a/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.styles.ts b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.styles.ts
index 56ff6ee2..78230f45 100644
--- a/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.styles.ts
+++ b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/Calendar.styles.ts
@@ -43,47 +43,16 @@ export const CalendarWrapper = styled.div`
}
`;
-export const CalendarHeader = styled.div`
- display: grid;
- grid-template-columns: 1.1fr 1fr;
- margin: 0 15px;
- margin-bottom: 5px;
-`;
-
export const CalendarHeaderTitle = styled.h2`
${mixins.Bold}
font-size: var(--font-size);
color: var(--neutral600);
`;
-export const CalendarHeaderButtons = styled.div`
- display: flex;
- align-items: center;
- justify-content: space-between;
-`;
-
export const CalendarContent = styled.table`
height: var(--calendar-content-height);
min-width: var(--calendar-content-height);
-`;
-
-export const CalendarFooter = styled.div`
- display: flex;
- align-items: center;
- justify-content: flex-end;
- margin-top: auto;
-
- .aje-btn--calendar-footer {
- border: none;
- background-color: transparent;
- color: var(--primary600);
- padding: 5px;
-
- &:hover {
- cursor: pointer;
- color: var(--primary800);
- }
- }
+ margin: auto;
`;
export const CalendarWeekDay = styled.th`
@@ -101,18 +70,24 @@ export const StyledCalendarCell = styled.td`
color: var(--text-clr);
height: var(--calendar-cell-size);
- &.is-selected {
- background-color: var(--time-selected-back-clr);
- color: var(--time-selected-text-clr);
+ &[aria-selected="true"] {
+ background-color: var(--calendar-selected-bg-clr);
+ color: var(--calendar-selected-text-clr);
border-radius: 3px;
&:hover {
- background-color: var(--time-selected-back-clr);
+ background-color: var(--calendar-selected-bg-clr);
}
}
&[aria-invalid="true"] {
- background-color: var(--error500);
+ background-color: var(--error-clr);
+
+ &:hover {
+ cursor: pointer;
+ border-radius: 3px;
+ background-color: var(--error-clr);
+ }
}
&:hover {
@@ -121,7 +96,7 @@ export const StyledCalendarCell = styled.td`
background-color: var(--neutral200);
}
- &.is-disabled {
+ &[data-disabled] {
color: var(--neutral400);
&:hover {
@@ -129,32 +104,6 @@ export const StyledCalendarCell = styled.td`
background-color: transparent;
}
}
-
- /*
-
- &.in-interval {
- border-radius: 0px;
- background-color: var(--neutral200);
- }
-
- &.in-potential-interval {
- border-top: 1px dashed var(--neutral400);
- border-bottom: 1px dashed var(--neutral400);
- }
-
- &.neighboring-month {
- color: var(--neutral400);
- }
-
- &.interval-start {
- background-color: var(--primary700);
- border-radius: 5px 0px 0px 5px;
- }
-
- &.interval-end {
- background-color: var(--primary700);
- border-radius: 0px 5px 5px 0px;
- } */
`;
export const CalendarCellButton = styled.div`
@@ -163,10 +112,4 @@ export const CalendarCellButton = styled.div`
display: flex;
justify-content: center;
align-items: center;
-
- &[hidden] {
- visibility: hidden;
- display: auto;
- pointer-events: none;
- }
`;
diff --git a/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/components/CalendarCell.tsx b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/components/CalendarCell.tsx
new file mode 100644
index 00000000..a7183427
--- /dev/null
+++ b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/components/CalendarCell.tsx
@@ -0,0 +1,61 @@
+import { CalendarDate } from "@internationalized/date";
+import { useContext, useRef } from "react";
+import { CalendarStateContext } from "../Calendar.context";
+import { useCalendarCell } from "@react-aria/calendar";
+import { CalendarCellButton, StyledCalendarCell } from "../Calendar.styles";
+import { useRenderProps } from "@hooks";
+import { RenderBaseProps } from "../../../../../types";
+
+interface CalendarCellRenderProps {
+ focusedDate: CalendarDate;
+ isDisabled: boolean;
+ isSelected: boolean;
+ formattedDate: string;
+}
+
+interface CalendarCellProps extends RenderBaseProps {
+ date: CalendarDate;
+ isDisabled?: boolean;
+}
+
+export function CalendarCell(props: CalendarCellProps) {
+ const state = useContext(CalendarStateContext)!;
+ const ref = useRef(null);
+
+ const {
+ cellProps,
+ buttonProps,
+ isSelected,
+ isOutsideVisibleRange,
+ isDisabled,
+ isUnavailable,
+ formattedDate,
+ } = useCalendarCell(props, state, ref);
+
+ const renderProps = useRenderProps({
+ componentClassName: "aje-calendar__cell",
+ ...props,
+ values: {
+ focusedDate: state.focusedDate,
+ formattedDate,
+ isDisabled,
+ isSelected,
+ },
+ selectors: {
+ "data-disabled": isDisabled,
+ "data-unavailable": isUnavailable,
+ },
+ });
+
+ return (
+
+
+ {formattedDate}
+
+
+ );
+}
diff --git a/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/components/CalendarGrid.tsx b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/components/CalendarGrid.tsx
new file mode 100644
index 00000000..e7ab03a7
--- /dev/null
+++ b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/components/CalendarGrid.tsx
@@ -0,0 +1,51 @@
+import React, { useContext } from "react";
+import { AriaCalendarGridProps, useCalendarGrid } from "@react-aria/calendar";
+import { CalendarStateContext } from "../Calendar.context";
+import { useLocale } from "@react-aria/i18n";
+import { CalendarDate, getWeeksInMonth } from "@internationalized/date";
+import { CalendarContent, CalendarWeekDay } from "../Calendar.styles";
+import { RenderStyleProps } from "../../../../../types";
+
+interface CalendarGridProps
+ extends AriaCalendarGridProps,
+ RenderStyleProps {
+ children: (date: CalendarDate) => React.ReactNode;
+}
+
+export function CalendarGrid(props: CalendarGridProps) {
+ const state = useContext(CalendarStateContext)!;
+ const { locale } = useLocale();
+ const { gridProps, headerProps, weekDays } = useCalendarGrid(props, state);
+
+ // Get the number of weeks in the month so we can render the proper number of rows.
+ const weeksInMonth = getWeeksInMonth(state.visibleRange.start, locale);
+
+ return (
+
+
+
+ {weekDays.map((day, index) => (
+ {day}
+ ))}
+
+
+
+ {[...new Array(weeksInMonth).keys()].map((weekIndex) => (
+
+ {state
+ .getDatesInWeek(weekIndex)
+ .map((date, i) =>
+ date ? (
+
+ {props.children(date)}
+
+ ) : (
+ |
+ )
+ )}
+
+ ))}
+
+
+ );
+}
diff --git a/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/components/CalendarTitle.tsx b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/components/CalendarTitle.tsx
new file mode 100644
index 00000000..b0b0334c
--- /dev/null
+++ b/packages/atomic-elements/src/components/Inputs/DateAndTimes/Calendar/components/CalendarTitle.tsx
@@ -0,0 +1,42 @@
+import { useContext } from "react";
+import { RenderBaseProps } from "../../../../../types";
+import { useRenderProps } from "@hooks";
+
+import {
+ CalendarStateContext,
+ CalendarTitleContext,
+} from "../Calendar.context";
+import { CalendarHeaderTitle } from "../Calendar.styles";
+import { CalendarDate } from "@internationalized/date";
+
+interface CalendarTitleRenderProps {
+ focusedDate: CalendarDate;
+ isDisabled: boolean;
+ isFocused: boolean;
+ title: string;
+}
+
+interface CalendarTitleProps
+ extends RenderBaseProps {}
+
+export function CalendarTitle(props: CalendarTitleProps) {
+ const state = useContext(CalendarStateContext)!;
+ const { title } = useContext(CalendarTitleContext)!;
+
+ const renderProps = useRenderProps({
+ componentClassName: "aje-calendar__title",
+ values: {
+ focusedDate: state.focusedDate,
+ isDisabled: state.isDisabled,
+ isFocused: state.isFocused,
+ title: title,
+ },
+ ...props,
+ });
+
+ return (
+
+ {props.children ? renderProps.children : title}
+
+ );
+}
diff --git a/packages/atomic-elements/src/components/Inputs/DateAndTimes/DatePicker/DatePicker.component.tsx b/packages/atomic-elements/src/components/Inputs/DateAndTimes/DatePicker/DatePicker.component.tsx
index 002b4343..625778ca 100644
--- a/packages/atomic-elements/src/components/Inputs/DateAndTimes/DatePicker/DatePicker.component.tsx
+++ b/packages/atomic-elements/src/components/Inputs/DateAndTimes/DatePicker/DatePicker.component.tsx
@@ -5,21 +5,21 @@ import {
DateValue,
} from "@react-aria/datepicker";
import { useDatePickerState } from "react-stately";
-import { Size, AriaProps, FieldInputProps } from "../../../../types";
+import { AriaProps, FieldInputProps } from "../../../../types";
import { DatePickerComboInput, DatePickerWrapper } from "./DatePicker.styles";
-import classNames from "classnames";
import { DateInput } from "../DateInput";
import { IconButton } from "../../../Buttons/IconButton";
import { Popover } from "../../../Overlays/Popover";
-import { Dialog } from "../../../Overlays/Dialog";
import { Calendar } from "../Calendar";
import { ErrorMessage, Label, Message } from "../../../Fields";
import { OverlayTriggerStateContext } from "@components/Overlays/OverlayTrigger/context";
+import { useRenderProps } from "@hooks";
+import { Flex } from "@components/Layout/Flex/Flex";
+import { filterDOMProps } from "@react-aria/utils";
-export type DatePickerProps = AriaProps<
- AriaDatePickerProps
-> &
- FieldInputProps;
+export interface DatePickerProps
+ extends AriaProps>,
+ FieldInputProps {}
/** DatePicker is a combination of a `` component and a dropdown `` component. */
export function DatePicker(props: DatePickerProps) {
@@ -30,7 +30,6 @@ export function DatePicker(props: DatePickerProps) {
labelProps,
fieldProps,
buttonProps,
- dialogProps,
calendarProps,
errorMessageProps,
descriptionProps,
@@ -39,28 +38,21 @@ export function DatePicker(props: DatePickerProps) {
const {
size = "medium",
error,
- className,
- isDisabled,
isRequired,
- isReadOnly,
isInvalid,
label,
message,
} = props;
- const calendarSize: Size = ["auto", "full"].includes(size)
- ? "medium"
- : (size as Size);
+ const calendarSize = ["auto", "full"].includes(size) ? "medium" : size;
+
+ const renderProps = useRenderProps({
+ componentClassName: "aje-date-picker",
+ ...props,
+ });
return (
-
+
{label && }
{message && {message}}
@@ -68,6 +60,7 @@ export function DatePicker(props: DatePickerProps) {
{...groupProps}
ref={ref}
className={"aje-input__date-segments"}
+ padding={["left", "right"]}
>
@@ -79,9 +72,24 @@ export function DatePicker(props: DatePickerProps) {
-
+
+
+
+
+
+
+
+ {(date) => }
+
+
diff --git a/packages/atomic-elements/src/components/Inputs/DateAndTimes/DatePicker/DatePicker.styles.ts b/packages/atomic-elements/src/components/Inputs/DateAndTimes/DatePicker/DatePicker.styles.ts
index 4cd495b0..1461f145 100644
--- a/packages/atomic-elements/src/components/Inputs/DateAndTimes/DatePicker/DatePicker.styles.ts
+++ b/packages/atomic-elements/src/components/Inputs/DateAndTimes/DatePicker/DatePicker.styles.ts
@@ -1,10 +1,9 @@
import styled from "styled-components";
import mixins from "../../../../styles/mixins";
-import { FieldWrapper } from "../../../Internal/FieldWrapper";
import { ComboInput } from "../../../Fields";
import { StyledComboInput } from "../../../Fields/ComboInput";
-export const DatePickerWrapper = styled(FieldWrapper)`
+export const DatePickerWrapper = styled.div`
${mixins.FieldStatus}
${mixins.SizingX}
diff --git a/packages/atomic-elements/src/components/Inputs/DateAndTimes/TimeInput/TimeInput.component.tsx b/packages/atomic-elements/src/components/Inputs/DateAndTimes/TimeInput/TimeInput.component.tsx
index ffb7bdc5..899809d2 100644
--- a/packages/atomic-elements/src/components/Inputs/DateAndTimes/TimeInput/TimeInput.component.tsx
+++ b/packages/atomic-elements/src/components/Inputs/DateAndTimes/TimeInput/TimeInput.component.tsx
@@ -56,6 +56,7 @@ export function TimeInput(props: TimeInputProps) {
{...fieldProps}
ref={ref}
className={"aje-input__date-segments"}
+ padding={["left", "right"]}
>
{state.segments.map((segment, i) => (
diff --git a/packages/atomic-elements/src/components/Inputs/DateAndTimes/TimeInput/TimeInput.stories.tsx b/packages/atomic-elements/src/components/Inputs/DateAndTimes/TimeInput/TimeInput.stories.tsx
index ed5d1d81..6284156d 100644
--- a/packages/atomic-elements/src/components/Inputs/DateAndTimes/TimeInput/TimeInput.stories.tsx
+++ b/packages/atomic-elements/src/components/Inputs/DateAndTimes/TimeInput/TimeInput.stories.tsx
@@ -52,7 +52,7 @@ const date = now(getLocalTimeZone());
export const Primary: Story = {
args: {
defaultValue: date,
- label: "Date input",
+ label: "Time input",
size: "medium",
hideTimeZone: true,
shouldForceLeadingZeros: false,
diff --git a/packages/atomic-elements/src/components/Layout/Table/components/TableFooter.tsx b/packages/atomic-elements/src/components/Layout/Table/components/TableFooter.tsx
deleted file mode 100644
index cad5f0c1..00000000
--- a/packages/atomic-elements/src/components/Layout/Table/components/TableFooter.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import { TableRowGroup } from "./TableRowGroup";
-import { StyledTableFooter } from "../Table.styles";
-import { TableState, TreeGridState } from "../Table.types";
-import { TableRow } from "./TableRow";
-import { TableCell } from "./TableCell";
-import { useRenderProps } from "@hooks";
-
-interface TableFooterProps {
- state: TableState | TreeGridState;
-}
-
-export function TableFooter(props: TableFooterProps) {
- const { state } = props;
-
- const { collection } = state;
-
- const rows = [...collection.footer!.childNodes];
-
- const renderProps = useRenderProps({
- componentClassName: "aje-table__footer",
- ...collection.body.props,
- });
-
- return (
-
- {rows.map((row) => {
- return (
-
- {[...collection.getChildren!(row.key)].map((cell) => {
- return ;
- })}
-
- );
- })}
-
- );
-}
diff --git a/packages/atomic-elements/src/components/Layout/Tabs/Tabs.component.tsx b/packages/atomic-elements/src/components/Layout/Tabs/Tabs.component.tsx
index 522b5646..8983cb09 100644
--- a/packages/atomic-elements/src/components/Layout/Tabs/Tabs.component.tsx
+++ b/packages/atomic-elements/src/components/Layout/Tabs/Tabs.component.tsx
@@ -15,7 +15,7 @@ import {
} from "@react-aria/collections";
import { useObjectRef } from "@react-aria/utils";
-import { useContextPropsV2 } from "@hooks/useContextProps";
+import { useContextProps } from "@hooks/useContextProps";
import { useRenderProps } from "@hooks";
import { useCollectionRenderer } from "@hooks/useCollectionRenderer";
import { Provider } from "@components/Internal/Provider";
@@ -48,7 +48,7 @@ export const Tabs = forwardRef(function Tabs(
props: TabsProps,
ref: React.ForwardedRef
) {
- [props, ref] = useContextPropsV2(TabsContext, props, ref);
+ [props, ref] = useContextProps(TabsContext, props, ref);
return (
@@ -129,7 +129,7 @@ function Tab(
ref: React.ForwardedRef,
item: Node
) {
- [props, ref] = useContextPropsV2(TabContext, props, ref);
+ [props, ref] = useContextProps(TabContext, props, ref);
const state = useContext(TabsStateContext)!;
const { key } = item;
diff --git a/packages/atomic-elements/src/components/Overlays/ConfirmationModal/ConfirmationModal.component.tsx b/packages/atomic-elements/src/components/Overlays/ConfirmationModal/ConfirmationModal.component.tsx
index 5057af4f..245c0f02 100644
--- a/packages/atomic-elements/src/components/Overlays/ConfirmationModal/ConfirmationModal.component.tsx
+++ b/packages/atomic-elements/src/components/Overlays/ConfirmationModal/ConfirmationModal.component.tsx
@@ -3,8 +3,7 @@ import { Button } from "../../Buttons/Button";
import { Modal, BaseModalProps } from "../Modal";
import { OverlayTriggerStateContext } from "../OverlayTrigger/context";
-export interface ConfirmationModalProps
- extends Omit {
+export interface ConfirmationModalProps extends BaseModalProps {
children: React.ReactNode;
/** Must include a title. Titles are always in Title case. */
title: string;
diff --git a/packages/atomic-elements/src/components/Overlays/ErrorModal/ErrorModal.component.tsx b/packages/atomic-elements/src/components/Overlays/ErrorModal/ErrorModal.component.tsx
index da6fdfe4..2af48a21 100644
--- a/packages/atomic-elements/src/components/Overlays/ErrorModal/ErrorModal.component.tsx
+++ b/packages/atomic-elements/src/components/Overlays/ErrorModal/ErrorModal.component.tsx
@@ -3,7 +3,7 @@ import { Button } from "../../Buttons/Button";
import { MaterialIcon } from "../../Icons/MaterialIcon";
import { Modal, BaseModalProps } from "../Modal";
-export interface ErrorModalProps extends Omit {
+export interface ErrorModalProps extends BaseModalProps {
children: React.ReactNode;
/** Must include a title. Titles are always in Title case. */
title: string;
diff --git a/packages/atomic-elements/src/components/Overlays/Modal/Modal.component.tsx b/packages/atomic-elements/src/components/Overlays/Modal/Modal.component.tsx
index fa83f3bd..a46824bf 100644
--- a/packages/atomic-elements/src/components/Overlays/Modal/Modal.component.tsx
+++ b/packages/atomic-elements/src/components/Overlays/Modal/Modal.component.tsx
@@ -9,8 +9,7 @@ import {
OverlayTriggerState,
useOverlayTriggerState,
} from "react-stately";
-import { useVariantClass } from "../../../hooks/variants";
-import { HasClassName } from "../../../types";
+import { RenderStyleProps } from "../../../types";
import {
ModalBackground,
ModalWrapper,
@@ -23,49 +22,43 @@ import classNames from "classnames";
import { useContextProps } from "../../../hooks/useContextProps";
import { ModalContext } from "./Modal.context";
import { OverlayTriggerStateContext } from "../OverlayTrigger/context";
+import { useRenderProps } from "@hooks";
+import { filterDOMProps } from "@react-aria/utils";
type CloseModal = () => void;
-export interface BaseModalProps extends HasClassName, OverlayTriggerProps {
- id?: string;
- children?: React.ReactNode | ((close: CloseModal) => React.ReactNode);
+export interface BaseModalProps
+ extends RenderStyleProps,
+ OverlayTriggerProps {
+ id?: string;
/** Centers the modal within the viewport */
centered?: boolean;
}
export interface ModalProps extends BaseModalProps {
variant?: string;
+ children?: React.ReactNode | ((close: CloseModal) => React.ReactNode);
}
/**
* Modal Component to render content overlayed on top of the page content.
*/
export function Modal(props: ModalProps) {
- const {
- children,
- centered = false,
- variant = "default",
- className,
- ...rest
- } = useContextProps(ModalContext, props);
+ let ref = useRef(null);
+ [props, ref] = useContextProps(ModalContext, props, ref);
+
+ const { children, centered = false, variant = "default", ...rest } = props;
const contextState = useContext(OverlayTriggerStateContext);
const localState = useOverlayTriggerState(props);
const state = contextState ?? localState;
- const variantClassName = useVariantClass("aje-modal", variant);
-
if (!state.isOpen) {
return null;
}
return (
-
+
{children}
);
@@ -73,13 +66,20 @@ export function Modal(props: ModalProps) {
interface ModalOverlayProps extends BaseModalProps, AriaModalOverlayProps {
state: OverlayTriggerState;
+ children: React.ReactNode | ((close: CloseModal) => React.ReactNode);
+ variant?: string;
}
function ModalOverlay(props: ModalOverlayProps) {
- const { children, state, centered, className } = props;
+ const { children, state, centered } = props;
const ref = useRef(null);
const { modalProps, underlayProps } = useModalOverlay(props, state, ref);
+ const renderProps = useRenderProps({
+ componentClassName: "aje-modal",
+ ...props,
+ });
+
return (
) => e.stopPropagation()}
ref={ref}
id={props.id}
diff --git a/packages/atomic-elements/src/components/Overlays/Modal/Modal.context.ts b/packages/atomic-elements/src/components/Overlays/Modal/Modal.context.ts
index 0a74de63..b750c048 100644
--- a/packages/atomic-elements/src/components/Overlays/Modal/Modal.context.ts
+++ b/packages/atomic-elements/src/components/Overlays/Modal/Modal.context.ts
@@ -1,4 +1,5 @@
import React from "react";
import { ModalProps } from ".";
+import { createComponentContext } from '@utils/index';
-export const ModalContext = React.createContext(null);
+export const ModalContext = createComponentContext();
diff --git a/packages/atomic-elements/src/components/Overlays/OverlayTrigger/OverlayTrigger.component.tsx b/packages/atomic-elements/src/components/Overlays/OverlayTrigger/OverlayTrigger.component.tsx
index ed6f59b3..fa64bfd5 100644
--- a/packages/atomic-elements/src/components/Overlays/OverlayTrigger/OverlayTrigger.component.tsx
+++ b/packages/atomic-elements/src/components/Overlays/OverlayTrigger/OverlayTrigger.component.tsx
@@ -6,7 +6,7 @@ import {
useOverlayTriggerState,
} from "react-stately";
-import { PopoverContext } from "../Popover/context";
+import { PopoverContext } from "../Popover/Popover.context";
import { Provider } from "../../Internal/Provider";
import { HasChildren } from "../../../types";
import { OverlayTriggerStateContext } from "./context";
diff --git a/packages/atomic-elements/src/components/Overlays/Popover/Popover.component.tsx b/packages/atomic-elements/src/components/Overlays/Popover/Popover.component.tsx
index ce957606..7b686620 100644
--- a/packages/atomic-elements/src/components/Overlays/Popover/Popover.component.tsx
+++ b/packages/atomic-elements/src/components/Overlays/Popover/Popover.component.tsx
@@ -10,6 +10,8 @@ import {
OverlayTriggerState,
useOverlayTriggerState,
} from "react-stately";
+import { useIsHidden } from "@react-aria/collections";
+
import { mergeProps } from "@react-aria/utils";
import { RenderBaseProps, HasVariant } from "../../../types";
@@ -18,10 +20,9 @@ import { useContextProps } from "@hooks/useContextProps";
import { useResizeObserver } from "@hooks/useResizeObserver";
import { useForwardedRef } from "@hooks/useForwardedRef";
import { PopoverUnderlay, PopoverContent } from "./Popover.styles";
-import { PopoverContext } from "./context";
+import { PopoverContext } from "./Popover.context";
import { OverlayTriggerStateContext } from "../OverlayTrigger/context";
import { invertPlacementAxis } from "@utils/placement";
-import { useIsHidden } from "@react-aria/collections";
export interface PopoverRenderProps {
/** Width in pixels of the triggering element that opened this popover */
@@ -41,8 +42,9 @@ export interface PopoverProps
/** A popover is an overlay element positioned relative to a target. */
export const Popover = React.forwardRef(
(props: PopoverProps, ref) => {
- const contextProps = useContextProps(PopoverContext, props);
- const { triggerRef, ...rest } = contextProps;
+ [props, ref] = useContextProps(PopoverContext, props, ref);
+
+ const { triggerRef, ...rest } = props;
const contextState = useContext(OverlayTriggerStateContext);
const localState = useOverlayTriggerState(props);
diff --git a/packages/atomic-elements/src/components/Overlays/Popover/Popover.context.ts b/packages/atomic-elements/src/components/Overlays/Popover/Popover.context.ts
new file mode 100644
index 00000000..b14802f7
--- /dev/null
+++ b/packages/atomic-elements/src/components/Overlays/Popover/Popover.context.ts
@@ -0,0 +1,4 @@
+import { PopoverProps } from ".";
+import { createComponentContext } from "@utils/index";
+
+export const PopoverContext = createComponentContext();
diff --git a/packages/atomic-elements/src/components/Overlays/Popover/Popover.styles.ts b/packages/atomic-elements/src/components/Overlays/Popover/Popover.styles.ts
index 482f3d3c..ef0e9d1e 100644
--- a/packages/atomic-elements/src/components/Overlays/Popover/Popover.styles.ts
+++ b/packages/atomic-elements/src/components/Overlays/Popover/Popover.styles.ts
@@ -32,7 +32,7 @@ export const PopoverContent = styled.div<{
}
&.aje-popover--datepicker {
- --popover-min-height: 330px;
+ --popover-min-height: auto;
--popover-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
--popover-radius: 5px;
--popover-border: 1px solid var(--neutral300);
diff --git a/packages/atomic-elements/src/components/Overlays/Popover/context.ts b/packages/atomic-elements/src/components/Overlays/Popover/context.ts
deleted file mode 100644
index 4f790ec6..00000000
--- a/packages/atomic-elements/src/components/Overlays/Popover/context.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import React from "react";
-import { PopoverProps } from ".";
-
-export const PopoverContext = React.createContext(null as any);
diff --git a/packages/atomic-elements/src/components/Overlays/ToolTip/ToolTip.component.tsx b/packages/atomic-elements/src/components/Overlays/ToolTip/ToolTip.component.tsx
index 1f569dee..eacdfc29 100644
--- a/packages/atomic-elements/src/components/Overlays/ToolTip/ToolTip.component.tsx
+++ b/packages/atomic-elements/src/components/Overlays/ToolTip/ToolTip.component.tsx
@@ -1,5 +1,4 @@
import { useContext, useRef } from "react";
-import classNames from "classnames";
import {
Overlay,
useOverlayPosition,
@@ -9,14 +8,8 @@ import {
import { useTooltip } from "@react-aria/tooltip";
import { OverlayTriggerProps } from "react-stately";
import { Transition } from "react-transition-group";
-
import { ToolTipArrow, ToolTipOverlay } from "./ToolTip.styles";
-import {
- HasChildren,
- HasClassName,
- PresentationProps,
- RenderBaseProps,
-} from "../../../types";
+import { RenderBaseProps } from "../../../types";
import { TooltipContext, TooltipStateContext } from "./ToolTip.context";
import { useContextProps } from "../../../hooks/useContextProps";
import { mergeProps } from "@react-aria/utils";
@@ -43,13 +36,11 @@ export interface ToolTipProps
/** A ToolTip component displays a popup with additional information when a user hovers over or focuses on an element. */
export function ToolTip(props: ToolTipProps) {
- const {
- triggerRef,
- transitionDuration = 300,
- ...rest
- } = useContextProps(TooltipContext, props);
+ let ref = useRef(null);
+ [props, ref] = useContextProps(TooltipContext, props, ref);
+ const { triggerRef, transitionDuration = 300, ...rest } = props;
+
const state = useContext(TooltipStateContext);
- const ref = useRef(null);
const { tooltipProps } = useTooltip({ ...rest }, state);
diff --git a/packages/atomic-elements/src/components/Overlays/ToolTip/ToolTip.context.ts b/packages/atomic-elements/src/components/Overlays/ToolTip/ToolTip.context.ts
index 4f5bc8f5..04f4fb24 100644
--- a/packages/atomic-elements/src/components/Overlays/ToolTip/ToolTip.context.ts
+++ b/packages/atomic-elements/src/components/Overlays/ToolTip/ToolTip.context.ts
@@ -1,8 +1,9 @@
import React from "react";
import { TooltipTriggerState } from "react-stately";
import { ToolTipProps } from "./ToolTip.component";
+import { createComponentContext } from "@utils/index";
-export const TooltipContext = React.createContext(null as any);
+export const TooltipContext = createComponentContext();
export const TooltipStateContext = React.createContext(
null as any
diff --git a/packages/atomic-elements/src/components/index.ts b/packages/atomic-elements/src/components/index.ts
index 41d17ae5..fc9dbbd3 100644
--- a/packages/atomic-elements/src/components/index.ts
+++ b/packages/atomic-elements/src/components/index.ts
@@ -93,6 +93,7 @@ export {
export { SelectField } from "./Fields/SelectField";
export { MultiSelectField } from "./Fields/MultiSelectField";
export { ComboBoxField } from "./Fields/ComboBoxField";
+export { ChipGroupField } from "./Fields/ChipGroupField";
export { FormatDate } from "./Format/FormatDate";
export { FormatNumber } from "./Format/FormatNumber";
@@ -125,11 +126,7 @@ export { LiveMessage } from "./Accessibility/LiveMessage";
export type { BannerProps, BannerVariants } from "./Banners/Banner";
export type { ButtonProps } from "./Buttons/Button";
export type { IconButtonProps } from "./Buttons/IconButton";
-export type {
- ButtonGroupProps,
- ButtonGroupChild,
- ButtonGroupChildProps,
-} from "./Buttons/ButtonGroup";
+export type { ButtonGroupProps } from "./Buttons/ButtonGroup";
export type { ComboBoxProps } from "./Dropdowns/Combobox";
export type { CustomSelectProps } from "./Dropdowns/CustomSelect";
export type { SelectProps, SelectValue } from "./Dropdowns/Select";
@@ -179,6 +176,9 @@ export type {
NumberFieldProps,
ComboInputProps,
} from "./Fields";
+export type { SelectFieldProps } from "./Fields/SelectField";
+export type { ComboBoxFieldProps } from "./Fields/ComboBoxField";
+export type { ChipGroupFieldProps } from "./Fields/ChipGroupField";
export type { TableProps } from "./Layout/Table/Table.types";
export type { TabsProps } from "./Layout/Tabs";
export type { CardProps } from "./Layout/Card";
diff --git a/packages/atomic-elements/src/hooks/useContextProps.ts b/packages/atomic-elements/src/hooks/useContextProps.ts
index ac556120..6a658a0b 100644
--- a/packages/atomic-elements/src/hooks/useContextProps.ts
+++ b/packages/atomic-elements/src/hooks/useContextProps.ts
@@ -1,28 +1,21 @@
-import { useContext } from "react";
import { mergeProps, mergeRefs, useObjectRef } from "@react-aria/utils";
-import { SlotProps, SlottedContextValue, useSlottedContext } from './useSlottedContext';
+import {
+ SlotProps,
+ SlottedContextValue,
+ useSlottedContext,
+} from "./useSlottedContext";
type WithRef = T & { ref?: React.Ref };
export type ContextValue = SlottedContextValue>;
-export function useContextProps(
- context: React.Context,
- props: T
-) {
- const contextProps = useContext(context);
-
- return mergeProps(contextProps, props);
-}
-
-
// from: https://github.com/adobe/react-spectrum/blob/c6bd2cb0808838a9f1f850b6c1ffe88465254222/packages/react-aria-components/src/utils.tsx#L180
/** Consume a value from a context & merge it with the provided props */
-export function useContextPropsV2(
+export function useContextProps(
context: React.Context>,
props: T,
ref: React.Ref
): [T, React.RefObject] {
- const ctx = useSlottedContext(context, (props as SlotProps).slot) || {}
+ const ctx = useSlottedContext(context, (props as SlotProps).slot) || {};
const { ref: contextRef, ...contextProps } = ctx as WithRef;
const mergedRef = useObjectRef(mergeRefs(ref, contextRef!));
diff --git a/packages/atomic-elements/src/styles/variables.ts b/packages/atomic-elements/src/styles/variables.ts
index 3c051b5c..50075077 100644
--- a/packages/atomic-elements/src/styles/variables.ts
+++ b/packages/atomic-elements/src/styles/variables.ts
@@ -242,11 +242,16 @@ export const CssVariables = createGlobalStyle`
--choose-label-padding-left: 32px;
--choose-label-height: 24px;
- /* # Calendar */
+ /* # TimePicker */
--time-clr: var(--neutral200);
--time-selected-back-clr: var(--primary600);
--time-selected-text-clr: var(--neutral100);
+ /* # Calendar */
+ --calendar-clr: var(--neutral200);
+ --calendar-selected-bg-clr: var(--accent-clr);
+ --calendar-selected-text-clr: var(--neutral100);
+
/* # Card */
--card-bg-clr: var(--background-clr-alt);
--card-text-clr: var(--text-clr);
diff --git a/playground/src/tabs/Aria.tsx b/playground/src/tabs/Aria.tsx
index 7d77cf09..3d5c27c2 100644
--- a/playground/src/tabs/Aria.tsx
+++ b/playground/src/tabs/Aria.tsx
@@ -1,5 +1,25 @@
import React from "react";
+import {
+ Calendar,
+ Flex,
+ IconButton,
+} from "../../../packages/atomic-elements/src/index";
export default function Aria() {
- return Hi there
;
+ return (
+
+
+
+
+
+
+
+ {(date) => }
+
+
+ );
}