Compare commits
30 Commits
4.0.0
..
319f976d2b
| Author | SHA1 | Date | |
|---|---|---|---|
| 319f976d2b | |||
| 13a50a3af3 | |||
| 23bcf922ab | |||
| e1ecd23050 | |||
| 2f5b71a3eb | |||
| 22ba8601f3 | |||
| 4a8745b497 | |||
| d5ec7dba67 | |||
| 7c54176132 | |||
| 03ef1236f0 | |||
| 7ac2ba9013 | |||
| 5f951584c7 | |||
| 817ffa0d62 | |||
| 9585f62298 | |||
| aad48fca63 | |||
| 59f3ebffe7 | |||
| 6fd2e4d96e | |||
| 1c65a74541 | |||
| a5aafc1d34 | |||
| 0f42b3760d | |||
| c4dec65f2a | |||
| 6f85c751de | |||
| 411fecb517 | |||
| 4c7b0c0f5d | |||
| 3ba6d75db2 | |||
| b00460a670 | |||
| 51c93b25d0 | |||
| c4c2d47d54 | |||
| cb0f98582a | |||
| fa5009486a |
@@ -1,5 +1,29 @@
|
|||||||
# Changelog
|
# 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**
|
||||||
|
|
||||||
|
- Refactored dashboard sections to components
|
||||||
|
- Migrate sass from @import to @use
|
||||||
|
|
||||||
|
## 4.1.0 (2024-07-29)
|
||||||
|
|
||||||
|
- Changed menu button location at topbar
|
||||||
|
- Add border to overlay menu
|
||||||
|
- Animation for mobile mask
|
||||||
|
- Fixed chart colors
|
||||||
|
|
||||||
|
## 4.0.0 (2024-07-29)
|
||||||
|
|
||||||
|
- Updated to PrimeVue v4
|
||||||
|
|
||||||
## 3.10.0 (2024-03-11)
|
## 3.10.0 (2024-03-11)
|
||||||
|
|
||||||
**Migration Guide**
|
**Migration Guide**
|
||||||
|
|||||||
@@ -1,29 +1,3 @@
|
|||||||
This template should help get you started developing with Vue 3 in Vite.
|
Sakai is an application template for Vue based on the [create-vue](https://github.com/vuejs/create-vue), the recommended way to start a Vite-powered Vue projects.
|
||||||
|
|
||||||
## Customize configuration
|
Visit the [documentation](https://sakai.primevue.org/documentation) to get started.
|
||||||
|
|
||||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
|
||||||
|
|
||||||
## Project Setup
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compile and Hot-Reload for Development
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### Compile and Minify for Production
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lint with [ESLint](https://eslint.org/)
|
|
||||||
|
|
||||||
```sh
|
|
||||||
npm run lint
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sakai-vue",
|
"name": "sakai-vue",
|
||||||
"version": "4.0.0",
|
"version": "4.3.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
@@ -8,26 +8,25 @@
|
|||||||
"lint": "eslint --fix . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
|
"lint": "eslint --fix . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@primevue/themes": "^4.0.0",
|
"@primeuix/themes": "^1.0.0",
|
||||||
"chart.js": "3.3.2",
|
"chart.js": "3.3.2",
|
||||||
"primeicons": "^6.0.1",
|
"primeicons": "^7.0.0",
|
||||||
"primevue": "^4.0.0",
|
"primevue": "^4.3.1",
|
||||||
|
"tailwindcss-primeui": "^0.5.0",
|
||||||
"vue": "^3.4.34",
|
"vue": "^3.4.34",
|
||||||
"vue-router": "^4.4.0"
|
"vue-router": "^4.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@primevue/auto-import-resolver": "^4.0.1",
|
"@primevue/auto-import-resolver": "^4.3.1",
|
||||||
"@rushstack/eslint-patch": "^1.8.0",
|
"@rushstack/eslint-patch": "^1.8.0",
|
||||||
|
"@tailwindcss/vite": "^4.1.17",
|
||||||
"@vitejs/plugin-vue": "^5.0.5",
|
"@vitejs/plugin-vue": "^5.0.5",
|
||||||
"@vue/eslint-config-prettier": "^9.0.0",
|
"@vue/eslint-config-prettier": "^9.0.0",
|
||||||
"autoprefixer": "^10.4.19",
|
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-vue": "^9.23.0",
|
"eslint-plugin-vue": "^9.23.0",
|
||||||
"postcss": "^8.4.40",
|
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"sass": "^1.55.0",
|
"sass": "^1.55.0",
|
||||||
"tailwindcss": "^3.4.6",
|
"tailwindcss": "^4.1.17",
|
||||||
"tailwindcss-primeui": "^0.3.2",
|
|
||||||
"unplugin-vue-components": "^0.27.3",
|
"unplugin-vue-components": "^0.27.3",
|
||||||
"vite": "^5.3.1"
|
"vite": "^5.3.1"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 1009 B |
|
Before Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg width="300px" height="200px" viewBox="0 0 300 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<title>Artboard</title>
|
|
||||||
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
||||||
<rect id="Rectangle" fill="#F8F9FA" x="0" y="0" width="300" height="200"></rect>
|
|
||||||
<g id="image" transform="translate(110.000000, 70.000000)" fill="#BABABC" fill-rule="nonzero">
|
|
||||||
<path d="M75,0 L5,0 C2.23857625,0 0,2.23857625 0,5 L0,55 C0,57.7614237 2.23857625,60 5,60 L75,60 C77.7614237,60 80,57.7614237 80,55 L80,5 C80,2.23857625 77.7614237,0 75,0 Z M20,10 C25.5228475,10 30,14.4771525 30,20 C30,25.5228475 25.5228475,30 20,30 C14.4771525,30 10,25.5228475 10,20 C10,14.4771525 14.4771525,10 20,10 Z M70,40 L70,50 L10,50 L10,40 L18.55,35.7 C19.4648753,35.2524957 20.5351247,35.2524957 21.45,35.7 L30,40 L53.65,21.1 C54.4866298,20.4991452 55.6133702,20.4991452 56.45,21.1 L70,30 L70,40 Z" id="Shape"></path>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
@@ -1,2 +1,2 @@
|
|||||||
@import './flags/flags.css';
|
@use './code.scss';
|
||||||
@import './code.scss';
|
@use './flags/flags.css';
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 54 KiB |
@@ -1,6 +1,7 @@
|
|||||||
html {
|
html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@use 'mixins' as *;
|
||||||
|
|
||||||
.layout-sidebar {
|
.layout-sidebar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: 20rem;
|
width: 20rem;
|
||||||
|
|||||||
@@ -22,6 +22,10 @@
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-bottom-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:
|
box-shadow:
|
||||||
0px 3px 5px rgba(0, 0, 0, 0.02),
|
0px 3px 5px rgba(0, 0, 0, 0.02),
|
||||||
0px 0px 2px rgba(0, 0, 0, 0.05),
|
0px 0px 2px rgba(0, 0, 0, 0.05),
|
||||||
@@ -77,6 +81,9 @@
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
border-top-left-radius: 0;
|
border-top-left-radius: 0;
|
||||||
border-bottom-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 {
|
.layout-mask {
|
||||||
@@ -97,7 +104,6 @@
|
|||||||
|
|
||||||
.layout-mask {
|
.layout-mask {
|
||||||
display: block;
|
display: block;
|
||||||
animation: fadein var(--layout-section-transition-duration);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@use 'mixins' as *;
|
||||||
|
|
||||||
.layout-topbar {
|
.layout-topbar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
@@ -39,7 +41,6 @@
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: var(--text-color-secondary);
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
width: 2.5rem;
|
width: 2.5rem;
|
||||||
height: 2.5rem;
|
height: 2.5rem;
|
||||||
@@ -71,7 +72,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.layout-menu-button {
|
.layout-menu-button {
|
||||||
margin-left: 2rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-topbar-menu-button {
|
.layout-topbar-menu-button {
|
||||||
@@ -97,24 +98,19 @@
|
|||||||
|
|
||||||
@media (max-width: 991px) {
|
@media (max-width: 991px) {
|
||||||
.layout-topbar {
|
.layout-topbar {
|
||||||
|
padding: 0 2rem;
|
||||||
|
|
||||||
.layout-topbar-logo-container {
|
.layout-topbar-logo-container {
|
||||||
width: auto;
|
width: auto;
|
||||||
order: 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-menu-button {
|
.layout-menu-button {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: 1rem;
|
margin-right: 0.5rem;
|
||||||
order: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-topbar-menu-button {
|
.layout-topbar-menu-button {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
order: 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layout-topbar-actions {
|
|
||||||
order: 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-topbar-menu {
|
.layout-topbar-menu {
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
@import './variables/_common';
|
@use './variables/_common';
|
||||||
@import './variables/_light';
|
@use './variables/_light';
|
||||||
@import './variables/_dark';
|
@use './variables/_dark';
|
||||||
@import './_mixins';
|
@use './_mixins';
|
||||||
@import './_preloading';
|
@use './_preloading';
|
||||||
@import './_core';
|
@use './_core';
|
||||||
@import './_main';
|
@use './_main';
|
||||||
@import './_topbar';
|
@use './_topbar';
|
||||||
@import './_menu';
|
@use './_menu';
|
||||||
@import './_footer';
|
@use './_footer';
|
||||||
@import './_responsive';
|
@use './_responsive';
|
||||||
@import './_utils';
|
@use './_utils';
|
||||||
@import './_typography';
|
@use './_typography';
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
/* You can add global styles to this file, and also import other style files */
|
/* You can add global styles to this file, and also import other style files */
|
||||||
@import '@/assets/layout/layout.scss';
|
@use 'primeicons/primeicons.css';
|
||||||
@import 'primeicons/primeicons.css';
|
@use '@/assets/layout/layout.scss';
|
||||||
@import '@/assets/demo/demo.scss';
|
@use '@/assets/demo/demo.scss';
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,32 @@
|
|||||||
@tailwind base;
|
@import 'tailwindcss';
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
@plugin 'tailwindcss-primeui';
|
||||||
|
|
||||||
|
@custom-variant dark (&:where([class*="app-dark"], [class*="app-dark"] *));
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--breakpoint-*: initial;
|
||||||
|
--breakpoint-sm: 576px;
|
||||||
|
--breakpoint-md: 768px;
|
||||||
|
--breakpoint-lg: 992px;
|
||||||
|
--breakpoint-xl: 1200px;
|
||||||
|
--breakpoint-2xl: 1920px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The default border color has changed to `currentcolor` in Tailwind CSS v4,
|
||||||
|
so we've added these compatibility styles to make sure everything still
|
||||||
|
looks the same as it did with Tailwind CSS v3.
|
||||||
|
|
||||||
|
If we ever want to remove these styles, we need to add an explicit border
|
||||||
|
color utility to any element that depends on these defaults.
|
||||||
|
*/
|
||||||
|
@layer base {
|
||||||
|
*,
|
||||||
|
::after,
|
||||||
|
::before,
|
||||||
|
::backdrop,
|
||||||
|
::file-selector-button {
|
||||||
|
border-color: var(--color-gray-200, currentcolor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||