@globalbrain/sefirot 4.25.1 → 4.27.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/lib/components/SContent.vue +1 -0
- package/lib/components/SDataList.vue +30 -0
- package/lib/components/SDataListItem.vue +137 -0
- package/lib/components/SInputDropdown.vue +1 -0
- package/lib/components/SInputSegments.vue +1 -0
- package/lib/components/SMarkdown.vue +6 -6
- package/lib/components/STable.vue +7 -0
- package/lib/composables/DataList.ts +23 -0
- package/lib/composables/Markdown.ts +74 -1
- package/lib/composables/Table.ts +1 -0
- package/lib/mixins/DataList.ts +15 -0
- package/lib/mixins/Fundamental.ts +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { provideDataListState } from '../composables/DataList'
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(defineProps<{
|
|
6
|
+
labelWidth?: string
|
|
7
|
+
}>(), {
|
|
8
|
+
labelWidth: '128px'
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
provideDataListState({
|
|
12
|
+
labelWidth: computed(() => props.labelWidth)
|
|
13
|
+
})
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<template>
|
|
17
|
+
<div class="SDataList">
|
|
18
|
+
<slot />
|
|
19
|
+
</div>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<style scoped lang="postcss">
|
|
23
|
+
.SDataList :deep(.SDataListItem::after),
|
|
24
|
+
.SDataList :deep(.SDataListItem:first-child::before) {
|
|
25
|
+
display: block;
|
|
26
|
+
border-top: 1px dashed var(--c-divider);
|
|
27
|
+
width: 100%;
|
|
28
|
+
content: "";
|
|
29
|
+
}
|
|
30
|
+
</style>
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { Comment, Text, computed, useSlots } from 'vue'
|
|
3
|
+
import { useDataListState } from '../composables/DataList'
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(defineProps<{
|
|
6
|
+
dir?: 'row' | 'column'
|
|
7
|
+
maxWidth?: string
|
|
8
|
+
align?: 'left' | 'right'
|
|
9
|
+
preWrap?: boolean
|
|
10
|
+
lineClamp?: string | number
|
|
11
|
+
tnum?: boolean
|
|
12
|
+
}>(), {
|
|
13
|
+
dir: 'row',
|
|
14
|
+
maxWidth: '100%'
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
labelWidth
|
|
19
|
+
} = useDataListState()
|
|
20
|
+
|
|
21
|
+
const slots = useSlots()
|
|
22
|
+
|
|
23
|
+
const classes = computed(() => [
|
|
24
|
+
props.dir,
|
|
25
|
+
props.align,
|
|
26
|
+
{ 'pre-wrap': props.preWrap },
|
|
27
|
+
{ 'line-clamp': !!props.lineClamp },
|
|
28
|
+
{ tnum: props.tnum }
|
|
29
|
+
])
|
|
30
|
+
|
|
31
|
+
const labelStyles = computed(() => ({
|
|
32
|
+
width: props.dir === 'row' ? labelWidth.value : '100%'
|
|
33
|
+
}))
|
|
34
|
+
|
|
35
|
+
const valueStyles = computed(() => ({
|
|
36
|
+
'max-width': props.maxWidth,
|
|
37
|
+
'-webkit-line-clamp': props.lineClamp
|
|
38
|
+
}))
|
|
39
|
+
|
|
40
|
+
const hasValue = computed(() => hasSlotContent('value'))
|
|
41
|
+
|
|
42
|
+
function hasSlotContent(name = 'default'): boolean {
|
|
43
|
+
return !!slots[name]?.().some((s) => {
|
|
44
|
+
if (s.type === Comment) {
|
|
45
|
+
return false
|
|
46
|
+
}
|
|
47
|
+
if (s.type === Text && typeof s.children === 'string') {
|
|
48
|
+
return !!s.children.trim()
|
|
49
|
+
}
|
|
50
|
+
return true
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<template>
|
|
56
|
+
<div class="SDataListItem" :class="classes">
|
|
57
|
+
<div class="content">
|
|
58
|
+
<div class="label" :style="labelStyles">
|
|
59
|
+
<slot name="label" />
|
|
60
|
+
</div>
|
|
61
|
+
<div v-if="!hasValue" class="empty">
|
|
62
|
+
—
|
|
63
|
+
</div>
|
|
64
|
+
<div v-else-if="hasValue" class="value" :style="valueStyles">
|
|
65
|
+
<slot name="value" />
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</template>
|
|
70
|
+
|
|
71
|
+
<style scoped lang="postcss">
|
|
72
|
+
.SDataListItem {
|
|
73
|
+
width: 100%;
|
|
74
|
+
max-width: 100%;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.content {
|
|
78
|
+
display: flex;
|
|
79
|
+
padding: 10px 0;
|
|
80
|
+
min-height: 48px;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.label {
|
|
84
|
+
flex-shrink: 0;
|
|
85
|
+
padding: 2px 0;
|
|
86
|
+
line-height: 24px;
|
|
87
|
+
font-size: 14px;
|
|
88
|
+
color: var(--c-text-2);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.empty {
|
|
92
|
+
flex-grow: 1;
|
|
93
|
+
padding: 2px 0;
|
|
94
|
+
line-height: 24px;
|
|
95
|
+
font-size: 14px;
|
|
96
|
+
color: var(--c-text-3);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.value {
|
|
100
|
+
flex-grow: 1;
|
|
101
|
+
padding: 2px 0;
|
|
102
|
+
line-height: 24px;
|
|
103
|
+
font-size: 14px;
|
|
104
|
+
color: var(--c-text-1);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.SDataListItem.row .content {
|
|
108
|
+
flex-direction: row;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.SDataListItem.column .content {
|
|
112
|
+
flex-direction: column;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.SDataListItem.left .value {
|
|
116
|
+
text-align: left;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.SDataListItem.right .value {
|
|
120
|
+
text-align: right;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.SDataListItem.pre-wrap .value {
|
|
124
|
+
white-space: pre-wrap;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.SDataListItem.line-clamp .value {
|
|
128
|
+
display: -webkit-box;
|
|
129
|
+
-webkit-box-orient: vertical;
|
|
130
|
+
text-overflow: ellipsis;
|
|
131
|
+
overflow: hidden;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.SDataListItem.tnum .value {
|
|
135
|
+
font-feature-settings: "tnum";
|
|
136
|
+
}
|
|
137
|
+
</style>
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { type Component, computed } from 'vue'
|
|
3
|
-
import { useMarkdown } from '../composables/Markdown'
|
|
3
|
+
import { type UseMarkdownOptions, useMarkdown } from '../composables/Markdown'
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
export interface SMarkdownProps extends UseMarkdownOptions {
|
|
6
6
|
tag?: Component | string
|
|
7
7
|
content: string
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const props = withDefaults(defineProps<SMarkdownProps>(), {
|
|
11
11
|
tag: 'div',
|
|
12
12
|
html: true
|
|
13
13
|
})
|
|
14
14
|
|
|
15
|
-
const markdown = useMarkdown(
|
|
15
|
+
const markdown = useMarkdown(props)
|
|
16
16
|
const rendered = computed(() => markdown(props.content))
|
|
17
17
|
</script>
|
|
18
18
|
|
|
@@ -61,6 +61,13 @@ const cellOfColToGrow = computed(() => {
|
|
|
61
61
|
const colWidths = reactive<Record<string, string>>({})
|
|
62
62
|
const blockWidth = ref<number | undefined>()
|
|
63
63
|
|
|
64
|
+
watch(() => unref(props.options.columns), (columns) => {
|
|
65
|
+
Object.keys(columns).forEach((key) => {
|
|
66
|
+
const width = columns[key]?.width
|
|
67
|
+
if (width) { colWidths[key] = width }
|
|
68
|
+
})
|
|
69
|
+
}, { immediate: true, deep: true, flush: 'pre' })
|
|
70
|
+
|
|
64
71
|
const showHeader = computed(() => {
|
|
65
72
|
const header = unref(props.options.header)
|
|
66
73
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ComputedRef, inject, provide } from 'vue'
|
|
2
|
+
|
|
3
|
+
export interface DataListState {
|
|
4
|
+
labelWidth: ComputedRef<string>
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const DataListStateKey = 'sefirot-data-list-state-key'
|
|
8
|
+
|
|
9
|
+
export function provideDataListState(state: DataListState): void {
|
|
10
|
+
provide(DataListStateKey, state)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function useDataListState(): DataListState {
|
|
14
|
+
const state = inject<DataListState | null>(DataListStateKey, null) || null
|
|
15
|
+
if (!state) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
'Unexpected call to `useDataListState`. This probably means you are using'
|
|
18
|
+
+ '`<DDataList>` child component outside of `<DDataList>`. Make sure'
|
|
19
|
+
+ ' to wrap the component within `<DDataList>` component.'
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
return state
|
|
23
|
+
}
|
|
@@ -1,8 +1,71 @@
|
|
|
1
1
|
import DOMPurify, { type Config } from 'dompurify'
|
|
2
|
-
import MarkdownIt
|
|
2
|
+
import MarkdownIt from 'markdown-it'
|
|
3
3
|
|
|
4
4
|
export type UseMarkdown = (source: string, inline?: boolean) => string
|
|
5
5
|
|
|
6
|
+
// vendored for vue compatibility
|
|
7
|
+
export interface MarkdownItOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Set `true` to enable HTML tags in source. Be careful!
|
|
10
|
+
* That's not safe! You may need external sanitizer to protect output from XSS.
|
|
11
|
+
* It's better to extend features via plugins, instead of enabling HTML.
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
html?: boolean | undefined
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Set `true` to add '/' when closing single tags
|
|
18
|
+
* (`<br />`). This is needed only for full CommonMark compatibility. In real
|
|
19
|
+
* world you will need HTML output.
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
xhtmlOut?: boolean | undefined
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Set `true` to convert `\n` in paragraphs into `<br>`.
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
breaks?: boolean | undefined
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* CSS language class prefix for fenced blocks.
|
|
32
|
+
* Can be useful for external highlighters.
|
|
33
|
+
* @default 'language-'
|
|
34
|
+
*/
|
|
35
|
+
langPrefix?: string | undefined
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Set `true` to autoconvert URL-like text to links.
|
|
39
|
+
* @default false
|
|
40
|
+
*/
|
|
41
|
+
linkify?: boolean | undefined
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Set `true` to enable [some language-neutral replacement](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js) +
|
|
45
|
+
* quotes beautification (smartquotes).
|
|
46
|
+
* @default false
|
|
47
|
+
*/
|
|
48
|
+
typographer?: boolean | undefined
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Double + single quotes replacement
|
|
52
|
+
* pairs, when typographer enabled and smartquotes on. For example, you can
|
|
53
|
+
* use `'«»„“'` for Russian, `'„“‚‘'` for German, and
|
|
54
|
+
* `['«\xA0', '\xA0»', '‹\xA0', '\xA0›']` for French (including nbsp).
|
|
55
|
+
* @default '“”‘’'
|
|
56
|
+
*/
|
|
57
|
+
quotes?: string | string[]
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Highlighter function for fenced code blocks.
|
|
61
|
+
* Highlighter `function (str, lang, attrs)` should return escaped HTML. It can
|
|
62
|
+
* also return empty string if the source was not changed and should be escaped
|
|
63
|
+
* externally. If result starts with <pre... internal wrapper is skipped.
|
|
64
|
+
* @default null
|
|
65
|
+
*/
|
|
66
|
+
highlight?: ((str: string, lang: string, attrs: string) => string) | null | undefined
|
|
67
|
+
}
|
|
68
|
+
|
|
6
69
|
export interface UseMarkdownOptions extends MarkdownItOptions {
|
|
7
70
|
config?: (md: MarkdownIt) => void
|
|
8
71
|
/** @default false */
|
|
@@ -40,6 +103,16 @@ export function useMarkdown({
|
|
|
40
103
|
//
|
|
41
104
|
|
|
42
105
|
const md = new MarkdownIt({ html: true, linkify: true, ...options })
|
|
106
|
+
|
|
107
|
+
md.renderer.rules.ordered_list_open = (tokens, idx, options, env, self) => {
|
|
108
|
+
const token = tokens[idx]
|
|
109
|
+
const start = Number(token.attrGet('start')) - 1
|
|
110
|
+
if (start >= 0) {
|
|
111
|
+
token.attrSet('style', `counter-reset: s-medium-counter ${start}`)
|
|
112
|
+
}
|
|
113
|
+
return self.renderToken(tokens, idx, options)
|
|
114
|
+
}
|
|
115
|
+
|
|
43
116
|
config?.(md)
|
|
44
117
|
|
|
45
118
|
return (source, inline = _inline) => {
|
package/lib/composables/Table.ts
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type App } from 'vue'
|
|
2
|
+
import SDataList from '../components/SDataList.vue'
|
|
3
|
+
import SDataListItem from '../components/SDataListItem.vue'
|
|
4
|
+
|
|
5
|
+
export function mixin(app: App): void {
|
|
6
|
+
app.component('SDataList', SDataList)
|
|
7
|
+
app.component('SDataListItem', SDataListItem)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare module 'vue' {
|
|
11
|
+
export interface GlobalComponents {
|
|
12
|
+
SDataList: typeof SDataList
|
|
13
|
+
SDataListItem: typeof SDataListItem
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -6,6 +6,7 @@ import SModal from '../components/SModal.vue'
|
|
|
6
6
|
import STrans from '../components/STrans.vue'
|
|
7
7
|
import { mixin as mixinCard } from './Card'
|
|
8
8
|
import { mixin as mixinControl } from './Control'
|
|
9
|
+
import { mixin as mixinDataList } from './DataList'
|
|
9
10
|
import { mixin as mixinDesc } from './Desc'
|
|
10
11
|
import { mixin as mixinDoc } from './Doc'
|
|
11
12
|
import { mixin as mixinGrid } from './Grid'
|
|
@@ -14,6 +15,7 @@ import { mixin as mixinHead } from './Head'
|
|
|
14
15
|
export function mixin(app: App): void {
|
|
15
16
|
mixinCard(app)
|
|
16
17
|
mixinControl(app)
|
|
18
|
+
mixinDataList(app)
|
|
17
19
|
mixinDesc(app)
|
|
18
20
|
mixinDoc(app)
|
|
19
21
|
mixinGrid(app)
|
package/package.json
CHANGED