Skip to content

Commit

Permalink
feat: implement controlled popover, add styles for select; move selec…
Browse files Browse the repository at this point in the history
…t from forms to collections
  • Loading branch information
josemarluedke committed Feb 19, 2024
1 parent d1bbcea commit 3749a92
Show file tree
Hide file tree
Showing 11 changed files with 294 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
import Base, { type BaseArgs, type BaseSignature } from './base';
import { action } from '@ember/object';
// import FormSelect, {
import {
type FormSelectArgs,
type Select
} from '@frontile/forms/components/form-select';
import { type FormSelectArgs } from '@frontile/forms/components/form-select';

export interface ChangesetFormFieldsSelectArgs
extends BaseArgs,
FormSelectArgs {
onChange: (selection: unknown, select: Select, event?: Event) => void;
onFocusOut?: (select: Select, event: FocusEvent) => void;
onClose?: (select: Select, e: Event) => boolean | undefined;
onChange: (selection: unknown, select: unknown, event?: Event) => void;
onFocusOut?: (select: unknown, event: FocusEvent) => void;
onClose?: (select: unknown, e: Event) => boolean | undefined;
}

export interface ChangesetFormFieldsSelectSignature extends BaseSignature {
Args: ChangesetFormFieldsSelectArgs;
Blocks: {
default: [option: unknown, select: Select];
default: [option: unknown, select: unknown];
};
Element: HTMLDivElement;
}
Expand All @@ -26,7 +22,7 @@ export default class ChangesetFormFieldsSelect extends Base<ChangesetFormFieldsS
@action
async handleChange(
selection: unknown,
select: Select,
select: unknown,
event?: Event
): Promise<void> {
this.args.changeset.set(this.args.fieldName, selection);
Expand All @@ -38,7 +34,7 @@ export default class ChangesetFormFieldsSelect extends Base<ChangesetFormFieldsS
}

@action
async handleFocusOut(select: Select, event: FocusEvent): Promise<void> {
async handleFocusOut(select: unknown, event: FocusEvent): Promise<void> {
await this.validate();

if (typeof this.args.onFocusOut === 'function') {
Expand All @@ -47,7 +43,7 @@ export default class ChangesetFormFieldsSelect extends Base<ChangesetFormFieldsS
}

@action
async handleClose(select: Select, event: Event): Promise<void> {
async handleClose(select: unknown, event: Event): Promise<void> {
await this.validate();

if (typeof this.args.onClose === 'function') {
Expand Down
3 changes: 2 additions & 1 deletion packages/collections/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@
"app-js": {
"./components/dropdown.js": "./dist/_app_/components/dropdown.js",
"./components/listbox.js": "./dist/_app_/components/listbox.js",
"./components/native-select.js": "./dist/_app_/components/native-select.js"
"./components/native-select.js": "./dist/_app_/components/native-select.js",
"./components/select.js": "./dist/_app_/components/select.js"
}
},
"exports": {
Expand Down
4 changes: 2 additions & 2 deletions packages/collections/src/components/dropdown.gts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface DropdownArgs
| 'shiftOptions'
| 'offsetOptions'
| 'strategy'
| 'onClose'
| 'didClose'
> {
/**
* Whether the dropdown should close upon selecting an item.
Expand Down Expand Up @@ -58,7 +58,7 @@ class Dropdown extends Component<DropdownSignature> {
@shiftOptions={{@shiftOptions}}
@offsetOptions={{@offsetOptions}}
@strategy={{@strategy}}
@onClose={{@onClose}}
@didClose={{@didClose}}
as |p|
>
{{yield
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
import Component from '@glimmer/component';
import type { TOC } from '@ember/component/template-only';
import { tracked } from '@glimmer/tracking';
import { on } from '@ember/modifier';
import {
NativeSelect,
Listbox,
type ListboxSignature,
type ListItemNode
} from '@frontile/collections';
import { NativeSelect } from './native-select';
import { Listbox, type ListboxSignature, type ListItemNode } from './listbox';
import { useStyles } from '@frontile/theme';
import { VisuallyHidden } from '@frontile/utilities';
import {
Popover,
type PopoverSignature,
type ContentSignature
} from '@frontile/overlays';
import { assert } from '@ember/debug';
import { hash } from '@ember/helper';
import type { ModifierLike } from '@glint/template';
import type { WithBoundArgs } from '@glint/template';

interface FormFieldSelectArgs<T = unknown>
interface SelectArgs<T = unknown>
extends Pick<
PopoverSignature['Args'],
| 'placement'
Expand All @@ -28,7 +20,7 @@ interface FormFieldSelectArgs<T = unknown>
| 'shiftOptions'
| 'offsetOptions'
| 'strategy'
| 'onClose'
| 'didClose'
>,
Pick<
ListboxSignature<T>['Args'],
Expand All @@ -40,6 +32,7 @@ interface FormFieldSelectArgs<T = unknown>
| 'allowEmpty'
| 'onSelectionChange'
| 'items'
| 'onAction'
>,
Pick<
ContentSignature['Args'],
Expand Down Expand Up @@ -73,14 +66,19 @@ interface FormFieldSelectArgs<T = unknown>
disableFocusTrap?: boolean;
}

interface FormFieldSelectSignature {
Args: FormFieldSelectArgs;
interface SelectSignature {
Args: SelectArgs;
Element: HTMLUListElement | HTMLSelectElement;
Blocks: ListboxSignature['Blocks'];
}

class FormFieldSelect extends Component<FormFieldSelectSignature> {
class Select extends Component<SelectSignature> {
@tracked nodes: ListItemNode[] = [];
@tracked isOpen = false;

onOpenChange = (isOpen: boolean) => {
this.isOpen = isOpen;
};

get blockScroll() {
if (this.args.blockScroll === false) {
Expand All @@ -97,7 +95,16 @@ class FormFieldSelect extends Component<FormFieldSelectSignature> {
}

onAction = (key: string) => {
// todo
if (typeof this.args.onAction === 'function') {
this.args.onAction(key);
}

if (
this.args.closeOnItemSelect !== false &&
this.args.selectionMode !== 'multiple'
) {
this.isOpen = false;
}
};

get selectedText() {
Expand Down Expand Up @@ -125,6 +132,15 @@ class FormFieldSelect extends Component<FormFieldSelectSignature> {
return this.args.backdrop;
}

get classNames() {
const { select } = useStyles();
const { base, icon } = select();
return {
base: base({ class: this.args.class }),
icon: icon()
};
}

<template>
<Popover
@placement={{@placement}}
Expand All @@ -133,7 +149,9 @@ class FormFieldSelect extends Component<FormFieldSelectSignature> {
@shiftOptions={{@shiftOptions}}
@offsetOptions={{@offsetOptions}}
@strategy={{@strategy}}
@onClose={{@onClose}}
@didClose={{@didClose}}
@isOpen={{this.isOpen}}
@onOpenChange={{this.onOpenChange}}
as |p|
>
<VisuallyHidden>
Expand All @@ -149,6 +167,7 @@ class FormFieldSelect extends Component<FormFieldSelectSignature> {
>
<:item as |l|>
{{#if (has-block "item")}}
{{! @glint-expect-error: the signature of the native select item is not the same as the listtbox item}}
{{yield l to="item"}}
{{else}}
<l.Item @key={{l.key}}>
Expand All @@ -157,14 +176,23 @@ class FormFieldSelect extends Component<FormFieldSelectSignature> {
{{/if}}
</:item>
<:default as |l|>
{{! @glint-expect-error: the signature of the native select is not the same as the listtbox}}
{{yield l to="default"}}
</:default>
</NativeSelect>
</VisuallyHidden>
<button {{p.trigger}} {{p.anchor}} data-test-id="trigger">
{{this.selectedTextValue}}
BUTTON
<button
{{p.trigger}}
{{p.anchor}}
data-test-id="trigger"
class={{this.classNames.base}}
>
<span>
{{this.selectedTextValue}}
</span>
<Icon class={{this.classNames.icon}} />
</button>
<p.Content
Expand Down Expand Up @@ -217,5 +245,25 @@ class FormFieldSelect extends Component<FormFieldSelectSignature> {
</template>
}
export { FormFieldSelect, type FormFieldSelectSignature };
export default FormFieldSelect;
const Icon: TOC<{
Element: SVGElement;
}> = <template>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
aria-hidden="true"
...attributes
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M8.25 15 12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9"
/>
</svg>
</template>;

export { Select, type SelectSignature };
export default Select;
Loading

0 comments on commit 3749a92

Please sign in to comment.