@ideal-postcodes/address-finder
Version:
Address Finder JS library backed by the Ideal Postcodes UK address search API
246 lines (245 loc) • 8.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = void 0;
const fsm_1 = require("@xstate/fsm");
// @hidden
const create = ({ c }) => {
const machine = (0, fsm_1.createMachine)({
initial: "closed",
states: {
closed: {
entry: ["close"],
exit: ["open"],
on: {
COUNTRY_CHANGE_EVENT: {
actions: ["updateContextWithCountry"],
},
AWAKE: [
{
target: "suggesting",
cond: () => c.suggestions.length > 0,
},
{
target: "notifying",
},
],
},
},
notifying: {
entry: ["renderNotice"],
exit: ["clearAnnouncement"],
on: {
CLOSE: "closed",
SUGGEST: { target: "suggesting", actions: ["updateSuggestions"] },
NOTIFY: { target: "notifying", actions: ["updateMessage"] },
INPUT: { actions: "input" },
CHANGE_COUNTRY: { target: "suggesting_country" },
},
},
suggesting_country: {
entry: [
"clearInput",
"renderContexts",
"gotoCurrent",
"expand",
"addCountryHint",
],
exit: [
"resetCurrent",
"gotoCurrent",
"contract",
"clearHint",
"clearInput",
],
on: {
CLOSE: "closed",
NOTIFY: { target: "notifying", actions: ["updateMessage"] },
NEXT: { actions: ["next", "gotoCurrent"] },
PREVIOUS: { actions: ["previous", "gotoCurrent"] },
RESET: { actions: ["resetCurrent", "gotoCurrent"] },
INPUT: {
actions: ["countryInput"],
},
SELECT_COUNTRY: {
target: "notifying",
actions: ["selectCountry"],
},
},
},
suggesting: {
entry: ["renderSuggestions", "gotoCurrent", "expand", "addHint"],
exit: ["resetCurrent", "gotoCurrent", "contract", "clearHint"],
on: {
CLOSE: "closed",
SUGGEST: { target: "suggesting", actions: ["updateSuggestions"] },
NOTIFY: { target: "notifying", actions: ["updateMessage"] },
INPUT: { actions: "input" },
CHANGE_COUNTRY: { target: "suggesting_country" },
NEXT: { actions: ["next", "gotoCurrent"] },
PREVIOUS: { actions: ["previous", "gotoCurrent"] },
RESET: { actions: ["resetCurrent", "gotoCurrent"] },
SELECT_ADDRESS: { target: "closed", actions: ["selectAddress"] },
},
},
},
}, {
actions: {
// Updates the Address Finder context
updateContextWithCountry: (_, e) => {
if (e.type !== "COUNTRY_CHANGE_EVENT")
return;
if (!e.contextDetails)
return;
c.applyContext(e.contextDetails);
c.suggestions = [];
c.cache.clear();
},
addHint: () => {
c.setPlaceholder(c.options.msgPlaceholder);
},
addCountryHint: () => {
c.setPlaceholder(c.options.msgPlaceholderCountry);
},
clearHint: () => {
c.unsetPlaceholder();
},
// Empties current input
clearInput: () => {
c.clearInput();
},
/**
* Updates current li in list to active descendant
*/
gotoCurrent: () => {
c.goToCurrent();
},
/**
* Unhighlights a suggestion
*/
resetCurrent: () => {
c.current = -1;
},
/**
* Triggers onInput callback
*/
input: (_, e) => {
if (e.type !== "INPUT")
return;
c.retrieveSuggestions(e.event);
},
/**
* Narrows country search box
*/
countryInput: () => {
c.renderContexts();
},
/**
* Clears ARIA announcement fields
*/
clearAnnouncement: () => {
c.announce("");
},
/**
* Renders suggestion within list
*/
renderContexts: (_, e) => {
if (e.type !== "CHANGE_COUNTRY")
return;
c.renderContexts();
},
/**
* Renders suggestion within list
*/
renderSuggestions: (_, e) => {
if (e.type !== "SUGGEST")
return;
c.renderSuggestions();
},
/**
* Update suggestions
*/
updateSuggestions: (_, e) => {
if (e.type !== "SUGGEST")
return;
c.updateSuggestions(e.suggestions);
},
/**
* Hides list and runs callback
*/
close: (_, e) => {
if (e.type === "CLOSE")
return c.close(e.reason);
c.close();
},
/**
* Makes list visible and run callback
*/
open: () => {
c.open();
},
/**
* Marks aria component as expanded
*/
expand: () => {
c.ariaExpand();
},
/**
* Marks aria component as closed
*/
contract: () => {
c.ariaContract();
},
/**
* Assigns notification message
*/
updateMessage: (_, e) => {
if (e.type !== "NOTIFY")
return;
c.notification = e.notification;
},
/**
* Renders message container and current message
*/
renderNotice: () => {
c.renderNotice();
},
/**
* Selects next element in list. Wraps to top if at bottom
*/
next: () => {
c.next();
},
/**
* Selects previous element in list. Wraps to bottom if at top
*/
previous: () => {
c.previous();
},
/**
* Triggers select on current context or clicked element
*/
selectCountry: (_, e) => {
if (e.type !== "SELECT_COUNTRY")
return;
const co = e.contextDetails;
if (!co)
return;
c.applyContext(co);
c.notification = `Country switched to ${co.description} ${co.emoji}`;
},
/**
* Triggers select on current suggestion or clicked element
*/
selectAddress: (_, e) => {
if (e.type !== "SELECT_ADDRESS")
return;
const s = e.suggestion;
if (!s)
return;
c.applySuggestion(s);
},
},
});
return (0, fsm_1.interpret)(machine);
};
exports.create = create;