@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.
Files changed (122) hide show
  1. package/LICENSE +25 -12
  2. package/README.md +106 -0
  3. package/array.js +162 -0
  4. package/cache.js +7 -0
  5. package/cdn.js +83 -0
  6. package/component.js +25 -0
  7. package/cookie.js +71 -0
  8. package/{src/detectHeight.js → detectHeight.js} +3 -3
  9. package/dist/cjs/array.js +168 -0
  10. package/dist/cjs/browser.js +0 -2
  11. package/dist/cjs/cache.js +26 -0
  12. package/dist/cjs/cdn.js +85 -0
  13. package/dist/cjs/component.js +45 -0
  14. package/dist/cjs/cookie.js +75 -0
  15. package/dist/cjs/date.js +1 -3
  16. package/dist/cjs/detectHeight.js +4 -6
  17. package/dist/cjs/element.js +136 -0
  18. package/dist/cjs/env.js +43 -0
  19. package/dist/cjs/events.js +39 -0
  20. package/dist/cjs/extends.js +434 -0
  21. package/dist/cjs/fibonacci.js +1 -3
  22. package/dist/cjs/files.js +1 -3
  23. package/dist/cjs/function.js +114 -0
  24. package/dist/cjs/globals.js +30 -0
  25. package/dist/cjs/if.js +48 -0
  26. package/dist/cjs/index.js +38 -425
  27. package/dist/cjs/key.js +38 -0
  28. package/dist/cjs/keys.js +201 -0
  29. package/dist/cjs/load.js +5 -7
  30. package/dist/cjs/log.js +34 -0
  31. package/dist/cjs/metadata.js +310 -0
  32. package/dist/cjs/methods.js +599 -0
  33. package/dist/cjs/node.js +35 -0
  34. package/dist/cjs/object.js +634 -0
  35. package/dist/cjs/projectKeys.js +35 -0
  36. package/dist/cjs/props.js +282 -0
  37. package/dist/cjs/scaling.js +5 -169
  38. package/dist/cjs/scope.js +44 -0
  39. package/dist/cjs/sharedLibraries.js +146 -0
  40. package/dist/cjs/state.js +173 -0
  41. package/dist/cjs/string-extra.js +72 -0
  42. package/dist/cjs/string.js +183 -0
  43. package/dist/cjs/style.js +1 -3
  44. package/dist/cjs/tags.js +220 -0
  45. package/dist/cjs/triggerEvent.js +112 -0
  46. package/dist/cjs/types.js +74 -0
  47. package/dist/cjs/update.js +42 -0
  48. package/dist/esm/array.js +148 -0
  49. package/dist/esm/browser.js +14 -0
  50. package/dist/esm/cache.js +6 -0
  51. package/dist/esm/cdn.js +65 -0
  52. package/dist/esm/component.js +25 -0
  53. package/dist/esm/cookie.js +55 -0
  54. package/dist/esm/date.js +11 -0
  55. package/dist/esm/detectHeight.js +42 -0
  56. package/dist/esm/element.js +116 -0
  57. package/dist/esm/env.js +23 -0
  58. package/dist/esm/events.js +19 -0
  59. package/dist/esm/extends.js +414 -0
  60. package/dist/esm/fibonacci.js +10 -0
  61. package/dist/esm/files.js +4 -0
  62. package/dist/esm/function.js +94 -0
  63. package/dist/esm/globals.js +10 -0
  64. package/dist/esm/if.js +28 -0
  65. package/dist/esm/index.js +37 -0
  66. package/dist/esm/key.js +18 -0
  67. package/dist/esm/keys.js +181 -0
  68. package/dist/esm/load.js +151 -0
  69. package/dist/esm/log.js +14 -0
  70. package/dist/esm/metadata.js +290 -0
  71. package/dist/esm/methods.js +569 -0
  72. package/dist/esm/node.js +15 -0
  73. package/dist/esm/object.js +621 -0
  74. package/dist/esm/projectKeys.js +16 -0
  75. package/dist/esm/props.js +262 -0
  76. package/dist/esm/scaling.js +15 -0
  77. package/dist/esm/scope.js +24 -0
  78. package/dist/esm/sharedLibraries.js +126 -0
  79. package/dist/esm/state.js +163 -0
  80. package/dist/esm/string-extra.js +52 -0
  81. package/dist/esm/string.js +163 -0
  82. package/dist/esm/style.js +20 -0
  83. package/dist/esm/tags.js +200 -0
  84. package/dist/esm/triggerEvent.js +92 -0
  85. package/dist/esm/types.js +54 -0
  86. package/dist/esm/update.js +22 -0
  87. package/dist/iife/index.js +5818 -0
  88. package/element.js +148 -0
  89. package/env.js +15 -0
  90. package/events.js +19 -0
  91. package/extends.js +519 -0
  92. package/function.js +145 -0
  93. package/globals.js +8 -0
  94. package/if.js +30 -0
  95. package/index.js +41 -0
  96. package/key.js +20 -0
  97. package/keys.js +176 -0
  98. package/log.js +12 -0
  99. package/metadata.js +392 -0
  100. package/methods.js +636 -0
  101. package/node.js +37 -0
  102. package/object.js +803 -0
  103. package/package.json +38 -22
  104. package/projectKeys.js +30 -0
  105. package/props.js +327 -0
  106. package/{src/scaling.js → scaling.js} +1 -1
  107. package/scope.js +32 -0
  108. package/sharedLibraries.js +184 -0
  109. package/state.js +203 -0
  110. package/{src/index.js → string-extra.js} +11 -17
  111. package/string.js +206 -0
  112. package/tags.js +176 -0
  113. package/triggerEvent.js +102 -0
  114. package/types.js +55 -0
  115. package/update.js +27 -0
  116. package/dist/cjs/package.json +0 -4
  117. /package/{src/browser.js → browser.js} +0 -0
  118. /package/{src/date.js → date.js} +0 -0
  119. /package/{src/fibonacci.js → fibonacci.js} +0 -0
  120. /package/{src/files.js → files.js} +0 -0
  121. /package/{src/load.js → load.js} +0 -0
  122. /package/{src/style.js → style.js} +0 -0
package/element.js ADDED
@@ -0,0 +1,148 @@
1
+ 'use strict'
2
+
3
+ import { createExtends } from './extends.js'
4
+ import { createKey } from './key.js'
5
+ import { isNode } from './node.js'
6
+ import { createProps } from './props.js'
7
+ import { HTML_TAGS } from './tags.js'
8
+ import { is, isFunction } from './types.js'
9
+
10
+ const ENV = process.env.NODE_ENV
11
+
12
+ export const returnValueAsText = (element, parent, key) => {
13
+ const childExtendsTag = parent.childExtends && parent.childExtends.tag
14
+ const childPropsTag = parent.childProps && parent.childProps.tag
15
+ const isKeyValidHTMLTag = HTML_TAGS.body.has(key) && key
16
+ return {
17
+ text: element,
18
+ tag: childExtendsTag || childPropsTag || isKeyValidHTMLTag || 'string'
19
+ }
20
+ }
21
+
22
+ export const createBasedOnType = (element, parent, key) => {
23
+ // if ELEMENT is not given
24
+ if (element === undefined) {
25
+ if (ENV === 'test' || ENV === 'development') {
26
+ console.warn(
27
+ key,
28
+ 'element is undefined in',
29
+ parent?.__ref?.path
30
+ )
31
+ }
32
+ return {}
33
+ }
34
+
35
+ if (element === null) return
36
+ if (element === true) return {}
37
+
38
+ if (is(element)('string', 'number')) {
39
+ return returnValueAsText(element, parent, key)
40
+ }
41
+
42
+ if (isFunction(element)) {
43
+ return { props: element }
44
+ }
45
+
46
+ return element
47
+ }
48
+
49
+ export const addRef = (element, parent) => {
50
+ const ref = {}
51
+ ref.origin = element
52
+ ref.parent = parent
53
+ return ref
54
+ }
55
+
56
+ export const createParent = (element, parent, key, options, root) => {
57
+ if (!parent) return root
58
+ if (isNode(parent)) {
59
+ const parentNodeWrapper = { key: ':root', node: parent }
60
+ root[`${key}_parent`] = parentNodeWrapper
61
+ return parentNodeWrapper
62
+ }
63
+ return parent
64
+ }
65
+
66
+ export const createRoot = (element, parent) => {
67
+ const { __ref: ref } = element
68
+ const { __ref: parentRef } = parent
69
+
70
+ const hasRoot = parent && parent.key === ':root'
71
+ if (!ref?.root) {
72
+ ref.root = hasRoot ? element : parentRef?.root
73
+ }
74
+ }
75
+
76
+ export const createPath = (element, parent, key) => {
77
+ let { __ref: parentRef } = parent
78
+ // set the PATH array
79
+ if (!parentRef) parentRef = parent.ref = {}
80
+ if (!parentRef.path) parentRef.path = []
81
+ return parentRef.path.concat(key)
82
+ }
83
+
84
+ export const addContext = (element, parent, key, options, root) => {
85
+ const forcedOptionsContext =
86
+ options.context && !root.context && !element.context
87
+ if (forcedOptionsContext) root.context = options.context
88
+
89
+ // inherit from parent or root
90
+ return options.context || parent.context || root.context || element.context
91
+ }
92
+
93
+ export const addCaching = (element, parent, key) => {
94
+ const ref = addRef(element, parent)
95
+
96
+ element.__ref = ref
97
+
98
+ // enable CACHING
99
+ if (!ref.__defineCache) ref.__defineCache = {}
100
+
101
+ // enable EXEC
102
+ if (!ref.__exec) ref.__exec = {}
103
+ if (!ref.__execProps) ref.__execProps = {}
104
+
105
+ // enable CLASS CACHING
106
+ if (!ref.__class) ref.__class = {}
107
+ if (!ref.__classNames) ref.__classNames = {}
108
+
109
+ // enable CLASS CACHING
110
+ if (!ref.__attr) ref.__attr = {}
111
+
112
+ // enable CHANGES storing
113
+ if (!ref.__changes) ref.__changes = []
114
+
115
+ // enable CHANGES storing
116
+ if (!ref.__children) ref.__children = []
117
+
118
+ ref.__extends = createExtends(element, parent, key)
119
+ ref.path = createPath(element, parent, key)
120
+
121
+ return ref
122
+ }
123
+
124
+ export const createElement = (passedProps, parentEl, passedKey, opts, root) => {
125
+ const hashed = passedProps?.__hash
126
+ const element = hashed
127
+ ? { extends: [passedProps] }
128
+ : createBasedOnType(passedProps, parentEl, passedKey)
129
+ if (!element) return
130
+
131
+ const parent = createParent(element, parentEl, passedKey, opts, root)
132
+ const key = createKey(element, parent, passedKey)
133
+
134
+ addCaching(element, parent, key)
135
+
136
+ const props = createProps(element, parent, key)
137
+ const context = addContext(element, parent, key, opts, root)
138
+ const on = element.on || {}
139
+
140
+ return {
141
+ ...element,
142
+ key,
143
+ props,
144
+ parent,
145
+ context,
146
+ on
147
+ }
148
+ }
package/env.js ADDED
@@ -0,0 +1,15 @@
1
+ 'use strict'
2
+
3
+ // @preserve-env
4
+ export const NODE_ENV = process.env.NODE_ENV
5
+ export const ENV = NODE_ENV
6
+
7
+ export const isProduction = (env = NODE_ENV) => env === 'production'
8
+ export const isTest = (env = NODE_ENV) => env === 'testing' || env === 'test'
9
+ export const isTesting = isTest
10
+ export const isStaging = (env = NODE_ENV) => env === 'staging'
11
+ export const isLocal = (env = NODE_ENV) => env === 'local'
12
+ export const isDevelopment = (env = NODE_ENV) =>
13
+ env === 'development' || env === 'dev' || env === 'local'
14
+ export const getNev = (key, env = NODE_ENV) => env[key]
15
+ export const isNotProduction = (env = NODE_ENV) => !isProduction(env)
package/events.js ADDED
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ import { lowercaseFirstLetter } from './string.js'
4
+ import { isFunction } from './types.js'
5
+
6
+ export function addEventFromProps (key, obj) {
7
+ const { props, on } = obj
8
+ const eventName = lowercaseFirstLetter(key.split('on')[1])
9
+ const origEvent = on[eventName]
10
+ const funcFromProps = props[key]
11
+ if (isFunction(origEvent)) {
12
+ on[eventName] = (...args) => {
13
+ const originalEventRetunrs = origEvent(...args)
14
+ if (originalEventRetunrs !== false) {
15
+ if (isFunction(funcFromProps)) return funcFromProps(...args)
16
+ }
17
+ }
18
+ } else on[eventName] = funcFromProps
19
+ }
package/extends.js ADDED
@@ -0,0 +1,519 @@
1
+ 'use strict'
2
+
3
+ import { joinArrays, removeDuplicatesInArray } from './array.js'
4
+ import { matchesComponentNaming } from './component.js'
5
+ import { deepClone, exec } from './object.js'
6
+ import { isArray, isObject, isString } from './types.js'
7
+ const ENV = process.env.NODE_ENV
8
+ const isSourcemapEnabled = (options) => options.sourcemap !== false && ENV !== 'production'
9
+
10
+ export const createExtendsFromKeys = key => {
11
+ if (key.includes('+')) {
12
+ return key.split('+').filter(matchesComponentNaming)
13
+ }
14
+
15
+ if (key.includes('_')) {
16
+ const [first] = key.split('_')
17
+ return [first]
18
+ }
19
+
20
+ if (key.includes('.') && !matchesComponentNaming(key.split('.')[1])) {
21
+ const [first] = key.split('.')
22
+ return [first]
23
+ }
24
+
25
+ return [key]
26
+ }
27
+
28
+ // Initial extend creation
29
+ export const createExtends = (element, parent, key) => {
30
+ let __extends = []
31
+ const keyExtends = createExtendsFromKeys(key)
32
+ if (keyExtends) __extends = [...keyExtends]
33
+ const elementExtends = element.extends
34
+ if (elementExtends) {
35
+ __extends = isArray(elementExtends)
36
+ ? [...__extends, ...elementExtends]
37
+ : [...__extends, elementExtends]
38
+ }
39
+ return __extends
40
+ }
41
+
42
+ export const addExtends = (newExtends, element) => {
43
+ const { __ref: ref } = element
44
+ let { __extends } = ref
45
+
46
+ if (!newExtends) return __extends
47
+
48
+ // Check if the first extend has a variant in components
49
+ const variant = element.variant
50
+ const context = element.context
51
+ if (
52
+ variant &&
53
+ context?.components &&
54
+ !Array.isArray(newExtends) &&
55
+ typeof newExtends === 'string'
56
+ ) {
57
+ const variantKey = `${newExtends}.${variant}`
58
+ if (context.components[variantKey]) {
59
+ newExtends = variantKey
60
+ }
61
+ }
62
+
63
+ if (!__extends.includes(newExtends)) {
64
+ __extends = Array.isArray(newExtends)
65
+ ? [...__extends, ...newExtends]
66
+ : [...__extends, newExtends]
67
+ ref.__extends = __extends
68
+ }
69
+ return __extends
70
+ }
71
+
72
+ export const concatAddExtends = (newExtend, element) => {
73
+ if (!newExtend) return element
74
+ const { extends: elementExtend } = element
75
+ const originalArray = isArray(elementExtend) ? elementExtend : [elementExtend]
76
+ const receivedArray = isArray(newExtend) ? newExtend : [newExtend]
77
+ return {
78
+ ...element,
79
+ extends: joinArrays(receivedArray, originalArray)
80
+ }
81
+ }
82
+
83
+ export const generateHash = () => Math.random().toString(36).substring(2)
84
+
85
+ // hashing
86
+ export const extendStackRegistry = {}
87
+ export const extendCachedRegistry = {}
88
+
89
+ export const getHashedExtend = extend => {
90
+ return extendStackRegistry[extend.__hash]
91
+ }
92
+
93
+ export const setHashedExtend = (extend, stack) => {
94
+ const hash = generateHash()
95
+ if (!isString(extend)) {
96
+ extend.__hash = hash
97
+ }
98
+ if (hash !== '__proto__' && hash !== 'constructor' && hash !== 'prototype') {
99
+ extendStackRegistry[hash] = stack
100
+ }
101
+ return stack
102
+ }
103
+
104
+ export const getExtendsStackRegistry = (extend, stack) => {
105
+ if (extend.__hash) {
106
+ return stack.concat(getHashedExtend(extend))
107
+ }
108
+ return setHashedExtend(extend, stack) // stack .concat(hashedExtend)
109
+ }
110
+
111
+ // stacking
112
+ export const extractArrayExtend = (
113
+ extend,
114
+ stack,
115
+ context,
116
+ processed = new Set(),
117
+ nameStack,
118
+ componentNameMap
119
+ ) => {
120
+ for (const each of extend) {
121
+ if (isArray(each)) {
122
+ extractArrayExtend(each, stack, context, processed, nameStack, componentNameMap)
123
+ } else {
124
+ flattenExtend(each, stack, context, processed, nameStack, undefined, componentNameMap)
125
+ }
126
+ }
127
+ return stack
128
+ }
129
+
130
+ export const deepExtend = (extend, stack, context, processed = new Set(), nameStack, currentName, componentNameMap) => {
131
+ const extendOflattenExtend = extend.extends
132
+ const cleanExtend = { ...extend }
133
+ delete cleanExtend.extends
134
+ let hasKeys = false
135
+ for (const _k in cleanExtend) { hasKeys = true; break } // eslint-disable-line
136
+ if (hasKeys) {
137
+ stack.push(cleanExtend)
138
+ if (nameStack) nameStack.push(currentName)
139
+ }
140
+ if (extendOflattenExtend) {
141
+ flattenExtend(extendOflattenExtend, stack, context, processed, nameStack, currentName, componentNameMap)
142
+ }
143
+ return stack
144
+ }
145
+
146
+ export const flattenExtend = (
147
+ extend,
148
+ stack,
149
+ context,
150
+ processed = new Set(),
151
+ nameStack,
152
+ parentName,
153
+ componentNameMap
154
+ ) => {
155
+ if (!extend) return stack
156
+ if (processed.has(extend)) return stack
157
+
158
+ if (isArray(extend)) {
159
+ return extractArrayExtend(extend, stack, context, processed, nameStack, componentNameMap)
160
+ }
161
+
162
+ let currentName = parentName
163
+ if (isString(extend)) {
164
+ currentName = extend
165
+ extend = mapStringsWithContextComponents(extend, context)
166
+ } else if (componentNameMap && isObject(extend) && componentNameMap.has(extend)) {
167
+ // Resolve name from pre-built map (top-level resolved extends)
168
+ currentName = componentNameMap.get(extend)
169
+ }
170
+
171
+ processed.add(extend)
172
+
173
+ if (extend?.extends) {
174
+ deepExtend(extend, stack, context, processed, nameStack, currentName, componentNameMap)
175
+ } else if (extend) {
176
+ stack.push(extend)
177
+ if (nameStack) nameStack.push(currentName)
178
+ }
179
+
180
+ return stack
181
+ }
182
+
183
+ const MERGE_EXTENDS_SKIP = new Set([
184
+ 'parent', 'node', '__ref', '__proto__', 'extends', 'childExtends', 'childExtendsRecursive'
185
+ ])
186
+
187
+ export const deepMergeExtends = (element, extend, sourcemap, sourceName, preBuiltSourcemap) => {
188
+ // Clone extend to prevent mutations
189
+ extend = deepClone(extend)
190
+
191
+ for (const e in extend) {
192
+ if (MERGE_EXTENDS_SKIP.has(e)) continue
193
+
194
+ const elementProp = element[e]
195
+ const extendProp = extend[e]
196
+
197
+ // Skip if the property is undefined in the extend object
198
+ if (extendProp === undefined) continue
199
+
200
+ // Handle only properties that exist in the extend object
201
+ if (
202
+ Object.prototype.hasOwnProperty.call(extend, e) &&
203
+ e !== '__proto__' && e !== 'constructor' && e !== 'prototype'
204
+ ) {
205
+ if (elementProp === undefined) {
206
+ // For undefined properties in element, copy from extend
207
+ element[e] = extendProp
208
+ // Track sourcemap for this property
209
+ if (sourcemap && sourceName) {
210
+ if (isObject(extendProp) && !isArray(extendProp)) {
211
+ sourcemap[e] = sourcemap[e] || {}
212
+ trackSourcemapDeep(sourcemap[e], extendProp, sourceName)
213
+ } else {
214
+ sourcemap[e] = sourceName
215
+ }
216
+ } else if (sourcemap && preBuiltSourcemap?.[e]) {
217
+ // Copy sourcemap entry from pre-built sourcemap (used in finalizeExtends)
218
+ sourcemap[e] = preBuiltSourcemap[e]
219
+ }
220
+ } else if (isObject(elementProp) && isObject(extendProp)) {
221
+ // For objects, merge based on type
222
+ const nestedSourcemap = sourcemap ? (sourcemap[e] = sourcemap[e] || {}) : undefined
223
+ const nestedPreBuilt = preBuiltSourcemap?.[e]
224
+ if (matchesComponentNaming(e)) {
225
+ // For components, override base properties with extended ones
226
+ element[e] = deepMergeExtends(elementProp, extendProp, nestedSourcemap, sourceName, nestedPreBuilt)
227
+ } else {
228
+ // For other objects, merge normally
229
+ deepMergeExtends(elementProp, extendProp, nestedSourcemap, sourceName, nestedPreBuilt)
230
+ }
231
+ }
232
+
233
+ if (
234
+ e === 'extends' ||
235
+ e === 'childExtends' ||
236
+ e === 'childExtendsRecursive'
237
+ ) {
238
+ if (isArray(elementProp) && isArray(extendProp)) {
239
+ element[e] = elementProp.concat(extendProp)
240
+ } else if (isArray(elementProp) && isObject(extendProp)) {
241
+ const obj = deepMergeExtends({}, elementProp)
242
+ element[e] = deepMergeExtends(obj, extendProp)
243
+ }
244
+ }
245
+ // If elementProp is defined and not an object, keep it (don't override)
246
+ // This preserves properties from earlier in the extend chain
247
+ }
248
+ }
249
+
250
+ return element
251
+ }
252
+
253
+ const trackSourcemapDeep = (sourcemap, obj, sourceName, seen) => {
254
+ if (!seen) seen = new WeakSet()
255
+ if (seen.has(obj)) return
256
+ seen.add(obj)
257
+ for (const key in obj) {
258
+ if (!Object.prototype.hasOwnProperty.call(obj, key)) continue
259
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue
260
+ const val = obj[key]
261
+ if (isObject(val) && !isArray(val)) {
262
+ sourcemap[key] = sourcemap[key] || {}
263
+ trackSourcemapDeep(sourcemap[key], val, sourceName, seen)
264
+ } else {
265
+ sourcemap[key] = sourceName
266
+ }
267
+ }
268
+ }
269
+
270
+ export const cloneAndMergeArrayExtend = (stack, sourcemap, extendNames) => {
271
+ return stack.reduce((acc, current, i) => {
272
+ // Clone current extend to avoid mutations
273
+ const cloned = deepClone(current)
274
+ const sourceName = extendNames ? extendNames[i] : undefined
275
+ // Merge into accumulator, giving priority to current extend
276
+ return deepMergeExtends(acc, cloned, sourcemap, sourceName)
277
+ }, {})
278
+ }
279
+
280
+ export const mapStringsWithContextComponents = (
281
+ extend,
282
+ context,
283
+ options = {},
284
+ variant
285
+ ) => {
286
+ const COMPONENTS = context?.components || options.components
287
+ const PAGES = context?.pages || options.pages
288
+ if (isString(extend)) {
289
+ const componentExists =
290
+ COMPONENTS &&
291
+ (COMPONENTS[extend + '.' + variant] ||
292
+ COMPONENTS[extend] ||
293
+ COMPONENTS['smbls.' + extend])
294
+ const pageExists = PAGES && extend.charCodeAt(0) === 47 && PAGES[extend]
295
+ if (componentExists) return componentExists
296
+ else if (pageExists) return pageExists
297
+ else {
298
+ if (options.verbose && (ENV === 'test' || ENV === 'development')) {
299
+ console.warn('Extend is string but component was not found:', extend)
300
+ }
301
+ return
302
+ }
303
+ }
304
+ return extend
305
+ }
306
+
307
+ // joint stacks
308
+ export const jointStacks = (extendStack, childExtendsStack) => {
309
+ return []
310
+ .concat(extendStack.slice(0, 1))
311
+ .concat(childExtendsStack.slice(0, 1))
312
+ .concat(extendStack.slice(1))
313
+ .concat(childExtendsStack.slice(1))
314
+ }
315
+
316
+ // init
317
+ export const getExtendsStack = (extend, context, nameStack, componentNameMap) => {
318
+ if (!extend) return []
319
+ if (extend.__hash) return getHashedExtend(extend) || []
320
+ const processed = new Set()
321
+ const stack = flattenExtend(extend, [], context, processed, nameStack, undefined, componentNameMap)
322
+ if (nameStack) return stack
323
+ return getExtendsStackRegistry(extend, stack)
324
+ }
325
+
326
+ export const addExtend = (newExtends, elementExtends) => {
327
+ if (!newExtends) return elementExtends
328
+ const receivedArray = isArray(newExtends) ? newExtends : [newExtends]
329
+ return joinArrays(receivedArray, elementExtends)
330
+ }
331
+
332
+ export const getExtendsInElement = obj => {
333
+ let result = []
334
+
335
+ function traverse (o) {
336
+ for (const key in o) {
337
+ if (Object.prototype.hasOwnProperty.call(o, key)) {
338
+ // Check if the key starts with a capital letter and exclude keys like @mobileL, $router
339
+ if (matchesComponentNaming(key)) {
340
+ result.push(key)
341
+ }
342
+
343
+ // Check if the key is "extend" and it's either a string or an array
344
+ if (key === 'extends') {
345
+ // Add the value of the extend key to the result array
346
+ if (typeof o[key] === 'string') {
347
+ result.push(o[key])
348
+ } else if (Array.isArray(o[key])) {
349
+ result = result.concat(o[key])
350
+ }
351
+ }
352
+
353
+ // If the property is an object, traverse it
354
+ if (typeof o[key] === 'object' && o[key] !== null) {
355
+ traverse(o[key])
356
+ }
357
+ }
358
+ }
359
+ }
360
+
361
+ traverse(obj)
362
+ return result
363
+ }
364
+
365
+ export const createElementExtends = (element, parent, options = {}) => {
366
+ const { __ref: ref } = element
367
+ const context = element.context || parent.context
368
+ const variant = element.variant
369
+
370
+ if (element.extends) {
371
+ if (Array.isArray(element.extends) && element.extends.length > 0) {
372
+ // Handle first item in array specially for variant
373
+ const [firstExtend, ...restExtends] = element.extends
374
+ if (typeof firstExtend === 'string' && variant && context?.components) {
375
+ const variantKey = `${firstExtend}.${variant}`
376
+ if (context.components[variantKey]) {
377
+ addExtends([variantKey, ...restExtends], element)
378
+ } else {
379
+ addExtends(element.extends, element)
380
+ }
381
+ } else {
382
+ addExtends(element.extends, element)
383
+ }
384
+ } else if (
385
+ typeof element.extends === 'string' &&
386
+ variant &&
387
+ context?.components
388
+ ) {
389
+ const variantKey = `${element.extends}.${variant}`
390
+ if (context.components[variantKey]) {
391
+ addExtends(variantKey, element)
392
+ } else {
393
+ addExtends(element.extends, element)
394
+ }
395
+ } else {
396
+ addExtends(element.extends, element)
397
+ }
398
+ }
399
+
400
+ inheritChildPropsExtends(element, parent, options)
401
+ inheritChildExtends(element, parent, options)
402
+ inheritRecursiveChildExtends(element, parent, options)
403
+
404
+ if (element.component) {
405
+ addExtends(exec(element.component, element), element)
406
+ }
407
+
408
+ if (context.defaultExtends) {
409
+ addExtends(context.defaultExtends, element)
410
+ }
411
+
412
+ return removeDuplicatesInArray(ref.__extends)
413
+ }
414
+
415
+ export const inheritChildPropsExtends = (element, parent, options = {}) => {
416
+ const { __ref: ref } = element
417
+ const ignoreChildExtends =
418
+ options.ignoreChildExtends || element.ignoreChildExtends
419
+ if (!ignoreChildExtends) {
420
+ if (parent.childProps?.extends) {
421
+ addExtends(parent.childProps.extends, element)
422
+ }
423
+ }
424
+ return ref.__extends
425
+ }
426
+
427
+ export const inheritChildExtends = (element, parent, options = {}) => {
428
+ const { __ref: ref } = element
429
+ const ignoreChildExtends =
430
+ options.ignoreChildExtends || element.ignoreChildExtends
431
+
432
+ const childExtends = parent.childExtends
433
+ if (!ignoreChildExtends && childExtends) {
434
+ addExtends(childExtends, element)
435
+ }
436
+ return ref.__extends
437
+ }
438
+
439
+ export const inheritRecursiveChildExtends = (element, parent, options = {}) => {
440
+ const { __ref: ref } = element
441
+ const childExtendsRecursive = parent.childExtendsRecursive
442
+ const ignoreChildExtendsRecursive =
443
+ options.ignoreChildExtendsRecursive || element.ignoreChildExtendsRecursive
444
+ const isText = element.key === '__text'
445
+ if (childExtendsRecursive && !isText && !ignoreChildExtendsRecursive) {
446
+ addExtends(childExtendsRecursive, element)
447
+ }
448
+ return ref.__extends
449
+ }
450
+
451
+ export const createExtendsStack = (element, parent, options = {}) => {
452
+ const { __ref: ref } = element
453
+ const context = element.context || parent.context
454
+
455
+ const variant = element.variant
456
+
457
+ // Keep original string names before resolution for sourcemap tracking
458
+ const sourcemap = isSourcemapEnabled(options)
459
+ const originalExtendNames = sourcemap ? [...ref.__extends] : null
460
+
461
+ const __extends = removeDuplicatesInArray(
462
+ ref.__extends.map((val, i) => {
463
+ return mapStringsWithContextComponents(
464
+ val,
465
+ context,
466
+ options,
467
+ i === 0 && variant
468
+ )
469
+ })
470
+ )
471
+
472
+ if (sourcemap) {
473
+ // Build a map from resolved component objects to their original string names
474
+ const componentNameMap = new WeakMap()
475
+ for (let i = 0; i < __extends.length; i++) {
476
+ const resolved = __extends[i]
477
+ const originalName = originalExtendNames[i]
478
+ if (resolved && isObject(resolved) && isString(originalName)) {
479
+ componentNameMap.set(resolved, originalName)
480
+ }
481
+ }
482
+ const nameStack = []
483
+ const stack = getExtendsStack(__extends, context, nameStack, componentNameMap)
484
+ ref.__extendsStack = stack
485
+ ref.__extendsNames = nameStack
486
+ } else {
487
+ const stack = getExtendsStack(__extends, context)
488
+ ref.__extendsStack = stack
489
+ }
490
+
491
+ return ref.__extendsStack
492
+ }
493
+
494
+ export const finalizeExtends = (element, parent, options = {}) => {
495
+ const { __ref: ref } = element
496
+ const { __extendsStack } = ref
497
+
498
+ if (isSourcemapEnabled(options)) {
499
+ const sourcemapAcc = {}
500
+ const extendNames = ref.__extendsNames || []
501
+ const flattenExtends = cloneAndMergeArrayExtend(__extendsStack, sourcemapAcc, extendNames)
502
+ // Only keep sourcemap entries for properties actually merged into element
503
+ const appliedSourcemap = {}
504
+ deepMergeExtends(element, flattenExtends, appliedSourcemap, undefined, sourcemapAcc)
505
+ ref.__sourcemap = appliedSourcemap
506
+ } else {
507
+ const flattenExtends = cloneAndMergeArrayExtend(__extendsStack)
508
+ deepMergeExtends(element, flattenExtends)
509
+ }
510
+
511
+ return element
512
+ }
513
+
514
+ export const applyExtends = (element, parent, options = {}) => {
515
+ createElementExtends(element, parent, options)
516
+ createExtendsStack(element, parent, options)
517
+ finalizeExtends(element, parent, options)
518
+ return element
519
+ }