@arcgis/lumina 4.33.0-next.94 → 4.33.0-next.96

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.
Files changed (43) hide show
  1. package/dist/ControllerManager-B2comd8J.js +310 -0
  2. package/dist/LitElement.d.ts +3 -3
  3. package/dist/context.d.ts +1 -1
  4. package/dist/controllers/ComponentInternals.d.ts +92 -0
  5. package/dist/controllers/Controller.d.ts +152 -0
  6. package/dist/controllers/ControllerInternals.d.ts +52 -0
  7. package/dist/controllers/ControllerManager.d.ts +63 -0
  8. package/dist/controllers/accessor/index.d.ts +2 -0
  9. package/dist/controllers/accessor/index.js +307 -0
  10. package/dist/controllers/accessor/reEmitEvent.d.ts +14 -0
  11. package/dist/controllers/accessor/useAccessor.d.ts +75 -0
  12. package/dist/controllers/framework.d.ts +45 -0
  13. package/dist/controllers/functional.d.ts +19 -0
  14. package/dist/controllers/getSet.d.ts +116 -0
  15. package/dist/controllers/index.d.ts +23 -0
  16. package/dist/controllers/index.js +283 -0
  17. package/dist/controllers/load.d.ts +6 -0
  18. package/dist/controllers/proxyExports.d.ts +27 -0
  19. package/dist/controllers/readonly.d.ts +29 -0
  20. package/dist/controllers/tests/autoDestroyMock.d.ts +5 -0
  21. package/dist/controllers/tests/utils.d.ts +1 -0
  22. package/dist/controllers/toFunction.d.ts +8 -0
  23. package/dist/controllers/trackKey.d.ts +8 -0
  24. package/dist/controllers/trackPropKey.d.ts +21 -0
  25. package/dist/controllers/trackPropertyKey.d.ts +28 -0
  26. package/dist/controllers/types.d.ts +182 -0
  27. package/dist/controllers/useDirection.d.ts +11 -0
  28. package/dist/controllers/useMedia.d.ts +8 -0
  29. package/dist/controllers/usePropertyChange.d.ts +11 -0
  30. package/dist/controllers/useT9n.d.ts +48 -0
  31. package/dist/controllers/useWatch.d.ts +27 -0
  32. package/dist/controllers/useWatchAttributes.d.ts +7 -0
  33. package/dist/controllers/utils.d.ts +15 -0
  34. package/dist/createEvent.d.ts +1 -1
  35. package/dist/decorators.d.ts +1 -1
  36. package/dist/index.d.ts +2 -2
  37. package/dist/index.js +5 -42
  38. package/dist/lazyLoad.d.ts +2 -2
  39. package/dist/makeRuntime.d.ts +109 -0
  40. package/dist/proxyExports-Dl5CHmHQ.js +150 -0
  41. package/dist/runtime.d.ts +4 -107
  42. package/dist/useWatch-CFtSpNnN.js +925 -0
  43. package/package.json +4 -3
@@ -0,0 +1,310 @@
1
+ import { G as GenericController, j as ComponentInternals, l as retrieveComponentMembers, s as setAmbientComponent, m as elementToInstance, k as keyTrackResolve, n as devOnlySetPersistentControllerData, w as watch, h as controllerSymbol } from "./useWatch-CFtSpNnN.js";
2
+ import { isEsriInternalEnv, Deferred, devToolsAwareTimeout, safeCall, safeAsyncCall } from "@arcgis/components-utils";
3
+ const useControllerManager = (component) => new ControllerManager(component);
4
+ class ControllerManager extends GenericController {
5
+ constructor(component) {
6
+ const isLit = "addController" in component;
7
+ const controllers = /* @__PURE__ */ new Set();
8
+ function addController(controller) {
9
+ controllers.add(controller);
10
+ if (!(controllerSymbol in controller) && component.renderRoot && component.el.isConnected) {
11
+ controller.hostConnected?.();
12
+ }
13
+ }
14
+ function removeController(controller) {
15
+ void controllers.delete(controller);
16
+ controller.controllerRemoved?.();
17
+ }
18
+ const controllerHost = component;
19
+ controllerHost.addController = addController;
20
+ controllerHost.removeController = removeController;
21
+ if (process.env.NODE_ENV !== "production" && isEsriInternalEnv()) {
22
+ const stencilToLitMapping = {
23
+ componentDidLoad: "loaded",
24
+ componentDidRender: "updated",
25
+ componentDidUpdate: "updated",
26
+ componentShouldUpdate: "shouldUpdate",
27
+ componentWillLoad: "load",
28
+ componentWillRender: "willUpdate",
29
+ componentWillUpdate: "willUpdate"
30
+ };
31
+ Object.entries(stencilToLitMapping).forEach(([stencilMethod, litMethod]) => {
32
+ if (isLit && stencilMethod in component) {
33
+ throw new Error(
34
+ `Unexpected ${stencilMethod}() in a Lit component ${component.el.localName}. In Lit, you should use ${litMethod}() instead`
35
+ );
36
+ }
37
+ });
38
+ if (isLit) {
39
+ let i = 0;
40
+ let isLitElementClass = false;
41
+ for (let prototype = component; !isLitElementClass; i++) {
42
+ if (prototype === null) {
43
+ throw new Error("Expected controllers to be used in a LitElement class");
44
+ }
45
+ if (Object.hasOwn(prototype, "_load")) {
46
+ isLitElementClass = true;
47
+ break;
48
+ }
49
+ prototype = Object.getPrototypeOf(prototype);
50
+ }
51
+ if (i < 1) {
52
+ throw new Error(
53
+ "It looks like you are trying to call useControllerManager in a component that uses LitElement imported from 'lit'. useControllerManager should only be used in the LitElement coming from `@arcgis/lumina`"
54
+ );
55
+ }
56
+ }
57
+ }
58
+ super(component);
59
+ this.internals = new ComponentInternals(this.component);
60
+ this.destroyed = false;
61
+ this._updatePromise = new Deferred();
62
+ this._originalLifecycles = {};
63
+ this.isLit = isLit;
64
+ this.component.manager = this;
65
+ retrieveComponentMembers(component, isLit);
66
+ this._controllers = controllers;
67
+ this.exports = void 0;
68
+ this.hasDestroy = autoDestroyDisabledPropName in this.component && typeof this.component.destroy === "function";
69
+ this._bindLifecycleMethods();
70
+ const internals = this.internals;
71
+ Object.keys(internals.members).forEach((name) => {
72
+ internals.accessorGetter[name] = defaultGetterSetter;
73
+ internals.accessorSetter[name] = defaultGetterSetter;
74
+ internals.getSetProxy(name);
75
+ });
76
+ if (isLit) {
77
+ this.internals.enabledWatchers = this.internals.allWatchers;
78
+ } else {
79
+ Object.defineProperty(component, "updateComplete", {
80
+ get: async () => await this._updatePromise.promise
81
+ });
82
+ }
83
+ queueMicrotask(internals.enableReadonly);
84
+ setAmbientComponent(component);
85
+ elementToInstance.set(component.el, component);
86
+ elementToInstance.set(component, component);
87
+ }
88
+ _bindLifecycleMethods() {
89
+ const component = this.component;
90
+ const isLit = this.isLit;
91
+ const isStencilDistBuild = component.el === component;
92
+ this._originalLifecycles = {
93
+ // These component's callbacks will be called by Lit, so we don't have to
94
+ _connectedCallback: isLit || isStencilDistBuild ? void 0 : component.connectedCallback,
95
+ _disconnectedCallback: isLit || isStencilDistBuild ? void 0 : component.disconnectedCallback,
96
+ _load: isLit ? component.load : component.componentWillLoad,
97
+ _loaded: isLit ? component.loaded : component.componentDidLoad,
98
+ _willUpdate: isLit ? void 0 : component.componentWillUpdate,
99
+ _updated: isLit ? void 0 : component.componentDidUpdate,
100
+ _destroy: component.destroy
101
+ };
102
+ const hostConnected = this._connectedCallback.bind(this);
103
+ const hostDisconnected = this._disconnectedCallback.bind(this);
104
+ const hostUpdate = this._update.bind(this);
105
+ const hostUpdated = this._updated.bind(this);
106
+ if (isLit) {
107
+ component.constructor.prototype.addController.call(component, {
108
+ // Lit will call these callbacks
109
+ hostConnected,
110
+ hostDisconnected,
111
+ hostUpdate,
112
+ hostUpdated
113
+ });
114
+ } else {
115
+ component.connectedCallback = hostConnected;
116
+ component.disconnectedCallback = hostDisconnected;
117
+ component.componentWillLoad = this._load.bind(this);
118
+ component.componentDidLoad = this._loaded.bind(this);
119
+ component.componentWillUpdate = hostUpdate;
120
+ component.componentDidUpdate = hostUpdated;
121
+ }
122
+ if (this.hasDestroy) {
123
+ component.destroy = this.destroy.bind(this);
124
+ }
125
+ }
126
+ /**
127
+ * Private because this is not supposed to be called by Component directly.
128
+ * Instead, _bindLifecycleMethods will take care of that. Otherwise, you risk
129
+ * calling lifecycle methods twice.
130
+ *
131
+ * @internal
132
+ */
133
+ _connectedCallback() {
134
+ if (this.destroyed) {
135
+ const tagName = this.component.el.localName;
136
+ this.component.el.remove();
137
+ throw new Error(
138
+ `The ${tagName} component has already been destroyed. It cannot be used again. If you meant to disconnect and reconnect a component without automatic destroy, set the ${autoDestroyDisabledPropName} prop.`
139
+ );
140
+ }
141
+ if (this._autoDestroyTimeout !== void 0) {
142
+ clearTimeout(this._autoDestroyTimeout);
143
+ }
144
+ const internals = this.internals;
145
+ internals.enabledWatchers = internals.allWatchers;
146
+ keyTrackResolve();
147
+ internals.enableReadonly?.();
148
+ this._controllers.forEach(callConnected);
149
+ this._originalLifecycles._connectedCallback?.call(this.component);
150
+ if (process.env.NODE_ENV !== "production" && isEsriInternalEnv()) {
151
+ devOnlySetPersistentControllerData?.(this, true);
152
+ }
153
+ }
154
+ /** @internal */
155
+ _disconnectedCallback() {
156
+ if (this.destroyed) {
157
+ return;
158
+ }
159
+ this._controllers.forEach(callDisconnected);
160
+ this._originalLifecycles._disconnectedCallback?.call(this.component);
161
+ if (this.hasDestroy) {
162
+ this._setAutoDestroyTimeout();
163
+ }
164
+ }
165
+ /** @internal */
166
+ async _load() {
167
+ await Promise.allSettled(Array.from(this._controllers, callLoad));
168
+ await this._originalLifecycles._load?.call(this.component);
169
+ if (this.hasDestroy) {
170
+ watch(this.component, autoDestroyDisabledPropName, () => this._setAutoDestroyTimeout());
171
+ }
172
+ }
173
+ /** @internal */
174
+ _loaded() {
175
+ this._controllers.forEach(callLoaded);
176
+ this._originalLifecycles._loaded?.call(this.component);
177
+ }
178
+ _update() {
179
+ const maybeLitComponent = this.component;
180
+ this._controllers.forEach(callUpdate, maybeLitComponent.$changes);
181
+ return this._originalLifecycles._willUpdate?.call(this.component);
182
+ }
183
+ _updated() {
184
+ const maybeLitComponent = this.component;
185
+ this._controllers.forEach(callUpdated, maybeLitComponent.$changes);
186
+ this._originalLifecycles._updated?.call(this.component);
187
+ if (this.isLit) {
188
+ maybeLitComponent.$changes = /* @__PURE__ */ new Map();
189
+ } else {
190
+ const updatePromise = this._updatePromise;
191
+ this._updatePromise = new Deferred();
192
+ updatePromise.resolve(true);
193
+ }
194
+ }
195
+ async destroy() {
196
+ if (process.env.NODE_ENV !== "production" && isEsriInternalEnv()) {
197
+ this.ensureHasDestroy?.();
198
+ }
199
+ if (this.destroyed) {
200
+ return;
201
+ }
202
+ if (this.component.el.isConnected) {
203
+ this.hasDestroy = false;
204
+ try {
205
+ this.component.el.remove();
206
+ } finally {
207
+ this.hasDestroy = true;
208
+ }
209
+ }
210
+ this._autoDestroyTimeout = void 0;
211
+ this.destroyed = true;
212
+ this._controllers.forEach(callDestroy);
213
+ this._controllers.clear();
214
+ await this._originalLifecycles._destroy?.call(this.component);
215
+ }
216
+ _setAutoDestroyTimeout() {
217
+ if (this._autoDestroyTimeout !== void 0) {
218
+ clearTimeout(this._autoDestroyTimeout);
219
+ }
220
+ if (!this.component.el.isConnected && !this.component.autoDestroyDisabled) {
221
+ const destroy = () => void this.destroy().catch(console.error);
222
+ if (process.env.NODE_ENV !== "production" && isEsriInternalEnv() && autoDestroyOnDisconnectTimeout === 0) ;
223
+ else {
224
+ this._autoDestroyTimeout = devToolsAwareTimeout(destroy, autoDestroyOnDisconnectTimeout);
225
+ }
226
+ }
227
+ }
228
+ }
229
+ if (process.env.NODE_ENV !== "production" && isEsriInternalEnv()) {
230
+ ControllerManager.prototype.ensureHasDestroy = function ensureHasDestroy() {
231
+ if (!this.hasDestroy) {
232
+ throw new Error(
233
+ `
234
+ If the component uses a controller that uses destroy() method, then the
235
+ component must have the following properties:
236
+ /**
237
+ * If true, the component will not be destroyed automatically when it is
238
+ * disconnected from the document. This is useful when you want to move the
239
+ * component to a different place on the page, or temporarily hide it. If this
240
+ * is set, make sure to call the \`destroy\` method when you are done to prevent
241
+ * memory leaks.
242
+ */
243
+ @${this.isLit ? "property" : "Prop"}() ${autoDestroyDisabledPropName} = false;
244
+
245
+ /** Permanently destroy the component */
246
+ @${this.isLit ? "method" : "Method"}()
247
+ async destroy(): Promise<void> {
248
+ await this.manager.destroy();
249
+ }
250
+ `.trim().split("\n").map((line) => line.trim()).join("\n")
251
+ );
252
+ }
253
+ };
254
+ }
255
+ const autoDestroyDisabledPropName = "autoDestroyDisabled";
256
+ let autoDestroyOnDisconnectTimeout = 1e3;
257
+ process.env.NODE_ENV !== "production" && isEsriInternalEnv() ? {} : void 0;
258
+ const defaultGetterSetter = (value) => value;
259
+ function callConnected(controller) {
260
+ if ("triggerConnected" in controller) {
261
+ controller.triggerConnected();
262
+ } else {
263
+ safeCall(controller.hostConnected, controller);
264
+ }
265
+ }
266
+ function callDisconnected(controller) {
267
+ if ("triggerDisconnected" in controller) {
268
+ controller.triggerDisconnected();
269
+ } else {
270
+ safeCall(controller.hostDisconnected, controller);
271
+ }
272
+ }
273
+ async function callLoad(controller) {
274
+ if ("triggerLoad" in controller) {
275
+ await controller.triggerLoad();
276
+ } else {
277
+ await safeAsyncCall(controller.hostLoad, controller);
278
+ }
279
+ }
280
+ function callLoaded(controller) {
281
+ if ("triggerLoaded" in controller) {
282
+ controller.triggerLoaded();
283
+ } else {
284
+ safeCall(controller.hostLoaded, controller);
285
+ }
286
+ }
287
+ function callUpdate(controller) {
288
+ if ("triggerUpdate" in controller) {
289
+ controller.triggerUpdate(this);
290
+ } else {
291
+ safeCall(controller.hostUpdate, controller, this);
292
+ }
293
+ }
294
+ function callUpdated(controller) {
295
+ if ("triggerUpdated" in controller) {
296
+ controller.triggerUpdated(this);
297
+ } else {
298
+ safeCall(controller.hostUpdated, controller, this);
299
+ }
300
+ }
301
+ function callDestroy(controller) {
302
+ if ("triggerDestroy" in controller) {
303
+ controller.triggerDestroy();
304
+ } else {
305
+ safeCall(controller.hostDestroy, controller);
306
+ }
307
+ }
308
+ export {
309
+ useControllerManager as u
310
+ };
@@ -1,8 +1,8 @@
1
1
  import { CSSResultGroup, CSSResultOrNative, PropertyValues, LitElement as OriginalLitElement } from 'lit';
2
- import { LuminaPropertyDeclaration } from '@arcgis/components-controllers';
3
- import { Runtime } from './runtime';
2
+ import { Runtime } from './makeRuntime';
4
3
  import { ProxyComponent } from './lazyLoad';
5
4
  import { ToElement } from './jsx/types';
5
+ import { LuminaPropertyDeclaration } from './controllers/types';
6
6
  type ComponentLifecycle = {
7
7
  connectedCallback?: () => void;
8
8
  disconnectedCallback?: () => void;
@@ -82,7 +82,7 @@ export declare class LitElement extends OriginalLitElement implements ComponentL
82
82
  * Controller Manager orchestrates all controllers used by this component,
83
83
  * connecting their lifecycle hooks and providing context information.
84
84
  */
85
- manager: import('@arcgis/components-controllers').ControllerManager<never>;
85
+ manager: import('./controllers').ControllerManager;
86
86
  /**
87
87
  * Map with keys for any properties that have changed since the last
88
88
  * update cycle with previous values.
package/dist/context.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { ControllerHost } from '@arcgis/components-controllers';
2
1
  import { ContextConsumer, ContextProvider, Context, ContextType } from '@lit/context';
2
+ import { ControllerHost } from './controllers/types';
3
3
  interface ContextProviderOptions<C extends Context<unknown, unknown>> {
4
4
  context: C;
5
5
  initialValue?: ContextType<C>;
@@ -0,0 +1,92 @@
1
+ import { BaseComponent, BaseController, ControllerHost } from './types';
2
+ export type TrackKeyResolution = {
3
+ readonly key: string;
4
+ readonly host: BaseComponent | BaseController;
5
+ /**
6
+ * True if property is decorated with `@State()` or `@Prop()` decorator
7
+ */
8
+ readonly isReactive: boolean;
9
+ };
10
+ /**
11
+ * Like ControllerInternals, but specific to each instance of a component
12
+ *
13
+ * @internal
14
+ */
15
+ export declare class ComponentInternals {
16
+ /**
17
+ * When watchers are set, they are set into `allWatchers`. When watchers are
18
+ * read in the setter, they are read from `enabledWatchers`.
19
+ *
20
+ * In Stencil, on connectedCallback(), controller manager does
21
+ * `enabledWatchers=allWatchers`. Reasoning:
22
+ * - This disables watchers until connected callback (matches behavior of
23
+ * Stencil's watchers)
24
+ * - This removes the need for a check in the setter for whether the watchers
25
+ * were enabled already or not (as getters/setters are hot path, and should
26
+ * be streamlined)
27
+ *
28
+ * In Lit, we set enabledWatchers to allWatchers in the constructor.
29
+ * Reasoning:
30
+ * - While in Stencil all user provided properties are either set before the
31
+ * component constructor (this is possible since Stencil's props store is
32
+ * externalized) or after connectedCallback, in Lit the properties may be
33
+ * set by attributeChangedCallback before connectedCallback. Thus, we need
34
+ * to enable watchers even before connectedCallback.
35
+ * - This means, that a watcher set for some prop before your component got
36
+ * a chance to set the default value will trigger the watcher when the
37
+ * default value is set - but, that is inline with Lit's willUpdate behavior
38
+ * of triggering for default values AND, the only way to set a watcher
39
+ * before default value is if you called watcher inside a controller. For
40
+ * now, there are no controllers written outside of arcgis-map-components
41
+ * package, so I was able to verify that this change would have no
42
+ * negative impact.
43
+ *
44
+ * In either way, I plan to remove watchers from controllers once Stencil
45
+ * support is removed.
46
+ */
47
+ enabledWatchers: Watchers;
48
+ allWatchers: Watchers;
49
+ readonly component: BaseComponent & ControllerHost;
50
+ /**
51
+ * Do not use this directly as it may break on framework updates.
52
+ * Instead, use helpers like getPropMembers() and getPropType()
53
+ */
54
+ members: Record<string, [number, string?]>;
55
+ constructor(component: BaseComponent & ControllerHost);
56
+ /**
57
+ * "readOnly" is not enabled initially since we need to allow to set property
58
+ * default values in the constructor.
59
+ * For Stencil, readonly is enabled by the `readonly()` controller.
60
+ * For Lit, we have the following logic:
61
+ */
62
+ enableReadonly: (() => void) | undefined;
63
+ trackedValue: unknown;
64
+ keyTrackers: ((key: string | undefined, value: unknown) => void)[];
65
+ firePropTrackers(key: string | undefined, value: unknown): void;
66
+ readonly getters: Record<string, ((value: unknown, propertyName: string) => unknown)[] | undefined>;
67
+ readonly setters: Record<string, ((newValue: unknown, oldValue: unknown, propertyName: string) => unknown)[] | undefined>;
68
+ readonly accessorGetter: Record<string, (value: unknown, propertyName: string) => unknown>;
69
+ readonly accessorSetter: Record<string, (newValue: unknown, oldValue: unknown, propertyName: string) => unknown>;
70
+ /**
71
+ * Configure a getter or setter for a given \@Prop/\@State
72
+ *
73
+ * Since props are defined on the prototype, they are shared between all
74
+ * instances of a component. Thus, instead of passing a reference to the
75
+ * getter/setter function, you should update the
76
+ * ComponentInternals.getters/setters properties, and then call getSetProxy
77
+ * to apply the changes to the prototype
78
+ */
79
+ getSetProxy(property: string): void;
80
+ private _getSetProxy;
81
+ private _exports;
82
+ /**
83
+ * Associate an exports object with a controller for reverse lookup in
84
+ * controller.use
85
+ */
86
+ markExports(controller: BaseController, exports: unknown): void;
87
+ resolveExports(exports: unknown): BaseController | undefined;
88
+ readonlySetter: <T>(newValue: T, _oldValue: T, property: string) => T;
89
+ }
90
+ type Watchers = Record<string, ((newValue: unknown, oldValue: unknown, propertyName: string) => void)[] | undefined>;
91
+ export declare const nothing: symbol;
92
+ export {};
@@ -0,0 +1,152 @@
1
+ import { Deferred } from '@arcgis/components-utils';
2
+ import { BaseComponent, BaseController, ControllerHost, ControllerLifecycleMethods, controllerSymbol } from './types';
3
+ import { use, useRef, useRefSync } from './ControllerInternals';
4
+ import { PropertyValues } from 'lit';
5
+ /**
6
+ * Base class for Controllers defined using a class rather than a function.
7
+ * Defining controller using makeController() function is more succinct for smaller
8
+ * controllers. For controllers that need to declare several methods, or need
9
+ * more flexibility, this class may be used
10
+ *
11
+ * See ./examples.tsx for many example controllers and their usages.
12
+ */
13
+ export declare abstract class Controller<Exports = never> implements BaseController {
14
+ protected _callbacks: {
15
+ readonly [KEY in keyof Omit<ControllerLifecycleMethods, "controllerRemoved">]-?: NonNullable<ControllerLifecycleMethods[KEY]>[];
16
+ };
17
+ protected _ready: Deferred<Exports>;
18
+ private _lifecycleCleanups;
19
+ /** @internal */
20
+ assignedProperty?: string | false;
21
+ connectedCalled: boolean;
22
+ protected _loadCalled: boolean;
23
+ loadedCalled: boolean;
24
+ readonly [controllerSymbol] = true;
25
+ component: BaseComponent & ControllerHost;
26
+ ready: Promise<Exports>;
27
+ constructor(component?: BaseComponent);
28
+ /**
29
+ * If controller is being added dynamically, after the component
30
+ * construction, then trigger connected and load right away
31
+ */
32
+ catchUpLifecycle(): void;
33
+ private _exports;
34
+ get exports(): Exports;
35
+ /**
36
+ * Set controller's exports property (for usage with proxyExports()) and mark
37
+ * controller as ready (for usage in other controllers). Also, triggers
38
+ * re-render of the component
39
+ */
40
+ set exports(exports: Exports);
41
+ /**
42
+ * If controller needs to await a promise before it's exports are fully ready
43
+ * but it wishes to make some limited exports available before then,
44
+ * this method can be used.
45
+ *
46
+ * This is useful for permitting a limited usage of the controller in default
47
+ * values of properties or in component constructor.
48
+ *
49
+ * In order to help detect bugs, trying to access a prop on the exports value
50
+ * that does not exist will throw an error (in development only). This is
51
+ * useful to detect usages of controller that forgot to await it's exports.
52
+ * (the "value in this.myController" check won't cause an exception though)
53
+ *
54
+ * @param proxy [true] - whether to throw an error if unknown property is
55
+ * accessed before the controller is loaded.
56
+ */
57
+ setProvisionalExports(exports: Exports, proxy?: boolean): void;
58
+ setProvisionalExports(exports: Exports extends object ? Partial<Exports> : Exports, proxy?: boolean): void;
59
+ setProvisionalExports<Props extends keyof Exports>(exports: Pick<Exports, Props>, proxy?: boolean): void;
60
+ private _exportWatchers;
61
+ watchExports(callback: (exports: Exports) => void): () => void;
62
+ /**
63
+ * A flexible utility for making sure a controller is loaded before it's used,
64
+ * regardless of how or where a controller was defined:
65
+ *
66
+ * @example
67
+ * makeGenericController(async (component, controller) => {
68
+ * // Await some controller from the component:
69
+ * await controller.use(component.someController);
70
+ * // Initialize new controllers
71
+ * await controller.use(load(importCoreReactiveUtils));
72
+ * await controller.use(new ViewModelController(component,newWidgetsHomeHomeViewModel));
73
+ * await controller.use(someController(component));
74
+ * });
75
+ *
76
+ * @remarks
77
+ * If your controller is not async, and you are not creating it async, then
78
+ * you are not required to use controller.use - you can use it directly.
79
+ * Similarly, accessing controllers after componentWillLoad callback does not
80
+ * require awaiting them as they are guaranteed to be loaded by then.
81
+ */
82
+ get use(): typeof use;
83
+ /**
84
+ * Just like controller.use, but returns the controller itself, rather than it's
85
+ * exports
86
+ *
87
+ * Use cases:
88
+ * - You have a controller and you want to make sure it's loaded before you
89
+ * try to use it
90
+ * - Your controller is not using exports, so you wish to access some props on
91
+ * it directly
92
+ * - You have a controller exports only, and you want to retrieve the
93
+ * controller itself. This is useful if you wish to call .watchExports() or
94
+ * some other method on the controller
95
+ */
96
+ get useRef(): typeof useRef;
97
+ /**
98
+ * Like useRef, but doesn't wait for the controller to get ready
99
+ *
100
+ * @internal
101
+ */
102
+ get useRefSync(): typeof useRefSync;
103
+ controllerRemoved(): void;
104
+ onConnected(callback: NonNullable<ControllerLifecycleMethods["hostConnected"]>): void;
105
+ onDisconnected(callback: NonNullable<ControllerLifecycleMethods["hostDisconnected"]>): void;
106
+ onLoad(callback: NonNullable<ControllerLifecycleMethods["hostLoad"]>): void;
107
+ onLoaded(callback: NonNullable<ControllerLifecycleMethods["hostLoaded"]>): void;
108
+ onUpdate(callback: NonNullable<ControllerLifecycleMethods["hostUpdate"]>): void;
109
+ onUpdated(callback: NonNullable<ControllerLifecycleMethods["hostUpdated"]>): void;
110
+ onDestroy(callback: NonNullable<ControllerLifecycleMethods["hostDestroy"]>): void;
111
+ onLifecycle(callback: NonNullable<ControllerLifecycleMethods["hostLifecycle"]>): void;
112
+ /** @internal */
113
+ triggerConnected(): void;
114
+ /** @internal */
115
+ triggerDisconnected(): void;
116
+ /** @internal */
117
+ triggerLoad(): Promise<void>;
118
+ /** @internal */
119
+ triggerLoaded(): void;
120
+ /** @internal */
121
+ triggerUpdate(changes: PropertyValues): void;
122
+ /** @internal */
123
+ triggerUpdated(changes: PropertyValues): void;
124
+ /** @internal */
125
+ triggerDestroy(): void;
126
+ /** @internal */
127
+ triggerLifecycle(): void;
128
+ private _callLifecycle;
129
+ }
130
+ export declare abstract class GenericControllerType<Exports, Requires = BaseComponent> extends Controller<Exports> {
131
+ component: BaseComponent & ControllerHost & Requires;
132
+ constructor(component: BaseComponent & Requires);
133
+ }
134
+ /**
135
+ * If your controller requires some specific properties to be present on the
136
+ * component, besides what's included in the BaseComponent, use
137
+ * GenericController over the usual Controller. Use the 2nd generic argument
138
+ * on this class for specifying what properties your controller expects on the
139
+ * component
140
+ *
141
+ * When using a controller created using GenericController, consumer must
142
+ * pass in "this" explicitly to the constructor. If controller was
143
+ * created using Controller, that is not necessary
144
+ *
145
+ * @remarks
146
+ * GenericController class is identical to Controller class in all but typing.
147
+ * That is why, at runtime GenericController is actually equal to Controller
148
+ * class.
149
+ * You can use GenericControllerType type if you wish to reference generic
150
+ * controller instance type.
151
+ */
152
+ export declare const GenericController: typeof GenericControllerType;
@@ -0,0 +1,52 @@
1
+ import { Controller } from './Controller';
2
+ import { BaseComponent, BaseController, ControllerHost } from './types';
3
+ export declare function setAmbientComponent(component: BaseComponent & ControllerHost): void;
4
+ export declare function retrieveComponent(name?: string): BaseComponent & ControllerHost;
5
+ export declare function setParentController(controller: BaseController | undefined): void;
6
+ /**
7
+ * Get references to controllers this nested controller might have been called
8
+ * from. The list may include extra controllers, but at least one of them or
9
+ * the component itself is the parent for this controller.
10
+ */
11
+ export declare function retrieveParentControllers(): readonly BaseController[];
12
+ export declare function setAmbientChildController(controller: BaseController | undefined): void;
13
+ /**
14
+ * The type definition has to be duplicated due to this TypeScript error:
15
+ * "'use' is referenced directly or indirectly in its own type annotation."
16
+ */
17
+ export declare const use: <Value>(value: Value, watchExports?: (value: NotNever<InferController<Value>>, unsubscribe: () => void) => void) => Promise<NotNever<InferController<Value>>>;
18
+ export declare const useRef: <Value>(value: Value) => Promise<InferController<Value>>;
19
+ export declare const useRefSync: <Value>(value: Value) => InferController<Value> | undefined;
20
+ export declare const shouldBypass: {
21
+ setter: boolean;
22
+ getter: boolean;
23
+ readOnly: boolean;
24
+ };
25
+ /**
26
+ * A map from component instance or component element to component instance.
27
+ * To get from component instance or component element to component element,
28
+ * you can just use the .el property
29
+ */
30
+ export declare const elementToInstance: WeakMap<HTMLElement | BaseComponent, BaseComponent>;
31
+ /**
32
+ * If passed value is a controller, then return it. Otherwise, assume it's a
33
+ * proxyExports() result and wrap it into a controller
34
+ *
35
+ * This won't type correctly if a proxyExports() controller is exporting a
36
+ * non-proxyExports() controller
37
+ */
38
+ type InferController<ControllerOrExports> = ControllerOrExports extends BaseController ? ControllerOrExports & {
39
+ exports?: unknown;
40
+ ready?: Promise<void>;
41
+ watchExports?: Controller["watchExports"];
42
+ } : Controller<ControllerOrExports>;
43
+ /**
44
+ * If controller never sets it's exports, then it's default exports is "this".
45
+ * This allows usage of controller.use with controllers that don't have exports
46
+ */
47
+ type NotNever<T extends {
48
+ exports?: any;
49
+ }> = T extends {
50
+ exports: never;
51
+ } ? T : T["exports"];
52
+ export {};