Skip to content

Commit

Permalink
feat(js): pass scope API to prop getters
Browse files Browse the repository at this point in the history
  • Loading branch information
francoischalifour committed Dec 7, 2020
1 parent 2e3a8ed commit 18c7474
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 160 deletions.
102 changes: 38 additions & 64 deletions packages/autocomplete-js/src/autocomplete.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { BaseItem, createAutocomplete } from '@algolia/autocomplete-core';
import {
AutocompleteScopeApi,
BaseItem,
createAutocomplete,
} from '@algolia/autocomplete-core';
import { createRef, invariant } from '@algolia/autocomplete-shared';

import { createAutocompleteDom } from './createAutocompleteDom';
Expand All @@ -8,6 +12,7 @@ import { render } from './render';
import {
AutocompleteApi,
AutocompleteOptions,
AutocompletePropGetters,
AutocompleteState,
} from './types';
import { debounce, getHTMLElement, setProperties } from './utils';
Expand Down Expand Up @@ -60,20 +65,7 @@ export function autocomplete<TItem extends BaseItem>({
...props.initialState,
};

const {
inputWrapper,
form,
label,
input,
submitButton,
resetButton,
loadingIndicator,
root,
panel,
} = createAutocompleteDom({
state: initialState,
autocomplete,
classNames,
const propGetters: AutocompletePropGetters<TItem> = {
getEnvironmentProps,
getFormProps,
getInputProps,
Expand All @@ -82,24 +74,40 @@ export function autocomplete<TItem extends BaseItem>({
getListProps,
getPanelProps,
getRootProps,
};
const autocompleteScopeApi: AutocompleteScopeApi<TItem> = {
setSelectedItemId: autocomplete.setSelectedItemId,
setQuery: autocomplete.setQuery,
setCollections: autocomplete.setCollections,
setIsOpen: autocomplete.setIsOpen,
setStatus: autocomplete.setStatus,
setContext: autocomplete.setContext,
refresh: autocomplete.refresh,
};
const dom = createAutocompleteDom({
state: initialState,
autocomplete,
classNames,
propGetters,
autocompleteScopeApi,
});

function setPanelPosition() {
setProperties(panel, {
setProperties(dom.panel, {
style: getPanelPositionStyle({
panelPlacement,
container: root,
form,
container: dom.root,
form: dom.form,
environment: props.environment,
}),
});
}

runEffect(() => {
const environmentProps = autocomplete.getEnvironmentProps({
formElement: form,
panelElement: panel,
inputElement: input,
formElement: dom.form,
panelElement: dom.panel,
inputElement: dom.input,
});

setProperties(window as any, environmentProps);
Expand All @@ -122,25 +130,11 @@ export function autocomplete<TItem extends BaseItem>({
render(renderer, {
state: initialState,
autocomplete,
getEnvironmentProps,
getFormProps,
getInputProps,
getItemProps,
getLabelProps,
getListProps,
getPanelProps,
getRootProps,
propGetters,
dom,
classNames,
panelRoot,
root,
form,
input,
inputWrapper,
label,
panel,
submitButton,
resetButton,
loadingIndicator,
autocompleteScopeApi,
});

return () => {};
Expand All @@ -162,25 +156,11 @@ export function autocomplete<TItem extends BaseItem>({
unmountRef.current = render(renderer, {
state,
autocomplete,
getEnvironmentProps,
getFormProps,
getInputProps,
getItemProps,
getLabelProps,
getListProps,
getPanelProps,
getRootProps,
propGetters,
dom,
classNames,
panelRoot,
root,
form,
input,
inputWrapper,
label,
panel,
submitButton,
resetButton,
loadingIndicator,
autocompleteScopeApi,
});
}, 0);

Expand Down Expand Up @@ -208,10 +188,10 @@ export function autocomplete<TItem extends BaseItem>({
containerElement.tagName !== 'INPUT',
'The `container` option does not support `input` elements. You need to change the container to a `div`.'
);
containerElement.appendChild(root);
containerElement.appendChild(dom.root);

return () => {
containerElement.removeChild(root);
containerElement.removeChild(dom.root);
};
});

Expand All @@ -232,13 +212,7 @@ export function autocomplete<TItem extends BaseItem>({
});

return {
setSelectedItemId: autocomplete.setSelectedItemId,
setQuery: autocomplete.setQuery,
setCollections: autocomplete.setCollections,
setIsOpen: autocomplete.setIsOpen,
setStatus: autocomplete.setStatus,
setContext: autocomplete.setContext,
refresh: autocomplete.refresh,
...autocompleteScopeApi,
destroy() {
cleanupEffects();
},
Expand Down
19 changes: 13 additions & 6 deletions packages/autocomplete-js/src/components/Input.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { AutocompleteApi as AutocompleteCoreApi } from '@algolia/autocomplete-core';
import {
AutocompleteApi as AutocompleteCoreApi,
AutocompleteScopeApi,
} from '@algolia/autocomplete-core';

import { AutocompletePropGetters, AutocompleteState } from '../types';
import { Component, WithClassNames } from '../types/Component';
Expand All @@ -8,21 +11,25 @@ type InputProps = WithClassNames<{
state: AutocompleteState<any>;
getInputProps: AutocompletePropGetters<any>['getInputProps'];
getInputPropsCore: AutocompleteCoreApi<any>['getInputProps'];
autocompleteScopeApi: AutocompleteScopeApi<any>;
}>;

export const Input: Component<InputProps, HTMLInputElement> = ({
classNames,
getInputProps,
getInputPropsCore,
state,
autocompleteScopeApi,
}) => {
const element = document.createElement('input');
const inputProps = getInputProps({
state,
props: getInputPropsCore({ inputElement: element }),
inputElement: element,
...autocompleteScopeApi,
});
setProperties(element, {
...getInputProps({
state,
props: getInputPropsCore({ inputElement: element }),
inputElement: element,
}),
...inputProps,
class: concatClassNames(['aa-Input', classNames.input]),
});

Expand Down
53 changes: 28 additions & 25 deletions packages/autocomplete-js/src/createAutocompleteDom.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
AutocompleteApi as AutocompleteCoreApi,
AutocompleteScopeApi,
BaseItem,
} from '@algolia/autocomplete-core';

Expand All @@ -21,54 +22,56 @@ import {
AutocompleteState,
} from './types';

type CreateDomProps<TItem extends BaseItem> = AutocompletePropGetters<TItem> & {
type CreateDomProps<TItem extends BaseItem> = {
classNames: Partial<AutocompleteClassNames>;
autocomplete: AutocompleteCoreApi<TItem>;
state: AutocompleteState<TItem>;
propGetters: AutocompletePropGetters<TItem>;
autocompleteScopeApi: AutocompleteScopeApi<TItem>;
};

export function createAutocompleteDom<TItem extends BaseItem>({
autocomplete,
classNames,
getRootProps,
getFormProps,
getLabelProps,
getInputProps,
getPanelProps,
propGetters,
state,
autocompleteScopeApi,
}: CreateDomProps<TItem>): AutocompleteDom {
const root = Root({
classNames,
...getRootProps({
state,
props: autocomplete.getRootProps({}),
}),
const rootProps = propGetters.getRootProps({
state,
props: autocomplete.getRootProps({}),
...autocompleteScopeApi,
});
const root = Root({ classNames, ...rootProps });
const inputWrapper = InputWrapper({ classNames });
const label = Label({
classNames,
...getLabelProps({ state, props: autocomplete.getLabelProps({}) }),
const labelProps = propGetters.getLabelProps({
state,
props: autocomplete.getLabelProps({}),
...autocompleteScopeApi,
});
const label = Label({ classNames, ...labelProps });
const input = Input({
classNames,
state,
getInputProps,
getInputProps: propGetters.getInputProps,
getInputPropsCore: autocomplete.getInputProps,
autocompleteScopeApi,
});
const submitButton = SubmitButton({ classNames });
const resetButton = ResetButton({ classNames });
const loadingIndicator = LoadingIndicator({ classNames });
const form = Form({
classNames,
...getFormProps({
state,
props: autocomplete.getFormProps({ inputElement: input }),
}),
const formProps = propGetters.getFormProps({
state,
props: autocomplete.getFormProps({ inputElement: input }),
...autocompleteScopeApi,
});
const panel = Panel({
classNames,
...getPanelProps({ state, props: autocomplete.getPanelProps({}) }),
const form = Form({ classNames, ...formProps });
const panelProps = propGetters.getPanelProps({
state,
props: autocomplete.getPanelProps({}),
...autocompleteScopeApi,
});
const panel = Panel({ classNames, ...panelProps });

label.appendChild(submitButton);
inputWrapper.appendChild(input);
Expand Down
Loading

0 comments on commit 18c7474

Please sign in to comment.