@finsweet/webflow-apps-utils 1.0.7 → 1.0.8
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/dist/index.d.ts +0 -3
- package/dist/index.js +0 -3
- package/dist/ui/components/layout/Layout.svelte +0 -1
- package/dist/ui/components/layout/common/EditModeMessage.svelte +1 -1
- package/dist/ui/components/layout/examples/ExampleLayout.svelte +1 -1
- package/dist/ui/components/layout/examples/Wrapper.svelte +1 -1
- package/dist/ui/index.d.ts +4 -0
- package/dist/ui/index.js +4 -0
- package/dist/{providers → ui/providers}/GlobalProvider.stories.js +7 -7
- package/dist/{providers → ui/providers}/GlobalProvider.svelte +1 -1
- package/dist/{router → ui/router}/providers/RouterProvider.svelte +1 -1
- package/dist/{router → ui/router}/router.svelte.d.ts +0 -1
- package/dist/{router → ui/router}/router.svelte.js +3 -2
- package/dist/{stores → ui/stores}/forms/Form.stories.js +5 -5
- package/dist/{stores → ui/stores}/forms/FormDemo.svelte +1 -1
- package/dist/{stores → ui/stores}/index.d.ts +1 -3
- package/dist/{stores → ui/stores}/index.js +1 -3
- package/dist/ui/utils/api/checkIfAppModeIsDesign.d.ts +4 -0
- package/dist/ui/utils/api/checkIfAppModeIsDesign.js +19 -0
- package/dist/ui/utils/api/clipboard/handlePaste.d.ts +15 -0
- package/dist/ui/utils/api/clipboard/handlePaste.js +49 -0
- package/dist/ui/utils/api/clipboard/index.d.ts +1 -0
- package/dist/ui/utils/api/clipboard/index.js +1 -0
- package/dist/ui/utils/api/getAllAssets.d.ts +11 -0
- package/dist/ui/utils/api/getAllAssets.js +20 -0
- package/dist/ui/utils/api/getFinsweetComponentsEnvironment.d.ts +8 -0
- package/dist/ui/utils/api/getFinsweetComponentsEnvironment.js +66 -0
- package/dist/ui/utils/api/index.d.ts +5 -0
- package/dist/ui/utils/api/index.js +5 -0
- package/dist/ui/utils/api/insertWithXSCP.d.ts +4 -0
- package/dist/ui/utils/api/insertWithXSCP.js +12 -0
- package/dist/{utils → ui/utils}/auth/crossWindowLogin.d.ts +1 -1
- package/dist/{utils → ui/utils}/auth/crossWindowLogin.js +1 -1
- package/dist/{utils → ui/utils}/auth/index.d.ts +1 -1
- package/dist/{utils → ui/utils}/auth/index.js +4 -6
- package/dist/{utils → ui/utils}/diff-mapper/DiffMapper.stories.js +2 -2
- package/dist/{utils → ui/utils}/diff-mapper/DiffMapperDemo.svelte +1 -1
- package/dist/{utils → ui/utils}/helpers/goto.js +2 -4
- package/dist/ui/utils/helpers/index.d.ts +1 -0
- package/dist/ui/utils/helpers/index.js +1 -0
- package/dist/ui/utils/index.d.ts +3 -0
- package/dist/ui/utils/index.js +3 -0
- package/dist/utils/custom-code/api.d.ts +1 -1
- package/dist/utils/custom-code/api.js +4 -6
- package/dist/utils/custom-code/configs.d.ts +3 -2
- package/dist/utils/custom-code/configs.js +5 -8
- package/dist/utils/custom-code/index.d.ts +1 -1
- package/dist/utils/custom-code/index.js +1 -1
- package/dist/utils/helpers/index.d.ts +0 -1
- package/dist/utils/helpers/index.js +0 -1
- package/dist/utils/index.d.ts +2 -3
- package/dist/utils/index.js +1 -3
- package/dist/utils/logger/index.d.ts +1 -2
- package/dist/utils/stores/index.d.ts +2 -0
- package/dist/utils/stores/index.js +2 -0
- package/package.json +13 -4
- /package/dist/{providers → ui/providers}/GlobalProvider.stories.d.ts +0 -0
- /package/dist/{providers → ui/providers}/GlobalProvider.svelte.d.ts +0 -0
- /package/dist/{providers → ui/providers}/GlobalProviderDemo.svelte +0 -0
- /package/dist/{providers → ui/providers}/GlobalProviderDemo.svelte.d.ts +0 -0
- /package/dist/{providers → ui/providers}/configuratorUtils.d.ts +0 -0
- /package/dist/{providers → ui/providers}/configuratorUtils.js +0 -0
- /package/dist/{providers → ui/providers}/globalContext.svelte.d.ts +0 -0
- /package/dist/{providers → ui/providers}/globalContext.svelte.js +0 -0
- /package/dist/{providers → ui/providers}/index.d.ts +0 -0
- /package/dist/{providers → ui/providers}/index.js +0 -0
- /package/dist/{providers → ui/providers}/types.d.ts +0 -0
- /package/dist/{providers → ui/providers}/types.js +0 -0
- /package/dist/{router → ui/router}/Router.stories.d.ts +0 -0
- /package/dist/{router → ui/router}/Router.stories.js +0 -0
- /package/dist/{router → ui/router}/examples/RouterExample.svelte +0 -0
- /package/dist/{router → ui/router}/examples/RouterExample.svelte.d.ts +0 -0
- /package/dist/{router → ui/router}/examples/index.d.ts +0 -0
- /package/dist/{router → ui/router}/examples/index.js +0 -0
- /package/dist/{router → ui/router}/examples/pages/AboutPage.svelte +0 -0
- /package/dist/{router → ui/router}/examples/pages/AboutPage.svelte.d.ts +0 -0
- /package/dist/{router → ui/router}/examples/pages/HomePage.svelte +0 -0
- /package/dist/{router → ui/router}/examples/pages/HomePage.svelte.d.ts +0 -0
- /package/dist/{router → ui/router}/examples/pages/NotFoundPage.svelte +0 -0
- /package/dist/{router → ui/router}/examples/pages/NotFoundPage.svelte.d.ts +0 -0
- /package/dist/{router → ui/router}/hooks.svelte.d.ts +0 -0
- /package/dist/{router → ui/router}/hooks.svelte.js +0 -0
- /package/dist/{router → ui/router}/index.d.ts +0 -0
- /package/dist/{router → ui/router}/index.js +0 -0
- /package/dist/{router → ui/router}/providers/Link.svelte +0 -0
- /package/dist/{router → ui/router}/providers/Link.svelte.d.ts +0 -0
- /package/dist/{router → ui/router}/providers/Route.svelte +0 -0
- /package/dist/{router → ui/router}/providers/Route.svelte.d.ts +0 -0
- /package/dist/{router → ui/router}/providers/RouterProvider.svelte.d.ts +0 -0
- /package/dist/{router → ui/router}/providers/index.d.ts +0 -0
- /package/dist/{router → ui/router}/providers/index.js +0 -0
- /package/dist/{stores → ui/stores}/breakpoints.d.ts +0 -0
- /package/dist/{stores → ui/stores}/breakpoints.js +0 -0
- /package/dist/{stores → ui/stores}/componentInjectErrors.d.ts +0 -0
- /package/dist/{stores → ui/stores}/componentInjectErrors.js +0 -0
- /package/dist/{stores/forms.d.ts → ui/stores/form.d.ts} +0 -0
- /package/dist/{stores/forms.js → ui/stores/form.js} +0 -0
- /package/dist/{stores → ui/stores}/forms/Form.stories.d.ts +0 -0
- /package/dist/{stores → ui/stores}/forms/FormDemo.svelte.d.ts +0 -0
- /package/dist/{stores → ui/stores}/showConfirmActionModal.d.ts +0 -0
- /package/dist/{stores → ui/stores}/showConfirmActionModal.js +0 -0
- /package/dist/{stores → ui/stores}/siteInfo.d.ts +0 -0
- /package/dist/{stores → ui/stores}/siteInfo.js +0 -0
- /package/dist/{utils → ui/utils}/diff-mapper/DiffMapper.stories.d.ts +0 -0
- /package/dist/{utils → ui/utils}/diff-mapper/DiffMapperDemo.svelte.d.ts +0 -0
- /package/dist/{utils → ui/utils}/diff-mapper/deepDiffMapper.d.ts +0 -0
- /package/dist/{utils → ui/utils}/diff-mapper/deepDiffMapper.js +0 -0
- /package/dist/{utils → ui/utils}/diff-mapper/index.d.ts +0 -0
- /package/dist/{utils → ui/utils}/diff-mapper/index.js +0 -0
- /package/dist/{utils → ui/utils}/helpers/goto.d.ts +0 -0
- /package/dist/{stores → utils/stores}/isPreviewMode.d.ts +0 -0
- /package/dist/{stores → utils/stores}/isPreviewMode.js +0 -0
- /package/dist/{stores → utils/stores}/router.d.ts +0 -0
- /package/dist/{stores → utils/stores}/router.js +0 -0
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { useAppContext } from '../../../../providers';
|
|
3
2
|
import { Pencil, WarningTriangleOutlineIcon } from '../../../icons';
|
|
3
|
+
import { useAppContext } from '../../../providers';
|
|
4
4
|
import { BRAND } from '../../../../utils';
|
|
5
5
|
|
|
6
6
|
import { Notification } from '../../notification';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount } from 'svelte';
|
|
3
3
|
|
|
4
|
-
import { useAppContext } from '
|
|
4
|
+
import { useAppContext } from '../../../providers';
|
|
5
5
|
|
|
6
6
|
import { CheckCircleIcon, CodeIcon, InfoIcon, SettingsIcon } from '../../../icons';
|
|
7
7
|
import { Button } from '../../button';
|
package/dist/ui/index.d.ts
CHANGED
package/dist/ui/index.js
CHANGED
|
@@ -34,7 +34,7 @@ The \`GlobalProvider\` is a comprehensive context management system built on Sve
|
|
|
34
34
|
|
|
35
35
|
\`\`\`svelte
|
|
36
36
|
<script lang="ts">
|
|
37
|
-
import { GlobalProvider } from '
|
|
37
|
+
import { GlobalProvider } from '../../providers';
|
|
38
38
|
|
|
39
39
|
const initialContexts = {
|
|
40
40
|
app: {
|
|
@@ -66,7 +66,7 @@ The \`GlobalProvider\` automatically creates these default contexts:
|
|
|
66
66
|
|
|
67
67
|
\`\`\`svelte
|
|
68
68
|
<script lang="ts">
|
|
69
|
-
import { useAppContext, useFormContext, useDataContext } from '
|
|
69
|
+
import { useAppContext, useFormContext, useDataContext } from '../../providers';
|
|
70
70
|
|
|
71
71
|
const appContext = useAppContext();
|
|
72
72
|
const formContext = useFormContext();
|
|
@@ -141,7 +141,7 @@ The \`GlobalProvider\` includes sophisticated configurator state management with
|
|
|
141
141
|
|
|
142
142
|
\`\`\`svelte
|
|
143
143
|
<script lang="ts">
|
|
144
|
-
import { useConfiguratorContext, useAppContext } from '
|
|
144
|
+
import { useConfiguratorContext, useAppContext } from '../../providers';
|
|
145
145
|
|
|
146
146
|
// Define your configurator type
|
|
147
147
|
type MyConfiguratorType = {
|
|
@@ -230,7 +230,7 @@ const config6 = { user: { name: 'John', age: 31 }, settings: { theme: 'dark' } }
|
|
|
230
230
|
### Generic Context Usage
|
|
231
231
|
|
|
232
232
|
\`\`\`typescript
|
|
233
|
-
import type { ContextOperations, AppContextData, DataContextData } from '
|
|
233
|
+
import type { ContextOperations, AppContextData, DataContextData } from '../../providers';
|
|
234
234
|
|
|
235
235
|
// For custom contexts
|
|
236
236
|
const userContext: ContextOperations<UserType> = useContext<UserType>('user');
|
|
@@ -266,7 +266,7 @@ The GlobalProvider system includes several powerful utility functions for advanc
|
|
|
266
266
|
For detailed object comparison and change analysis:
|
|
267
267
|
|
|
268
268
|
\`\`\`typescript
|
|
269
|
-
import { hasChangesViaDiff, getDetailedDiff, compareKeys } from '
|
|
269
|
+
import { hasChangesViaDiff, getDetailedDiff, compareKeys } from '../../providers';
|
|
270
270
|
|
|
271
271
|
// Quick change detection
|
|
272
272
|
const hasChanges = hasChangesViaDiff(oldConfig, newConfig);
|
|
@@ -291,7 +291,7 @@ import {
|
|
|
291
291
|
validateWatchOptions,
|
|
292
292
|
extractKeys,
|
|
293
293
|
createDebouncedUpdate
|
|
294
|
-
} from '
|
|
294
|
+
} from '../../providers';
|
|
295
295
|
|
|
296
296
|
// Create default configurator state
|
|
297
297
|
const defaultState = createDefaultConfiguratorState<MyConfigType>();
|
|
@@ -313,7 +313,7 @@ const debouncedSave = createDebouncedUpdate(saveConfig, 300);
|
|
|
313
313
|
### Performance Optimization Helpers
|
|
314
314
|
|
|
315
315
|
\`\`\`typescript
|
|
316
|
-
import { createDebouncedUpdate } from '
|
|
316
|
+
import { createDebouncedUpdate } from '../../providers';
|
|
317
317
|
|
|
318
318
|
// Create debounced functions for expensive operations
|
|
319
319
|
const debouncedValidation = createDebouncedUpdate((config) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { getFinsweetComponentsEnvironment } from '
|
|
2
|
+
import { getFinsweetComponentsEnvironment } from '../../utils/index.js';
|
|
3
3
|
|
|
4
4
|
import { createGlobalContext, setGlobalContext } from './globalContext.svelte';
|
|
5
5
|
import type { GlobalProviderProps } from './types';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onDestroy, onMount, setContext, type Snippet } from 'svelte';
|
|
3
3
|
|
|
4
|
+
import { LoadingScreen } from '../..';
|
|
4
5
|
import type { RouteConfig, Router } from '../router.svelte';
|
|
5
|
-
import { LoadingScreen } from '../../ui';
|
|
6
6
|
|
|
7
7
|
interface Props {
|
|
8
8
|
/** Router instance to use for routing */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { routerStore } from '
|
|
2
|
+
import { routerStore } from '../../utils/stores';
|
|
3
3
|
/**
|
|
4
4
|
* Custom Client-Side Router for Svelte 5
|
|
5
5
|
*/
|
|
@@ -394,4 +394,5 @@ export function createRouter(config) {
|
|
|
394
394
|
export const router = createRouter();
|
|
395
395
|
// Export hooks and utilities
|
|
396
396
|
export * from './hooks.svelte.js';
|
|
397
|
-
|
|
397
|
+
// Providers moved to main package - import from @finsweet/webflow-apps-utils directly
|
|
398
|
+
// export * from './providers/index.js';
|
|
@@ -35,7 +35,7 @@ The form validation system provides:
|
|
|
35
35
|
The main class for creating and managing form validation state.
|
|
36
36
|
|
|
37
37
|
\`\`\`typescript
|
|
38
|
-
import { FormValidator } from '
|
|
38
|
+
import { FormValidator } from '../../../stores/forms';
|
|
39
39
|
|
|
40
40
|
// Define your form data structure
|
|
41
41
|
interface MyFormData {
|
|
@@ -196,7 +196,7 @@ The system maintains a global registry of all forms for cross-component access.
|
|
|
196
196
|
Retrieve a form instance by its identifier:
|
|
197
197
|
|
|
198
198
|
\`\`\`typescript
|
|
199
|
-
import { getFormById } from '
|
|
199
|
+
import { getFormById } from '../../../stores/forms';
|
|
200
200
|
|
|
201
201
|
const form = getFormById('my-form-id');
|
|
202
202
|
if (form) {
|
|
@@ -209,7 +209,7 @@ if (form) {
|
|
|
209
209
|
Check if a specific form is valid:
|
|
210
210
|
|
|
211
211
|
\`\`\`typescript
|
|
212
|
-
import { isFormValid } from '
|
|
212
|
+
import { isFormValid } from '../../../stores/forms';
|
|
213
213
|
|
|
214
214
|
if (isFormValid('my-form-id')) {
|
|
215
215
|
console.log('Form is valid!');
|
|
@@ -221,7 +221,7 @@ if (isFormValid('my-form-id')) {
|
|
|
221
221
|
Get error messages for a specific form:
|
|
222
222
|
|
|
223
223
|
\`\`\`typescript
|
|
224
|
-
import { getFormErrors } from '
|
|
224
|
+
import { getFormErrors } from '../../../stores/forms';
|
|
225
225
|
|
|
226
226
|
const errors = getFormErrors('my-form-id');
|
|
227
227
|
console.log(errors);
|
|
@@ -232,7 +232,7 @@ console.log(errors);
|
|
|
232
232
|
Reset a form by its identifier:
|
|
233
233
|
|
|
234
234
|
\`\`\`typescript
|
|
235
|
-
import { resetForm } from '
|
|
235
|
+
import { resetForm } from '../../../stores/forms';
|
|
236
236
|
|
|
237
237
|
resetForm('my-form-id');
|
|
238
238
|
\`\`\`
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if the app mode is design and shows error notification if not.
|
|
3
|
+
*/
|
|
4
|
+
export const checkIfAppModeIsDesign = async () => {
|
|
5
|
+
const capabilities = await webflow.canForAppMode([
|
|
6
|
+
webflow.appModes.canDesign,
|
|
7
|
+
webflow.appModes.canEdit
|
|
8
|
+
]);
|
|
9
|
+
if (capabilities.canDesign) {
|
|
10
|
+
// Proceed with the action
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
// Provide feedback to the user
|
|
14
|
+
await webflow.notify({
|
|
15
|
+
type: 'Error',
|
|
16
|
+
message: 'This action cannot be performed right now. Ensure you are working in the Primary Locale, on the Main Branch, and in design mode.'
|
|
17
|
+
});
|
|
18
|
+
return false;
|
|
19
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { XSCPMetadata } from '../../../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Processes pasted component data to validate Finsweet components.
|
|
4
|
+
*/
|
|
5
|
+
export declare const processPastedComponent: (pasteData: XSCPMetadata, component: string) => {
|
|
6
|
+
data: XSCPMetadata;
|
|
7
|
+
key: string;
|
|
8
|
+
} | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Handles pasting of Webflow components from clipboard.
|
|
11
|
+
*/
|
|
12
|
+
export declare const handlePasteXSCP: (e: ClipboardEvent, component: string) => {
|
|
13
|
+
data: XSCPMetadata;
|
|
14
|
+
key: string;
|
|
15
|
+
} | undefined;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { getLogger } from '../../../../utils/logger';
|
|
2
|
+
const logger = getLogger('webflow-apps-ui-utils');
|
|
3
|
+
/**
|
|
4
|
+
* Processes pasted component data to validate Finsweet components.
|
|
5
|
+
*/
|
|
6
|
+
export const processPastedComponent = (pasteData, component) => {
|
|
7
|
+
const valid = pasteData?.payload?.nodes?.some((node) => node?.data?.xattr?.some((attr) => {
|
|
8
|
+
if (component === 'consent') {
|
|
9
|
+
// consent is kinda different
|
|
10
|
+
const bannerFound = attr.name.includes(`fs-consent-element`) && attr.value === 'banner';
|
|
11
|
+
const wrapperFound = attr.name.includes(`fs-consent-element`) && attr.value === 'wrapper';
|
|
12
|
+
return bannerFound || wrapperFound;
|
|
13
|
+
}
|
|
14
|
+
return attr.name.includes(`fs-${component}-instance`);
|
|
15
|
+
}));
|
|
16
|
+
if (valid) {
|
|
17
|
+
return { data: pasteData, key: component };
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Handles pasting of Webflow components from clipboard.
|
|
22
|
+
*/
|
|
23
|
+
export const handlePasteXSCP = (e, component) => {
|
|
24
|
+
if (!e.clipboardData?.types.includes('application/json'))
|
|
25
|
+
return;
|
|
26
|
+
const data = e.clipboardData?.getData('application/json');
|
|
27
|
+
const clipboard = JSON.parse(data);
|
|
28
|
+
if (clipboard?.type === '@webflow/XscpData') {
|
|
29
|
+
try {
|
|
30
|
+
const data = e.clipboardData.getData('application/json');
|
|
31
|
+
const clipboard = JSON.parse(data);
|
|
32
|
+
if (clipboard?.type === '@webflow/XscpData') {
|
|
33
|
+
return processPastedComponent(clipboard, component);
|
|
34
|
+
}
|
|
35
|
+
webflow.notify({
|
|
36
|
+
type: 'Error',
|
|
37
|
+
message: 'Invalid! You can only paste valid Finsweet Components.'
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
logger.error({}, 'handlePasteXSCP', error);
|
|
42
|
+
webflow.notify({
|
|
43
|
+
type: 'Error',
|
|
44
|
+
message: 'Invalid! You can only paste valid Finsweet Components.'
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './handlePaste';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './handlePaste';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface AllAssets {
|
|
2
|
+
name: string;
|
|
3
|
+
url: string;
|
|
4
|
+
mimeType: string;
|
|
5
|
+
altText: string;
|
|
6
|
+
asset: Asset;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Gets all assets from the Webflow Canvas with their metadata.
|
|
10
|
+
*/
|
|
11
|
+
export declare const getAllAssets: () => Promise<AllAssets[]>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gets all assets from the Webflow Canvas with their metadata.
|
|
3
|
+
*/
|
|
4
|
+
export const getAllAssets = async () => {
|
|
5
|
+
const assets = await webflow.getAllAssets();
|
|
6
|
+
const assetPromises = assets.map(async (asset) => {
|
|
7
|
+
const url = await asset.getUrl();
|
|
8
|
+
const name = await asset.getName();
|
|
9
|
+
const mimeType = await asset.getMimeType();
|
|
10
|
+
const altText = (await asset.getAltText()) ?? '';
|
|
11
|
+
return {
|
|
12
|
+
name,
|
|
13
|
+
url,
|
|
14
|
+
mimeType,
|
|
15
|
+
altText,
|
|
16
|
+
asset
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
return await Promise.all(assetPromises);
|
|
20
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { COMPONENTS_CORE_SCRIPT, COMPONENTS_CORE_SCRIPT_LOCAL, COMPONENTS_SERVER_DEV_ENDPOINT, COMPONENTS_SERVER_DEV_ENDPOINT_LOCAL, COMPONENTS_SERVER_PROD_ENDPOINT, getLocalStorage } from '../../../utils';
|
|
2
|
+
const DEV_MODE_KEY = 'fsComponentsDevMode';
|
|
3
|
+
const DEV_MODE_SCRIPT_KEY = 'fsComponentsDevModeScript';
|
|
4
|
+
const DEV_MODE_API_KEY = 'fsComponentsDevModeApi';
|
|
5
|
+
const URL_DEV_MODE_KEY = 'dev';
|
|
6
|
+
const URL_DEV_MODE_SCRIPT_KEY = 'script';
|
|
7
|
+
const URL_DEV_MODE_API_KEY = 'api';
|
|
8
|
+
let lastLogTime = 0;
|
|
9
|
+
const LOG_THROTTLE_MS = 3000;
|
|
10
|
+
/**
|
|
11
|
+
* Gets a parameter value from the URL search params.
|
|
12
|
+
*/
|
|
13
|
+
const getUrlParam = (key) => {
|
|
14
|
+
if (typeof window === 'undefined')
|
|
15
|
+
return null;
|
|
16
|
+
try {
|
|
17
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
18
|
+
return urlParams.get(key);
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
console.error('Error getting URL parameter:', e);
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Throttled console log that only logs once within the throttle interval.
|
|
27
|
+
*/
|
|
28
|
+
const throttledLog = (message, data) => {
|
|
29
|
+
const now = Date.now();
|
|
30
|
+
if (now - lastLogTime >= LOG_THROTTLE_MS) {
|
|
31
|
+
console.log(message, data || '');
|
|
32
|
+
lastLogTime = now;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Gets the Finsweet components environment configuration.
|
|
37
|
+
*/
|
|
38
|
+
export const getFinsweetComponentsEnvironment = () => {
|
|
39
|
+
const devFromUrl = getUrlParam(URL_DEV_MODE_KEY);
|
|
40
|
+
const scriptFromUrl = getUrlParam(URL_DEV_MODE_SCRIPT_KEY);
|
|
41
|
+
const apiFromUrl = getUrlParam(URL_DEV_MODE_API_KEY);
|
|
42
|
+
const dev = devFromUrl !== null ? devFromUrl === 'true' : getLocalStorage(DEV_MODE_KEY) === 'true';
|
|
43
|
+
let script = scriptFromUrl || getLocalStorage(DEV_MODE_SCRIPT_KEY) || COMPONENTS_CORE_SCRIPT;
|
|
44
|
+
let api = dev
|
|
45
|
+
? apiFromUrl || getLocalStorage(DEV_MODE_API_KEY) || COMPONENTS_SERVER_DEV_ENDPOINT
|
|
46
|
+
: COMPONENTS_SERVER_PROD_ENDPOINT;
|
|
47
|
+
const isBrowser = typeof window !== 'undefined';
|
|
48
|
+
const isLocalhost = isBrowser && window?.location?.hostname?.includes('localhost');
|
|
49
|
+
//if localhost then use local scripts
|
|
50
|
+
if (isLocalhost) {
|
|
51
|
+
script = COMPONENTS_CORE_SCRIPT_LOCAL;
|
|
52
|
+
api = COMPONENTS_SERVER_DEV_ENDPOINT_LOCAL;
|
|
53
|
+
}
|
|
54
|
+
const development = !!dev || isLocalhost;
|
|
55
|
+
if (development) {
|
|
56
|
+
throttledLog(`\n\nFinsweet Components Environment:
|
|
57
|
+
- API: ${api}
|
|
58
|
+
- Core script: ${script}
|
|
59
|
+
- Development mode: ${development ? 'Yes' : 'No'}\n\n`);
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
development,
|
|
63
|
+
coreScript: script,
|
|
64
|
+
api
|
|
65
|
+
};
|
|
66
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inserts a template into the Designer Canvas using XSCP APIs.
|
|
3
|
+
*/
|
|
4
|
+
export const insertWithXSCP = async (template) => {
|
|
5
|
+
try {
|
|
6
|
+
// @ts-expect-error - typings not available for xscp
|
|
7
|
+
await webflow._internal.xscp(template);
|
|
8
|
+
}
|
|
9
|
+
catch (error) {
|
|
10
|
+
throw new Error(`Failed to insert template with XSCP: ${error}`);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AUTH0_AUDIENCE, AUTH0_CLIENT_ID, AUTH0_LOGIN_URL, AUTH0_REDIRECT_URL, AUTH0_SCOPE, PROD_FINSWEEET_ACCOUNTS_ORIGIN } from '
|
|
1
|
+
import { AUTH0_AUDIENCE, AUTH0_CLIENT_ID, AUTH0_LOGIN_URL, AUTH0_REDIRECT_URL, AUTH0_SCOPE, PROD_FINSWEEET_ACCOUNTS_ORIGIN } from '../../../utils/constants';
|
|
2
2
|
/**
|
|
3
3
|
* Opens a popup window for cross-window authentication with Auth0.
|
|
4
4
|
*/
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
2
|
import Cookies from 'js-cookie';
|
|
3
3
|
import { get, writable } from 'svelte/store';
|
|
4
|
+
import { getLocalStorage, removeLocalStorage, setLocalStorage } from '../../../utils';
|
|
5
|
+
import { FINSWEET_SUBSCRIPTIONS_ENDPOINT, FINSWEET_SUBSCRIPTIONS_ENDPOINT_STAGING } from '../../../utils/constants';
|
|
4
6
|
import { getFinsweetComponentsEnvironment } from '../api';
|
|
5
|
-
import { getLocalStorage, removeLocalStorage, setLocalStorage } from '../browser-storage';
|
|
6
|
-
import { FINSWEET_SUBSCRIPTIONS_ENDPOINT, FINSWEET_SUBSCRIPTIONS_ENDPOINT_STAGING } from '../constants';
|
|
7
|
-
import { getLogger } from '../logger';
|
|
8
7
|
import { crossWindowLogin } from './crossWindowLogin';
|
|
9
|
-
const logger = getLogger('webflow-apps-ui-utils');
|
|
10
8
|
/**
|
|
11
9
|
* Store for the Finsweet user data.
|
|
12
10
|
*/
|
|
@@ -51,7 +49,7 @@ export const getSubscriptions = async (token) => {
|
|
|
51
49
|
return data;
|
|
52
50
|
}
|
|
53
51
|
catch (error) {
|
|
54
|
-
|
|
52
|
+
console.error('Failed to fetch subscriptions', error);
|
|
55
53
|
return [];
|
|
56
54
|
}
|
|
57
55
|
};
|
|
@@ -95,7 +93,7 @@ export const handleLogin = async () => {
|
|
|
95
93
|
}
|
|
96
94
|
catch (error) {
|
|
97
95
|
const err = error;
|
|
98
|
-
|
|
96
|
+
console.error('Login failed:', err.message);
|
|
99
97
|
finsweetUser.set(null);
|
|
100
98
|
webflow.notify({
|
|
101
99
|
type: 'Error',
|
|
@@ -131,7 +131,7 @@ Automatic cache cleanup when size exceeds 100 entries or TTL expires.
|
|
|
131
131
|
The diff mapper is seamlessly integrated with the GlobalProvider system:
|
|
132
132
|
|
|
133
133
|
\`\`\`typescript
|
|
134
|
-
import { useConfiguratorContext } from '
|
|
134
|
+
import { useConfiguratorContext } from '../../../providers';
|
|
135
135
|
|
|
136
136
|
const configurator = useConfiguratorContext<MyConfigType>();
|
|
137
137
|
|
|
@@ -155,7 +155,7 @@ import {
|
|
|
155
155
|
validateWatchOptions,
|
|
156
156
|
extractKeys,
|
|
157
157
|
createDebouncedUpdate
|
|
158
|
-
} from '
|
|
158
|
+
} from '../../../providers';
|
|
159
159
|
|
|
160
160
|
// Create default configurator state
|
|
161
161
|
const defaultState = createDefaultConfiguratorState<MyConfigType>();
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { get } from 'svelte/store';
|
|
2
2
|
import { navigate } from 'svelte-routing';
|
|
3
|
-
import { routerStore } from '
|
|
4
|
-
import { getLogger } from '../logger';
|
|
5
|
-
const logger = getLogger('webflow-apps-ui-utils');
|
|
3
|
+
import { routerStore } from '../../../utils/stores';
|
|
6
4
|
/**
|
|
7
5
|
* Normalizes a URL path to ensure proper formatting.
|
|
8
6
|
*/
|
|
@@ -21,7 +19,7 @@ const normalizeUrlPath = (path, hash) => {
|
|
|
21
19
|
export const goto = (path = '/', state = {}) => {
|
|
22
20
|
const { hash = '' } = get(routerStore);
|
|
23
21
|
if (!hash) {
|
|
24
|
-
|
|
22
|
+
console.error('goto method found no router hash in the router store. Contact Finsweet support.');
|
|
25
23
|
return;
|
|
26
24
|
}
|
|
27
25
|
const url = normalizeUrlPath(`/${hash}/${path}`, hash);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './goto';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './goto';
|
|
@@ -2,7 +2,7 @@ import type { CustomCodeBlock } from '../../types';
|
|
|
2
2
|
/**
|
|
3
3
|
* Gets stored Custom Code blocks by ID or returns all if no ID provided.
|
|
4
4
|
*/
|
|
5
|
-
export declare const getCustomCode: (
|
|
5
|
+
export declare const getCustomCode: (displayName?: string) => Promise<Array<CustomCodeBlock>>;
|
|
6
6
|
/**
|
|
7
7
|
* Sets custom code blocks in the site.
|
|
8
8
|
*/
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import { getLogger } from '../logger';
|
|
2
|
-
const logger = getLogger('webflow-apps-ui-utils');
|
|
3
1
|
/**
|
|
4
2
|
* Gets stored Custom Code blocks by ID or returns all if no ID provided.
|
|
5
3
|
*/
|
|
6
|
-
export const getCustomCode = async (
|
|
4
|
+
export const getCustomCode = async (displayName) => {
|
|
7
5
|
//TODO: update this when typings are available plus any other place we have disabled this warning.
|
|
8
6
|
//@ts-expect-error - not available in typings for now
|
|
9
7
|
const customCodeBlock = (await webflow.getSiteCustomCode());
|
|
10
8
|
if (!customCodeBlock || customCodeBlock.length === 0)
|
|
11
9
|
return [];
|
|
12
|
-
if (!
|
|
10
|
+
if (!displayName)
|
|
13
11
|
return customCodeBlock;
|
|
14
|
-
const storedConfigs = customCodeBlock.filter((block) => block.id ===
|
|
12
|
+
const storedConfigs = customCodeBlock.filter((block) => block.id === displayName);
|
|
15
13
|
if (storedConfigs)
|
|
16
14
|
return storedConfigs;
|
|
17
15
|
return [];
|
|
@@ -25,7 +23,7 @@ export const setCustomCode = async (customCodeBlock) => {
|
|
|
25
23
|
await webflow.setSiteCustomCode(customCodeBlock);
|
|
26
24
|
}
|
|
27
25
|
catch (error) {
|
|
28
|
-
|
|
26
|
+
console.error('Failed to save custom code block', error, customCodeBlock);
|
|
29
27
|
}
|
|
30
28
|
};
|
|
31
29
|
/**
|
|
@@ -12,11 +12,12 @@ export type CustomCodeConfigsStore = {
|
|
|
12
12
|
export declare const customCodeConfigsStore: import("svelte/store").Writable<CustomCodeConfigsStore>;
|
|
13
13
|
/**
|
|
14
14
|
* Get configs from custom code.
|
|
15
|
+
* @param displayName - The name of the custom code block to get configs from.
|
|
15
16
|
*/
|
|
16
|
-
export declare const getProjectConfigs: () => Promise<any>;
|
|
17
|
+
export declare const getProjectConfigs: (displayName: string) => Promise<any>;
|
|
17
18
|
/**
|
|
18
19
|
* Fetches configs stored in custom code for a given component.
|
|
19
20
|
* @param component
|
|
20
21
|
* @returns
|
|
21
22
|
*/
|
|
22
|
-
export declare const getComponentConfigs: (component: string) => Promise<any>;
|
|
23
|
+
export declare const getComponentConfigs: (component: string, displayName: string) => Promise<any>;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { writable } from 'svelte/store';
|
|
2
|
-
import { getLogger } from '../logger';
|
|
3
2
|
import { getCustomCode } from './api';
|
|
4
|
-
const logger = getLogger('utils');
|
|
5
|
-
const DISPLAY_NAME = 'finsweetcomponentsconfig';
|
|
6
3
|
/**
|
|
7
4
|
* Store for Custom Code stored Component configs
|
|
8
5
|
*/
|
|
@@ -13,9 +10,10 @@ export const componentConfigsStore = writable(null);
|
|
|
13
10
|
export const customCodeConfigsStore = writable([]);
|
|
14
11
|
/**
|
|
15
12
|
* Get configs from custom code.
|
|
13
|
+
* @param displayName - The name of the custom code block to get configs from.
|
|
16
14
|
*/
|
|
17
|
-
export const getProjectConfigs = async () => {
|
|
18
|
-
const [customCodeBlock] = await getCustomCode(
|
|
15
|
+
export const getProjectConfigs = async (displayName) => {
|
|
16
|
+
const [customCodeBlock] = await getCustomCode(displayName);
|
|
19
17
|
if (!customCodeBlock || !customCodeBlock.hostedLocation) {
|
|
20
18
|
return null;
|
|
21
19
|
}
|
|
@@ -24,7 +22,6 @@ export const getProjectConfigs = async () => {
|
|
|
24
22
|
const configs = await import(/* @vite-ignore */ customCodeBlock.hostedLocation);
|
|
25
23
|
window.isLoadingCustomCodeConfigs = false;
|
|
26
24
|
customCodeConfigsStore.set(configs);
|
|
27
|
-
logger.log({}, 'Project custom code configs', configs);
|
|
28
25
|
return configs;
|
|
29
26
|
};
|
|
30
27
|
/**
|
|
@@ -32,8 +29,8 @@ export const getProjectConfigs = async () => {
|
|
|
32
29
|
* @param component
|
|
33
30
|
* @returns
|
|
34
31
|
*/
|
|
35
|
-
export const getComponentConfigs = async (component) => {
|
|
36
|
-
const customCodeBlock = await getProjectConfigs();
|
|
32
|
+
export const getComponentConfigs = async (component, displayName) => {
|
|
33
|
+
const customCodeBlock = await getProjectConfigs(displayName);
|
|
37
34
|
if (!customCodeBlock || Object.keys(customCodeBlock[component]).length === 0)
|
|
38
35
|
return null;
|
|
39
36
|
return customCodeBlock[component];
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
export * from './animations';
|
|
2
2
|
export * from './api';
|
|
3
|
-
export * from './auth';
|
|
4
3
|
export * from './browser-storage';
|
|
5
|
-
export * from './constants';
|
|
6
4
|
export * from './custom-code';
|
|
7
|
-
export * from './
|
|
5
|
+
export * from './constants';
|
|
8
6
|
export * from './helpers';
|
|
9
7
|
export * from './logger';
|
|
10
8
|
export * from './webflow';
|
|
11
9
|
export * from './webflow-canvas';
|
|
10
|
+
export type * from '../types';
|
package/dist/utils/index.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
export * from './animations';
|
|
2
2
|
export * from './api';
|
|
3
|
-
export * from './auth';
|
|
4
3
|
export * from './browser-storage';
|
|
5
|
-
export * from './constants';
|
|
6
4
|
export * from './custom-code';
|
|
7
|
-
export * from './
|
|
5
|
+
export * from './constants';
|
|
8
6
|
export * from './helpers';
|
|
9
7
|
export * from './logger';
|
|
10
8
|
export * from './webflow';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
export type
|
|
2
|
-
export type LoggerContext = PredefinedLoggerContext | (string & Record<never, never>);
|
|
1
|
+
export type LoggerContext = string & Record<never, never>;
|
|
3
2
|
export interface LogData {
|
|
4
3
|
[key: string]: any;
|
|
5
4
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finsweet/webflow-apps-utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Shared utilities for Webflow apps",
|
|
5
5
|
"homepage": "https://github.com/finsweet/webflow-apps-utils",
|
|
6
6
|
"repository": {
|
|
@@ -18,9 +18,18 @@
|
|
|
18
18
|
"type": "module",
|
|
19
19
|
"exports": {
|
|
20
20
|
".": {
|
|
21
|
-
"types": "./dist/index.d.ts",
|
|
22
|
-
"svelte": "./dist/index.js",
|
|
23
|
-
"default": "./dist/index.js"
|
|
21
|
+
"types": "./dist/ui/index.d.ts",
|
|
22
|
+
"svelte": "./dist/ui/index.js",
|
|
23
|
+
"default": "./dist/ui/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./utils": {
|
|
26
|
+
"types": "./dist/utils/index.d.ts",
|
|
27
|
+
"default": "./dist/utils/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./ui": {
|
|
30
|
+
"types": "./dist/ui/index.d.ts",
|
|
31
|
+
"svelte": "./dist/ui/index.js",
|
|
32
|
+
"default": "./dist/ui/index.js"
|
|
24
33
|
},
|
|
25
34
|
"./index.css": "./dist/ui/index.css"
|
|
26
35
|
},
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|