@finsweet/webflow-apps-utils 1.0.3 → 1.0.5
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 +1 -1
- package/dist/index.js +1 -1
- package/dist/providers/GlobalProvider.stories.d.ts +5 -0
- package/dist/providers/GlobalProvider.stories.js +419 -0
- package/dist/providers/GlobalProviderDemo.svelte +266 -0
- package/dist/providers/GlobalProviderDemo.svelte.d.ts +3 -0
- package/dist/providers/configuratorUtils.d.ts +11 -14
- package/dist/providers/configuratorUtils.js +68 -115
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +1 -1
- package/dist/router/Router.stories.d.ts +6 -0
- package/dist/router/Router.stories.js +564 -0
- package/dist/router/examples/RouterExample.svelte +271 -0
- package/dist/router/examples/RouterExample.svelte.d.ts +18 -0
- package/dist/router/examples/index.d.ts +4 -0
- package/dist/router/examples/index.js +4 -0
- package/dist/router/examples/pages/AboutPage.svelte +568 -0
- package/dist/router/examples/pages/AboutPage.svelte.d.ts +13 -0
- package/dist/router/examples/pages/HomePage.svelte +200 -0
- package/dist/router/examples/pages/HomePage.svelte.d.ts +14 -0
- package/dist/router/examples/pages/NotFoundPage.svelte +307 -0
- package/dist/router/examples/pages/NotFoundPage.svelte.d.ts +17 -0
- package/dist/router/hooks.svelte.d.ts +2 -2
- package/dist/router/index.d.ts +3 -0
- package/dist/router/index.js +3 -0
- package/dist/router/{Link.svelte → providers/Link.svelte} +1 -1
- package/dist/router/{Route.svelte → providers/Route.svelte} +1 -1
- package/dist/router/{Route.svelte.d.ts → providers/Route.svelte.d.ts} +1 -1
- package/dist/router/{Router.svelte → providers/RouterProvider.svelte} +22 -5
- package/dist/router/{Router.svelte.d.ts → providers/RouterProvider.svelte.d.ts} +8 -4
- package/dist/router/providers/index.d.ts +3 -0
- package/dist/router/providers/index.js +3 -0
- package/dist/router/{index.svelte.d.ts → router.svelte.d.ts} +1 -3
- package/dist/router/{index.svelte.js → router.svelte.js} +1 -4
- package/dist/stores/forms/Form.stories.d.ts +5 -0
- package/dist/stores/forms/Form.stories.js +342 -0
- package/dist/stores/forms/FormDemo.svelte +545 -0
- package/dist/stores/forms/FormDemo.svelte.d.ts +18 -0
- package/dist/stores/forms.d.ts +41 -4
- package/dist/stores/forms.js +86 -32
- package/dist/types/customCode.d.ts +1 -1
- package/dist/types/window.d.ts +1 -0
- package/dist/ui/components/button/Button.svelte +1 -1
- package/dist/ui/components/copy-text/CopyText.stories.d.ts +70 -0
- package/dist/ui/components/copy-text/CopyText.stories.js +241 -0
- package/dist/ui/components/copy-text/CopyText.svelte +247 -0
- package/dist/ui/components/copy-text/CopyText.svelte.d.ts +4 -0
- package/dist/ui/components/copy-text/index.d.ts +2 -0
- package/dist/ui/components/copy-text/index.js +1 -0
- package/dist/ui/components/copy-text/types.d.ts +52 -0
- package/dist/ui/components/copy-text/types.js +1 -0
- package/dist/ui/components/index.d.ts +1 -0
- package/dist/ui/components/index.js +1 -0
- package/dist/ui/components/input/Input.stories.d.ts +9 -0
- package/dist/ui/components/input/Input.stories.js +78 -0
- package/dist/ui/components/input/Input.svelte +39 -3
- package/dist/ui/components/input/types.d.ts +6 -0
- package/dist/ui/components/layout/Layout.svelte +45 -64
- package/dist/ui/components/layout/Layout.svelte.d.ts +26 -3
- package/dist/ui/components/layout/examples/ExampleLayout.svelte +32 -27
- package/dist/ui/components/layout/index.d.ts +1 -1
- package/dist/ui/components/layout/test-helpers/TestLayoutWithFooter.svelte +20 -0
- package/dist/ui/components/layout/test-helpers/TestLayoutWithFooter.svelte.d.ts +7 -0
- package/dist/ui/components/layout/types.d.ts +1 -10
- package/dist/ui/components/notification/Notification.stories.svelte +12 -1
- package/dist/ui/components/notification/Notification.svelte +10 -5
- package/dist/ui/components/notification/Notification.svelte.d.ts +1 -1
- package/dist/ui/components/notification/types.d.ts +1 -1
- package/dist/ui/components/section/Section.svelte +8 -4
- package/dist/ui/components/section/types.d.ts +8 -0
- package/dist/ui/components/text/Text.stories.svelte +67 -1
- package/dist/ui/components/text/Text.svelte +209 -8
- package/dist/ui/components/text/types.d.ts +4 -0
- package/dist/ui/index.css +6 -2
- package/dist/utils/animations/factory.d.ts +7 -0
- package/dist/utils/animations/factory.js +101 -0
- package/dist/utils/animations/index.d.ts +7 -0
- package/dist/utils/animations/index.js +62 -0
- package/dist/utils/animations/types.d.ts +39 -0
- package/dist/utils/animations/types.js +1 -0
- package/dist/utils/custom-code/configs.d.ts +22 -0
- package/dist/utils/custom-code/configs.js +40 -0
- package/dist/utils/custom-code/index.d.ts +1 -0
- package/dist/utils/custom-code/index.js +1 -0
- package/dist/utils/diff-mapper/DiffMapper.stories.d.ts +5 -0
- package/dist/utils/diff-mapper/DiffMapper.stories.js +185 -0
- package/dist/utils/diff-mapper/DiffMapperDemo.svelte +351 -0
- package/dist/utils/diff-mapper/DiffMapperDemo.svelte.d.ts +18 -0
- package/dist/utils/diff-mapper/deepDiffMapper.d.ts +31 -0
- package/dist/utils/diff-mapper/deepDiffMapper.js +264 -0
- package/dist/utils/diff-mapper/index.d.ts +1 -0
- package/dist/utils/diff-mapper/index.js +1 -0
- package/dist/utils/helpers/capitalizeFirstLetter.d.ts +4 -0
- package/dist/utils/helpers/capitalizeFirstLetter.js +9 -0
- package/dist/utils/helpers/getTimeNow.d.ts +4 -0
- package/dist/utils/helpers/getTimeNow.js +8 -0
- package/dist/utils/helpers/index.d.ts +4 -0
- package/dist/utils/helpers/index.js +4 -0
- package/dist/utils/helpers/minifyCode.d.ts +10 -0
- package/dist/utils/helpers/minifyCode.js +73 -0
- package/dist/utils/helpers/objectsToModuleExports.d.ts +1 -1
- package/dist/utils/helpers/objectsToModuleExports.js +1 -0
- package/dist/utils/helpers/toHumanReadableList.d.ts +4 -0
- package/dist/utils/helpers/toHumanReadableList.js +11 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/webflow-canvas/getAllChildren.d.ts +16 -0
- package/dist/utils/webflow-canvas/getAllChildren.js +65 -0
- package/dist/utils/webflow-canvas/getElementClassList.d.ts +9 -0
- package/dist/utils/webflow-canvas/getElementClassList.js +19 -0
- package/dist/utils/webflow-canvas/index.d.ts +2 -0
- package/dist/utils/webflow-canvas/index.js +2 -0
- package/package.json +6 -1
- package/dist/providers/GlobalProvider.mdx +0 -322
- package/dist/router/README.md +0 -397
- /package/dist/router/{Link.svelte.d.ts → providers/Link.svelte.d.ts} +0 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
export var DiffType;
|
|
3
|
+
(function (DiffType) {
|
|
4
|
+
DiffType["CREATED"] = "created";
|
|
5
|
+
DiffType["UPDATED"] = "updated";
|
|
6
|
+
DiffType["DELETED"] = "deleted";
|
|
7
|
+
DiffType["UNCHANGED"] = "unchanged";
|
|
8
|
+
})(DiffType || (DiffType = {}));
|
|
9
|
+
class DeepDiffMapper {
|
|
10
|
+
visitedPairs = new WeakMap();
|
|
11
|
+
isFunction(x) {
|
|
12
|
+
return Object.prototype.toString.call(x) === '[object Function]';
|
|
13
|
+
}
|
|
14
|
+
isArray(x) {
|
|
15
|
+
return Object.prototype.toString.call(x) === '[object Array]';
|
|
16
|
+
}
|
|
17
|
+
isDate(x) {
|
|
18
|
+
return Object.prototype.toString.call(x) === '[object Date]';
|
|
19
|
+
}
|
|
20
|
+
isObject(x) {
|
|
21
|
+
return Object.prototype.toString.call(x) === '[object Object]';
|
|
22
|
+
}
|
|
23
|
+
isValue(x) {
|
|
24
|
+
return !this.isObject(x) && !this.isArray(x);
|
|
25
|
+
}
|
|
26
|
+
compareValues(value1, value2) {
|
|
27
|
+
if (value1 === value2 || this.areEquivalentPrimitives(value1, value2)) {
|
|
28
|
+
return DiffType.UNCHANGED;
|
|
29
|
+
}
|
|
30
|
+
if (this.isDate(value1) && this.isDate(value2) && value1.getTime() === value2.getTime()) {
|
|
31
|
+
return DiffType.UNCHANGED;
|
|
32
|
+
}
|
|
33
|
+
if (value1 === undefined) {
|
|
34
|
+
return DiffType.CREATED;
|
|
35
|
+
}
|
|
36
|
+
if (value2 === undefined) {
|
|
37
|
+
return DiffType.DELETED;
|
|
38
|
+
}
|
|
39
|
+
return DiffType.UPDATED;
|
|
40
|
+
}
|
|
41
|
+
areEquivalentPrimitives(value1, value2) {
|
|
42
|
+
// Handle null and undefined
|
|
43
|
+
if (value1 == null && value2 == null) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
// Handle string trimming - if both are strings, compare trimmed versions
|
|
47
|
+
if (typeof value1 === 'string' && typeof value2 === 'string') {
|
|
48
|
+
return value1.trim() === value2.trim();
|
|
49
|
+
}
|
|
50
|
+
// Handle string/boolean coercion with specific string values
|
|
51
|
+
if ((typeof value1 === 'string' || typeof value1 === 'boolean') &&
|
|
52
|
+
(typeof value2 === 'string' || typeof value2 === 'boolean')) {
|
|
53
|
+
const val1 = typeof value1 === 'string' ? value1.trim().toLowerCase() : value1;
|
|
54
|
+
const val2 = typeof value2 === 'string' ? value2.trim().toLowerCase() : value2;
|
|
55
|
+
// Handle specific string-boolean equivalences
|
|
56
|
+
if (typeof val1 === 'string' && typeof val2 === 'boolean') {
|
|
57
|
+
if ((val1 === 'true' && val2 === true) || (val1 === 'false' && val2 === false)) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
// Handle empty string as false
|
|
61
|
+
if (val1 === '' && val2 === false) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (typeof val2 === 'string' && typeof val1 === 'boolean') {
|
|
66
|
+
if ((val2 === 'true' && val1 === true) || (val2 === 'false' && val1 === false)) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
// Handle empty string as false
|
|
70
|
+
if (val2 === '' && val1 === false) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Handle string/number coercion
|
|
76
|
+
if ((typeof value1 === 'string' || typeof value1 === 'number') &&
|
|
77
|
+
(typeof value2 === 'string' || typeof value2 === 'number')) {
|
|
78
|
+
// For string to number comparison, trim the string first
|
|
79
|
+
const str1 = typeof value1 === 'string' ? value1.trim() : value1.toString();
|
|
80
|
+
const str2 = typeof value2 === 'string' ? value2.trim() : value2.toString();
|
|
81
|
+
// Only treat truly empty strings (not whitespace-only) as equivalent to 0
|
|
82
|
+
// Distinguish between empty string ('') and whitespace-only strings (' ', ' ')
|
|
83
|
+
if (typeof value1 === 'string' && value1 === '' && typeof value2 === 'number') {
|
|
84
|
+
return value2 === 0;
|
|
85
|
+
}
|
|
86
|
+
if (typeof value2 === 'string' && value2 === '' && typeof value1 === 'number') {
|
|
87
|
+
return value1 === 0;
|
|
88
|
+
}
|
|
89
|
+
// Don't treat whitespace-only strings as equivalent to numbers
|
|
90
|
+
if (typeof value1 === 'string' && value1.trim() === '' && value1 !== '') {
|
|
91
|
+
return false; // ' ', ' ', etc. should not be equivalent to numbers
|
|
92
|
+
}
|
|
93
|
+
if (typeof value2 === 'string' && value2.trim() === '' && value2 !== '') {
|
|
94
|
+
return false; // ' ', ' ', etc. should not be equivalent to numbers
|
|
95
|
+
}
|
|
96
|
+
// Convert both to numbers and compare
|
|
97
|
+
const num1 = Number(str1);
|
|
98
|
+
const num2 = Number(str2);
|
|
99
|
+
// Handle NaN case specifically - only consider equal if both are exactly NaN
|
|
100
|
+
if (isNaN(num1) || isNaN(num2)) {
|
|
101
|
+
return Number.isNaN(value1) && Number.isNaN(value2);
|
|
102
|
+
}
|
|
103
|
+
if (!isNaN(num1) && !isNaN(num2)) {
|
|
104
|
+
return num1 === num2;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
hasCircularReference(obj1, obj2) {
|
|
110
|
+
if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
if (!this.visitedPairs.has(obj1)) {
|
|
114
|
+
this.visitedPairs.set(obj1, new WeakSet());
|
|
115
|
+
}
|
|
116
|
+
const visited = this.visitedPairs.get(obj1);
|
|
117
|
+
if (visited.has(obj2)) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
visited.add(obj2);
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
_map(obj1, obj2) {
|
|
124
|
+
if (this.isFunction(obj1) || this.isFunction(obj2)) {
|
|
125
|
+
throw new Error('Invalid argument. Function given, object expected.');
|
|
126
|
+
}
|
|
127
|
+
// Only treat as values if both are values, or if one is undefined and the other is also a value
|
|
128
|
+
// This prevents treating undefined vs complex object as a value comparison
|
|
129
|
+
if (this.isValue(obj1) && this.isValue(obj2)) {
|
|
130
|
+
const diffType = this.compareValues(obj1, obj2);
|
|
131
|
+
return {
|
|
132
|
+
type: diffType,
|
|
133
|
+
data: diffType === DiffType.CREATED ? obj2 : obj1
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// Special case: one is undefined/null and the other is a complex object
|
|
137
|
+
if ((obj1 === undefined || obj1 === null) && (this.isArray(obj2) || this.isObject(obj2))) {
|
|
138
|
+
// Recursively process the non-undefined object as if it was created
|
|
139
|
+
return this._map({}, obj2);
|
|
140
|
+
}
|
|
141
|
+
if ((obj2 === undefined || obj2 === null) && (this.isArray(obj1) || this.isObject(obj1))) {
|
|
142
|
+
// Recursively process the non-undefined object as if it was deleted
|
|
143
|
+
return this._map(obj1, {});
|
|
144
|
+
}
|
|
145
|
+
// Handle primitive value cases (one or both are primitives but not both complex)
|
|
146
|
+
if (this.isValue(obj1) || this.isValue(obj2)) {
|
|
147
|
+
const diffType = this.compareValues(obj1, obj2);
|
|
148
|
+
return {
|
|
149
|
+
type: diffType,
|
|
150
|
+
data: diffType === DiffType.CREATED ? obj2 : obj1
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// Check if both are complex types but of different specific types (array vs object)
|
|
154
|
+
const isArrayVsObject = (this.isArray(obj1) && this.isObject(obj2)) || (this.isObject(obj1) && this.isArray(obj2));
|
|
155
|
+
// For mixed types (array vs object), check if they have the same structure first
|
|
156
|
+
if (isArrayVsObject) {
|
|
157
|
+
// If both are empty, they're still different types
|
|
158
|
+
const keys1 = Object.keys(obj1 || {});
|
|
159
|
+
const keys2 = Object.keys(obj2 || {});
|
|
160
|
+
if (keys1.length === 0 && keys2.length === 0) {
|
|
161
|
+
return {
|
|
162
|
+
type: DiffType.UPDATED,
|
|
163
|
+
data: obj1
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
// Continue with property comparison for non-empty mixed types
|
|
167
|
+
}
|
|
168
|
+
// Check for circular references
|
|
169
|
+
if (this.hasCircularReference(obj1, obj2)) {
|
|
170
|
+
return {
|
|
171
|
+
type: DiffType.UNCHANGED,
|
|
172
|
+
data: obj1
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
const diff = {};
|
|
176
|
+
// Get all property keys including symbols and own properties
|
|
177
|
+
const getAllKeys = (obj) => {
|
|
178
|
+
if (!obj)
|
|
179
|
+
return [];
|
|
180
|
+
const keys = [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
|
|
181
|
+
// Include inherited enumerable properties
|
|
182
|
+
for (const key in obj) {
|
|
183
|
+
if (!keys.includes(key)) {
|
|
184
|
+
keys.push(key);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return keys;
|
|
188
|
+
};
|
|
189
|
+
const keys1 = getAllKeys(obj1);
|
|
190
|
+
const keys2 = getAllKeys(obj2);
|
|
191
|
+
const allKeys = new Set([...keys1, ...keys2]);
|
|
192
|
+
// Check if prototypes are different and add __proto__ to comparison
|
|
193
|
+
const proto1 = obj1 ? Object.getPrototypeOf(obj1) : null;
|
|
194
|
+
const proto2 = obj2 ? Object.getPrototypeOf(obj2) : null;
|
|
195
|
+
// Add __proto__ to comparison if prototypes differ
|
|
196
|
+
if (proto1 !== proto2) {
|
|
197
|
+
allKeys.add('__proto__');
|
|
198
|
+
}
|
|
199
|
+
// Check all properties from both objects
|
|
200
|
+
for (const key of allKeys) {
|
|
201
|
+
if (this.isFunction(obj1?.[key]) || this.isFunction(obj2?.[key])) {
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
let value1;
|
|
205
|
+
let value2;
|
|
206
|
+
// Special handling for __proto__
|
|
207
|
+
if (key === '__proto__') {
|
|
208
|
+
// We already know prototypes differ if we got here (since we added __proto__ to allKeys)
|
|
209
|
+
// For prototypes, we'll do a shallow comparison to avoid infinite recursion
|
|
210
|
+
if (proto1 === proto2) {
|
|
211
|
+
continue; // Should not happen since we only added this key when they differ
|
|
212
|
+
}
|
|
213
|
+
// Compare prototypes - treat default Object.prototype as "undefined" for comparison purposes
|
|
214
|
+
const isDefaultProto1 = proto1 === Object.prototype || proto1 === null;
|
|
215
|
+
const isDefaultProto2 = proto2 === Object.prototype || proto2 === null;
|
|
216
|
+
// If one has default prototype and other has custom, treat as create/delete
|
|
217
|
+
if (isDefaultProto1 && !isDefaultProto2) {
|
|
218
|
+
diff[key] = {
|
|
219
|
+
type: DiffType.CREATED,
|
|
220
|
+
data: proto2
|
|
221
|
+
};
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (!isDefaultProto1 && isDefaultProto2) {
|
|
225
|
+
diff[key] = {
|
|
226
|
+
type: DiffType.DELETED,
|
|
227
|
+
data: proto1
|
|
228
|
+
};
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
// Both have custom prototypes but they're different
|
|
232
|
+
if (!isDefaultProto1 && !isDefaultProto2 && proto1 !== proto2) {
|
|
233
|
+
diff[key] = {
|
|
234
|
+
type: DiffType.UPDATED,
|
|
235
|
+
data: proto1
|
|
236
|
+
};
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
value1 = obj1?.[key];
|
|
242
|
+
value2 = obj2?.[key];
|
|
243
|
+
}
|
|
244
|
+
diff[key] = this._map(value1, value2);
|
|
245
|
+
}
|
|
246
|
+
return diff;
|
|
247
|
+
}
|
|
248
|
+
map(obj1, obj2) {
|
|
249
|
+
// Reset visited pairs for each new comparison
|
|
250
|
+
this.visitedPairs = new WeakMap();
|
|
251
|
+
return this._map(obj1, obj2);
|
|
252
|
+
}
|
|
253
|
+
compare(obj1, obj2) {
|
|
254
|
+
return this.map(obj1, obj2);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// Export singleton instance
|
|
258
|
+
export const deepDiffMapper = new DeepDiffMapper();
|
|
259
|
+
// Export class for custom instances if needed
|
|
260
|
+
export { DeepDiffMapper };
|
|
261
|
+
// Export convenience function
|
|
262
|
+
export function compareObjects(obj1, obj2) {
|
|
263
|
+
return deepDiffMapper.compare(obj1, obj2);
|
|
264
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './deepDiffMapper';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './deepDiffMapper';
|
|
@@ -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
|
+
};
|
|
@@ -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
|
+
};
|
|
@@ -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
|
+
};
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
export * from './animations';
|
|
1
2
|
export * from './api';
|
|
2
3
|
export * from './auth';
|
|
3
4
|
export * from './browser-storage';
|
|
4
5
|
export * from './constants';
|
|
5
6
|
export * from './custom-code';
|
|
7
|
+
export * from './diff-mapper';
|
|
6
8
|
export * from './helpers';
|
|
7
9
|
export * from './logger';
|
|
8
10
|
export * from './webflow-canvas';
|
package/dist/utils/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
export * from './animations';
|
|
1
2
|
export * from './api';
|
|
2
3
|
export * from './auth';
|
|
3
4
|
export * from './browser-storage';
|
|
4
5
|
export * from './constants';
|
|
5
6
|
export * from './custom-code';
|
|
7
|
+
export * from './diff-mapper';
|
|
6
8
|
export * from './helpers';
|
|
7
9
|
export * from './logger';
|
|
8
10
|
export * from './webflow-canvas';
|
|
@@ -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,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
|
+
};
|
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.5",
|
|
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 .",
|