Skip to content

Commit

Permalink
menu radio group progress
Browse files Browse the repository at this point in the history
  • Loading branch information
huntabyte committed May 11, 2024
1 parent 52ebf5a commit 679b154
Show file tree
Hide file tree
Showing 7 changed files with 6,444 additions and 5,154 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"prettier": "^3.2.5",
"prettier-plugin-svelte": "^3.2.2",
"prettier-plugin-tailwindcss": "0.5.13",
"svelte": "5.0.0-next.109",
"svelte": "5.0.0-next.126",
"svelte-eslint-parser": "^0.34.1",
"wrangler": "^3.44.0"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/bits-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"jsdom": "^24.0.0",
"publint": "^0.2.7",
"resize-observer-polyfill": "^1.5.1",
"svelte": "5.0.0-next.109",
"svelte": "5.0.0-next.126",
"svelte-check": "^3.6.9",
"tslib": "^2.6.2",
"typescript": "^5.3.3",
Expand Down
123 changes: 119 additions & 4 deletions packages/bits-ui/src/lib/bits/menu/menu.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ const CONTENT_ATTR = "data-menu-content";
const ITEM_ATTR = "data-menu-item";
const SUB_TRIGGER_ATTR = "data-menu-subtrigger";
const CHECKBOX_ITEM_ATTR = "data-menu-checkbox-item";
const GROUP_ATTR = "data-menu-group";
const LABEL_ATTR = "data-menu-label";
const RADIO_GROUP_ATTR = "data-menu-radio-group";
const RADIO_ITEM_ATTR = "data-menu-radio-item";

const [setMenuRootContext] = createContext<MenuRootState>("Menu.Root");

Expand All @@ -55,6 +59,9 @@ const [setMenuMenuContext, getMenuMenuContext] = createContext<MenuMenuState>(
const [setMenuContentContext, getMenuContentContext] =
createContext<MenuContentState>("Menu.Content");

const [setMenuRadioGroupContext, getMenuRadioGroupContext] =
createContext<MenuRadioGroupState>("Menu.RadioGroup");

export type MenuRootStateProps = ReadableBoxedValues<{
dir: Direction;
}> & {
Expand Down Expand Up @@ -339,6 +346,10 @@ class MenuContentState {
return new MenuCheckboxItemState(props, item);
}

createRadioGroup(props: MenuRadioGroupStateProps) {
return new MenuRadioGroupState(props, this);
}

createSubTrigger(props: MenuItemSharedStateProps) {
const item = new MenuItemSharedState(props, this);
const submenu = getMenuMenuContext();
Expand Down Expand Up @@ -655,6 +666,94 @@ class MenuCheckboxItemState {
);
}

class MenuGroupState {
props = $derived.by(
() =>
({
role: "group",
[GROUP_ATTR]: "",
}) as const
);
}

class MenuLabelState {
props = $derived.by(
() =>
({
[LABEL_ATTR]: "",
}) as const
);
}

type MenuRadioGroupStateProps = WritableBoxedValues<{
value: string;
}>;

class MenuRadioGroupState {
value: MenuRadioGroupStateProps["value"];
#content: MenuContentState;

constructor(props: MenuRadioGroupStateProps, content: MenuContentState) {
this.value = props.value;
this.#content = content;
}

setValue(v: string) {
this.value.value = v;
}

createRadioItem(
props: MenuItemSharedStateProps & MenuItemStateProps & MenuRadioItemStateProps
) {
const item = this.#content.createItem(props);
return new MenuRadioItemState(props, item, this);
}

props = $derived.by(
() =>
({
[RADIO_GROUP_ATTR]: "",
role: "group",
}) as const
);
}

type MenuRadioItemStateProps = ReadableBoxedValues<{
value: string;
}>;

class MenuRadioItemState {
#item: MenuItemState;
#value: MenuRadioItemStateProps["value"];
#group: MenuRadioGroupState;
#isChecked = $derived.by(() => this.#group.value.value === this.#value.value);

constructor(props: MenuRadioItemStateProps, item: MenuItemState, group: MenuRadioGroupState) {
this.#item = item;
this.#group = group;
this.#value = props.value;
}

selectValue() {
this.#group.setValue(this.#value.value);
}

props = $derived.by(
() =>
({
[RADIO_ITEM_ATTR]: "",
...this.#item.props,
role: "menuitemradio",
"aria-checked": getAriaChecked(this.#isChecked),
"data-state": getCheckedState(this.#isChecked),
}) as const
);
}

//
// DROPDOWN MENU TRIGGER
//

type DropdownMenuTriggerStateProps = ReadableBoxedValues<{
id: string;
disabled: boolean;
Expand Down Expand Up @@ -717,6 +816,8 @@ class DropdownMenuTriggerState {
);
}

type MenuItemCombinedProps = MenuItemSharedStateProps & MenuItemStateProps;

//
// CONTEXT METHODS
//
Expand Down Expand Up @@ -745,12 +846,26 @@ export function useMenuContent(props: MenuContentStateProps) {
return setMenuContentContext(getMenuMenuContext().createContent(props));
}

export function useMenuItem(props: MenuItemSharedStateProps & MenuItemStateProps) {
export function useMenuItem(props: MenuItemCombinedProps) {
return getMenuContentContext().createItem(props);
}

export function useMenuCheckboxItem(
props: MenuItemSharedStateProps & MenuItemStateProps & MenuCheckboxItemStateProps
) {
export function useMenuCheckboxItem(props: MenuItemCombinedProps & MenuCheckboxItemStateProps) {
return getMenuContentContext().createCheckboxItem(props);
}

export function useMenuRadioGroup(props: MenuRadioGroupStateProps) {
return setMenuRadioGroupContext(getMenuContentContext().createRadioGroup(props));
}

export function useMenuRadioItem(props: MenuRadioItemStateProps & MenuItemCombinedProps) {
return getMenuRadioGroupContext().createRadioItem(props);
}

export function useMenuGroup() {
return new MenuGroupState();
}

export function useMenuLabel() {
return new MenuLabelState();
}
Loading

0 comments on commit 679b154

Please sign in to comment.