@weaverse/core 5.17.1 → 5.18.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/src/types.ts ADDED
@@ -0,0 +1,264 @@
1
+ import type { CSSProperties, ForwardRefExoticComponent } from 'react'
2
+ import type { IconName } from './icon-name'
3
+
4
+ /** Actions that can be displayed in an element's Studio toolbar. */
5
+ export type ToolbarAction =
6
+ | 'general-settings'
7
+ | 'settings-level-2'
8
+ | 'duplicate'
9
+ | 'delete'
10
+ | 'global-sections'
11
+
12
+ /** Advanced style groups available in the Studio settings panel. */
13
+ export type AdvancedGroupType =
14
+ | 'border'
15
+ | 'alignment'
16
+ | 'background'
17
+ | 'dimensions'
18
+ | 'spacing'
19
+ | 'typography'
20
+ | 'visibility'
21
+ | 'shadows-and-effects'
22
+ | 'layout-background'
23
+
24
+ /** Preset positions supported by position inputs. */
25
+ export type PositionInputValue =
26
+ | 'top left'
27
+ | 'top center'
28
+ | 'top right'
29
+ | 'center left'
30
+ | 'center center'
31
+ | 'center right'
32
+ | 'bottom left'
33
+ | 'bottom center'
34
+ | 'bottom right'
35
+
36
+ /**
37
+ * Input controls supported by legacy Core schemas.
38
+ *
39
+ * @remarks Prefer the equivalent input types from `@weaverse/schema` for new
40
+ * schemas. This type remains available for backward compatibility.
41
+ */
42
+ export type InputType =
43
+ | 'blog'
44
+ | 'collection'
45
+ | 'collection-list'
46
+ | 'color'
47
+ | 'datepicker'
48
+ | 'image'
49
+ | 'video'
50
+ | 'map-autocomplete'
51
+ | 'position'
52
+ | 'product'
53
+ | 'product-list'
54
+ | 'range'
55
+ | 'richtext'
56
+ | 'select'
57
+ | 'switch'
58
+ | 'text'
59
+ | 'textarea'
60
+ | 'toggle-group'
61
+ | 'metaobject'
62
+ | 'url'
63
+
64
+ /** CSS properties accepted by Weaverse elements. */
65
+ export type WeaverseCSSProperties = CSSProperties
66
+
67
+ /** Nested CSS rules keyed by a child selector. */
68
+ export type ChildElementCSS = Partial<{
69
+ /** Styles for a nested child selector. */
70
+ [selector: string]: WeaverseCSSProperties & ChildElementCSS
71
+ }>
72
+
73
+ /** A resource selected by its numeric identifier and handle. */
74
+ export type WeaverseResourcePickerData = {
75
+ /** The resource's numeric identifier. */
76
+ id: number
77
+ /** The resource's URL-friendly handle. */
78
+ handle: string
79
+ }
80
+
81
+ /** Image metadata returned by a Weaverse image input. */
82
+ export type WeaverseImage = {
83
+ /** The image identifier. */
84
+ id: string
85
+ /** The image URL. */
86
+ url: string
87
+ /** Alternative text for the image. */
88
+ altText: string
89
+ /** The intrinsic image width in pixels. */
90
+ width: number
91
+ /** The intrinsic image height in pixels. */
92
+ height: number
93
+ /** A lightweight URL suitable for previews. */
94
+ previewSrc: string
95
+ }
96
+
97
+ /** Video metadata returned by a Weaverse video input. */
98
+ export type WeaverseVideo = {
99
+ /** The video identifier. */
100
+ id: string
101
+ /** The video URL. */
102
+ url: string
103
+ /** Alternative text for the video. */
104
+ altText: string
105
+ /** The intrinsic video width in pixels. */
106
+ width: number
107
+ /** The intrinsic video height in pixels. */
108
+ height: number
109
+ /** A lightweight URL suitable for previews. */
110
+ previewSrc: string
111
+ }
112
+
113
+ /** Additional configuration accepted by configurable input controls. */
114
+ export type AdditionalInputConfigs =
115
+ | SelectInputConfigs
116
+ | ToggleGroupConfigs
117
+ | RangeInputConfigs
118
+
119
+ /** Responsive CSS assigned to a Weaverse element. */
120
+ export type ElementCSS = {
121
+ /** Styles applied at the desktop breakpoint. */
122
+ '@desktop'?: WeaverseCSSProperties | ChildElementCSS
123
+ /** Styles applied at the mobile breakpoint. */
124
+ '@mobile'?: WeaverseCSSProperties | ChildElementCSS
125
+ }
126
+
127
+ /** Serialized data for one element in a Weaverse project. */
128
+ export type ElementData = {
129
+ /** The unique element identifier. */
130
+ id: string
131
+ /** The registered element type. */
132
+ type: string
133
+ /** Component-specific settings and metadata. */
134
+ [key: string]: any
135
+ }
136
+
137
+ /** Runtime metadata attached to a rendered Weaverse element. */
138
+ export type WeaverseElement = {
139
+ /** The React component registered for the element. */
140
+ Component: ForwardRefExoticComponent<any>
141
+ /** The registered element type. */
142
+ type: string
143
+ /** The unique element identifier used in rendered markup. */
144
+ 'data-wv-id': string
145
+ /** The element type used in rendered markup. */
146
+ 'data-wv-type': string
147
+ }
148
+
149
+ /**
150
+ * Minimal legacy schema metadata for an element.
151
+ *
152
+ * @remarks Prefer `SchemaType` from `@weaverse/schema` for new schemas. This
153
+ * type remains available for backward compatibility.
154
+ */
155
+ export type ElementSchema = {
156
+ /** The human-readable element title. */
157
+ title: string
158
+ /** The unique element type. */
159
+ type: string
160
+ }
161
+
162
+ /** Media query values used for responsive element styles. */
163
+ export type BreakPoints = {
164
+ /** The media query used for mobile styles. */
165
+ mobile: string
166
+ /** The media query used for desktop styles. */
167
+ desktop: string
168
+ }
169
+
170
+ /** Serialized project data consumed by the Core runtime. */
171
+ export type WeaverseProjectDataType = {
172
+ /** The optional project or page identifier. */
173
+ id?: string
174
+ /** All serialized elements in the project. */
175
+ items: ElementData[]
176
+ /** The identifier of the project's root element. */
177
+ rootId: string
178
+ }
179
+
180
+ /** Options used to initialize the Weaverse Core runtime. */
181
+ export type WeaverseCoreParams = {
182
+ /** Custom media queries for responsive element styles. */
183
+ mediaBreakPoints?: BreakPoints
184
+ /** Base URL of the Weaverse Studio host. */
185
+ weaverseHost?: string
186
+ /** Weaverse runtime version exposed to integrations. */
187
+ weaverseVersion?: string
188
+ /** Identifier of the project being rendered. */
189
+ projectId: string
190
+ /** Initial serialized project data. */
191
+ data: WeaverseProjectDataType
192
+ /** Whether the runtime is connected to Studio design mode. */
193
+ isDesignMode?: boolean
194
+ }
195
+
196
+ /** Describes a legacy Studio input bound to element data or styles. */
197
+ export type BasicInput<ConfigsType = AdditionalInputConfigs> = {
198
+ /** The input control to render. */
199
+ type: InputType
200
+ /** The element data or style property updated by the input. */
201
+ name: string
202
+ /** The label shown in Studio. */
203
+ label?: string
204
+ /** Additional control-specific configuration. */
205
+ configs?: ConfigsType
206
+ /** An expression controlling whether the input is displayed. */
207
+ condition?: string
208
+ /** The value used when the setting has not been customized. */
209
+ defaultValue?:
210
+ | string
211
+ | number
212
+ | boolean
213
+ | Partial<WeaverseImage>
214
+ | {
215
+ /** Structured input data keyed by field name. */
216
+ [x: string]: any
217
+ }
218
+ /** Placeholder text shown by supported controls. */
219
+ placeholder?: string
220
+ /** Supporting text shown alongside the input. */
221
+ helpText?: string
222
+ }
223
+
224
+ /** Configuration for a legacy select input. */
225
+ export type SelectInputConfigs = {
226
+ /** Choices displayed by the input. */
227
+ options?: {
228
+ /** The value stored when the option is selected. */
229
+ value: string
230
+ /** The option label shown in Studio. */
231
+ label: string
232
+ }[]
233
+ }
234
+
235
+ /** Configuration for a legacy toggle-group input. */
236
+ export type ToggleGroupConfigs = {
237
+ /** Choices displayed by the input. */
238
+ options?: {
239
+ /** The value stored when the option is selected. */
240
+ value: string
241
+ /** The option label shown in Studio. */
242
+ label: string
243
+ /** An optional icon displayed with the option. */
244
+ icon?: IconName
245
+ }[]
246
+ }
247
+
248
+ /** Configuration for a legacy range input. */
249
+ export type RangeInputConfigs = {
250
+ /** The smallest selectable value. */
251
+ min?: number
252
+ /** The largest selectable value. */
253
+ max?: number
254
+ /** The increment between selectable values. */
255
+ step?: number
256
+ /** The unit displayed beside the value. */
257
+ unit?: string
258
+ }
259
+
260
+ declare global {
261
+ interface Window {
262
+ weaverseStudio: any
263
+ }
264
+ }
@@ -0,0 +1,31 @@
1
+ /** A callback accepted by the Core runtime event system. */
2
+ export type AnyFunction = (...args: any[]) => any
3
+
4
+ /** Provides synchronous subscription and notification for runtime updates. */
5
+ export class EventEmitter {
6
+ /** Functions called when an update is emitted. */
7
+ listeners: Set<AnyFunction>
8
+
9
+ /** Creates an emitter with no listeners. */
10
+ constructor() {
11
+ this.listeners = new Set()
12
+ }
13
+
14
+ /** Adds a listener and returns a function that removes it. */
15
+ subscribe = (fn: AnyFunction) => {
16
+ this.listeners.add(fn)
17
+ return () => this.unsubscribe(fn)
18
+ }
19
+
20
+ /** Removes a previously subscribed listener. */
21
+ unsubscribe = (fn: AnyFunction) => {
22
+ this.listeners.delete(fn)
23
+ }
24
+
25
+ /** Calls every subscribed listener with the supplied data. */
26
+ emit = (data) => {
27
+ for (const fn of this.listeners) {
28
+ fn(data)
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,71 @@
1
+ /** Whether the current runtime is React Native. */
2
+ export let isReactNative =
3
+ typeof navigator === 'object' && navigator.product === 'ReactNative'
4
+
5
+ /** Whether the current runtime provides a browser window. */
6
+ export let isBrowser = typeof window !== 'undefined' && !isReactNative
7
+
8
+ /** Whether the current browser window is embedded in an iframe. */
9
+ export let isIframe = isBrowser && window.top !== window.self
10
+
11
+ /** An object whose properties can be recursively merged. */
12
+ export interface MergeObject {
13
+ /** Property value keyed by its object field name. */
14
+ [key: string]: any
15
+ }
16
+
17
+ /**
18
+ * Recursively merges object properties from `source` into a copy of `target`.
19
+ * Each nested non-array object owned by `source` is mutated in place and reused
20
+ * in the result. Arrays and non-object values replace the target value.
21
+ */
22
+ export function merge(target: MergeObject, source: MergeObject): MergeObject {
23
+ let t = { ...(target || {}) }
24
+ // Iterate through `source` properties and if an `Object` set property to merge of `target` and `source` properties
25
+ for (let key of Object.keys(source)) {
26
+ if (source[key] instanceof Object && !Array.isArray(source[key])) {
27
+ Object.assign(source[key], merge(t[key], source[key]))
28
+ }
29
+ }
30
+
31
+ // Join `target` and modified `source`
32
+ Object.assign(t || {}, source)
33
+ return t
34
+ }
35
+
36
+ // Cache in-flight/settled loads per src. A bare `querySelector` check is not
37
+ // enough: the tag exists as soon as the first caller appends it, so a second
38
+ // caller arriving before the script *executes* would resolve early and read
39
+ // globals (e.g. `window.weaverseStudio`) that aren't set yet. See issue #451.
40
+ let scriptLoadPromises = new Map<string, Promise<unknown>>()
41
+
42
+ /**
43
+ * Loads a script once and reuses the same promise for concurrent callers.
44
+ * Failed loads are removed so a later call can retry.
45
+ */
46
+ export function loadScript(src: string) {
47
+ let pending = scriptLoadPromises.get(src)
48
+ if (pending) {
49
+ return pending
50
+ }
51
+ let promise = new Promise((resolve, reject) => {
52
+ let currScript = document.querySelector(`script[src="${src}"]`)
53
+ if (currScript) {
54
+ // Tag injected outside loadScript (e.g. SSR markup) — assume executed.
55
+ return resolve(true)
56
+ }
57
+ let script = document.createElement('script')
58
+ script.src = src
59
+ script.onload = resolve
60
+ script.onerror = (error) => {
61
+ // Drop the cache entry and the broken tag so a later call can retry.
62
+ scriptLoadPromises.delete(src)
63
+ script.remove()
64
+ reject(error)
65
+ }
66
+ script.defer = true
67
+ document.body.appendChild(script)
68
+ })
69
+ scriptLoadPromises.set(src, promise)
70
+ return promise
71
+ }