@searchspring/snap-controller 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +167 -0
- package/dist/cjs/Abstract/AbstractController.d.ts +40 -0
- package/dist/cjs/Abstract/AbstractController.d.ts.map +1 -0
- package/dist/cjs/Abstract/AbstractController.js +281 -0
- package/dist/cjs/Autocomplete/AutocompleteController.d.ts +40 -0
- package/dist/cjs/Autocomplete/AutocompleteController.d.ts.map +1 -0
- package/dist/cjs/Autocomplete/AutocompleteController.js +687 -0
- package/dist/cjs/Finder/FinderController.d.ts +14 -0
- package/dist/cjs/Finder/FinderController.d.ts.map +1 -0
- package/dist/cjs/Finder/FinderController.js +286 -0
- package/dist/cjs/Recommendation/RecommendationController.d.ts +31 -0
- package/dist/cjs/Recommendation/RecommendationController.d.ts.map +1 -0
- package/dist/cjs/Recommendation/RecommendationController.js +452 -0
- package/dist/cjs/Search/SearchController.d.ts +23 -0
- package/dist/cjs/Search/SearchController.d.ts.map +1 -0
- package/dist/cjs/Search/SearchController.js +429 -0
- package/dist/cjs/index.d.ts +7 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +24 -0
- package/dist/cjs/types.d.ts +52 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/utils/getParams.d.ts +2 -0
- package/dist/cjs/utils/getParams.d.ts.map +1 -0
- package/dist/cjs/utils/getParams.js +72 -0
- package/dist/esm/Abstract/AbstractController.d.ts +40 -0
- package/dist/esm/Abstract/AbstractController.d.ts.map +1 -0
- package/dist/esm/Abstract/AbstractController.js +181 -0
- package/dist/esm/Autocomplete/AutocompleteController.d.ts +40 -0
- package/dist/esm/Autocomplete/AutocompleteController.d.ts.map +1 -0
- package/dist/esm/Autocomplete/AutocompleteController.js +472 -0
- package/dist/esm/Finder/FinderController.d.ts +14 -0
- package/dist/esm/Finder/FinderController.d.ts.map +1 -0
- package/dist/esm/Finder/FinderController.js +164 -0
- package/dist/esm/Recommendation/RecommendationController.d.ts +31 -0
- package/dist/esm/Recommendation/RecommendationController.d.ts.map +1 -0
- package/dist/esm/Recommendation/RecommendationController.js +330 -0
- package/dist/esm/Search/SearchController.d.ts +23 -0
- package/dist/esm/Search/SearchController.d.ts.map +1 -0
- package/dist/esm/Search/SearchController.js +282 -0
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/types.d.ts +52 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/utils/getParams.d.ts +2 -0
- package/dist/esm/utils/getParams.d.ts.map +1 -0
- package/dist/esm/utils/getParams.js +68 -0
- package/package.json +40 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { LogMode } from '@searchspring/snap-logger';
|
|
2
|
+
import { DomTargeter, cookies, url } from '@searchspring/snap-toolbox';
|
|
3
|
+
const SS_DEV_COOKIE = 'ssDev';
|
|
4
|
+
export class AbstractController {
|
|
5
|
+
constructor(config, { client, store, urlManager, eventManager, profiler, logger, tracker }) {
|
|
6
|
+
this.type = 'abstract';
|
|
7
|
+
this.targeters = {};
|
|
8
|
+
this._initialized = false;
|
|
9
|
+
this._environment = LogMode.PRODUCTION;
|
|
10
|
+
if (typeof config != 'object' || typeof config.id != 'string' || !config.id.match(/^[a-zA-Z0-9_-]*$/)) {
|
|
11
|
+
throw new Error(`Invalid config passed to controller. The "id" attribute must be an alphanumeric string.`);
|
|
12
|
+
}
|
|
13
|
+
if (typeof client != 'object' || typeof client.search != 'function') {
|
|
14
|
+
throw new Error(`Invalid service 'client' passed to controller. Missing "search" function.`);
|
|
15
|
+
}
|
|
16
|
+
if (typeof store != 'object' || typeof store.update != 'function') {
|
|
17
|
+
throw new Error(`Invalid service 'store' passed to controller. Missing "update" function.`);
|
|
18
|
+
}
|
|
19
|
+
if (typeof urlManager != 'object' || typeof urlManager.subscribe != 'function') {
|
|
20
|
+
throw new Error(`Invalid service 'urlManager' passed to controller. Missing "subscribe" function.`);
|
|
21
|
+
}
|
|
22
|
+
if (typeof eventManager != 'object' || typeof eventManager.on != 'function') {
|
|
23
|
+
throw new Error(`Invalid service 'eventManager' passed to controller. Missing "on" function.`);
|
|
24
|
+
}
|
|
25
|
+
if (typeof eventManager != 'object' || typeof eventManager.fire != 'function') {
|
|
26
|
+
throw new Error(`Invalid service 'eventManager' passed to controller. Missing "fire" function.`);
|
|
27
|
+
}
|
|
28
|
+
if (typeof profiler != 'object' || typeof profiler.setNamespace != 'function') {
|
|
29
|
+
throw new Error(`Invalid service 'profiler' passed to controller. Missing "setNamespace" function.`);
|
|
30
|
+
}
|
|
31
|
+
if (typeof profiler != 'object' || typeof profiler.create != 'function') {
|
|
32
|
+
throw new Error(`Invalid service 'profiler' passed to controller. Missing "create" function.`);
|
|
33
|
+
}
|
|
34
|
+
if (typeof logger != 'object' || typeof logger.dev != 'function') {
|
|
35
|
+
throw new Error(`Invalid service 'logger' passed to controller. Missing "dev" function.`);
|
|
36
|
+
}
|
|
37
|
+
if (typeof tracker != 'object' || typeof tracker.track != 'object') {
|
|
38
|
+
throw new Error(`Invalid service 'tracker' passed to controller. Missing "track" object.`);
|
|
39
|
+
}
|
|
40
|
+
window.searchspring = window.searchspring || {};
|
|
41
|
+
window.searchspring.controller = window.searchspring.controller || {};
|
|
42
|
+
if (window.searchspring.controller[config.id]) {
|
|
43
|
+
throw new Error(`Controller with id '${config.id}' is already defined`);
|
|
44
|
+
}
|
|
45
|
+
window.searchspring.controller[config.id] = this;
|
|
46
|
+
this.id = config.id;
|
|
47
|
+
this.config = config;
|
|
48
|
+
this.client = client;
|
|
49
|
+
this.store = store;
|
|
50
|
+
this.urlManager = urlManager;
|
|
51
|
+
this.eventManager = eventManager;
|
|
52
|
+
this.profiler = profiler;
|
|
53
|
+
this.log = logger;
|
|
54
|
+
this.tracker = tracker;
|
|
55
|
+
// configure the logger
|
|
56
|
+
this.log.setNamespace(this.config.id);
|
|
57
|
+
// set namespaces
|
|
58
|
+
this.profiler.setNamespace(this.config.id);
|
|
59
|
+
// set environment
|
|
60
|
+
if (url(window.location.href)?.params?.query?.dev) {
|
|
61
|
+
cookies.set(SS_DEV_COOKIE, '1', 'Lax', 0);
|
|
62
|
+
}
|
|
63
|
+
const dev = cookies.get(SS_DEV_COOKIE);
|
|
64
|
+
this.environment = (dev === '1' ? 'development' : process.env.NODE_ENV);
|
|
65
|
+
}
|
|
66
|
+
get initialized() {
|
|
67
|
+
return this._initialized;
|
|
68
|
+
}
|
|
69
|
+
createTargeter(target, onTarget, document) {
|
|
70
|
+
return this.addTargeter(new DomTargeter([target], onTarget, document));
|
|
71
|
+
}
|
|
72
|
+
addTargeter(target) {
|
|
73
|
+
const firstTarget = target.getTargets()[0];
|
|
74
|
+
const targetName = firstTarget?.name ?? firstTarget?.selector;
|
|
75
|
+
if (targetName && !this.targeters[targetName]) {
|
|
76
|
+
this.targeters[targetName] = target;
|
|
77
|
+
return target;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
set environment(env) {
|
|
81
|
+
if (Object.values(LogMode).includes(env)) {
|
|
82
|
+
this._environment = env;
|
|
83
|
+
this.log.setMode(env);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
get environment() {
|
|
87
|
+
return this._environment;
|
|
88
|
+
}
|
|
89
|
+
async init() {
|
|
90
|
+
if (this._initialized) {
|
|
91
|
+
this.log.warn(`'init' middleware recalled`);
|
|
92
|
+
}
|
|
93
|
+
const initProfile = this.profiler.create({ type: 'event', name: 'init', context: this.config }).start();
|
|
94
|
+
try {
|
|
95
|
+
try {
|
|
96
|
+
await this.eventManager.fire('init', {
|
|
97
|
+
controller: this,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
if (err?.message == 'cancelled') {
|
|
102
|
+
this.log.warn(`'init' middleware cancelled`);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
this.log.error(`error in 'init' middleware`);
|
|
106
|
+
throw err;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
if (err) {
|
|
112
|
+
console.error(err);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (!this._initialized) {
|
|
116
|
+
// subscribe to urlManager changes
|
|
117
|
+
this.urlManager.subscribe((prev, next) => {
|
|
118
|
+
try {
|
|
119
|
+
const prevString = JSON.stringify(prev);
|
|
120
|
+
const nextString = JSON.stringify(next);
|
|
121
|
+
if (prevString !== nextString) {
|
|
122
|
+
this.search();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
this.log.error('URL state is invalid', err);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
this._initialized = true;
|
|
130
|
+
}
|
|
131
|
+
initProfile.stop();
|
|
132
|
+
this.log.profile(initProfile);
|
|
133
|
+
}
|
|
134
|
+
retarget() {
|
|
135
|
+
Object.keys(this.targeters).forEach((target) => {
|
|
136
|
+
this.targeters[target].retarget();
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
async plugin(func, ...args) {
|
|
140
|
+
await func(this, ...args);
|
|
141
|
+
}
|
|
142
|
+
on(event, ...func) {
|
|
143
|
+
this.eventManager.on(event, ...func);
|
|
144
|
+
}
|
|
145
|
+
use(attachments) {
|
|
146
|
+
// attach plugins
|
|
147
|
+
if (attachments?.plugins) {
|
|
148
|
+
try {
|
|
149
|
+
if (!Array.isArray(attachments?.plugins)) {
|
|
150
|
+
throw 'invalid format';
|
|
151
|
+
}
|
|
152
|
+
attachments?.plugins.forEach((plugin) => {
|
|
153
|
+
if (!Array.isArray(plugin)) {
|
|
154
|
+
throw 'invalid format';
|
|
155
|
+
}
|
|
156
|
+
const [func, ...args] = plugin;
|
|
157
|
+
this.plugin(func, ...args);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
this.log.warn('plugins not attached - use format [func, ...args?][]');
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// attach event middleware
|
|
165
|
+
if (attachments?.middleware) {
|
|
166
|
+
Object.keys(attachments.middleware).forEach((eventName) => {
|
|
167
|
+
const eventMiddleware = attachments.middleware[eventName];
|
|
168
|
+
let middlewareArray;
|
|
169
|
+
if (Array.isArray(eventMiddleware)) {
|
|
170
|
+
middlewareArray = eventMiddleware;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
middlewareArray = [eventMiddleware];
|
|
174
|
+
}
|
|
175
|
+
middlewareArray.forEach((middleware) => {
|
|
176
|
+
this.on(eventName, middleware);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { StorageStore } from '@searchspring/snap-store-mobx';
|
|
2
|
+
import { AbstractController } from '../Abstract/AbstractController';
|
|
3
|
+
import type { AutocompleteStore } from '@searchspring/snap-store-mobx';
|
|
4
|
+
import type { AutocompleteControllerConfig, ControllerServices } from '../types';
|
|
5
|
+
import type { AutocompleteRequestModel } from '@searchspring/snapi-types';
|
|
6
|
+
declare type AutocompleteTrackMethods = {
|
|
7
|
+
product: {
|
|
8
|
+
click: (e: any, result: any) => void;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export declare class AutocompleteController extends AbstractController {
|
|
12
|
+
type: string;
|
|
13
|
+
store: AutocompleteStore;
|
|
14
|
+
config: AutocompleteControllerConfig;
|
|
15
|
+
storage: StorageStore;
|
|
16
|
+
constructor(config: AutocompleteControllerConfig, { client, store, urlManager, eventManager, profiler, logger, tracker }: ControllerServices);
|
|
17
|
+
track: AutocompleteTrackMethods;
|
|
18
|
+
get params(): AutocompleteRequestModel;
|
|
19
|
+
setFocused(inputElement?: HTMLInputElement): Promise<void>;
|
|
20
|
+
reset(): void;
|
|
21
|
+
handlers: {
|
|
22
|
+
input: {
|
|
23
|
+
enterKey: (e: KeyboardEvent) => Promise<void>;
|
|
24
|
+
escKey: (e: KeyboardEvent) => void;
|
|
25
|
+
focus: (e: FocusEvent) => void;
|
|
26
|
+
formSubmit: (e: any) => Promise<void>;
|
|
27
|
+
keyUp: (e: KeyboardEvent) => void;
|
|
28
|
+
timeoutDelay: any;
|
|
29
|
+
};
|
|
30
|
+
document: {
|
|
31
|
+
click: (e: MouseEvent) => void;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
unbind(): void;
|
|
35
|
+
bind(): Promise<void>;
|
|
36
|
+
searchTrending: () => Promise<void>;
|
|
37
|
+
search: () => Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=AutocompleteController.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutocompleteController.d.ts","sourceRoot":"","sources":["../../../src/Autocomplete/AutocompleteController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAA0B,MAAM,+BAA+B,CAAC;AAErF,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,4BAA4B,EAAkD,kBAAkB,EAAa,MAAM,UAAU,CAAC;AAC5I,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAuB1E,aAAK,wBAAwB,GAAG;IAC/B,OAAO,EAAE;QACR,KAAK,EAAE,CAAC,CAAC,KAAA,EAAE,MAAM,KAAA,KAAK,IAAI,CAAC;KAC3B,CAAC;CACF,CAAC;AAEF,qBAAa,sBAAuB,SAAQ,kBAAkB;IACtD,IAAI,SAAkB;IACtB,KAAK,EAAE,iBAAiB,CAAC;IACzB,MAAM,EAAE,4BAA4B,CAAC;IACrC,OAAO,EAAE,YAAY,CAAC;gBAEjB,MAAM,EAAE,4BAA4B,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,kBAAkB;IAkD5I,KAAK,EAAE,wBAAwB,CAO7B;IAEF,IAAI,MAAM,IAAI,wBAAwB,CA+BrC;IAEK,UAAU,CAAC,YAAY,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BhE,KAAK,IAAI,IAAI;IASb,QAAQ;;0BAEc,aAAa,KAAG,QAAQ,IAAI,CAAC;wBA6CrC,aAAa,KAAG,IAAI;uBAMrB,UAAU,KAAG,IAAI;oCAQL,QAAQ,IAAI,CAAC;uBAwCzB,aAAa,KAAG,IAAI;;;;uBA0CpB,UAAU,KAAG,IAAI;;MAS5B;IAEF,MAAM,IAAI,IAAI;IAYR,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAgE3B,cAAc,QAAa,QAAQ,IAAI,CAAC,CAsBtC;IAEF,MAAM,QAAa,QAAQ,IAAI,CAAC,CA6G9B;CACF"}
|