@contentful/app-sdk 5.0.0-alpha.1 → 5.0.0-alpha.3
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/README.md +1 -7
- package/dist/api.js +109 -0
- package/dist/app.d.ts +2 -1
- package/dist/app.js +99 -0
- package/dist/channel.js +111 -0
- package/dist/cma.js +16 -0
- package/dist/cmaAdapter.js +12 -0
- package/dist/dialogs.js +37 -0
- package/dist/editor.js +29 -0
- package/dist/entry.js +60 -0
- package/dist/field-locale.js +70 -0
- package/dist/field.js +77 -0
- package/dist/index.js +23 -0
- package/dist/initialize.js +64 -0
- package/dist/locations.js +13 -0
- package/dist/navigator.js +62 -0
- package/dist/signal.js +51 -0
- package/dist/types/api.types.d.ts +1 -9
- package/dist/types/api.types.js +2 -0
- package/dist/types/app.types.d.ts +6 -10
- package/dist/types/app.types.js +2 -0
- package/dist/types/cmaClient.types.js +2 -0
- package/dist/types/dialogs.types.js +2 -0
- package/dist/types/entities.js +2 -0
- package/dist/types/entry.types.d.ts +0 -5
- package/dist/types/entry.types.js +2 -0
- package/dist/types/field-locale.types.js +2 -0
- package/dist/types/field.types.js +2 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/navigator.types.d.ts +12 -2
- package/dist/types/navigator.types.js +2 -0
- package/dist/types/utils.js +2 -0
- package/dist/types/validation-error.js +2 -0
- package/dist/types/window.types.js +2 -0
- package/dist/utils/deferred.js +20 -0
- package/dist/window.js +106 -0
- package/package.json +118 -1
- package/dist/README.md +0 -9
- package/dist/cf-extension-api.bundled.js +0 -1
- package/dist/cf-extension-api.js +0 -1
- package/dist/cf-extension.css +0 -600
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.init = exports.locations = void 0;
|
|
18
|
+
const initialize_1 = require("./initialize");
|
|
19
|
+
const api_1 = require("./api");
|
|
20
|
+
__exportStar(require("./types"), exports);
|
|
21
|
+
var locations_1 = require("./locations");
|
|
22
|
+
Object.defineProperty(exports, "locations", { enumerable: true, get: function () { return locations_1.default; } });
|
|
23
|
+
exports.init = (0, initialize_1.createInitializer)(globalThis, api_1.default);
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createInitializer = void 0;
|
|
4
|
+
const channel_1 = require("./channel");
|
|
5
|
+
const deferred_1 = require("./utils/deferred");
|
|
6
|
+
function createInitializer(currentGlobal, apiCreator) {
|
|
7
|
+
if (typeof currentGlobal.window === 'undefined' ||
|
|
8
|
+
typeof currentGlobal.document === 'undefined') {
|
|
9
|
+
// make `init` a noop if window or document is not available
|
|
10
|
+
return () => { };
|
|
11
|
+
}
|
|
12
|
+
const connectDeferred = (0, deferred_1.createDeferred)();
|
|
13
|
+
connectDeferred.promise.then(([channel]) => {
|
|
14
|
+
const { document } = currentGlobal;
|
|
15
|
+
document.addEventListener('focus', () => channel.send('setActive', true), true);
|
|
16
|
+
document.addEventListener('blur', () => channel.send('setActive', false), true);
|
|
17
|
+
});
|
|
18
|
+
// We need to connect right away so we can record incoming
|
|
19
|
+
// messages before `init` is called.
|
|
20
|
+
(0, channel_1.connect)(currentGlobal, (...args) => connectDeferred.resolve(args));
|
|
21
|
+
let initializedSdks;
|
|
22
|
+
return function init(initCb, { makeCustomApi, supressIframeWarning, } = {
|
|
23
|
+
supressIframeWarning: false,
|
|
24
|
+
}) {
|
|
25
|
+
if (!supressIframeWarning) {
|
|
26
|
+
warnIfOutsideOfContentful(currentGlobal);
|
|
27
|
+
}
|
|
28
|
+
if (!initializedSdks) {
|
|
29
|
+
initializedSdks = connectDeferred.promise.then(([channel, params, messageQueue]) => {
|
|
30
|
+
const api = apiCreator(channel, params, currentGlobal);
|
|
31
|
+
let customApi;
|
|
32
|
+
if (typeof makeCustomApi === 'function') {
|
|
33
|
+
customApi = makeCustomApi(channel, params);
|
|
34
|
+
}
|
|
35
|
+
// Handle pending incoming messages.
|
|
36
|
+
// APIs are created before so handlers are already
|
|
37
|
+
// registered on the channel.
|
|
38
|
+
messageQueue.forEach((m) => {
|
|
39
|
+
// TODO Expose private handleMessage method
|
|
40
|
+
;
|
|
41
|
+
channel._handleMessage(m);
|
|
42
|
+
});
|
|
43
|
+
return [api, customApi];
|
|
44
|
+
});
|
|
45
|
+
if (!connectDeferred.isFulfilled) {
|
|
46
|
+
(0, channel_1.sendInitMessage)(currentGlobal);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
initializedSdks.then(([sdk, customSdk]) =>
|
|
50
|
+
// Hand over control to the developer.
|
|
51
|
+
initCb(sdk, customSdk));
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
exports.createInitializer = createInitializer;
|
|
55
|
+
function warnIfOutsideOfContentful(currentGlobal) {
|
|
56
|
+
if (currentGlobal.self === currentGlobal.top) {
|
|
57
|
+
console.error(`Cannot use App SDK outside of Contenful:
|
|
58
|
+
|
|
59
|
+
In order for the App SDK to function correctly, your app needs to be run in an iframe in the Contentful Web App, Compose or Launch.
|
|
60
|
+
|
|
61
|
+
Learn more about local development with the App SDK here:
|
|
62
|
+
https://www.contentful.com/developers/docs/extensibility/ui-extensions/faq/#how-can-i-develop-with-the-ui-extension-sdk-locally`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const locations = {
|
|
4
|
+
LOCATION_ENTRY_FIELD: 'entry-field',
|
|
5
|
+
LOCATION_ENTRY_FIELD_SIDEBAR: 'entry-field-sidebar',
|
|
6
|
+
LOCATION_ENTRY_SIDEBAR: 'entry-sidebar',
|
|
7
|
+
LOCATION_DIALOG: 'dialog',
|
|
8
|
+
LOCATION_ENTRY_EDITOR: 'entry-editor',
|
|
9
|
+
LOCATION_PAGE: 'page',
|
|
10
|
+
LOCATION_APP_CONFIG: 'app-config',
|
|
11
|
+
LOCATION_HOME: 'home',
|
|
12
|
+
};
|
|
13
|
+
exports.default = locations;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const signal_1 = require("./signal");
|
|
4
|
+
function createNavigator(channel, ids) {
|
|
5
|
+
const _onSlideInSignal = new signal_1.Signal();
|
|
6
|
+
channel.addHandler('navigateSlideIn', (data) => {
|
|
7
|
+
_onSlideInSignal.dispatch(data);
|
|
8
|
+
});
|
|
9
|
+
return {
|
|
10
|
+
openEntry: (id, opts) => {
|
|
11
|
+
return channel.call('navigateToContentEntity', {
|
|
12
|
+
...opts,
|
|
13
|
+
entityType: 'Entry',
|
|
14
|
+
id,
|
|
15
|
+
});
|
|
16
|
+
},
|
|
17
|
+
openNewEntry: (contentTypeId, opts) => {
|
|
18
|
+
return channel.call('navigateToContentEntity', {
|
|
19
|
+
...opts,
|
|
20
|
+
entityType: 'Entry',
|
|
21
|
+
id: null,
|
|
22
|
+
contentTypeId,
|
|
23
|
+
});
|
|
24
|
+
},
|
|
25
|
+
openBulkEditor: (entryId, opts) => {
|
|
26
|
+
return channel.call('navigateToBulkEditor', {
|
|
27
|
+
entryId,
|
|
28
|
+
...opts,
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
openAsset: (id, opts) => {
|
|
32
|
+
return channel.call('navigateToContentEntity', {
|
|
33
|
+
...opts,
|
|
34
|
+
entityType: 'Asset',
|
|
35
|
+
id,
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
openNewAsset: (opts) => {
|
|
39
|
+
return channel.call('navigateToContentEntity', {
|
|
40
|
+
...opts,
|
|
41
|
+
entityType: 'Asset',
|
|
42
|
+
id: null,
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
openPage: (opts) => {
|
|
46
|
+
return channel.call('navigateToPage', { type: 'app', id: ids.app, ...opts });
|
|
47
|
+
},
|
|
48
|
+
openAppConfig: () => {
|
|
49
|
+
return channel.call('navigateToAppConfig');
|
|
50
|
+
},
|
|
51
|
+
openEntriesList: (options = {}) => {
|
|
52
|
+
return channel.call('navigateToSpaceEnvRoute', { route: 'entries', options });
|
|
53
|
+
},
|
|
54
|
+
openAssetsList: (options = {}) => {
|
|
55
|
+
return channel.call('navigateToSpaceEnvRoute', { route: 'assets', options });
|
|
56
|
+
},
|
|
57
|
+
onSlideInNavigation: (handler) => {
|
|
58
|
+
return _onSlideInSignal.attach(handler);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
exports.default = createNavigator;
|
package/dist/signal.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MemoizedSignal = exports.Signal = void 0;
|
|
4
|
+
class Signal {
|
|
5
|
+
constructor() {
|
|
6
|
+
this._id = 0;
|
|
7
|
+
this._listeners = {};
|
|
8
|
+
}
|
|
9
|
+
dispatch(...args) {
|
|
10
|
+
for (const key in this._listeners) {
|
|
11
|
+
this._listeners[key](...args);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
attach(listener) {
|
|
15
|
+
if (typeof listener !== 'function') {
|
|
16
|
+
throw new Error('listener function expected');
|
|
17
|
+
}
|
|
18
|
+
const id = this._id++;
|
|
19
|
+
this._listeners[id] = listener;
|
|
20
|
+
// return function that'll detach the listener
|
|
21
|
+
return () => delete this._listeners[id];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.Signal = Signal;
|
|
25
|
+
class MemoizedSignal extends Signal {
|
|
26
|
+
constructor(...memoizedArgs) {
|
|
27
|
+
super();
|
|
28
|
+
if (!memoizedArgs.length) {
|
|
29
|
+
throw new Error('Initial value to be memoized expected');
|
|
30
|
+
}
|
|
31
|
+
this._memoizedArgs = memoizedArgs;
|
|
32
|
+
}
|
|
33
|
+
dispatch(...args) {
|
|
34
|
+
this._memoizedArgs = args;
|
|
35
|
+
super.dispatch(...args);
|
|
36
|
+
}
|
|
37
|
+
attach(listener) {
|
|
38
|
+
/*
|
|
39
|
+
* attaching first so that we throw a sensible
|
|
40
|
+
* error if listener is not a function without
|
|
41
|
+
* duplication of is function check
|
|
42
|
+
*/
|
|
43
|
+
const detachListener = super.attach(listener);
|
|
44
|
+
listener(...this._memoizedArgs);
|
|
45
|
+
return detachListener;
|
|
46
|
+
}
|
|
47
|
+
getMemoizedArgs() {
|
|
48
|
+
return this._memoizedArgs;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.MemoizedSignal = MemoizedSignal;
|
|
@@ -122,14 +122,6 @@ export interface SharedEditorSDK {
|
|
|
122
122
|
* @returns Function to unsubscribe. `callback` won't be called anymore.
|
|
123
123
|
*/
|
|
124
124
|
onLocaleSettingsChanged: (callback: (localeSettings: EditorLocaleSettings) => void) => () => void;
|
|
125
|
-
/**
|
|
126
|
-
* Subscribes to changes of whether or not disabled fields are displayed
|
|
127
|
-
*
|
|
128
|
-
* @param callback Function that is called every time the setting whether or not disabled fields are displayed changes. Called immediately with the current state.
|
|
129
|
-
* @returns Function to unsubscribe. `callback` won't be called anymore.
|
|
130
|
-
* @deprecated Use {@link onShowHiddenFieldsChanged} instead
|
|
131
|
-
*/
|
|
132
|
-
onShowDisabledFieldsChanged: (callback: (showDisabledFields: boolean) => void) => () => void;
|
|
133
125
|
/**
|
|
134
126
|
* Returns whether or not hidden fields are displayed
|
|
135
127
|
*
|
|
@@ -236,7 +228,7 @@ export type ConfigAppSDK<InstallationParameters extends KeyValueMap = KeyValueMa
|
|
|
236
228
|
ids: Omit<IdsAPI, EntryScopedIds | 'app'> & {
|
|
237
229
|
app: string;
|
|
238
230
|
};
|
|
239
|
-
app: AppConfigAPI
|
|
231
|
+
app: AppConfigAPI<InstallationParameters>;
|
|
240
232
|
};
|
|
241
233
|
export type KnownAppSDK<InstallationParameters extends KeyValueMap = KeyValueMap, InstanceParameters extends KeyValueMap = KeyValueMap, InvocationParameters extends SerializedJSONValue = SerializedJSONValue> = FieldAppSDK<InstallationParameters, InstanceParameters> | SidebarAppSDK<InstallationParameters, InstanceParameters> | DialogAppSDK<InstallationParameters, InvocationParameters> | EditorAppSDK<InstallationParameters, InstanceParameters> | PageAppSDK<InstallationParameters> | ConfigAppSDK<InstallationParameters> | HomeAppSDK<InstallationParameters>;
|
|
242
234
|
export interface ConnectMessage {
|
|
@@ -12,20 +12,16 @@ interface AppStateEditorInterfaceItem {
|
|
|
12
12
|
position: number;
|
|
13
13
|
settings?: Record<string, any>;
|
|
14
14
|
};
|
|
15
|
-
/**
|
|
16
|
-
* @deprecated use `editors` instead
|
|
17
|
-
*/
|
|
18
|
-
editor?: boolean;
|
|
19
15
|
}
|
|
20
16
|
export interface AppState {
|
|
21
17
|
EditorInterface: Record<ContentType['sys']['id'], AppStateEditorInterfaceItem>;
|
|
22
18
|
}
|
|
23
|
-
export type OnConfigureHandlerReturn = {
|
|
24
|
-
parameters?:
|
|
19
|
+
export type OnConfigureHandlerReturn<InstallationParameters extends KeyValueMap> = {
|
|
20
|
+
parameters?: InstallationParameters | null;
|
|
25
21
|
targetState?: AppState | null;
|
|
26
22
|
} | false;
|
|
27
|
-
export type OnConfigureHandler = () => OnConfigureHandlerReturn | Promise<OnConfigureHandlerReturn
|
|
28
|
-
export interface AppConfigAPI {
|
|
23
|
+
export type OnConfigureHandler<InstallationParameters extends KeyValueMap> = () => OnConfigureHandlerReturn<InstallationParameters> | Promise<OnConfigureHandlerReturn<InstallationParameters>>;
|
|
24
|
+
export interface AppConfigAPI<InstallationParameters extends KeyValueMap> {
|
|
29
25
|
/** Tells the web app that the app is loaded */
|
|
30
26
|
setReady: () => Promise<void>;
|
|
31
27
|
/** Returns true if an App is installed */
|
|
@@ -33,9 +29,9 @@ export interface AppConfigAPI {
|
|
|
33
29
|
/** Returns current state of an App */
|
|
34
30
|
getCurrentState: () => Promise<AppState | null>;
|
|
35
31
|
/** Returns parameters of an App, null otherwise */
|
|
36
|
-
getParameters:
|
|
32
|
+
getParameters: () => Promise<null | InstallationParameters>;
|
|
37
33
|
/** Registers a handler to be called to produce parameters for an App */
|
|
38
|
-
onConfigure: (handler: OnConfigureHandler) => void;
|
|
34
|
+
onConfigure: (handler: OnConfigureHandler<InstallationParameters>) => void;
|
|
39
35
|
/** Registers a handler to be called once configuration was finished */
|
|
40
36
|
onConfigurationCompleted: (handler: (err: null | {
|
|
41
37
|
message: string;
|
|
@@ -34,11 +34,6 @@ export interface EntryAPI extends TaskAPI {
|
|
|
34
34
|
fields: {
|
|
35
35
|
[key: string]: EntryFieldAPI;
|
|
36
36
|
};
|
|
37
|
-
/**
|
|
38
|
-
* Optional metadata on an entry
|
|
39
|
-
* @deprecated
|
|
40
|
-
*/
|
|
41
|
-
metadata?: Metadata;
|
|
42
37
|
getMetadata: () => Metadata | undefined;
|
|
43
38
|
onMetadataChanged: (callback: (metadata?: Metadata) => void) => VoidFunction;
|
|
44
39
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type { Asset, CanonicalRequest, ContentType, ContentTypeField, EditorInte
|
|
|
5
5
|
export type { EntryAPI, TaskAPI, TaskInputData } from './entry.types';
|
|
6
6
|
export type { FieldInfo, EntryFieldInfo, EntryFieldAPI } from './field.types';
|
|
7
7
|
export type { FieldAPI } from './field-locale.types';
|
|
8
|
-
export type { NavigatorAPI, AppPageLocationOptions, NavigatorAPIOptions, NavigatorOpenResponse, NavigatorPageResponse, NavigatorSlideInfo, } from './navigator.types';
|
|
8
|
+
export type { NavigatorAPI, AppPageLocationOptions, NavigatorAPIOptions, NavigatorOpenResponse, NavigatorPageResponse, NavigatorSlideInfo, OpenEntriesListOptions, OpenAssetsListOptions, } from './navigator.types';
|
|
9
9
|
export type { SearchQuery, CollectionResponse, EntrySys, ContentEntitySys, ContentEntityType, FieldType, FieldLinkType, Items, Link, WithOptionalId, WithId, SerializedJSONValue, } from './utils';
|
|
10
10
|
export type { DateRangeValidationError, InValidationError, LinkContentTypeValidationError, LinkMimetypeGroupValidationError, NotResolvableValidationError, ProhibitRegexpValidationError, RangeValidationError, RegexpValidationError, RequiredValidationError, SizeValidationError, TypeValidationError, UniqueValidationError, UnknownValidationError, ValidationError, } from './validation-error';
|
|
11
11
|
export type { WindowAPI } from './window.types';
|
|
@@ -9,6 +9,16 @@ export interface AppPageLocationOptions {
|
|
|
9
9
|
/** A path to navigate to within your app's page location. */
|
|
10
10
|
path?: string;
|
|
11
11
|
}
|
|
12
|
+
export interface OpenEntriesListOptions {
|
|
13
|
+
filters?: {
|
|
14
|
+
contentType?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface OpenAssetsListOptions {
|
|
18
|
+
filters?: {
|
|
19
|
+
type?: 'attachment' | 'plaintext' | 'image' | 'audio' | 'video' | 'richtext' | 'presentation' | 'spreadsheet' | 'pdfdocument' | 'archive' | 'code' | 'markup';
|
|
20
|
+
};
|
|
21
|
+
}
|
|
12
22
|
/** Information about current value of the navigation status. */
|
|
13
23
|
export interface NavigatorPageResponse {
|
|
14
24
|
/** Will be true if navigation was successfully executed by the web app. */
|
|
@@ -49,7 +59,7 @@ export interface NavigatorAPI {
|
|
|
49
59
|
slide?: NavigatorSlideInfo;
|
|
50
60
|
}>;
|
|
51
61
|
openAppConfig: () => Promise<void>;
|
|
52
|
-
openEntriesList: () => Promise<void>;
|
|
53
|
-
openAssetsList: () => Promise<void>;
|
|
62
|
+
openEntriesList: (options?: OpenEntriesListOptions) => Promise<void>;
|
|
63
|
+
openAssetsList: (options?: OpenAssetsListOptions) => Promise<void>;
|
|
54
64
|
onSlideInNavigation: (fn: (slide: NavigatorSlideInfo) => void) => () => void;
|
|
55
65
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createDeferred = void 0;
|
|
4
|
+
function createDeferred() {
|
|
5
|
+
const deferred = {
|
|
6
|
+
// @ts-expect-error Immediately set below
|
|
7
|
+
promise: null,
|
|
8
|
+
// @ts-expect-error Promise executor is immdiately executed and sets `resolve`
|
|
9
|
+
resolve: null,
|
|
10
|
+
isFulfilled: false,
|
|
11
|
+
};
|
|
12
|
+
deferred.promise = new Promise((resolve) => {
|
|
13
|
+
deferred.resolve = (...args) => {
|
|
14
|
+
deferred.isFulfilled = true;
|
|
15
|
+
resolve(...args);
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
return deferred;
|
|
19
|
+
}
|
|
20
|
+
exports.createDeferred = createDeferred;
|
package/dist/window.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function createWindow(currentGlobal, channel) {
|
|
4
|
+
const { document, MutationObserver, ResizeObserver } = currentGlobal;
|
|
5
|
+
let oldHeight;
|
|
6
|
+
let isAutoResizing = false;
|
|
7
|
+
let checkAbsoluteElements = false;
|
|
8
|
+
const absolutePositionedElems = new Set();
|
|
9
|
+
const mutationObserver = new MutationObserver((mutations) => {
|
|
10
|
+
checkAbsolutePositionedElems(mutations);
|
|
11
|
+
if (isAutoResizing) {
|
|
12
|
+
self.updateHeight();
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
16
|
+
self.updateHeight();
|
|
17
|
+
});
|
|
18
|
+
mutationObserver.observe(document.body, {
|
|
19
|
+
attributes: true,
|
|
20
|
+
childList: true,
|
|
21
|
+
subtree: true,
|
|
22
|
+
characterData: true,
|
|
23
|
+
});
|
|
24
|
+
const self = { startAutoResizer, stopAutoResizer, updateHeight };
|
|
25
|
+
return self;
|
|
26
|
+
function checkAbsoluteElementStyle(type, element) {
|
|
27
|
+
const computedStyle = getComputedStyle(element);
|
|
28
|
+
if (computedStyle.position !== 'absolute') {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
switch (type) {
|
|
32
|
+
case 'attributes':
|
|
33
|
+
return computedStyle.display !== 'none';
|
|
34
|
+
default:
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function checkAbsolutePositionedElems(mutations) {
|
|
39
|
+
mutations.forEach((mutation) => {
|
|
40
|
+
switch (mutation.type) {
|
|
41
|
+
case 'attributes':
|
|
42
|
+
if (mutation.target.nodeType === Node.ELEMENT_NODE) {
|
|
43
|
+
const element = mutation.target;
|
|
44
|
+
if (checkAbsoluteElementStyle(mutation.type, element)) {
|
|
45
|
+
absolutePositionedElems.add(element);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
absolutePositionedElems.delete(element);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
break;
|
|
52
|
+
case 'childList':
|
|
53
|
+
mutation.addedNodes.forEach((node) => {
|
|
54
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
55
|
+
const element = node;
|
|
56
|
+
if (checkAbsoluteElementStyle(mutation.type, element)) {
|
|
57
|
+
absolutePositionedElems.add(element);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
mutation.removedNodes.forEach((node) => {
|
|
62
|
+
const element = node;
|
|
63
|
+
absolutePositionedElems.delete(element);
|
|
64
|
+
});
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function startAutoResizer({ absoluteElements = false } = {}) {
|
|
70
|
+
checkAbsoluteElements = Boolean(absoluteElements);
|
|
71
|
+
self.updateHeight();
|
|
72
|
+
if (isAutoResizing) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
isAutoResizing = true;
|
|
76
|
+
resizeObserver.observe(document.body);
|
|
77
|
+
}
|
|
78
|
+
function stopAutoResizer() {
|
|
79
|
+
if (!isAutoResizing) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
isAutoResizing = false;
|
|
83
|
+
resizeObserver.disconnect();
|
|
84
|
+
}
|
|
85
|
+
function updateHeight(height = null) {
|
|
86
|
+
if (height === null) {
|
|
87
|
+
const documentHeight = Math.ceil(document.documentElement.getBoundingClientRect().height);
|
|
88
|
+
// Only check for absolute elements if option is provided to startAutoResizer
|
|
89
|
+
if (checkAbsoluteElements && absolutePositionedElems.size) {
|
|
90
|
+
let maxHeight = documentHeight;
|
|
91
|
+
absolutePositionedElems.forEach((element) => {
|
|
92
|
+
maxHeight = Math.max(element.getBoundingClientRect().bottom, maxHeight);
|
|
93
|
+
});
|
|
94
|
+
height = maxHeight;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
height = documentHeight;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (height !== oldHeight) {
|
|
101
|
+
channel.send('setHeight', height);
|
|
102
|
+
oldHeight = height;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.default = createWindow;
|
package/package.json
CHANGED
|
@@ -1 +1,118 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"name": "@contentful/app-sdk",
|
|
3
|
+
"description": "A JavaScript library to develop custom apps for Contentful",
|
|
4
|
+
"version": "5.0.0-alpha.3",
|
|
5
|
+
"author": "Contentful GmbH",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"sideEffects": true,
|
|
8
|
+
"repository": {
|
|
9
|
+
"url": "https://github.com/contentful/ui-extensions-sdk.git",
|
|
10
|
+
"type": "git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://www.contentful.com/developers/docs/extensibility/app-framework/sdk/",
|
|
13
|
+
"main": "dist/index.js",
|
|
14
|
+
"types": "dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"clean": "rimraf dist",
|
|
20
|
+
"test": "ts-mocha -p tsconfig.test.json 'test/unit/*.[jt]s' --reporter mocha-multi-reporters --reporter-options configFile=mocha.unit-reporters.json",
|
|
21
|
+
"lint": "eslint '{lib,test}/**/*.{t,j}s'",
|
|
22
|
+
"lint:fix": "npm run lint -- --fix",
|
|
23
|
+
"build": "npm run clean && npm run build:types && npm run build:cjs",
|
|
24
|
+
"build:types": "tsc --emitDeclarationOnly",
|
|
25
|
+
"build:cjs": "tsc",
|
|
26
|
+
"prepublishOnly": "npm run build",
|
|
27
|
+
"semantic-release": "semantic-release",
|
|
28
|
+
"prepare": "husky install",
|
|
29
|
+
"lint-staged": "lint-staged"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"contentful-management": ">=7.30.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@semantic-release/changelog": "6.0.3",
|
|
36
|
+
"@semantic-release/git": "10.0.1",
|
|
37
|
+
"@testing-library/dom": "9.3.1",
|
|
38
|
+
"@types/chai-as-promised": "7.1.5",
|
|
39
|
+
"@types/cross-spawn": "6.0.2",
|
|
40
|
+
"@types/fs-extra": "11.0.1",
|
|
41
|
+
"@types/jsdom": "21.1.1",
|
|
42
|
+
"@types/mocha": "10.0.1",
|
|
43
|
+
"@types/nanoid": "3.0.0",
|
|
44
|
+
"@types/sinon": "^10.0.0",
|
|
45
|
+
"@types/sinon-chai": "^3.2.5",
|
|
46
|
+
"@typescript-eslint/eslint-plugin": "5.61.0",
|
|
47
|
+
"@typescript-eslint/parser": "5.62.0",
|
|
48
|
+
"babel-eslint": "10.1.0",
|
|
49
|
+
"chai": "4.3.7",
|
|
50
|
+
"chai-as-promised": "7.1.1",
|
|
51
|
+
"cross-spawn": "7.0.3",
|
|
52
|
+
"eslint": "8.45.0",
|
|
53
|
+
"eslint-config-prettier": "8.8.0",
|
|
54
|
+
"eslint-config-standard": "17.1.0",
|
|
55
|
+
"eslint-plugin-import": "2.27.5",
|
|
56
|
+
"eslint-plugin-node": "11.1.0",
|
|
57
|
+
"eslint-plugin-prettier": "4.2.1",
|
|
58
|
+
"eslint-plugin-promise": "6.1.1",
|
|
59
|
+
"eslint-plugin-react": "7.32.2",
|
|
60
|
+
"eslint-plugin-standard": "5.0.0",
|
|
61
|
+
"fs-extra": "11.1.1",
|
|
62
|
+
"husky": "8.0.3",
|
|
63
|
+
"jsdom": "22.1.0",
|
|
64
|
+
"lint-staged": "13.2.3",
|
|
65
|
+
"mocha": "10.2.0",
|
|
66
|
+
"mocha-junit-reporter": "2.2.1",
|
|
67
|
+
"mocha-multi-reporters": "1.5.1",
|
|
68
|
+
"mochawesome": "7.1.3",
|
|
69
|
+
"mochawesome-merge": "4.3.0",
|
|
70
|
+
"mochawesome-report-generator": "6.2.0",
|
|
71
|
+
"prettier": "2.8.8",
|
|
72
|
+
"rimraf": "^5.0.1",
|
|
73
|
+
"semantic-release": "21.0.7",
|
|
74
|
+
"sinon": "15.2.0",
|
|
75
|
+
"sinon-chai": "3.7.0",
|
|
76
|
+
"ts-mocha": "10.0.0",
|
|
77
|
+
"typescript": "5.1.6"
|
|
78
|
+
},
|
|
79
|
+
"lint-staged": {
|
|
80
|
+
"*.ts": [
|
|
81
|
+
"prettier --write",
|
|
82
|
+
"eslint --fix",
|
|
83
|
+
"git add"
|
|
84
|
+
],
|
|
85
|
+
"*.md": [
|
|
86
|
+
"prettier --write",
|
|
87
|
+
"git add"
|
|
88
|
+
]
|
|
89
|
+
},
|
|
90
|
+
"release": {
|
|
91
|
+
"branches": [
|
|
92
|
+
"master",
|
|
93
|
+
{
|
|
94
|
+
"name": "canary",
|
|
95
|
+
"channel": "canary",
|
|
96
|
+
"prerelease": "alpha"
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
"plugins": [
|
|
100
|
+
"@semantic-release/commit-analyzer",
|
|
101
|
+
"@semantic-release/release-notes-generator",
|
|
102
|
+
"@semantic-release/changelog",
|
|
103
|
+
"@semantic-release/npm",
|
|
104
|
+
[
|
|
105
|
+
"@semantic-release/git",
|
|
106
|
+
{
|
|
107
|
+
"message": "chore: ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}",
|
|
108
|
+
"assets": [
|
|
109
|
+
"CHANGELOG.md",
|
|
110
|
+
"package.json",
|
|
111
|
+
"package-lock.json"
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
"@semantic-release/github"
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
}
|
package/dist/README.md
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# !! WARNING !!
|
|
2
|
-
|
|
3
|
-
`cf-extension.css` file in this directory is a prebuilt committed version of legacy
|
|
4
|
-
Contentful UI Extension styles.
|
|
5
|
-
|
|
6
|
-
It is here for backwards compatibility only: it will be packaged and published on npm
|
|
7
|
-
so it's available under its legacy URL:
|
|
8
|
-
|
|
9
|
-
https://unpkg.com/contentful-ui-extensions-sdk/dist/cf-extension.css
|