Skip to content

Commit 08e1957

Browse files
author
pipeline
committed
v31.1.17 is released
1 parent 2f52e78 commit 08e1957

File tree

358 files changed

+33521
-91628
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

358 files changed

+33521
-91628
lines changed

package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ej2-vue-samples",
3-
"version": "30.2.4",
3+
"version": "31.1.17",
44
"description": "Examples of Vue UI Components",
55
"keywords": [],
66
"dependencies": {
@@ -12,7 +12,6 @@
1212
"@syncfusion/ej2-vue-charts": "*",
1313
"@syncfusion/ej2-vue-circulargauge": "*",
1414
"@syncfusion/ej2-vue-diagrams": "*",
15-
"@syncfusion/ej2-vue-documenteditor": "*",
1615
"@syncfusion/ej2-vue-dropdowns": "*",
1716
"@syncfusion/ej2-vue-filemanager": "*",
1817
"@syncfusion/ej2-vue-gantt": "*",
@@ -27,15 +26,13 @@
2726
"@syncfusion/ej2-vue-maps": "*",
2827
"@syncfusion/ej2-vue-navigations": "*",
2928
"@syncfusion/ej2-vue-notifications": "*",
30-
"@syncfusion/ej2-vue-pdfviewer": "*",
3129
"@syncfusion/ej2-vue-pivotview": "*",
3230
"@syncfusion/ej2-vue-popups": "*",
3331
"@syncfusion/ej2-vue-querybuilder": "*",
3432
"@syncfusion/ej2-vue-ribbon": "*",
3533
"@syncfusion/ej2-vue-richtexteditor": "*",
3634
"@syncfusion/ej2-vue-schedule": "*",
3735
"@syncfusion/ej2-vue-splitbuttons": "*",
38-
"@syncfusion/ej2-vue-spreadsheet": "*",
3936
"@syncfusion/ej2-vue-treegrid": "*",
4037
"@syncfusion/ej2-vue-treemap": "*",
4138
"@syncfusion/ej2-vue-progressbar": "*",

public/index.html

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
</script>
99

1010
<!-- Google Tag Manager -->
11+
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
12+
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
13+
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
14+
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
15+
})(window,document,'script','dataLayer','GTM-P3WXFWCW');</script>
1116
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
1217
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
1318
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
@@ -23,11 +28,7 @@
2328
<link rel="manifest" href="./manifest.webmanifest">
2429
<link href="styles/bootstrap.min.css" rel="stylesheet" />
2530
<link href="https://fonts.googleapis.com/css2?family=Open+Sans&display=swap" rel="stylesheet"></link>
26-
<script>
27-
var themeName = location.hash.split('/')[1];
28-
themeName = themeName ? themeName : 'tailwind3';
29-
document.write('<link href="styles/' + (themeName.includes('bootstrap5') ? themeName.replace('bootstrap5', 'bootstrap5.3') : themeName) + '.css" rel="stylesheet" />');
30-
</script>
31+
<link id="dynamic-theme" rel="stylesheet" href="styles/tailwind3.css" />
3132
<link href="styles/index.css" rel="stylesheet" />
3233
<script type="text/javascript">
3334
if (/MSIE \d|Trident.*rv:/.test(navigator.userAgent)) {
@@ -40,6 +41,7 @@
4041
</head>
4142
<body class='e-view' aria-busy="true">
4243
<!-- Google Tag Manager (noscript) -->
44+
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-P3WXFWCW" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
4345
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-W8WD8WN" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
4446
<!-- End Google Tag Manager (noscript) -->
4547
<div hidden id="sync-analytics" data-queue="EJ2 - Vue - Demos"></div>

public/styles/common.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ span.e-input-group.e-control-wrapper.e-ddl {
8989
display: flex;
9090
font-size: 13px;
9191
font-weight: 500;
92+
color: #D1D5DB;
9293
}
9394
/*sb-icons declaration*/
9495

public/styles/themes/bootstrap5.3-dark.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,4 +288,8 @@ body.bootstrap5_3-dark,
288288

289289
.bootstrap5_3-dark .sb-desktop-setting > :nth-child(4) {
290290
padding-right: 15px;
291-
}
291+
}
292+
293+
.bootstrap5_3-dark .e-tab .e-tab-header:not(.e-vertical)::before {
294+
border-width: 0;
295+
}

public/styles/themes/tailwind3.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,6 @@
4646
color:#4B5563;
4747
}
4848

49-
.tailwind3 .sb-download-text{
50-
color: #111111;
51-
}
52-
5349
.tailwind3 .sb-left-pane .e-listview .e-list-item.e-active{
5450
background-color: #E5E7EB ;
5551
}

src/App.vue

Lines changed: 140 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
</div>
6565
<div class='sb-header-item sb-table-cell'>
6666
<div id='sb-header-text' class='e-sb-header-text'>
67-
<span class='sb-header-text-left'>Essential Studio<sup>®</sup> for </span>
67+
<span class='sb-header-text-left'>Essential Studio<sup>®</sup> UI Suite for </span>
6868
<span class='sb-header-text-right' role="button" tabindex="0">Vue</span>
6969
</div>
7070
</div>
@@ -489,6 +489,9 @@ const sampleRegex: RegExp = /#\/(([^\/]+\/)+[^\/\.]+)/;
489489
const sbArray: string[] = ['angular', 'react', 'nextjs', 'javascript', 'aspnetcore', 'aspnetmvc', 'typescript', 'blazor'];
490490
//Regex for removing hidden
491491
const reg: RegExp = /.*custom code start([\S\s]*?)custom code end.*/g;
492+
let skipReload: boolean = false; // Flag to skip reload when switching themes
493+
let isReloadingTheme = false; // Flag to indicate if the theme is being reloaded
494+
let hasHandledInitialTheme = false; // Flag to check if the initial theme has been handled
492495
let selectedTheme: string = location.hash.split('/')[1] || 'tailwind3';
493496
const themeCollection: string[] = ['material3', 'bootstrap5', 'fluent2', 'tailwind3', 'fluent2-highcontrast', 'highcontrast', 'tailwind', 'fluent'];
494497
const themesToRedirect: string[] = ['material', 'material-dark', 'bootstrap4', 'bootstrap', 'bootstrap-dark', 'fabric', 'fabric-dark'];
@@ -577,12 +580,26 @@ onBeforeMount(() => {
577580
});
578581
579582
const urlChange = async () => {
583+
584+
// Check if this is just a dark/light mode switch
585+
const currentHash = location.hash;
586+
const currentParts = currentHash.split('/');
587+
const prevParts = prev.split('/');
588+
// If only the theme part changed (index 1) but component and sample are the same, skip urlChange
589+
const isThemeOnlyChange = prevParts.length >= 3 && currentParts.length >= 3 &&
590+
currentParts[2] === prevParts[2] && // same component
591+
currentParts[3] === prevParts[3] && // same sample
592+
currentParts[1] !== prevParts[1]; // different theme
593+
if (isThemeOnlyChange) {
594+
prev = currentHash;
595+
return;
596+
}
580597
await router.isReady();
581598
sb.vars.contentTab.selectedItem = 0;
582599
updateBreadCrumb();
583600
updateDescription();
584601
updatesourceTab();
585-
};
602+
}
586603
587604
onMounted(async () => {
588605
rootEle = homeEle.value as HTMLElement;
@@ -654,8 +671,11 @@ onMounted(async () => {
654671
sidebar.appendTo('#left-sidebar');
655672
}
656673
loadJSON();
674+
const themeFromHash = location.hash.split("/")[1] || selectedTheme;
675+
selectedTheme = themeFromHash;
676+
loadTheme(selectedTheme, false); // full setup on initial load
677+
hasHandledInitialTheme = true; // prevent hashchange duplication
657678
router.afterEach(urlChange);
658-
updateBreadCrumb();
659679
updateDescription();
660680
});
661681
@@ -1047,6 +1067,7 @@ const rendersbPopup = (): void => {
10471067
else {
10481068
selectedTheme = selectedTheme.replace("-dark", "");
10491069
}
1070+
skipReload = true;
10501071
switchTheme(selectedTheme);
10511072
},
10521073
});
@@ -1260,6 +1281,8 @@ const eventBinding = (): void => {
12601281
};
12611282
const onSwitchMode = (arg: any): void => {
12621283
selectedTheme = selectedTheme.endsWith("-dark") ? selectedTheme.replace("-dark", "") : selectedTheme + "-dark";
1284+
localStorage.setItem("selectedTheme", selectedTheme);
1285+
skipReload = true; // signal that we're toggling mode, not switching base theme
12631286
switchTheme(selectedTheme);
12641287
};
12651288
const changeRtl = (args: any): void => {
@@ -1388,6 +1411,8 @@ const changeTheme = (e: MouseEvent): void => {
13881411
if ((select("#sb-icon-text") as HTMLElement).textContent === "LIGHT" && !['highcontrast', 'fluent2-highcontrast'].includes(themeName)) {
13891412
themeName += "-dark";
13901413
}
1414+
skipReload = false; // Force full reload for dropdown
1415+
isReloadingTheme = true; // flag reload to skip hashchange theme apply
13911416
switchTheme(themeName);
13921417
let imageEditorElem = document.querySelector(".e-image-editor") as HTMLElement;
13931418
if (imageEditorElem != null) {
@@ -1396,15 +1421,20 @@ const changeTheme = (e: MouseEvent): void => {
13961421
}
13971422
};
13981423
1399-
const switchTheme = (str: string): void => {
1400-
str = str.includes('_') ? str.replace('_', '.') : str;
1401-
let hash: string[] = location.hash.split('/');
1402-
if (hash[1] !== str) {
1403-
hash[1] = str;
1404-
location.hash = hash.join('/');
1405-
location.reload();
1424+
const switchTheme = (themeName: string): void => {
1425+
themeName = themeName.includes("_") ? themeName.replace("_", ".") : themeName;
1426+
const hashParts = location.hash.split("/");
1427+
hashParts[1] = themeName;
1428+
location.hash = hashParts.join("/");
1429+
if (skipReload) {
1430+
loadTheme(themeName, true); // soft switch for toggle
1431+
skipReload = false; // Reset the flag after soft switch
1432+
} else {
1433+
localStorage.setItem("selectedTheme", themeName); // ensures theme survives reload
1434+
location.reload(); // hard reload for dropdown
14061435
}
14071436
};
1437+
14081438
const setThemeModesButton = (): void => {
14091439
let themeModeText = select("#sb-icon-text") as HTMLElement;
14101440
let darkThemeIcon = select("#icon-dark") as HTMLElement;
@@ -1425,35 +1455,109 @@ const setThemeModesButton = (): void => {
14251455
mobileDarkThemeIcon.classList.add("hide");
14261456
}
14271457
};
1428-
const loadTheme = (theme: string): void => {
1429-
theme = themesToRedirect.indexOf(theme) !== -1 ? 'tailwind3': theme;
1430-
let body: HTMLElement = document.body;
1431-
if (body.classList.length > 0) {
1432-
for (let themeItem of themeCollection) {
1433-
body.classList.remove(themeItem);
1458+
const loadTheme = (theme: string, softSwitch = false): void => {
1459+
selectedTheme = theme;
1460+
theme = themesToRedirect.includes(theme) ? "tailwind3" : theme;
1461+
// Theme class resolution
1462+
const resolvedClass = theme.includes("bootstrap5")
1463+
? theme.replace("bootstrap5", "bootstrap5_3")
1464+
: theme;
1465+
const themeFile = theme.includes("bootstrap5")
1466+
? theme.replace("bootstrap5", "bootstrap5.3")
1467+
: theme;
1468+
const body = document.body;
1469+
const themePrefixes = ["tailwind3", "fluent2", "bootstrap5_3", "material3", "highcontrast"];
1470+
// Remove previous theme classes
1471+
body.className = body.className
1472+
.split(" ")
1473+
.filter(cls => !themePrefixes.some(prefix =>
1474+
cls.startsWith(prefix) || cls.startsWith(prefix + "-dark")))
1475+
.join(" ");
1476+
body.classList.add(resolvedClass);
1477+
// Update dynamic theme stylesheet
1478+
const cssLink = document.getElementById("dynamic-theme") as HTMLLinkElement;
1479+
if (cssLink) {
1480+
cssLink.href = `./styles/${themeFile}.css`;
1481+
}
1482+
// Highlight selected theme in UI
1483+
themeList?.querySelector(".active")?.classList.remove("active");
1484+
const normalized = theme.endsWith("-dark") ? theme.replace("-dark", "") : theme;
1485+
themeList?.querySelector(`#${normalized}`)?.classList.add("active");
1486+
// Handle unsupported toggle modes
1487+
const unsupported = ["highcontrast", "fluent2-highcontrast"];
1488+
const toggleBtn = select("#themeMode-switch-btn");
1489+
const modeSection = select(".sb-setting-themeModes-section");
1490+
if (unsupported.includes(selectedTheme)) {
1491+
toggleBtn?.classList.add("hide");
1492+
modeSection?.classList.add("hide");
1493+
} else {
1494+
toggleBtn?.classList.remove("hide");
1495+
modeSection?.classList.remove("hide");
1496+
}
1497+
// Ripple effect and toggle button visuals
1498+
enableRipple(selectedTheme.indexOf("material") !== -1 || !selectedTheme);
1499+
setThemeModesButton();
1500+
// Re-bind UI components only on full load
1501+
if (!softSwitch) {
1502+
renderLeftPaneComponents(); // Sidebar and left pane
1503+
rendersbPopup(); // Settings and popups
1504+
eventBinding(); // Interaction and event listeners
1505+
refreshDynamicContent(); // Update content and search
1506+
}else {
1507+
// Soft switch: only update theme and refresh samples
1508+
refreshDynamicContent();
1509+
refreshSamples();
1510+
}
1511+
// UI layout cleanup
1512+
setTimeout(() => {
1513+
select(".sb-loading-overlay")?.classList.add("hide");
1514+
window.dispatchEvent(new Event("resize"));
1515+
}, 500);
1516+
};
1517+
1518+
// data visualization components
1519+
const doControls: string[] = [
1520+
"chart", "three-dimension-chart", "circular-3d-chart", "stock-chart", "arc-gauge", "circular-gauge",
1521+
"diagram", "heatmap", "linear-gauge", "maps", "range-navigator", "smith-chart",
1522+
"barcode", "sparkline", "treemap", "bullet-chart","kanban"
1523+
];
1524+
1525+
// components rerendering for every dark/light toggle
1526+
const refreshSamples = () => {
1527+
const currentControl = location.hash.split('/')[2];
1528+
if (doControls.includes(currentControl)) {
1529+
const demo = document.querySelector('.sb-demo-section');
1530+
if (demo) {
1531+
const controls = demo.getElementsByClassName('e-control e-lib');
1532+
for (let i = 0; i < controls.length; i++) {
1533+
const instance = (controls[i] as any).ej2_instances;
1534+
if (instance?.[0]?.refresh instanceof Function) {
1535+
instance[0].refresh();
14341536
}
1537+
}
14351538
}
1436-
body.classList.add(theme.includes('bootstrap5') ? theme.replace('bootstrap5', 'bootstrap5_3') : theme);
1437-
themeList.querySelector(".active").classList.remove("active");
1438-
if (theme.endsWith("-dark")) {
1439-
theme = theme.replace("-dark", "");
1440-
}
1441-
else if (["highcontrast", "fluent2-highcontrast"].includes(selectedTheme)) {
1442-
(select("#themeMode-switch-btn") as HTMLElement).classList.add("hide");
1443-
(select(".sb-setting-themeModes-section") as HTMLElement).classList.add("hide");
1444-
}
1445-
themeList.querySelector("#" + theme)?.classList.add("active");
1446-
setThemeModesButton();
1447-
renderLeftPaneComponents();
1448-
rendersbPopup();
1449-
eventBinding();
1450-
sampleArray();
1451-
updatesourceTab();
1452-
(elasticlunr as any).clearStopWords();
1453-
searchInstance = (elasticlunr as any).Index.load(searchJson);
1454-
setTimeout(() => { window.dispatchEvent(new Event('resize')); }, 500);
1539+
}
1540+
};
1541+
1542+
const refreshDynamicContent = () => {
1543+
updateBreadCrumb();
1544+
sampleArray();
1545+
updatesourceTab();
1546+
searchInstance = (elasticlunr as any).Index.load(searchJson);
1547+
(elasticlunr as any).clearStopWords();
14551548
};
14561549
1550+
window.addEventListener("hashchange", () => {
1551+
if (isReloadingTheme || !hasHandledInitialTheme) return;
1552+
1553+
const hashTheme = location.hash.split("/")[1];
1554+
if (hashTheme && hashTheme !== selectedTheme) {
1555+
selectedTheme = hashTheme;
1556+
localStorage.setItem("selectedTheme", selectedTheme);
1557+
loadTheme(selectedTheme, true); // soft switch
1558+
}
1559+
});
1560+
14571561
const setMouseOrTouch = (e: MouseEvent): void => {
14581562
let ele: HTMLElement = <any>closest(<any>e.target, '.sb-responsive-items');
14591563
let switchType: string = ele.id;
@@ -1936,9 +2040,8 @@ const loadJSON = (): void => {
19362040
}
19372041
overlay();
19382042
changeMouseOrTouch(switchText);
1939-
localStorage.removeItem('ej2-switch');
2043+
//localStorage.removeItem('ej2-switch');
19402044
enableRipple(selectedTheme.indexOf('material') !== -1 || !selectedTheme);
1941-
loadTheme(selectedTheme);
19422045
};
19432046
19442047
</script>

0 commit comments

Comments
 (0)