@servlyadmin/runtime-core 0.1.44 → 0.1.46

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/README.md CHANGED
@@ -14,10 +14,60 @@ pnpm add @servlyadmin/runtime-core
14
14
 
15
15
  ## Quick Start
16
16
 
17
+ The simplest way to render a component:
18
+
19
+ ```typescript
20
+ import { mount } from '@servlyadmin/runtime-core';
21
+
22
+ // Mount a component - that's it!
23
+ const app = await mount({
24
+ componentId: 'my-component-id',
25
+ target: '#app',
26
+ props: { title: 'Hello World' }
27
+ });
28
+
29
+ // Update props
30
+ app.update({ props: { title: 'Updated!' } });
31
+
32
+ // Cleanup
33
+ app.destroy();
34
+ ```
35
+
36
+ ### With Callbacks
37
+
38
+ ```typescript
39
+ const app = await mount({
40
+ componentId: 'my-component-id',
41
+ target: '#app',
42
+ props: { title: 'Hello' },
43
+ onReady: (result) => console.log('Mounted!', result.version),
44
+ onError: (err) => console.error('Failed:', err)
45
+ });
46
+ ```
47
+
48
+ ### With Version & Cache Control
49
+
50
+ ```typescript
51
+ const app = await mount({
52
+ componentId: 'my-component-id',
53
+ target: document.getElementById('app'),
54
+ props: { title: 'Hello' },
55
+ version: '^1.0.0',
56
+ fetchOptions: {
57
+ cacheStrategy: 'memory',
58
+ forceRefresh: true
59
+ }
60
+ });
61
+ ```
62
+
63
+ ## Low-Level API
64
+
65
+ For more control, use `fetchComponent` and `render` directly:
66
+
17
67
  ```typescript
18
68
  import { render, fetchComponent } from '@servlyadmin/runtime-core';
19
69
 
20
- // Fetch a component from the registry (uses Servly's default registry)
70
+ // Fetch a component from the registry
21
71
  const { data } = await fetchComponent('my-component-id');
22
72
 
23
73
  // Render to a container
@@ -135,6 +185,55 @@ const elements = [
135
185
 
136
186
  ## API Reference
137
187
 
188
+ ### mount(options) - Recommended
189
+
190
+ The simplest way to render a component. Handles fetching, container resolution, and rendering.
191
+
192
+ ```typescript
193
+ const app = await mount({
194
+ componentId: string, // Required: Component ID to fetch
195
+ target: string | HTMLElement, // Required: CSS selector or element
196
+ props?: Record<string, any>, // Props to pass (default: {})
197
+ state?: Record<string, any>, // Initial state (default: {})
198
+ context?: Record<string, any>, // Additional context (default: {})
199
+ version?: string, // Version specifier (default: 'latest')
200
+ eventHandlers?: Record<string, Record<string, (e: Event) => void>>,
201
+ fetchOptions?: {
202
+ cacheStrategy?: 'localStorage' | 'memory' | 'none',
203
+ forceRefresh?: boolean,
204
+ apiKey?: string,
205
+ retryConfig?: RetryConfig,
206
+ },
207
+ onReady?: (result: MountResult) => void,
208
+ onError?: (error: Error) => void,
209
+ });
210
+
211
+ // Returns MountResult
212
+ interface MountResult {
213
+ update(context: Partial<BindingContext>): void;
214
+ destroy(): void;
215
+ rootElement: HTMLElement | null;
216
+ container: HTMLElement;
217
+ data: ComponentData;
218
+ fromCache: boolean;
219
+ version: string;
220
+ }
221
+ ```
222
+
223
+ ### mountData(options)
224
+
225
+ Mount with pre-fetched data (useful for SSR or custom data sources):
226
+
227
+ ```typescript
228
+ import { mountData } from '@servlyadmin/runtime-core';
229
+
230
+ const app = mountData({
231
+ data: myComponentData, // Pre-fetched ComponentData
232
+ target: '#app',
233
+ props: { title: 'Hello' }
234
+ });
235
+ ```
236
+
138
237
  ### render(options)
139
238
 
140
239
  Renders elements to a container.
@@ -33,6 +33,7 @@ function markTailwindAsLoaded() {
33
33
  function preloadTailwind(cdnUrl, usePlayCdn) {
34
34
  if (typeof document === "undefined") return;
35
35
  if (document.querySelector("link[data-servly-tailwind-preload]")) return;
36
+ if (document.querySelector('script[src*="tailwindcss.com"]')) return;
36
37
  const url = cdnUrl || DEFAULT_TAILWIND_CDN;
37
38
  const fullUrl = usePlayCdn ? `${url}?plugins=forms,typography,aspect-ratio` : url;
38
39
  const link = document.createElement("link");
@@ -40,15 +41,18 @@ function preloadTailwind(cdnUrl, usePlayCdn) {
40
41
  link.as = "script";
41
42
  link.href = fullUrl;
42
43
  link.setAttribute("data-servly-tailwind-preload", "true");
44
+ link.setAttribute("crossorigin", "anonymous");
43
45
  if (document.head.firstChild) {
44
46
  document.head.insertBefore(link, document.head.firstChild);
45
47
  } else {
46
48
  document.head.appendChild(link);
47
49
  }
48
- const dnsPrefetch = document.createElement("link");
49
- dnsPrefetch.rel = "dns-prefetch";
50
- dnsPrefetch.href = "https://cdn.tailwindcss.com";
51
- document.head.appendChild(dnsPrefetch);
50
+ if (!document.querySelector('link[rel="dns-prefetch"][href*="tailwindcss.com"]')) {
51
+ const dnsPrefetch = document.createElement("link");
52
+ dnsPrefetch.rel = "dns-prefetch";
53
+ dnsPrefetch.href = "https://cdn.tailwindcss.com";
54
+ document.head.appendChild(dnsPrefetch);
55
+ }
52
56
  }
53
57
  function preventFOUC() {
54
58
  if (typeof document === "undefined") return;
@@ -135,7 +139,6 @@ function injectTailwind(config = {}) {
135
139
  const {
136
140
  cdnUrl = DEFAULT_TAILWIND_CDN,
137
141
  config: tailwindConfig,
138
- plugins = [],
139
142
  usePlayCdn = false,
140
143
  onReady,
141
144
  onError,
package/dist/index.cjs CHANGED
@@ -61,6 +61,7 @@ function markTailwindAsLoaded() {
61
61
  function preloadTailwind(cdnUrl, usePlayCdn) {
62
62
  if (typeof document === "undefined") return;
63
63
  if (document.querySelector("link[data-servly-tailwind-preload]")) return;
64
+ if (document.querySelector('script[src*="tailwindcss.com"]')) return;
64
65
  const url = cdnUrl || DEFAULT_TAILWIND_CDN;
65
66
  const fullUrl = usePlayCdn ? `${url}?plugins=forms,typography,aspect-ratio` : url;
66
67
  const link = document.createElement("link");
@@ -68,15 +69,18 @@ function preloadTailwind(cdnUrl, usePlayCdn) {
68
69
  link.as = "script";
69
70
  link.href = fullUrl;
70
71
  link.setAttribute("data-servly-tailwind-preload", "true");
72
+ link.setAttribute("crossorigin", "anonymous");
71
73
  if (document.head.firstChild) {
72
74
  document.head.insertBefore(link, document.head.firstChild);
73
75
  } else {
74
76
  document.head.appendChild(link);
75
77
  }
76
- const dnsPrefetch = document.createElement("link");
77
- dnsPrefetch.rel = "dns-prefetch";
78
- dnsPrefetch.href = "https://cdn.tailwindcss.com";
79
- document.head.appendChild(dnsPrefetch);
78
+ if (!document.querySelector('link[rel="dns-prefetch"][href*="tailwindcss.com"]')) {
79
+ const dnsPrefetch = document.createElement("link");
80
+ dnsPrefetch.rel = "dns-prefetch";
81
+ dnsPrefetch.href = "https://cdn.tailwindcss.com";
82
+ document.head.appendChild(dnsPrefetch);
83
+ }
80
84
  }
81
85
  function preventFOUC() {
82
86
  if (typeof document === "undefined") return;
@@ -163,7 +167,6 @@ function injectTailwind(config = {}) {
163
167
  const {
164
168
  cdnUrl = DEFAULT_TAILWIND_CDN,
165
169
  config: tailwindConfig,
166
- plugins = [],
167
170
  usePlayCdn = false,
168
171
  onReady,
169
172
  onError,
@@ -695,6 +698,7 @@ __export(index_exports, {
695
698
  camelToKebab: () => camelToKebab,
696
699
  clearAllCaches: () => clearAllCaches,
697
700
  clearIconCache: () => clearIconCache,
701
+ clearIconStorageCache: () => clearIconStorageCache,
698
702
  clearLocalStorageCache: () => clearLocalStorageCache,
699
703
  clearMemoryCache: () => clearMemoryCache,
700
704
  clearStyles: () => clearStyles,
@@ -769,6 +773,8 @@ __export(index_exports, {
769
773
  loadFont: () => loadFont,
770
774
  loadFonts: () => loadFonts,
771
775
  markElementReady: () => markElementReady,
776
+ mount: () => mount,
777
+ mountData: () => mountData,
772
778
  navigateTo: () => navigateTo,
773
779
  parseVersion: () => parseVersion,
774
780
  prefetchComponents: () => prefetchComponents,
@@ -3127,6 +3133,58 @@ function resetOverrideSystem() {
3127
3133
 
3128
3134
  // src/icons.ts
3129
3135
  var cdnEnabled = true;
3136
+ var ICON_CACHE_KEY = "servly-icon-cache";
3137
+ var ICON_CACHE_VERSION = "1";
3138
+ var localStorageLoaded = false;
3139
+ function loadIconCacheFromStorage() {
3140
+ if (localStorageLoaded) return;
3141
+ localStorageLoaded = true;
3142
+ if (typeof localStorage === "undefined") return;
3143
+ try {
3144
+ const cached = localStorage.getItem(ICON_CACHE_KEY);
3145
+ if (!cached) return;
3146
+ const parsed = JSON.parse(cached);
3147
+ if (parsed.version !== ICON_CACHE_VERSION) {
3148
+ localStorage.removeItem(ICON_CACHE_KEY);
3149
+ return;
3150
+ }
3151
+ for (const [key, data] of Object.entries(parsed.icons)) {
3152
+ if (!iconCache.has(key) && !registeredIcons.has(key)) {
3153
+ iconCache.set(key, data);
3154
+ }
3155
+ }
3156
+ } catch {
3157
+ }
3158
+ }
3159
+ function saveIconToStorage(key, data) {
3160
+ if (typeof localStorage === "undefined") return;
3161
+ try {
3162
+ const cached = localStorage.getItem(ICON_CACHE_KEY);
3163
+ let cacheData;
3164
+ if (cached) {
3165
+ cacheData = JSON.parse(cached);
3166
+ if (cacheData.version !== ICON_CACHE_VERSION) {
3167
+ cacheData = { version: ICON_CACHE_VERSION, icons: {} };
3168
+ }
3169
+ } else {
3170
+ cacheData = { version: ICON_CACHE_VERSION, icons: {} };
3171
+ }
3172
+ cacheData.icons[key] = data;
3173
+ const keys = Object.keys(cacheData.icons);
3174
+ if (keys.length > 500) {
3175
+ keys.slice(0, 100).forEach((k) => delete cacheData.icons[k]);
3176
+ }
3177
+ localStorage.setItem(ICON_CACHE_KEY, JSON.stringify(cacheData));
3178
+ } catch {
3179
+ }
3180
+ }
3181
+ function clearIconStorageCache() {
3182
+ if (typeof localStorage === "undefined") return;
3183
+ try {
3184
+ localStorage.removeItem(ICON_CACHE_KEY);
3185
+ } catch {
3186
+ }
3187
+ }
3130
3188
  function setIconCdnEnabled(enabled) {
3131
3189
  cdnEnabled = enabled;
3132
3190
  }
@@ -3299,6 +3357,7 @@ function parseSvgResponse(svgText) {
3299
3357
  }
3300
3358
  async function getIconData(icon) {
3301
3359
  const key = `${icon.set}:${icon.name}`;
3360
+ loadIconCacheFromStorage();
3302
3361
  if (iconCache.has(key)) {
3303
3362
  return iconCache.get(key);
3304
3363
  }
@@ -3314,11 +3373,13 @@ async function getIconData(icon) {
3314
3373
  pendingFetches.delete(key);
3315
3374
  if (data) {
3316
3375
  iconCache.set(key, data);
3376
+ saveIconToStorage(key, data);
3317
3377
  }
3318
3378
  return data;
3319
3379
  }
3320
3380
  function getIconDataSync(icon) {
3321
3381
  const key = `${icon.set}:${icon.name}`;
3382
+ loadIconCacheFromStorage();
3322
3383
  return iconCache.get(key) || null;
3323
3384
  }
3324
3385
  function createIconSVG(icon, data, size = 24, color = "currentColor") {
@@ -3418,12 +3479,15 @@ function renderIcon(container, icon, size = 24, color = "currentColor") {
3418
3479
  async function preloadIcons(icons) {
3419
3480
  await Promise.all(icons.map((icon) => getIconData(icon)));
3420
3481
  }
3421
- function clearIconCache() {
3482
+ function clearIconCache(clearStorage = false) {
3422
3483
  iconCache.clear();
3423
3484
  pendingFetches.clear();
3424
3485
  registeredIcons.forEach((data, key) => {
3425
3486
  iconCache.set(key, data);
3426
3487
  });
3488
+ if (clearStorage) {
3489
+ clearIconStorageCache();
3490
+ }
3427
3491
  }
3428
3492
  function isIconSetSupported(set) {
3429
3493
  return set in ICONIFY_COLLECTIONS;
@@ -4483,10 +4547,9 @@ function renderInShadow(options) {
4483
4547
  shadowRoot.insertBefore(styleEl, innerContainer);
4484
4548
  }
4485
4549
  if (shouldInjectTailwind) {
4486
- const tailwindLink = document.createElement("link");
4487
- tailwindLink.rel = "stylesheet";
4488
- tailwindLink.href = "https://cdn.tailwindcss.com";
4489
- shadowRoot.insertBefore(tailwindLink, innerContainer);
4550
+ const tailwindScript2 = document.createElement("script");
4551
+ tailwindScript2.src = "https://cdn.tailwindcss.com";
4552
+ shadowRoot.insertBefore(tailwindScript2, innerContainer);
4490
4553
  }
4491
4554
  const result = render({
4492
4555
  ...renderOptions,
@@ -5221,6 +5284,109 @@ async function getDependencyTree(id, options = {}) {
5221
5284
  return data.data;
5222
5285
  }
5223
5286
 
5287
+ // src/mount.ts
5288
+ async function mount(options) {
5289
+ const {
5290
+ componentId,
5291
+ target,
5292
+ props = {},
5293
+ state = {},
5294
+ context = {},
5295
+ version = "latest",
5296
+ eventHandlers,
5297
+ fetchOptions = {},
5298
+ onReady,
5299
+ onError
5300
+ } = options;
5301
+ try {
5302
+ const container = typeof target === "string" ? document.querySelector(target) : target;
5303
+ if (!container) {
5304
+ throw new Error(`Target container not found: ${target}`);
5305
+ }
5306
+ const fetchResult = await fetchComponentWithDependencies(componentId, {
5307
+ ...fetchOptions,
5308
+ version
5309
+ });
5310
+ const { data, fromCache, version: resolvedVersion, registry, views } = fetchResult;
5311
+ const bindingContext = {
5312
+ props,
5313
+ state,
5314
+ context
5315
+ };
5316
+ const renderResult = render({
5317
+ container,
5318
+ elements: data.layout,
5319
+ context: bindingContext,
5320
+ eventHandlers,
5321
+ componentRegistry: registry,
5322
+ views
5323
+ });
5324
+ const result = {
5325
+ update: (newContext) => {
5326
+ renderResult.update({
5327
+ props: newContext.props ?? props,
5328
+ state: newContext.state ?? state,
5329
+ context: newContext.context ?? context
5330
+ });
5331
+ },
5332
+ destroy: () => {
5333
+ renderResult.destroy();
5334
+ },
5335
+ rootElement: renderResult.rootElement,
5336
+ container,
5337
+ data,
5338
+ fromCache,
5339
+ version: resolvedVersion
5340
+ };
5341
+ onReady?.(result);
5342
+ return result;
5343
+ } catch (error) {
5344
+ const err = error instanceof Error ? error : new Error(String(error));
5345
+ onError?.(err);
5346
+ throw err;
5347
+ }
5348
+ }
5349
+ function mountData(options) {
5350
+ const {
5351
+ data,
5352
+ target,
5353
+ props = {},
5354
+ state = {},
5355
+ context = {},
5356
+ eventHandlers
5357
+ } = options;
5358
+ const container = typeof target === "string" ? document.querySelector(target) : target;
5359
+ if (!container) {
5360
+ throw new Error(`Target container not found: ${target}`);
5361
+ }
5362
+ const bindingContext = {
5363
+ props,
5364
+ state,
5365
+ context
5366
+ };
5367
+ const renderResult = render({
5368
+ container,
5369
+ elements: data.layout,
5370
+ context: bindingContext,
5371
+ eventHandlers
5372
+ });
5373
+ return {
5374
+ update: (newContext) => {
5375
+ renderResult.update({
5376
+ props: newContext.props ?? props,
5377
+ state: newContext.state ?? state,
5378
+ context: newContext.context ?? context
5379
+ });
5380
+ },
5381
+ destroy: () => {
5382
+ renderResult.destroy();
5383
+ },
5384
+ rootElement: renderResult.rootElement,
5385
+ container,
5386
+ data
5387
+ };
5388
+ }
5389
+
5224
5390
  // src/version.ts
5225
5391
  function parseVersion(version) {
5226
5392
  const match = version.match(/^(\d+)\.(\d+)\.(\d+)$/);
@@ -5618,6 +5784,7 @@ init_tailwind();
5618
5784
  camelToKebab,
5619
5785
  clearAllCaches,
5620
5786
  clearIconCache,
5787
+ clearIconStorageCache,
5621
5788
  clearLocalStorageCache,
5622
5789
  clearMemoryCache,
5623
5790
  clearStyles,
@@ -5692,6 +5859,8 @@ init_tailwind();
5692
5859
  loadFont,
5693
5860
  loadFonts,
5694
5861
  markElementReady,
5862
+ mount,
5863
+ mountData,
5695
5864
  navigateTo,
5696
5865
  parseVersion,
5697
5866
  prefetchComponents,
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  scheduleRefresh,
18
18
  updateTailwindConfig,
19
19
  waitForTailwind
20
- } from "./chunk-TXHGJYYM.js";
20
+ } from "./chunk-GN6KAMNI.js";
21
21
  import {
22
22
  buildRegistryFromBundle,
23
23
  collectAllDependencies,
@@ -2332,6 +2332,58 @@ function resetOverrideSystem() {
2332
2332
 
2333
2333
  // src/icons.ts
2334
2334
  var cdnEnabled = true;
2335
+ var ICON_CACHE_KEY = "servly-icon-cache";
2336
+ var ICON_CACHE_VERSION = "1";
2337
+ var localStorageLoaded = false;
2338
+ function loadIconCacheFromStorage() {
2339
+ if (localStorageLoaded) return;
2340
+ localStorageLoaded = true;
2341
+ if (typeof localStorage === "undefined") return;
2342
+ try {
2343
+ const cached = localStorage.getItem(ICON_CACHE_KEY);
2344
+ if (!cached) return;
2345
+ const parsed = JSON.parse(cached);
2346
+ if (parsed.version !== ICON_CACHE_VERSION) {
2347
+ localStorage.removeItem(ICON_CACHE_KEY);
2348
+ return;
2349
+ }
2350
+ for (const [key, data] of Object.entries(parsed.icons)) {
2351
+ if (!iconCache.has(key) && !registeredIcons.has(key)) {
2352
+ iconCache.set(key, data);
2353
+ }
2354
+ }
2355
+ } catch {
2356
+ }
2357
+ }
2358
+ function saveIconToStorage(key, data) {
2359
+ if (typeof localStorage === "undefined") return;
2360
+ try {
2361
+ const cached = localStorage.getItem(ICON_CACHE_KEY);
2362
+ let cacheData;
2363
+ if (cached) {
2364
+ cacheData = JSON.parse(cached);
2365
+ if (cacheData.version !== ICON_CACHE_VERSION) {
2366
+ cacheData = { version: ICON_CACHE_VERSION, icons: {} };
2367
+ }
2368
+ } else {
2369
+ cacheData = { version: ICON_CACHE_VERSION, icons: {} };
2370
+ }
2371
+ cacheData.icons[key] = data;
2372
+ const keys = Object.keys(cacheData.icons);
2373
+ if (keys.length > 500) {
2374
+ keys.slice(0, 100).forEach((k) => delete cacheData.icons[k]);
2375
+ }
2376
+ localStorage.setItem(ICON_CACHE_KEY, JSON.stringify(cacheData));
2377
+ } catch {
2378
+ }
2379
+ }
2380
+ function clearIconStorageCache() {
2381
+ if (typeof localStorage === "undefined") return;
2382
+ try {
2383
+ localStorage.removeItem(ICON_CACHE_KEY);
2384
+ } catch {
2385
+ }
2386
+ }
2335
2387
  function setIconCdnEnabled(enabled) {
2336
2388
  cdnEnabled = enabled;
2337
2389
  }
@@ -2504,6 +2556,7 @@ function parseSvgResponse(svgText) {
2504
2556
  }
2505
2557
  async function getIconData(icon) {
2506
2558
  const key = `${icon.set}:${icon.name}`;
2559
+ loadIconCacheFromStorage();
2507
2560
  if (iconCache.has(key)) {
2508
2561
  return iconCache.get(key);
2509
2562
  }
@@ -2519,11 +2572,13 @@ async function getIconData(icon) {
2519
2572
  pendingFetches.delete(key);
2520
2573
  if (data) {
2521
2574
  iconCache.set(key, data);
2575
+ saveIconToStorage(key, data);
2522
2576
  }
2523
2577
  return data;
2524
2578
  }
2525
2579
  function getIconDataSync(icon) {
2526
2580
  const key = `${icon.set}:${icon.name}`;
2581
+ loadIconCacheFromStorage();
2527
2582
  return iconCache.get(key) || null;
2528
2583
  }
2529
2584
  function createIconSVG(icon, data, size = 24, color = "currentColor") {
@@ -2623,12 +2678,15 @@ function renderIcon(container, icon, size = 24, color = "currentColor") {
2623
2678
  async function preloadIcons(icons) {
2624
2679
  await Promise.all(icons.map((icon) => getIconData(icon)));
2625
2680
  }
2626
- function clearIconCache() {
2681
+ function clearIconCache(clearStorage = false) {
2627
2682
  iconCache.clear();
2628
2683
  pendingFetches.clear();
2629
2684
  registeredIcons.forEach((data, key) => {
2630
2685
  iconCache.set(key, data);
2631
2686
  });
2687
+ if (clearStorage) {
2688
+ clearIconStorageCache();
2689
+ }
2632
2690
  }
2633
2691
  function isIconSetSupported(set) {
2634
2692
  return set in ICONIFY_COLLECTIONS;
@@ -3685,10 +3743,9 @@ function renderInShadow(options) {
3685
3743
  shadowRoot.insertBefore(styleEl, innerContainer);
3686
3744
  }
3687
3745
  if (shouldInjectTailwind) {
3688
- const tailwindLink = document.createElement("link");
3689
- tailwindLink.rel = "stylesheet";
3690
- tailwindLink.href = "https://cdn.tailwindcss.com";
3691
- shadowRoot.insertBefore(tailwindLink, innerContainer);
3746
+ const tailwindScript = document.createElement("script");
3747
+ tailwindScript.src = "https://cdn.tailwindcss.com";
3748
+ shadowRoot.insertBefore(tailwindScript, innerContainer);
3692
3749
  }
3693
3750
  const result = render({
3694
3751
  ...renderOptions,
@@ -3719,7 +3776,7 @@ async function createServlyRenderer(options) {
3719
3776
  container = containerOption;
3720
3777
  }
3721
3778
  if (shouldInjectTailwind) {
3722
- const { initServlyTailwind: initServlyTailwind2 } = await import("./tailwind-GU53TXCZ.js");
3779
+ const { initServlyTailwind: initServlyTailwind2 } = await import("./tailwind-MYAEYQPY.js");
3723
3780
  await initServlyTailwind2(tailwindConfig);
3724
3781
  }
3725
3782
  const activeRenders = [];
@@ -4422,6 +4479,109 @@ async function getDependencyTree(id, options = {}) {
4422
4479
  return data.data;
4423
4480
  }
4424
4481
 
4482
+ // src/mount.ts
4483
+ async function mount(options) {
4484
+ const {
4485
+ componentId,
4486
+ target,
4487
+ props = {},
4488
+ state = {},
4489
+ context = {},
4490
+ version = "latest",
4491
+ eventHandlers,
4492
+ fetchOptions = {},
4493
+ onReady,
4494
+ onError
4495
+ } = options;
4496
+ try {
4497
+ const container = typeof target === "string" ? document.querySelector(target) : target;
4498
+ if (!container) {
4499
+ throw new Error(`Target container not found: ${target}`);
4500
+ }
4501
+ const fetchResult = await fetchComponentWithDependencies(componentId, {
4502
+ ...fetchOptions,
4503
+ version
4504
+ });
4505
+ const { data, fromCache, version: resolvedVersion, registry, views } = fetchResult;
4506
+ const bindingContext = {
4507
+ props,
4508
+ state,
4509
+ context
4510
+ };
4511
+ const renderResult = render({
4512
+ container,
4513
+ elements: data.layout,
4514
+ context: bindingContext,
4515
+ eventHandlers,
4516
+ componentRegistry: registry,
4517
+ views
4518
+ });
4519
+ const result = {
4520
+ update: (newContext) => {
4521
+ renderResult.update({
4522
+ props: newContext.props ?? props,
4523
+ state: newContext.state ?? state,
4524
+ context: newContext.context ?? context
4525
+ });
4526
+ },
4527
+ destroy: () => {
4528
+ renderResult.destroy();
4529
+ },
4530
+ rootElement: renderResult.rootElement,
4531
+ container,
4532
+ data,
4533
+ fromCache,
4534
+ version: resolvedVersion
4535
+ };
4536
+ onReady?.(result);
4537
+ return result;
4538
+ } catch (error) {
4539
+ const err = error instanceof Error ? error : new Error(String(error));
4540
+ onError?.(err);
4541
+ throw err;
4542
+ }
4543
+ }
4544
+ function mountData(options) {
4545
+ const {
4546
+ data,
4547
+ target,
4548
+ props = {},
4549
+ state = {},
4550
+ context = {},
4551
+ eventHandlers
4552
+ } = options;
4553
+ const container = typeof target === "string" ? document.querySelector(target) : target;
4554
+ if (!container) {
4555
+ throw new Error(`Target container not found: ${target}`);
4556
+ }
4557
+ const bindingContext = {
4558
+ props,
4559
+ state,
4560
+ context
4561
+ };
4562
+ const renderResult = render({
4563
+ container,
4564
+ elements: data.layout,
4565
+ context: bindingContext,
4566
+ eventHandlers
4567
+ });
4568
+ return {
4569
+ update: (newContext) => {
4570
+ renderResult.update({
4571
+ props: newContext.props ?? props,
4572
+ state: newContext.state ?? state,
4573
+ context: newContext.context ?? context
4574
+ });
4575
+ },
4576
+ destroy: () => {
4577
+ renderResult.destroy();
4578
+ },
4579
+ rootElement: renderResult.rootElement,
4580
+ container,
4581
+ data
4582
+ };
4583
+ }
4584
+
4425
4585
  // src/version.ts
4426
4586
  function parseVersion(version) {
4427
4587
  const match = version.match(/^(\d+)\.(\d+)\.(\d+)$/);
@@ -4814,6 +4974,7 @@ export {
4814
4974
  camelToKebab,
4815
4975
  clearAllCaches,
4816
4976
  clearIconCache,
4977
+ clearIconStorageCache,
4817
4978
  clearLocalStorageCache,
4818
4979
  clearMemoryCache,
4819
4980
  clearStyles,
@@ -4888,6 +5049,8 @@ export {
4888
5049
  loadFont,
4889
5050
  loadFonts,
4890
5051
  markElementReady,
5052
+ mount,
5053
+ mountData,
4891
5054
  navigateTo,
4892
5055
  parseVersion,
4893
5056
  prefetchComponents,
@@ -18,7 +18,7 @@ import {
18
18
  tailwind_default,
19
19
  updateTailwindConfig,
20
20
  waitForTailwind
21
- } from "./chunk-TXHGJYYM.js";
21
+ } from "./chunk-GN6KAMNI.js";
22
22
  export {
23
23
  DEFAULT_SERVLY_TAILWIND_CONFIG,
24
24
  addCustomStyles,