sykj 0.1.8 → 0.2.0

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.
@@ -0,0 +1,195 @@
1
+ <template>
2
+ <teleport to="body">
3
+ <!-- 单一外层 transition:mask + box 同步动画,使用 appear 支持首次入场 -->
4
+ <transition name="sy-fade" appear @after-leave="onAfterLeave">
5
+ <div v-if="visible" class="sy-mask" role="dialog" aria-modal="true">
6
+ <div class="sy-box">
7
+ <div class="sy-header" v-if="title">
8
+ <div class="icon">
9
+ <img
10
+ v-if="props.icon"
11
+ :src="getIcons(props.icon)"
12
+ :alt="props.icon"
13
+ />
14
+ </div>
15
+ {{ title }}
16
+ </div>
17
+ <div class="sy-content">
18
+ <div
19
+ v-if="message"
20
+ class="sy-message"
21
+ v-html="message"
22
+ ></div>
23
+ <input
24
+ v-if="type === 'prompt'"
25
+ v-model="inputValue"
26
+ class="sy-input"
27
+ :placeholder="inputPlaceholder"
28
+ />
29
+ </div>
30
+ <div class="sy-footer">
31
+ <!-- <button
32
+ v-if="type !== 'alert'"
33
+ class="sy-btn sy-btn--cancel"
34
+ @click="onCancel"
35
+ >
36
+ {{ cancelText }}
37
+ </button> -->
38
+ <sy-button
39
+ v-if="type !== 'alert'"
40
+ @click="onCancel"
41
+ type="info"
42
+ >
43
+ {{ cancelText }}
44
+ </sy-button>
45
+ <sy-button type="primary" @click="onConfirm">
46
+ {{ confirmText }}
47
+ </sy-button>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ </transition>
52
+ </teleport>
53
+ </template>
54
+
55
+ <script setup lang="ts">
56
+ import { ref } from 'vue'
57
+ import { SyButton } from '../../button/index'
58
+
59
+ interface Props {
60
+ type?: 'alert' | 'confirm' | 'prompt'
61
+ title?: string
62
+ message?: string
63
+ confirmText?: string
64
+ cancelText?: string
65
+ inputPlaceholder?: string
66
+ inputValue?: string
67
+ icon?: 'tip' | 'warning' | 'error'
68
+ }
69
+ const props = defineProps<Props>()
70
+ const emit = defineEmits(['requestClose', 'closed'])
71
+
72
+ const visible = ref(true)
73
+ const inputValue = ref(props.inputValue || '')
74
+ const closeResult = ref<{ type: 'confirm' | 'cancel'; value?: any } | null>(
75
+ null
76
+ )
77
+
78
+ const confirmText = props.confirmText || '确定'
79
+ const cancelText = props.cancelText || '取消'
80
+
81
+ function onConfirm() {
82
+ closeResult.value = { type: 'confirm', value: inputValue.value ?? true }
83
+ visible.value = false
84
+ emit('requestClose', closeResult.value) // optional: notify service
85
+ }
86
+ function onCancel() {
87
+ closeResult.value = { type: 'cancel' }
88
+ visible.value = false
89
+ emit('requestClose', closeResult.value)
90
+ }
91
+
92
+ // 当 leave 完成(动画播完)时触发
93
+ function onAfterLeave() {
94
+ emit('closed', closeResult.value)
95
+ }
96
+
97
+ function getIcons(icon: string) {
98
+ return new URL(`./assets/${icon}.png`, import.meta.url).href
99
+ }
100
+ </script>
101
+
102
+ <style scoped lang="scss">
103
+ /* 遮罩 */
104
+ .sy-mask {
105
+ position: fixed;
106
+ inset: 0;
107
+ background: rgba(0, 0, 0, 0.45);
108
+ display: flex;
109
+ align-items: center;
110
+ justify-content: center;
111
+ z-index: 2000;
112
+ color: black;
113
+ }
114
+
115
+ /* 弹窗主体 */
116
+ .sy-box {
117
+ min-width: 60%;
118
+ max-width: 80%;
119
+ background: #fff;
120
+ border-radius: 8px;
121
+ box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
122
+ padding: 30px 20px;
123
+ }
124
+ .sy-header {
125
+ font-weight: 600;
126
+ margin-bottom: 8px;
127
+ /* font-size: 16px; */
128
+ font-size: 1.6rem;
129
+ text-align: center;
130
+ letter-spacing: 0.4rem;
131
+
132
+ .icon {
133
+ // border: 1px solid red;
134
+ // height: 60px;
135
+ // padding: 10px;
136
+ display: flex;
137
+ justify-content: center;
138
+ align-items: center;
139
+
140
+ padding-bottom: 20px;
141
+ img {
142
+ // width: 60px;
143
+ height: 60px;
144
+ object-fit: contain;
145
+ }
146
+ }
147
+ }
148
+ .sy-content {
149
+ margin-bottom: 14px;
150
+ text-align: center;
151
+ font-size: 1.2rem;
152
+ opacity: 0.8;
153
+ padding: 10px 0;
154
+ }
155
+ .sy-message {
156
+ margin-bottom: 8px;
157
+ color: #333;
158
+ }
159
+ .sy-input {
160
+ width: 100%;
161
+ padding: 6px 10px;
162
+ border: 1px solid #ddd;
163
+ border-radius: 6px;
164
+ }
165
+ input::placeholder {
166
+ color: #00000090;
167
+ }
168
+ .sy-footer {
169
+ display: flex;
170
+ justify-content: center;
171
+ gap: 28px;
172
+ }
173
+
174
+ /* --- transition (外层 transition 控制遮罩,同时通过后代选择器让 box 做缩放) --- */
175
+ /* mask 的透明度动画 */
176
+ .sy-fade-enter-from,
177
+ .sy-fade-leave-to {
178
+ opacity: 0;
179
+ }
180
+ .sy-fade-enter-active,
181
+ .sy-fade-leave-active {
182
+ transition: opacity 250ms ease;
183
+ }
184
+
185
+ /* 同步为内层 sy-box 添加缩放效果(通过选择器在 transition 的不同阶段作用到子元素) */
186
+ .sy-fade-enter-from .sy-box,
187
+ .sy-fade-leave-to .sy-box {
188
+ transform: scale(0.92);
189
+ opacity: 0;
190
+ }
191
+ .sy-fade-enter-active .sy-box,
192
+ .sy-fade-leave-active .sy-box {
193
+ transition: all 250ms cubic-bezier(0.2, 0.8, 0.2, 1);
194
+ }
195
+ </style>
@@ -1,7 +1,13 @@
1
- import Vue from "vue";
1
+ import { App } from 'vue'
2
+
3
+ declare module '*.vue' {
4
+ import type { DefineComponent } from 'vue'
5
+ const component: DefineComponent<{}, {}, any>
6
+ export default component
7
+ }
2
8
 
3
9
  /** ElementUI component common definition */
4
- export declare class ElementUIComponent extends Vue {
10
+ export declare class ElementUIComponent {
5
11
  /** Install component into Vue */
6
- static install(vue: typeof Vue): void;
12
+ static install(app: App): void
7
13
  }
package/types/global.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  // types/global.d.ts
2
2
 
3
3
  // 确保 TypeScript 识别这是一个模块
4
- export {};
4
+ export {}
5
5
 
6
6
  declare global {
7
7
  interface Window {
8
- Vue: any;
9
- $sy: any;
8
+ Vue: any
9
+ $sy: any
10
10
  }
11
11
  }
package/types/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  // types/global.d.ts
2
2
 
3
3
  // 确保 TypeScript 识别这是一个模块
4
- export {};
4
+ export {}
package/lib/focus.ts DELETED
@@ -1,40 +0,0 @@
1
- // import { useKeyStore } from "./store";
2
- // console.log("🚀 ~ file: focus.ts:3 ~ useKeyStore:", useKeyStore)
3
- const globalKey = window.$sy.key;
4
- // const keyStore = useKeyStore()
5
-
6
- let st: any = null;
7
-
8
- document.addEventListener("focusin", (event) => {
9
- const target = event.target as HTMLElement;
10
- if (target?.tagName === "INPUT" || target?.tagName === "TEXTAREA") {
11
- if (!isEditableFormComponent(target)) return;
12
- clearTimeout(st);
13
- globalKey.open();
14
- globalKey.currentElement = event.target;
15
- }
16
- });
17
-
18
- document.addEventListener("focusout", (event) => {
19
- globalKey.close();
20
-
21
- // st = setTimeout(() => {
22
- // // globalKey.currentElement = null;
23
- // }, 100);
24
- // const target = event.target as HTMLElement;
25
- // if (target?.tagName === "INPUT" || target?.tagName === "TEXTAREA") {
26
- // // window.showKeyboard()
27
- // //
28
- // }
29
- });
30
-
31
- // 是否展示输入法
32
- const isEditableFormComponent = (el: HTMLElement): boolean => {
33
- const notType: Array<string> = ["checkbox", "radio"];
34
- if (!(el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement))
35
- return false; // 类型守卫
36
- if (el.readOnly || notType.includes(el.type)) {
37
- return false;
38
- }
39
- return true;
40
- };
package/lib/store.ts DELETED
@@ -1,5 +0,0 @@
1
- (window.globalThis as any).$sy = {
2
- key: {
3
- show_keyboard: false,
4
- },
5
- };