@symbo.ls/utils 3.2.3 → 3.14.0
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/LICENSE +25 -12
- package/README.md +106 -0
- package/array.js +162 -0
- package/cache.js +7 -0
- package/cdn.js +83 -0
- package/component.js +25 -0
- package/cookie.js +71 -0
- package/{src/detectHeight.js → detectHeight.js} +3 -3
- package/dist/cjs/array.js +168 -0
- package/dist/cjs/browser.js +0 -2
- package/dist/cjs/cache.js +26 -0
- package/dist/cjs/cdn.js +85 -0
- package/dist/cjs/component.js +45 -0
- package/dist/cjs/cookie.js +75 -0
- package/dist/cjs/date.js +1 -3
- package/dist/cjs/detectHeight.js +4 -6
- package/dist/cjs/element.js +136 -0
- package/dist/cjs/env.js +43 -0
- package/dist/cjs/events.js +39 -0
- package/dist/cjs/extends.js +434 -0
- package/dist/cjs/fibonacci.js +1 -3
- package/dist/cjs/files.js +1 -3
- package/dist/cjs/function.js +114 -0
- package/dist/cjs/globals.js +30 -0
- package/dist/cjs/if.js +48 -0
- package/dist/cjs/index.js +38 -425
- package/dist/cjs/key.js +38 -0
- package/dist/cjs/keys.js +201 -0
- package/dist/cjs/load.js +5 -7
- package/dist/cjs/log.js +34 -0
- package/dist/cjs/metadata.js +310 -0
- package/dist/cjs/methods.js +599 -0
- package/dist/cjs/node.js +35 -0
- package/dist/cjs/object.js +634 -0
- package/dist/cjs/projectKeys.js +35 -0
- package/dist/cjs/props.js +282 -0
- package/dist/cjs/scaling.js +5 -169
- package/dist/cjs/scope.js +44 -0
- package/dist/cjs/sharedLibraries.js +146 -0
- package/dist/cjs/state.js +173 -0
- package/dist/cjs/string-extra.js +72 -0
- package/dist/cjs/string.js +183 -0
- package/dist/cjs/style.js +1 -3
- package/dist/cjs/tags.js +220 -0
- package/dist/cjs/triggerEvent.js +112 -0
- package/dist/cjs/types.js +74 -0
- package/dist/cjs/update.js +42 -0
- package/dist/esm/array.js +148 -0
- package/dist/esm/browser.js +14 -0
- package/dist/esm/cache.js +6 -0
- package/dist/esm/cdn.js +65 -0
- package/dist/esm/component.js +25 -0
- package/dist/esm/cookie.js +55 -0
- package/dist/esm/date.js +11 -0
- package/dist/esm/detectHeight.js +42 -0
- package/dist/esm/element.js +116 -0
- package/dist/esm/env.js +23 -0
- package/dist/esm/events.js +19 -0
- package/dist/esm/extends.js +414 -0
- package/dist/esm/fibonacci.js +10 -0
- package/dist/esm/files.js +4 -0
- package/dist/esm/function.js +94 -0
- package/dist/esm/globals.js +10 -0
- package/dist/esm/if.js +28 -0
- package/dist/esm/index.js +37 -0
- package/dist/esm/key.js +18 -0
- package/dist/esm/keys.js +181 -0
- package/dist/esm/load.js +151 -0
- package/dist/esm/log.js +14 -0
- package/dist/esm/metadata.js +290 -0
- package/dist/esm/methods.js +569 -0
- package/dist/esm/node.js +15 -0
- package/dist/esm/object.js +621 -0
- package/dist/esm/projectKeys.js +16 -0
- package/dist/esm/props.js +262 -0
- package/dist/esm/scaling.js +15 -0
- package/dist/esm/scope.js +24 -0
- package/dist/esm/sharedLibraries.js +126 -0
- package/dist/esm/state.js +163 -0
- package/dist/esm/string-extra.js +52 -0
- package/dist/esm/string.js +163 -0
- package/dist/esm/style.js +20 -0
- package/dist/esm/tags.js +200 -0
- package/dist/esm/triggerEvent.js +92 -0
- package/dist/esm/types.js +54 -0
- package/dist/esm/update.js +22 -0
- package/dist/iife/index.js +5818 -0
- package/element.js +148 -0
- package/env.js +15 -0
- package/events.js +19 -0
- package/extends.js +519 -0
- package/function.js +145 -0
- package/globals.js +8 -0
- package/if.js +30 -0
- package/index.js +41 -0
- package/key.js +20 -0
- package/keys.js +176 -0
- package/log.js +12 -0
- package/metadata.js +392 -0
- package/methods.js +636 -0
- package/node.js +37 -0
- package/object.js +803 -0
- package/package.json +38 -22
- package/projectKeys.js +30 -0
- package/props.js +327 -0
- package/{src/scaling.js → scaling.js} +1 -1
- package/scope.js +32 -0
- package/sharedLibraries.js +184 -0
- package/state.js +203 -0
- package/{src/index.js → string-extra.js} +11 -17
- package/string.js +206 -0
- package/tags.js +176 -0
- package/triggerEvent.js +102 -0
- package/types.js +55 -0
- package/update.js +27 -0
- package/dist/cjs/package.json +0 -4
- /package/{src/browser.js → browser.js} +0 -0
- /package/{src/date.js → date.js} +0 -0
- /package/{src/fibonacci.js → fibonacci.js} +0 -0
- /package/{src/files.js → files.js} +0 -0
- /package/{src/load.js → load.js} +0 -0
- /package/{src/style.js → style.js} +0 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { DOMQ_PROPERTIES, PROPS_METHODS } from "./keys.js";
|
|
2
|
+
import { addEventFromProps } from "./events.js";
|
|
3
|
+
import { deepClone, deepMerge, exec } from "./object.js";
|
|
4
|
+
import { is, isArray, isFunction, isObject, isObjectLike } from "./types.js";
|
|
5
|
+
import { lowercaseFirstLetter } from "./string.js";
|
|
6
|
+
import { hasHandlerPlugin } from "./function.js";
|
|
7
|
+
const RE_UPPER = /^[A-Z]/;
|
|
8
|
+
const RE_DIGITS = /^\d+$/;
|
|
9
|
+
const CSS_SELECTOR_PREFIXES = /* @__PURE__ */ new Set([":", "@", "[", "*", "+", "~", "&", ">", "$", "-", ".", "!"]);
|
|
10
|
+
const ELEMENT_INDICATOR_KEYS = /* @__PURE__ */ new Set([
|
|
11
|
+
"extend",
|
|
12
|
+
"props",
|
|
13
|
+
"text",
|
|
14
|
+
"tag",
|
|
15
|
+
"on",
|
|
16
|
+
"if",
|
|
17
|
+
"childExtend",
|
|
18
|
+
"children",
|
|
19
|
+
"childrenAs",
|
|
20
|
+
"state",
|
|
21
|
+
"html",
|
|
22
|
+
"attr",
|
|
23
|
+
"define",
|
|
24
|
+
"content"
|
|
25
|
+
]);
|
|
26
|
+
const looksLikeElement = (value) => {
|
|
27
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
28
|
+
for (const k in value) {
|
|
29
|
+
if (ELEMENT_INDICATOR_KEYS.has(k)) return true;
|
|
30
|
+
if (RE_UPPER.test(k)) return true;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
};
|
|
34
|
+
const createProps = (element, parent, key) => {
|
|
35
|
+
const { props, __ref: ref } = element;
|
|
36
|
+
ref.__propsStack = [];
|
|
37
|
+
if (props) ref.__initialProps = props;
|
|
38
|
+
else return {};
|
|
39
|
+
if (!isObjectLike(props)) {
|
|
40
|
+
ref.__propsStack.push(props);
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
return { ...props };
|
|
44
|
+
};
|
|
45
|
+
function pickupPropsFromElement(obj, opts = {}) {
|
|
46
|
+
const cachedKeys = opts.cachedKeys || [];
|
|
47
|
+
for (const key in obj) {
|
|
48
|
+
const value = obj[key];
|
|
49
|
+
const isOnKey = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110 && key[2] === key[2].toUpperCase();
|
|
50
|
+
const isEventHandler = isOnKey && (isFunction(value) || value != null && hasHandlerPlugin(this.context));
|
|
51
|
+
if (isEventHandler) {
|
|
52
|
+
const eventName = lowercaseFirstLetter(key.slice(2));
|
|
53
|
+
if (obj.on) obj.on[eventName] = value;
|
|
54
|
+
delete obj[key];
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (key === "childProps") {
|
|
58
|
+
obj.props[key] = value;
|
|
59
|
+
delete obj[key];
|
|
60
|
+
cachedKeys.push(key);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const defineValue = this.define?.[key];
|
|
64
|
+
const globalDefineValue = this.context?.define?.[key];
|
|
65
|
+
const hasDefine = isObject(defineValue) || isFunction(defineValue);
|
|
66
|
+
const hasGlobalDefine = isObject(globalDefineValue) || isFunction(globalDefineValue);
|
|
67
|
+
if (hasDefine || hasGlobalDefine) continue;
|
|
68
|
+
const firstChar = key.charAt(0);
|
|
69
|
+
if (CSS_SELECTOR_PREFIXES.has(firstChar)) {
|
|
70
|
+
obj.props[key] = value;
|
|
71
|
+
delete obj[key];
|
|
72
|
+
cachedKeys.push(key);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const isElement = RE_UPPER.test(key) || RE_DIGITS.test(key) || looksLikeElement(value);
|
|
76
|
+
const isBuiltin = DOMQ_PROPERTIES.has(key);
|
|
77
|
+
if (!isElement && !isBuiltin) {
|
|
78
|
+
if (!(key in obj.props)) obj.props[key] = value;
|
|
79
|
+
delete obj[key];
|
|
80
|
+
cachedKeys.push(key);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return obj;
|
|
84
|
+
}
|
|
85
|
+
function pickupElementFromProps(obj = this, opts) {
|
|
86
|
+
const cachedKeys = opts.cachedKeys || [];
|
|
87
|
+
for (const key in obj.props) {
|
|
88
|
+
const value = obj.props[key];
|
|
89
|
+
const isEvent = key.length > 2 && key.charCodeAt(0) === 111 && key.charCodeAt(1) === 110;
|
|
90
|
+
const isHandler = isFunction(value) || value != null && hasHandlerPlugin(this.context);
|
|
91
|
+
if (isEvent && isHandler) {
|
|
92
|
+
addEventFromProps(key, obj);
|
|
93
|
+
delete obj.props[key];
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (cachedKeys.includes(key)) continue;
|
|
97
|
+
if (key === "childProps") continue;
|
|
98
|
+
const firstChar = key.charAt(0);
|
|
99
|
+
if (CSS_SELECTOR_PREFIXES.has(firstChar)) continue;
|
|
100
|
+
const defineValue = this.define?.[key];
|
|
101
|
+
const globalDefineValue = this.context?.define?.[key];
|
|
102
|
+
const hasDefine = isObject(defineValue) || isFunction(defineValue);
|
|
103
|
+
const hasGlobalDefine = isObject(globalDefineValue) || isFunction(globalDefineValue);
|
|
104
|
+
const isElement = RE_UPPER.test(key) || RE_DIGITS.test(key);
|
|
105
|
+
const isBuiltin = DOMQ_PROPERTIES.has(key);
|
|
106
|
+
if (isElement || isBuiltin || hasDefine || hasGlobalDefine) {
|
|
107
|
+
if (obj[key] === void 0 || value === null) {
|
|
108
|
+
obj[key] = value;
|
|
109
|
+
if (obj.props) delete obj.props[key];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return obj;
|
|
114
|
+
}
|
|
115
|
+
function propertizeElement(element = this) {
|
|
116
|
+
const cachedKeys = [];
|
|
117
|
+
pickupPropsFromElement.call(this, element, { cachedKeys });
|
|
118
|
+
pickupElementFromProps.call(this, element, { cachedKeys });
|
|
119
|
+
return element;
|
|
120
|
+
}
|
|
121
|
+
function propertizeUpdate(params = {}) {
|
|
122
|
+
if (!params.on) params.on = {};
|
|
123
|
+
if (!params.props) params.props = {};
|
|
124
|
+
return propertizeElement.call(this, params);
|
|
125
|
+
}
|
|
126
|
+
const objectizeStringProperty = (propValue) => {
|
|
127
|
+
if (is(propValue)("string", "number")) {
|
|
128
|
+
return { inheritedString: propValue };
|
|
129
|
+
}
|
|
130
|
+
return propValue;
|
|
131
|
+
};
|
|
132
|
+
const propExists = (prop, stack) => {
|
|
133
|
+
if (!prop || !stack.length) return false;
|
|
134
|
+
return stack.includes(prop);
|
|
135
|
+
};
|
|
136
|
+
const inheritParentProps = (element, parent) => {
|
|
137
|
+
const { __ref: ref } = element;
|
|
138
|
+
const propsStack = ref.__propsStack || [];
|
|
139
|
+
const parentProps = parent.props;
|
|
140
|
+
if (!parentProps) return propsStack;
|
|
141
|
+
const matchParentKeyProps = parentProps[element.key];
|
|
142
|
+
const matchParentChildProps = parentProps.childProps || parent.childProps;
|
|
143
|
+
const ignoreChildProps = element.props?.ignoreChildProps;
|
|
144
|
+
if (matchParentChildProps && !ignoreChildProps) {
|
|
145
|
+
const childProps = objectizeStringProperty(matchParentChildProps);
|
|
146
|
+
propsStack.unshift(childProps);
|
|
147
|
+
}
|
|
148
|
+
if (matchParentKeyProps) {
|
|
149
|
+
const keyProps = objectizeStringProperty(matchParentKeyProps);
|
|
150
|
+
propsStack.unshift(keyProps);
|
|
151
|
+
}
|
|
152
|
+
return propsStack;
|
|
153
|
+
};
|
|
154
|
+
function update(props, options) {
|
|
155
|
+
const element = this.__element;
|
|
156
|
+
element.update({ props }, options);
|
|
157
|
+
}
|
|
158
|
+
function setPropsPrototype(element) {
|
|
159
|
+
const methods = { update: update.bind(element.props), __element: element };
|
|
160
|
+
Object.setPrototypeOf(element.props, methods);
|
|
161
|
+
}
|
|
162
|
+
const removeDuplicateProps = (propsStack) => {
|
|
163
|
+
const seen = /* @__PURE__ */ new Set();
|
|
164
|
+
return propsStack.filter((prop) => {
|
|
165
|
+
if (!prop || PROPS_METHODS.has(prop)) return false;
|
|
166
|
+
if (seen.has(prop)) return false;
|
|
167
|
+
seen.add(prop);
|
|
168
|
+
return true;
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
const syncProps = (propsStack, element, opts) => {
|
|
172
|
+
element.props = propsStack.reduce((mergedProps, v) => {
|
|
173
|
+
if (PROPS_METHODS.has(v)) return mergedProps;
|
|
174
|
+
while (isFunction(v)) v = exec(v, element);
|
|
175
|
+
return deepMerge(mergedProps, deepClone(v, { exclude: PROPS_METHODS }));
|
|
176
|
+
}, {});
|
|
177
|
+
setPropsPrototype(element);
|
|
178
|
+
return element.props;
|
|
179
|
+
};
|
|
180
|
+
const createPropsStack = (element, parent) => {
|
|
181
|
+
const { props, __ref: ref } = element;
|
|
182
|
+
let propsStack = ref.__propsStack || [];
|
|
183
|
+
if (parent?.props) {
|
|
184
|
+
const parentStack = inheritParentProps(element, parent);
|
|
185
|
+
propsStack = [...parentStack];
|
|
186
|
+
}
|
|
187
|
+
if (isObject(props)) propsStack.push(props);
|
|
188
|
+
else if (props === "inherit" && parent?.props) propsStack.push(parent.props);
|
|
189
|
+
else if (props) propsStack.push(props);
|
|
190
|
+
if (isArray(ref.__extendsStack)) {
|
|
191
|
+
for (let i = 0; i < ref.__extendsStack.length; i++) {
|
|
192
|
+
const _extends = ref.__extendsStack[i];
|
|
193
|
+
if (_extends.props && _extends.props !== props) {
|
|
194
|
+
propsStack.push(_extends.props);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
ref.__propsStack = removeDuplicateProps(propsStack);
|
|
199
|
+
return ref.__propsStack;
|
|
200
|
+
};
|
|
201
|
+
const applyProps = (element, parent) => {
|
|
202
|
+
const { __ref: ref } = element;
|
|
203
|
+
const propsStack = createPropsStack(element, parent);
|
|
204
|
+
if (propsStack.length) {
|
|
205
|
+
syncProps(propsStack, element);
|
|
206
|
+
} else {
|
|
207
|
+
ref.__propsStack = [];
|
|
208
|
+
element.props = {};
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
const initProps = function(element, parent, options) {
|
|
212
|
+
const { __ref: ref } = element;
|
|
213
|
+
if (ref.__if) applyProps(element, parent);
|
|
214
|
+
else {
|
|
215
|
+
try {
|
|
216
|
+
applyProps(element, parent);
|
|
217
|
+
} catch (e) {
|
|
218
|
+
if (element.context?.designSystem?.verbose) {
|
|
219
|
+
console.warn("initProps error at", ref.path?.join("."), e);
|
|
220
|
+
}
|
|
221
|
+
element.props = {};
|
|
222
|
+
ref.__propsStack = [];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
setPropsPrototype(element);
|
|
226
|
+
return element;
|
|
227
|
+
};
|
|
228
|
+
const updateProps = (newProps, element, parent) => {
|
|
229
|
+
const { __ref: ref } = element;
|
|
230
|
+
const propsStack = ref.__propsStack || [];
|
|
231
|
+
let newStack = [...propsStack];
|
|
232
|
+
const parentProps = inheritParentProps(element, parent);
|
|
233
|
+
if (parentProps.length) {
|
|
234
|
+
newStack = [...parentProps, ...newStack];
|
|
235
|
+
}
|
|
236
|
+
if (newProps) {
|
|
237
|
+
newStack = [newProps, ...newStack];
|
|
238
|
+
}
|
|
239
|
+
ref.__propsStack = removeDuplicateProps(newStack);
|
|
240
|
+
if (ref.__propsStack.length) {
|
|
241
|
+
syncProps(ref.__propsStack, element);
|
|
242
|
+
}
|
|
243
|
+
return element;
|
|
244
|
+
};
|
|
245
|
+
export {
|
|
246
|
+
applyProps,
|
|
247
|
+
createProps,
|
|
248
|
+
createPropsStack,
|
|
249
|
+
inheritParentProps,
|
|
250
|
+
initProps,
|
|
251
|
+
objectizeStringProperty,
|
|
252
|
+
pickupElementFromProps,
|
|
253
|
+
pickupPropsFromElement,
|
|
254
|
+
propExists,
|
|
255
|
+
propertizeElement,
|
|
256
|
+
propertizeUpdate,
|
|
257
|
+
removeDuplicateProps,
|
|
258
|
+
setPropsPrototype,
|
|
259
|
+
syncProps,
|
|
260
|
+
update,
|
|
261
|
+
updateProps
|
|
262
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isObject, isArray } from "./types.js";
|
|
2
|
+
const findClosestNumber = (number, arr) => {
|
|
3
|
+
return (isArray(arr) ? arr : Object.values(arr)).reduce((prev, curr) => {
|
|
4
|
+
return Math.abs(curr - number) < Math.abs(prev - number) ? curr : prev;
|
|
5
|
+
});
|
|
6
|
+
};
|
|
7
|
+
const findClosestNumberInFactory = (val, factory) => {
|
|
8
|
+
val = parseFloat(val);
|
|
9
|
+
if (isObject(factory)) factory = Object.values(factory);
|
|
10
|
+
return findClosestNumber(val, factory);
|
|
11
|
+
};
|
|
12
|
+
export {
|
|
13
|
+
findClosestNumber,
|
|
14
|
+
findClosestNumberInFactory
|
|
15
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const createScope = (element, parent) => {
|
|
2
|
+
const { __ref: ref } = element;
|
|
3
|
+
const context = element.context || parent.context || ref.root?.context;
|
|
4
|
+
if (context && !context.globalScope) context.globalScope = {};
|
|
5
|
+
const parentScope = parent.scope || ref.root?.scope;
|
|
6
|
+
const globalScope = context?.globalScope;
|
|
7
|
+
if (!element.scope) {
|
|
8
|
+
if (parentScope) {
|
|
9
|
+
element.scope = parentScope;
|
|
10
|
+
} else if (globalScope) {
|
|
11
|
+
element.scope = Object.create(globalScope);
|
|
12
|
+
} else {
|
|
13
|
+
element.scope = {};
|
|
14
|
+
}
|
|
15
|
+
} else if (typeof element.scope === "object" && element.scope !== null) {
|
|
16
|
+
if (Object.getPrototypeOf(element.scope) === Object.prototype) {
|
|
17
|
+
const proto = parentScope || globalScope;
|
|
18
|
+
if (proto) Object.setPrototypeOf(element.scope, proto);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
export {
|
|
23
|
+
createScope
|
|
24
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { isObject, isString } from "./types.js";
|
|
2
|
+
const DEFAULT_LIBRARY_OWNER = "system";
|
|
3
|
+
const KV_BASE_URL = "https://smbls-kv.nika-980.workers.dev";
|
|
4
|
+
const API_BASE_URL = "https://api.symbols.app";
|
|
5
|
+
function normalizeLibraryKey(raw) {
|
|
6
|
+
const s = String(raw || "").trim();
|
|
7
|
+
if (!s) return { owner: DEFAULT_LIBRARY_OWNER, key: "", full: "" };
|
|
8
|
+
let owner = null;
|
|
9
|
+
let key = s;
|
|
10
|
+
if (s.includes("/")) {
|
|
11
|
+
const idx = s.indexOf("/");
|
|
12
|
+
owner = s.slice(0, idx);
|
|
13
|
+
key = s.slice(idx + 1);
|
|
14
|
+
}
|
|
15
|
+
key = key.replace(/\.symbo\.ls$/iu, "");
|
|
16
|
+
if (!owner) owner = DEFAULT_LIBRARY_OWNER;
|
|
17
|
+
const full = key ? `${owner}/${key}` : "";
|
|
18
|
+
return { owner, key, full };
|
|
19
|
+
}
|
|
20
|
+
const deepDefaults = (target, source) => {
|
|
21
|
+
for (const k in source) {
|
|
22
|
+
if (!(k in target)) {
|
|
23
|
+
target[k] = source[k];
|
|
24
|
+
} else if (isObject(target[k]) && isObject(source[k])) {
|
|
25
|
+
deepDefaults(target[k], source[k]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const mergeSharedLibraries = (context, libraries) => {
|
|
30
|
+
if (!libraries || !libraries.length) return;
|
|
31
|
+
for (let i = 0; i < libraries.length; i++) {
|
|
32
|
+
const sharedLib = libraries[i];
|
|
33
|
+
if (!isObject(sharedLib)) continue;
|
|
34
|
+
for (const key in sharedLib) {
|
|
35
|
+
if (!Object.prototype.hasOwnProperty.call(sharedLib, key)) continue;
|
|
36
|
+
if (isObject(sharedLib[key]) && isObject(context[key])) {
|
|
37
|
+
if (key === "designSystem") {
|
|
38
|
+
deepDefaults(context[key], sharedLib[key]);
|
|
39
|
+
} else {
|
|
40
|
+
for (const k in sharedLib[key]) {
|
|
41
|
+
if (!(k in context[key])) context[key][k] = sharedLib[key][k];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
} else if (!(key in context)) {
|
|
45
|
+
context[key] = sharedLib[key];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
async function fetchLibraryData(identifier, opts = {}) {
|
|
51
|
+
const provider = opts.provider || "kv";
|
|
52
|
+
if (provider === "api") {
|
|
53
|
+
return fetchLibraryFromApi(identifier, opts);
|
|
54
|
+
}
|
|
55
|
+
const result = await fetchLibraryFromKv(identifier, opts);
|
|
56
|
+
if (result) return result;
|
|
57
|
+
return fetchLibraryFromApi(identifier, opts);
|
|
58
|
+
}
|
|
59
|
+
async function fetchLibraryFromKv(identifier, opts = {}) {
|
|
60
|
+
const baseUrl = opts.kvBaseUrl || KV_BASE_URL;
|
|
61
|
+
const env = opts.env || "production";
|
|
62
|
+
const url = `${baseUrl}/kv/${encodeURIComponent(identifier)}?env=${env}`;
|
|
63
|
+
try {
|
|
64
|
+
const response = await fetch(url, { method: "GET" });
|
|
65
|
+
if (!response.ok) return null;
|
|
66
|
+
const json = await response.json();
|
|
67
|
+
return json?.value || null;
|
|
68
|
+
} catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function fetchLibraryFromApi(identifier, opts = {}) {
|
|
73
|
+
const baseUrl = opts.apiBaseUrl || API_BASE_URL;
|
|
74
|
+
const { key } = normalizeLibraryKey(identifier);
|
|
75
|
+
try {
|
|
76
|
+
const listUrl = `${baseUrl}/core/projects/libraries/available?search=${encodeURIComponent(key)}&limit=10`;
|
|
77
|
+
const listRes = await fetch(listUrl, { method: "GET" });
|
|
78
|
+
if (!listRes.ok) return null;
|
|
79
|
+
const listJson = await listRes.json();
|
|
80
|
+
const items = listJson?.items || listJson?.data || (Array.isArray(listJson) ? listJson : []);
|
|
81
|
+
const match = items.find((lib) => {
|
|
82
|
+
const { key: libKey } = normalizeLibraryKey(lib?.key);
|
|
83
|
+
return libKey.toLowerCase() === key.toLowerCase();
|
|
84
|
+
});
|
|
85
|
+
if (!match?.id && !match?._id) return null;
|
|
86
|
+
const libId = match.id || match._id;
|
|
87
|
+
const dataUrl = `${baseUrl}/core/projects/${encodeURIComponent(libId)}/data?branch=main`;
|
|
88
|
+
const dataRes = await fetch(dataUrl, { method: "GET" });
|
|
89
|
+
if (!dataRes.ok) return null;
|
|
90
|
+
const dataJson = await dataRes.json();
|
|
91
|
+
return dataJson?.data || dataJson || null;
|
|
92
|
+
} catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async function resolveSharedLibraries(libraries, opts = {}) {
|
|
97
|
+
if (!libraries || !libraries.length) return [];
|
|
98
|
+
const resolved = await Promise.all(
|
|
99
|
+
libraries.map(async (entry) => {
|
|
100
|
+
if (isObject(entry)) return entry;
|
|
101
|
+
if (isString(entry)) {
|
|
102
|
+
const { full } = normalizeLibraryKey(entry);
|
|
103
|
+
if (!full) return null;
|
|
104
|
+
try {
|
|
105
|
+
const data = await fetchLibraryData(full, opts);
|
|
106
|
+
if (!data) {
|
|
107
|
+
console.warn(`[smbls] Shared library "${full}" not found`);
|
|
108
|
+
}
|
|
109
|
+
return data;
|
|
110
|
+
} catch (e) {
|
|
111
|
+
console.warn(`[smbls] Failed to fetch shared library "${full}":`, e.message);
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return null;
|
|
116
|
+
})
|
|
117
|
+
);
|
|
118
|
+
return resolved.filter(Boolean);
|
|
119
|
+
}
|
|
120
|
+
export {
|
|
121
|
+
deepDefaults,
|
|
122
|
+
fetchLibraryData,
|
|
123
|
+
mergeSharedLibraries,
|
|
124
|
+
normalizeLibraryKey,
|
|
125
|
+
resolveSharedLibraries
|
|
126
|
+
};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { addProtoToArray } from "./array.js";
|
|
2
|
+
import { STATE_METHODS } from "./keys.js";
|
|
3
|
+
import {
|
|
4
|
+
deepClone,
|
|
5
|
+
deepMerge,
|
|
6
|
+
overwriteDeep,
|
|
7
|
+
overwriteShallow
|
|
8
|
+
} from "./object.js";
|
|
9
|
+
import {
|
|
10
|
+
is,
|
|
11
|
+
isObject,
|
|
12
|
+
isObjectLike,
|
|
13
|
+
isString
|
|
14
|
+
} from "./types.js";
|
|
15
|
+
const checkForStateTypes = (element) => {
|
|
16
|
+
const { state: orig, props, __ref: ref } = element;
|
|
17
|
+
const state = props?.state || orig;
|
|
18
|
+
if (is(state)("string", "number")) {
|
|
19
|
+
ref.__state = state;
|
|
20
|
+
return { value: state };
|
|
21
|
+
} else if (state === true) {
|
|
22
|
+
ref.__state = element.key;
|
|
23
|
+
return {};
|
|
24
|
+
} else if (state) {
|
|
25
|
+
ref.__hasRootState = true;
|
|
26
|
+
return state;
|
|
27
|
+
} else {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const getRootStateInKey = (stateKey, parentState) => {
|
|
32
|
+
if (!stateKey.includes("~/")) return;
|
|
33
|
+
const arr = stateKey.split("~/");
|
|
34
|
+
if (arr.length > 1) return parentState.root;
|
|
35
|
+
};
|
|
36
|
+
const getParentStateInKey = (stateKey, parentState) => {
|
|
37
|
+
if (!stateKey.includes("../")) return;
|
|
38
|
+
const arr = stateKey.split("../");
|
|
39
|
+
const arrLength = arr.length - 1;
|
|
40
|
+
for (let i = 0; i < arrLength; i++) {
|
|
41
|
+
if (!parentState.parent) return null;
|
|
42
|
+
parentState = parentState.parent;
|
|
43
|
+
}
|
|
44
|
+
return parentState;
|
|
45
|
+
};
|
|
46
|
+
const getChildStateInKey = (stateKey, parentState, options = {}) => {
|
|
47
|
+
const arr = isString(stateKey) ? stateKey.split("/") : [stateKey];
|
|
48
|
+
const arrLength = arr.length - 1;
|
|
49
|
+
for (let i = 0; i < arrLength; i++) {
|
|
50
|
+
const childKey = arr[i];
|
|
51
|
+
const grandChildKey = arr[i + 1];
|
|
52
|
+
if (childKey === "__proto__" || grandChildKey === "__proto__") return;
|
|
53
|
+
let childInParent = parentState[childKey];
|
|
54
|
+
if (!childInParent) childInParent = parentState[childKey] = {};
|
|
55
|
+
if (!childInParent[grandChildKey]) childInParent[grandChildKey] = {};
|
|
56
|
+
stateKey = grandChildKey;
|
|
57
|
+
parentState = childInParent;
|
|
58
|
+
}
|
|
59
|
+
if (options.returnParent) return parentState;
|
|
60
|
+
return parentState[stateKey];
|
|
61
|
+
};
|
|
62
|
+
const findInheritedState = (element, parent, options = {}) => {
|
|
63
|
+
const ref = element.__ref;
|
|
64
|
+
let stateKey = ref.__state;
|
|
65
|
+
if (!checkIfInherits(element)) return;
|
|
66
|
+
const rootState = getRootStateInKey(stateKey, parent.state);
|
|
67
|
+
let parentState = parent.state;
|
|
68
|
+
if (rootState) {
|
|
69
|
+
parentState = rootState;
|
|
70
|
+
stateKey = stateKey.replaceAll("~/", "");
|
|
71
|
+
} else {
|
|
72
|
+
const findGrandParentState = getParentStateInKey(stateKey, parent.state);
|
|
73
|
+
if (findGrandParentState) {
|
|
74
|
+
parentState = findGrandParentState;
|
|
75
|
+
stateKey = stateKey.replaceAll("../", "");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (!parentState) return;
|
|
79
|
+
return getChildStateInKey(stateKey, parentState, options);
|
|
80
|
+
};
|
|
81
|
+
const createInheritedState = (element, parent) => {
|
|
82
|
+
const ref = element.__ref;
|
|
83
|
+
const inheritedState = findInheritedState(element, parent);
|
|
84
|
+
if (inheritedState === void 0) return element.state;
|
|
85
|
+
if (is(inheritedState)("object", "array")) {
|
|
86
|
+
return deepClone(inheritedState);
|
|
87
|
+
} else if (is(inheritedState)("string", "number", "boolean")) {
|
|
88
|
+
ref.__stateType = typeof inheritedState;
|
|
89
|
+
return { value: inheritedState };
|
|
90
|
+
}
|
|
91
|
+
console.warn(ref.__state, "is not present. Replacing with", {});
|
|
92
|
+
};
|
|
93
|
+
const checkIfInherits = (element) => {
|
|
94
|
+
const { __ref: ref } = element;
|
|
95
|
+
const stateKey = ref?.__state;
|
|
96
|
+
if (stateKey && is(stateKey)("number", "string", "boolean")) return true;
|
|
97
|
+
return false;
|
|
98
|
+
};
|
|
99
|
+
const isState = function(state) {
|
|
100
|
+
if (!isObjectLike(state)) return false;
|
|
101
|
+
return Boolean(
|
|
102
|
+
state.update && state.parse && state.clean && state.create && state.parent && state.destroy && state.rootUpdate && state.parentUpdate && state.keys && state.values && state.toggle && state.replace && state.quietUpdate && state.quietReplace && state.add && state.apply && state.applyReplace && state.setByPath && state.setPathCollection && state.removeByPath && state.removePathCollection && state.getByPath && state.applyFunction && state.__element && state.__children
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
const createNestedObjectByKeyPath = (path, value) => {
|
|
106
|
+
if (!path) {
|
|
107
|
+
return value || {};
|
|
108
|
+
}
|
|
109
|
+
const keys = path.split("/");
|
|
110
|
+
const obj = {};
|
|
111
|
+
let ref = obj;
|
|
112
|
+
const lastIdx = keys.length - 1;
|
|
113
|
+
for (let i = 0; i <= lastIdx; i++) {
|
|
114
|
+
ref[keys[i]] = i === lastIdx ? value || {} : {};
|
|
115
|
+
ref = ref[keys[i]];
|
|
116
|
+
}
|
|
117
|
+
return obj;
|
|
118
|
+
};
|
|
119
|
+
const applyDependentState = (element, state) => {
|
|
120
|
+
const { __element } = state;
|
|
121
|
+
const origState = __element?.state;
|
|
122
|
+
if (!origState) return;
|
|
123
|
+
const dependentState = deepClone(origState, STATE_METHODS);
|
|
124
|
+
const newDepends = { [element.key]: dependentState };
|
|
125
|
+
const __depends = isObject(origState.__depends) ? { ...origState.__depends, ...newDepends } : newDepends;
|
|
126
|
+
if (Array.isArray(origState)) {
|
|
127
|
+
addProtoToArray(origState, {
|
|
128
|
+
...Object.getPrototypeOf(origState),
|
|
129
|
+
__depends
|
|
130
|
+
});
|
|
131
|
+
} else {
|
|
132
|
+
Object.setPrototypeOf(origState, {
|
|
133
|
+
...Object.getPrototypeOf(origState),
|
|
134
|
+
__depends
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return dependentState;
|
|
138
|
+
};
|
|
139
|
+
const overwriteState = (state, obj, options = {}) => {
|
|
140
|
+
const { overwrite } = options;
|
|
141
|
+
if (!overwrite) return;
|
|
142
|
+
const shallow = overwrite === "shallow";
|
|
143
|
+
const merge = overwrite === "merge";
|
|
144
|
+
if (merge) {
|
|
145
|
+
deepMerge(state, obj, STATE_METHODS);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const overwriteFunc = shallow ? overwriteShallow : overwriteDeep;
|
|
149
|
+
overwriteFunc(state, obj, STATE_METHODS);
|
|
150
|
+
};
|
|
151
|
+
export {
|
|
152
|
+
applyDependentState,
|
|
153
|
+
checkForStateTypes,
|
|
154
|
+
checkIfInherits,
|
|
155
|
+
createInheritedState,
|
|
156
|
+
createNestedObjectByKeyPath,
|
|
157
|
+
findInheritedState,
|
|
158
|
+
getChildStateInKey,
|
|
159
|
+
getParentStateInKey,
|
|
160
|
+
getRootStateInKey,
|
|
161
|
+
isState,
|
|
162
|
+
overwriteState
|
|
163
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { isString, isObject, isArray, isNumber } from "./types.js";
|
|
2
|
+
const copyStringToClipboard = async (str) => {
|
|
3
|
+
try {
|
|
4
|
+
await navigator.clipboard.writeText(str);
|
|
5
|
+
} catch (err) {
|
|
6
|
+
console.warn("Failed to copy text: ", err);
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
const copyJavaScriptToClipboard = async (jsCode) => {
|
|
10
|
+
try {
|
|
11
|
+
const blob = new Blob([jsCode], { type: "text/javascript" });
|
|
12
|
+
const clipboardItem = new window.ClipboardItem({ "text/plain": blob });
|
|
13
|
+
await navigator.clipboard.write([clipboardItem]);
|
|
14
|
+
console.log("JavaScript code copied to clipboard as text/javascript");
|
|
15
|
+
} catch (err) {
|
|
16
|
+
console.error("Failed to copy JavaScript code: ", err);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const removeChars = (str) => {
|
|
20
|
+
return str.replace(/[^a-zA-Z0-9_]/g, "");
|
|
21
|
+
};
|
|
22
|
+
const toCamelCase = (str) => {
|
|
23
|
+
if (typeof str !== "string") str = String(str || "");
|
|
24
|
+
return str.replace(/(?:^\w|[A-Z]|\b\w)/g, function(word, index) {
|
|
25
|
+
return index === 0 ? word.toLowerCase() : word.toUpperCase();
|
|
26
|
+
}).replace(/\s+/g, "");
|
|
27
|
+
};
|
|
28
|
+
const toTitleCase = (str) => str && str.replace(/\w\S*/g, (txt) => {
|
|
29
|
+
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
|
30
|
+
});
|
|
31
|
+
const toDashCase = (val) => val.replace(/[^a-zA-Z0-9]/g, " ").trim().toLowerCase().replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
32
|
+
const toDescriptionCase = (str = "") => {
|
|
33
|
+
if (typeof str !== "string") return;
|
|
34
|
+
const result = str.replace(/([A-Z])/g, " $1");
|
|
35
|
+
return result.charAt(0).toUpperCase() + result.slice(1);
|
|
36
|
+
};
|
|
37
|
+
const arrayzeValue = (val) => {
|
|
38
|
+
if (isArray(val)) return val;
|
|
39
|
+
if (isString(val)) return val.split(" ");
|
|
40
|
+
if (isObject(val)) return Object.values(val);
|
|
41
|
+
if (isNumber(val)) return [val];
|
|
42
|
+
};
|
|
43
|
+
export {
|
|
44
|
+
arrayzeValue,
|
|
45
|
+
copyJavaScriptToClipboard,
|
|
46
|
+
copyStringToClipboard,
|
|
47
|
+
removeChars,
|
|
48
|
+
toCamelCase,
|
|
49
|
+
toDashCase,
|
|
50
|
+
toDescriptionCase,
|
|
51
|
+
toTitleCase
|
|
52
|
+
};
|