@m3ui-vue/m3ui-vue 0.1.1 → 0.1.2
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/README.md +1 -3
- package/dist/MIcon-CaEooCmZ.js +20 -0
- package/dist/MIcon-CaEooCmZ.js.map +1 -0
- package/dist/_plugin-vue_export-helper-B3ysoDQm.js +8 -0
- package/dist/chart.d.ts +1 -0
- package/dist/chart.js +141 -0
- package/dist/chart.js.map +1 -0
- package/dist/code-editor.d.ts +2 -0
- package/dist/code-editor.js +379 -0
- package/dist/code-editor.js.map +1 -0
- package/dist/components/MButton.vue.d.ts +1 -1
- package/dist/components/MCalendar.vue.d.ts +1 -1
- package/dist/components/MCodeEditor.vue.d.ts +3 -1
- package/dist/components/MDataTable.vue.d.ts +1 -1
- package/dist/components/MFab.vue.d.ts +0 -2
- package/dist/components/MIconButton.vue.d.ts +1 -1
- package/dist/components/MMultiSelect.vue.d.ts +1 -1
- package/dist/components/MProgressBar.vue.d.ts +1 -1
- package/dist/components/MRichTextEditor.vue.d.ts +1 -1
- package/dist/components/MScheduler.vue.d.ts +1 -1
- package/dist/components/MSelect.vue.d.ts +1 -1
- package/dist/components/MSkeleton.vue.d.ts +1 -1
- package/dist/components/MSpotlightSearch.vue.d.ts +1 -1
- package/dist/components/MStack.vue.d.ts +2 -2
- package/dist/components/MTerminal.vue.d.ts +2 -2
- package/dist/components/MTextField.vue.d.ts +1 -1
- package/dist/dist-Dsrzt6J5.js +1192 -0
- package/dist/dist-Dsrzt6J5.js.map +1 -0
- package/dist/index.d.ts +0 -6
- package/dist/m3ui-vue.css +2 -0
- package/dist/m3ui.js +2722 -3383
- package/dist/m3ui.js.map +1 -1
- package/dist/markdown.d.ts +1 -0
- package/dist/markdown.js +41 -0
- package/dist/markdown.js.map +1 -0
- package/dist/rich-text-editor.d.ts +1 -0
- package/dist/rich-text-editor.js +215 -0
- package/dist/rich-text-editor.js.map +1 -0
- package/dist/styles/theme.css +3 -0
- package/dist/styles.css +2 -0
- package/dist/terminal.d.ts +1 -0
- package/dist/terminal.js +97 -0
- package/dist/terminal.js.map +1 -0
- package/package.json +28 -2
- package/src/chart.ts +1 -0
- package/src/code-editor.ts +2 -0
- package/src/components/MAlert.vue +1 -1
- package/src/components/MCodeEditor.vue +99 -10
- package/src/components/MFab.vue +64 -48
- package/src/components/MMultiSelect.vue +3 -2
- package/src/components/MTooltip.vue +8 -1
- package/src/index.ts +6 -6
- package/src/markdown.ts +1 -0
- package/src/rich-text-editor.ts +1 -0
- package/src/styles/theme.css +3 -0
- package/src/terminal.ts +1 -0
- package/dist/m3ui.css +0 -2
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref, watch, onMounted, onBeforeUnmount, computed } from 'vue'
|
|
3
|
+
import MIcon from './MIcon.vue'
|
|
3
4
|
|
|
4
|
-
type Language = 'javascript' | 'typescript' | 'json' | 'html' | 'css' | 'python' | 'plain'
|
|
5
|
+
type Language = 'javascript' | 'typescript' | 'json' | 'html' | 'css' | 'python' | 'vue' | 'plain'
|
|
5
6
|
|
|
6
7
|
const props = withDefaults(
|
|
7
8
|
defineProps<{
|
|
@@ -13,6 +14,7 @@ const props = withDefaults(
|
|
|
13
14
|
minHeight?: string
|
|
14
15
|
maxHeight?: string
|
|
15
16
|
placeholder?: string
|
|
17
|
+
wrap?: boolean
|
|
16
18
|
}>(),
|
|
17
19
|
{
|
|
18
20
|
language: 'javascript',
|
|
@@ -21,6 +23,7 @@ const props = withDefaults(
|
|
|
21
23
|
theme: 'light',
|
|
22
24
|
minHeight: '200px',
|
|
23
25
|
maxHeight: '600px',
|
|
26
|
+
wrap: true,
|
|
24
27
|
},
|
|
25
28
|
)
|
|
26
29
|
|
|
@@ -29,6 +32,13 @@ const emit = defineEmits<{ 'update:modelValue': [string] }>()
|
|
|
29
32
|
const containerRef = ref<HTMLElement | null>(null)
|
|
30
33
|
let view: any = null
|
|
31
34
|
let cmModules: any = null
|
|
35
|
+
const copied = ref(false)
|
|
36
|
+
|
|
37
|
+
async function copyCode() {
|
|
38
|
+
await navigator.clipboard.writeText(props.modelValue)
|
|
39
|
+
copied.value = true
|
|
40
|
+
setTimeout(() => { copied.value = false }, 1500)
|
|
41
|
+
}
|
|
32
42
|
|
|
33
43
|
const langLabel = computed(() => {
|
|
34
44
|
const labels: Record<Language, string> = {
|
|
@@ -38,6 +48,7 @@ const langLabel = computed(() => {
|
|
|
38
48
|
html: 'HTML',
|
|
39
49
|
css: 'CSS',
|
|
40
50
|
python: 'Python',
|
|
51
|
+
vue: 'Vue',
|
|
41
52
|
plain: 'Texto',
|
|
42
53
|
}
|
|
43
54
|
return labels[props.language]
|
|
@@ -46,23 +57,71 @@ const langLabel = computed(() => {
|
|
|
46
57
|
async function loadModules() {
|
|
47
58
|
if (cmModules) return cmModules
|
|
48
59
|
|
|
49
|
-
const [viewMod, stateMod, commandsMod, languageMod, oneDarkMod, jsMod, jsonMod, htmlMod, cssMod, pyMod] = await Promise.all([
|
|
60
|
+
const [viewMod, stateMod, commandsMod, languageMod, highlightMod, oneDarkMod, jsMod, jsonMod, htmlMod, cssMod, pyMod, vueMod] = await Promise.all([
|
|
50
61
|
import('@codemirror/view'),
|
|
51
62
|
import('@codemirror/state'),
|
|
52
63
|
import('@codemirror/commands'),
|
|
53
64
|
import('@codemirror/language'),
|
|
65
|
+
import('@lezer/highlight'),
|
|
54
66
|
import('@codemirror/theme-one-dark'),
|
|
55
67
|
import('@codemirror/lang-javascript'),
|
|
56
68
|
import('@codemirror/lang-json'),
|
|
57
69
|
import('@codemirror/lang-html'),
|
|
58
70
|
import('@codemirror/lang-css'),
|
|
59
71
|
import('@codemirror/lang-python'),
|
|
72
|
+
import('@codemirror/lang-vue'),
|
|
60
73
|
])
|
|
61
74
|
|
|
62
|
-
cmModules = { viewMod, stateMod, commandsMod, languageMod, oneDarkMod, jsMod, jsonMod, htmlMod, cssMod, pyMod }
|
|
75
|
+
cmModules = { viewMod, stateMod, commandsMod, languageMod, highlightMod, oneDarkMod, jsMod, jsonMod, htmlMod, cssMod, pyMod, vueMod }
|
|
63
76
|
return cmModules
|
|
64
77
|
}
|
|
65
78
|
|
|
79
|
+
function buildM3HighlightStyle(languageMod: any, tags: any) {
|
|
80
|
+
return languageMod.HighlightStyle.define([
|
|
81
|
+
{ tag: tags.keyword, color: 'var(--color-primary)' },
|
|
82
|
+
{ tag: tags.controlKeyword, color: 'var(--color-primary)', fontWeight: '500' },
|
|
83
|
+
{ tag: tags.operatorKeyword, color: 'var(--color-primary)' },
|
|
84
|
+
{ tag: tags.definitionKeyword, color: 'var(--color-primary)' },
|
|
85
|
+
{ tag: tags.moduleKeyword, color: 'var(--color-primary)' },
|
|
86
|
+
|
|
87
|
+
{ tag: tags.string, color: 'var(--color-tertiary)' },
|
|
88
|
+
{ tag: tags.regexp, color: 'var(--color-tertiary)' },
|
|
89
|
+
|
|
90
|
+
{ tag: tags.number, color: 'var(--color-error)' },
|
|
91
|
+
{ tag: tags.bool, color: 'var(--color-error)' },
|
|
92
|
+
|
|
93
|
+
{ tag: tags.function(tags.variableName), color: 'var(--color-secondary)' },
|
|
94
|
+
{ tag: tags.function(tags.definition(tags.variableName)), color: 'var(--color-secondary)', fontWeight: '500' },
|
|
95
|
+
|
|
96
|
+
{ tag: tags.typeName, color: 'var(--color-primary)', fontStyle: 'italic' },
|
|
97
|
+
{ tag: tags.className, color: 'var(--color-primary)', fontStyle: 'italic' },
|
|
98
|
+
{ tag: tags.namespace, color: 'var(--color-on-surface-variant)' },
|
|
99
|
+
|
|
100
|
+
{ tag: tags.propertyName, color: 'var(--color-on-surface)' },
|
|
101
|
+
{ tag: tags.definition(tags.propertyName), color: 'var(--color-on-surface)' },
|
|
102
|
+
|
|
103
|
+
{ tag: tags.variableName, color: 'var(--color-on-surface)' },
|
|
104
|
+
{ tag: tags.definition(tags.variableName), color: 'var(--color-on-surface)' },
|
|
105
|
+
|
|
106
|
+
{ tag: tags.comment, color: 'var(--color-outline)', fontStyle: 'italic' },
|
|
107
|
+
{ tag: tags.lineComment, color: 'var(--color-outline)', fontStyle: 'italic' },
|
|
108
|
+
{ tag: tags.blockComment, color: 'var(--color-outline)', fontStyle: 'italic' },
|
|
109
|
+
|
|
110
|
+
{ tag: tags.meta, color: 'var(--color-on-surface-variant)' },
|
|
111
|
+
{ tag: tags.tagName, color: 'var(--color-primary)' },
|
|
112
|
+
{ tag: tags.attributeName, color: 'var(--color-tertiary)' },
|
|
113
|
+
{ tag: tags.attributeValue, color: 'var(--color-secondary)' },
|
|
114
|
+
|
|
115
|
+
{ tag: tags.atom, color: 'var(--color-error)' },
|
|
116
|
+
{ tag: tags.null, color: 'var(--color-error)' },
|
|
117
|
+
|
|
118
|
+
{ tag: tags.punctuation, color: 'var(--color-on-surface-variant)' },
|
|
119
|
+
{ tag: tags.bracket, color: 'var(--color-on-surface-variant)' },
|
|
120
|
+
{ tag: tags.operator, color: 'var(--color-on-surface-variant)' },
|
|
121
|
+
{ tag: tags.separator, color: 'var(--color-on-surface-variant)' },
|
|
122
|
+
])
|
|
123
|
+
}
|
|
124
|
+
|
|
66
125
|
function getLangExtension(mods: any) {
|
|
67
126
|
switch (props.language) {
|
|
68
127
|
case 'javascript': return mods.jsMod.javascript()
|
|
@@ -71,12 +130,15 @@ function getLangExtension(mods: any) {
|
|
|
71
130
|
case 'html': return mods.htmlMod.html()
|
|
72
131
|
case 'css': return mods.cssMod.css()
|
|
73
132
|
case 'python': return mods.pyMod.python()
|
|
133
|
+
case 'vue': return mods.vueMod.vue()
|
|
74
134
|
default: return []
|
|
75
135
|
}
|
|
76
136
|
}
|
|
77
137
|
|
|
78
138
|
function buildExtensions(mods: any) {
|
|
79
|
-
const { viewMod, stateMod, commandsMod, languageMod, oneDarkMod } = mods
|
|
139
|
+
const { viewMod, stateMod, commandsMod, languageMod, highlightMod, oneDarkMod } = mods
|
|
140
|
+
|
|
141
|
+
const m3Style = buildM3HighlightStyle(languageMod, highlightMod.tags)
|
|
80
142
|
|
|
81
143
|
const exts = [
|
|
82
144
|
viewMod.keymap.of([...commandsMod.defaultKeymap, ...commandsMod.historyKeymap, commandsMod.indentWithTab]),
|
|
@@ -86,6 +148,7 @@ function buildExtensions(mods: any) {
|
|
|
86
148
|
languageMod.foldGutter(),
|
|
87
149
|
viewMod.highlightActiveLine(),
|
|
88
150
|
viewMod.highlightActiveLineGutter(),
|
|
151
|
+
languageMod.syntaxHighlighting(m3Style),
|
|
89
152
|
languageMod.syntaxHighlighting(languageMod.defaultHighlightStyle, { fallback: true }),
|
|
90
153
|
getLangExtension(mods),
|
|
91
154
|
viewMod.EditorView.updateListener.of((update: any) => {
|
|
@@ -94,6 +157,7 @@ function buildExtensions(mods: any) {
|
|
|
94
157
|
stateMod.EditorState.readOnly.of(props.readonly),
|
|
95
158
|
]
|
|
96
159
|
|
|
160
|
+
if (props.wrap) exts.push(viewMod.EditorView.lineWrapping)
|
|
97
161
|
if (props.lineNumbers) exts.push(viewMod.lineNumbers())
|
|
98
162
|
if (props.theme === 'dark') exts.push(oneDarkMod.oneDark)
|
|
99
163
|
|
|
@@ -124,7 +188,7 @@ watch(() => props.modelValue, (val) => {
|
|
|
124
188
|
}
|
|
125
189
|
})
|
|
126
190
|
|
|
127
|
-
watch([() => props.language, () => props.theme, () => props.readonly, () => props.lineNumbers], createEditor)
|
|
191
|
+
watch([() => props.language, () => props.theme, () => props.readonly, () => props.lineNumbers, () => props.wrap], createEditor)
|
|
128
192
|
|
|
129
193
|
onBeforeUnmount(() => view?.destroy())
|
|
130
194
|
</script>
|
|
@@ -134,13 +198,24 @@ onBeforeUnmount(() => view?.destroy())
|
|
|
134
198
|
<!-- Header bar -->
|
|
135
199
|
<div class="flex items-center justify-between border-b border-outline-variant bg-surface-container px-4 py-2">
|
|
136
200
|
<span class="text-label-medium text-on-surface-variant">{{ langLabel }}</span>
|
|
137
|
-
<
|
|
201
|
+
<div class="flex items-center gap-2">
|
|
202
|
+
<slot name="actions" />
|
|
203
|
+
<button
|
|
204
|
+
type="button"
|
|
205
|
+
class="flex h-7 cursor-pointer items-center gap-1.5 rounded-md px-2 text-label-medium text-on-surface-variant transition-colors hover:bg-on-surface/8"
|
|
206
|
+
:title="copied ? 'Copied!' : 'Copy code'"
|
|
207
|
+
@click="copyCode"
|
|
208
|
+
>
|
|
209
|
+
<MIcon :name="copied ? 'check' : 'content_copy'" :size="16" :class="copied ? 'text-primary' : ''" />
|
|
210
|
+
<span v-if="copied" class="text-primary">Copied</span>
|
|
211
|
+
</button>
|
|
212
|
+
</div>
|
|
138
213
|
</div>
|
|
139
214
|
|
|
140
215
|
<!-- Editor -->
|
|
141
216
|
<div
|
|
142
217
|
ref="containerRef"
|
|
143
|
-
class="code-editor-container overflow-auto bg-surface"
|
|
218
|
+
class="code-editor-container overflow-auto bg-surface text-on-surface"
|
|
144
219
|
:style="{ minHeight, maxHeight }"
|
|
145
220
|
/>
|
|
146
221
|
</div>
|
|
@@ -150,8 +225,9 @@ onBeforeUnmount(() => view?.destroy())
|
|
|
150
225
|
.code-editor-container :deep(.cm-editor) {
|
|
151
226
|
height: 100%;
|
|
152
227
|
min-height: inherit;
|
|
153
|
-
font-family: '
|
|
154
|
-
font-size: 0.
|
|
228
|
+
font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;
|
|
229
|
+
font-size: 0.8125rem;
|
|
230
|
+
line-height: 1.6;
|
|
155
231
|
}
|
|
156
232
|
|
|
157
233
|
.code-editor-container :deep(.cm-editor.cm-focused) {
|
|
@@ -162,14 +238,25 @@ onBeforeUnmount(() => view?.destroy())
|
|
|
162
238
|
min-height: inherit;
|
|
163
239
|
}
|
|
164
240
|
|
|
241
|
+
.code-editor-container :deep(.cm-content) {
|
|
242
|
+
padding: 12px 0;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.code-editor-container :deep(.cm-line) {
|
|
246
|
+
padding: 0 16px;
|
|
247
|
+
}
|
|
248
|
+
|
|
165
249
|
.code-editor-container :deep(.cm-gutters) {
|
|
166
250
|
background: var(--color-surface-container);
|
|
167
251
|
border-right: 1px solid var(--color-outline-variant);
|
|
168
|
-
color: var(--color-
|
|
252
|
+
color: var(--color-outline);
|
|
253
|
+
font-size: 0.75rem;
|
|
254
|
+
padding: 0 4px;
|
|
169
255
|
}
|
|
170
256
|
|
|
171
257
|
.code-editor-container :deep(.cm-activeLineGutter) {
|
|
172
258
|
background: var(--color-surface-container-high);
|
|
259
|
+
color: var(--color-on-surface-variant);
|
|
173
260
|
}
|
|
174
261
|
|
|
175
262
|
.code-editor-container :deep(.cm-activeLine) {
|
|
@@ -182,11 +269,13 @@ onBeforeUnmount(() => view?.destroy())
|
|
|
182
269
|
|
|
183
270
|
.code-editor-container :deep(.cm-cursor) {
|
|
184
271
|
border-left-color: var(--color-primary);
|
|
272
|
+
border-left-width: 2px;
|
|
185
273
|
}
|
|
186
274
|
|
|
187
275
|
.code-editor-container :deep(.cm-matchingBracket) {
|
|
188
276
|
background: var(--color-tertiary-container);
|
|
189
277
|
color: var(--color-on-tertiary-container);
|
|
278
|
+
border-radius: 2px;
|
|
190
279
|
}
|
|
191
280
|
|
|
192
281
|
.code-editor-container :deep(.cm-foldGutter span) {
|
package/src/components/MFab.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
|
2
|
+
import { computed, onMounted, onUnmounted, ref, watch, nextTick } from 'vue'
|
|
3
3
|
import MIcon from './MIcon.vue'
|
|
4
4
|
|
|
5
5
|
export interface SpeedDialItem {
|
|
@@ -15,9 +15,7 @@ const props = withDefaults(
|
|
|
15
15
|
color?: 'primary' | 'secondary' | 'tertiary' | 'surface'
|
|
16
16
|
size?: 'small' | 'regular' | 'large'
|
|
17
17
|
disabled?: boolean
|
|
18
|
-
/** Speed-dial child items. If provided, clicking the FAB toggles them instead of emitting click. */
|
|
19
18
|
items?: SpeedDialItem[]
|
|
20
|
-
/** Direction the speed-dial items expand toward. */
|
|
21
19
|
direction?: 'up' | 'down' | 'left' | 'right' | 'radial'
|
|
22
20
|
}>(),
|
|
23
21
|
{
|
|
@@ -31,7 +29,7 @@ const props = withDefaults(
|
|
|
31
29
|
const emit = defineEmits<{ click: [MouseEvent] }>()
|
|
32
30
|
|
|
33
31
|
const open = ref(false)
|
|
34
|
-
const
|
|
32
|
+
const fabEl = ref<HTMLElement>()
|
|
35
33
|
|
|
36
34
|
const hasItems = computed(() => !!props.items?.length)
|
|
37
35
|
|
|
@@ -60,7 +58,6 @@ const fabIconSize = computed(() => {
|
|
|
60
58
|
}
|
|
61
59
|
})
|
|
62
60
|
|
|
63
|
-
// FAB height in px — used to position items relative to the container
|
|
64
61
|
const fabPx = computed(() => {
|
|
65
62
|
if (props.label) return 56
|
|
66
63
|
switch (props.size) {
|
|
@@ -70,17 +67,24 @@ const fabPx = computed(() => {
|
|
|
70
67
|
}
|
|
71
68
|
})
|
|
72
69
|
|
|
73
|
-
// Item size (always small-FAB-sized): 40px
|
|
74
70
|
const ITEM_PX = 40
|
|
75
71
|
const ITEM_GAP = 8
|
|
76
72
|
|
|
73
|
+
function getRect(): DOMRect | null {
|
|
74
|
+
return fabEl.value?.getBoundingClientRect() ?? null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
77
|
function itemStyle(index: number): Record<string, string> {
|
|
78
|
+
const rect = getRect()
|
|
79
|
+
if (!rect) return { position: 'fixed', opacity: '0', pointerEvents: 'none' }
|
|
80
|
+
|
|
81
|
+
const cx = rect.left + rect.width / 2
|
|
82
|
+
const cy = rect.top + rect.height / 2
|
|
78
83
|
const count = props.items?.length ?? 0
|
|
79
|
-
|
|
84
|
+
|
|
80
85
|
const delay = open.value
|
|
81
86
|
? `${index * 35}ms`
|
|
82
87
|
: `${(count - 1 - index) * 35}ms`
|
|
83
|
-
|
|
84
88
|
const transition = `transform 220ms cubic-bezier(0.2,0,0,1) ${delay}, opacity 180ms ease ${delay}`
|
|
85
89
|
|
|
86
90
|
if (props.direction === 'radial') {
|
|
@@ -89,27 +93,25 @@ function itemStyle(index: number): Record<string, string> {
|
|
|
89
93
|
const dx = (Math.cos(angle) * r).toFixed(1)
|
|
90
94
|
const dy = (Math.sin(angle) * r).toFixed(1)
|
|
91
95
|
return {
|
|
92
|
-
position: '
|
|
93
|
-
top:
|
|
94
|
-
left:
|
|
95
|
-
marginTop: `${-ITEM_PX / 2}px`,
|
|
96
|
-
marginLeft: `${-ITEM_PX / 2}px`,
|
|
96
|
+
position: 'fixed',
|
|
97
|
+
top: `${cy - ITEM_PX / 2}px`,
|
|
98
|
+
left: `${cx - ITEM_PX / 2}px`,
|
|
97
99
|
transform: open.value ? `translate(${dx}px, ${dy}px) scale(1)` : 'translate(0,0) scale(0)',
|
|
98
100
|
opacity: open.value ? '1' : '0',
|
|
99
101
|
transition,
|
|
100
102
|
pointerEvents: open.value ? 'auto' : 'none',
|
|
103
|
+
zIndex: '1000',
|
|
101
104
|
}
|
|
102
105
|
}
|
|
103
106
|
|
|
104
|
-
// Linear directions: offset from the container edge
|
|
105
107
|
const step = ITEM_PX + ITEM_GAP
|
|
106
|
-
const
|
|
108
|
+
const offset = fabPx.value / 2 + ITEM_GAP + ITEM_PX / 2 + index * step
|
|
107
109
|
|
|
108
|
-
const
|
|
109
|
-
up: {
|
|
110
|
-
down: { top:
|
|
111
|
-
left: {
|
|
112
|
-
right: {
|
|
110
|
+
const posMap: Record<string, { top: string; left: string }> = {
|
|
111
|
+
up: { top: `${cy - offset - ITEM_PX / 2}px`, left: `${cx - ITEM_PX / 2}px` },
|
|
112
|
+
down: { top: `${cy + offset - ITEM_PX / 2}px`, left: `${cx - ITEM_PX / 2}px` },
|
|
113
|
+
left: { top: `${cy - ITEM_PX / 2}px`, left: `${cx - offset - ITEM_PX / 2}px` },
|
|
114
|
+
right: { top: `${cy - ITEM_PX / 2}px`, left: `${cx + offset - ITEM_PX / 2}px` },
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
const translateFrom: Record<string, string> = {
|
|
@@ -119,19 +121,27 @@ function itemStyle(index: number): Record<string, string> {
|
|
|
119
121
|
right: 'translateX(-12px) scale(0.75)',
|
|
120
122
|
}
|
|
121
123
|
|
|
124
|
+
const pos = posMap[props.direction] ?? posMap.up
|
|
125
|
+
|
|
122
126
|
return {
|
|
123
|
-
position: '
|
|
124
|
-
...
|
|
127
|
+
position: 'fixed',
|
|
128
|
+
...pos,
|
|
125
129
|
transform: open.value ? 'translate(0,0) scale(1)' : (translateFrom[props.direction] ?? 'scale(0.75)'),
|
|
126
130
|
opacity: open.value ? '1' : '0',
|
|
127
131
|
transition,
|
|
128
132
|
pointerEvents: open.value ? 'auto' : 'none',
|
|
133
|
+
zIndex: '1000',
|
|
129
134
|
}
|
|
130
135
|
}
|
|
131
136
|
|
|
132
|
-
// Label only makes sense for up/down; placed to the left of the item button
|
|
133
137
|
const showLabel = computed(() => props.direction === 'up' || props.direction === 'down')
|
|
134
138
|
|
|
139
|
+
// Force re-render to recalculate positions on scroll
|
|
140
|
+
const scrollTick = ref(0)
|
|
141
|
+
function onScroll() {
|
|
142
|
+
if (open.value) scrollTick.value++
|
|
143
|
+
}
|
|
144
|
+
|
|
135
145
|
function createRipple(event: PointerEvent | MouseEvent, target?: HTMLElement) {
|
|
136
146
|
const button = (target ?? event.currentTarget) as HTMLElement
|
|
137
147
|
const rect = button.getBoundingClientRect()
|
|
@@ -159,19 +169,44 @@ function handleItemClick(e: PointerEvent, item: SpeedDialItem, buttonEl: HTMLEle
|
|
|
159
169
|
|
|
160
170
|
function onDocClick(e: MouseEvent) {
|
|
161
171
|
if (!open.value) return
|
|
162
|
-
if (
|
|
172
|
+
if (fabEl.value && !fabEl.value.contains(e.target as Node)) {
|
|
163
173
|
open.value = false
|
|
164
174
|
}
|
|
165
175
|
}
|
|
166
176
|
|
|
167
|
-
onMounted(() =>
|
|
168
|
-
|
|
177
|
+
onMounted(() => {
|
|
178
|
+
document.addEventListener('click', onDocClick, true)
|
|
179
|
+
window.addEventListener('scroll', onScroll, true)
|
|
180
|
+
})
|
|
181
|
+
onUnmounted(() => {
|
|
182
|
+
document.removeEventListener('click', onDocClick, true)
|
|
183
|
+
window.removeEventListener('scroll', onScroll, true)
|
|
184
|
+
})
|
|
169
185
|
</script>
|
|
170
186
|
|
|
171
187
|
<template>
|
|
172
|
-
<div ref="
|
|
173
|
-
|
|
188
|
+
<div ref="fabEl" class="relative inline-flex items-center justify-center">
|
|
189
|
+
<button
|
|
190
|
+
type="button"
|
|
191
|
+
class="relative inline-flex cursor-pointer items-center justify-center overflow-hidden shadow-elevation-1 transition-shadow duration-150 hover:shadow-elevation-2 active:shadow-elevation-1 disabled:cursor-not-allowed disabled:opacity-[0.38] before:content-[''] before:pointer-events-none before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:duration-150 hover:before:opacity-[0.08] active:before:opacity-[0.12]"
|
|
192
|
+
:class="[colorMap[color], fabSizeClasses]"
|
|
193
|
+
:disabled="disabled"
|
|
194
|
+
@pointerdown="(e) => { createRipple(e); handleFabClick(e) }"
|
|
195
|
+
>
|
|
196
|
+
<MIcon
|
|
197
|
+
:name="icon"
|
|
198
|
+
:size="fabIconSize"
|
|
199
|
+
class="transition-transform duration-300 ease-[cubic-bezier(0.34,1.56,0.64,1)]"
|
|
200
|
+
:class="hasItems && open ? 'rotate-45' : ''"
|
|
201
|
+
/>
|
|
202
|
+
<span v-if="label" class="text-label-large font-medium">{{ label }}</span>
|
|
203
|
+
</button>
|
|
204
|
+
</div>
|
|
205
|
+
|
|
206
|
+
<Teleport to="body">
|
|
174
207
|
<template v-if="hasItems">
|
|
208
|
+
<!-- hidden dep on scrollTick to force style recalc -->
|
|
209
|
+
<span :data-tick="scrollTick" class="hidden" />
|
|
175
210
|
<div
|
|
176
211
|
v-for="(item, i) in items"
|
|
177
212
|
:key="i"
|
|
@@ -179,7 +214,6 @@ onUnmounted(() => document.removeEventListener('click', onDocClick, true))
|
|
|
179
214
|
class="flex items-center gap-3"
|
|
180
215
|
:class="showLabel ? 'flex-row-reverse' : ''"
|
|
181
216
|
>
|
|
182
|
-
<!-- Label pill (up/down only) -->
|
|
183
217
|
<span
|
|
184
218
|
v-if="item.label && showLabel"
|
|
185
219
|
class="whitespace-nowrap rounded-md bg-surface-container-high px-3 py-1.5 text-label-medium text-on-surface shadow-elevation-1"
|
|
@@ -187,7 +221,6 @@ onUnmounted(() => document.removeEventListener('click', onDocClick, true))
|
|
|
187
221
|
{{ item.label }}
|
|
188
222
|
</span>
|
|
189
223
|
|
|
190
|
-
<!-- Mini FAB button -->
|
|
191
224
|
<button
|
|
192
225
|
type="button"
|
|
193
226
|
class="relative flex cursor-pointer items-center justify-center overflow-hidden rounded-lg shadow-elevation-1 transition-shadow duration-150 hover:shadow-elevation-2 active:shadow-elevation-1 before:content-[''] before:pointer-events-none before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:duration-150 hover:before:opacity-[0.08] active:before:opacity-[0.12]"
|
|
@@ -199,22 +232,5 @@ onUnmounted(() => document.removeEventListener('click', onDocClick, true))
|
|
|
199
232
|
</button>
|
|
200
233
|
</div>
|
|
201
234
|
</template>
|
|
202
|
-
|
|
203
|
-
<!-- Main FAB -->
|
|
204
|
-
<button
|
|
205
|
-
type="button"
|
|
206
|
-
class="relative inline-flex cursor-pointer items-center justify-center overflow-hidden shadow-elevation-1 transition-shadow duration-150 hover:shadow-elevation-2 active:shadow-elevation-1 disabled:cursor-not-allowed disabled:opacity-[0.38] before:content-[''] before:pointer-events-none before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:duration-150 hover:before:opacity-[0.08] active:before:opacity-[0.12]"
|
|
207
|
-
:class="[colorMap[color], fabSizeClasses]"
|
|
208
|
-
:disabled="disabled"
|
|
209
|
-
@pointerdown="(e) => { createRipple(e); handleFabClick(e) }"
|
|
210
|
-
>
|
|
211
|
-
<MIcon
|
|
212
|
-
:name="icon"
|
|
213
|
-
:size="fabIconSize"
|
|
214
|
-
class="transition-transform duration-300 ease-[cubic-bezier(0.34,1.56,0.64,1)]"
|
|
215
|
-
:class="hasItems && open ? 'rotate-45' : ''"
|
|
216
|
-
/>
|
|
217
|
-
<span v-if="label" class="text-label-large font-medium">{{ label }}</span>
|
|
218
|
-
</button>
|
|
219
|
-
</div>
|
|
235
|
+
</Teleport>
|
|
220
236
|
</template>
|
|
@@ -147,7 +147,8 @@ const triggerClasses = computed(() => {
|
|
|
147
147
|
|
|
148
148
|
return [
|
|
149
149
|
...base,
|
|
150
|
-
'rounded-t-sm bg-surface-container-highest border-b
|
|
150
|
+
'rounded-t-sm bg-surface-container-highest border-b pb-2',
|
|
151
|
+
hasValue.value || open.value ? 'pt-7' : 'pt-4',
|
|
151
152
|
open.value
|
|
152
153
|
? (props.error ? 'border-b-2 border-error' : 'border-b-2 border-primary')
|
|
153
154
|
: (props.error ? 'border-error' : 'border-on-surface-variant hover:border-on-surface'),
|
|
@@ -161,7 +162,7 @@ const labelClasses = computed(() => {
|
|
|
161
162
|
|
|
162
163
|
const floated = props.variant === 'outlined'
|
|
163
164
|
? '-top-2.5 translate-y-0 text-label-small bg-[var(--field-bg)] px-1 right-auto max-w-[calc(100%-1.5rem)]'
|
|
164
|
-
: 'top-
|
|
165
|
+
: 'top-2 translate-y-0 text-label-small'
|
|
165
166
|
|
|
166
167
|
const unFloated = 'top-1/2 -translate-y-1/2 text-body-large'
|
|
167
168
|
const active = open.value || hasValue.value
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { nextTick, ref } from 'vue'
|
|
2
|
+
import { nextTick, onMounted, onUnmounted, ref } from 'vue'
|
|
3
3
|
|
|
4
4
|
const props = withDefaults(defineProps<{
|
|
5
5
|
text: string
|
|
@@ -27,6 +27,10 @@ function hide() {
|
|
|
27
27
|
visible.value = false
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
function onScroll() {
|
|
31
|
+
if (visible.value) hide()
|
|
32
|
+
}
|
|
33
|
+
|
|
30
34
|
function reposition() {
|
|
31
35
|
if (!triggerEl.value || !tipEl.value) return
|
|
32
36
|
const tr = triggerEl.value.getBoundingClientRect()
|
|
@@ -45,6 +49,9 @@ function reposition() {
|
|
|
45
49
|
left = Math.max(6, Math.min(left, window.innerWidth - tt.width - 6))
|
|
46
50
|
tipStyle.value = { top: `${top}px`, left: `${left}px` }
|
|
47
51
|
}
|
|
52
|
+
|
|
53
|
+
onMounted(() => window.addEventListener('scroll', onScroll, true))
|
|
54
|
+
onUnmounted(() => window.removeEventListener('scroll', onScroll, true))
|
|
48
55
|
</script>
|
|
49
56
|
|
|
50
57
|
<template>
|
package/src/index.ts
CHANGED
|
@@ -21,10 +21,10 @@ export { default as MBreadcrumbs } from './components/MBreadcrumbs.vue'
|
|
|
21
21
|
export { default as MButton } from './components/MButton.vue'
|
|
22
22
|
export { default as MCalendar } from './components/MCalendar.vue'
|
|
23
23
|
export { default as MCard } from './components/MCard.vue'
|
|
24
|
-
|
|
24
|
+
// MChart — import from '@m3ui-vue/m3ui-vue/chart'
|
|
25
25
|
export { default as MCheckbox } from './components/MCheckbox.vue'
|
|
26
26
|
export { default as MChip } from './components/MChip.vue'
|
|
27
|
-
|
|
27
|
+
// MCodeEditor — import from '@m3ui-vue/m3ui-vue/code-editor'
|
|
28
28
|
export { default as MColorPicker } from './components/MColorPicker.vue'
|
|
29
29
|
export { default as MCommandPalette } from './components/MCommandPalette.vue'
|
|
30
30
|
export { default as MConfirmDialog } from './components/MConfirmDialog.vue'
|
|
@@ -45,11 +45,11 @@ export { default as MHotkeys } from './components/MHotkeys.vue'
|
|
|
45
45
|
export { default as MIcon } from './components/MIcon.vue'
|
|
46
46
|
export { default as MIconButton } from './components/MIconButton.vue'
|
|
47
47
|
export { default as MInfiniteScroll } from './components/MInfiniteScroll.vue'
|
|
48
|
-
|
|
48
|
+
// MJsonEditor — import from '@m3ui-vue/m3ui-vue/code-editor'
|
|
49
49
|
export { default as MJsonViewer } from './components/MJsonViewer.vue'
|
|
50
50
|
export { default as MKanban } from './components/MKanban.vue'
|
|
51
51
|
export { default as MLoadingOverlay } from './components/MLoadingOverlay.vue'
|
|
52
|
-
|
|
52
|
+
// MMarkdown — import from '@m3ui-vue/m3ui-vue/markdown'
|
|
53
53
|
export { default as MMasonry } from './components/MMasonry.vue'
|
|
54
54
|
export { default as MMenu } from './components/MMenu.vue'
|
|
55
55
|
export { default as MMenuItem } from './components/MMenuItem.vue'
|
|
@@ -63,7 +63,7 @@ export { default as MRadio } from './components/MRadio.vue'
|
|
|
63
63
|
export { default as MRadioGroup } from './components/MRadioGroup.vue'
|
|
64
64
|
export { default as MRating } from './components/MRating.vue'
|
|
65
65
|
export { default as MResult } from './components/MResult.vue'
|
|
66
|
-
|
|
66
|
+
// MRichTextEditor — import from '@m3ui-vue/m3ui-vue/rich-text-editor'
|
|
67
67
|
export { default as MScheduler } from './components/MScheduler.vue'
|
|
68
68
|
export { default as MSegmentedButton } from './components/MSegmentedButton.vue'
|
|
69
69
|
export { default as MSelect } from './components/MSelect.vue'
|
|
@@ -80,7 +80,7 @@ export { default as MStepper } from './components/MStepper.vue'
|
|
|
80
80
|
export { default as MSwitch } from './components/MSwitch.vue'
|
|
81
81
|
export { default as MTable } from './components/MTable.vue'
|
|
82
82
|
export { default as MTabs } from './components/MTabs.vue'
|
|
83
|
-
|
|
83
|
+
// MTerminal — import from '@m3ui-vue/m3ui-vue/terminal'
|
|
84
84
|
export { default as MTextField } from './components/MTextField.vue'
|
|
85
85
|
export { default as MTimeline } from './components/MTimeline.vue'
|
|
86
86
|
export { default as MTimePicker } from './components/MTimePicker.vue'
|
package/src/markdown.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as MMarkdown } from './components/MMarkdown.vue'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as MRichTextEditor } from './components/MRichTextEditor.vue'
|
package/src/styles/theme.css
CHANGED
package/src/terminal.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as MTerminal } from './components/MTerminal.vue'
|
package/dist/m3ui.css
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
.bs-scrim[data-v-941a89e7]{transition:opacity .3s}.bs-enter-from .bs-scrim[data-v-941a89e7],.bs-leave-to .bs-scrim[data-v-941a89e7]{opacity:0}.bs-panel[data-v-941a89e7]{transition:transform .32s cubic-bezier(.2,0,0,1),opacity .24s}.bs-enter-from .bs-panel[data-v-941a89e7]{opacity:0;transform:translateY(40%)}.bs-leave-to .bs-panel[data-v-941a89e7]{opacity:0;transform:translateY(100%)!important}@keyframes m3-wavy-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes m3-wavy-travel{0%{stroke-dashoffset:0}to{stroke-dashoffset:calc(var(--m3-wave-len) * -1px)}}@media (prefers-reduced-motion:reduce){.animate-\[m3-wavy-spin_2\.8s_linear_infinite\]{animation:2.8s linear infinite m3-wavy-spin}.animate-\[m3-wavy-travel_2s_linear_infinite\]{animation:none!important}}.code-editor-container[data-v-5274a428] .cm-editor{height:100%;min-height:inherit;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:.875rem}.code-editor-container[data-v-5274a428] .cm-editor.cm-focused{outline:none}.code-editor-container[data-v-5274a428] .cm-scroller{min-height:inherit}.code-editor-container[data-v-5274a428] .cm-gutters{background:var(--color-surface-container);border-right:1px solid var(--color-outline-variant);color:var(--color-on-surface-variant)}.code-editor-container[data-v-5274a428] .cm-activeLineGutter{background:var(--color-surface-container-high)}.code-editor-container[data-v-5274a428] .cm-activeLine{background:var(--color-surface-container-lowest)}.code-editor-container[data-v-5274a428] .cm-selectionBackground{background:var(--color-primary-container)!important}.code-editor-container[data-v-5274a428] .cm-cursor{border-left-color:var(--color-primary)}.code-editor-container[data-v-5274a428] .cm-matchingBracket{background:var(--color-tertiary-container);color:var(--color-on-tertiary-container)}.code-editor-container[data-v-5274a428] .cm-foldGutter span{color:var(--color-on-surface-variant)}.hue-slider[data-v-9ee0043f]{background:linear-gradient(90deg,red 0%,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%)}.hue-slider[data-v-9ee0043f]::-webkit-slider-thumb{-webkit-appearance:none;cursor:pointer;background:#fff;border-radius:50%;width:16px;height:16px;box-shadow:0 1px 3px #0006}.hue-slider[data-v-9ee0043f]::-moz-range-thumb{cursor:pointer;background:#fff;border:none;border-radius:50%;width:16px;height:16px;box-shadow:0 1px 3px #0006}.m3-cmd-enter-active[data-v-da578f14],.m3-cmd-leave-active[data-v-da578f14]{transition:opacity .15s}.m3-cmd-enter-from[data-v-da578f14],.m3-cmd-leave-to[data-v-da578f14]{opacity:0}.m3-cmd-enter-active .cmd-box[data-v-da578f14],.m3-cmd-leave-active .cmd-box[data-v-da578f14]{transition:transform .15s}.m3-cmd-enter-from .cmd-box[data-v-da578f14],.m3-cmd-leave-to .cmd-box[data-v-da578f14]{transform:scale(.95)translateY(-10px)}.m3-dialog-enter-active[data-v-e7dfca29],.m3-dialog-leave-active[data-v-e7dfca29]{transition:opacity .15s}.m3-dialog-enter-from[data-v-e7dfca29],.m3-dialog-leave-to[data-v-e7dfca29]{opacity:0}.m3-dialog-enter-active .dialog-box[data-v-e7dfca29],.m3-dialog-leave-active .dialog-box[data-v-e7dfca29]{transition:transform .15s}.m3-dialog-enter-from .dialog-box[data-v-e7dfca29],.m3-dialog-leave-to .dialog-box[data-v-e7dfca29]{transform:scale(.95)}.expand-grid[data-v-89e4475b]{grid-template-rows:1fr;display:grid}.expand-body[data-v-89e4475b]{min-height:0;overflow:hidden}.expand-enter-active[data-v-89e4475b]{transition:grid-template-rows .28s cubic-bezier(.2,0,0,1)}.expand-enter-active>.expand-body[data-v-89e4475b]{transition:opacity .22s}.expand-enter-from[data-v-89e4475b]{grid-template-rows:0fr}.expand-enter-from>.expand-body[data-v-89e4475b]{opacity:0}.expand-leave-active[data-v-89e4475b]{transition:grid-template-rows .22s cubic-bezier(.4,0,1,1)}.expand-leave-active>.expand-body[data-v-89e4475b]{transition:opacity .15s}.expand-leave-to[data-v-89e4475b]{grid-template-rows:0fr}.expand-leave-to>.expand-body[data-v-89e4475b]{opacity:0}.m3-file-enter-active[data-v-34a862f0],.m3-file-leave-active[data-v-34a862f0]{transition:all .2s}.m3-file-enter-from[data-v-34a862f0],.m3-file-leave-to[data-v-34a862f0]{opacity:0;transform:translateY(-8px)}.m3-markdown[data-v-6e4dc2b6] h1{font-size:var(--text-headline-large);line-height:var(--text-headline-large--line-height);color:var(--color-on-surface);margin:1em 0 .5em;font-weight:600}.m3-markdown[data-v-6e4dc2b6] h2{font-size:var(--text-headline-medium);line-height:var(--text-headline-medium--line-height);color:var(--color-on-surface);margin:1em 0 .5em;font-weight:600}.m3-markdown[data-v-6e4dc2b6] h3{font-size:var(--text-headline-small);line-height:var(--text-headline-small--line-height);color:var(--color-on-surface);margin:.75em 0 .25em;font-weight:600}.m3-markdown[data-v-6e4dc2b6] h4{font-size:var(--text-title-large);line-height:var(--text-title-large--line-height);color:var(--color-on-surface);margin:.75em 0 .25em;font-weight:600}.m3-markdown[data-v-6e4dc2b6] p{margin:.5em 0}.m3-markdown[data-v-6e4dc2b6] a{color:var(--color-primary);text-underline-offset:2px;text-decoration:underline}.m3-markdown[data-v-6e4dc2b6] a:hover{opacity:.8}.m3-markdown[data-v-6e4dc2b6] strong{color:var(--color-on-surface);font-weight:600}.m3-markdown[data-v-6e4dc2b6] em{font-style:italic}.m3-markdown[data-v-6e4dc2b6] ul,.m3-markdown[data-v-6e4dc2b6] ol{margin:.5em 0;padding-left:1.5em}.m3-markdown[data-v-6e4dc2b6] li{margin:.25em 0}.m3-markdown[data-v-6e4dc2b6] li::marker{color:var(--color-on-surface-variant)}.m3-markdown[data-v-6e4dc2b6] blockquote{border-left:3px solid var(--color-primary);background:var(--color-surface-container);color:var(--color-on-surface-variant);border-radius:0 8px 8px 0;margin:.75em 0;padding:.5em 1em}.m3-markdown[data-v-6e4dc2b6] code{background:var(--color-surface-container-highest);color:var(--color-primary);border-radius:4px;padding:.15em .4em;font-family:JetBrains Mono,Fira Code,monospace;font-size:.875em}.m3-markdown[data-v-6e4dc2b6] pre{background:var(--color-surface-container-highest);border:1px solid var(--color-outline-variant);border-radius:12px;margin:.75em 0;padding:1em;overflow-x:auto}.m3-markdown[data-v-6e4dc2b6] pre code{color:var(--color-on-surface);background:0 0;padding:0}.m3-markdown[data-v-6e4dc2b6] hr{border:none;border-top:1px solid var(--color-outline-variant);margin:1.5em 0}.m3-markdown[data-v-6e4dc2b6] table{border-collapse:collapse;width:100%;margin:.75em 0}.m3-markdown[data-v-6e4dc2b6] th{background:var(--color-surface-container);text-align:left;border-bottom:2px solid var(--color-outline-variant);font-weight:600;font-size:var(--text-label-large);color:var(--color-on-surface);padding:.5em .75em}.m3-markdown[data-v-6e4dc2b6] td{border-bottom:1px solid var(--color-outline-variant);padding:.5em .75em}.m3-markdown[data-v-6e4dc2b6] img{border-radius:12px;max-width:100%;height:auto;margin:.5em 0}.nd-scrim[data-v-98c11a62]{transition:opacity .28s}.nd-enter-from .nd-scrim[data-v-98c11a62],.nd-leave-to .nd-scrim[data-v-98c11a62]{opacity:0}.nd-panel[data-v-98c11a62]{transition:transform .3s cubic-bezier(.2,0,0,1)}.nd-enter-from .nd-panel[data-v-98c11a62],.nd-leave-to .nd-panel[data-v-98c11a62]{transform:translate(-100%)}@keyframes m3-wave-flow{0%{transform:translate(0)}to{transform:translate(-20px)}}@keyframes m3-progress-indeterminate{0%{left:-40%}to{left:100%}}@media (prefers-reduced-motion:reduce){.animate-\[m3-wave-flow_1\.2s_linear_infinite\],.animate-\[m3-wave-flow_0\.9s_linear_infinite\],.animate-\[m3-progress-indeterminate_1\.6s_ease-in-out_infinite\]{animation:none!important}}.m3-radio-dot[data-v-cdb650b5]{transform-box:fill-box;transform-origin:50%;transition:transform .15s;transform:scale(0)}.m3-radio-dot.is-checked[data-v-cdb650b5]{transform:scale(1)}.rte-content[data-v-89c08c83] .tiptap{min-height:inherit;outline:none}.rte-content[data-v-89c08c83] .tiptap p.is-editor-empty:first-child:before{content:attr(data-placeholder);float:left;color:var(--color-on-surface-variant);opacity:.5;pointer-events:none;height:0}.rte-content[data-v-89c08c83] h1{font-size:var(--text-headline-large);line-height:var(--text-headline-large--line-height);margin:.75em 0 .25em;font-weight:600}.rte-content[data-v-89c08c83] h2{font-size:var(--text-headline-medium);line-height:var(--text-headline-medium--line-height);margin:.75em 0 .25em;font-weight:600}.rte-content[data-v-89c08c83] h3{font-size:var(--text-headline-small);line-height:var(--text-headline-small--line-height);margin:.75em 0 .25em;font-weight:600}.rte-content[data-v-89c08c83] p{margin:.5em 0}.rte-content[data-v-89c08c83] ul,.rte-content[data-v-89c08c83] ol{margin:.5em 0;padding-left:1.5em}.rte-content[data-v-89c08c83] blockquote{border-left:3px solid var(--color-primary);color:var(--color-on-surface-variant);margin:.5em 0;padding-left:1em}.rte-content[data-v-89c08c83] code{background:var(--color-surface-container-highest);border-radius:4px;padding:.15em .4em;font-size:.875em}.rte-content[data-v-89c08c83] pre{background:var(--color-surface-container-highest);border-radius:8px;margin:.5em 0;padding:1em;overflow-x:auto}.rte-content[data-v-89c08c83] pre code{background:0 0;padding:0}.rte-content[data-v-89c08c83] a{color:var(--color-primary);text-decoration:underline}.rte-content[data-v-89c08c83] mark{background:var(--color-tertiary-container);color:var(--color-on-tertiary-container);border-radius:2px;padding:.1em .2em}.rte-content[data-v-89c08c83] img{border-radius:8px;max-width:100%;height:auto;margin:.5em 0}.ss-scrim[data-v-f8751672]{transition:opacity .28s}.ss-enter-from .ss-scrim[data-v-f8751672],.ss-leave-to .ss-scrim[data-v-f8751672]{opacity:0}.ss-panel[data-v-f8751672]{transition:transform .32s cubic-bezier(.2,0,0,1),opacity .24s}.ss-enter-from .ss-panel[data-v-f8751672]{opacity:0;transform:translate(40%)}.ss-leave-to .ss-panel[data-v-f8751672]{opacity:0;transform:translate(100%)!important}@keyframes skeleton-wave-move-32ecf05b{0%{transform:translate(-100%)}60%{transform:translate(100%)}to{transform:translate(100%)}}.skeleton-wave[data-v-32ecf05b]{position:relative;overflow:hidden}.skeleton-wave[data-v-32ecf05b]:after{content:"";background:linear-gradient(90deg, transparent 0%, var(--color-on-surface) 50%, transparent 100%);opacity:.06;animation:1.8s ease-in-out infinite skeleton-wave-move-32ecf05b;position:absolute;inset:0}.toast-row[data-v-e83a5c10]{grid-template-rows:1fr;padding-bottom:8px;display:grid}.toast-row>.toast-inner[data-v-e83a5c10]{min-height:0}.m3-toast-bot-enter-active[data-v-e83a5c10]{transition:grid-template-rows .22s cubic-bezier(.2,0,0,1),padding-bottom .22s cubic-bezier(.2,0,0,1);overflow:hidden}.m3-toast-bot-enter-active>.toast-inner[data-v-e83a5c10]{transition:opacity .18s,transform .22s cubic-bezier(.2,0,0,1)}.m3-toast-bot-enter-from[data-v-e83a5c10]{grid-template-rows:0fr;padding-bottom:0}.m3-toast-bot-enter-from>.toast-inner[data-v-e83a5c10]{opacity:0;transform:translateY(20px)scale(.94)}.m3-toast-bot-leave-active[data-v-e83a5c10]{transition:grid-template-rows .3s cubic-bezier(.2,0,0,1),padding-bottom .3s cubic-bezier(.2,0,0,1);overflow:hidden}.m3-toast-bot-leave-active>.toast-inner[data-v-e83a5c10]{transition:opacity .18s,transform .18s}.m3-toast-bot-leave-to[data-v-e83a5c10]{grid-template-rows:0fr;padding-bottom:0}.m3-toast-bot-leave-to>.toast-inner[data-v-e83a5c10]{opacity:0;transform:scale(.92)}.m3-toast-top-enter-active[data-v-e83a5c10]{transition:grid-template-rows .22s cubic-bezier(.2,0,0,1),padding-bottom .22s cubic-bezier(.2,0,0,1);overflow:hidden}.m3-toast-top-enter-active>.toast-inner[data-v-e83a5c10]{transition:opacity .18s,transform .22s cubic-bezier(.2,0,0,1)}.m3-toast-top-enter-from[data-v-e83a5c10]{grid-template-rows:0fr;padding-bottom:0}.m3-toast-top-enter-from>.toast-inner[data-v-e83a5c10]{opacity:0;transform:translateY(-20px)scale(.94)}.m3-toast-top-leave-active[data-v-e83a5c10]{transition:grid-template-rows .3s cubic-bezier(.2,0,0,1),padding-bottom .3s cubic-bezier(.2,0,0,1);overflow:hidden}.m3-toast-top-leave-active>.toast-inner[data-v-e83a5c10]{transition:opacity .18s,transform .18s}.m3-toast-top-leave-to[data-v-e83a5c10]{grid-template-rows:0fr;padding-bottom:0}.m3-toast-top-leave-to>.toast-inner[data-v-e83a5c10]{opacity:0;transform:scale(.92)}@keyframes m3-toast-progress-e83a5c10{0%{transform:scaleX(1)}to{transform:scaleX(0)}}.m3-spot-enter-active[data-v-51b103ff],.m3-spot-leave-active[data-v-51b103ff]{transition:opacity .15s}.m3-spot-enter-from[data-v-51b103ff],.m3-spot-leave-to[data-v-51b103ff]{opacity:0}.m3-spot-enter-active .spot-box[data-v-51b103ff],.m3-spot-leave-active .spot-box[data-v-51b103ff]{transition:transform .15s,opacity .15s}.m3-spot-enter-from .spot-box[data-v-51b103ff]{opacity:0;transform:scale(.96)translateY(-8px)}.m3-spot-leave-to .spot-box[data-v-51b103ff]{opacity:0;transform:scale(.98)}.m3-tour-highlight{box-shadow:0 0 0 4px var(--color-primary), 0 0 0 9999px #0006;border-radius:8px;position:relative;z-index:101!important}.m3-tour-enter-active,.m3-tour-leave-active{transition:opacity .2s}.m3-tour-enter-from,.m3-tour-leave-to{opacity:0}
|
|
2
|
-
/*$vite$:1*/
|