@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 +100 -1
- package/dist/{chunk-TXHGJYYM.js → chunk-GN6KAMNI.js} +8 -5
- package/dist/index.cjs +179 -10
- package/dist/index.js +170 -7
- package/dist/{tailwind-GU53TXCZ.js → tailwind-MYAEYQPY.js} +1 -1
- package/package.json +2 -2
- package/dist/index.d.cts +0 -2071
- package/dist/index.d.ts +0 -2071
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
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
4487
|
-
|
|
4488
|
-
|
|
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-
|
|
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
|
|
3689
|
-
|
|
3690
|
-
|
|
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-
|
|
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,
|