23 Commits

Author SHA1 Message Date
Cagatay Civici ec6b6ef53a set version as 5 2026-02-02 21:49:03 +03:00
tugcekucukoglu 76a3b60333 cchore: update PrimeVue version 2026-01-30 17:51:18 +03:00
tugcekucukoglu 410c08d693 chore: layout config updates 2025-12-25 10:03:32 +03:00
tugcekucukoglu a4b2c96b0d submodule added 2025-12-25 09:09:55 +03:00
tugcekucukoglu a47200fdf7 remove assets 2025-12-25 09:07:45 +03:00
tugcekucukoglu 7c32ae1f6f chore: remove sass warnings 2025-12-09 14:05:01 +03:00
Atakan db99863fac update transitions & dependencies 2025-12-08 14:36:22 +03:00
Atakan c2ef85fcab update for tw v4 2025-12-04 12:26:25 +03:00
Atakan deea8861f8 update 2025-11-18 05:16:32 +03:00
Atakan 319f976d2b add blocks 2025-11-08 17:37:47 +03:00
Atakan 13a50a3af3 update tw 2025-11-08 17:35:43 +03:00
Cagatay Civici 23bcf922ab Set version 2025-02-26 17:40:28 +03:00
tugcekucukoglu e1ecd23050 Update package-lock.json 2025-02-25 15:31:36 +03:00
tugcekucukoglu 2f5b71a3eb Use @primeuix/themes instead of @primevue/themes 2025-02-25 15:28:20 +03:00
tugcekucukoglu 22ba8601f3 Nora added 2025-02-18 16:01:41 +03:00
tugcekucukoglu 4a8745b497 Update FooterWidget.vue 2025-02-18 16:01:32 +03:00
tugcekucukoglu d5ec7dba67 Update package-lock.json 2025-02-18 16:01:27 +03:00
tugcekucukoglu 7c54176132 Update OverlayDoc.vue 2025-02-18 16:01:24 +03:00
tugcekucukoglu 03ef1236f0 Fixed #62 2025-02-18 16:01:19 +03:00
tugcekucukoglu 7ac2ba9013 Fixed #55 2025-02-18 15:51:13 +03:00
tugcekucukoglu 5f951584c7 Add Sakai-Vue to a Nuxt Project section added 2025-01-20 14:52:48 +03:00
tugcekucukoglu 817ffa0d62 Flag fixes 2025-01-16 13:51:47 +03:00
tugcekucukoglu 9585f62298 Update MiscDoc.vue 2025-01-16 13:03:27 +03:00
60 changed files with 3489 additions and 2406 deletions
+3
View File
@@ -0,0 +1,3 @@
[submodule "src/assets"]
path = src/assets
url = https://github.com/primefaces/sakai-assets.git
+6
View File
@@ -1,5 +1,11 @@
# Changelog
## 4.3.0 (2025-02-26)
**Implemented New Features and Enhancements**
- Update PrimeVue version
## 4.2.0 (2024-12-09)
**Implemented New Features and Enhancements**
+1781 -1412
View File
File diff suppressed because it is too large Load Diff
+7 -8
View File
@@ -1,6 +1,6 @@
{
"name": "sakai-vue",
"version": "4.2.0",
"version": "5.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
@@ -8,26 +8,25 @@
"lint": "eslint --fix . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
},
"dependencies": {
"@primevue/themes": "^4.2.4",
"@primeuix/themes": "^2.0.0",
"chart.js": "3.3.2",
"primeicons": "^7.0.0",
"primevue": "^4.2.4",
"primevue": "^4.5.4",
"tailwindcss-primeui": "^0.6.0",
"vue": "^3.4.34",
"vue-router": "^4.4.0"
},
"devDependencies": {
"@primevue/auto-import-resolver": "^4.2.4",
"@primevue/auto-import-resolver": "^4.3.1",
"@rushstack/eslint-patch": "^1.8.0",
"@tailwindcss/vite": "^4.1.17",
"@vitejs/plugin-vue": "^5.0.5",
"@vue/eslint-config-prettier": "^9.0.0",
"autoprefixer": "^10.4.19",
"eslint": "^8.57.0",
"eslint-plugin-vue": "^9.23.0",
"postcss": "^8.4.40",
"prettier": "^3.2.5",
"sass": "^1.55.0",
"tailwindcss": "^3.4.6",
"tailwindcss-primeui": "^0.3.2",
"tailwindcss": "^4.1.17",
"unplugin-vue-components": "^0.27.3",
"vite": "^5.3.1"
}
-6
View File
@@ -1,6 +0,0 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Submodule
+1
Submodule src/assets added at eaa70ece4c
-17
View File
@@ -1,17 +0,0 @@
pre.app-code {
background-color: var(--code-background);
margin: 0 0 1rem 0;
padding: 0;
border-radius: var(--content-border-radius);
overflow: auto;
code {
color: var(--code-color);
padding: 1rem;
margin: 0;
line-height: 1.5;
display: block;
font-weight: semibold;
font-family: monaco, Consolas, monospace;
}
}
-2
View File
@@ -1,2 +0,0 @@
@use './code.scss';
@import './flags/flags.css';
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

-23
View File
@@ -1,23 +0,0 @@
html {
height: 100%;
font-size: 14px;
}
body {
font-family: 'Lato', sans-serif;
color: var(--text-color);
background-color: var(--surface-ground);
margin: 0;
padding: 0;
min-height: 100%;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
text-decoration: none;
}
.layout-wrapper {
min-height: 100vh;
}
-8
View File
@@ -1,8 +0,0 @@
.layout-footer {
display: flex;
align-items: center;
justify-content: center;
padding: 1rem 0 1rem 0;
gap: 0.5rem;
border-top: 1px solid var(--surface-border);
}
-13
View File
@@ -1,13 +0,0 @@
.layout-main-container {
display: flex;
flex-direction: column;
min-height: 100vh;
justify-content: space-between;
padding: 6rem 2rem 0 2rem;
transition: margin-left var(--layout-section-transition-duration);
}
.layout-main {
flex: 1 1 auto;
padding-bottom: 2rem;
}
-160
View File
@@ -1,160 +0,0 @@
@use 'mixins' as *;
.layout-sidebar {
position: fixed;
width: 20rem;
height: calc(100vh - 8rem);
z-index: 999;
overflow-y: auto;
user-select: none;
top: 6rem;
left: 2rem;
transition:
transform var(--layout-section-transition-duration),
left var(--layout-section-transition-duration);
background-color: var(--surface-overlay);
border-radius: var(--content-border-radius);
padding: 0.5rem 1.5rem;
}
.layout-menu {
margin: 0;
padding: 0;
list-style-type: none;
.layout-root-menuitem {
> .layout-menuitem-root-text {
font-size: 0.857rem;
text-transform: uppercase;
font-weight: 700;
color: var(--text-color);
margin: 0.75rem 0;
}
> a {
display: none;
}
}
a {
user-select: none;
&.active-menuitem {
> .layout-submenu-toggler {
transform: rotate(-180deg);
}
}
}
li.active-menuitem {
> a {
.layout-submenu-toggler {
transform: rotate(-180deg);
}
}
}
ul {
margin: 0;
padding: 0;
list-style-type: none;
a {
display: flex;
align-items: center;
position: relative;
outline: 0 none;
color: var(--text-color);
cursor: pointer;
padding: 0.75rem 1rem;
border-radius: var(--content-border-radius);
transition:
background-color var(--element-transition-duration),
box-shadow var(--element-transition-duration);
.layout-menuitem-icon {
margin-right: 0.5rem;
}
.layout-submenu-toggler {
font-size: 75%;
margin-left: auto;
transition: transform var(--element-transition-duration);
}
&.active-route {
font-weight: 700;
color: var(--primary-color);
}
&:hover {
background-color: var(--surface-hover);
}
&:focus {
@include focused-inset();
}
}
ul {
overflow: hidden;
border-radius: var(--content-border-radius);
li {
a {
margin-left: 1rem;
}
li {
a {
margin-left: 2rem;
}
li {
a {
margin-left: 2.5rem;
}
li {
a {
margin-left: 3rem;
}
li {
a {
margin-left: 3.5rem;
}
li {
a {
margin-left: 4rem;
}
}
}
}
}
}
}
}
}
}
.layout-submenu-enter-from,
.layout-submenu-leave-to {
max-height: 0;
}
.layout-submenu-enter-to,
.layout-submenu-leave-from {
max-height: 1000px;
}
.layout-submenu-leave-active {
overflow: hidden;
transition: max-height 0.45s cubic-bezier(0, 1, 0, 1);
}
.layout-submenu-enter-active {
overflow: hidden;
transition: max-height 1s ease-in-out;
}
-15
View File
@@ -1,15 +0,0 @@
@mixin focused() {
outline-width: var(--focus-ring-width);
outline-style: var(--focus-ring-style);
outline-color: var(--focus-ring-color);
outline-offset: var(--focus-ring-offset);
box-shadow: var(--focus-ring-shadow);
transition:
box-shadow var(--transition-duration),
outline-color var(--transition-duration);
}
@mixin focused-inset() {
outline-offset: -1px;
box-shadow: inset var(--focus-ring-shadow);
}
-47
View File
@@ -1,47 +0,0 @@
.preloader {
position: fixed;
z-index: 999999;
background: #edf1f5;
width: 100%;
height: 100%;
}
.preloader-content {
border: 0 solid transparent;
border-radius: 50%;
width: 150px;
height: 150px;
position: absolute;
top: calc(50vh - 75px);
left: calc(50vw - 75px);
}
.preloader-content:before, .preloader-content:after{
content: '';
border: 1em solid var(--primary-color);
border-radius: 50%;
width: inherit;
height: inherit;
position: absolute;
top: 0;
left: 0;
animation: loader 2s linear infinite;
opacity: 0;
}
.preloader-content:before{
animation-delay: 0.5s;
}
@keyframes loader{
0%{
transform: scale(0);
opacity: 0;
}
50%{
opacity: 1;
}
100%{
transform: scale(1);
opacity: 0;
}
}
-110
View File
@@ -1,110 +0,0 @@
@media screen and (min-width: 1960px) {
.layout-main,
.landing-wrapper {
width: 1504px;
margin-left: auto !important;
margin-right: auto !important;
}
}
@media (min-width: 992px) {
.layout-wrapper {
&.layout-overlay {
.layout-main-container {
margin-left: 0;
padding-left: 2rem;
}
.layout-sidebar {
transform: translateX(-100%);
left: 0;
top: 0;
height: 100vh;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-right: 1px solid var(--surface-border);
transition:
transform 0.4s cubic-bezier(0.05, 0.74, 0.2, 0.99),
left 0.4s cubic-bezier(0.05, 0.74, 0.2, 0.99);
box-shadow:
0px 3px 5px rgba(0, 0, 0, 0.02),
0px 0px 2px rgba(0, 0, 0, 0.05),
0px 1px 4px rgba(0, 0, 0, 0.08);
}
&.layout-overlay-active {
.layout-sidebar {
transform: translateX(0);
}
}
}
&.layout-static {
.layout-main-container {
margin-left: 22rem;
}
&.layout-static-inactive {
.layout-sidebar {
transform: translateX(-100%);
left: 0;
}
.layout-main-container {
margin-left: 0;
padding-left: 2rem;
}
}
}
.layout-mask {
display: none;
}
}
}
@media (max-width: 991px) {
.blocked-scroll {
overflow: hidden;
}
.layout-wrapper {
.layout-main-container {
margin-left: 0;
padding-left: 2rem;
}
.layout-sidebar {
transform: translateX(-100%);
left: 0;
top: 0;
height: 100vh;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
transition:
transform 0.4s cubic-bezier(0.05, 0.74, 0.2, 0.99),
left 0.4s cubic-bezier(0.05, 0.74, 0.2, 0.99);
}
.layout-mask {
display: none;
position: fixed;
top: 0;
left: 0;
z-index: 998;
width: 100%;
height: 100%;
background-color: var(--maskbg);
}
&.layout-mobile-active {
.layout-sidebar {
transform: translateX(0);
}
.layout-mask {
display: block;
}
}
}
}
-202
View File
@@ -1,202 +0,0 @@
@use 'mixins' as *;
.layout-topbar {
position: fixed;
height: 4rem;
z-index: 997;
left: 0;
top: 0;
width: 100%;
padding: 0 2rem;
background-color: var(--surface-card);
transition: left var(--layout-section-transition-duration);
display: flex;
align-items: center;
.layout-topbar-logo-container {
width: 20rem;
display: flex;
align-items: center;
}
.layout-topbar-logo {
display: inline-flex;
align-items: center;
font-size: 1.5rem;
border-radius: var(--content-border-radius);
color: var(--text-color);
font-weight: 500;
gap: 0.5rem;
svg {
width: 3rem;
}
&:focus-visible {
@include focused();
}
}
.layout-topbar-action {
display: inline-flex;
justify-content: center;
align-items: center;
color: var(--text-color-secondary);
border-radius: 50%;
width: 2.5rem;
height: 2.5rem;
color: var(--text-color);
transition: background-color var(--element-transition-duration);
cursor: pointer;
&:hover {
background-color: var(--surface-hover);
}
&:focus-visible {
@include focused();
}
i {
font-size: 1.25rem;
}
span {
font-size: 1rem;
display: none;
}
&.layout-topbar-action-highlight {
background-color: var(--primary-color);
color: var(--primary-contrast-color);
}
}
.layout-menu-button {
margin-right: 0.5rem;
}
.layout-topbar-menu-button {
display: none;
}
.layout-topbar-actions {
margin-left: auto;
display: flex;
gap: 1rem;
}
.layout-topbar-menu-content {
display: flex;
gap: 1rem;
}
.layout-config-menu {
display: flex;
gap: 1rem;
}
}
@media (max-width: 991px) {
.layout-topbar {
padding: 0 2rem;
.layout-topbar-logo-container {
width: auto;
}
.layout-menu-button {
margin-left: 0;
margin-right: 0.5rem;
}
.layout-topbar-menu-button {
display: inline-flex;
}
.layout-topbar-menu {
position: absolute;
background-color: var(--surface-overlay);
transform-origin: top;
box-shadow:
0px 3px 5px rgba(0, 0, 0, 0.02),
0px 0px 2px rgba(0, 0, 0, 0.05),
0px 1px 4px rgba(0, 0, 0, 0.08);
border-radius: var(--content-border-radius);
padding: 1rem;
right: 2rem;
top: 4rem;
min-width: 15rem;
border: 1px solid var(--surface-border);
.layout-topbar-menu-content {
gap: 0.5rem;
}
.layout-topbar-action {
display: flex;
width: 100%;
height: auto;
justify-content: flex-start;
border-radius: var(--content-border-radius);
padding: 0.5rem 1rem;
i {
font-size: 1rem;
margin-right: 0.5rem;
}
span {
font-weight: medium;
display: block;
}
}
}
.layout-topbar-menu-content {
flex-direction: column;
}
}
}
.config-panel {
.config-panel-label {
font-size: 0.875rem;
color: var(--text-secondary-color);
font-weight: 600;
line-height: 1;
}
.config-panel-colors {
> div {
padding-top: 0.5rem;
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
justify-content: space-between;
button {
border: none;
width: 1.25rem;
height: 1.25rem;
border-radius: 50%;
padding: 0;
cursor: pointer;
outline-color: transparent;
outline-width: 2px;
outline-style: solid;
outline-offset: 1px;
&.active-color {
outline-color: var(--primary-color);
}
}
}
}
.config-panel-settings {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
}
-68
View File
@@ -1,68 +0,0 @@
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 1.5rem 0 1rem 0;
font-family: inherit;
font-weight: 700;
line-height: 1.5;
color: var(--text-color);
&:first-child {
margin-top: 0;
}
}
h1 {
font-size: 2.5rem;
}
h2 {
font-size: 2rem;
}
h3 {
font-size: 1.75rem;
}
h4 {
font-size: 1.5rem;
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
mark {
background: #fff8e1;
padding: 0.25rem 0.4rem;
border-radius: var(--content-border-radius);
font-family: monospace;
}
blockquote {
margin: 1rem 0;
padding: 0 2rem;
border-left: 4px solid #90a4ae;
}
hr {
border-top: solid var(--surface-border);
border-width: 1px 0 0 0;
margin: 1rem 0;
}
p {
margin: 0 0 1rem 0;
line-height: 1.5;
&:last-child {
margin-bottom: 0;
}
}
-25
View File
@@ -1,25 +0,0 @@
/* Utils */
.clearfix:after {
content: ' ';
display: block;
clear: both;
}
.card {
background: var(--surface-card);
padding: 2rem;
margin-bottom: 2rem;
border-radius: var(--content-border-radius);
&:last-child {
margin-bottom: 0;
}
}
.p-toast {
&.p-toast-top-right,
&.p-toast-top-left,
&.p-toast-top-center {
top: 100px;
}
}
-13
View File
@@ -1,13 +0,0 @@
@use './variables/_common';
@use './variables/_light';
@use './variables/_dark';
@use './_mixins';
@use './_preloading';
@use './_core';
@use './_main';
@use './_topbar';
@use './_menu';
@use './_footer';
@use './_responsive';
@use './_utils';
@use './_typography';
-20
View File
@@ -1,20 +0,0 @@
:root {
--primary-color: var(--p-primary-color);
--primary-contrast-color: var(--p-primary-contrast-color);
--text-color: var(--p-text-color);
--text-color-secondary: var(--p-text-muted-color);
--surface-border: var(--p-content-border-color);
--surface-card: var(--p-content-background);
--surface-hover: var(--p-content-hover-background);
--surface-overlay: var(--p-overlay-popover-background);
--transition-duration: var(--p-transition-duration);
--maskbg: var(--p-mask-background);
--content-border-radius: var(--p-content-border-radius);
--layout-section-transition-duration: 0.2s;
--element-transition-duration: var(--p-transition-duration);
--focus-ring-width: var(--p-focus-ring-width);
--focus-ring-style: var(--p-focus-ring-style);
--focus-ring-color: var(--p-focus-ring-color);
--focus-ring-offset: var(--p-focus-ring-offset);
--focus-ring-shadow: var(--p-focus-ring-shadow);
}
-5
View File
@@ -1,5 +0,0 @@
:root[class*='app-dark'] {
--surface-ground: var(--p-surface-950);
--code-background: var(--p-surface-800);
--code-color: var(--p-surface-100);
}
-5
View File
@@ -1,5 +0,0 @@
:root {
--surface-ground: var(--p-surface-100);
--code-background: var(--p-surface-900);
--code-color: var(--p-surface-200);
}
-5
View File
@@ -1,5 +0,0 @@
/* You can add global styles to this file, and also import other style files */
@use '@/assets/layout/layout.scss';
@use 'primeicons/primeicons.css';
@use '@/assets/demo/demo.scss';
-3
View File
@@ -1,3 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
+156
View File
@@ -0,0 +1,156 @@
<script setup>
import { reactive, ref } from 'vue';
const props = defineProps({
header: {
type: String,
default: null
},
code: null,
recent: {
type: Boolean,
default: false
},
free: {
type: Boolean,
default: false
},
containerClass: null,
previewStyle: null
});
const BlockView = reactive({
PREVIEW: 0,
CODE: 1
});
const blockView = ref(0);
const codeCopied = ref(false);
const codeCopyLoading = ref(false);
function activateView(event, blockViewValue) {
blockView.value = blockViewValue;
event.preventDefault();
}
async function copyCode(event) {
if (codeCopied.value || codeCopyLoading.value) return;
codeCopyLoading.value = true;
event.preventDefault();
try {
await navigator.clipboard.writeText(props.code);
codeCopyLoading.value = false;
codeCopied.value = true;
setTimeout(() => {
codeCopied.value = false;
}, 2000);
} catch (err) {
console.error('Clipboard write failed:', err);
codeCopyLoading.value = false;
}
}
</script>
<template>
<div class="mb-16 overflow-hidden">
<div class="flex flex-col lg:flex-row justify-between py-4 gap-4 lg:gap-2 px-0!">
<div class="flex items-center gap-2">
<span class="font-medium text-xl">{{ header }}</span>
<span v-if="free" class="flex items-center justify-center px-1.5 py-1 w-fit bg-emerald-500 text-emerald-100 dark:bg-emerald-400 dark:text-emerald-800 rounded-md leading-none! text-xs md:text-sm">Free</span>
</div>
<div class="flex items-center gap-2">
<!-- Preview/Code Toggle -->
<div class="inline-flex border border-surface-200 dark:border-surface-700 rounded-2xl overflow-hidden min-h-10">
<button
:class="[
'min-w-28 flex items-center gap-1 justify-center px-4 py-2 rounded-2xl transition-all duration-200 font-medium cursor-pointer ',
blockView === BlockView.CODE ? 'bg-primary text-primary-contrast ' : 'text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-surface-0'
]"
@click="activateView($event, BlockView.CODE)"
>
<span>Code</span>
</button>
<button
:class="[
'min-w-28 flex items-center gap-1 justify-center px-4 py-2 rounded-2xl transition-all duration-200 font-medium cursor-pointer',
blockView === BlockView.PREVIEW ? 'bg-primary text-primary-contrast ' : 'text-surface-600 dark:text-surface-400 hover:text-surface-900 dark:hover:text-surface-0'
]"
@click="activateView($event, BlockView.PREVIEW)"
>
<span>Preview</span>
</button>
</div>
<!-- Separator -->
<div class="h-6 w-px bg-surface-200 dark:bg-surface-700 hidden lg:block"></div>
<!-- Animated Copy Button -->
<div class="flex items-center gap-2 grow lg:grow-0 justify-end lg:justify-start">
<button
@click="copyCode($event)"
:disabled="codeCopyLoading"
class="relative w-10 h-10 border border-surface-200 dark:border-surface-700 rounded-full hover:bg-surface-100 dark:hover:bg-surface-800 transition-all focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 dark:focus-visible:ring-offset-surface-900 cursor-pointer disabled:cursor-wait"
>
<!-- Loading Spinner -->
<span :class="['absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 transition-all duration-300 leading-none', codeCopyLoading ? 'opacity-100 scale-100 z-10' : 'opacity-0 scale-50 -z-[2]']">
<i class="pi pi-spinner animate-spin text-surface-700 dark:text-surface-300" style="font-size: 1.25rem"></i>
</span>
<!-- Checkmark Icon -->
<span :class="['absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 transition-all duration-300 leading-none', codeCopied && !codeCopyLoading ? 'opacity-100 scale-100 z-10' : 'opacity-0 scale-50 -z-[2]']">
<svg class="w-5 h-5 fill-green-600 dark:fill-green-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g id="check">
<path d="M9,18.25A.74.74,0,0,1,8.47,18l-5-5A.75.75,0,1,1,4.53,12L9,16.44,19.47,6A.75.75,0,0,1,20.53,7l-11,11A.74.74,0,0,1,9,18.25Z"></path>
</g>
</svg>
</span>
<!-- Copy Icon -->
<span :class="['absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 transition-all duration-300 leading-none', !codeCopied && !codeCopyLoading ? 'opacity-100 scale-100 z-10' : 'opacity-0 scale-50 -z-[2]']">
<svg class="w-5 h-5 fill-surface-700 dark:fill-surface-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g id="clone">
<path
d="M14,16.75H6A2.75,2.75,0,0,1,3.25,14V6A2.75,2.75,0,0,1,6,3.25h8A2.75,2.75,0,0,1,16.75,6v8A2.75,2.75,0,0,1,14,16.75Zm-8-12A1.25,1.25,0,0,0,4.75,6v8A1.25,1.25,0,0,0,6,15.25h8A1.25,1.25,0,0,0,15.25,14V6A1.25,1.25,0,0,0,14,4.75Z"
></path>
<path d="M18,20.75H10A2.75,2.75,0,0,1,7.25,18V16h1.5v2A1.25,1.25,0,0,0,10,19.25h8A1.25,1.25,0,0,0,19.25,18V10A1.25,1.25,0,0,0,18,8.75H16V7.25h2A2.75,2.75,0,0,1,20.75,10v8A2.75,2.75,0,0,1,18,20.75Z"></path>
</g>
</svg>
</span>
</button>
</div>
</div>
</div>
<div class="p-0 border border-surface-200 dark:border-surface-700 rounded-xl overflow-hidden">
<div :class="containerClass" :style="previewStyle" v-if="blockView == BlockView.PREVIEW">
<slot />
</div>
<div v-if="blockView === BlockView.CODE">
<pre class="app-code"><code>{{code}}</code></pre>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
pre {
border: 0 none !important;
border-radius: 0 !important;
.app-code {
background: var(--p-surface-900) !important;
margin: 0 !important;
border: 0 none !important;
&:before,
&:after {
display: none !important;
}
code {
color: var(--p-surface-50);
padding: 1rem;
line-height: 1.5;
display: block;
font-family: monaco, Consolas, monospace;
}
}
}
</style>
@@ -15,7 +15,7 @@ const items = ref([
<div class="font-semibold text-xl">Best Selling Products</div>
<div>
<Button icon="pi pi-ellipsis-v" class="p-button-text p-button-plain p-button-rounded" @click="$refs.menu.toggle($event)"></Button>
<Menu ref="menu" popup :model="items" class="!min-w-40"></Menu>
<Menu ref="menu" popup :model="items" class="min-w-40!"></Menu>
</div>
</div>
<ul class="list-none p-0 m-0">
@@ -15,7 +15,7 @@ const items = ref([
<div class="font-semibold text-xl">Notifications</div>
<div>
<Button icon="pi pi-ellipsis-v" class="p-button-text p-button-plain p-button-rounded" @click="$refs.menu.toggle($event)"></Button>
<Menu ref="menu" popup :model="items" class="!min-w-40"></Menu>
<Menu ref="menu" popup :model="items" class="min-w-40!"></Menu>
</div>
</div>
@@ -23,7 +23,7 @@ const items = ref([
<ul class="p-0 mx-0 mt-0 mb-6 list-none">
<li class="flex items-center py-2 border-b border-surface">
<div class="w-12 h-12 flex items-center justify-center bg-blue-100 dark:bg-blue-400/10 rounded-full mr-4 shrink-0">
<i class="pi pi-dollar !text-xl text-blue-500"></i>
<i class="pi pi-dollar text-xl! text-blue-500"></i>
</div>
<span class="text-surface-900 dark:text-surface-0 leading-normal"
>Richard Jones
@@ -32,7 +32,7 @@ const items = ref([
</li>
<li class="flex items-center py-2">
<div class="w-12 h-12 flex items-center justify-center bg-orange-100 dark:bg-orange-400/10 rounded-full mr-4 shrink-0">
<i class="pi pi-download !text-xl text-orange-500"></i>
<i class="pi pi-download text-xl! text-orange-500"></i>
</div>
<span class="text-surface-700 dark:text-surface-100 leading-normal">Your request for withdrawal of <span class="text-primary font-bold">$2500.00</span> has been initiated.</span>
</li>
@@ -42,7 +42,7 @@ const items = ref([
<ul class="p-0 m-0 list-none mb-6">
<li class="flex items-center py-2 border-b border-surface">
<div class="w-12 h-12 flex items-center justify-center bg-blue-100 dark:bg-blue-400/10 rounded-full mr-4 shrink-0">
<i class="pi pi-dollar !text-xl text-blue-500"></i>
<i class="pi pi-dollar text-xl! text-blue-500"></i>
</div>
<span class="text-surface-900 dark:text-surface-0 leading-normal"
>Keyser Wick
@@ -51,7 +51,7 @@ const items = ref([
</li>
<li class="flex items-center py-2 border-b border-surface">
<div class="w-12 h-12 flex items-center justify-center bg-pink-100 dark:bg-pink-400/10 rounded-full mr-4 shrink-0">
<i class="pi pi-question !text-xl text-pink-500"></i>
<i class="pi pi-question text-xl! text-pink-500"></i>
</div>
<span class="text-surface-900 dark:text-surface-0 leading-normal"
>Jane Davis
@@ -63,13 +63,13 @@ const items = ref([
<ul class="p-0 m-0 list-none">
<li class="flex items-center py-2 border-b border-surface">
<div class="w-12 h-12 flex items-center justify-center bg-green-100 dark:bg-green-400/10 rounded-full mr-4 shrink-0">
<i class="pi pi-arrow-up !text-xl text-green-500"></i>
<i class="pi pi-arrow-up text-xl! text-green-500"></i>
</div>
<span class="text-surface-900 dark:text-surface-0 leading-normal">Your revenue has increased by <span class="text-primary font-bold">%25</span>.</span>
</li>
<li class="flex items-center py-2 border-b border-surface">
<div class="w-12 h-12 flex items-center justify-center bg-purple-100 dark:bg-purple-400/10 rounded-full mr-4 shrink-0">
<i class="pi pi-heart !text-xl text-purple-500"></i>
<i class="pi pi-heart text-xl! text-purple-500"></i>
</div>
<span class="text-surface-900 dark:text-surface-0 leading-normal"><span class="text-primary font-bold">12</span> users have added your products to their wishlist.</span>
</li>
@@ -2,7 +2,7 @@
import { useLayout } from '@/layout/composables/layout';
import { onMounted, ref, watch } from 'vue';
const { getPrimary, getSurface, isDarkTheme } = useLayout();
const { layoutConfig, isDarkTheme } = useLayout();
const chartData = ref(null);
const chartOptions = ref(null);
@@ -77,7 +77,7 @@ function setChartOptions() {
};
}
watch([getPrimary, getSurface, isDarkTheme], () => {
watch([() => layoutConfig.primary, () => layoutConfig.surface, isDarkTheme], () => {
chartData.value = setChartData();
chartOptions.value = setChartOptions();
});
+4 -4
View File
@@ -7,7 +7,7 @@
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">152</div>
</div>
<div class="flex items-center justify-center bg-blue-100 dark:bg-blue-400/10 rounded-border" style="width: 2.5rem; height: 2.5rem">
<i class="pi pi-shopping-cart text-blue-500 !text-xl"></i>
<i class="pi pi-shopping-cart text-blue-500 text-xl!"></i>
</div>
</div>
<span class="text-primary font-medium">24 new </span>
@@ -22,7 +22,7 @@
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">$2.100</div>
</div>
<div class="flex items-center justify-center bg-orange-100 dark:bg-orange-400/10 rounded-border" style="width: 2.5rem; height: 2.5rem">
<i class="pi pi-dollar text-orange-500 !text-xl"></i>
<i class="pi pi-dollar text-orange-500 text-xl!"></i>
</div>
</div>
<span class="text-primary font-medium">%52+ </span>
@@ -37,7 +37,7 @@
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">28441</div>
</div>
<div class="flex items-center justify-center bg-cyan-100 dark:bg-cyan-400/10 rounded-border" style="width: 2.5rem; height: 2.5rem">
<i class="pi pi-users text-cyan-500 !text-xl"></i>
<i class="pi pi-users text-cyan-500 text-xl!"></i>
</div>
</div>
<span class="text-primary font-medium">520 </span>
@@ -52,7 +52,7 @@
<div class="text-surface-900 dark:text-surface-0 font-medium text-xl">152 Unread</div>
</div>
<div class="flex items-center justify-center bg-purple-100 dark:bg-purple-400/10 rounded-border" style="width: 2.5rem; height: 2.5rem">
<i class="pi pi-comment text-purple-500 !text-xl"></i>
<i class="pi pi-comment text-purple-500 text-xl!"></i>
</div>
</div>
<span class="text-primary font-medium">85 </span>
+9 -9
View File
@@ -10,7 +10,7 @@
<div style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(253, 228, 165, 0.2), rgba(187, 199, 205, 0.2)), linear-gradient(180deg, rgba(253, 228, 165, 0.2), rgba(187, 199, 205, 0.2))">
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-yellow-200 mb-4" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
<i class="pi pi-fw pi-users !text-2xl text-yellow-700"></i>
<i class="pi pi-fw pi-users text-2xl! text-yellow-700"></i>
</div>
<h5 class="mb-2 text-surface-900 dark:text-surface-0">Easy to Use</h5>
<span class="text-surface-600 dark:text-surface-200">Posuere morbi leo urna molestie.</span>
@@ -22,7 +22,7 @@
<div style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(145, 226, 237, 0.2), rgba(251, 199, 145, 0.2)), linear-gradient(180deg, rgba(253, 228, 165, 0.2), rgba(172, 180, 223, 0.2))">
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-cyan-200 mb-4" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
<i class="pi pi-fw pi-palette !text-2xl text-cyan-700"></i>
<i class="pi pi-fw pi-palette text-2xl! text-cyan-700"></i>
</div>
<h5 class="mb-2 text-surface-900 dark:text-surface-0">Fresh Design</h5>
<span class="text-surface-600 dark:text-surface-200">Semper risus in hendrerit.</span>
@@ -34,7 +34,7 @@
<div style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(145, 226, 237, 0.2), rgba(172, 180, 223, 0.2)), linear-gradient(180deg, rgba(172, 180, 223, 0.2), rgba(246, 158, 188, 0.2))">
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-indigo-200" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
<i class="pi pi-fw pi-map !text-2xl text-indigo-700"></i>
<i class="pi pi-fw pi-map text-2xl! text-indigo-700"></i>
</div>
<div class="mt-6 mb-1 text-surface-900 dark:text-surface-0 text-xl font-semibold">Well Documented</div>
<span class="text-surface-600 dark:text-surface-200">Non arcu risus quis varius quam quisque.</span>
@@ -46,7 +46,7 @@
<div style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(187, 199, 205, 0.2), rgba(251, 199, 145, 0.2)), linear-gradient(180deg, rgba(253, 228, 165, 0.2), rgba(145, 210, 204, 0.2))">
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-slate-200 mb-4" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
<i class="pi pi-fw pi-id-card !text-2xl text-slate-700"></i>
<i class="pi pi-fw pi-id-card text-2xl! text-slate-700"></i>
</div>
<div class="mt-6 mb-1 text-surface-900 dark:text-surface-0 text-xl font-semibold">Responsive Layout</div>
<span class="text-surface-600 dark:text-surface-200">Nulla malesuada pellentesque elit.</span>
@@ -58,7 +58,7 @@
<div style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(187, 199, 205, 0.2), rgba(246, 158, 188, 0.2)), linear-gradient(180deg, rgba(145, 226, 237, 0.2), rgba(160, 210, 250, 0.2))">
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-orange-200 mb-4" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
<i class="pi pi-fw pi-star !text-2xl text-orange-700"></i>
<i class="pi pi-fw pi-star text-2xl! text-orange-700"></i>
</div>
<div class="mt-6 mb-1 text-surface-900 dark:text-surface-0 text-xl font-semibold">Clean Code</div>
<span class="text-surface-600 dark:text-surface-200">Condimentum lacinia quis vel eros.</span>
@@ -70,7 +70,7 @@
<div style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(251, 199, 145, 0.2), rgba(246, 158, 188, 0.2)), linear-gradient(180deg, rgba(172, 180, 223, 0.2), rgba(212, 162, 221, 0.2))">
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-pink-200 mb-4" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
<i class="pi pi-fw pi-moon !text-2xl text-pink-700"></i>
<i class="pi pi-fw pi-moon text-2xl! text-pink-700"></i>
</div>
<div class="mt-6 mb-1 text-surface-900 dark:text-surface-0 text-xl font-semibold">Dark Mode</div>
<span class="text-surface-600 dark:text-surface-200">Convallis tellus id interdum velit laoreet.</span>
@@ -82,7 +82,7 @@
<div style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(145, 210, 204, 0.2), rgba(160, 210, 250, 0.2)), linear-gradient(180deg, rgba(187, 199, 205, 0.2), rgba(145, 210, 204, 0.2))">
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-teal-200 mb-4" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
<i class="pi pi-fw pi-shopping-cart !text-2xl text-teal-700"></i>
<i class="pi pi-fw pi-shopping-cart text-2xl! text-teal-700"></i>
</div>
<div class="mt-6 mb-1 text-surface-900 dark:text-surface-0 text-xl font-semibold">Ready to Use</div>
<span class="text-surface-600 dark:text-surface-200">Mauris sit amet massa vitae.</span>
@@ -94,7 +94,7 @@
<div style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(145, 210, 204, 0.2), rgba(212, 162, 221, 0.2)), linear-gradient(180deg, rgba(251, 199, 145, 0.2), rgba(160, 210, 250, 0.2))">
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-blue-200 mb-4" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
<i class="pi pi-fw pi-globe !text-2xl text-blue-700"></i>
<i class="pi pi-fw pi-globe text-2xl! text-blue-700"></i>
</div>
<div class="mt-6 mb-1 text-surface-900 dark:text-surface-0 text-xl font-semibold">Modern Practices</div>
<span class="text-surface-600 dark:text-surface-200">Elementum nibh tellus molestie nunc non.</span>
@@ -106,7 +106,7 @@
<div style="height: 160px; padding: 2px; border-radius: 10px; background: linear-gradient(90deg, rgba(160, 210, 250, 0.2), rgba(212, 162, 221, 0.2)), linear-gradient(180deg, rgba(246, 158, 188, 0.2), rgba(212, 162, 221, 0.2))">
<div class="p-4 bg-surface-0 dark:bg-surface-900 h-full" style="border-radius: 8px">
<div class="flex items-center justify-center bg-purple-200 mb-4" style="width: 3.5rem; height: 3.5rem; border-radius: 10px">
<i class="pi pi-fw pi-eye !text-2xl text-purple-700"></i>
<i class="pi pi-fw pi-eye text-2xl! text-purple-700"></i>
</div>
<div class="mt-6 mb-1 text-surface-900 dark:text-surface-0 text-xl font-semibold">Privacy</div>
<span class="text-surface-600 dark:text-surface-200">Neque egestas congue quisque.</span>
+1 -1
View File
@@ -2,7 +2,7 @@
<div class="py-6 px-6 mx-0 mt-20 lg:mx-20">
<div class="grid grid-cols-12 gap-4">
<div class="col-span-12 md:col-span-2">
<a @click="smoothScroll('#home')" class="flex flex-wrap items-center justify-center md:justify-start md:mb-0 mb-4 cursor-pointer">
<a class="flex flex-wrap items-center justify-center md:justify-start md:mb-0 mb-4 cursor-pointer">
<svg viewBox="0 0 54 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-14 mr-2">
<path
fill-rule="evenodd"
+1 -1
View File
@@ -7,7 +7,7 @@
<div class="mx-6 md:mx-20 mt-0 md:mt-6">
<h1 class="text-6xl font-bold text-gray-900 leading-tight"><span class="font-light block">Eu sem integer</span>eget magna fermentum</h1>
<p class="font-normal text-2xl leading-normal md:mt-4 text-gray-700">Sed blandit libero volutpat sed cras. Fames ac turpis egestas integer. Placerat in egestas erat...</p>
<Button label="Get Started" as="router-link" to="/" rounded class="!text-xl mt-8 !px-4"></Button>
<Button label="Get Started" as="router-link" to="/" rounded class="text-xl! mt-8 px-4!"></Button>
</div>
<div class="flex justify-center md:justify-end">
<img src="/demo/images/landing/screen-1.png" alt="Hero Image" class="w-9/12 md:w-auto" />
+2 -2
View File
@@ -12,7 +12,7 @@
<div class="col-span-12 lg:col-span-6 my-auto flex flex-col lg:items-end text-center lg:text-right gap-4">
<div class="flex items-center justify-center bg-purple-200 self-center lg:self-end" style="width: 4.2rem; height: 4.2rem; border-radius: 10px">
<i class="pi pi-fw pi-mobile !text-4xl text-purple-700"></i>
<i class="pi pi-fw pi-mobile text-4xl! text-purple-700"></i>
</div>
<div class="leading-none text-surface-900 dark:text-surface-0 text-3xl font-normal">Congue Quisque Egestas</div>
<span class="text-surface-700 dark:text-surface-100 text-2xl leading-normal ml-0 md:ml-2" style="max-width: 650px"
@@ -24,7 +24,7 @@
<div class="grid grid-cols-12 gap-4 my-20 pt-2 md:pt-20">
<div class="col-span-12 lg:col-span-6 my-auto flex flex-col text-center lg:text-left lg:items-start gap-4">
<div class="flex items-center justify-center bg-yellow-200 self-center lg:self-start" style="width: 4.2rem; height: 4.2rem; border-radius: 10px">
<i class="pi pi-fw pi-desktop !text-3xl text-yellow-700"></i>
<i class="pi pi-fw pi-desktop text-3xl! text-yellow-700"></i>
</div>
<div class="leading-none text-surface-900 dark:text-surface-0 text-3xl font-normal">Celerisque Eu Ultrices</div>
<span class="text-surface-700 dark:text-surface-100 text-2xl leading-normal mr-0 md:mr-2" style="max-width: 650px"
+2 -2
View File
@@ -33,13 +33,13 @@ function smoothScroll(id) {
<span class="text-surface-900 dark:text-surface-0 font-medium text-2xl leading-normal mr-20">SAKAI</span>
</a>
<Button
class="lg:!hidden"
class="lg:hidden!"
text
severity="secondary"
rounded
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }"
>
<i class="pi pi-bars !text-2xl"></i>
<i class="pi pi-bars text-2xl!"></i>
</Button>
<div class="items-center bg-surface-0 dark:bg-surface-900 grow justify-between hidden lg:flex absolute lg:static w-full left-0 top-full px-12 lg:px-0 z-20 rounded-border">
<ul class="list-none p-0 m-0 flex lg:items-center select-none flex-col lg:flex-row cursor-pointer gap-8">
+8 -10
View File
@@ -1,15 +1,17 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { $t, updatePreset, updateSurfacePalette } from '@primevue/themes';
import Aura from '@primevue/themes/aura';
import Lara from '@primevue/themes/lara';
import { $t, updatePreset, updateSurfacePalette } from '@primeuix/themes';
import Aura from '@primeuix/themes/aura';
import Lara from '@primeuix/themes/lara';
import Nora from '@primeuix/themes/nora';
import { ref } from 'vue';
const { layoutConfig, isDarkTheme } = useLayout();
const { layoutConfig, isDarkTheme, changeMenuMode } = useLayout();
const presets = {
Aura,
Lara
Lara,
Nora
};
const preset = ref(layoutConfig.preset);
const presetOptions = ref(Object.keys(presets));
@@ -190,10 +192,6 @@ function onPresetChange() {
$t().preset(presetValue).preset(getPresetExt()).surfacePalette(surfacePalette).use({ useDefaultOptions: true });
}
function onMenuModeChange() {
layoutConfig.menuMode = menuMode.value;
}
</script>
<template>
@@ -238,7 +236,7 @@ function onMenuModeChange() {
</div>
<div class="flex flex-col gap-2">
<span class="text-sm text-muted-color font-semibold">Menu Mode</span>
<SelectButton v-model="menuMode" @change="onMenuModeChange" :options="menuModeOptions" :allowEmpty="false" optionLabel="label" optionValue="value" />
<SelectButton v-model="menuMode" @change="changeMenuMode" :options="menuModeOptions" :allowEmpty="false" optionLabel="label" optionValue="value" />
</div>
</div>
</div>
+9 -46
View File
@@ -1,71 +1,34 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { computed, ref, watch } from 'vue';
import { computed } from 'vue';
import AppFooter from './AppFooter.vue';
import AppSidebar from './AppSidebar.vue';
import AppTopbar from './AppTopbar.vue';
const { layoutConfig, layoutState, isSidebarActive } = useLayout();
const outsideClickListener = ref(null);
watch(isSidebarActive, (newVal) => {
if (newVal) {
bindOutsideClickListener();
} else {
unbindOutsideClickListener();
}
});
const { layoutConfig, layoutState, hideMobileMenu } = useLayout();
const containerClass = computed(() => {
return {
'layout-overlay': layoutConfig.menuMode === 'overlay',
'layout-static': layoutConfig.menuMode === 'static',
'layout-static-inactive': layoutState.staticMenuDesktopInactive && layoutConfig.menuMode === 'static',
'layout-overlay-active': layoutState.overlayMenuActive,
'layout-mobile-active': layoutState.staticMenuMobileActive
'layout-mobile-active': layoutState.mobileMenuActive,
'layout-static-inactive': layoutState.staticMenuInactive
};
});
function bindOutsideClickListener() {
if (!outsideClickListener.value) {
outsideClickListener.value = (event) => {
if (isOutsideClicked(event)) {
layoutState.overlayMenuActive = false;
layoutState.staticMenuMobileActive = false;
layoutState.menuHoverActive = false;
}
};
document.addEventListener('click', outsideClickListener.value);
}
}
function unbindOutsideClickListener() {
if (outsideClickListener.value) {
document.removeEventListener('click', outsideClickListener);
outsideClickListener.value = null;
}
}
function isOutsideClicked(event) {
const sidebarEl = document.querySelector('.layout-sidebar');
const topbarEl = document.querySelector('.layout-menu-button');
return !(sidebarEl.isSameNode(event.target) || sidebarEl.contains(event.target) || topbarEl.isSameNode(event.target) || topbarEl.contains(event.target));
}
</script>
<template>
<div class="layout-wrapper" :class="containerClass">
<app-topbar></app-topbar>
<app-sidebar></app-sidebar>
<AppTopbar />
<AppSidebar />
<div class="layout-main-container">
<div class="layout-main">
<router-view></router-view>
<router-view />
</div>
<app-footer></app-footer>
<AppFooter />
</div>
<div class="layout-mask animate-fadein"></div>
<div class="layout-mask animate-fadein" @click="hideMobileMenu" />
</div>
<Toast />
</template>
+152 -32
View File
@@ -1,37 +1,122 @@
<script setup>
import { ref } from 'vue';
import AppMenuItem from './AppMenuItem.vue';
const model = ref([
{
label: 'Home',
items: [{ label: 'Dashboard', icon: 'pi pi-fw pi-home', to: '/' }]
items: [
{
label: 'Dashboard',
icon: 'pi pi-fw pi-home',
to: '/'
}
]
},
{
label: 'UI Components',
path: '/uikit',
items: [
{ label: 'Form Layout', icon: 'pi pi-fw pi-id-card', to: '/uikit/formlayout' },
{ label: 'Input', icon: 'pi pi-fw pi-check-square', to: '/uikit/input' },
{ label: 'Button', icon: 'pi pi-fw pi-mobile', to: '/uikit/button', class: 'rotated-icon' },
{ label: 'Table', icon: 'pi pi-fw pi-table', to: '/uikit/table' },
{ label: 'List', icon: 'pi pi-fw pi-list', to: '/uikit/list' },
{ label: 'Tree', icon: 'pi pi-fw pi-share-alt', to: '/uikit/tree' },
{ label: 'Panel', icon: 'pi pi-fw pi-tablet', to: '/uikit/panel' },
{ label: 'Overlay', icon: 'pi pi-fw pi-clone', to: '/uikit/overlay' },
{ label: 'Media', icon: 'pi pi-fw pi-image', to: '/uikit/media' },
{ label: 'Menu', icon: 'pi pi-fw pi-bars', to: '/uikit/menu' },
{ label: 'Message', icon: 'pi pi-fw pi-comment', to: '/uikit/message' },
{ label: 'File', icon: 'pi pi-fw pi-file', to: '/uikit/file' },
{ label: 'Chart', icon: 'pi pi-fw pi-chart-bar', to: '/uikit/charts' },
{ label: 'Timeline', icon: 'pi pi-fw pi-calendar', to: '/uikit/timeline' },
{ label: 'Misc', icon: 'pi pi-fw pi-circle', to: '/uikit/misc' }
{
label: 'Form Layout',
icon: 'pi pi-fw pi-id-card',
to: '/uikit/formlayout'
},
{
label: 'Input',
icon: 'pi pi-fw pi-check-square',
to: '/uikit/input'
},
{
label: 'Button',
icon: 'pi pi-fw pi-mobile',
to: '/uikit/button',
class: 'rotated-icon'
},
{
label: 'Table',
icon: 'pi pi-fw pi-table',
to: '/uikit/table'
},
{
label: 'List',
icon: 'pi pi-fw pi-list',
to: '/uikit/list'
},
{
label: 'Tree',
icon: 'pi pi-fw pi-share-alt',
to: '/uikit/tree'
},
{
label: 'Panel',
icon: 'pi pi-fw pi-tablet',
to: '/uikit/panel'
},
{
label: 'Overlay',
icon: 'pi pi-fw pi-clone',
to: '/uikit/overlay'
},
{
label: 'Media',
icon: 'pi pi-fw pi-image',
to: '/uikit/media'
},
{
label: 'Menu',
icon: 'pi pi-fw pi-bars',
to: '/uikit/menu'
},
{
label: 'Message',
icon: 'pi pi-fw pi-comment',
to: '/uikit/message'
},
{
label: 'File',
icon: 'pi pi-fw pi-file',
to: '/uikit/file'
},
{
label: 'Chart',
icon: 'pi pi-fw pi-chart-bar',
to: '/uikit/charts'
},
{
label: 'Timeline',
icon: 'pi pi-fw pi-calendar',
to: '/uikit/timeline'
},
{
label: 'Misc',
icon: 'pi pi-fw pi-circle',
to: '/uikit/misc'
}
]
},
{
label: 'Prime Blocks',
icon: 'pi pi-fw pi-prime',
path: '/blocks',
items: [
{
label: 'Free Blocks',
icon: 'pi pi-fw pi-eye',
to: '/blocks/free'
},
{
label: 'All Blocks',
icon: 'pi pi-fw pi-globe',
url: 'https://blocks.primevue.org/',
target: '_blank'
}
]
},
{
label: 'Pages',
icon: 'pi pi-fw pi-briefcase',
to: '/pages',
path: '/pages',
items: [
{
label: 'Landing',
@@ -41,6 +126,7 @@ const model = ref([
{
label: 'Auth',
icon: 'pi pi-fw pi-user',
path: '/auth',
items: [
{
label: 'Login',
@@ -78,43 +164,76 @@ const model = ref([
},
{
label: 'Hierarchy',
icon: 'pi pi-fw pi-align-left',
path: '/hierarchy',
items: [
{
label: 'Submenu 1',
icon: 'pi pi-fw pi-bookmark',
icon: 'pi pi-fw pi-align-left',
path: '/submenu_1',
items: [
{
label: 'Submenu 1.1',
icon: 'pi pi-fw pi-bookmark',
icon: 'pi pi-fw pi-align-left',
path: '/submenu_1_1',
items: [
{ label: 'Submenu 1.1.1', icon: 'pi pi-fw pi-bookmark' },
{ label: 'Submenu 1.1.2', icon: 'pi pi-fw pi-bookmark' },
{ label: 'Submenu 1.1.3', icon: 'pi pi-fw pi-bookmark' }
{
label: 'Submenu 1.1.1',
icon: 'pi pi-fw pi-align-left'
},
{
label: 'Submenu 1.1.2',
icon: 'pi pi-fw pi-align-left'
},
{
label: 'Submenu 1.1.3',
icon: 'pi pi-fw pi-align-left'
}
]
},
{
label: 'Submenu 1.2',
icon: 'pi pi-fw pi-bookmark',
items: [{ label: 'Submenu 1.2.1', icon: 'pi pi-fw pi-bookmark' }]
icon: 'pi pi-fw pi-align-left',
path: '/submenu_1_2',
items: [
{
label: 'Submenu 1.2.1',
icon: 'pi pi-fw pi-align-left'
}
]
}
]
},
{
label: 'Submenu 2',
icon: 'pi pi-fw pi-bookmark',
icon: 'pi pi-fw pi-align-left',
path: '/submenu_2',
items: [
{
label: 'Submenu 2.1',
icon: 'pi pi-fw pi-bookmark',
icon: 'pi pi-fw pi-align-left',
path: '/submenu_2_1',
items: [
{ label: 'Submenu 2.1.1', icon: 'pi pi-fw pi-bookmark' },
{ label: 'Submenu 2.1.2', icon: 'pi pi-fw pi-bookmark' }
{
label: 'Submenu 2.1.1',
icon: 'pi pi-fw pi-align-left'
},
{
label: 'Submenu 2.1.2',
icon: 'pi pi-fw pi-align-left'
}
]
},
{
label: 'Submenu 2.2',
icon: 'pi pi-fw pi-bookmark',
items: [{ label: 'Submenu 2.2.1', icon: 'pi pi-fw pi-bookmark' }]
icon: 'pi pi-fw pi-align-left',
path: '/submenu_2_2',
items: [
{
label: 'Submenu 2.2.1',
icon: 'pi pi-fw pi-align-left'
}
]
}
]
}
@@ -122,11 +241,12 @@ const model = ref([
},
{
label: 'Get Started',
path: '/start',
items: [
{
label: 'Documentation',
icon: 'pi pi-fw pi-book',
to: '/documentation'
to: '/start/documentation'
},
{
label: 'View Source',
+33 -47
View File
@@ -1,92 +1,78 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { onBeforeMount, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { computed } from 'vue';
const route = useRoute();
const { layoutState, setActiveMenuItem, toggleMenu } = useLayout();
const { layoutState, isDesktop } = useLayout();
const props = defineProps({
item: {
type: Object,
default: () => ({})
},
index: {
type: Number,
default: 0
},
root: {
type: Boolean,
default: true
},
parentItemKey: {
parentPath: {
type: String,
default: null
}
});
const isActiveMenu = ref(false);
const itemKey = ref(null);
const fullPath = computed(() => (props.item.path ? (props.parentPath ? props.parentPath + props.item.path : props.item.path) : null));
onBeforeMount(() => {
itemKey.value = props.parentItemKey ? props.parentItemKey + '-' + props.index : String(props.index);
const activeItem = layoutState.activeMenuItem;
isActiveMenu.value = activeItem === itemKey.value || activeItem ? activeItem.startsWith(itemKey.value + '-') : false;
const isActive = computed(() => {
return props.item.path ? layoutState.activePath?.startsWith(fullPath.value) : layoutState.activePath === props.item.to;
});
watch(
() => layoutState.activeMenuItem,
(newVal) => {
isActiveMenu.value = newVal === itemKey.value || newVal.startsWith(itemKey.value + '-');
}
);
function itemClick(event, item) {
const itemClick = (event, item) => {
if (item.disabled) {
event.preventDefault();
return;
}
if ((item.to || item.url) && (layoutState.staticMenuMobileActive || layoutState.overlayMenuActive)) {
toggleMenu();
}
if (item.command) {
item.command({ originalEvent: event, item: item });
}
const foundItemKey = item.items ? (isActiveMenu.value ? props.parentItemKey : itemKey) : itemKey.value;
setActiveMenuItem(foundItemKey);
if (item.items) {
if (isActive.value) {
layoutState.activePath = layoutState.activePath.replace(item.path, '');
} else {
layoutState.activePath = fullPath.value;
layoutState.menuHoverActive = true;
}
function checkActiveRoute(item) {
return route.path === item.to;
} else {
layoutState.overlayMenuActive = false;
layoutState.mobileMenuActive = false;
layoutState.menuHoverActive = false;
}
};
const onMouseEnter = () => {
if (isDesktop() && props.root && props.item.items && layoutState.menuHoverActive) {
layoutState.activePath = fullPath.value;
}
};
</script>
<template>
<li :class="{ 'layout-root-menuitem': root, 'active-menuitem': isActiveMenu }">
<li :class="{ 'layout-root-menuitem': root, 'active-menuitem': isActive }">
<div v-if="root && item.visible !== false" class="layout-menuitem-root-text">{{ item.label }}</div>
<a v-if="(!item.to || item.items) && item.visible !== false" :href="item.url" @click="itemClick($event, item, index)" :class="item.class" :target="item.target" tabindex="0">
<i :class="item.icon" class="layout-menuitem-icon"></i>
<a v-if="(!item.to || item.items) && item.visible !== false" :href="item.url" @click="itemClick($event, item)" :class="item.class" :target="item.target" tabindex="0" @mouseenter="onMouseEnter">
<i :class="item.icon" class="layout-menuitem-icon" />
<span class="layout-menuitem-text">{{ item.label }}</span>
<i class="pi pi-fw pi-angle-down layout-submenu-toggler" v-if="item.items"></i>
<i class="pi pi-fw pi-angle-down layout-submenu-toggler" v-if="item.items" />
</a>
<router-link v-if="item.to && !item.items && item.visible !== false" @click="itemClick($event, item, index)" :class="[item.class, { 'active-route': checkActiveRoute(item) }]" tabindex="0" :to="item.to">
<i :class="item.icon" class="layout-menuitem-icon"></i>
<router-link v-if="item.to && !item.items && item.visible !== false" @click="itemClick($event, item)" exactActiveClass="active-route" :class="item.class" tabindex="0" :to="item.to" @mouseenter="onMouseEnter">
<i :class="item.icon" class="layout-menuitem-icon" />
<span class="layout-menuitem-text">{{ item.label }}</span>
<i class="pi pi-fw pi-angle-down layout-submenu-toggler" v-if="item.items"></i>
<i class="pi pi-fw pi-angle-down layout-submenu-toggler" v-if="item.items" />
</router-link>
<Transition v-if="item.items && item.visible !== false" name="layout-submenu">
<ul v-show="root ? true : isActiveMenu" class="layout-submenu">
<app-menu-item v-for="(child, i) in item.items" :key="child" :index="i" :item="child" :parentItemKey="itemKey" :root="false"></app-menu-item>
<ul v-show="root ? true : isActive" class="layout-submenu">
<app-menu-item v-for="child in item.items" :key="child.label + '_' + (child.to || child.path)" :item="child" :root="false" :parentPath="fullPath" />
</ul>
</Transition>
</li>
</template>
<style lang="scss" scoped></style>
+59 -4
View File
@@ -1,11 +1,66 @@
<script setup>
import { useLayout } from '@/layout/composables/layout';
import { onBeforeUnmount, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import AppMenu from './AppMenu.vue';
const { layoutState, isDesktop, hasOpenOverlay } = useLayout();
const route = useRoute();
const sidebarRef = ref(null);
let outsideClickListener = null;
watch(
() => route.path,
(newPath) => {
if (isDesktop()) layoutState.activePath = null;
else layoutState.activePath = newPath;
layoutState.overlayMenuActive = false;
layoutState.mobileMenuActive = false;
layoutState.menuHoverActive = false;
},
{ immediate: true }
);
watch(hasOpenOverlay, (newVal) => {
if (isDesktop()) {
if (newVal) bindOutsideClickListener();
else unbindOutsideClickListener();
}
});
const bindOutsideClickListener = () => {
if (!outsideClickListener) {
outsideClickListener = (event) => {
if (isOutsideClicked(event)) {
layoutState.overlayMenuActive = false;
}
};
document.addEventListener('click', outsideClickListener);
}
};
const unbindOutsideClickListener = () => {
if (outsideClickListener) {
document.removeEventListener('click', outsideClickListener);
outsideClickListener = null;
}
};
const isOutsideClicked = (event) => {
const topbarButtonEl = document.querySelector('.layout-menu-button');
return !(sidebarRef.value.isSameNode(event.target) || sidebarRef.value.contains(event.target) || topbarButtonEl?.isSameNode(event.target) || topbarButtonEl?.contains(event.target));
};
onBeforeUnmount(() => {
unbindOutsideClickListener();
});
</script>
<template>
<div class="layout-sidebar">
<app-menu></app-menu>
<div ref="sidebarRef" class="layout-sidebar">
<AppMenu />
</div>
</template>
<style lang="scss" scoped></style>
+2 -2
View File
@@ -41,7 +41,7 @@ const { toggleMenu, toggleDarkMode, isDarkTheme } = useLayout();
</button>
<div class="relative">
<button
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }"
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'p-anchored-overlay-enter-active', leaveToClass: 'hidden', leaveActiveClass: 'p-anchored-overlay-leave-active', hideOnOutsideClick: true }"
type="button"
class="layout-topbar-action layout-topbar-action-highlight"
>
@@ -53,7 +53,7 @@ const { toggleMenu, toggleDarkMode, isDarkTheme } = useLayout();
<button
class="layout-topbar-menu-button layout-topbar-action"
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }"
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'p-anchored-overlay-enter-active', leaveToClass: 'hidden', leaveActiveClass: 'p-anchored-overlay-leave-active', hideOnOutsideClick: true }"
>
<i class="pi pi-ellipsis-v"></i>
</button>
+35 -21
View File
@@ -9,20 +9,17 @@ const layoutConfig = reactive({
});
const layoutState = reactive({
staticMenuDesktopInactive: false,
staticMenuInactive: false,
overlayMenuActive: false,
profileSidebarVisible: false,
configSidebarVisible: false,
staticMenuMobileActive: false,
sidebarExpanded: false,
menuHoverActive: false,
activeMenuItem: null
activeMenuItem: null,
activePath: null
});
export function useLayout() {
const setActiveMenuItem = (item) => {
layoutState.activeMenuItem = item.value || item;
};
const toggleDarkMode = () => {
if (!document.startViewTransition) {
executeDarkModeToggle();
@@ -39,34 +36,51 @@ export function useLayout() {
};
const toggleMenu = () => {
if (isDesktop()) {
if (layoutConfig.menuMode === 'static') {
layoutState.staticMenuInactive = !layoutState.staticMenuInactive;
}
if (layoutConfig.menuMode === 'overlay') {
layoutState.overlayMenuActive = !layoutState.overlayMenuActive;
}
if (window.innerWidth > 991) {
layoutState.staticMenuDesktopInactive = !layoutState.staticMenuDesktopInactive;
} else {
layoutState.staticMenuMobileActive = !layoutState.staticMenuMobileActive;
layoutState.mobileMenuActive = !layoutState.mobileMenuActive;
}
};
const isSidebarActive = computed(() => layoutState.overlayMenuActive || layoutState.staticMenuMobileActive);
const toggleConfigSidebar = () => {
layoutState.configSidebarVisible = !layoutState.configSidebarVisible;
};
const hideMobileMenu = () => {
layoutState.mobileMenuActive = false;
};
const changeMenuMode = (event) => {
layoutConfig.menuMode = event.value;
layoutState.staticMenuInactive = false;
layoutState.mobileMenuActive = false;
layoutState.sidebarExpanded = false;
layoutState.menuHoverActive = false;
layoutState.anchored = false;
};
const isDarkTheme = computed(() => layoutConfig.darkTheme);
const isDesktop = () => window.innerWidth > 991;
const getPrimary = computed(() => layoutConfig.primary);
const getSurface = computed(() => layoutConfig.surface);
const hasOpenOverlay = computed(() => layoutState.overlayMenuActive);
return {
layoutConfig,
layoutState,
toggleMenu,
isSidebarActive,
isDarkTheme,
getPrimary,
getSurface,
setActiveMenuItem,
toggleDarkMode
toggleDarkMode,
toggleConfigSidebar,
toggleMenu,
hideMobileMenu,
changeMenuMode,
isDesktop,
hasOpenOverlay
};
}
+2 -2
View File
@@ -2,13 +2,13 @@ import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import Aura from '@primevue/themes/aura';
import Aura from '@primeuix/themes/aura';
import PrimeVue from 'primevue/config';
import ConfirmationService from 'primevue/confirmationservice';
import ToastService from 'primevue/toastservice';
import '@/assets/styles.scss';
import '@/assets/tailwind.css';
import '@/assets/styles.scss';
const app = createApp(App);
+9 -1
View File
@@ -89,6 +89,14 @@ const router = createRouter({
name: 'timeline',
component: () => import('@/views/uikit/TimelineDoc.vue')
},
{
path: '/blocks/free',
name: 'blocks',
meta: {
breadcrumb: ['Prime Blocks', 'Free Blocks']
},
component: () => import('@/views/utilities/Blocks.vue')
},
{
path: '/pages/empty',
name: 'empty',
@@ -100,7 +108,7 @@ const router = createRouter({
component: () => import('@/views/pages/Crud.vue')
},
{
path: '/documentation',
path: '/start/documentation',
name: 'documentation',
component: () => import('@/views/pages/Documentation.vue')
}
+2 -2
View File
@@ -264,7 +264,7 @@ function getStatusLabel(status) {
<Dialog v-model:visible="deleteProductDialog" :style="{ width: '450px' }" header="Confirm" :modal="true">
<div class="flex items-center gap-4">
<i class="pi pi-exclamation-triangle !text-3xl" />
<i class="pi pi-exclamation-triangle text-3xl!" />
<span v-if="product"
>Are you sure you want to delete <b>{{ product.name }}</b
>?</span
@@ -278,7 +278,7 @@ function getStatusLabel(status) {
<Dialog v-model:visible="deleteProductsDialog" :style="{ width: '450px' }" header="Confirm" :modal="true">
<div class="flex items-center gap-4">
<i class="pi pi-exclamation-triangle !text-3xl" />
<i class="pi pi-exclamation-triangle text-3xl!" />
<span v-if="product">Are you sure you want to delete the selected products?</span>
</div>
<template #footer>
+81
View File
@@ -45,6 +45,87 @@ npm run dev</code></pre>
CSS variables used in the template derive their values from the PrimeVue styled mode presets, use the files under <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">assets/layout/_variables.scss</span> to customize
according to your requirements.
</p>
<div class="font-semibold text-xl mb-4">Add Sakai-Vue to a Nuxt Project</div>
<p class="text-lg mb-4">To get started, create a Nuxt project.</p>
<pre class="app-code">
<code>npx nuxi@latest init sakai-nuxt</code></pre>
<p class="text-lg mb-4">Add Prime related libraries to the project.</p>
<pre class="app-code">
<code>npm install primevue @primevue/themes tailwindcss-primeui primeicons
npm install --save-dev @primevue/nuxt-module</code></pre>
<p class="text-lg mb-4">Add PrimeVue-Nuxt module to <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">nuxt.config.js</span></p>
<pre class="app-code">
<code>modules: [
'@primevue/nuxt-module',
]</code></pre>
<p class="text-lg mb-4">Install <a href="https://tailwindcss.com/docs/guides/nuxtjs" class="font-medium text-primary hover:underline">Tailwind CSS</a> with Nuxt using official documentation.</p>
<p class="text-lg mb-4">
Add <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">tailwindcss-primeui</span> package as a plugin to <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">tailwind.config.js</span>
</p>
<pre class="app-code">
<code>plugins: [require('tailwindcss-primeui')]</code></pre>
<p class="text-lg mb-4">Add PrimeVue to in <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">nuxt.config.js</span></p>
<pre class="app-code">
<code>import Aura from '@primevue/themes/aura';
primevue: {
options: {
theme: {
preset: Aura,
options: {
darkModeSelector: '.app-dark'
}
}
}
}</code></pre>
<p class="text-lg mb-4">
Copy <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">src/assets</span> folder and paste them to <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">assets</span> folder to your Nuxt project.
And add to <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">nuxt.config.js</span>
</p>
<pre class="app-code">
<code>css: ['~/assets/tailwind.css', '~/assets/styles.scss']</code></pre>
<p class="text-lg mb-4">Change <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">app.vue</span></p>
<pre class="app-code">
<code>&lt;template&gt;
&lt;NuxtLayout&gt;
&lt;NuxtPage /&gt;
&lt;/NuxtLayout&gt;
&lt;/template&gt;</code></pre>
<p class="text-lg mb-4">Create <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">layouts/default.vue</span> and paste this code:</p>
<pre class="app-code">
<code>&lt;script setup&gt;
import AppLayout from './AppLayout.vue';
&lt;/script&gt;
&lt;template&gt;
&lt;AppLayout /&gt;
&lt;/template&gt;</code></pre>
<p class="text-lg mb-4">
Create <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">layouts</span> folder and copy <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">src/layout</span> folder and paste them. And then
create <span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">composables/use-layout.vue</span> and replace it with
<span class="bg-highlight px-2 py-1 rounded-border not-italic text-base">src/layout/composables/layout.js</span>. Then remove this line:
</p>
<pre class="app-code">
<code>import { useLayout } from '@/layout/composables/layout';</code></pre>
<p class="text-lg mb-4">As a final step, copy the following folders:</p>
<ul class="leading-normal list-disc pl-8 text-lg mb-4">
<li><span class="text-primary font-medium">public/demo</span> <i class="pi pi-arrow-right text-sm! mr-1"></i> <span class="text-primary font-medium">public</span></li>
<li><span class="text-primary font-medium">src/components</span> <i class="pi pi-arrow-right text-sm! mr-1"></i> <span class="text-primary font-medium">components</span></li>
<li><span class="text-primary font-medium">src/service</span> <i class="pi pi-arrow-right text-sm! mr-1"></i> <span class="text-primary font-medium">service</span></li>
<li><span class="text-primary font-medium">src/views/uikit</span> <i class="pi pi-arrow-right text-sm! mr-1"></i> <span class="text-primary font-medium">pages/uikit</span></li>
<li><span class="text-primary font-medium">src/views/pages</span> <i class="pi pi-arrow-right text-sm! mr-1"></i> <span class="text-primary font-medium">pages</span></li>
</ul>
</div>
</template>
+3 -3
View File
@@ -30,7 +30,7 @@ import FloatingConfigurator from '@/components/FloatingConfigurator.vue';
<div class="text-surface-600 dark:text-surface-200 mb-8">Requested resource is not available.</div>
<router-link to="/" class="w-full flex items-center py-8 border-surface-300 dark:border-surface-500 border-b">
<span class="flex justify-center items-center border-2 border-primary text-primary rounded-border" style="height: 3.5rem; width: 3.5rem">
<i class="pi pi-fw pi-table !text-2xl"></i>
<i class="pi pi-fw pi-table text-2xl!"></i>
</span>
<span class="ml-6 flex flex-col">
<span class="text-surface-900 dark:text-surface-0 lg:text-xl font-medium mb-0 block">Frequently Asked Questions</span>
@@ -39,7 +39,7 @@ import FloatingConfigurator from '@/components/FloatingConfigurator.vue';
</router-link>
<router-link to="/" class="w-full flex items-center py-8 border-surface-300 dark:border-surface-500 border-b">
<span class="flex justify-center items-center border-2 border-primary text-primary rounded-border" style="height: 3.5rem; width: 3.5rem">
<i class="pi pi-fw pi-question-circle !text-2xl"></i>
<i class="pi pi-fw pi-question-circle text-2xl!"></i>
</span>
<span class="ml-6 flex flex-col">
<span class="text-surface-900 dark:text-surface-0 lg:text-xl font-medium mb-0">Solution Center</span>
@@ -48,7 +48,7 @@ import FloatingConfigurator from '@/components/FloatingConfigurator.vue';
</router-link>
<router-link to="/" class="w-full flex items-center mb-8 py-8 border-surface-300 dark:border-surface-500 border-b">
<span class="flex justify-center items-center border-2 border-primary text-primary rounded-border" style="height: 3.5rem; width: 3.5rem">
<i class="pi pi-fw pi-unlock !text-2xl"></i>
<i class="pi pi-fw pi-unlock text-2xl!"></i>
</span>
<span class="ml-6 flex flex-col">
<span class="text-surface-900 dark:text-surface-0 lg:text-xl font-medium mb-0">Permission Manager</span>
+1 -1
View File
@@ -10,7 +10,7 @@ import FloatingConfigurator from '@/components/FloatingConfigurator.vue';
<div class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20 flex flex-col items-center" style="border-radius: 53px">
<div class="gap-4 flex flex-col items-center">
<div class="flex justify-center items-center border-2 border-orange-500 rounded-full" style="width: 3.2rem; height: 3.2rem">
<i class="text-orange-500 pi pi-fw pi-lock !text-2xl"></i>
<i class="text-orange-500 pi pi-fw pi-lock text-2xl!"></i>
</div>
<h1 class="text-surface-900 dark:text-surface-0 font-bold text-4xl lg:text-5xl mb-2">Access Denied</h1>
<span class="text-muted-color mb-8">You do not have the necessary permisions. Please contact admins.</span>
+1 -1
View File
@@ -10,7 +10,7 @@ import FloatingConfigurator from '@/components/FloatingConfigurator.vue';
<div class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20 flex flex-col items-center" style="border-radius: 53px">
<div class="gap-4 flex flex-col items-center">
<div class="flex justify-center items-center border-2 border-pink-500 rounded-full" style="height: 3.2rem; width: 3.2rem">
<i class="pi pi-fw pi-exclamation-circle !text-2xl text-pink-500"></i>
<i class="pi pi-fw pi-exclamation-circle text-2xl! text-pink-500"></i>
</div>
<h1 class="text-surface-900 dark:text-surface-0 font-bold text-5xl mb-2">Error Occured</h1>
<span class="text-muted-color mb-8">Requested resource is not available.</span>
+2 -2
View File
@@ -2,7 +2,7 @@
import { useLayout } from '@/layout/composables/layout';
import { onMounted, ref, watch } from 'vue';
const { getPrimary, getSurface, isDarkTheme } = useLayout();
const { layoutConfig, isDarkTheme } = useLayout();
const lineData = ref(null);
const pieData = ref(null);
const polarData = ref(null);
@@ -219,7 +219,7 @@ function setColorOptions() {
}
watch(
[getPrimary, getSurface, isDarkTheme],
[() => layoutConfig.primary, () => layoutConfig.surface, isDarkTheme],
() => {
setColorOptions();
},
+2 -2
View File
@@ -54,7 +54,7 @@ function getSeverity(product) {
<div class="flex flex-col sm:flex-row sm:items-center p-6 gap-4" :class="{ 'border-t border-surface': index !== 0 }">
<div class="md:w-40 relative">
<img class="block xl:block mx-auto rounded w-full" :src="`https://primefaces.org/cdn/primevue/images/product/${item.image}`" :alt="item.name" />
<Tag :value="item.inventoryStatus" :severity="getSeverity(item)" class="absolute dark:!bg-surface-900" style="left: 4px; top: 4px"></Tag>
<Tag :value="item.inventoryStatus" :severity="getSeverity(item)" class="absolute dark:bg-surface-900!" style="left: 4px; top: 4px"></Tag>
</div>
<div class="flex flex-col md:flex-row justify-between md:items-center flex-1 gap-6">
<div class="flex flex-row md:flex-col justify-between items-start gap-2">
@@ -97,7 +97,7 @@ function getSeverity(product) {
<div class="bg-surface-50 flex justify-center rounded p-4">
<div class="relative mx-auto">
<img class="rounded w-full" :src="`https://primefaces.org/cdn/primevue/images/product/${item.image}`" :alt="item.name" style="max-width: 300px" />
<Tag :value="item.inventoryStatus" :severity="getSeverity(item)" class="absolute dark:!bg-surface-900" style="left: 4px; top: 4px"></Tag>
<Tag :value="item.inventoryStatus" :severity="getSeverity(item)" class="absolute dark:bg-surface-900!" style="left: 4px; top: 4px"></Tag>
</div>
</div>
<div class="pt-6">
+8 -8
View File
@@ -84,11 +84,11 @@ onBeforeUnmount(() => {
<div class="font-semibold text-xl mb-4">Avatar</div>
<div class="font-semibold mb-4">Group</div>
<AvatarGroup>
<Avatar :image="'/demo/images/avatar/amyelsner.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'/demo/images/avatar/asiyajavayant.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'/demo/images/avatar/onyamalimba.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'/demo/images/avatar/ionibowcher.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'/demo/images/avatar/xuxuefeng.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'https://primefaces.org/cdn/primevue/images/avatar/asiyajavayant.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'https://primefaces.org/cdn/primevue/images/avatar/onyamalimba.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'https://primefaces.org/cdn/primevue/images/avatar/ionibowcher.png'" size="large" shape="circle"></Avatar>
<Avatar :image="'https://primefaces.org/cdn/primevue/images/avatar/xuxuefeng.png'" size="large" shape="circle"></Avatar>
<Avatar label="+2" shape="circle" size="large" :style="{ 'background-color': '#9c27b0', color: '#ffffff' }"></Avatar>
</AvatarGroup>
@@ -168,9 +168,9 @@ onBeforeUnmount(() => {
<div class="font-semibold my-4">Image</div>
<div class="flex items-center flex-col sm:flex-row">
<Chip label="Amy Elsner" :image="'/demo/images/avatar/amyelsner.png'" class="mr-2 mb-2"></Chip>
<Chip label="Asiya Javayant" :image="'/demo/images/avatar/asiyajavayant.png'" class="mr-2 mb-2"></Chip>
<Chip label="Onyama Limba" :image="'/demo/images/avatar/onyamalimba.png'" class="mr-2 mb-2"></Chip>
<Chip label="Amy Elsner" :image="'https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png'" class="mr-2 mb-2"></Chip>
<Chip label="Asiya Javayant" :image="'https://primefaces.org/cdn/primevue/images/avatar/asiyajavayant.png'" class="mr-2 mb-2"></Chip>
<Chip label="Onyama Limba" :image="'https://primefaces.org/cdn/primevue/images/avatar/onyamalimba.png'" class="mr-2 mb-2"></Chip>
</div>
</div>
+2 -3
View File
@@ -14,7 +14,6 @@ const visibleFull = ref(false);
const products = ref(null);
const selectedProduct = ref(null);
const op = ref(null);
const op2 = ref(null);
const popup = ref(null);
const toast = useToast();
@@ -41,7 +40,7 @@ function closeConfirmation() {
}
function toggleDataTable(event) {
op2.value.toggle(event);
op.value.toggle(event);
}
function onProductSelect(event) {
@@ -93,7 +92,7 @@ function confirm(event) {
<div class="font-semibold text-xl mb-4">Popover</div>
<div class="flex flex-wrap gap-2">
<Button type="button" label="Show" @click="toggleDataTable" />
<Popover ref="op2" id="overlay_panel" style="width: 450px">
<Popover ref="op" id="overlay_panel" style="width: 450px">
<DataTable v-model:selection="selectedProduct" :value="products" selectionMode="single" :paginator="true" :rows="5" @row-select="onProductSelect">
<Column field="name" header="Name" sortable style="min-width: 12rem"></Column>
<Column header="Image">
+2 -2
View File
@@ -185,8 +185,8 @@ function toggle() {
</div>
</div>
<div class="w-full md:w-2/12">
<Divider layout="vertical" class="!hidden md:!flex"><b>OR</b></Divider>
<Divider layout="horizontal" class="!flex md:!hidden" align="center"><b>OR</b></Divider>
<Divider layout="vertical" class="hidden! md:flex!"><b>OR</b></Divider>
<Divider layout="horizontal" class="flex! md:hidden!" align="center"><b>OR</b></Divider>
</div>
<div class="w-full md:w-5/12 flex items-center justify-center py-5">
<Button label="Sign Up" icon="pi pi-user-plus" severity="success" class="w-full max-w-[17.35rem] mx-auto"></Button>
File diff suppressed because it is too large Load Diff
-15
View File
@@ -1,15 +0,0 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ['selector', '[class*="app-dark"]'],
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
plugins: [require('tailwindcss-primeui')],
theme: {
screens: {
sm: '576px',
md: '768px',
lg: '992px',
xl: '1200px',
'2xl': '1920px'
}
}
};
+9
View File
@@ -1,6 +1,7 @@
import { fileURLToPath, URL } from 'node:url';
import { PrimeVueResolver } from '@primevue/auto-import-resolver';
import tailwindcss from '@tailwindcss/vite';
import vue from '@vitejs/plugin-vue';
import Components from 'unplugin-vue-components/vite';
import { defineConfig } from 'vite';
@@ -12,6 +13,7 @@ export default defineConfig({
},
plugins: [
vue(),
tailwindcss(),
Components({
resolvers: [PrimeVueResolver()]
})
@@ -20,5 +22,12 @@ export default defineConfig({
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
css: {
preprocessorOptions: {
scss: {
api: 'modern-compiler'
}
}
}
});