@servlyadmin/runtime-core 0.1.8 → 0.1.9

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.js CHANGED
@@ -1,24 +1,522 @@
1
- import {
2
- DEFAULT_SERVLY_TAILWIND_CONFIG,
3
- addCustomStyles,
4
- getTailwind,
5
- initServlyTailwind,
6
- injectTailwind,
7
- isTailwindLoaded,
8
- removeCustomStyles,
9
- removeTailwind,
10
- updateTailwindConfig
11
- } from "./chunk-IWFVKY5N.js";
12
- import {
13
- buildRegistryFromBundle,
14
- collectAllDependencies,
15
- createRegistry,
16
- detectCircularDependencies,
17
- extractDependencies,
18
- extractDependenciesFromCode
19
- } from "./chunk-CIUQK4GA.js";
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __esm = (fn, res) => function __init() {
8
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
9
+ };
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+
32
+ // packages/runtime-core/src/tailwind.ts
33
+ var tailwind_exports = {};
34
+ __export(tailwind_exports, {
35
+ DEFAULT_SERVLY_TAILWIND_CONFIG: () => DEFAULT_SERVLY_TAILWIND_CONFIG,
36
+ addCustomStyles: () => addCustomStyles,
37
+ default: () => tailwind_default,
38
+ getTailwind: () => getTailwind,
39
+ initServlyTailwind: () => initServlyTailwind,
40
+ injectTailwind: () => injectTailwind,
41
+ isTailwindLoaded: () => isTailwindLoaded,
42
+ removeCustomStyles: () => removeCustomStyles,
43
+ removeTailwind: () => removeTailwind,
44
+ updateTailwindConfig: () => updateTailwindConfig
45
+ });
46
+ function injectTailwind(config = {}) {
47
+ return new Promise((resolve, reject) => {
48
+ if (tailwindInjected && tailwindScript) {
49
+ resolve();
50
+ return;
51
+ }
52
+ if (typeof document === "undefined") {
53
+ resolve();
54
+ return;
55
+ }
56
+ if (window.tailwind) {
57
+ tailwindInjected = true;
58
+ config.onReady?.();
59
+ resolve();
60
+ return;
61
+ }
62
+ const {
63
+ cdnUrl = DEFAULT_TAILWIND_CDN,
64
+ config: tailwindConfig,
65
+ plugins = [],
66
+ usePlayCdn = false,
67
+ onReady,
68
+ onError
69
+ } = config;
70
+ const script = document.createElement("script");
71
+ script.src = usePlayCdn ? `${cdnUrl}?plugins=forms,typography,aspect-ratio` : cdnUrl;
72
+ script.async = true;
73
+ script.onload = () => {
74
+ tailwindInjected = true;
75
+ tailwindScript = script;
76
+ if (tailwindConfig && window.tailwind) {
77
+ window.tailwind.config = tailwindConfig;
78
+ }
79
+ onReady?.();
80
+ resolve();
81
+ };
82
+ script.onerror = (event) => {
83
+ const error = new Error(`Failed to load Tailwind CSS from ${cdnUrl}`);
84
+ onError?.(error);
85
+ reject(error);
86
+ };
87
+ document.head.appendChild(script);
88
+ });
89
+ }
90
+ function removeTailwind() {
91
+ if (tailwindScript && tailwindScript.parentNode) {
92
+ tailwindScript.parentNode.removeChild(tailwindScript);
93
+ tailwindScript = null;
94
+ tailwindInjected = false;
95
+ delete window.tailwind;
96
+ }
97
+ }
98
+ function isTailwindLoaded() {
99
+ return tailwindInjected || !!window.tailwind;
100
+ }
101
+ function getTailwind() {
102
+ return window.tailwind;
103
+ }
104
+ function updateTailwindConfig(config) {
105
+ if (window.tailwind) {
106
+ window.tailwind.config = {
107
+ ...window.tailwind.config,
108
+ ...config
109
+ };
110
+ }
111
+ }
112
+ function addCustomStyles(css, id) {
113
+ if (typeof document === "undefined") {
114
+ throw new Error("addCustomStyles can only be used in browser environment");
115
+ }
116
+ const styleId = id || `servly-custom-styles-${Date.now()}`;
117
+ let existingStyle = document.getElementById(styleId);
118
+ if (existingStyle) {
119
+ existingStyle.textContent = css;
120
+ return existingStyle;
121
+ }
122
+ const style = document.createElement("style");
123
+ style.id = styleId;
124
+ style.textContent = css;
125
+ document.head.appendChild(style);
126
+ return style;
127
+ }
128
+ function removeCustomStyles(id) {
129
+ if (typeof document === "undefined") return;
130
+ const style = document.getElementById(id);
131
+ if (style && style.parentNode) {
132
+ style.parentNode.removeChild(style);
133
+ }
134
+ }
135
+ async function initServlyTailwind(customConfig) {
136
+ const config = customConfig ? { ...DEFAULT_SERVLY_TAILWIND_CONFIG, ...customConfig } : DEFAULT_SERVLY_TAILWIND_CONFIG;
137
+ await injectTailwind({
138
+ config,
139
+ usePlayCdn: true
140
+ });
141
+ }
142
+ var DEFAULT_TAILWIND_CDN, tailwindInjected, tailwindScript, DEFAULT_SERVLY_TAILWIND_CONFIG, tailwind_default;
143
+ var init_tailwind = __esm({
144
+ "packages/runtime-core/src/tailwind.ts"() {
145
+ DEFAULT_TAILWIND_CDN = "https://cdn.tailwindcss.com";
146
+ tailwindInjected = false;
147
+ tailwindScript = null;
148
+ DEFAULT_SERVLY_TAILWIND_CONFIG = {
149
+ theme: {
150
+ extend: {
151
+ // Add any Servly-specific theme extensions here
152
+ }
153
+ },
154
+ // Safelist common dynamic classes
155
+ safelist: [
156
+ // Spacing
157
+ { pattern: /^(p|m|gap)-/ },
158
+ // Sizing
159
+ { pattern: /^(w|h|min-w|min-h|max-w|max-h)-/ },
160
+ // Flexbox
161
+ { pattern: /^(flex|justify|items|self)-/ },
162
+ // Grid
163
+ { pattern: /^(grid|col|row)-/ },
164
+ // Colors
165
+ { pattern: /^(bg|text|border|ring)-/ },
166
+ // Typography
167
+ { pattern: /^(font|text|leading|tracking)-/ },
168
+ // Borders
169
+ { pattern: /^(rounded|border)-/ },
170
+ // Effects
171
+ { pattern: /^(shadow|opacity|blur)-/ },
172
+ // Transforms
173
+ { pattern: /^(scale|rotate|translate|skew)-/ },
174
+ // Transitions
175
+ { pattern: /^(transition|duration|ease|delay)-/ }
176
+ ]
177
+ };
178
+ tailwind_default = {
179
+ injectTailwind,
180
+ removeTailwind,
181
+ isTailwindLoaded,
182
+ getTailwind,
183
+ updateTailwindConfig,
184
+ addCustomStyles,
185
+ removeCustomStyles,
186
+ initServlyTailwind,
187
+ DEFAULT_SERVLY_TAILWIND_CONFIG
188
+ };
189
+ }
190
+ });
191
+
192
+ // packages/runtime-core/src/registry.ts
193
+ var registry_exports = {};
194
+ __export(registry_exports, {
195
+ buildRegistryFromBundle: () => buildRegistryFromBundle,
196
+ collectAllDependencies: () => collectAllDependencies,
197
+ createRegistry: () => createRegistry,
198
+ detectCircularDependencies: () => detectCircularDependencies,
199
+ extractDependencies: () => extractDependencies,
200
+ extractDependenciesFromCode: () => extractDependenciesFromCode
201
+ });
202
+ function createRegistry() {
203
+ const components = /* @__PURE__ */ new Map();
204
+ return {
205
+ get(id, version) {
206
+ if (version) {
207
+ const key = `${id}@${version}`;
208
+ if (components.has(key)) {
209
+ return components.get(key);
210
+ }
211
+ }
212
+ for (const [key, component] of components) {
213
+ if (key.startsWith(`${id}@`)) {
214
+ return component;
215
+ }
216
+ }
217
+ return components.get(id);
218
+ },
219
+ has(id, version) {
220
+ if (version) {
221
+ return components.has(`${id}@${version}`);
222
+ }
223
+ for (const key of components.keys()) {
224
+ if (key.startsWith(`${id}@`) || key === id) {
225
+ return true;
226
+ }
227
+ }
228
+ return false;
229
+ },
230
+ set(id, version, component) {
231
+ components.set(`${id}@${version}`, component);
232
+ }
233
+ };
234
+ }
235
+ function buildRegistryFromBundle(data) {
236
+ const registry = createRegistry();
237
+ registry.set(data.id, data.version, {
238
+ layout: data.layout,
239
+ propsInterface: data.propsInterface
240
+ });
241
+ if (data.bundle) {
242
+ for (const [key, component] of Object.entries(data.bundle)) {
243
+ const [id, version] = key.split("@");
244
+ if (id && version) {
245
+ registry.set(id, version, component);
246
+ }
247
+ }
248
+ }
249
+ return registry;
250
+ }
251
+ function extractDependencies(elements) {
252
+ const dependencies = [];
253
+ for (const element of elements) {
254
+ const config = element.configuration;
255
+ if (!config) continue;
256
+ if (config.componentViewRef) {
257
+ dependencies.push({
258
+ id: config.componentViewRef,
259
+ version: config.componentViewVersion,
260
+ type: "viewRef",
261
+ elementId: element.i
262
+ });
263
+ }
264
+ if (config.blueprint) {
265
+ dependencies.push({
266
+ id: config.blueprint,
267
+ version: config.blueprintVersion,
268
+ type: "blueprint",
269
+ elementId: element.i
270
+ });
271
+ }
272
+ }
273
+ return dependencies;
274
+ }
275
+ function extractDependenciesFromCode(code) {
276
+ const dependencies = [];
277
+ const pattern = /renderDynamicList\s*\(\s*\{[^}]*blueprint\s*:\s*["']([^"']+)["']/g;
278
+ let match;
279
+ while ((match = pattern.exec(code)) !== null) {
280
+ dependencies.push({
281
+ id: match[1],
282
+ type: "blueprint"
283
+ });
284
+ }
285
+ return dependencies;
286
+ }
287
+ async function collectAllDependencies(rootId, rootVersion, fetchComponent2, maxDepth = 10) {
288
+ const manifest = {};
289
+ const visited = /* @__PURE__ */ new Set();
290
+ async function collect(id, version, via, depth) {
291
+ if (depth > maxDepth) {
292
+ console.warn(`Max dependency depth (${maxDepth}) reached for ${id}`);
293
+ return;
294
+ }
295
+ const key = `${id}@${version || "latest"}`;
296
+ if (visited.has(key)) {
297
+ return;
298
+ }
299
+ visited.add(key);
300
+ try {
301
+ const component = await fetchComponent2(id, version);
302
+ if (!component) {
303
+ console.warn(`Dependency not found: ${id}@${version || "latest"}`);
304
+ return;
305
+ }
306
+ manifest[id] = {
307
+ version: version || "latest",
308
+ resolved: component.version,
309
+ type: via ? "viewRef" : "viewRef",
310
+ // Will be set by caller
311
+ via
312
+ };
313
+ const nestedDeps = extractDependencies(component.layout);
314
+ for (const dep of nestedDeps) {
315
+ await collect(dep.id, dep.version, id, depth + 1);
316
+ }
317
+ } catch (error) {
318
+ console.error(`Failed to fetch dependency ${id}:`, error);
319
+ }
320
+ }
321
+ const rootComponent = await fetchComponent2(rootId, rootVersion);
322
+ if (rootComponent) {
323
+ const rootDeps = extractDependencies(rootComponent.layout);
324
+ for (const dep of rootDeps) {
325
+ manifest[dep.id] = {
326
+ version: dep.version || "latest",
327
+ resolved: "",
328
+ // Will be filled when fetched
329
+ type: dep.type
330
+ };
331
+ await collect(dep.id, dep.version, void 0, 1);
332
+ }
333
+ }
334
+ return manifest;
335
+ }
336
+ function detectCircularDependencies(manifest) {
337
+ const graph = /* @__PURE__ */ new Map();
338
+ for (const [id, entry] of Object.entries(manifest)) {
339
+ if (entry.via) {
340
+ const deps = graph.get(entry.via) || [];
341
+ deps.push(id);
342
+ graph.set(entry.via, deps);
343
+ }
344
+ }
345
+ const visited = /* @__PURE__ */ new Set();
346
+ const stack = /* @__PURE__ */ new Set();
347
+ const path = [];
348
+ function dfs(node) {
349
+ if (stack.has(node)) {
350
+ const cycleStart = path.indexOf(node);
351
+ return [...path.slice(cycleStart), node];
352
+ }
353
+ if (visited.has(node)) {
354
+ return null;
355
+ }
356
+ visited.add(node);
357
+ stack.add(node);
358
+ path.push(node);
359
+ const neighbors = graph.get(node) || [];
360
+ for (const neighbor of neighbors) {
361
+ const cycle = dfs(neighbor);
362
+ if (cycle) return cycle;
363
+ }
364
+ stack.delete(node);
365
+ path.pop();
366
+ return null;
367
+ }
368
+ for (const node of graph.keys()) {
369
+ const cycle = dfs(node);
370
+ if (cycle) return cycle;
371
+ }
372
+ return null;
373
+ }
374
+ var init_registry = __esm({
375
+ "packages/runtime-core/src/registry.ts"() {
376
+ }
377
+ });
378
+
379
+ // packages/runtime-core/src/index.ts
380
+ var index_exports = {};
381
+ __export(index_exports, {
382
+ AnalyticsCollector: () => AnalyticsCollector,
383
+ DEFAULT_CACHE_CONFIG: () => DEFAULT_CACHE_CONFIG,
384
+ DEFAULT_RETRY_CONFIG: () => DEFAULT_RETRY_CONFIG,
385
+ DEFAULT_SERVLY_TAILWIND_CONFIG: () => DEFAULT_SERVLY_TAILWIND_CONFIG,
386
+ EVENT_HANDLERS: () => EVENT_HANDLERS,
387
+ EventSystem: () => EventSystem,
388
+ LongTaskObserver: () => LongTaskObserver,
389
+ MemorySampler: () => MemorySampler,
390
+ OverrideSystem: () => OverrideSystem,
391
+ SessionManager: () => SessionManager,
392
+ StateManager: () => StateManager,
393
+ addClass: () => addClass,
394
+ addCustomStyles: () => addCustomStyles,
395
+ analytics: () => analytics,
396
+ applyStyles: () => applyStyles,
397
+ batchFetchComponents: () => batchFetchComponents,
398
+ buildClassName: () => buildClassName,
399
+ buildElementStyles: () => buildElementStyles,
400
+ buildRegistryFromBundle: () => buildRegistryFromBundle,
401
+ bumpVersion: () => bumpVersion,
402
+ camelToKebab: () => camelToKebab,
403
+ clearAllCaches: () => clearAllCaches,
404
+ clearIconCache: () => clearIconCache,
405
+ clearLocalStorageCache: () => clearLocalStorageCache,
406
+ clearMemoryCache: () => clearMemoryCache,
407
+ clearStyles: () => clearStyles,
408
+ collectAllDependencies: () => collectAllDependencies,
409
+ collectAllViewDependencies: () => collectAllViewDependencies,
410
+ compareVersions: () => compareVersions,
411
+ configureAnalytics: () => configureAnalytics,
412
+ createIconSVG: () => createIconSVG,
413
+ createPlaceholderIcon: () => createPlaceholderIcon,
414
+ createRegistry: () => createRegistry,
415
+ createServlyRenderer: () => createServlyRenderer,
416
+ createViewsMap: () => createViewsMap,
417
+ deepMerge: () => deepMerge,
418
+ deleteValueByPath: () => deleteValueByPath,
419
+ detectCircularDependencies: () => detectCircularDependencies,
420
+ extractBindingKeys: () => extractBindingKeys,
421
+ extractDependencies: () => extractDependencies,
422
+ extractDependenciesFromCode: () => extractDependenciesFromCode,
423
+ extractIconFromReactIcons: () => extractIconFromReactIcons,
424
+ extractIconsForLayout: () => extractIconsForLayout,
425
+ extractOverrideDependencies: () => extractOverrideDependencies,
426
+ extractReferencedViewIds: () => extractReferencedViewIds,
427
+ fetchComponent: () => fetchComponent,
428
+ fetchComponentWithDependencies: () => fetchComponentWithDependencies,
429
+ findIconsInLayout: () => findIconsInLayout,
430
+ formatStyleValue: () => formatStyleValue,
431
+ formatVersion: () => formatVersion,
432
+ generateIconBundle: () => generateIconBundle,
433
+ generateTestCases: () => generateTestCases,
434
+ getAnalytics: () => getAnalytics,
435
+ getCacheKey: () => getCacheKey,
436
+ getCleanupOverrides: () => getCleanupOverrides,
437
+ getDependencyTree: () => getDependencyTree,
438
+ getEventSystem: () => getEventSystem,
439
+ getFromCache: () => getFromCache,
440
+ getIconData: () => getIconData,
441
+ getIconDataSync: () => getIconDataSync,
442
+ getIconifyCollection: () => getIconifyCollection,
443
+ getLocalStorage: () => getLocalStorage,
444
+ getLongTaskObserver: () => getLongTaskObserver,
445
+ getMemoryCacheSize: () => getMemoryCacheSize,
446
+ getMemorySampler: () => getMemorySampler,
447
+ getMountOverrides: () => getMountOverrides,
448
+ getOverrideSystem: () => getOverrideSystem,
449
+ getRegisteredIconKeys: () => getRegisteredIconKeys,
450
+ getRegistryUrl: () => getRegistryUrl,
451
+ getSessionManager: () => getSessionManager,
452
+ getSessionStorage: () => getSessionStorage,
453
+ getSupportedIconSets: () => getSupportedIconSets,
454
+ getTailwind: () => getTailwind,
455
+ getUrlInfo: () => getUrlInfo,
456
+ getValueByPath: () => getValueByPath,
457
+ goBack: () => goBack,
458
+ goForward: () => goForward,
459
+ hasClass: () => hasClass,
460
+ hasDependencyOverrides: () => hasDependencyOverrides,
461
+ hasOverrides: () => hasOverrides,
462
+ hasTemplateSyntax: () => hasTemplateSyntax,
463
+ initServlyTailwind: () => initServlyTailwind,
464
+ injectTailwind: () => injectTailwind,
465
+ invalidateCache: () => invalidateCache,
466
+ isComponentAvailable: () => isComponentAvailable,
467
+ isIconCdnEnabled: () => isIconCdnEnabled,
468
+ isIconRegistered: () => isIconRegistered,
469
+ isIconSetSupported: () => isIconSetSupported,
470
+ isTailwindLoaded: () => isTailwindLoaded,
471
+ isValidSpecifier: () => isValidSpecifier,
472
+ navigateTo: () => navigateTo,
473
+ parseVersion: () => parseVersion,
474
+ prefetchComponents: () => prefetchComponents,
475
+ preloadIcons: () => preloadIcons,
476
+ processStyles: () => processStyles,
477
+ registerIcon: () => registerIcon,
478
+ registerIcons: () => registerIcons,
479
+ removeClass: () => removeClass,
480
+ removeCustomStyles: () => removeCustomStyles,
481
+ removeLocalStorage: () => removeLocalStorage,
482
+ removeSessionStorage: () => removeSessionStorage,
483
+ removeTailwind: () => removeTailwind,
484
+ render: () => render,
485
+ renderDynamicList: () => renderDynamicList,
486
+ renderIcon: () => renderIcon,
487
+ renderInShadow: () => renderInShadow,
488
+ renderNode: () => renderNode,
489
+ resetAnalytics: () => resetAnalytics,
490
+ resetEventSystem: () => resetEventSystem,
491
+ resetLongTaskObserver: () => resetLongTaskObserver,
492
+ resetMemorySampler: () => resetMemorySampler,
493
+ resetOverrideSystem: () => resetOverrideSystem,
494
+ resetSessionManager: () => resetSessionManager,
495
+ resolveBindingPath: () => resolveBindingPath,
496
+ resolveTemplate: () => resolveTemplate,
497
+ resolveTemplateValue: () => resolveTemplateValue,
498
+ resolveTemplatesDeep: () => resolveTemplatesDeep,
499
+ resolveVersion: () => resolveVersion,
500
+ runAllTests: () => runAllTests,
501
+ runTestCase: () => runTestCase,
502
+ satisfiesVersion: () => satisfiesVersion,
503
+ setIconCdnEnabled: () => setIconCdnEnabled,
504
+ setInCache: () => setInCache,
505
+ setLocalStorage: () => setLocalStorage,
506
+ setRegistryUrl: () => setRegistryUrl,
507
+ setSessionStorage: () => setSessionStorage,
508
+ setValueByPath: () => setValueByPath,
509
+ toDomEventName: () => toDomEventName,
510
+ toReactEventName: () => toReactEventName,
511
+ toggleClass: () => toggleClass,
512
+ updateStyles: () => updateStyles,
513
+ updateTailwindConfig: () => updateTailwindConfig,
514
+ validateAssertion: () => validateAssertion,
515
+ validateProps: () => validateProps
516
+ });
517
+ module.exports = __toCommonJS(index_exports);
20
518
 
21
- // src/analyticsTypes.ts
519
+ // packages/runtime-core/src/analyticsTypes.ts
22
520
  var DEFAULT_ANALYTICS_CONFIG = {
23
521
  enabled: true,
24
522
  endpoint: "/api/v1/analytics/events",
@@ -36,7 +534,7 @@ var MAX_RETRY_ATTEMPTS = 3;
36
534
  var SESSION_TIMEOUT_MS = 30 * 60 * 1e3;
37
535
  var SDK_VERSION = "1.0.0";
38
536
 
39
- // src/sessionManager.ts
537
+ // packages/runtime-core/src/sessionManager.ts
40
538
  var SESSION_STORAGE_KEY = "servly_analytics_session";
41
539
  function generateUUID() {
42
540
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
@@ -98,8 +596,8 @@ function isSessionExpired(session) {
98
596
  return now - session.lastActivityAt > SESSION_TIMEOUT_MS;
99
597
  }
100
598
  var SessionManager = class {
599
+ session = null;
101
600
  constructor() {
102
- this.session = null;
103
601
  this.initialize();
104
602
  }
105
603
  /**
@@ -179,13 +677,15 @@ function resetSessionManager() {
179
677
  sessionManagerInstance = null;
180
678
  }
181
679
 
182
- // src/analytics.ts
680
+ // packages/runtime-core/src/analytics.ts
183
681
  var AnalyticsCollector = class {
682
+ config;
683
+ eventQueue = [];
684
+ flushTimer = null;
685
+ isEnabled;
686
+ isFlushing = false;
687
+ retryDelay = 1e3;
184
688
  constructor(config) {
185
- this.eventQueue = [];
186
- this.flushTimer = null;
187
- this.isFlushing = false;
188
- this.retryDelay = 1e3;
189
689
  this.config = { ...DEFAULT_ANALYTICS_CONFIG, ...config };
190
690
  this.isEnabled = this.config.enabled;
191
691
  this.startFlushTimer();
@@ -528,7 +1028,7 @@ var analytics = {
528
1028
  enable: () => getAnalytics().enable()
529
1029
  };
530
1030
 
531
- // src/bindings.ts
1031
+ // packages/runtime-core/src/bindings.ts
532
1032
  var BINDING_SOURCES = [
533
1033
  "props",
534
1034
  "state",
@@ -912,7 +1412,7 @@ function extractBindingKeys(template) {
912
1412
  return Array.from(keys);
913
1413
  }
914
1414
 
915
- // src/styles.ts
1415
+ // packages/runtime-core/src/styles.ts
916
1416
  var UNITLESS_PROPERTIES = /* @__PURE__ */ new Set([
917
1417
  "animationIterationCount",
918
1418
  "borderImageOutset",
@@ -1086,8 +1586,9 @@ function updateStyles(element, oldStyles, newStyles) {
1086
1586
  }
1087
1587
  }
1088
1588
 
1089
- // src/memorySampler.ts
1589
+ // packages/runtime-core/src/memorySampler.ts
1090
1590
  var MemorySampler = class {
1591
+ isSupported;
1091
1592
  constructor() {
1092
1593
  this.isSupported = this.checkSupport();
1093
1594
  }
@@ -1147,12 +1648,13 @@ function resetMemorySampler() {
1147
1648
  memorySamplerInstance = null;
1148
1649
  }
1149
1650
 
1150
- // src/longTaskObserver.ts
1651
+ // packages/runtime-core/src/longTaskObserver.ts
1151
1652
  var LongTaskObserver = class {
1653
+ observer = null;
1654
+ longTaskCount = 0;
1655
+ isSupported;
1656
+ isObserving = false;
1152
1657
  constructor() {
1153
- this.observer = null;
1154
- this.longTaskCount = 0;
1155
- this.isObserving = false;
1156
1658
  this.isSupported = this.checkSupport();
1157
1659
  }
1158
1660
  /**
@@ -1242,11 +1744,12 @@ function resetLongTaskObserver() {
1242
1744
  longTaskObserverInstance = null;
1243
1745
  }
1244
1746
 
1245
- // src/stateManager.ts
1747
+ // packages/runtime-core/src/stateManager.ts
1246
1748
  var StateManager = class {
1749
+ state = {};
1750
+ listeners = /* @__PURE__ */ new Set();
1751
+ config;
1247
1752
  constructor(config = {}) {
1248
- this.state = {};
1249
- this.listeners = /* @__PURE__ */ new Set();
1250
1753
  this.config = config;
1251
1754
  this.state = config.initialState || {};
1252
1755
  if (config.persistToLocalStorage && typeof localStorage !== "undefined") {
@@ -1632,7 +2135,7 @@ function getUrlInfo() {
1632
2135
  };
1633
2136
  }
1634
2137
 
1635
- // src/eventSystem.ts
2138
+ // packages/runtime-core/src/eventSystem.ts
1636
2139
  var builtInPlugins = {
1637
2140
  /**
1638
2141
  * Set state value
@@ -1898,9 +2401,11 @@ var builtInPlugins = {
1898
2401
  }
1899
2402
  };
1900
2403
  var EventSystem = class {
2404
+ config;
2405
+ pluginExecutors;
2406
+ debounceTimers = /* @__PURE__ */ new Map();
2407
+ throttleTimers = /* @__PURE__ */ new Map();
1901
2408
  constructor(config = {}) {
1902
- this.debounceTimers = /* @__PURE__ */ new Map();
1903
- this.throttleTimers = /* @__PURE__ */ new Map();
1904
2409
  this.config = config;
1905
2410
  this.pluginExecutors = {
1906
2411
  ...builtInPlugins,
@@ -2070,11 +2575,12 @@ function resetEventSystem() {
2070
2575
  }
2071
2576
  }
2072
2577
 
2073
- // src/overrides.ts
2578
+ // packages/runtime-core/src/overrides.ts
2074
2579
  var OverrideSystem = class {
2580
+ config;
2581
+ elementStates = /* @__PURE__ */ new Map();
2582
+ watchIntervals = /* @__PURE__ */ new Map();
2075
2583
  constructor(config = {}) {
2076
- this.elementStates = /* @__PURE__ */ new Map();
2077
- this.watchIntervals = /* @__PURE__ */ new Map();
2078
2584
  this.config = config;
2079
2585
  }
2080
2586
  /**
@@ -2291,7 +2797,317 @@ function resetOverrideSystem() {
2291
2797
  }
2292
2798
  }
2293
2799
 
2294
- // src/renderer.ts
2800
+ // packages/runtime-core/src/icons.ts
2801
+ var cdnEnabled = false;
2802
+ function setIconCdnEnabled(enabled) {
2803
+ cdnEnabled = enabled;
2804
+ }
2805
+ function isIconCdnEnabled() {
2806
+ return cdnEnabled;
2807
+ }
2808
+ var ICONIFY_COLLECTIONS = {
2809
+ Ai: "ant-design",
2810
+ Bi: "bi",
2811
+ Bs: "bi",
2812
+ Bx: "bx",
2813
+ Ci: "circum",
2814
+ Cg: "gg",
2815
+ Di: "devicon",
2816
+ Fi: "feather",
2817
+ Fc: "flat-color-icons",
2818
+ Fa: "fa-solid",
2819
+ Fa6: "fa6-solid",
2820
+ Gi: "game-icons",
2821
+ Go: "octicon",
2822
+ Gr: "grommet-icons",
2823
+ Hi: "heroicons-outline",
2824
+ Hi2: "heroicons",
2825
+ Im: "icomoon-free",
2826
+ Io: "ion",
2827
+ Io5: "ion",
2828
+ Lu: "lucide",
2829
+ Md: "ic",
2830
+ Pi: "ph",
2831
+ Ri: "ri",
2832
+ Rx: "radix-icons",
2833
+ Si: "simple-icons",
2834
+ Sl: "simple-line-icons",
2835
+ Tb: "tabler",
2836
+ Tfi: "themify",
2837
+ Vsc: "codicon",
2838
+ Wi: "wi"
2839
+ };
2840
+ var ICON_SET_STYLES = {
2841
+ Fi: { stroke: true },
2842
+ Lu: { stroke: true },
2843
+ Hi: { stroke: true },
2844
+ Hi2: { stroke: true },
2845
+ Tb: { stroke: true }
2846
+ };
2847
+ var iconCache = /* @__PURE__ */ new Map();
2848
+ var pendingFetches = /* @__PURE__ */ new Map();
2849
+ var registeredIcons = /* @__PURE__ */ new Map();
2850
+ function registerIcon(set, name, data) {
2851
+ const key = `${set}:${name}`;
2852
+ registeredIcons.set(key, data);
2853
+ iconCache.set(key, data);
2854
+ }
2855
+ function registerIcons(icons) {
2856
+ for (const [set, setIcons] of Object.entries(icons)) {
2857
+ for (const [name, data] of Object.entries(setIcons)) {
2858
+ registerIcon(set, name, data);
2859
+ }
2860
+ }
2861
+ }
2862
+ function isIconRegistered(icon) {
2863
+ const key = `${icon.set}:${icon.name}`;
2864
+ return registeredIcons.has(key);
2865
+ }
2866
+ function getRegisteredIconKeys() {
2867
+ return Array.from(registeredIcons.keys());
2868
+ }
2869
+ function toKebabCase(str) {
2870
+ return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase();
2871
+ }
2872
+ function getIconifyName(name, set) {
2873
+ const prefixLength = set.length;
2874
+ let baseName = name;
2875
+ if (name.startsWith(set)) {
2876
+ baseName = name.slice(prefixLength);
2877
+ }
2878
+ let kebabName = toKebabCase(baseName);
2879
+ switch (set) {
2880
+ case "Md":
2881
+ if (baseName.startsWith("Outline")) {
2882
+ kebabName = toKebabCase(baseName.slice(7)) + "-outline";
2883
+ }
2884
+ kebabName = "baseline-" + kebabName;
2885
+ break;
2886
+ case "Hi2":
2887
+ if (baseName.startsWith("Outline")) {
2888
+ kebabName = toKebabCase(baseName.slice(7));
2889
+ } else if (baseName.startsWith("Solid")) {
2890
+ kebabName = toKebabCase(baseName.slice(5)) + "-solid";
2891
+ }
2892
+ break;
2893
+ case "Io":
2894
+ case "Io5":
2895
+ if (baseName.startsWith("Ios")) {
2896
+ kebabName = toKebabCase(baseName.slice(3));
2897
+ } else if (baseName.startsWith("Md")) {
2898
+ kebabName = toKebabCase(baseName.slice(2));
2899
+ }
2900
+ break;
2901
+ case "Pi":
2902
+ if (baseName.endsWith("Bold")) {
2903
+ kebabName = toKebabCase(baseName.slice(0, -4)) + "-bold";
2904
+ } else if (baseName.endsWith("Fill")) {
2905
+ kebabName = toKebabCase(baseName.slice(0, -4)) + "-fill";
2906
+ } else if (baseName.endsWith("Light")) {
2907
+ kebabName = toKebabCase(baseName.slice(0, -5)) + "-light";
2908
+ } else if (baseName.endsWith("Thin")) {
2909
+ kebabName = toKebabCase(baseName.slice(0, -4)) + "-thin";
2910
+ } else if (baseName.endsWith("Duotone")) {
2911
+ kebabName = toKebabCase(baseName.slice(0, -7)) + "-duotone";
2912
+ }
2913
+ break;
2914
+ }
2915
+ return kebabName;
2916
+ }
2917
+ async function fetchIconFromIconify(set, name) {
2918
+ if (!cdnEnabled) {
2919
+ return null;
2920
+ }
2921
+ const collection = ICONIFY_COLLECTIONS[set];
2922
+ if (!collection) {
2923
+ return null;
2924
+ }
2925
+ const iconName = getIconifyName(name, set);
2926
+ try {
2927
+ const url = `https://api.iconify.design/${collection}/${iconName}.svg`;
2928
+ const response = await fetch(url);
2929
+ if (!response.ok) {
2930
+ const altNames = [
2931
+ iconName.replace(/-outline$/, ""),
2932
+ iconName.replace(/-solid$/, ""),
2933
+ iconName.replace(/-fill$/, ""),
2934
+ iconName.replace(/^baseline-/, "")
2935
+ ].filter((alt) => alt !== iconName);
2936
+ for (const altName of altNames) {
2937
+ const altUrl = `https://api.iconify.design/${collection}/${altName}.svg`;
2938
+ const altResponse = await fetch(altUrl);
2939
+ if (altResponse.ok) {
2940
+ return parseSvgResponse(await altResponse.text());
2941
+ }
2942
+ }
2943
+ return null;
2944
+ }
2945
+ return parseSvgResponse(await response.text());
2946
+ } catch {
2947
+ return null;
2948
+ }
2949
+ }
2950
+ function parseSvgResponse(svgText) {
2951
+ try {
2952
+ const parser = new DOMParser();
2953
+ const doc = parser.parseFromString(svgText, "image/svg+xml");
2954
+ const svg = doc.querySelector("svg");
2955
+ if (!svg) {
2956
+ return null;
2957
+ }
2958
+ const viewBox = svg.getAttribute("viewBox");
2959
+ const width = parseInt(svg.getAttribute("width") || "24", 10);
2960
+ const height = parseInt(svg.getAttribute("height") || "24", 10);
2961
+ const body = svg.innerHTML;
2962
+ return {
2963
+ body,
2964
+ width,
2965
+ height,
2966
+ viewBox: viewBox || `0 0 ${width} ${height}`
2967
+ };
2968
+ } catch {
2969
+ return null;
2970
+ }
2971
+ }
2972
+ async function getIconData(icon) {
2973
+ const key = `${icon.set}:${icon.name}`;
2974
+ if (iconCache.has(key)) {
2975
+ return iconCache.get(key);
2976
+ }
2977
+ if (pendingFetches.has(key)) {
2978
+ return pendingFetches.get(key);
2979
+ }
2980
+ if (!cdnEnabled) {
2981
+ return null;
2982
+ }
2983
+ const fetchPromise = fetchIconFromIconify(icon.set, icon.name);
2984
+ pendingFetches.set(key, fetchPromise);
2985
+ const data = await fetchPromise;
2986
+ pendingFetches.delete(key);
2987
+ if (data) {
2988
+ iconCache.set(key, data);
2989
+ }
2990
+ return data;
2991
+ }
2992
+ function getIconDataSync(icon) {
2993
+ const key = `${icon.set}:${icon.name}`;
2994
+ return iconCache.get(key) || null;
2995
+ }
2996
+ function createIconSVG(icon, data, size = 24, color = "currentColor") {
2997
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
2998
+ svg.setAttribute("width", String(size));
2999
+ svg.setAttribute("height", String(size));
3000
+ svg.setAttribute("viewBox", data.viewBox || "0 0 24 24");
3001
+ svg.setAttribute("data-icon-name", icon.name);
3002
+ svg.setAttribute("data-icon-set", icon.set);
3003
+ svg.setAttribute("class", `servly-icon servly-icon-${icon.set.toLowerCase()}`);
3004
+ const style = ICON_SET_STYLES[icon.set];
3005
+ if (style?.stroke) {
3006
+ svg.setAttribute("fill", "none");
3007
+ svg.setAttribute("stroke", color);
3008
+ svg.setAttribute("stroke-width", "2");
3009
+ svg.setAttribute("stroke-linecap", "round");
3010
+ svg.setAttribute("stroke-linejoin", "round");
3011
+ } else {
3012
+ svg.setAttribute("fill", color);
3013
+ }
3014
+ svg.innerHTML = data.body;
3015
+ const paths = svg.querySelectorAll("path, circle, rect, polygon, line, polyline");
3016
+ paths.forEach((el) => {
3017
+ if (!el.getAttribute("fill") || el.getAttribute("fill") === "currentColor") {
3018
+ if (style?.stroke) {
3019
+ el.setAttribute("stroke", color);
3020
+ } else {
3021
+ el.setAttribute("fill", color);
3022
+ }
3023
+ }
3024
+ });
3025
+ return svg;
3026
+ }
3027
+ function createPlaceholderIcon(icon, size = 24, color = "currentColor") {
3028
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
3029
+ svg.setAttribute("width", String(size));
3030
+ svg.setAttribute("height", String(size));
3031
+ svg.setAttribute("viewBox", "0 0 24 24");
3032
+ svg.setAttribute("fill", "none");
3033
+ svg.setAttribute("stroke", color);
3034
+ svg.setAttribute("stroke-width", "2");
3035
+ svg.setAttribute("stroke-linecap", "round");
3036
+ svg.setAttribute("stroke-linejoin", "round");
3037
+ svg.setAttribute("data-icon-name", icon.name);
3038
+ svg.setAttribute("data-icon-set", icon.set);
3039
+ svg.setAttribute("data-icon-missing", "true");
3040
+ svg.setAttribute("class", "servly-icon servly-icon-placeholder");
3041
+ const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
3042
+ circle.setAttribute("cx", "12");
3043
+ circle.setAttribute("cy", "12");
3044
+ circle.setAttribute("r", "10");
3045
+ const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
3046
+ path.setAttribute("d", "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3");
3047
+ const dot = document.createElementNS("http://www.w3.org/2000/svg", "line");
3048
+ dot.setAttribute("x1", "12");
3049
+ dot.setAttribute("y1", "17");
3050
+ dot.setAttribute("x2", "12.01");
3051
+ dot.setAttribute("y2", "17");
3052
+ svg.appendChild(circle);
3053
+ svg.appendChild(path);
3054
+ svg.appendChild(dot);
3055
+ return svg;
3056
+ }
3057
+ function renderIcon(container, icon, size = 24, color = "currentColor") {
3058
+ const cachedData = getIconDataSync(icon);
3059
+ if (cachedData) {
3060
+ const svg = createIconSVG(icon, cachedData, size, color);
3061
+ container.innerHTML = "";
3062
+ container.appendChild(svg);
3063
+ return;
3064
+ }
3065
+ if (!cdnEnabled) {
3066
+ const placeholder2 = createPlaceholderIcon(icon, size, color);
3067
+ container.innerHTML = "";
3068
+ container.appendChild(placeholder2);
3069
+ console.warn(
3070
+ `[Icons] Icon not bundled: ${icon.set}:${icon.name}. Use registerIcon() to bundle it, or enable CDN with setIconCdnEnabled(true).`
3071
+ );
3072
+ return;
3073
+ }
3074
+ const placeholder = createPlaceholderIcon(icon, size, color);
3075
+ placeholder.setAttribute("data-icon-loading", "true");
3076
+ placeholder.removeAttribute("data-icon-missing");
3077
+ container.innerHTML = "";
3078
+ container.appendChild(placeholder);
3079
+ getIconData(icon).then((data) => {
3080
+ if (data) {
3081
+ const svg = createIconSVG(icon, data, size, color);
3082
+ container.innerHTML = "";
3083
+ container.appendChild(svg);
3084
+ } else {
3085
+ placeholder.setAttribute("data-icon-missing", "true");
3086
+ placeholder.removeAttribute("data-icon-loading");
3087
+ }
3088
+ });
3089
+ }
3090
+ async function preloadIcons(icons) {
3091
+ await Promise.all(icons.map((icon) => getIconData(icon)));
3092
+ }
3093
+ function clearIconCache() {
3094
+ iconCache.clear();
3095
+ pendingFetches.clear();
3096
+ registeredIcons.forEach((data, key) => {
3097
+ iconCache.set(key, data);
3098
+ });
3099
+ }
3100
+ function isIconSetSupported(set) {
3101
+ return set in ICONIFY_COLLECTIONS;
3102
+ }
3103
+ function getSupportedIconSets() {
3104
+ return Object.keys(ICONIFY_COLLECTIONS);
3105
+ }
3106
+ function getIconifyCollection(set) {
3107
+ return ICONIFY_COLLECTIONS[set];
3108
+ }
3109
+
3110
+ // packages/runtime-core/src/renderer.ts
2295
3111
  var COMPONENT_TO_TAG = {
2296
3112
  container: "div",
2297
3113
  text: "span",
@@ -2673,6 +3489,9 @@ function renderElement(element, tree, context, eventHandlers, elementStates, sta
2673
3489
  if (element.componentId === "slot") {
2674
3490
  return renderSlotElement(element, tree, context, eventHandlers, elementStates, state, isRootElement);
2675
3491
  }
3492
+ if (element.componentId === "icon") {
3493
+ return renderIconElement(element, context, eventHandlers, elementStates, state, isRootElement);
3494
+ }
2676
3495
  const elementState = createElement(element, context, eventHandlers, isRootElement, state);
2677
3496
  elementStates.set(element.i, elementState);
2678
3497
  const config = element.configuration;
@@ -2690,6 +3509,40 @@ function renderElement(element, tree, context, eventHandlers, elementStates, sta
2690
3509
  }
2691
3510
  return elementState.domElement;
2692
3511
  }
3512
+ function renderIconElement(element, context, eventHandlers, elementStates, state, isRootElement) {
3513
+ const config = element.configuration || {};
3514
+ const icon = config.icon;
3515
+ const iconColor = config.iconColor || "currentColor";
3516
+ const iconSize = config.iconSize || 24;
3517
+ const wrapper = document.createElement("div");
3518
+ wrapper.setAttribute("data-servly-id", element.i);
3519
+ wrapper.className = "pointer-events-none";
3520
+ const styles = buildElementStyles(element, context);
3521
+ applyStyles(wrapper, styles);
3522
+ const className = buildClassName(element, context);
3523
+ if (className) {
3524
+ wrapper.className = `pointer-events-none ${className}`;
3525
+ }
3526
+ if (state.iconRenderer && icon) {
3527
+ const iconElement = state.iconRenderer(icon, iconSize, iconColor, "");
3528
+ if (iconElement) {
3529
+ wrapper.appendChild(iconElement);
3530
+ }
3531
+ } else if (icon) {
3532
+ renderIcon(wrapper, icon, iconSize, iconColor);
3533
+ }
3534
+ const elementState = {
3535
+ element,
3536
+ domElement: wrapper,
3537
+ styles,
3538
+ className: wrapper.className,
3539
+ textContent: "",
3540
+ eventListeners: /* @__PURE__ */ new Map()
3541
+ };
3542
+ elementStates.set(element.i, elementState);
3543
+ attachEventHandlers(wrapper, element, eventHandlers, context, elementState, isRootElement, state);
3544
+ return wrapper;
3545
+ }
2693
3546
  function renderComponentViewElement(element, tree, context, eventHandlers, elementStates, state, isRootElement) {
2694
3547
  const componentViewId = `${element.componentId}-${element.i}`;
2695
3548
  if (globalRenderingStack.has(componentViewId)) {
@@ -2709,7 +3562,15 @@ function renderComponentViewElement(element, tree, context, eventHandlers, eleme
2709
3562
  viewLayout = component.layout;
2710
3563
  }
2711
3564
  }
3565
+ if (!viewLayout && state.views === void 0 && state.viewsArray) {
3566
+ const viewsArray = state.viewsArray;
3567
+ const found = viewsArray.find((v) => v.id === element.componentId);
3568
+ if (found) {
3569
+ viewLayout = found.layout;
3570
+ }
3571
+ }
2712
3572
  if (!viewLayout) {
3573
+ console.warn(`[Servly] Component not found: ${element.componentId}. Available in views: ${state.views ? Array.from(state.views.keys()).join(", ") : "none"}. Registry has: ${state.componentRegistry?.has(element.componentId) ? "yes" : "no"}`);
2713
3574
  const placeholder = document.createElement("div");
2714
3575
  placeholder.className = "border-2 border-yellow-500 border-dashed p-4 bg-yellow-50";
2715
3576
  placeholder.innerHTML = `<p class="text-yellow-600 text-sm">Component not found: ${element.componentId}</p>`;
@@ -2823,14 +3684,26 @@ function render(options) {
2823
3684
  eventHandlers,
2824
3685
  componentRegistry,
2825
3686
  onDependencyNeeded,
2826
- views,
3687
+ views: viewsInput,
2827
3688
  enableStateManager,
2828
3689
  initialState,
2829
3690
  onStateChange,
2830
3691
  pluginExecutors,
2831
3692
  onNavigate,
2832
- onApiCall
3693
+ onApiCall,
3694
+ iconRenderer
2833
3695
  } = options;
3696
+ let views;
3697
+ if (viewsInput instanceof Map) {
3698
+ views = viewsInput;
3699
+ } else if (Array.isArray(viewsInput)) {
3700
+ views = /* @__PURE__ */ new Map();
3701
+ for (const view of viewsInput) {
3702
+ if (view && view.id) {
3703
+ views.set(view.id, view);
3704
+ }
3705
+ }
3706
+ }
2834
3707
  const startTime = performance.now();
2835
3708
  const memorySampler = getMemorySampler();
2836
3709
  const longTaskObserver = getLongTaskObserver();
@@ -2878,7 +3751,8 @@ function render(options) {
2878
3751
  eventSystem,
2879
3752
  stateManager,
2880
3753
  overrideSystem,
2881
- enableOverrides: hasAnyOverrides
3754
+ enableOverrides: hasAnyOverrides,
3755
+ iconRenderer
2882
3756
  };
2883
3757
  container.innerHTML = "";
2884
3758
  if (rootElements.length === 0) {
@@ -3155,7 +4029,7 @@ async function createServlyRenderer(options) {
3155
4029
  container = containerOption;
3156
4030
  }
3157
4031
  if (shouldInjectTailwind) {
3158
- const { initServlyTailwind: initServlyTailwind2 } = await import("./tailwind-CGAHPC3O.js");
4032
+ const { initServlyTailwind: initServlyTailwind2 } = await Promise.resolve().then(() => (init_tailwind(), tailwind_exports));
3159
4033
  await initServlyTailwind2(tailwindConfig);
3160
4034
  }
3161
4035
  const activeRenders = [];
@@ -3253,7 +4127,7 @@ function collectAllViewDependencies(views, startViewId) {
3253
4127
  return collected;
3254
4128
  }
3255
4129
 
3256
- // src/cache.ts
4130
+ // packages/runtime-core/src/cache.ts
3257
4131
  var DEFAULT_CACHE_CONFIG = {
3258
4132
  maxEntries: 50,
3259
4133
  ttl: 5 * 60 * 1e3,
@@ -3497,7 +4371,8 @@ function invalidateCache(id, version, config = DEFAULT_CACHE_CONFIG) {
3497
4371
  }
3498
4372
  }
3499
4373
 
3500
- // src/fetcher.ts
4374
+ // packages/runtime-core/src/fetcher.ts
4375
+ init_registry();
3501
4376
  var DEFAULT_RETRY_CONFIG = {
3502
4377
  maxRetries: 3,
3503
4378
  initialDelay: 1e3,
@@ -3727,7 +4602,7 @@ async function fetchComponent(id, options = {}) {
3727
4602
  async function fetchComponentWithDependencies(id, options = {}) {
3728
4603
  const result = await fetchComponent(id, { ...options, includeBundle: true });
3729
4604
  if (result.pendingDependencies && result.pendingDependencies.length > 0) {
3730
- const { createRegistry: createRegistry2 } = await import("./registry-GCCVK65D.js");
4605
+ const { createRegistry: createRegistry2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
3731
4606
  const registry = result.registry || createRegistry2();
3732
4607
  await Promise.all(
3733
4608
  result.pendingDependencies.map(async (dep) => {
@@ -3833,7 +4708,7 @@ async function getDependencyTree(id, options = {}) {
3833
4708
  return data.data;
3834
4709
  }
3835
4710
 
3836
- // src/version.ts
4711
+ // packages/runtime-core/src/version.ts
3837
4712
  function parseVersion(version) {
3838
4713
  const match = version.match(/^(\d+)\.(\d+)\.(\d+)$/);
3839
4714
  if (!match) return null;
@@ -3945,7 +4820,7 @@ function formatVersion(version) {
3945
4820
  return `v${parsed.major}.${parsed.minor}.${parsed.patch}`;
3946
4821
  }
3947
4822
 
3948
- // src/testRunner.ts
4823
+ // packages/runtime-core/src/testRunner.ts
3949
4824
  function runTestCase(elements, testCase, container) {
3950
4825
  const startTime = performance.now();
3951
4826
  const assertionResults = [];
@@ -4199,7 +5074,148 @@ function getSampleValue(def) {
4199
5074
  return def.defaultValue;
4200
5075
  }
4201
5076
  }
4202
- export {
5077
+
5078
+ // packages/runtime-core/src/index.ts
5079
+ init_registry();
5080
+ init_tailwind();
5081
+
5082
+ // packages/runtime-core/src/iconExtractor.ts
5083
+ var REACT_ICONS_PACKAGES = {
5084
+ Ai: "react-icons/ai",
5085
+ Bi: "react-icons/bi",
5086
+ Bs: "react-icons/bs",
5087
+ Cg: "react-icons/cg",
5088
+ Di: "react-icons/di",
5089
+ Fa: "react-icons/fa",
5090
+ Fa6: "react-icons/fa6",
5091
+ Fc: "react-icons/fc",
5092
+ Fi: "react-icons/fi",
5093
+ Gi: "react-icons/gi",
5094
+ Go: "react-icons/go",
5095
+ Gr: "react-icons/gr",
5096
+ Hi: "react-icons/hi",
5097
+ Hi2: "react-icons/hi2",
5098
+ Im: "react-icons/im",
5099
+ Io: "react-icons/io",
5100
+ Io5: "react-icons/io5",
5101
+ Lu: "react-icons/lu",
5102
+ Md: "react-icons/md",
5103
+ Pi: "react-icons/pi",
5104
+ Ri: "react-icons/ri",
5105
+ Rx: "react-icons/rx",
5106
+ Si: "react-icons/si",
5107
+ Sl: "react-icons/sl",
5108
+ Tb: "react-icons/tb",
5109
+ Tfi: "react-icons/tfi",
5110
+ Vsc: "react-icons/vsc",
5111
+ Wi: "react-icons/wi"
5112
+ };
5113
+ async function extractIconFromReactIcons(iconName, iconSet) {
5114
+ const packagePath = REACT_ICONS_PACKAGES[iconSet];
5115
+ if (!packagePath) {
5116
+ console.warn(`Unknown icon set: ${iconSet}`);
5117
+ return null;
5118
+ }
5119
+ try {
5120
+ const iconModule = await import(packagePath);
5121
+ const IconComponent = iconModule[iconName];
5122
+ if (!IconComponent) {
5123
+ console.warn(`Icon not found: ${iconName} in ${packagePath}`);
5124
+ return null;
5125
+ }
5126
+ const React = await import("react");
5127
+ const { renderToStaticMarkup } = await import("react-dom/server");
5128
+ const svgString = renderToStaticMarkup(React.createElement(IconComponent, { size: 24 }));
5129
+ return parseSvgString(svgString);
5130
+ } catch (error) {
5131
+ console.error(`Failed to extract icon ${iconSet}:${iconName}:`, error);
5132
+ return null;
5133
+ }
5134
+ }
5135
+ function parseSvgString(svgString) {
5136
+ const viewBoxMatch = svgString.match(/viewBox="([^"]+)"/);
5137
+ const viewBox = viewBoxMatch ? viewBoxMatch[1] : "0 0 24 24";
5138
+ const widthMatch = svgString.match(/width="(\d+)"/);
5139
+ const heightMatch = svgString.match(/height="(\d+)"/);
5140
+ const width = widthMatch ? parseInt(widthMatch[1], 10) : 24;
5141
+ const height = heightMatch ? parseInt(heightMatch[1], 10) : 24;
5142
+ const bodyMatch = svgString.match(/<svg[^>]*>([\s\S]*)<\/svg>/);
5143
+ const body = bodyMatch ? bodyMatch[1].trim() : "";
5144
+ if (!body) {
5145
+ return null;
5146
+ }
5147
+ return {
5148
+ body,
5149
+ viewBox,
5150
+ width,
5151
+ height
5152
+ };
5153
+ }
5154
+ function findIconsInLayout(elements) {
5155
+ const icons = [];
5156
+ const seen = /* @__PURE__ */ new Set();
5157
+ for (const element of elements) {
5158
+ if (element.componentId === "icon" && element.configuration?.icon) {
5159
+ const icon = element.configuration.icon;
5160
+ const key = `${icon.set}:${icon.name}`;
5161
+ if (!seen.has(key)) {
5162
+ seen.add(key);
5163
+ icons.push({
5164
+ name: icon.name,
5165
+ set: icon.set,
5166
+ setName: icon.setName
5167
+ });
5168
+ }
5169
+ }
5170
+ }
5171
+ return icons;
5172
+ }
5173
+ async function extractIconsForLayout(elements) {
5174
+ const icons = findIconsInLayout(elements);
5175
+ const result = {};
5176
+ for (const icon of icons) {
5177
+ const data = await extractIconFromReactIcons(icon.name, icon.set);
5178
+ if (data) {
5179
+ if (!result[icon.set]) {
5180
+ result[icon.set] = {};
5181
+ }
5182
+ result[icon.set][icon.name] = data;
5183
+ }
5184
+ }
5185
+ return result;
5186
+ }
5187
+ function generateIconBundle(icons) {
5188
+ const lines = [
5189
+ "// Auto-generated icon bundle",
5190
+ "// Do not edit manually",
5191
+ "",
5192
+ "import { registerIcons, type IconData } from '@servlyadmin/runtime-core';",
5193
+ "",
5194
+ "const BUNDLED_ICONS: Record<string, Record<string, IconData>> = {"
5195
+ ];
5196
+ for (const [set, setIcons] of Object.entries(icons)) {
5197
+ lines.push(` ${set}: {`);
5198
+ for (const [name, data] of Object.entries(setIcons)) {
5199
+ const escapedBody = data.body.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n");
5200
+ lines.push(` ${name}: {`);
5201
+ lines.push(` body: '${escapedBody}',`);
5202
+ lines.push(` viewBox: '${data.viewBox}',`);
5203
+ if (data.width) lines.push(` width: ${data.width},`);
5204
+ if (data.height) lines.push(` height: ${data.height},`);
5205
+ lines.push(` },`);
5206
+ }
5207
+ lines.push(` },`);
5208
+ }
5209
+ lines.push("};");
5210
+ lines.push("");
5211
+ lines.push("// Register all bundled icons");
5212
+ lines.push("registerIcons(BUNDLED_ICONS);");
5213
+ lines.push("");
5214
+ lines.push("export { BUNDLED_ICONS };");
5215
+ return lines.join("\n");
5216
+ }
5217
+ // Annotate the CommonJS export names for ESM import in node:
5218
+ 0 && (module.exports = {
4203
5219
  AnalyticsCollector,
4204
5220
  DEFAULT_CACHE_CONFIG,
4205
5221
  DEFAULT_RETRY_CONFIG,
@@ -4222,6 +5238,7 @@ export {
4222
5238
  bumpVersion,
4223
5239
  camelToKebab,
4224
5240
  clearAllCaches,
5241
+ clearIconCache,
4225
5242
  clearLocalStorageCache,
4226
5243
  clearMemoryCache,
4227
5244
  clearStyles,
@@ -4229,6 +5246,8 @@ export {
4229
5246
  collectAllViewDependencies,
4230
5247
  compareVersions,
4231
5248
  configureAnalytics,
5249
+ createIconSVG,
5250
+ createPlaceholderIcon,
4232
5251
  createRegistry,
4233
5252
  createServlyRenderer,
4234
5253
  createViewsMap,
@@ -4238,12 +5257,16 @@ export {
4238
5257
  extractBindingKeys,
4239
5258
  extractDependencies,
4240
5259
  extractDependenciesFromCode,
5260
+ extractIconFromReactIcons,
5261
+ extractIconsForLayout,
4241
5262
  extractOverrideDependencies,
4242
5263
  extractReferencedViewIds,
4243
5264
  fetchComponent,
4244
5265
  fetchComponentWithDependencies,
5266
+ findIconsInLayout,
4245
5267
  formatStyleValue,
4246
5268
  formatVersion,
5269
+ generateIconBundle,
4247
5270
  generateTestCases,
4248
5271
  getAnalytics,
4249
5272
  getCacheKey,
@@ -4251,15 +5274,20 @@ export {
4251
5274
  getDependencyTree,
4252
5275
  getEventSystem,
4253
5276
  getFromCache,
5277
+ getIconData,
5278
+ getIconDataSync,
5279
+ getIconifyCollection,
4254
5280
  getLocalStorage,
4255
5281
  getLongTaskObserver,
4256
5282
  getMemoryCacheSize,
4257
5283
  getMemorySampler,
4258
5284
  getMountOverrides,
4259
5285
  getOverrideSystem,
5286
+ getRegisteredIconKeys,
4260
5287
  getRegistryUrl,
4261
5288
  getSessionManager,
4262
5289
  getSessionStorage,
5290
+ getSupportedIconSets,
4263
5291
  getTailwind,
4264
5292
  getUrlInfo,
4265
5293
  getValueByPath,
@@ -4273,12 +5301,18 @@ export {
4273
5301
  injectTailwind,
4274
5302
  invalidateCache,
4275
5303
  isComponentAvailable,
5304
+ isIconCdnEnabled,
5305
+ isIconRegistered,
5306
+ isIconSetSupported,
4276
5307
  isTailwindLoaded,
4277
5308
  isValidSpecifier,
4278
5309
  navigateTo,
4279
5310
  parseVersion,
4280
5311
  prefetchComponents,
5312
+ preloadIcons,
4281
5313
  processStyles,
5314
+ registerIcon,
5315
+ registerIcons,
4282
5316
  removeClass,
4283
5317
  removeCustomStyles,
4284
5318
  removeLocalStorage,
@@ -4286,6 +5320,7 @@ export {
4286
5320
  removeTailwind,
4287
5321
  render,
4288
5322
  renderDynamicList,
5323
+ renderIcon,
4289
5324
  renderInShadow,
4290
5325
  renderNode,
4291
5326
  resetAnalytics,
@@ -4302,6 +5337,7 @@ export {
4302
5337
  runAllTests,
4303
5338
  runTestCase,
4304
5339
  satisfiesVersion,
5340
+ setIconCdnEnabled,
4305
5341
  setInCache,
4306
5342
  setLocalStorage,
4307
5343
  setRegistryUrl,
@@ -4314,4 +5350,4 @@ export {
4314
5350
  updateTailwindConfig,
4315
5351
  validateAssertion,
4316
5352
  validateProps
4317
- };
5353
+ });