@keyfunc/keybricks-ds 2.7.0 → 2.8.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.
- package/DEPLOY.md +3 -3
- package/DESIGN.md +8 -1
- package/INTEGRATION.md +18 -2
- package/_adherence.oxlintrc.json +0 -1
- package/_ds_bundle.js +293 -307
- package/{components/feedback → _vue-services}/MESSAGE_SERVICES.md +2 -2
- package/_vue-services/_internal/MessageBoxView.vue +150 -0
- package/{components/feedback → _vue-services}/_internal/service-utils.js +0 -12
- package/_vue-services/message.js +87 -0
- package/changelog.js +10 -1
- package/components/_cards/modal.card.html +8 -2
- package/components/_cards/table.card.html +10 -1
- package/components/_cards/toast.card.html +11 -1
- package/components/_cards/tree.card.html +22 -1
- package/components/data/Table.d.ts +5 -0
- package/components/data/Table.jsx +10 -5
- package/components/data/Table.vue +9 -3
- package/components/data/data.prompt.md +2 -0
- package/components/data/row-open.js +13 -0
- package/components/feedback/Modal.d.ts +58 -7
- package/components/feedback/Modal.jsx +46 -16
- package/components/feedback/Modal.vue +24 -6
- package/components/feedback/Toast.vue +3 -3
- package/components/feedback/ToastStack.vue +37 -4
- package/components/feedback/feedback.prompt.md +5 -1
- package/components/feedback/modal-behavior.js +50 -0
- package/components/navigation/Tree.d.ts +5 -1
- package/components/navigation/Tree.jsx +9 -7
- package/components/navigation/Tree.vue +7 -6
- package/components/navigation/navigation.prompt.md +2 -0
- package/index.html +3 -3
- package/package.json +6 -5
- package/site-nav.js +1 -1
- package/tokens/tokens.json +1 -1
- package/components/feedback/_internal/MessageBoxView.vue +0 -237
- package/components/feedback/_internal/MessageView.vue +0 -73
- package/components/feedback/message.js +0 -68
- /package/{components/feedback → _vue-services}/message-box.d.ts +0 -0
- /package/{components/feedback → _vue-services}/message-box.js +0 -0
- /package/{components/feedback → _vue-services}/message.d.ts +0 -0
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import { computed, h, isVNode, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
3
|
-
import Toast from '../Toast.vue'
|
|
4
|
-
import Icon from '../../icons/Icon.vue'
|
|
5
|
-
import { contentNode } from './service-utils.js'
|
|
6
|
-
|
|
7
|
-
const props = defineProps({ options: { type: Object, required: true } })
|
|
8
|
-
const emit = defineEmits(['close', 'height'])
|
|
9
|
-
const root = ref(null)
|
|
10
|
-
const tone = computed(() => props.options.type === 'error' ? 'danger' : props.options.type)
|
|
11
|
-
const Content = () => contentNode(props.options.message, props.options.dangerouslyUseHTMLString)
|
|
12
|
-
const CustomIcon = () => typeof props.options.icon === 'string'
|
|
13
|
-
? h(Icon, { name: props.options.icon, size: 16 })
|
|
14
|
-
: isVNode(props.options.icon) ? props.options.icon : h(props.options.icon)
|
|
15
|
-
let timer
|
|
16
|
-
let observer
|
|
17
|
-
let paused = false
|
|
18
|
-
function stop() { clearTimeout(timer) }
|
|
19
|
-
function start() {
|
|
20
|
-
stop()
|
|
21
|
-
if (!paused && props.options.duration > 0) timer = setTimeout(() => emit('close'), props.options.duration)
|
|
22
|
-
}
|
|
23
|
-
function onEscape(event) {
|
|
24
|
-
if (event.key === 'Escape') emit('close')
|
|
25
|
-
}
|
|
26
|
-
watch(() => [props.options.restart, props.options.duration], start)
|
|
27
|
-
onMounted(() => {
|
|
28
|
-
start()
|
|
29
|
-
const measure = () => emit('height', root.value.getBoundingClientRect().height)
|
|
30
|
-
measure()
|
|
31
|
-
if (typeof ResizeObserver !== 'undefined') {
|
|
32
|
-
observer = new ResizeObserver(measure)
|
|
33
|
-
observer.observe(root.value)
|
|
34
|
-
}
|
|
35
|
-
document.addEventListener('keydown', onEscape)
|
|
36
|
-
})
|
|
37
|
-
onBeforeUnmount(() => {
|
|
38
|
-
stop()
|
|
39
|
-
observer?.disconnect()
|
|
40
|
-
document.removeEventListener('keydown', onEscape)
|
|
41
|
-
})
|
|
42
|
-
</script>
|
|
43
|
-
|
|
44
|
-
<template>
|
|
45
|
-
<div
|
|
46
|
-
:id="options.id"
|
|
47
|
-
ref="root"
|
|
48
|
-
:class="['kb-message', options.customClass, { 'kb-message--center': options.center, 'kb-message--plain': options.plain }]"
|
|
49
|
-
:role="options.type === 'error' || options.type === 'warning' ? 'alert' : 'status'"
|
|
50
|
-
:style="{ position: 'fixed', top: `${options.top}px`, left: '50%', transform: 'translateX(-50%)', zIndex: options.zIndex ?? 'var(--z-toast)', maxWidth: '92vw' }"
|
|
51
|
-
@mouseenter="paused = true; stop()"
|
|
52
|
-
@mouseleave="paused = false; start()"
|
|
53
|
-
@focusin="paused = true; stop()"
|
|
54
|
-
@focusout="paused = false; start()"
|
|
55
|
-
>
|
|
56
|
-
<Toast
|
|
57
|
-
:tone="tone"
|
|
58
|
-
:dismissible="options.showClose"
|
|
59
|
-
:close-label="options.closeLabel"
|
|
60
|
-
:style="{ minWidth: 'min(280px, 92vw)', maxWidth: '100%', boxSizing: 'border-box', ...(options.plain ? { boxShadow: 'none' } : {}) }"
|
|
61
|
-
@close="emit('close')"
|
|
62
|
-
>
|
|
63
|
-
<template v-if="options.icon" #icon><CustomIcon /></template>
|
|
64
|
-
<Content />
|
|
65
|
-
<span v-if="options.repeatNum > 1" class="kb-message__count"> × {{ options.repeatNum }}</span>
|
|
66
|
-
</Toast>
|
|
67
|
-
</div>
|
|
68
|
-
</template>
|
|
69
|
-
|
|
70
|
-
<style scoped>
|
|
71
|
-
.kb-message--center { text-align: center; }
|
|
72
|
-
.kb-message__count { color: var(--text-secondary); font-variant-numeric: tabular-nums; }
|
|
73
|
-
</style>
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { getCurrentInstance, isVNode, reactive } from 'vue'
|
|
2
|
-
import MessageView from './_internal/MessageView.vue'
|
|
3
|
-
import { mountService, resolveTarget } from './_internal/service-utils.js'
|
|
4
|
-
|
|
5
|
-
const instances = []
|
|
6
|
-
let seed = 0
|
|
7
|
-
const normalize = value => typeof value === 'string' || typeof value === 'function' || isVNode(value)
|
|
8
|
-
? { message: value } : { ...value }
|
|
9
|
-
|
|
10
|
-
/** Vue 消息服务;样式由 Toast 提供,业务错误脱敏仍由应用处理。 */
|
|
11
|
-
export function Message(value = {}, appContext) {
|
|
12
|
-
if (typeof document === 'undefined') return { close() {} }
|
|
13
|
-
const options = { type: 'info', duration: 3000, offset: 16, ...Message.defaults, ...normalize(value) }
|
|
14
|
-
const target = resolveTarget(options)
|
|
15
|
-
if (options.grouping) {
|
|
16
|
-
const existing = instances.find(item => item.target === target && item.options.message === options.message)
|
|
17
|
-
if (existing) {
|
|
18
|
-
existing.options.repeatNum++
|
|
19
|
-
existing.options.type = options.type
|
|
20
|
-
existing.options.restart++
|
|
21
|
-
return existing.handle
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
const state = reactive({ ...options, id: `kb-message-${++seed}`, repeatNum: 1, restart: 0, height: 0, top: options.offset })
|
|
25
|
-
let dispose
|
|
26
|
-
let closed = false
|
|
27
|
-
const handle = { close() {
|
|
28
|
-
if (closed) return
|
|
29
|
-
closed = true
|
|
30
|
-
instances.splice(instances.indexOf(entry), 1)
|
|
31
|
-
dispose?.()
|
|
32
|
-
reflow()
|
|
33
|
-
options.onClose?.(handle)
|
|
34
|
-
} }
|
|
35
|
-
const entry = { options: state, handle, target }
|
|
36
|
-
function reflow() {
|
|
37
|
-
const tops = new Map()
|
|
38
|
-
for (const item of instances) {
|
|
39
|
-
const target = item.target
|
|
40
|
-
item.options.top = Math.max(Number(item.options.offset) || 0, tops.get(target) || 0)
|
|
41
|
-
tops.set(target, item.options.top + item.options.height + 16)
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
instances.push(entry)
|
|
45
|
-
try {
|
|
46
|
-
dispose = mountService(MessageView, {
|
|
47
|
-
options: state, onClose: handle.close,
|
|
48
|
-
onHeight: height => { state.height = height; reflow() },
|
|
49
|
-
}, options, appContext || getCurrentInstance()?.appContext)
|
|
50
|
-
} catch (error) {
|
|
51
|
-
instances.splice(instances.indexOf(entry), 1)
|
|
52
|
-
reflow()
|
|
53
|
-
throw error
|
|
54
|
-
}
|
|
55
|
-
reflow()
|
|
56
|
-
return handle
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
for (const type of ['success', 'info', 'warning', 'error']) {
|
|
60
|
-
Message[type] = (value, appContext) => Message({ ...normalize(value), type }, appContext)
|
|
61
|
-
}
|
|
62
|
-
Message.closeAll = type => {
|
|
63
|
-
for (const entry of [...instances]) {
|
|
64
|
-
if (!type || entry.options.type === type) entry.handle.close()
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
export default Message
|
|
68
|
-
Message.defaults = {}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|