spoko-design-system 1.3.7 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/code-quality.yml +35 -2
- package/CHANGELOG.md +8 -0
- package/package.json +32 -32
- package/src/components/MainColors.vue +91 -9
- package/src/components/Modal.astro +132 -12
- package/src/components/SlimBanner.vue +161 -52
- package/src/pages/components/modal.mdx +178 -30
- package/src/pages/components/slimbanner.mdx +232 -7
- package/src/pages/core/colors.mdx +13 -2
- package/src/pages/core/grid.mdx +104 -0
- package/src/styles/base/grid.css +22 -0
- package/src/utils/text.ts +5 -3
- package/.github/workflows/sonarcloud.yml +0 -39
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
name: Code Quality
|
|
1
|
+
name: Code Quality & Analysis
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
@@ -36,4 +36,37 @@ jobs:
|
|
|
36
36
|
run: pnpm run lint
|
|
37
37
|
|
|
38
38
|
- name: Type check
|
|
39
|
-
run: pnpm run check
|
|
39
|
+
run: pnpm run check
|
|
40
|
+
|
|
41
|
+
sonarcloud:
|
|
42
|
+
name: SonarCloud Analysis
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
|
|
45
|
+
steps:
|
|
46
|
+
- name: Checkout code
|
|
47
|
+
uses: actions/checkout@v5
|
|
48
|
+
with:
|
|
49
|
+
fetch-depth: 0 # Shallow clones should be disabled for better analysis
|
|
50
|
+
|
|
51
|
+
- name: Setup pnpm
|
|
52
|
+
uses: pnpm/action-setup@v4
|
|
53
|
+
with:
|
|
54
|
+
version: 10.17.1
|
|
55
|
+
|
|
56
|
+
- name: Setup Node.js
|
|
57
|
+
uses: actions/setup-node@v5
|
|
58
|
+
with:
|
|
59
|
+
node-version: '22'
|
|
60
|
+
cache: 'pnpm'
|
|
61
|
+
|
|
62
|
+
- name: Install dependencies
|
|
63
|
+
run: pnpm install --frozen-lockfile
|
|
64
|
+
|
|
65
|
+
- name: Build project
|
|
66
|
+
run: pnpm run build
|
|
67
|
+
|
|
68
|
+
- name: SonarCloud Scan
|
|
69
|
+
uses: SonarSource/sonarcloud-github-action@master
|
|
70
|
+
env:
|
|
71
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
|
|
72
|
+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## [1.4.1](https://github.com/polo-blue/sds/compare/v1.4.0...v1.4.1) (2025-10-20)
|
|
2
|
+
|
|
3
|
+
## [1.4.0](https://github.com/polo-blue/sds/compare/v1.3.7...v1.4.0) (2025-10-20)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* enhance components with flexible layouts and click-to-copy functionality ([3dfa718](https://github.com/polo-blue/sds/commit/3dfa718f7f4355c0beed4032e84d01a2c2c4a547))
|
|
8
|
+
|
|
1
9
|
## [1.3.7](https://github.com/polo-blue/sds/compare/v1.3.6...v1.3.7) (2025-10-08)
|
|
2
10
|
|
|
3
11
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spoko-design-system",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"main": "./index.ts",
|
|
6
6
|
"module": "./index.ts",
|
|
@@ -51,33 +51,33 @@
|
|
|
51
51
|
"spoko design system"
|
|
52
52
|
],
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@algolia/client-search": "^5.40.
|
|
55
|
-
"@astrojs/mdx": "^4.3.
|
|
56
|
-
"@astrojs/node": "^9.
|
|
54
|
+
"@algolia/client-search": "^5.40.1",
|
|
55
|
+
"@astrojs/mdx": "^4.3.7",
|
|
56
|
+
"@astrojs/node": "^9.5.0",
|
|
57
57
|
"@astrojs/sitemap": "^3.6.0",
|
|
58
|
-
"@astrojs/ts-plugin": "^1.10.
|
|
58
|
+
"@astrojs/ts-plugin": "^1.10.5",
|
|
59
59
|
"@astrojs/vue": "^5.1.1",
|
|
60
|
-
"@docsearch/css": "^4.
|
|
60
|
+
"@docsearch/css": "^4.2.0",
|
|
61
61
|
"@iconify-json/ant-design": "^1.2.5",
|
|
62
62
|
"@iconify-json/bi": "^1.2.6",
|
|
63
63
|
"@iconify-json/bx": "^1.2.2",
|
|
64
|
-
"@iconify-json/carbon": "^1.2.
|
|
65
|
-
"@iconify-json/circle-flags": "^1.2.
|
|
64
|
+
"@iconify-json/carbon": "^1.2.14",
|
|
65
|
+
"@iconify-json/circle-flags": "^1.2.10",
|
|
66
66
|
"@iconify-json/ei": "^1.2.2",
|
|
67
67
|
"@iconify-json/el": "^1.2.2",
|
|
68
68
|
"@iconify-json/eos-icons": "^1.2.4",
|
|
69
69
|
"@iconify-json/et": "^1.2.1",
|
|
70
70
|
"@iconify-json/flowbite": "^1.2.7",
|
|
71
|
-
"@iconify-json/fluent": "^1.2.
|
|
71
|
+
"@iconify-json/fluent": "^1.2.33",
|
|
72
72
|
"@iconify-json/fluent-emoji": "1.2.6",
|
|
73
73
|
"@iconify-json/ic": "^1.2.4",
|
|
74
74
|
"@iconify-json/icon-park-outline": "^1.2.4",
|
|
75
75
|
"@iconify-json/la": "^1.2.1",
|
|
76
|
-
"@iconify-json/lucide": "^1.2.
|
|
77
|
-
"@iconify-json/material-symbols-light": "^1.2.
|
|
76
|
+
"@iconify-json/lucide": "^1.2.70",
|
|
77
|
+
"@iconify-json/material-symbols-light": "^1.2.42",
|
|
78
78
|
"@iconify-json/mdi": "^1.2.3",
|
|
79
79
|
"@iconify-json/noto-v1": "^1.2.5",
|
|
80
|
-
"@iconify-json/octicon": "^1.2.
|
|
80
|
+
"@iconify-json/octicon": "^1.2.16",
|
|
81
81
|
"@iconify-json/ph": "^1.2.2",
|
|
82
82
|
"@iconify-json/simple-icons": "^1.2.54",
|
|
83
83
|
"@iconify-json/streamline": "^1.2.5",
|
|
@@ -85,19 +85,19 @@
|
|
|
85
85
|
"@iconify-json/streamline-freehand-color": "^1.2.2",
|
|
86
86
|
"@iconify-json/system-uicons": "^1.2.4",
|
|
87
87
|
"@iconify-json/uil": "^1.2.3",
|
|
88
|
-
"@iconify-json/vscode-icons": "^1.2.
|
|
89
|
-
"@iconify/json": "^2.2.
|
|
88
|
+
"@iconify-json/vscode-icons": "^1.2.32",
|
|
89
|
+
"@iconify/json": "^2.2.397",
|
|
90
90
|
"@iconify/vue": "^5.0.0",
|
|
91
91
|
"@playform/compress": "^0.2.0",
|
|
92
92
|
"@playform/inline": "^0.1.2",
|
|
93
|
-
"@unocss/astro": "66.5.
|
|
94
|
-
"@unocss/preset-attributify": "66.5.
|
|
95
|
-
"@unocss/preset-typography": "66.5.
|
|
96
|
-
"@unocss/preset-uno": "66.5.
|
|
97
|
-
"@unocss/preset-web-fonts": "66.5.
|
|
98
|
-
"@unocss/preset-wind": "66.5.
|
|
99
|
-
"@unocss/reset": "66.5.
|
|
100
|
-
"@vite-pwa/astro": "^1.1.
|
|
93
|
+
"@unocss/astro": "66.5.4",
|
|
94
|
+
"@unocss/preset-attributify": "66.5.4",
|
|
95
|
+
"@unocss/preset-typography": "66.5.4",
|
|
96
|
+
"@unocss/preset-uno": "66.5.4",
|
|
97
|
+
"@unocss/preset-web-fonts": "66.5.4",
|
|
98
|
+
"@unocss/preset-wind": "66.5.4",
|
|
99
|
+
"@unocss/reset": "66.5.4",
|
|
100
|
+
"@vite-pwa/astro": "^1.1.1",
|
|
101
101
|
"@vueuse/core": "^13.9.0",
|
|
102
102
|
"astro-icon": "^1.1.5",
|
|
103
103
|
"astro-meta-tags": "^0.4.0",
|
|
@@ -106,30 +106,30 @@
|
|
|
106
106
|
"astro-remote": "^0.3.4",
|
|
107
107
|
"dotenv": "^17.2.3",
|
|
108
108
|
"swiper": "^12.0.2",
|
|
109
|
-
"unocss": "66.5.
|
|
109
|
+
"unocss": "66.5.4",
|
|
110
110
|
"vue": "^3.5.22"
|
|
111
111
|
},
|
|
112
112
|
"devDependencies": {
|
|
113
113
|
"@semantic-release/changelog": "^6.0.3",
|
|
114
114
|
"@semantic-release/git": "^10.0.1",
|
|
115
115
|
"@types/gtag.js": "^0.0.20",
|
|
116
|
-
"@types/node": "^24.
|
|
117
|
-
"@typescript-eslint/eslint-plugin": "^8.46.
|
|
118
|
-
"@typescript-eslint/parser": "^8.46.
|
|
119
|
-
"@unocss/transformer-variant-group": "66.5.
|
|
116
|
+
"@types/node": "^24.8.1",
|
|
117
|
+
"@typescript-eslint/eslint-plugin": "^8.46.1",
|
|
118
|
+
"@typescript-eslint/parser": "^8.46.1",
|
|
119
|
+
"@unocss/transformer-variant-group": "66.5.4",
|
|
120
120
|
"@vitejs/plugin-vue": "^6.0.1",
|
|
121
121
|
"@vue/compiler-sfc": "^3.5.22",
|
|
122
122
|
"@vue/eslint-config-typescript": "^14.6.0",
|
|
123
|
-
"astro": "^5.14.
|
|
123
|
+
"astro": "^5.14.6",
|
|
124
124
|
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
125
|
-
"eslint": "^9.
|
|
125
|
+
"eslint": "^9.38.0",
|
|
126
126
|
"eslint-plugin-astro": "^1.3.1",
|
|
127
|
-
"eslint-plugin-vue": "^10.5.
|
|
127
|
+
"eslint-plugin-vue": "^10.5.1",
|
|
128
128
|
"prettier": "^3.6.2",
|
|
129
129
|
"prettier-plugin-astro": "^0.14.1",
|
|
130
|
-
"semantic-release": "^
|
|
130
|
+
"semantic-release": "^25.0.1",
|
|
131
131
|
"unocss": "^0.65.0",
|
|
132
|
-
"vite": "^7.1.
|
|
132
|
+
"vite": "^7.1.11"
|
|
133
133
|
},
|
|
134
134
|
"packageManager": "pnpm@10.17.1",
|
|
135
135
|
"pnpm": {
|
|
@@ -1,8 +1,30 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue';
|
|
2
3
|
import { colors } from './../../uno-config/theme/colors';
|
|
3
4
|
|
|
4
5
|
// Get color categories
|
|
5
6
|
const colorCategories = Object.entries(colors);
|
|
7
|
+
|
|
8
|
+
// Track copied state for visual feedback
|
|
9
|
+
const copiedItem = ref<string | null>(null);
|
|
10
|
+
|
|
11
|
+
const copyToClipboard = async (text: string, id: string) => {
|
|
12
|
+
try {
|
|
13
|
+
await navigator.clipboard.writeText(text);
|
|
14
|
+
copiedItem.value = id;
|
|
15
|
+
setTimeout(() => {
|
|
16
|
+
copiedItem.value = null;
|
|
17
|
+
}, 2000);
|
|
18
|
+
} catch (err) {
|
|
19
|
+
console.error('Failed to copy:', err);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const getColorClass = (category: string, name: string) => {
|
|
24
|
+
// Generate Tailwind/UnoCSS class name
|
|
25
|
+
const colorName = name === 'default' ? category : `${category}-${name}`;
|
|
26
|
+
return colorName;
|
|
27
|
+
};
|
|
6
28
|
</script>
|
|
7
29
|
|
|
8
30
|
<template>
|
|
@@ -11,22 +33,82 @@ const colorCategories = Object.entries(colors);
|
|
|
11
33
|
v-for="[category, shades] in colorCategories"
|
|
12
34
|
:key="category"
|
|
13
35
|
>
|
|
14
|
-
<h3 class="capitalize">
|
|
36
|
+
<h3 class="capitalize text-xl font-bold mb-4">
|
|
15
37
|
{{ category }}
|
|
16
38
|
</h3>
|
|
17
|
-
<div class="grid grid-cols-
|
|
39
|
+
<div class="grid grid-cols-2 md:grid-cols-4 xl:grid-cols-5 gap-x-6 gap-y-10">
|
|
18
40
|
<div
|
|
19
41
|
v-for="(value, name) in shades"
|
|
20
42
|
:key="name"
|
|
21
|
-
class="
|
|
43
|
+
class="group relative"
|
|
22
44
|
>
|
|
23
|
-
|
|
24
|
-
|
|
45
|
+
<!-- Color Swatch -->
|
|
46
|
+
<button
|
|
47
|
+
class="w-full h-10 rounded-lg shadow-md transition-all duration-200 hover:shadow-xl hover:scale-105 cursor-pointer relative overflow-hidden"
|
|
25
48
|
:style="`background: ${value}`"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
49
|
+
:title="`Click to copy hex: ${value}`"
|
|
50
|
+
@click="copyToClipboard(value, `${category}-${name}-hex`)"
|
|
51
|
+
>
|
|
52
|
+
<!-- Copied indicator -->
|
|
53
|
+
<div
|
|
54
|
+
v-if="copiedItem === `${category}-${name}-hex`"
|
|
55
|
+
class="absolute inset-0 bg-black/50 flex items-center justify-center text-white font-bold text-sm"
|
|
56
|
+
>
|
|
57
|
+
✓ Copied!
|
|
58
|
+
</div>
|
|
59
|
+
</button>
|
|
60
|
+
|
|
61
|
+
<!-- Color Info -->
|
|
62
|
+
<div class="mt-2 space-y-1">
|
|
63
|
+
<!-- Color Name -->
|
|
64
|
+
<div class="text-sm font-medium text-gray-700 text-center">
|
|
65
|
+
{{ name }}
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<!-- Copy Buttons -->
|
|
69
|
+
<div class="flex gap-1 text-xs font-mono">
|
|
70
|
+
<!-- Copy Hex -->
|
|
71
|
+
<button
|
|
72
|
+
class="flex-1 px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded transition-colors text-gray-600 hover:text-gray-900 relative"
|
|
73
|
+
:title="`Copy hex: ${value}`"
|
|
74
|
+
@click="copyToClipboard(value, `${category}-${name}-hex`)"
|
|
75
|
+
>
|
|
76
|
+
<span
|
|
77
|
+
v-if="copiedItem === `${category}-${name}-hex`"
|
|
78
|
+
class="text-green-600"
|
|
79
|
+
>✓</span>
|
|
80
|
+
<span
|
|
81
|
+
v-else
|
|
82
|
+
class="uppercase text-xs"
|
|
83
|
+
>{{ value }}</span>
|
|
84
|
+
</button>
|
|
85
|
+
|
|
86
|
+
<!-- Copy Class Name (text-*) -->
|
|
87
|
+
<button
|
|
88
|
+
class="flex-1 px-2 py-1 bg-blue-100 hover:bg-blue-200 rounded transition-colors text-blue-700 hover:text-blue-900 relative"
|
|
89
|
+
:title="`Copy class: text-${getColorClass(category, name)}`"
|
|
90
|
+
@click="copyToClipboard(`text-${getColorClass(category, name)}`, `${category}-${name}-class`)"
|
|
91
|
+
>
|
|
92
|
+
<span
|
|
93
|
+
v-if="copiedItem === `${category}-${name}-class`"
|
|
94
|
+
class="text-green-600"
|
|
95
|
+
>✓</span>
|
|
96
|
+
<span v-else>text-</span>
|
|
97
|
+
</button>
|
|
98
|
+
|
|
99
|
+
<!-- Copy Class Name (bg-*) -->
|
|
100
|
+
<button
|
|
101
|
+
class="flex-1 px-2 py-1 bg-purple-100 hover:bg-purple-200 rounded transition-colors text-purple-700 hover:text-purple-900 relative"
|
|
102
|
+
:title="`Copy class: bg-${getColorClass(category, name)}`"
|
|
103
|
+
@click="copyToClipboard(`bg-${getColorClass(category, name)}`, `${category}-${name}-bg`)"
|
|
104
|
+
>
|
|
105
|
+
<span
|
|
106
|
+
v-if="copiedItem === `${category}-${name}-bg`"
|
|
107
|
+
class="text-green-600"
|
|
108
|
+
>✓</span>
|
|
109
|
+
<span v-else>bg-</span>
|
|
110
|
+
</button>
|
|
111
|
+
</div>
|
|
30
112
|
</div>
|
|
31
113
|
</div>
|
|
32
114
|
</div>
|
|
@@ -1,11 +1,40 @@
|
|
|
1
1
|
---
|
|
2
|
-
const { id, open } = Astro.props;
|
|
3
2
|
import Button from '../components/Button.vue';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
id: string;
|
|
6
|
+
open?: string;
|
|
7
|
+
title?: string;
|
|
8
|
+
maxWidth?: string;
|
|
9
|
+
showXButton?: boolean;
|
|
10
|
+
showTrigger?: boolean;
|
|
11
|
+
|
|
12
|
+
// Action buttons
|
|
13
|
+
showActions?: boolean;
|
|
14
|
+
cancelText?: string;
|
|
15
|
+
confirmText?: string;
|
|
16
|
+
confirmPrimary?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
id,
|
|
21
|
+
open = 'Open modal',
|
|
22
|
+
title,
|
|
23
|
+
maxWidth = '600px',
|
|
24
|
+
showXButton = true,
|
|
25
|
+
showTrigger = true,
|
|
26
|
+
showActions = false,
|
|
27
|
+
cancelText = 'Cancel',
|
|
28
|
+
confirmText = 'Confirm',
|
|
29
|
+
confirmPrimary = true,
|
|
30
|
+
} = Astro.props;
|
|
4
31
|
---
|
|
5
32
|
|
|
6
|
-
<style>
|
|
33
|
+
<style define:vars={{ maxWidth }}>
|
|
7
34
|
dialog {
|
|
8
|
-
@apply fixed top-0 left-0 right-0 bottom-0;
|
|
35
|
+
@apply fixed top-0 left-0 right-0 bottom-0 rounded-lg shadow-xl;
|
|
36
|
+
max-width: var(--maxWidth);
|
|
37
|
+
width: calc(100% - 2rem);
|
|
9
38
|
|
|
10
39
|
&::backdrop {
|
|
11
40
|
@apply bg-slate-medium/50 fixed;
|
|
@@ -15,20 +44,111 @@ import Button from '../components/Button.vue';
|
|
|
15
44
|
left: 0px;
|
|
16
45
|
}
|
|
17
46
|
}
|
|
47
|
+
|
|
48
|
+
.modal-header {
|
|
49
|
+
@apply relative pb-4 mb-4 border-b border-gray-300;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.modal-close-x {
|
|
53
|
+
@apply absolute top-0 right-0 w-8 h-8 flex items-center justify-center rounded-full hover:bg-gray-200 transition-colors cursor-pointer border-0 bg-transparent;
|
|
54
|
+
|
|
55
|
+
&::before,
|
|
56
|
+
&::after {
|
|
57
|
+
content: '';
|
|
58
|
+
position: absolute;
|
|
59
|
+
width: 16px;
|
|
60
|
+
height: 2px;
|
|
61
|
+
background-color: #666;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
&::before {
|
|
65
|
+
transform: rotate(45deg);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
&::after {
|
|
69
|
+
transform: rotate(-45deg);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
&:hover::before,
|
|
73
|
+
&:hover::after {
|
|
74
|
+
background-color: #000;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.modal-content {
|
|
79
|
+
@apply mb-4;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.modal-actions {
|
|
83
|
+
@apply flex gap-3 justify-end pt-4 border-t border-gray-300;
|
|
84
|
+
}
|
|
18
85
|
</style>
|
|
19
86
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
>
|
|
87
|
+
{showTrigger && (
|
|
88
|
+
<Button
|
|
89
|
+
primary
|
|
90
|
+
onclick={`window.${id}.showModal()`}
|
|
91
|
+
>{open}</Button
|
|
92
|
+
>
|
|
93
|
+
)}
|
|
25
94
|
|
|
26
95
|
<dialog
|
|
27
96
|
id={id}
|
|
28
97
|
class="p-6"
|
|
29
98
|
>
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
<slot name="
|
|
33
|
-
|
|
99
|
+
<div class="modal-header">
|
|
100
|
+
{title && <h2 class="text-2xl font-bold pr-8">{title}</h2>}
|
|
101
|
+
<slot name="header" />
|
|
102
|
+
|
|
103
|
+
{showXButton && (
|
|
104
|
+
<form method="dialog" class="inline">
|
|
105
|
+
<button
|
|
106
|
+
class="modal-close-x"
|
|
107
|
+
aria-label="Close"
|
|
108
|
+
type="submit"
|
|
109
|
+
/>
|
|
110
|
+
</form>
|
|
111
|
+
)}
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<div class="modal-content">
|
|
115
|
+
<slot name="main" />
|
|
116
|
+
<slot />
|
|
117
|
+
</div>
|
|
118
|
+
|
|
119
|
+
{showActions && (
|
|
120
|
+
<div class="modal-actions">
|
|
121
|
+
<slot name="actions">
|
|
122
|
+
<form method="dialog" class="contents">
|
|
123
|
+
<Button>{cancelText}</Button>
|
|
124
|
+
</form>
|
|
125
|
+
<Button primary={confirmPrimary} onclick={`document.getElementById('${id}').dispatchEvent(new CustomEvent('confirm', { detail: { id: '${id}' } }))`}>
|
|
126
|
+
{confirmText}
|
|
127
|
+
</Button>
|
|
128
|
+
</slot>
|
|
129
|
+
</div>
|
|
130
|
+
)}
|
|
131
|
+
|
|
132
|
+
{!showActions && (
|
|
133
|
+
<form method="dialog">
|
|
134
|
+
<slot name="close" />
|
|
135
|
+
</form>
|
|
136
|
+
)}
|
|
34
137
|
</dialog>
|
|
138
|
+
|
|
139
|
+
<script define:vars={{ id }}>
|
|
140
|
+
// Close on backdrop click
|
|
141
|
+
const dialog = document.getElementById(id);
|
|
142
|
+
dialog?.addEventListener('click', (e) => {
|
|
143
|
+
if (e.target === dialog) {
|
|
144
|
+
dialog.close();
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Close on Escape key
|
|
149
|
+
dialog?.addEventListener('keydown', (e) => {
|
|
150
|
+
if (e.key === 'Escape') {
|
|
151
|
+
dialog.close();
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
</script>
|