@finsweet/webflow-apps-utils 1.0.3 → 1.0.4

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 (95) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/router/Router.mdx +958 -0
  4. package/dist/router/Router.stories.d.ts +6 -0
  5. package/dist/router/Router.stories.js +47 -0
  6. package/dist/router/examples/RouterExample.svelte +271 -0
  7. package/dist/router/examples/RouterExample.svelte.d.ts +18 -0
  8. package/dist/router/examples/index.d.ts +4 -0
  9. package/dist/router/examples/index.js +4 -0
  10. package/dist/router/examples/pages/AboutPage.svelte +568 -0
  11. package/dist/router/examples/pages/AboutPage.svelte.d.ts +13 -0
  12. package/dist/router/examples/pages/HomePage.svelte +200 -0
  13. package/dist/router/examples/pages/HomePage.svelte.d.ts +14 -0
  14. package/dist/router/examples/pages/NotFoundPage.svelte +307 -0
  15. package/dist/router/examples/pages/NotFoundPage.svelte.d.ts +17 -0
  16. package/dist/router/hooks.svelte.d.ts +2 -2
  17. package/dist/router/index.d.ts +3 -0
  18. package/dist/router/index.js +3 -0
  19. package/dist/router/{Link.svelte → providers/Link.svelte} +1 -1
  20. package/dist/router/{Route.svelte → providers/Route.svelte} +1 -1
  21. package/dist/router/{Route.svelte.d.ts → providers/Route.svelte.d.ts} +1 -1
  22. package/dist/router/{Router.svelte → providers/RouterProvider.svelte} +22 -5
  23. package/dist/router/{Router.svelte.d.ts → providers/RouterProvider.svelte.d.ts} +8 -4
  24. package/dist/router/providers/index.d.ts +3 -0
  25. package/dist/router/providers/index.js +3 -0
  26. package/dist/router/{index.svelte.d.ts → router.svelte.d.ts} +1 -3
  27. package/dist/router/{index.svelte.js → router.svelte.js} +1 -4
  28. package/dist/stores/docs/Form.mdx +542 -0
  29. package/dist/stores/forms.d.ts +41 -4
  30. package/dist/stores/forms.js +86 -32
  31. package/dist/types/customCode.d.ts +1 -1
  32. package/dist/types/window.d.ts +1 -0
  33. package/dist/ui/components/copy-text/CopyText.stories.d.ts +70 -0
  34. package/dist/ui/components/copy-text/CopyText.stories.js +241 -0
  35. package/dist/ui/components/copy-text/CopyText.svelte +249 -0
  36. package/dist/ui/components/copy-text/CopyText.svelte.d.ts +4 -0
  37. package/dist/ui/components/copy-text/index.d.ts +2 -0
  38. package/dist/ui/components/copy-text/index.js +1 -0
  39. package/dist/ui/components/copy-text/types.d.ts +52 -0
  40. package/dist/ui/components/copy-text/types.js +1 -0
  41. package/dist/ui/components/index.d.ts +1 -0
  42. package/dist/ui/components/index.js +1 -0
  43. package/dist/ui/components/input/Input.stories.d.ts +9 -0
  44. package/dist/ui/components/input/Input.stories.js +78 -0
  45. package/dist/ui/components/input/Input.svelte +39 -3
  46. package/dist/ui/components/input/types.d.ts +6 -0
  47. package/dist/ui/components/layout/Layout.svelte +7 -59
  48. package/dist/ui/components/layout/Layout.svelte.d.ts +2 -2
  49. package/dist/ui/components/layout/examples/ExampleLayout.svelte +22 -17
  50. package/dist/ui/components/layout/index.d.ts +1 -1
  51. package/dist/ui/components/layout/test-helpers/TestLayoutWithFooter.svelte +20 -0
  52. package/dist/ui/components/layout/test-helpers/TestLayoutWithFooter.svelte.d.ts +7 -0
  53. package/dist/ui/components/layout/types.d.ts +1 -10
  54. package/dist/ui/components/notification/Notification.stories.svelte +12 -1
  55. package/dist/ui/components/notification/Notification.svelte +10 -5
  56. package/dist/ui/components/notification/Notification.svelte.d.ts +1 -1
  57. package/dist/ui/components/notification/types.d.ts +1 -1
  58. package/dist/ui/components/section/Section.svelte +4 -2
  59. package/dist/ui/components/section/types.d.ts +8 -0
  60. package/dist/ui/components/text/Text.stories.svelte +67 -1
  61. package/dist/ui/components/text/Text.svelte +209 -8
  62. package/dist/ui/components/text/types.d.ts +4 -0
  63. package/dist/utils/animations/factory.d.ts +7 -0
  64. package/dist/utils/animations/factory.js +101 -0
  65. package/dist/utils/animations/index.d.ts +7 -0
  66. package/dist/utils/animations/index.js +62 -0
  67. package/dist/utils/animations/types.d.ts +39 -0
  68. package/dist/utils/animations/types.js +1 -0
  69. package/dist/utils/custom-code/configs.d.ts +22 -0
  70. package/dist/utils/custom-code/configs.js +40 -0
  71. package/dist/utils/custom-code/index.d.ts +1 -0
  72. package/dist/utils/custom-code/index.js +1 -0
  73. package/dist/utils/helpers/capitalizeFirstLetter.d.ts +4 -0
  74. package/dist/utils/helpers/capitalizeFirstLetter.js +9 -0
  75. package/dist/utils/helpers/getTimeNow.d.ts +4 -0
  76. package/dist/utils/helpers/getTimeNow.js +8 -0
  77. package/dist/utils/helpers/index.d.ts +4 -0
  78. package/dist/utils/helpers/index.js +4 -0
  79. package/dist/utils/helpers/minifyCode.d.ts +10 -0
  80. package/dist/utils/helpers/minifyCode.js +73 -0
  81. package/dist/utils/helpers/objectsToModuleExports.d.ts +1 -1
  82. package/dist/utils/helpers/objectsToModuleExports.js +1 -0
  83. package/dist/utils/helpers/toHumanReadableList.d.ts +4 -0
  84. package/dist/utils/helpers/toHumanReadableList.js +11 -0
  85. package/dist/utils/index.d.ts +1 -0
  86. package/dist/utils/index.js +1 -0
  87. package/dist/utils/webflow-canvas/getAllChildren.d.ts +16 -0
  88. package/dist/utils/webflow-canvas/getAllChildren.js +65 -0
  89. package/dist/utils/webflow-canvas/getElementClassList.d.ts +9 -0
  90. package/dist/utils/webflow-canvas/getElementClassList.js +19 -0
  91. package/dist/utils/webflow-canvas/index.d.ts +2 -0
  92. package/dist/utils/webflow-canvas/index.js +2 -0
  93. package/package.json +6 -1
  94. package/dist/router/README.md +0 -397
  95. /package/dist/router/{Link.svelte.d.ts → providers/Link.svelte.d.ts} +0 -0
@@ -0,0 +1,101 @@
1
+ import { animate, stagger as staggerDelay } from 'motion';
2
+ /**
3
+ * Creates a new Animation.
4
+ * @param props The animaiton props.
5
+ * @returns A new `in` and `out` Animation functions.
6
+ */
7
+ export const createAnimation = ({ initialStyles, keyframes }) => {
8
+ const isBrowser = typeof window !== 'undefined';
9
+ /**
10
+ * Prepares the {@link animateIn} elements by setting the initial styles and rendering them to the DOM.
11
+ * @param elements The elements to prepare.
12
+ * @param options.target If defined, the element will be appended to the target.
13
+ * @param options.insertAfter A child of the target. If defined, the element will be appended right after this anchor element.
14
+ */
15
+ const prepareIn = (elements, options = {}) => {
16
+ const { target, insertAfter, display = '' } = options;
17
+ if (!Array.isArray(elements))
18
+ elements = [elements];
19
+ for (const element of elements) {
20
+ element.style.display = display;
21
+ Object.assign(element.style, initialStyles);
22
+ if (target && insertAfter !== undefined) {
23
+ if (insertAfter)
24
+ target.insertBefore(element, insertAfter.nextSibling);
25
+ else {
26
+ if (isBrowser && target instanceof HTMLElement) {
27
+ target.insertBefore(element, target.firstChild);
28
+ }
29
+ }
30
+ }
31
+ else if (target)
32
+ target.appendChild(element);
33
+ }
34
+ };
35
+ /**
36
+ * In animation.
37
+ * @param elements The elements to animate.
38
+ * @param options.target If defined, the element will be appended to the target.
39
+ * @param options.insertAfter A child of the target. If defined, the element will be appended right after this anchor element.
40
+ * @param options.prepared Defines if the animation has been prepared beforehand, useful to avoid performing double preparation.
41
+ * @param options.stagger If defined, the animation will be staggered using this time value.
42
+ * @param options.animationOptions The main options of the animation. Reference: {@link [Motion One](https://motion.dev/dom/animate#options)}.
43
+ * @returns An awaitable promise.
44
+ */
45
+ const animateIn = async (elements, options = {}) => {
46
+ //TODO: probably display can be used also?
47
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
48
+ const { prepared, stagger, display, duration, ...animationOptions } = options;
49
+ const durationInSeconds = duration ? duration / 1000 : undefined;
50
+ if (!prepared)
51
+ prepareIn(elements, options);
52
+ const { finished } = animate(elements, keyframes, {
53
+ ...animationOptions,
54
+ delay: stagger ? staggerDelay(stagger / 1000) : undefined,
55
+ duration: durationInSeconds
56
+ });
57
+ return await finished;
58
+ };
59
+ /**
60
+ * Out animation.
61
+ * @param elements The elements to animate.
62
+ * @param options.remove If defined, the element will be removed from the DOM after the animation ends.
63
+ * @param options.stagger If defined, the animation will be staggered using this time value.
64
+ * @param options.animationOptions The main options of the animation. Reference: {@link [Motion One](https://motion.dev/dom/animate#options)}.
65
+ * @returns An awaitable promise.
66
+ */
67
+ const animateOut = async (elements, options = {}) => {
68
+ const { remove, stagger, target, insertAfter, display = 'none', duration, ...animationOptions } = options;
69
+ const durationInSeconds = duration ? duration / 1000 : undefined;
70
+ if (!Array.isArray(elements))
71
+ elements = [elements];
72
+ elements = elements.filter((element) => document.body.contains(element));
73
+ if (!elements.length)
74
+ return;
75
+ const { finished } = animate(elements, keyframes, {
76
+ ...animationOptions,
77
+ duration: durationInSeconds,
78
+ delay: stagger ? staggerDelay(stagger / 1000) : undefined,
79
+ direction: 'reverse'
80
+ });
81
+ await finished;
82
+ for (const element of elements) {
83
+ if (target && insertAfter !== undefined) {
84
+ if (insertAfter)
85
+ target.insertBefore(element, insertAfter.nextSibling);
86
+ else {
87
+ if (isBrowser && target instanceof HTMLElement) {
88
+ target.insertBefore(element, target.firstChild);
89
+ }
90
+ }
91
+ }
92
+ else if (target)
93
+ target.appendChild(element);
94
+ if (remove)
95
+ element.remove();
96
+ else
97
+ element.style.display = display;
98
+ }
99
+ };
100
+ return { prepareIn, animateIn, animateOut };
101
+ };
@@ -0,0 +1,7 @@
1
+ import type { AnimationsObject } from './types';
2
+ export * from './types';
3
+ export declare const easings: readonly ["linear", "ease", "ease-in", "ease-out", "ease-in-out"];
4
+ /**
5
+ * Contains all animation functions.
6
+ */
7
+ export declare const animations: AnimationsObject;
@@ -0,0 +1,62 @@
1
+ import { createAnimation } from './factory';
2
+ export * from './types';
3
+ // Constants
4
+ export const easings = ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out'];
5
+ /**
6
+ * Contains all animation functions.
7
+ */
8
+ export const animations = {
9
+ /**
10
+ * Fade
11
+ */
12
+ fade: createAnimation({ keyframes: { opacity: [0, 1] }, initialStyles: { opacity: '0' } }),
13
+ /**
14
+ * Slide Up
15
+ */
16
+ 'slide-up': createAnimation({
17
+ keyframes: { y: [100, 0], opacity: [0, 1] },
18
+ initialStyles: { transform: 'translateY(100px)', opacity: '0' }
19
+ }),
20
+ /**
21
+ * Slide Down
22
+ */
23
+ 'slide-down': createAnimation({
24
+ keyframes: { y: [-100, 0], opacity: [0, 1] },
25
+ initialStyles: { transform: 'translateY(-100px)', opacity: '0' }
26
+ }),
27
+ /**
28
+ * Slide Right
29
+ */
30
+ 'slide-right': createAnimation({
31
+ keyframes: { x: [-100, 0], opacity: [0, 1] },
32
+ initialStyles: { transform: 'translateX(-100px)', opacity: '0' }
33
+ }),
34
+ /**
35
+ * Slide Left
36
+ */
37
+ 'slide-left': createAnimation({
38
+ keyframes: { x: [100, 0], opacity: [0, 1] },
39
+ initialStyles: { transform: 'translateX(100px)', opacity: '0' }
40
+ }),
41
+ /**
42
+ * Grow
43
+ */
44
+ grow: createAnimation({
45
+ keyframes: { scale: [0, 1], opacity: [0, 1] },
46
+ initialStyles: { transform: 'scale(0)', opacity: '0' }
47
+ }),
48
+ /**
49
+ * Shrink
50
+ */
51
+ shrink: createAnimation({
52
+ keyframes: { scale: [1.25, 1], opacity: [0, 1] },
53
+ initialStyles: { transform: 'scale(1.25)', opacity: '0' }
54
+ }),
55
+ /**
56
+ * Spin
57
+ */
58
+ spin: createAnimation({
59
+ keyframes: { rotate: [900, 0], opacity: [0, 1] },
60
+ initialStyles: { transform: 'rotate(900deg)', opacity: '0' }
61
+ })
62
+ };
@@ -0,0 +1,39 @@
1
+ import type { AnimationOptions, MotionKeyframesDefinition } from 'motion';
2
+ import type { easings } from '.';
3
+ export interface AnimationProps {
4
+ keyframes: MotionKeyframesDefinition;
5
+ initialStyles: {
6
+ [key: string]: string;
7
+ };
8
+ }
9
+ type FilteredAnimationOptions = Pick<AnimationOptions, 'duration' | 'easing'> & {
10
+ stagger?: number;
11
+ };
12
+ type AnimationPrepare<T> = (element: HTMLElement | HTMLElement[], options?: T) => void;
13
+ type AnimationBase<T> = (element: HTMLElement | HTMLElement[], options?: T & FilteredAnimationOptions) => Promise<void>;
14
+ type PrepareProps = {
15
+ target?: Element;
16
+ insertAfter?: Node | null;
17
+ display?: string;
18
+ };
19
+ type AnimationInProps = PrepareProps & {
20
+ prepared?: true;
21
+ };
22
+ type AnimationOutProps = PrepareProps & {
23
+ remove?: boolean;
24
+ };
25
+ type PrepareIn = AnimationPrepare<PrepareProps>;
26
+ type AnimationIn = AnimationBase<AnimationInProps>;
27
+ type AnimationOut = AnimationBase<AnimationOutProps>;
28
+ export type AnimationFunctions = {
29
+ prepareIn: PrepareIn;
30
+ animateIn: AnimationIn;
31
+ animateOut: AnimationOut;
32
+ };
33
+ export type Animation = AnimationFunctions & {
34
+ options?: FilteredAnimationOptions;
35
+ };
36
+ export type AnimationsObject = Readonly<Record<'fade' | 'slide-up' | 'slide-down' | 'slide-right' | 'slide-left' | 'grow' | 'shrink' | 'spin', AnimationFunctions>>;
37
+ export type Easings = typeof easings;
38
+ export type AnimationOptionsCustom = Readonly<Record<'fade' | 'slide-up' | 'slide-down' | 'slide-right' | 'slide-left' | 'grow' | 'shrink' | 'spin', string>>;
39
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Store for Custom Code stored Component configs
3
+ */
4
+ export declare const componentConfigsStore: import("svelte/store").Writable<null>;
5
+ export type CustomCodeConfigsStore = {
6
+ component: string;
7
+ instance: string[];
8
+ }[];
9
+ /**
10
+ * Store for Custom Code stored Component configs instances
11
+ */
12
+ export declare const customCodeConfigsStore: import("svelte/store").Writable<CustomCodeConfigsStore>;
13
+ /**
14
+ * Get configs from custom code.
15
+ */
16
+ export declare const getProjectConfigs: () => Promise<any>;
17
+ /**
18
+ * Fetches configs stored in custom code for a given component.
19
+ * @param component
20
+ * @returns
21
+ */
22
+ export declare const getComponentConfigs: (component: string) => Promise<any>;
@@ -0,0 +1,40 @@
1
+ import { writable } from 'svelte/store';
2
+ import { getLogger } from '../logger';
3
+ import { getCustomCode } from './api';
4
+ const logger = getLogger('utils');
5
+ const DISPLAY_NAME = 'finsweetcomponentsconfig';
6
+ /**
7
+ * Store for Custom Code stored Component configs
8
+ */
9
+ export const componentConfigsStore = writable(null);
10
+ /**
11
+ * Store for Custom Code stored Component configs instances
12
+ */
13
+ export const customCodeConfigsStore = writable([]);
14
+ /**
15
+ * Get configs from custom code.
16
+ */
17
+ export const getProjectConfigs = async () => {
18
+ const [customCodeBlock] = await getCustomCode(DISPLAY_NAME);
19
+ if (!customCodeBlock || !customCodeBlock.hostedLocation) {
20
+ return null;
21
+ }
22
+ // activate loading state to block iife scripts
23
+ window.isLoadingCustomCodeConfigs = true;
24
+ const configs = await import(/* @vite-ignore */ customCodeBlock.hostedLocation);
25
+ window.isLoadingCustomCodeConfigs = false;
26
+ customCodeConfigsStore.set(configs);
27
+ logger.log({}, 'Project custom code configs', configs);
28
+ return configs;
29
+ };
30
+ /**
31
+ * Fetches configs stored in custom code for a given component.
32
+ * @param component
33
+ * @returns
34
+ */
35
+ export const getComponentConfigs = async (component) => {
36
+ const customCodeBlock = await getProjectConfigs();
37
+ if (!customCodeBlock || Object.keys(customCodeBlock[component]).length === 0)
38
+ return null;
39
+ return customCodeBlock[component];
40
+ };
@@ -1 +1,2 @@
1
1
  export * from './api';
2
+ export * from './configs';
@@ -1 +1,2 @@
1
1
  export * from './api';
2
+ export * from './configs';
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Capitalizes the first letter of each word in a comma-separated string and adds a space after commas.
3
+ */
4
+ export declare const capitalizeFirstLetter: (input: string) => string;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Capitalizes the first letter of each word in a comma-separated string and adds a space after commas.
3
+ */
4
+ export const capitalizeFirstLetter = (input) => {
5
+ return input
6
+ .split(',')
7
+ .map((word) => `${word.charAt(0).toUpperCase()}${word.slice(1)}`)
8
+ .join(', ');
9
+ };
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Generate a string with the current date and time in ISO format.
3
+ */
4
+ export declare const getTimeNow: () => string;
@@ -0,0 +1,8 @@
1
+ import { DateTime } from 'luxon';
2
+ /**
3
+ * Generate a string with the current date and time in ISO format.
4
+ */
5
+ export const getTimeNow = () => {
6
+ const now = DateTime.local();
7
+ return `${now.toFormat('MMMM d, yyyy, h:mma')}`;
8
+ };
@@ -1,6 +1,10 @@
1
+ export * from './capitalizeFirstLetter';
1
2
  export * from './cleanupTooltipMessage';
2
3
  export * from './goto';
4
+ export * from './getTimeNow';
5
+ export * from './minifyCode';
3
6
  export * from './noop';
4
7
  export * from './numbers';
5
8
  export * from './objectsToModuleExports';
6
9
  export * from './trimText';
10
+ export * from './toHumanReadableList';
@@ -1,6 +1,10 @@
1
+ export * from './capitalizeFirstLetter';
1
2
  export * from './cleanupTooltipMessage';
2
3
  export * from './goto';
4
+ export * from './getTimeNow';
5
+ export * from './minifyCode';
3
6
  export * from './noop';
4
7
  export * from './numbers';
5
8
  export * from './objectsToModuleExports';
6
9
  export * from './trimText';
10
+ export * from './toHumanReadableList';
@@ -0,0 +1,10 @@
1
+ import { type MinifyOptions } from 'terser';
2
+ /**
3
+ * Minifies the provided JavaScript code string.
4
+ */
5
+ export declare const minifyCode: (code: string, options?: MinifyOptions) => Promise<string>;
6
+ /**
7
+ * Core script as a string.
8
+ * TODO: temporary, migrate it to a re-usable util
9
+ */
10
+ export declare const createScriptContent: (coreScript: string) => string;
@@ -0,0 +1,73 @@
1
+ import { minify } from 'terser';
2
+ /**
3
+ * Minifies the provided JavaScript code string.
4
+ */
5
+ export const minifyCode = async (code, options) => {
6
+ try {
7
+ const result = await minify(code, options);
8
+ if (result.code) {
9
+ return result.code;
10
+ }
11
+ throw new Error('Minification failed: No output code produced.');
12
+ }
13
+ catch (error) {
14
+ if (error instanceof Error) {
15
+ // Handle specific Error object
16
+ throw new Error(`Minification error: ${error.message}`);
17
+ }
18
+ else {
19
+ // Handle unknown error types
20
+ throw new Error(`Unexpected error: ${String(error)}`);
21
+ }
22
+ }
23
+ };
24
+ /**
25
+ * Core script as a string.
26
+ * TODO: temporary, migrate it to a re-usable util
27
+ */
28
+ export const createScriptContent = (coreScript) => {
29
+ const scriptToAdd = `
30
+ const injectStyles = () => {
31
+ const curr = document.querySelector(\`style[fs-components-cloak]\`);
32
+ curr?.remove();
33
+ const cloak = document.createElement('style');
34
+ cloak.setAttribute('fs-components-cloak', 'cloak');
35
+ cloak.textContent = \`
36
+ [fs-marquee-instance],[fs-cnumbercount-instance]{ opacity: 0; }
37
+ [fs-consent-element="internal-component"],[fs-consent-element="banner"],[fs-consent-element="fixed-preferences"],[fs-consent-element="preferences"],[fs-consent-element="interaction"]{display:none}
38
+ \`;
39
+ document.head.appendChild(cloak);
40
+ };
41
+ const initFsComponents = async (url) => {
42
+ injectStyles();
43
+ // happens in-app, check to prevent script being invoked in-app
44
+ const configsLoading = window?.finsweetComponentsConfigLoading;
45
+
46
+ const found = document?.querySelector("script[fs-components-src]");
47
+ if (typeof import.meta !== "undefined" && !(found || configsLoading)) {
48
+ const corescript = document?.querySelector(
49
+ 'script[finsweet="components"][async][type="module"]'
50
+ );
51
+
52
+ const appConfigs = (await import(/* @vite-ignore */ import.meta.url));
53
+ const components = Object.keys(appConfigs) || [];
54
+
55
+ return new Promise((resolve, reject) => {
56
+ const script = document.createElement("script");
57
+ const srcUrl = url + "?v=" + new Date().getTime();
58
+ script.src = srcUrl;
59
+ script.type = "module";
60
+ script.async = true;
61
+ script.setAttribute("fs-components-src", import.meta.url);
62
+ script.setAttribute("fs-components-installed", components?.join(","));
63
+ script.onload = () => resolve();
64
+ script.onerror = () => reject(new Error("Failed to load script"));
65
+ document.head.appendChild(script);
66
+ });
67
+ }
68
+ };
69
+
70
+ // Load dev script
71
+ initFsComponents("${coreScript}");`;
72
+ return scriptToAdd;
73
+ };
@@ -3,5 +3,5 @@
3
3
  */
4
4
  export declare const objectsToModuleExports: (exportsArray: Array<{
5
5
  moduleName: string;
6
- data: object;
6
+ data: any;
7
7
  }>) => string;
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  /**
2
3
  * Converts an array of objects to module export statements.
3
4
  */
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Converts an array of strings into a human-readable list by adding commas and "and" before the last item.
3
+ */
4
+ export declare const toHumanReadableList: (arr: string[], conjunction?: string) => string;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Converts an array of strings into a human-readable list by adding commas and "and" before the last item.
3
+ */
4
+ export const toHumanReadableList = (arr, conjunction = 'and') => {
5
+ const len = arr.length;
6
+ if (len === 0)
7
+ return '';
8
+ if (len === 1)
9
+ return arr[0];
10
+ return `${arr.slice(0, -1).join(', ')} ${conjunction} ${arr[len - 1]}`;
11
+ };
@@ -1,3 +1,4 @@
1
+ export * from './animations';
1
2
  export * from './api';
2
3
  export * from './auth';
3
4
  export * from './browser-storage';
@@ -1,3 +1,4 @@
1
+ export * from './animations';
1
2
  export * from './api';
2
3
  export * from './auth';
3
4
  export * from './browser-storage';
@@ -0,0 +1,16 @@
1
+ export interface ElementChildren {
2
+ attribute: string | null;
3
+ customAttributes: NamedValue[] | null;
4
+ element: AnyElement;
5
+ parent: AnyElement | null;
6
+ }
7
+ /**
8
+ * Recursively fetches children elements and attributes.
9
+ *
10
+ * @param element - The root element.
11
+ * @param attributeName - The attribute name to fetch.
12
+ * @param parent - The parent of the current element.
13
+ * @param className - The class name to fetch.
14
+ * @returns - Promise of array containing elements and their children recursively.
15
+ */
16
+ export declare const getAllChildren: (element: AnyElement, attributeName?: string, parent?: AnyElement | null, className?: string) => Promise<ElementChildren[]>;
@@ -0,0 +1,65 @@
1
+ import { getWebflowElementAttribute } from './attributes';
2
+ /**
3
+ * Recursively fetches children elements and attributes.
4
+ *
5
+ * @param element - The root element.
6
+ * @param attributeName - The attribute name to fetch.
7
+ * @param parent - The parent of the current element.
8
+ * @param className - The class name to fetch.
9
+ * @returns - Promise of array containing elements and their children recursively.
10
+ */
11
+ export const getAllChildren = async (element, attributeName, parent, className = 'fs-consent') => {
12
+ let attribute = '';
13
+ let customAttributes = [];
14
+ if (attributeName) {
15
+ if (attributeName === 'wized' || attributeName === 'w-el') {
16
+ // wized may have old attribute name "w-el" so we check for both
17
+ attribute =
18
+ (await getWebflowElementAttribute(element, 'wized')) ||
19
+ (await getWebflowElementAttribute(element, 'w-el')) ||
20
+ null;
21
+ }
22
+ else {
23
+ attribute = (await getWebflowElementAttribute(element, attributeName)) || null;
24
+ }
25
+ }
26
+ if (element?.customAttributes) {
27
+ // Get All Custom Attributes
28
+ const attributesList = await element.getAllCustomAttributes();
29
+ if (attributesList) {
30
+ customAttributes = attributesList;
31
+ }
32
+ }
33
+ const children = element?.children ? await element?.getChildren() : [];
34
+ // const styles: ElementChildren['styles'] = [];
35
+ // if (element?.styles) {
36
+ // const stylesData = await element?.getStyles();
37
+ // const isArray = Array.isArray(stylesData);
38
+ // if (isArray && stylesData.length > 0) {
39
+ // for (const style of stylesData) {
40
+ // try {
41
+ // const name = (await style?.getName()) || undefined;
42
+ // const properties = (await style?.getProperties()) || undefined;
43
+ // if (name && properties && style) {
44
+ // styles.push({ style, name, properties });
45
+ // }
46
+ // } catch (error) {
47
+ // }
48
+ // }
49
+ // }
50
+ // }
51
+ const current = {
52
+ element,
53
+ parent: parent,
54
+ attribute,
55
+ customAttributes
56
+ // styles,
57
+ // defaultClassName: styles?.find((style) => style?.name?.includes(className))?.name || '',
58
+ };
59
+ if (children.length === 0) {
60
+ return [current];
61
+ }
62
+ const childrenArrays = await Promise.all(children.map((child) => getAllChildren(child, attributeName, element, className)));
63
+ const flattenedChildren = childrenArrays.flat();
64
+ return [current, ...flattenedChildren];
65
+ };
@@ -0,0 +1,9 @@
1
+ type ClassList = {
2
+ name: string;
3
+ style: Style;
4
+ };
5
+ /**
6
+ * Returns the class list of the element
7
+ */
8
+ export declare const getElementClassList: (element: AnyElement) => Promise<ClassList[]>;
9
+ export {};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Returns the class list of the element
3
+ */
4
+ export const getElementClassList = async (element) => {
5
+ const classList = [];
6
+ if (element?.styles) {
7
+ const stylesData = await element.getStyles();
8
+ const isArray = Array.isArray(stylesData);
9
+ if (isArray) {
10
+ for (const style of stylesData) {
11
+ const clsName = await style?.getName();
12
+ if (style && clsName) {
13
+ classList.push({ name: clsName, style });
14
+ }
15
+ }
16
+ }
17
+ }
18
+ return classList?.filter(Boolean);
19
+ };
@@ -1,4 +1,6 @@
1
1
  export * from './attributes';
2
2
  export * from './findInstanceElement';
3
3
  export * from './getAllPages';
4
+ export * from './getAllChildren';
4
5
  export * from './getSiteStagingUrl';
6
+ export * from './getElementClassList';
@@ -1,4 +1,6 @@
1
1
  export * from './attributes';
2
2
  export * from './findInstanceElement';
3
3
  export * from './getAllPages';
4
+ export * from './getAllChildren';
4
5
  export * from './getSiteStagingUrl';
6
+ export * from './getElementClassList';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finsweet/webflow-apps-utils",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Shared utilities for Webflow apps",
5
5
  "homepage": "https://github.com/finsweet/webflow-apps-utils",
6
6
  "repository": {
@@ -51,6 +51,7 @@
51
51
  "@types/lodash": "^4.17.18",
52
52
  "@types/lodash-es": "^4.17.12",
53
53
  "@types/lodash.isequal": "^4.5.8",
54
+ "@types/luxon": "^3.6.2",
54
55
  "@types/node": "^22",
55
56
  "@vitest/browser": "3.2.3",
56
57
  "@vitest/coverage-v8": "3.2.3",
@@ -85,10 +86,13 @@
85
86
  "lodash-es": "^4.17.21",
86
87
  "lodash.isequal": "^4.5.0",
87
88
  "logrocket": "^10.1.0",
89
+ "luxon": "^3.6.1",
90
+ "motion": "^10.18.0",
88
91
  "overlayscrollbars": "^2.11.4",
89
92
  "overlayscrollbars-svelte": "^0.5.5",
90
93
  "svelte-routing": "^2.13.0",
91
94
  "swiper": "^11.2.8",
95
+ "terser": "^5.43.1",
92
96
  "uuid": "^11.1.0",
93
97
  "zod": "^3.25.64"
94
98
  },
@@ -96,6 +100,7 @@
96
100
  "dev": "vite dev",
97
101
  "build": "vite build && npm run prepack",
98
102
  "preview": "vite preview",
103
+ "watch": "svelte-kit sync && svelte-package --watch",
99
104
  "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
100
105
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
101
106
  "format": "prettier --write .",