@servlyadmin/runtime-core 0.1.8 → 0.1.10
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 +308 -0
- package/dist/chunk-MCKGQKYU.js +15 -0
- package/dist/chunk-OHWFJHAT.js +2189 -0
- package/dist/index.cjs +16960 -26
- package/dist/index.js +558 -17
- package/dist/react-EKMBDYIU.js +5 -0
- package/dist/{registry-GCCVK65D.js → registry-7UL42655.js} +1 -0
- package/dist/server.node-CQL3CG75.js +14187 -0
- package/dist/{tailwind-CGAHPC3O.js → tailwind-3FTT56ZG.js} +1 -0
- package/package.json +6 -7
- package/dist/index.d.cts +0 -1842
- package/dist/index.d.ts +0 -1842
package/dist/index.js
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
extractDependencies,
|
|
18
18
|
extractDependenciesFromCode
|
|
19
19
|
} from "./chunk-CIUQK4GA.js";
|
|
20
|
+
import "./chunk-MCKGQKYU.js";
|
|
20
21
|
|
|
21
22
|
// src/analyticsTypes.ts
|
|
22
23
|
var DEFAULT_ANALYTICS_CONFIG = {
|
|
@@ -2291,6 +2292,316 @@ function resetOverrideSystem() {
|
|
|
2291
2292
|
}
|
|
2292
2293
|
}
|
|
2293
2294
|
|
|
2295
|
+
// src/icons.ts
|
|
2296
|
+
var cdnEnabled = false;
|
|
2297
|
+
function setIconCdnEnabled(enabled) {
|
|
2298
|
+
cdnEnabled = enabled;
|
|
2299
|
+
}
|
|
2300
|
+
function isIconCdnEnabled() {
|
|
2301
|
+
return cdnEnabled;
|
|
2302
|
+
}
|
|
2303
|
+
var ICONIFY_COLLECTIONS = {
|
|
2304
|
+
Ai: "ant-design",
|
|
2305
|
+
Bi: "bi",
|
|
2306
|
+
Bs: "bi",
|
|
2307
|
+
Bx: "bx",
|
|
2308
|
+
Ci: "circum",
|
|
2309
|
+
Cg: "gg",
|
|
2310
|
+
Di: "devicon",
|
|
2311
|
+
Fi: "feather",
|
|
2312
|
+
Fc: "flat-color-icons",
|
|
2313
|
+
Fa: "fa-solid",
|
|
2314
|
+
Fa6: "fa6-solid",
|
|
2315
|
+
Gi: "game-icons",
|
|
2316
|
+
Go: "octicon",
|
|
2317
|
+
Gr: "grommet-icons",
|
|
2318
|
+
Hi: "heroicons-outline",
|
|
2319
|
+
Hi2: "heroicons",
|
|
2320
|
+
Im: "icomoon-free",
|
|
2321
|
+
Io: "ion",
|
|
2322
|
+
Io5: "ion",
|
|
2323
|
+
Lu: "lucide",
|
|
2324
|
+
Md: "ic",
|
|
2325
|
+
Pi: "ph",
|
|
2326
|
+
Ri: "ri",
|
|
2327
|
+
Rx: "radix-icons",
|
|
2328
|
+
Si: "simple-icons",
|
|
2329
|
+
Sl: "simple-line-icons",
|
|
2330
|
+
Tb: "tabler",
|
|
2331
|
+
Tfi: "themify",
|
|
2332
|
+
Vsc: "codicon",
|
|
2333
|
+
Wi: "wi"
|
|
2334
|
+
};
|
|
2335
|
+
var ICON_SET_STYLES = {
|
|
2336
|
+
Fi: { stroke: true },
|
|
2337
|
+
Lu: { stroke: true },
|
|
2338
|
+
Hi: { stroke: true },
|
|
2339
|
+
Hi2: { stroke: true },
|
|
2340
|
+
Tb: { stroke: true }
|
|
2341
|
+
};
|
|
2342
|
+
var iconCache = /* @__PURE__ */ new Map();
|
|
2343
|
+
var pendingFetches = /* @__PURE__ */ new Map();
|
|
2344
|
+
var registeredIcons = /* @__PURE__ */ new Map();
|
|
2345
|
+
function registerIcon(set, name, data) {
|
|
2346
|
+
const key = `${set}:${name}`;
|
|
2347
|
+
registeredIcons.set(key, data);
|
|
2348
|
+
iconCache.set(key, data);
|
|
2349
|
+
}
|
|
2350
|
+
function registerIcons(icons) {
|
|
2351
|
+
for (const [set, setIcons] of Object.entries(icons)) {
|
|
2352
|
+
for (const [name, data] of Object.entries(setIcons)) {
|
|
2353
|
+
registerIcon(set, name, data);
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
function isIconRegistered(icon) {
|
|
2358
|
+
const key = `${icon.set}:${icon.name}`;
|
|
2359
|
+
return registeredIcons.has(key);
|
|
2360
|
+
}
|
|
2361
|
+
function getRegisteredIconKeys() {
|
|
2362
|
+
return Array.from(registeredIcons.keys());
|
|
2363
|
+
}
|
|
2364
|
+
function toKebabCase(str) {
|
|
2365
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase();
|
|
2366
|
+
}
|
|
2367
|
+
function getIconifyName(name, set) {
|
|
2368
|
+
const prefixLength = set.length;
|
|
2369
|
+
let baseName = name;
|
|
2370
|
+
if (name.startsWith(set)) {
|
|
2371
|
+
baseName = name.slice(prefixLength);
|
|
2372
|
+
}
|
|
2373
|
+
let kebabName = toKebabCase(baseName);
|
|
2374
|
+
switch (set) {
|
|
2375
|
+
case "Md":
|
|
2376
|
+
if (baseName.startsWith("Outline")) {
|
|
2377
|
+
kebabName = toKebabCase(baseName.slice(7)) + "-outline";
|
|
2378
|
+
}
|
|
2379
|
+
kebabName = "baseline-" + kebabName;
|
|
2380
|
+
break;
|
|
2381
|
+
case "Hi2":
|
|
2382
|
+
if (baseName.startsWith("Outline")) {
|
|
2383
|
+
kebabName = toKebabCase(baseName.slice(7));
|
|
2384
|
+
} else if (baseName.startsWith("Solid")) {
|
|
2385
|
+
kebabName = toKebabCase(baseName.slice(5)) + "-solid";
|
|
2386
|
+
}
|
|
2387
|
+
break;
|
|
2388
|
+
case "Io":
|
|
2389
|
+
case "Io5":
|
|
2390
|
+
if (baseName.startsWith("Ios")) {
|
|
2391
|
+
kebabName = toKebabCase(baseName.slice(3));
|
|
2392
|
+
} else if (baseName.startsWith("Md")) {
|
|
2393
|
+
kebabName = toKebabCase(baseName.slice(2));
|
|
2394
|
+
}
|
|
2395
|
+
break;
|
|
2396
|
+
case "Pi":
|
|
2397
|
+
if (baseName.endsWith("Bold")) {
|
|
2398
|
+
kebabName = toKebabCase(baseName.slice(0, -4)) + "-bold";
|
|
2399
|
+
} else if (baseName.endsWith("Fill")) {
|
|
2400
|
+
kebabName = toKebabCase(baseName.slice(0, -4)) + "-fill";
|
|
2401
|
+
} else if (baseName.endsWith("Light")) {
|
|
2402
|
+
kebabName = toKebabCase(baseName.slice(0, -5)) + "-light";
|
|
2403
|
+
} else if (baseName.endsWith("Thin")) {
|
|
2404
|
+
kebabName = toKebabCase(baseName.slice(0, -4)) + "-thin";
|
|
2405
|
+
} else if (baseName.endsWith("Duotone")) {
|
|
2406
|
+
kebabName = toKebabCase(baseName.slice(0, -7)) + "-duotone";
|
|
2407
|
+
}
|
|
2408
|
+
break;
|
|
2409
|
+
}
|
|
2410
|
+
return kebabName;
|
|
2411
|
+
}
|
|
2412
|
+
async function fetchIconFromIconify(set, name) {
|
|
2413
|
+
if (!cdnEnabled) {
|
|
2414
|
+
return null;
|
|
2415
|
+
}
|
|
2416
|
+
const collection = ICONIFY_COLLECTIONS[set];
|
|
2417
|
+
if (!collection) {
|
|
2418
|
+
return null;
|
|
2419
|
+
}
|
|
2420
|
+
const iconName = getIconifyName(name, set);
|
|
2421
|
+
try {
|
|
2422
|
+
const url = `https://api.iconify.design/${collection}/${iconName}.svg`;
|
|
2423
|
+
const response = await fetch(url);
|
|
2424
|
+
if (!response.ok) {
|
|
2425
|
+
const altNames = [
|
|
2426
|
+
iconName.replace(/-outline$/, ""),
|
|
2427
|
+
iconName.replace(/-solid$/, ""),
|
|
2428
|
+
iconName.replace(/-fill$/, ""),
|
|
2429
|
+
iconName.replace(/^baseline-/, "")
|
|
2430
|
+
].filter((alt) => alt !== iconName);
|
|
2431
|
+
for (const altName of altNames) {
|
|
2432
|
+
const altUrl = `https://api.iconify.design/${collection}/${altName}.svg`;
|
|
2433
|
+
const altResponse = await fetch(altUrl);
|
|
2434
|
+
if (altResponse.ok) {
|
|
2435
|
+
return parseSvgResponse(await altResponse.text());
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
return null;
|
|
2439
|
+
}
|
|
2440
|
+
return parseSvgResponse(await response.text());
|
|
2441
|
+
} catch {
|
|
2442
|
+
return null;
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
function parseSvgResponse(svgText) {
|
|
2446
|
+
try {
|
|
2447
|
+
const parser = new DOMParser();
|
|
2448
|
+
const doc = parser.parseFromString(svgText, "image/svg+xml");
|
|
2449
|
+
const svg = doc.querySelector("svg");
|
|
2450
|
+
if (!svg) {
|
|
2451
|
+
return null;
|
|
2452
|
+
}
|
|
2453
|
+
const viewBox = svg.getAttribute("viewBox");
|
|
2454
|
+
const width = parseInt(svg.getAttribute("width") || "24", 10);
|
|
2455
|
+
const height = parseInt(svg.getAttribute("height") || "24", 10);
|
|
2456
|
+
const body = svg.innerHTML;
|
|
2457
|
+
return {
|
|
2458
|
+
body,
|
|
2459
|
+
width,
|
|
2460
|
+
height,
|
|
2461
|
+
viewBox: viewBox || `0 0 ${width} ${height}`
|
|
2462
|
+
};
|
|
2463
|
+
} catch {
|
|
2464
|
+
return null;
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
async function getIconData(icon) {
|
|
2468
|
+
const key = `${icon.set}:${icon.name}`;
|
|
2469
|
+
if (iconCache.has(key)) {
|
|
2470
|
+
return iconCache.get(key);
|
|
2471
|
+
}
|
|
2472
|
+
if (pendingFetches.has(key)) {
|
|
2473
|
+
return pendingFetches.get(key);
|
|
2474
|
+
}
|
|
2475
|
+
if (!cdnEnabled) {
|
|
2476
|
+
return null;
|
|
2477
|
+
}
|
|
2478
|
+
const fetchPromise = fetchIconFromIconify(icon.set, icon.name);
|
|
2479
|
+
pendingFetches.set(key, fetchPromise);
|
|
2480
|
+
const data = await fetchPromise;
|
|
2481
|
+
pendingFetches.delete(key);
|
|
2482
|
+
if (data) {
|
|
2483
|
+
iconCache.set(key, data);
|
|
2484
|
+
}
|
|
2485
|
+
return data;
|
|
2486
|
+
}
|
|
2487
|
+
function getIconDataSync(icon) {
|
|
2488
|
+
const key = `${icon.set}:${icon.name}`;
|
|
2489
|
+
return iconCache.get(key) || null;
|
|
2490
|
+
}
|
|
2491
|
+
function createIconSVG(icon, data, size = 24, color = "currentColor") {
|
|
2492
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
2493
|
+
svg.setAttribute("width", String(size));
|
|
2494
|
+
svg.setAttribute("height", String(size));
|
|
2495
|
+
svg.setAttribute("viewBox", data.viewBox || "0 0 24 24");
|
|
2496
|
+
svg.setAttribute("data-icon-name", icon.name);
|
|
2497
|
+
svg.setAttribute("data-icon-set", icon.set);
|
|
2498
|
+
svg.setAttribute("class", `servly-icon servly-icon-${icon.set.toLowerCase()}`);
|
|
2499
|
+
const style = ICON_SET_STYLES[icon.set];
|
|
2500
|
+
if (style?.stroke) {
|
|
2501
|
+
svg.setAttribute("fill", "none");
|
|
2502
|
+
svg.setAttribute("stroke", color);
|
|
2503
|
+
svg.setAttribute("stroke-width", "2");
|
|
2504
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
2505
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
2506
|
+
} else {
|
|
2507
|
+
svg.setAttribute("fill", color);
|
|
2508
|
+
}
|
|
2509
|
+
svg.innerHTML = data.body;
|
|
2510
|
+
const paths = svg.querySelectorAll("path, circle, rect, polygon, line, polyline");
|
|
2511
|
+
paths.forEach((el) => {
|
|
2512
|
+
if (!el.getAttribute("fill") || el.getAttribute("fill") === "currentColor") {
|
|
2513
|
+
if (style?.stroke) {
|
|
2514
|
+
el.setAttribute("stroke", color);
|
|
2515
|
+
} else {
|
|
2516
|
+
el.setAttribute("fill", color);
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
});
|
|
2520
|
+
return svg;
|
|
2521
|
+
}
|
|
2522
|
+
function createPlaceholderIcon(icon, size = 24, color = "currentColor") {
|
|
2523
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
2524
|
+
svg.setAttribute("width", String(size));
|
|
2525
|
+
svg.setAttribute("height", String(size));
|
|
2526
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
2527
|
+
svg.setAttribute("fill", "none");
|
|
2528
|
+
svg.setAttribute("stroke", color);
|
|
2529
|
+
svg.setAttribute("stroke-width", "2");
|
|
2530
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
2531
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
2532
|
+
svg.setAttribute("data-icon-name", icon.name);
|
|
2533
|
+
svg.setAttribute("data-icon-set", icon.set);
|
|
2534
|
+
svg.setAttribute("data-icon-missing", "true");
|
|
2535
|
+
svg.setAttribute("class", "servly-icon servly-icon-placeholder");
|
|
2536
|
+
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
|
2537
|
+
circle.setAttribute("cx", "12");
|
|
2538
|
+
circle.setAttribute("cy", "12");
|
|
2539
|
+
circle.setAttribute("r", "10");
|
|
2540
|
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
2541
|
+
path.setAttribute("d", "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3");
|
|
2542
|
+
const dot = document.createElementNS("http://www.w3.org/2000/svg", "line");
|
|
2543
|
+
dot.setAttribute("x1", "12");
|
|
2544
|
+
dot.setAttribute("y1", "17");
|
|
2545
|
+
dot.setAttribute("x2", "12.01");
|
|
2546
|
+
dot.setAttribute("y2", "17");
|
|
2547
|
+
svg.appendChild(circle);
|
|
2548
|
+
svg.appendChild(path);
|
|
2549
|
+
svg.appendChild(dot);
|
|
2550
|
+
return svg;
|
|
2551
|
+
}
|
|
2552
|
+
function renderIcon(container, icon, size = 24, color = "currentColor") {
|
|
2553
|
+
const cachedData = getIconDataSync(icon);
|
|
2554
|
+
if (cachedData) {
|
|
2555
|
+
const svg = createIconSVG(icon, cachedData, size, color);
|
|
2556
|
+
container.innerHTML = "";
|
|
2557
|
+
container.appendChild(svg);
|
|
2558
|
+
return;
|
|
2559
|
+
}
|
|
2560
|
+
if (!cdnEnabled) {
|
|
2561
|
+
const placeholder2 = createPlaceholderIcon(icon, size, color);
|
|
2562
|
+
container.innerHTML = "";
|
|
2563
|
+
container.appendChild(placeholder2);
|
|
2564
|
+
console.warn(
|
|
2565
|
+
`[Icons] Icon not bundled: ${icon.set}:${icon.name}. Use registerIcon() to bundle it, or enable CDN with setIconCdnEnabled(true).`
|
|
2566
|
+
);
|
|
2567
|
+
return;
|
|
2568
|
+
}
|
|
2569
|
+
const placeholder = createPlaceholderIcon(icon, size, color);
|
|
2570
|
+
placeholder.setAttribute("data-icon-loading", "true");
|
|
2571
|
+
placeholder.removeAttribute("data-icon-missing");
|
|
2572
|
+
container.innerHTML = "";
|
|
2573
|
+
container.appendChild(placeholder);
|
|
2574
|
+
getIconData(icon).then((data) => {
|
|
2575
|
+
if (data) {
|
|
2576
|
+
const svg = createIconSVG(icon, data, size, color);
|
|
2577
|
+
container.innerHTML = "";
|
|
2578
|
+
container.appendChild(svg);
|
|
2579
|
+
} else {
|
|
2580
|
+
placeholder.setAttribute("data-icon-missing", "true");
|
|
2581
|
+
placeholder.removeAttribute("data-icon-loading");
|
|
2582
|
+
}
|
|
2583
|
+
});
|
|
2584
|
+
}
|
|
2585
|
+
async function preloadIcons(icons) {
|
|
2586
|
+
await Promise.all(icons.map((icon) => getIconData(icon)));
|
|
2587
|
+
}
|
|
2588
|
+
function clearIconCache() {
|
|
2589
|
+
iconCache.clear();
|
|
2590
|
+
pendingFetches.clear();
|
|
2591
|
+
registeredIcons.forEach((data, key) => {
|
|
2592
|
+
iconCache.set(key, data);
|
|
2593
|
+
});
|
|
2594
|
+
}
|
|
2595
|
+
function isIconSetSupported(set) {
|
|
2596
|
+
return set in ICONIFY_COLLECTIONS;
|
|
2597
|
+
}
|
|
2598
|
+
function getSupportedIconSets() {
|
|
2599
|
+
return Object.keys(ICONIFY_COLLECTIONS);
|
|
2600
|
+
}
|
|
2601
|
+
function getIconifyCollection(set) {
|
|
2602
|
+
return ICONIFY_COLLECTIONS[set];
|
|
2603
|
+
}
|
|
2604
|
+
|
|
2294
2605
|
// src/renderer.ts
|
|
2295
2606
|
var COMPONENT_TO_TAG = {
|
|
2296
2607
|
container: "div",
|
|
@@ -2673,6 +2984,9 @@ function renderElement(element, tree, context, eventHandlers, elementStates, sta
|
|
|
2673
2984
|
if (element.componentId === "slot") {
|
|
2674
2985
|
return renderSlotElement(element, tree, context, eventHandlers, elementStates, state, isRootElement);
|
|
2675
2986
|
}
|
|
2987
|
+
if (element.componentId === "icon") {
|
|
2988
|
+
return renderIconElement(element, context, eventHandlers, elementStates, state, isRootElement);
|
|
2989
|
+
}
|
|
2676
2990
|
const elementState = createElement(element, context, eventHandlers, isRootElement, state);
|
|
2677
2991
|
elementStates.set(element.i, elementState);
|
|
2678
2992
|
const config = element.configuration;
|
|
@@ -2690,6 +3004,40 @@ function renderElement(element, tree, context, eventHandlers, elementStates, sta
|
|
|
2690
3004
|
}
|
|
2691
3005
|
return elementState.domElement;
|
|
2692
3006
|
}
|
|
3007
|
+
function renderIconElement(element, context, eventHandlers, elementStates, state, isRootElement) {
|
|
3008
|
+
const config = element.configuration || {};
|
|
3009
|
+
const icon = config.icon;
|
|
3010
|
+
const iconColor = config.iconColor || "currentColor";
|
|
3011
|
+
const iconSize = config.iconSize || 24;
|
|
3012
|
+
const wrapper = document.createElement("div");
|
|
3013
|
+
wrapper.setAttribute("data-servly-id", element.i);
|
|
3014
|
+
wrapper.className = "pointer-events-none";
|
|
3015
|
+
const styles = buildElementStyles(element, context);
|
|
3016
|
+
applyStyles(wrapper, styles);
|
|
3017
|
+
const className = buildClassName(element, context);
|
|
3018
|
+
if (className) {
|
|
3019
|
+
wrapper.className = `pointer-events-none ${className}`;
|
|
3020
|
+
}
|
|
3021
|
+
if (state.iconRenderer && icon) {
|
|
3022
|
+
const iconElement = state.iconRenderer(icon, iconSize, iconColor, "");
|
|
3023
|
+
if (iconElement) {
|
|
3024
|
+
wrapper.appendChild(iconElement);
|
|
3025
|
+
}
|
|
3026
|
+
} else if (icon) {
|
|
3027
|
+
renderIcon(wrapper, icon, iconSize, iconColor);
|
|
3028
|
+
}
|
|
3029
|
+
const elementState = {
|
|
3030
|
+
element,
|
|
3031
|
+
domElement: wrapper,
|
|
3032
|
+
styles,
|
|
3033
|
+
className: wrapper.className,
|
|
3034
|
+
textContent: "",
|
|
3035
|
+
eventListeners: /* @__PURE__ */ new Map()
|
|
3036
|
+
};
|
|
3037
|
+
elementStates.set(element.i, elementState);
|
|
3038
|
+
attachEventHandlers(wrapper, element, eventHandlers, context, elementState, isRootElement, state);
|
|
3039
|
+
return wrapper;
|
|
3040
|
+
}
|
|
2693
3041
|
function renderComponentViewElement(element, tree, context, eventHandlers, elementStates, state, isRootElement) {
|
|
2694
3042
|
const componentViewId = `${element.componentId}-${element.i}`;
|
|
2695
3043
|
if (globalRenderingStack.has(componentViewId)) {
|
|
@@ -2709,7 +3057,15 @@ function renderComponentViewElement(element, tree, context, eventHandlers, eleme
|
|
|
2709
3057
|
viewLayout = component.layout;
|
|
2710
3058
|
}
|
|
2711
3059
|
}
|
|
3060
|
+
if (!viewLayout && state.views === void 0 && state.viewsArray) {
|
|
3061
|
+
const viewsArray = state.viewsArray;
|
|
3062
|
+
const found = viewsArray.find((v) => v.id === element.componentId);
|
|
3063
|
+
if (found) {
|
|
3064
|
+
viewLayout = found.layout;
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
2712
3067
|
if (!viewLayout) {
|
|
3068
|
+
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
3069
|
const placeholder = document.createElement("div");
|
|
2714
3070
|
placeholder.className = "border-2 border-yellow-500 border-dashed p-4 bg-yellow-50";
|
|
2715
3071
|
placeholder.innerHTML = `<p class="text-yellow-600 text-sm">Component not found: ${element.componentId}</p>`;
|
|
@@ -2823,14 +3179,26 @@ function render(options) {
|
|
|
2823
3179
|
eventHandlers,
|
|
2824
3180
|
componentRegistry,
|
|
2825
3181
|
onDependencyNeeded,
|
|
2826
|
-
views,
|
|
3182
|
+
views: viewsInput,
|
|
2827
3183
|
enableStateManager,
|
|
2828
3184
|
initialState,
|
|
2829
3185
|
onStateChange,
|
|
2830
3186
|
pluginExecutors,
|
|
2831
3187
|
onNavigate,
|
|
2832
|
-
onApiCall
|
|
3188
|
+
onApiCall,
|
|
3189
|
+
iconRenderer
|
|
2833
3190
|
} = options;
|
|
3191
|
+
let views;
|
|
3192
|
+
if (viewsInput instanceof Map) {
|
|
3193
|
+
views = viewsInput;
|
|
3194
|
+
} else if (Array.isArray(viewsInput)) {
|
|
3195
|
+
views = /* @__PURE__ */ new Map();
|
|
3196
|
+
for (const view of viewsInput) {
|
|
3197
|
+
if (view && view.id) {
|
|
3198
|
+
views.set(view.id, view);
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
2834
3202
|
const startTime = performance.now();
|
|
2835
3203
|
const memorySampler = getMemorySampler();
|
|
2836
3204
|
const longTaskObserver = getLongTaskObserver();
|
|
@@ -2878,7 +3246,8 @@ function render(options) {
|
|
|
2878
3246
|
eventSystem,
|
|
2879
3247
|
stateManager,
|
|
2880
3248
|
overrideSystem,
|
|
2881
|
-
enableOverrides: hasAnyOverrides
|
|
3249
|
+
enableOverrides: hasAnyOverrides,
|
|
3250
|
+
iconRenderer
|
|
2882
3251
|
};
|
|
2883
3252
|
container.innerHTML = "";
|
|
2884
3253
|
if (rootElements.length === 0) {
|
|
@@ -3155,7 +3524,7 @@ async function createServlyRenderer(options) {
|
|
|
3155
3524
|
container = containerOption;
|
|
3156
3525
|
}
|
|
3157
3526
|
if (shouldInjectTailwind) {
|
|
3158
|
-
const { initServlyTailwind: initServlyTailwind2 } = await import("./tailwind-
|
|
3527
|
+
const { initServlyTailwind: initServlyTailwind2 } = await import("./tailwind-3FTT56ZG.js");
|
|
3159
3528
|
await initServlyTailwind2(tailwindConfig);
|
|
3160
3529
|
}
|
|
3161
3530
|
const activeRenders = [];
|
|
@@ -3525,17 +3894,33 @@ function calculateBackoffDelay(retryCount, config) {
|
|
|
3525
3894
|
function sleep(ms) {
|
|
3526
3895
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3527
3896
|
}
|
|
3528
|
-
function buildViewsMap(views) {
|
|
3529
|
-
if (!views || views.length === 0) return void 0;
|
|
3897
|
+
function buildViewsMap(views, bundle) {
|
|
3530
3898
|
const viewsMap = /* @__PURE__ */ new Map();
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3899
|
+
if (views && views.length > 0) {
|
|
3900
|
+
for (const view of views) {
|
|
3901
|
+
if (view && view.id) {
|
|
3902
|
+
viewsMap.set(view.id, {
|
|
3903
|
+
id: view.id,
|
|
3904
|
+
layout: view.layout,
|
|
3905
|
+
props: view.props
|
|
3906
|
+
});
|
|
3907
|
+
}
|
|
3908
|
+
}
|
|
3537
3909
|
}
|
|
3538
|
-
|
|
3910
|
+
if (bundle) {
|
|
3911
|
+
for (const [key, component] of Object.entries(bundle)) {
|
|
3912
|
+
const atIndex = key.lastIndexOf("@");
|
|
3913
|
+
const viewId = atIndex > 0 ? key.substring(0, atIndex) : key;
|
|
3914
|
+
if (!viewsMap.has(viewId) && component && component.layout) {
|
|
3915
|
+
viewsMap.set(viewId, {
|
|
3916
|
+
id: viewId,
|
|
3917
|
+
layout: component.layout,
|
|
3918
|
+
props: void 0
|
|
3919
|
+
});
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3922
|
+
}
|
|
3923
|
+
return viewsMap.size > 0 ? viewsMap : void 0;
|
|
3539
3924
|
}
|
|
3540
3925
|
async function resolveVersionFromApi(id, specifier, apiKey) {
|
|
3541
3926
|
if (/^\d+\.\d+\.\d+$/.test(specifier)) {
|
|
@@ -3637,7 +4022,7 @@ async function fetchComponent(id, options = {}) {
|
|
|
3637
4022
|
if (cached.bundle) {
|
|
3638
4023
|
registry = buildRegistryFromBundle(cached);
|
|
3639
4024
|
}
|
|
3640
|
-
const views = buildViewsMap(cached.views);
|
|
4025
|
+
const views = buildViewsMap(cached.views, cached.bundle);
|
|
3641
4026
|
const duration = performance.now() - startTime;
|
|
3642
4027
|
analytics.trackFetch(id, cached.version, duration, true, {
|
|
3643
4028
|
cacheHit: true,
|
|
@@ -3660,7 +4045,7 @@ async function fetchComponent(id, options = {}) {
|
|
|
3660
4045
|
if (cached.bundle) {
|
|
3661
4046
|
registry = buildRegistryFromBundle(cached);
|
|
3662
4047
|
}
|
|
3663
|
-
const views = buildViewsMap(cached.views);
|
|
4048
|
+
const views = buildViewsMap(cached.views, cached.bundle);
|
|
3664
4049
|
return {
|
|
3665
4050
|
data: cached,
|
|
3666
4051
|
fromCache: true,
|
|
@@ -3692,7 +4077,7 @@ async function fetchComponent(id, options = {}) {
|
|
|
3692
4077
|
version: entry.resolved || entry.version
|
|
3693
4078
|
}));
|
|
3694
4079
|
}
|
|
3695
|
-
const views = buildViewsMap(data.views);
|
|
4080
|
+
const views = buildViewsMap(data.views, data.bundle);
|
|
3696
4081
|
const duration = performance.now() - startTime;
|
|
3697
4082
|
analytics.trackFetch(id, resolvedVersion, duration, false, {
|
|
3698
4083
|
cacheHit: false,
|
|
@@ -3727,7 +4112,7 @@ async function fetchComponent(id, options = {}) {
|
|
|
3727
4112
|
async function fetchComponentWithDependencies(id, options = {}) {
|
|
3728
4113
|
const result = await fetchComponent(id, { ...options, includeBundle: true });
|
|
3729
4114
|
if (result.pendingDependencies && result.pendingDependencies.length > 0) {
|
|
3730
|
-
const { createRegistry: createRegistry2 } = await import("./registry-
|
|
4115
|
+
const { createRegistry: createRegistry2 } = await import("./registry-7UL42655.js");
|
|
3731
4116
|
const registry = result.registry || createRegistry2();
|
|
3732
4117
|
await Promise.all(
|
|
3733
4118
|
result.pendingDependencies.map(async (dep) => {
|
|
@@ -4199,6 +4584,142 @@ function getSampleValue(def) {
|
|
|
4199
4584
|
return def.defaultValue;
|
|
4200
4585
|
}
|
|
4201
4586
|
}
|
|
4587
|
+
|
|
4588
|
+
// src/iconExtractor.ts
|
|
4589
|
+
var REACT_ICONS_PACKAGES = {
|
|
4590
|
+
Ai: "react-icons/ai",
|
|
4591
|
+
Bi: "react-icons/bi",
|
|
4592
|
+
Bs: "react-icons/bs",
|
|
4593
|
+
Cg: "react-icons/cg",
|
|
4594
|
+
Di: "react-icons/di",
|
|
4595
|
+
Fa: "react-icons/fa",
|
|
4596
|
+
Fa6: "react-icons/fa6",
|
|
4597
|
+
Fc: "react-icons/fc",
|
|
4598
|
+
Fi: "react-icons/fi",
|
|
4599
|
+
Gi: "react-icons/gi",
|
|
4600
|
+
Go: "react-icons/go",
|
|
4601
|
+
Gr: "react-icons/gr",
|
|
4602
|
+
Hi: "react-icons/hi",
|
|
4603
|
+
Hi2: "react-icons/hi2",
|
|
4604
|
+
Im: "react-icons/im",
|
|
4605
|
+
Io: "react-icons/io",
|
|
4606
|
+
Io5: "react-icons/io5",
|
|
4607
|
+
Lu: "react-icons/lu",
|
|
4608
|
+
Md: "react-icons/md",
|
|
4609
|
+
Pi: "react-icons/pi",
|
|
4610
|
+
Ri: "react-icons/ri",
|
|
4611
|
+
Rx: "react-icons/rx",
|
|
4612
|
+
Si: "react-icons/si",
|
|
4613
|
+
Sl: "react-icons/sl",
|
|
4614
|
+
Tb: "react-icons/tb",
|
|
4615
|
+
Tfi: "react-icons/tfi",
|
|
4616
|
+
Vsc: "react-icons/vsc",
|
|
4617
|
+
Wi: "react-icons/wi"
|
|
4618
|
+
};
|
|
4619
|
+
async function extractIconFromReactIcons(iconName, iconSet) {
|
|
4620
|
+
const packagePath = REACT_ICONS_PACKAGES[iconSet];
|
|
4621
|
+
if (!packagePath) {
|
|
4622
|
+
console.warn(`Unknown icon set: ${iconSet}`);
|
|
4623
|
+
return null;
|
|
4624
|
+
}
|
|
4625
|
+
try {
|
|
4626
|
+
const iconModule = await import(packagePath);
|
|
4627
|
+
const IconComponent = iconModule[iconName];
|
|
4628
|
+
if (!IconComponent) {
|
|
4629
|
+
console.warn(`Icon not found: ${iconName} in ${packagePath}`);
|
|
4630
|
+
return null;
|
|
4631
|
+
}
|
|
4632
|
+
const React = await import("./react-EKMBDYIU.js");
|
|
4633
|
+
const { renderToStaticMarkup } = await import("./server.node-CQL3CG75.js");
|
|
4634
|
+
const svgString = renderToStaticMarkup(React.createElement(IconComponent, { size: 24 }));
|
|
4635
|
+
return parseSvgString(svgString);
|
|
4636
|
+
} catch (error) {
|
|
4637
|
+
console.error(`Failed to extract icon ${iconSet}:${iconName}:`, error);
|
|
4638
|
+
return null;
|
|
4639
|
+
}
|
|
4640
|
+
}
|
|
4641
|
+
function parseSvgString(svgString) {
|
|
4642
|
+
const viewBoxMatch = svgString.match(/viewBox="([^"]+)"/);
|
|
4643
|
+
const viewBox = viewBoxMatch ? viewBoxMatch[1] : "0 0 24 24";
|
|
4644
|
+
const widthMatch = svgString.match(/width="(\d+)"/);
|
|
4645
|
+
const heightMatch = svgString.match(/height="(\d+)"/);
|
|
4646
|
+
const width = widthMatch ? parseInt(widthMatch[1], 10) : 24;
|
|
4647
|
+
const height = heightMatch ? parseInt(heightMatch[1], 10) : 24;
|
|
4648
|
+
const bodyMatch = svgString.match(/<svg[^>]*>([\s\S]*)<\/svg>/);
|
|
4649
|
+
const body = bodyMatch ? bodyMatch[1].trim() : "";
|
|
4650
|
+
if (!body) {
|
|
4651
|
+
return null;
|
|
4652
|
+
}
|
|
4653
|
+
return {
|
|
4654
|
+
body,
|
|
4655
|
+
viewBox,
|
|
4656
|
+
width,
|
|
4657
|
+
height
|
|
4658
|
+
};
|
|
4659
|
+
}
|
|
4660
|
+
function findIconsInLayout(elements) {
|
|
4661
|
+
const icons = [];
|
|
4662
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4663
|
+
for (const element of elements) {
|
|
4664
|
+
if (element.componentId === "icon" && element.configuration?.icon) {
|
|
4665
|
+
const icon = element.configuration.icon;
|
|
4666
|
+
const key = `${icon.set}:${icon.name}`;
|
|
4667
|
+
if (!seen.has(key)) {
|
|
4668
|
+
seen.add(key);
|
|
4669
|
+
icons.push({
|
|
4670
|
+
name: icon.name,
|
|
4671
|
+
set: icon.set,
|
|
4672
|
+
setName: icon.setName
|
|
4673
|
+
});
|
|
4674
|
+
}
|
|
4675
|
+
}
|
|
4676
|
+
}
|
|
4677
|
+
return icons;
|
|
4678
|
+
}
|
|
4679
|
+
async function extractIconsForLayout(elements) {
|
|
4680
|
+
const icons = findIconsInLayout(elements);
|
|
4681
|
+
const result = {};
|
|
4682
|
+
for (const icon of icons) {
|
|
4683
|
+
const data = await extractIconFromReactIcons(icon.name, icon.set);
|
|
4684
|
+
if (data) {
|
|
4685
|
+
if (!result[icon.set]) {
|
|
4686
|
+
result[icon.set] = {};
|
|
4687
|
+
}
|
|
4688
|
+
result[icon.set][icon.name] = data;
|
|
4689
|
+
}
|
|
4690
|
+
}
|
|
4691
|
+
return result;
|
|
4692
|
+
}
|
|
4693
|
+
function generateIconBundle(icons) {
|
|
4694
|
+
const lines = [
|
|
4695
|
+
"// Auto-generated icon bundle",
|
|
4696
|
+
"// Do not edit manually",
|
|
4697
|
+
"",
|
|
4698
|
+
"import { registerIcons, type IconData } from '@servlyadmin/runtime-core';",
|
|
4699
|
+
"",
|
|
4700
|
+
"const BUNDLED_ICONS: Record<string, Record<string, IconData>> = {"
|
|
4701
|
+
];
|
|
4702
|
+
for (const [set, setIcons] of Object.entries(icons)) {
|
|
4703
|
+
lines.push(` ${set}: {`);
|
|
4704
|
+
for (const [name, data] of Object.entries(setIcons)) {
|
|
4705
|
+
const escapedBody = data.body.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\n/g, "\\n");
|
|
4706
|
+
lines.push(` ${name}: {`);
|
|
4707
|
+
lines.push(` body: '${escapedBody}',`);
|
|
4708
|
+
lines.push(` viewBox: '${data.viewBox}',`);
|
|
4709
|
+
if (data.width) lines.push(` width: ${data.width},`);
|
|
4710
|
+
if (data.height) lines.push(` height: ${data.height},`);
|
|
4711
|
+
lines.push(` },`);
|
|
4712
|
+
}
|
|
4713
|
+
lines.push(` },`);
|
|
4714
|
+
}
|
|
4715
|
+
lines.push("};");
|
|
4716
|
+
lines.push("");
|
|
4717
|
+
lines.push("// Register all bundled icons");
|
|
4718
|
+
lines.push("registerIcons(BUNDLED_ICONS);");
|
|
4719
|
+
lines.push("");
|
|
4720
|
+
lines.push("export { BUNDLED_ICONS };");
|
|
4721
|
+
return lines.join("\n");
|
|
4722
|
+
}
|
|
4202
4723
|
export {
|
|
4203
4724
|
AnalyticsCollector,
|
|
4204
4725
|
DEFAULT_CACHE_CONFIG,
|
|
@@ -4222,6 +4743,7 @@ export {
|
|
|
4222
4743
|
bumpVersion,
|
|
4223
4744
|
camelToKebab,
|
|
4224
4745
|
clearAllCaches,
|
|
4746
|
+
clearIconCache,
|
|
4225
4747
|
clearLocalStorageCache,
|
|
4226
4748
|
clearMemoryCache,
|
|
4227
4749
|
clearStyles,
|
|
@@ -4229,6 +4751,8 @@ export {
|
|
|
4229
4751
|
collectAllViewDependencies,
|
|
4230
4752
|
compareVersions,
|
|
4231
4753
|
configureAnalytics,
|
|
4754
|
+
createIconSVG,
|
|
4755
|
+
createPlaceholderIcon,
|
|
4232
4756
|
createRegistry,
|
|
4233
4757
|
createServlyRenderer,
|
|
4234
4758
|
createViewsMap,
|
|
@@ -4238,12 +4762,16 @@ export {
|
|
|
4238
4762
|
extractBindingKeys,
|
|
4239
4763
|
extractDependencies,
|
|
4240
4764
|
extractDependenciesFromCode,
|
|
4765
|
+
extractIconFromReactIcons,
|
|
4766
|
+
extractIconsForLayout,
|
|
4241
4767
|
extractOverrideDependencies,
|
|
4242
4768
|
extractReferencedViewIds,
|
|
4243
4769
|
fetchComponent,
|
|
4244
4770
|
fetchComponentWithDependencies,
|
|
4771
|
+
findIconsInLayout,
|
|
4245
4772
|
formatStyleValue,
|
|
4246
4773
|
formatVersion,
|
|
4774
|
+
generateIconBundle,
|
|
4247
4775
|
generateTestCases,
|
|
4248
4776
|
getAnalytics,
|
|
4249
4777
|
getCacheKey,
|
|
@@ -4251,15 +4779,20 @@ export {
|
|
|
4251
4779
|
getDependencyTree,
|
|
4252
4780
|
getEventSystem,
|
|
4253
4781
|
getFromCache,
|
|
4782
|
+
getIconData,
|
|
4783
|
+
getIconDataSync,
|
|
4784
|
+
getIconifyCollection,
|
|
4254
4785
|
getLocalStorage,
|
|
4255
4786
|
getLongTaskObserver,
|
|
4256
4787
|
getMemoryCacheSize,
|
|
4257
4788
|
getMemorySampler,
|
|
4258
4789
|
getMountOverrides,
|
|
4259
4790
|
getOverrideSystem,
|
|
4791
|
+
getRegisteredIconKeys,
|
|
4260
4792
|
getRegistryUrl,
|
|
4261
4793
|
getSessionManager,
|
|
4262
4794
|
getSessionStorage,
|
|
4795
|
+
getSupportedIconSets,
|
|
4263
4796
|
getTailwind,
|
|
4264
4797
|
getUrlInfo,
|
|
4265
4798
|
getValueByPath,
|
|
@@ -4273,12 +4806,18 @@ export {
|
|
|
4273
4806
|
injectTailwind,
|
|
4274
4807
|
invalidateCache,
|
|
4275
4808
|
isComponentAvailable,
|
|
4809
|
+
isIconCdnEnabled,
|
|
4810
|
+
isIconRegistered,
|
|
4811
|
+
isIconSetSupported,
|
|
4276
4812
|
isTailwindLoaded,
|
|
4277
4813
|
isValidSpecifier,
|
|
4278
4814
|
navigateTo,
|
|
4279
4815
|
parseVersion,
|
|
4280
4816
|
prefetchComponents,
|
|
4817
|
+
preloadIcons,
|
|
4281
4818
|
processStyles,
|
|
4819
|
+
registerIcon,
|
|
4820
|
+
registerIcons,
|
|
4282
4821
|
removeClass,
|
|
4283
4822
|
removeCustomStyles,
|
|
4284
4823
|
removeLocalStorage,
|
|
@@ -4286,6 +4825,7 @@ export {
|
|
|
4286
4825
|
removeTailwind,
|
|
4287
4826
|
render,
|
|
4288
4827
|
renderDynamicList,
|
|
4828
|
+
renderIcon,
|
|
4289
4829
|
renderInShadow,
|
|
4290
4830
|
renderNode,
|
|
4291
4831
|
resetAnalytics,
|
|
@@ -4302,6 +4842,7 @@ export {
|
|
|
4302
4842
|
runAllTests,
|
|
4303
4843
|
runTestCase,
|
|
4304
4844
|
satisfiesVersion,
|
|
4845
|
+
setIconCdnEnabled,
|
|
4305
4846
|
setInCache,
|
|
4306
4847
|
setLocalStorage,
|
|
4307
4848
|
setRegistryUrl,
|