@finsweet/webflow-apps-utils 1.0.5 → 1.0.7
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/stores/index.d.ts +1 -0
- package/dist/stores/index.js +1 -0
- package/dist/stores/isPreviewMode.d.ts +1 -0
- package/dist/stores/isPreviewMode.js +2 -0
- package/dist/types/dom.d.ts +1 -0
- package/dist/types/dom.js +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/webflow.d.ts +1 -1
- package/dist/ui/components/input/Input.svelte +18 -22
- package/dist/ui/components/layout/Layout.svelte +4 -2
- package/dist/ui/components/layout/Layout.svelte.d.ts +2 -0
- package/dist/ui/components/text/Text.svelte +4 -2
- package/dist/ui/components/text/types.d.ts +22 -0
- package/dist/ui/icons/ChevronIcon.svelte +1 -1
- package/dist/utils/constants.d.ts +5 -0
- package/dist/utils/constants.js +11 -0
- package/dist/utils/helpers/dom.d.ts +37 -0
- package/dist/utils/helpers/dom.js +104 -0
- package/dist/utils/helpers/encodeDecodeConfigs.d.ts +13 -0
- package/dist/utils/helpers/encodeDecodeConfigs.js +20 -0
- package/dist/utils/helpers/events.d.ts +19 -0
- package/dist/utils/helpers/events.js +28 -0
- package/dist/utils/helpers/forms.d.ts +22 -0
- package/dist/utils/helpers/forms.js +82 -0
- package/dist/utils/helpers/guards.d.ts +124 -0
- package/dist/utils/helpers/guards.js +107 -0
- package/dist/utils/helpers/index.d.ts +8 -0
- package/dist/utils/helpers/index.js +8 -0
- package/dist/utils/helpers/parseCSV.d.ts +6 -0
- package/dist/utils/helpers/parseCSV.js +29 -0
- package/dist/utils/helpers/string.d.ts +23 -0
- package/dist/utils/helpers/string.js +33 -0
- package/dist/utils/helpers/wait.d.ts +13 -0
- package/dist/utils/helpers/wait.js +27 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/webflow/CopyJSONButton.d.ts +54 -0
- package/dist/utils/webflow/CopyJSONButton.js +117 -0
- package/dist/utils/webflow/DisplayController.d.ts +55 -0
- package/dist/utils/webflow/DisplayController.js +91 -0
- package/dist/utils/webflow/Interaction.d.ts +47 -0
- package/dist/utils/webflow/Interaction.js +52 -0
- package/dist/utils/webflow/index.d.ts +4 -0
- package/dist/utils/webflow/index.js +4 -0
- package/dist/utils/webflow/webflow.d.ts +32 -0
- package/dist/utils/webflow/webflow.js +90 -0
- package/package.json +5 -6
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { animations } from '../animations';
|
|
2
|
+
import { isVisible } from '../helpers';
|
|
3
|
+
import { Interaction } from './Interaction';
|
|
4
|
+
/**
|
|
5
|
+
* Controls showing/hiding an element.
|
|
6
|
+
* Works with Webflow interactions, built-in fade animations or no animations at all.
|
|
7
|
+
*/
|
|
8
|
+
export class DisplayController {
|
|
9
|
+
interaction;
|
|
10
|
+
animation;
|
|
11
|
+
animationEasing;
|
|
12
|
+
animationDuration;
|
|
13
|
+
visible;
|
|
14
|
+
element;
|
|
15
|
+
constructor({ element, interaction, animation, startsHidden, animationEasing, animationDuration }) {
|
|
16
|
+
// Store properties
|
|
17
|
+
this.element = element;
|
|
18
|
+
this.animation = animation;
|
|
19
|
+
this.animationEasing = animationEasing;
|
|
20
|
+
this.animationDuration = animationDuration;
|
|
21
|
+
// Visibility check
|
|
22
|
+
if (startsHidden) {
|
|
23
|
+
this.element.style.display = 'none';
|
|
24
|
+
this.visible = false;
|
|
25
|
+
}
|
|
26
|
+
else
|
|
27
|
+
this.visible = isVisible(this.element);
|
|
28
|
+
if (interaction) {
|
|
29
|
+
const { element, duration } = interaction;
|
|
30
|
+
this.interaction = new Interaction({ element, duration });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @returns If the element is visible
|
|
35
|
+
*/
|
|
36
|
+
isVisible = () => this.visible;
|
|
37
|
+
/**
|
|
38
|
+
* Displays the element
|
|
39
|
+
* @returns An awaitable promise
|
|
40
|
+
*/
|
|
41
|
+
async show() {
|
|
42
|
+
if (this.visible)
|
|
43
|
+
return;
|
|
44
|
+
const { interaction, animation, element, animationDuration, animationEasing } = this;
|
|
45
|
+
const display = 'block';
|
|
46
|
+
// Interaction
|
|
47
|
+
if (interaction) {
|
|
48
|
+
await interaction.trigger('first');
|
|
49
|
+
}
|
|
50
|
+
// Animation
|
|
51
|
+
else if (animation) {
|
|
52
|
+
animations[animation].prepareIn(element, { display });
|
|
53
|
+
await animations[animation].animateIn(element, {
|
|
54
|
+
display,
|
|
55
|
+
duration: animationDuration,
|
|
56
|
+
easing: animationEasing
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// No interaction or animation
|
|
60
|
+
else {
|
|
61
|
+
element.style.display = display;
|
|
62
|
+
}
|
|
63
|
+
this.visible = true;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Hides the element
|
|
67
|
+
* @returns An awaitable promise
|
|
68
|
+
*/
|
|
69
|
+
async hide() {
|
|
70
|
+
if (!this.visible)
|
|
71
|
+
return;
|
|
72
|
+
const { interaction, animation, element, animationDuration, animationEasing } = this;
|
|
73
|
+
// Interaction
|
|
74
|
+
if (interaction) {
|
|
75
|
+
await interaction.trigger('second');
|
|
76
|
+
}
|
|
77
|
+
// Animation
|
|
78
|
+
else if (animation) {
|
|
79
|
+
await animations[animation].animateOut(element, {
|
|
80
|
+
display: 'none',
|
|
81
|
+
duration: animationDuration,
|
|
82
|
+
easing: animationEasing
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// No interaction or animation
|
|
86
|
+
else {
|
|
87
|
+
element.style.display = 'none';
|
|
88
|
+
}
|
|
89
|
+
this.visible = false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface InteractionParams {
|
|
2
|
+
/**
|
|
3
|
+
* The element that has a Webflow Ix2 Click interaction binded to it.
|
|
4
|
+
*/
|
|
5
|
+
element: HTMLElement | string;
|
|
6
|
+
/**
|
|
7
|
+
* The duration of the interaction.
|
|
8
|
+
* If a single number is passed, it will be used for both first and second interactions.
|
|
9
|
+
* If an object is passed, you can specify the duration for each interaction.
|
|
10
|
+
*/
|
|
11
|
+
duration?: number | Partial<Interaction['duration']>;
|
|
12
|
+
}
|
|
13
|
+
export declare class Interaction {
|
|
14
|
+
private readonly element;
|
|
15
|
+
private active;
|
|
16
|
+
private running;
|
|
17
|
+
private runningPromise?;
|
|
18
|
+
readonly duration: {
|
|
19
|
+
first: number;
|
|
20
|
+
second: number;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Acts as the controller for a Webflow Interaction.
|
|
24
|
+
* It accepts an element that will be clicked when required (firing a Mouse Click interaction).
|
|
25
|
+
* @param element Element that has the Mouse Click interaction.
|
|
26
|
+
* @param duration Optionally, the duration can be explicitly set so the trigger methods will return an awaitable Promise.
|
|
27
|
+
*/
|
|
28
|
+
constructor({ element, duration }: InteractionParams);
|
|
29
|
+
/**
|
|
30
|
+
* Trigger the interaction
|
|
31
|
+
* @param click Perform first or second click
|
|
32
|
+
* @returns True if the interaction was fired
|
|
33
|
+
*/
|
|
34
|
+
trigger(click?: 'first' | 'second'): Promise<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* @returns If the interaction is active
|
|
37
|
+
*/
|
|
38
|
+
isActive: () => boolean;
|
|
39
|
+
/**
|
|
40
|
+
* @returns If the interaction is running
|
|
41
|
+
*/
|
|
42
|
+
isRunning: () => boolean;
|
|
43
|
+
/**
|
|
44
|
+
* @returns A promise that fulfills when the current running interaction has finished
|
|
45
|
+
*/
|
|
46
|
+
untilFinished: () => Promise<unknown> | undefined;
|
|
47
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { simulateEvent, wait } from '../helpers';
|
|
2
|
+
export class Interaction {
|
|
3
|
+
element;
|
|
4
|
+
active = false;
|
|
5
|
+
running = false;
|
|
6
|
+
runningPromise;
|
|
7
|
+
duration;
|
|
8
|
+
/**
|
|
9
|
+
* Acts as the controller for a Webflow Interaction.
|
|
10
|
+
* It accepts an element that will be clicked when required (firing a Mouse Click interaction).
|
|
11
|
+
* @param element Element that has the Mouse Click interaction.
|
|
12
|
+
* @param duration Optionally, the duration can be explicitly set so the trigger methods will return an awaitable Promise.
|
|
13
|
+
*/
|
|
14
|
+
constructor({ element, duration }) {
|
|
15
|
+
this.element =
|
|
16
|
+
typeof element === 'string' ? document.querySelector(element) : element;
|
|
17
|
+
this.duration = {
|
|
18
|
+
first: typeof duration === 'number' ? duration : (duration?.first ?? 0),
|
|
19
|
+
second: typeof duration === 'number' ? duration : (duration?.second ?? 0)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Trigger the interaction
|
|
24
|
+
* @param click Perform first or second click
|
|
25
|
+
* @returns True if the interaction was fired
|
|
26
|
+
*/
|
|
27
|
+
async trigger(click) {
|
|
28
|
+
if ((click === 'first' && this.active) || (click === 'second' && !this.active))
|
|
29
|
+
return false;
|
|
30
|
+
if (!click)
|
|
31
|
+
click = this.active ? 'second' : 'first';
|
|
32
|
+
simulateEvent(this.element, 'click');
|
|
33
|
+
this.running = true;
|
|
34
|
+
this.runningPromise = wait(this.duration[click]);
|
|
35
|
+
await this.runningPromise;
|
|
36
|
+
this.running = false;
|
|
37
|
+
this.active = click === 'first';
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* @returns If the interaction is active
|
|
42
|
+
*/
|
|
43
|
+
isActive = () => this.active;
|
|
44
|
+
/**
|
|
45
|
+
* @returns If the interaction is running
|
|
46
|
+
*/
|
|
47
|
+
isRunning = () => this.running;
|
|
48
|
+
/**
|
|
49
|
+
* @returns A promise that fulfills when the current running interaction has finished
|
|
50
|
+
*/
|
|
51
|
+
untilFinished = () => this.runningPromise;
|
|
52
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { WebflowModule } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* @returns The Webflow Site ID of the website.
|
|
4
|
+
* @param page The page to get the site ID from. Defaults to the current page.
|
|
5
|
+
*/
|
|
6
|
+
export declare const getSiteId: (page?: Document) => string | null;
|
|
7
|
+
/**
|
|
8
|
+
* Extracts the publish date of a Webflow site
|
|
9
|
+
* @returns A Date object, if found.
|
|
10
|
+
* @param page The page to get the publish date from. Defaults to the current page.
|
|
11
|
+
*/
|
|
12
|
+
export declare const getPublishDate: (page?: Document) => Date | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Restarts the Webflow JS library.
|
|
15
|
+
*
|
|
16
|
+
* @param modules An array of {@link WebflowModule} to restart. If passed, only those modules will be restarted instead of the whole `Webflow` instance.
|
|
17
|
+
*
|
|
18
|
+
* @returns An awaitable promise that is fulfilled when the library has been correctly reinitialized.
|
|
19
|
+
*/
|
|
20
|
+
export declare const restartWebflow: (modules?: WebflowModule[]) => Promise<unknown>;
|
|
21
|
+
export declare const FORM_CSS_CLASSES: {
|
|
22
|
+
readonly formBlock: "w-form";
|
|
23
|
+
readonly checkboxField: "w-checkbox";
|
|
24
|
+
readonly checkboxInput: "w-checkbox-input";
|
|
25
|
+
readonly radioField: "w-radio";
|
|
26
|
+
readonly radioInput: "w-radio-input";
|
|
27
|
+
readonly checkboxOrRadioLabel: "w-form-label";
|
|
28
|
+
readonly checkboxOrRadioFocus: "w--redirected-focus";
|
|
29
|
+
readonly checkboxOrRadioChecked: "w--redirected-checked";
|
|
30
|
+
readonly successMessage: "w-form-done";
|
|
31
|
+
readonly errorMessage: "w-form-fail";
|
|
32
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @returns The Webflow Site ID of the website.
|
|
3
|
+
* @param page The page to get the site ID from. Defaults to the current page.
|
|
4
|
+
*/
|
|
5
|
+
export const getSiteId = (page = document) => page.documentElement.getAttribute('data-wf-site');
|
|
6
|
+
/**
|
|
7
|
+
* Extracts the publish date of a Webflow site
|
|
8
|
+
* @returns A Date object, if found.
|
|
9
|
+
* @param page The page to get the publish date from. Defaults to the current page.
|
|
10
|
+
*/
|
|
11
|
+
export const getPublishDate = (page = document) => {
|
|
12
|
+
const publishDatePrefix = 'Last Published:';
|
|
13
|
+
for (const node of Array.from(page.childNodes)) {
|
|
14
|
+
if (node.nodeType === Node.COMMENT_NODE && node.textContent?.includes(publishDatePrefix)) {
|
|
15
|
+
const publishDateValue = node.textContent.trim().split(publishDatePrefix)[1];
|
|
16
|
+
if (publishDateValue)
|
|
17
|
+
return new Date(publishDateValue);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Restarts the Webflow JS library.
|
|
23
|
+
*
|
|
24
|
+
* @param modules An array of {@link WebflowModule} to restart. If passed, only those modules will be restarted instead of the whole `Webflow` instance.
|
|
25
|
+
*
|
|
26
|
+
* @returns An awaitable promise that is fulfilled when the library has been correctly reinitialized.
|
|
27
|
+
*/
|
|
28
|
+
export const restartWebflow = async (modules) => {
|
|
29
|
+
const { Webflow } = window;
|
|
30
|
+
if (!Webflow || !('destroy' in Webflow) || !('ready' in Webflow) || !('require' in Webflow))
|
|
31
|
+
return;
|
|
32
|
+
if (modules && !modules.length)
|
|
33
|
+
return;
|
|
34
|
+
// Global
|
|
35
|
+
if (!modules) {
|
|
36
|
+
Webflow.destroy();
|
|
37
|
+
Webflow.ready();
|
|
38
|
+
}
|
|
39
|
+
// IX2
|
|
40
|
+
if (!modules || modules.includes('ix2')) {
|
|
41
|
+
const ix2 = Webflow.require('ix2');
|
|
42
|
+
if (ix2) {
|
|
43
|
+
// const { store, actions } = ix2;
|
|
44
|
+
// const { eventState } = store.getState().ixSession;
|
|
45
|
+
// const stateEntries = Object.entries(eventState);
|
|
46
|
+
// if (stateEntries?.length > 0) {
|
|
47
|
+
// if (!modules)
|
|
48
|
+
// await Promise.all(stateEntries.map((state) => store.dispatch(actions.eventStateChanged(...state))));
|
|
49
|
+
// }
|
|
50
|
+
ix2.destroy();
|
|
51
|
+
ix2.init();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Commerce
|
|
55
|
+
if (!modules || modules.includes('commerce')) {
|
|
56
|
+
const commerce = Webflow.require('commerce');
|
|
57
|
+
const siteId = getSiteId();
|
|
58
|
+
if (commerce && siteId) {
|
|
59
|
+
commerce.destroy();
|
|
60
|
+
commerce.init({ siteId, apiUrl: 'https://render.webflow.com' });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Lightbox
|
|
64
|
+
if (modules?.includes('lightbox'))
|
|
65
|
+
Webflow.require('lightbox')?.ready();
|
|
66
|
+
// Slider
|
|
67
|
+
if (modules?.includes('slider')) {
|
|
68
|
+
const slider = Webflow.require('slider');
|
|
69
|
+
if (slider) {
|
|
70
|
+
slider.redraw();
|
|
71
|
+
slider.ready();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Tabs
|
|
75
|
+
if (modules?.includes('tabs'))
|
|
76
|
+
Webflow.require('tabs')?.redraw();
|
|
77
|
+
return new Promise((resolve) => Webflow.push(() => resolve(undefined)));
|
|
78
|
+
};
|
|
79
|
+
export const FORM_CSS_CLASSES = {
|
|
80
|
+
formBlock: 'w-form',
|
|
81
|
+
checkboxField: 'w-checkbox',
|
|
82
|
+
checkboxInput: 'w-checkbox-input',
|
|
83
|
+
radioField: 'w-radio',
|
|
84
|
+
radioInput: 'w-radio-input',
|
|
85
|
+
checkboxOrRadioLabel: 'w-form-label',
|
|
86
|
+
checkboxOrRadioFocus: 'w--redirected-focus',
|
|
87
|
+
checkboxOrRadioChecked: 'w--redirected-checked',
|
|
88
|
+
successMessage: 'w-form-done',
|
|
89
|
+
errorMessage: 'w-form-fail'
|
|
90
|
+
};
|
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.7",
|
|
4
4
|
"description": "Shared utilities for Webflow apps",
|
|
5
5
|
"homepage": "https://github.com/finsweet/webflow-apps-utils",
|
|
6
6
|
"repository": {
|
|
@@ -15,13 +15,12 @@
|
|
|
15
15
|
"sideEffects": [
|
|
16
16
|
"**/*.css"
|
|
17
17
|
],
|
|
18
|
-
"svelte": "./dist/index.js",
|
|
19
|
-
"types": "./dist/index.d.ts",
|
|
20
18
|
"type": "module",
|
|
21
19
|
"exports": {
|
|
22
20
|
".": {
|
|
23
21
|
"types": "./dist/index.d.ts",
|
|
24
|
-
"svelte": "./dist/index.js"
|
|
22
|
+
"svelte": "./dist/index.js",
|
|
23
|
+
"default": "./dist/index.js"
|
|
25
24
|
},
|
|
26
25
|
"./index.css": "./dist/ui/index.css"
|
|
27
26
|
},
|
|
@@ -50,7 +49,6 @@
|
|
|
50
49
|
"@types/js-cookie": "^3.0.6",
|
|
51
50
|
"@types/lodash": "^4.17.18",
|
|
52
51
|
"@types/lodash-es": "^4.17.12",
|
|
53
|
-
"@types/lodash.isequal": "^4.5.8",
|
|
54
52
|
"@types/luxon": "^3.6.2",
|
|
55
53
|
"@types/node": "^22",
|
|
56
54
|
"@vitest/browser": "3.2.3",
|
|
@@ -79,12 +77,13 @@
|
|
|
79
77
|
],
|
|
80
78
|
"dependencies": {
|
|
81
79
|
"@floating-ui/dom": "^1.7.1",
|
|
80
|
+
"cheerio": "^1.1.0",
|
|
82
81
|
"clipboard": "^2.0.11",
|
|
82
|
+
"csv-parse": "^5.6.0",
|
|
83
83
|
"js-cookie": "^3.0.5",
|
|
84
84
|
"just-debounce": "^1.1.0",
|
|
85
85
|
"lodash": "^4.17.21",
|
|
86
86
|
"lodash-es": "^4.17.21",
|
|
87
|
-
"lodash.isequal": "^4.5.0",
|
|
88
87
|
"logrocket": "^10.1.0",
|
|
89
88
|
"luxon": "^3.6.1",
|
|
90
89
|
"motion": "^10.18.0",
|