@m3ui-vue/m3ui-vue 0.1.0 → 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.
Files changed (64) hide show
  1. package/README.md +80 -23
  2. package/dist/MIcon-CaEooCmZ.js +20 -0
  3. package/dist/MIcon-CaEooCmZ.js.map +1 -0
  4. package/dist/_plugin-vue_export-helper-B3ysoDQm.js +8 -0
  5. package/dist/chart.d.ts +1 -0
  6. package/dist/chart.js +141 -0
  7. package/dist/chart.js.map +1 -0
  8. package/dist/code-editor.d.ts +2 -0
  9. package/dist/code-editor.js +379 -0
  10. package/dist/code-editor.js.map +1 -0
  11. package/dist/components/MButton.vue.d.ts +1 -1
  12. package/dist/components/MCalendar.vue.d.ts +1 -1
  13. package/dist/components/MChart.vue.d.ts +2 -3
  14. package/dist/components/MCodeEditor.vue.d.ts +3 -1
  15. package/dist/components/MContainer.vue.d.ts +1 -1
  16. package/dist/components/MDataTable.vue.d.ts +1 -1
  17. package/dist/components/MFab.vue.d.ts +0 -2
  18. package/dist/components/MIconButton.vue.d.ts +1 -1
  19. package/dist/components/MMultiSelect.vue.d.ts +1 -1
  20. package/dist/components/MProgressBar.vue.d.ts +1 -1
  21. package/dist/components/MRichTextEditor.vue.d.ts +1 -1
  22. package/dist/components/MScheduler.vue.d.ts +1 -1
  23. package/dist/components/MSelect.vue.d.ts +1 -1
  24. package/dist/components/MSkeleton.vue.d.ts +1 -1
  25. package/dist/components/MSpotlightSearch.vue.d.ts +1 -1
  26. package/dist/components/MStack.vue.d.ts +2 -2
  27. package/dist/components/MTerminal.vue.d.ts +6 -6
  28. package/dist/components/MTextField.vue.d.ts +1 -1
  29. package/dist/components/MTooltip.vue.d.ts +1 -1
  30. package/dist/dist-Dsrzt6J5.js +1192 -0
  31. package/dist/dist-Dsrzt6J5.js.map +1 -0
  32. package/dist/index.d.ts +0 -6
  33. package/dist/m3ui-vue.css +2 -0
  34. package/dist/m3ui.js +2738 -3367
  35. package/dist/m3ui.js.map +1 -1
  36. package/dist/markdown.d.ts +1 -0
  37. package/dist/markdown.js +41 -0
  38. package/dist/markdown.js.map +1 -0
  39. package/dist/rich-text-editor.d.ts +1 -0
  40. package/dist/rich-text-editor.js +215 -0
  41. package/dist/rich-text-editor.js.map +1 -0
  42. package/dist/styles/theme.css +3 -0
  43. package/dist/styles.css +2 -0
  44. package/dist/terminal.d.ts +1 -0
  45. package/dist/terminal.js +97 -0
  46. package/dist/terminal.js.map +1 -0
  47. package/package.json +28 -2
  48. package/src/chart.ts +1 -0
  49. package/src/code-editor.ts +2 -0
  50. package/src/components/MAlert.vue +1 -1
  51. package/src/components/MChart.vue +54 -47
  52. package/src/components/MCodeEditor.vue +149 -44
  53. package/src/components/MFab.vue +64 -48
  54. package/src/components/MMarkdown.vue +24 -17
  55. package/src/components/MMultiSelect.vue +3 -2
  56. package/src/components/MRichTextEditor.vue +101 -67
  57. package/src/components/MTerminal.vue +10 -8
  58. package/src/components/MTooltip.vue +8 -1
  59. package/src/index.ts +6 -6
  60. package/src/markdown.ts +1 -0
  61. package/src/rich-text-editor.ts +1 -0
  62. package/src/styles/theme.css +3 -0
  63. package/src/terminal.ts +1 -0
  64. package/dist/m3ui.css +0 -2
package/README.md CHANGED
@@ -1,16 +1,22 @@
1
- # @m3ui/vue
1
+ # M3UI Vue
2
2
 
3
3
  Material 3 component library for Vue 3 + Tailwind CSS v4.
4
4
 
5
5
  80+ components following [Material Design 3](https://m3.material.io/) guidelines with 20 built-in color palettes, dark mode, and full TypeScript support.
6
6
 
7
- ## Install
7
+ ## Quick Start
8
+
9
+ ### 1. Install
8
10
 
9
11
  ```bash
10
- pnpm add @m3ui/vue
12
+ pnpm add @m3ui-vue/m3ui-vue
13
+ # or
14
+ npm install @m3ui-vue/m3ui-vue
11
15
  ```
12
16
 
13
- Add the Google Fonts link to your `index.html`:
17
+ ### 2. Add Google Fonts
18
+
19
+ Add the following to your `index.html` `<head>`:
14
20
 
15
21
  ```html
16
22
  <link
@@ -19,49 +25,97 @@ Add the Google Fonts link to your `index.html`:
19
25
  />
20
26
  ```
21
27
 
22
- Import the theme CSS in your main stylesheet (after Tailwind):
28
+ ### 3. Configure CSS
29
+
30
+ In your main stylesheet (e.g. `src/style.css`):
23
31
 
24
32
  ```css
25
33
  @import 'tailwindcss';
26
- @import '@m3ui/vue/theme';
27
- @import '@m3ui/vue/palettes'; /* optional — 20 color palettes */
34
+ @import '@m3ui-vue/m3ui-vue/theme';
35
+ @import '@m3ui-vue/m3ui-vue/palettes'; /* optional — includes 20 color palettes */
36
+ @import '@m3ui-vue/m3ui-vue/styles'; /* component scoped styles (transitions, animations) */
28
37
  ```
29
38
 
30
- Tell Tailwind to scan the library's source for class names:
39
+ ### 4. Register the Plugin (optional)
31
40
 
32
- ```css
33
- @source '../node_modules/@m3ui/vue';
41
+ ```ts
42
+ // main.ts
43
+ import { createApp } from 'vue'
44
+ import { createM3UI } from '@m3ui-vue/m3ui-vue'
45
+ import App from './App.vue'
46
+
47
+ const app = createApp(App)
48
+ app.use(createM3UI({ palette: 'teal' })) // sets initial palette
49
+ app.mount('#app')
34
50
  ```
35
51
 
52
+ The plugin is optional — without it the default purple palette is used.
53
+
36
54
  ## Usage
37
55
 
38
56
  ```vue
39
57
  <script setup>
40
- import { MButton, MCard, MTextField, useToast, useTheme } from '@m3ui/vue'
58
+ import { MButton, MCard, MTextField, useToast } from '@m3ui-vue/m3ui-vue'
41
59
 
42
60
  const toast = useToast()
61
+ const name = ref('')
43
62
  </script>
44
63
 
45
64
  <template>
46
65
  <MCard>
47
- <MTextField v-model="name" label="Nombre" />
48
- <MButton icon="save" @click="toast.success('Guardado')">
49
- Guardar
66
+ <MTextField v-model="name" label="Name" />
67
+ <MButton icon="save" @click="toast.success('Saved!')">
68
+ Save
50
69
  </MButton>
51
70
  </MCard>
52
71
  </template>
53
72
  ```
54
73
 
55
- ### Vue Plugin (optional)
74
+ ## Color Palettes
56
75
 
57
- ```ts
58
- import { createApp } from 'vue'
59
- import { createM3UI } from '@m3ui/vue'
76
+ M3UI ships with 20 pre-built color palettes, each with light and dark variants:
60
77
 
61
- const app = createApp(App)
62
- app.use(createM3UI({ palette: 'teal' }))
78
+ `purple` (default), `indigo`, `navy`, `blue`, `cyan`, `teal`, `green`, `lime`, `olive`, `amber`, `sand`, `orange`, `deep-orange`, `brown`, `red`, `coral`, `crimson`, `pink`, `violet`, `slate`
79
+
80
+ ### Switching Palettes at Runtime
81
+
82
+ ```vue
83
+ <script setup>
84
+ import { useColorPalette } from '@m3ui-vue/m3ui-vue'
85
+
86
+ const { palette, palettes, set } = useColorPalette()
87
+ </script>
88
+
89
+ <template>
90
+ <select @change="set(($event.target as HTMLSelectElement).value)">
91
+ <option v-for="p in palettes" :key="p.id" :value="p.id" :selected="p.id === palette">
92
+ {{ p.label }}
93
+ </option>
94
+ </select>
95
+ </template>
96
+ ```
97
+
98
+ The selection is persisted to `localStorage` automatically.
99
+
100
+ ## Dark Mode
101
+
102
+ ```vue
103
+ <script setup>
104
+ import { useTheme } from '@m3ui-vue/m3ui-vue'
105
+
106
+ const { theme, cycle } = useTheme()
107
+ // theme: 'light' | 'dark' | 'system'
108
+ </script>
109
+
110
+ <template>
111
+ <MButton @click="cycle">
112
+ Theme: {{ theme }}
113
+ </MButton>
114
+ </template>
63
115
  ```
64
116
 
117
+ The theme is persisted to `localStorage` and respects `prefers-color-scheme` when set to `system`.
118
+
65
119
  ## Components
66
120
 
67
121
  ### Inputs
@@ -77,17 +131,20 @@ MAlert, MSnackbar (toast), MDialog, MConfirmDialog, MBottomSheet, MSideSheet, MP
77
131
  MTabs, MMenu, MMenuItem, MContextMenu, MBreadcrumbs, MStepper, MPagination, MNavigationBar, MNavigationRail, MNavigationDrawer, MTopAppBar, MAppBar, MSegmentedButton
78
132
 
79
133
  ### Layout
80
- MContainer, MGrid, MStack, MSplitter, MMasonry, MDivider
134
+ MContainer, MGrid, MStack, MSplitter, MMasonry, MDivider, MExpansionPanel
81
135
 
82
136
  ### Advanced
83
137
  MRichTextEditor, MCodeEditor, MJsonEditor, MKanban, MScheduler, MChart, MTerminal, MFileUpload, MTour, MCommandPalette, MSpotlightSearch, MHotkeys, MDragDropList, MTransferList, MInfiniteScroll
84
138
 
85
139
  ### Composables
86
- `useTheme()`, `useColorPalette()`, `useToast()`, `useFieldBg()`
140
+ - `useTheme()` light/dark/system theme with `cycle()`
141
+ - `useColorPalette()` — switch between 20 palettes at runtime
142
+ - `useToast()` — programmatic toast notifications
143
+ - `useFieldBg()` — context-aware field background color
87
144
 
88
145
  ## Optional Dependencies
89
146
 
90
- Some components require additional packages. Install only what you use:
147
+ Some components require peer packages. Install only what you need:
91
148
 
92
149
  | Component | Install |
93
150
  |---|---|
@@ -0,0 +1,20 @@
1
+ import { createElementBlock as e, defineComponent as t, normalizeStyle as n, openBlock as r, toDisplayString as i } from "vue";
2
+ //#endregion
3
+ //#region src/components/MIcon.vue
4
+ var a = /* @__PURE__ */ t({
5
+ __name: "MIcon",
6
+ props: {
7
+ name: {},
8
+ size: { default: 24 }
9
+ },
10
+ setup(t) {
11
+ return (a, o) => (r(), e("span", {
12
+ class: "material-symbols-outlined leading-none",
13
+ style: n({ fontSize: `${t.size}px` })
14
+ }, i(t.name), 5));
15
+ }
16
+ });
17
+ //#endregion
18
+ export { a as t };
19
+
20
+ //# sourceMappingURL=MIcon-CaEooCmZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MIcon-CaEooCmZ.js","names":[],"sources":["../src/components/MIcon.vue","../src/components/MIcon.vue"],"sourcesContent":["<script setup lang=\"ts\">\nwithDefaults(defineProps<{ name: string; size?: number }>(), { size: 24 })\n</script>\n\n<template>\n <span class=\"material-symbols-outlined leading-none\" :style=\"{ fontSize: `${size}px` }\">{{\n name\n }}</span>\n</template>\n","<script setup lang=\"ts\">\nwithDefaults(defineProps<{ name: string; size?: number }>(), { size: 24 })\n</script>\n\n<template>\n <span class=\"material-symbols-outlined leading-none\" :style=\"{ fontSize: `${size}px` }\">{{\n name\n }}</span>\n</template>\n"],"mappings":";;;;;;;;;;yBAKE,EAES,QAAA;GAFH,OAAM;GAA0C,OAAK,EAAA,EAAA,UAAA,GAAiB,EAAA,KAAI,IAAA,CAAA;OAC9E,EAAA,IAAI,GAAA,CAAA"}
@@ -0,0 +1,8 @@
1
+ //#region \0plugin-vue:export-helper
2
+ var e = (e, t) => {
3
+ let n = e.__vccOpts || e;
4
+ for (let [e, r] of t) n[e] = r;
5
+ return n;
6
+ };
7
+ //#endregion
8
+ export { e as t };
@@ -0,0 +1 @@
1
+ export { default as MChart } from './components/MChart.vue';
package/dist/chart.js ADDED
@@ -0,0 +1,141 @@
1
+ import { computed as e, createBlock as t, createCommentVNode as n, createElementBlock as r, defineComponent as i, normalizeStyle as a, onBeforeUnmount as o, onMounted as s, openBlock as c, ref as l, resolveDynamicComponent as u, shallowRef as d, watch as f } from "vue";
2
+ //#endregion
3
+ //#region src/components/MChart.vue
4
+ var p = /* @__PURE__ */ i({
5
+ __name: "MChart",
6
+ props: {
7
+ type: {},
8
+ data: {},
9
+ options: {},
10
+ height: { default: "300px" }
11
+ },
12
+ setup(i) {
13
+ let p = i, m = l(!1), h = d(null), g = d({});
14
+ function _() {
15
+ let e = getComputedStyle(document.documentElement), t = (t) => e.getPropertyValue(t).trim();
16
+ return {
17
+ primary: t("--color-primary"),
18
+ onSurface: t("--color-on-surface"),
19
+ onSurfaceVariant: t("--color-on-surface-variant"),
20
+ outlineVariant: t("--color-outline-variant"),
21
+ surface: t("--color-surface"),
22
+ surfaceContainer: t("--color-surface-container")
23
+ };
24
+ }
25
+ let v = l(_()), y = null;
26
+ s(async () => {
27
+ v.value = _(), y = new MutationObserver(() => {
28
+ v.value = _();
29
+ }), y.observe(document.documentElement, {
30
+ attributes: !0,
31
+ attributeFilter: ["class"]
32
+ });
33
+ let [e, t] = await Promise.all([import("chart.js"), import("vue-chartjs")]);
34
+ e.Chart.register(e.CategoryScale, e.LinearScale, e.PointElement, e.LineElement, e.BarElement, e.ArcElement, e.RadialLinearScale, e.Filler, e.Tooltip, e.Legend, e.Title), g.value = {
35
+ line: t.Line,
36
+ bar: t.Bar,
37
+ pie: t.Pie,
38
+ doughnut: t.Doughnut,
39
+ radar: t.Radar
40
+ }, m.value = !0;
41
+ }), o(() => {
42
+ y?.disconnect();
43
+ }), f(() => p.type, () => {
44
+ m.value && (h.value = g.value[p.type] ?? null);
45
+ }, { immediate: !0 }), f(m, () => {
46
+ h.value = g.value[p.type] ?? null;
47
+ });
48
+ let b = e(() => {
49
+ let e = v.value, t = {
50
+ responsive: !0,
51
+ maintainAspectRatio: !1,
52
+ plugins: {
53
+ legend: { labels: {
54
+ color: e.onSurface,
55
+ font: {
56
+ family: "'Roboto', system-ui, sans-serif",
57
+ size: 12
58
+ },
59
+ usePointStyle: !0,
60
+ pointStyle: "circle",
61
+ padding: 16
62
+ } },
63
+ tooltip: {
64
+ backgroundColor: e.surfaceContainer,
65
+ titleColor: e.onSurface,
66
+ bodyColor: e.onSurfaceVariant,
67
+ borderColor: e.outlineVariant,
68
+ borderWidth: 1,
69
+ cornerRadius: 12,
70
+ padding: 12,
71
+ titleFont: {
72
+ family: "'Roboto', system-ui, sans-serif",
73
+ size: 13,
74
+ weight: "600"
75
+ },
76
+ bodyFont: {
77
+ family: "'Roboto', system-ui, sans-serif",
78
+ size: 12
79
+ },
80
+ displayColors: !0,
81
+ boxPadding: 4
82
+ }
83
+ }
84
+ };
85
+ return p.type !== "pie" && p.type !== "doughnut" && (t.scales = {
86
+ x: {
87
+ grid: {
88
+ color: e.outlineVariant + "40",
89
+ drawTicks: !1
90
+ },
91
+ ticks: {
92
+ color: e.onSurfaceVariant,
93
+ font: { size: 11 },
94
+ padding: 8
95
+ },
96
+ border: { color: e.outlineVariant }
97
+ },
98
+ y: {
99
+ grid: {
100
+ color: e.outlineVariant + "40",
101
+ drawTicks: !1
102
+ },
103
+ ticks: {
104
+ color: e.onSurfaceVariant,
105
+ font: { size: 11 },
106
+ padding: 8
107
+ },
108
+ border: { color: e.outlineVariant }
109
+ }
110
+ }), p.type === "radar" && (t.scales = { r: {
111
+ grid: { color: e.outlineVariant + "40" },
112
+ angleLines: { color: e.outlineVariant + "40" },
113
+ pointLabels: {
114
+ color: e.onSurfaceVariant,
115
+ font: { size: 11 }
116
+ },
117
+ ticks: {
118
+ color: e.onSurfaceVariant,
119
+ backdropColor: "transparent"
120
+ }
121
+ } }), x(t, p.options ?? {});
122
+ });
123
+ function x(e, t) {
124
+ let n = { ...e };
125
+ for (let r of Object.keys(t)) t[r] && typeof t[r] == "object" && !Array.isArray(t[r]) ? n[r] = x(e[r] ?? {}, t[r]) : n[r] = t[r];
126
+ return n;
127
+ }
128
+ return (e, o) => (c(), r("div", {
129
+ class: "rounded-lg border border-outline-variant bg-surface p-4",
130
+ style: a({ height: i.height })
131
+ }, [m.value && h.value ? (c(), t(u(h.value), {
132
+ key: 0,
133
+ data: i.data,
134
+ options: b.value
135
+ }, null, 8, ["data", "options"])) : n("", !0)], 4));
136
+ }
137
+ });
138
+ //#endregion
139
+ export { p as MChart };
140
+
141
+ //# sourceMappingURL=chart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart.js","names":[],"sources":["../src/components/MChart.vue","../src/components/MChart.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, ref, watch, onMounted, onBeforeUnmount, shallowRef, type Component } from 'vue'\n\ntype ChartType = 'line' | 'bar' | 'pie' | 'doughnut' | 'radar'\n\nconst props = withDefaults(\n defineProps<{\n type: ChartType\n data: Record<string, any>\n options?: Record<string, any>\n height?: string\n }>(),\n { height: '300px' },\n)\n\nconst ready = ref(false)\nconst chartComponent = shallowRef<Component | null>(null)\nconst componentMap = shallowRef<Record<string, Component>>({})\n\nfunction getM3Colors() {\n const style = getComputedStyle(document.documentElement)\n const get = (v: string) => style.getPropertyValue(v).trim()\n return {\n primary: get('--color-primary'),\n onSurface: get('--color-on-surface'),\n onSurfaceVariant: get('--color-on-surface-variant'),\n outlineVariant: get('--color-outline-variant'),\n surface: get('--color-surface'),\n surfaceContainer: get('--color-surface-container'),\n }\n}\n\nconst m3Colors = ref(getM3Colors())\n\nlet themeObserver: MutationObserver | null = null\n\nonMounted(async () => {\n m3Colors.value = getM3Colors()\n\n themeObserver = new MutationObserver(() => { m3Colors.value = getM3Colors() })\n themeObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })\n\n const [chartjs, vueChartjs] = await Promise.all([\n import('chart.js'),\n import('vue-chartjs'),\n ])\n\n chartjs.Chart.register(\n chartjs.CategoryScale,\n chartjs.LinearScale,\n chartjs.PointElement,\n chartjs.LineElement,\n chartjs.BarElement,\n chartjs.ArcElement,\n chartjs.RadialLinearScale,\n chartjs.Filler,\n chartjs.Tooltip,\n chartjs.Legend,\n chartjs.Title,\n )\n\n componentMap.value = {\n line: vueChartjs.Line,\n bar: vueChartjs.Bar,\n pie: vueChartjs.Pie,\n doughnut: vueChartjs.Doughnut,\n radar: vueChartjs.Radar,\n }\n\n ready.value = true\n})\n\nonBeforeUnmount(() => { themeObserver?.disconnect() })\n\nwatch(() => props.type, () => {\n if (ready.value) chartComponent.value = componentMap.value[props.type] ?? null\n}, { immediate: true })\n\nwatch(ready, () => {\n chartComponent.value = componentMap.value[props.type] ?? null\n})\n\nconst mergedOptions = computed<Record<string, any>>(() => {\n const c = m3Colors.value\n const base: Record<string, any> = {\n responsive: true,\n maintainAspectRatio: false,\n plugins: {\n legend: {\n labels: {\n color: c.onSurface,\n font: { family: \"'Roboto', system-ui, sans-serif\", size: 12 },\n usePointStyle: true,\n pointStyle: 'circle',\n padding: 16,\n },\n },\n tooltip: {\n backgroundColor: c.surfaceContainer,\n titleColor: c.onSurface,\n bodyColor: c.onSurfaceVariant,\n borderColor: c.outlineVariant,\n borderWidth: 1,\n cornerRadius: 12,\n padding: 12,\n titleFont: { family: \"'Roboto', system-ui, sans-serif\", size: 13, weight: '600' as const },\n bodyFont: { family: \"'Roboto', system-ui, sans-serif\", size: 12 },\n displayColors: true,\n boxPadding: 4,\n },\n },\n }\n\n if (props.type !== 'pie' && props.type !== 'doughnut') {\n base.scales = {\n x: {\n grid: { color: c.outlineVariant + '40', drawTicks: false },\n ticks: { color: c.onSurfaceVariant, font: { size: 11 }, padding: 8 },\n border: { color: c.outlineVariant },\n },\n y: {\n grid: { color: c.outlineVariant + '40', drawTicks: false },\n ticks: { color: c.onSurfaceVariant, font: { size: 11 }, padding: 8 },\n border: { color: c.outlineVariant },\n },\n }\n }\n\n if (props.type === 'radar') {\n base.scales = {\n r: {\n grid: { color: c.outlineVariant + '40' },\n angleLines: { color: c.outlineVariant + '40' },\n pointLabels: { color: c.onSurfaceVariant, font: { size: 11 } },\n ticks: { color: c.onSurfaceVariant, backdropColor: 'transparent' },\n },\n }\n }\n\n return deepMerge(base, props.options ?? {})\n})\n\nfunction deepMerge(target: any, source: any): any {\n const output = { ...target }\n for (const key of Object.keys(source)) {\n if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {\n output[key] = deepMerge(target[key] ?? {}, source[key])\n } else {\n output[key] = source[key]\n }\n }\n return output\n}\n</script>\n\n<template>\n <div class=\"rounded-lg border border-outline-variant bg-surface p-4\" :style=\"{ height }\">\n <component\n v-if=\"ready && chartComponent\"\n :is=\"chartComponent\"\n :data=\"data\"\n :options=\"mergedOptions\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch, onMounted, onBeforeUnmount, shallowRef, type Component } from 'vue'\n\ntype ChartType = 'line' | 'bar' | 'pie' | 'doughnut' | 'radar'\n\nconst props = withDefaults(\n defineProps<{\n type: ChartType\n data: Record<string, any>\n options?: Record<string, any>\n height?: string\n }>(),\n { height: '300px' },\n)\n\nconst ready = ref(false)\nconst chartComponent = shallowRef<Component | null>(null)\nconst componentMap = shallowRef<Record<string, Component>>({})\n\nfunction getM3Colors() {\n const style = getComputedStyle(document.documentElement)\n const get = (v: string) => style.getPropertyValue(v).trim()\n return {\n primary: get('--color-primary'),\n onSurface: get('--color-on-surface'),\n onSurfaceVariant: get('--color-on-surface-variant'),\n outlineVariant: get('--color-outline-variant'),\n surface: get('--color-surface'),\n surfaceContainer: get('--color-surface-container'),\n }\n}\n\nconst m3Colors = ref(getM3Colors())\n\nlet themeObserver: MutationObserver | null = null\n\nonMounted(async () => {\n m3Colors.value = getM3Colors()\n\n themeObserver = new MutationObserver(() => { m3Colors.value = getM3Colors() })\n themeObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] })\n\n const [chartjs, vueChartjs] = await Promise.all([\n import('chart.js'),\n import('vue-chartjs'),\n ])\n\n chartjs.Chart.register(\n chartjs.CategoryScale,\n chartjs.LinearScale,\n chartjs.PointElement,\n chartjs.LineElement,\n chartjs.BarElement,\n chartjs.ArcElement,\n chartjs.RadialLinearScale,\n chartjs.Filler,\n chartjs.Tooltip,\n chartjs.Legend,\n chartjs.Title,\n )\n\n componentMap.value = {\n line: vueChartjs.Line,\n bar: vueChartjs.Bar,\n pie: vueChartjs.Pie,\n doughnut: vueChartjs.Doughnut,\n radar: vueChartjs.Radar,\n }\n\n ready.value = true\n})\n\nonBeforeUnmount(() => { themeObserver?.disconnect() })\n\nwatch(() => props.type, () => {\n if (ready.value) chartComponent.value = componentMap.value[props.type] ?? null\n}, { immediate: true })\n\nwatch(ready, () => {\n chartComponent.value = componentMap.value[props.type] ?? null\n})\n\nconst mergedOptions = computed<Record<string, any>>(() => {\n const c = m3Colors.value\n const base: Record<string, any> = {\n responsive: true,\n maintainAspectRatio: false,\n plugins: {\n legend: {\n labels: {\n color: c.onSurface,\n font: { family: \"'Roboto', system-ui, sans-serif\", size: 12 },\n usePointStyle: true,\n pointStyle: 'circle',\n padding: 16,\n },\n },\n tooltip: {\n backgroundColor: c.surfaceContainer,\n titleColor: c.onSurface,\n bodyColor: c.onSurfaceVariant,\n borderColor: c.outlineVariant,\n borderWidth: 1,\n cornerRadius: 12,\n padding: 12,\n titleFont: { family: \"'Roboto', system-ui, sans-serif\", size: 13, weight: '600' as const },\n bodyFont: { family: \"'Roboto', system-ui, sans-serif\", size: 12 },\n displayColors: true,\n boxPadding: 4,\n },\n },\n }\n\n if (props.type !== 'pie' && props.type !== 'doughnut') {\n base.scales = {\n x: {\n grid: { color: c.outlineVariant + '40', drawTicks: false },\n ticks: { color: c.onSurfaceVariant, font: { size: 11 }, padding: 8 },\n border: { color: c.outlineVariant },\n },\n y: {\n grid: { color: c.outlineVariant + '40', drawTicks: false },\n ticks: { color: c.onSurfaceVariant, font: { size: 11 }, padding: 8 },\n border: { color: c.outlineVariant },\n },\n }\n }\n\n if (props.type === 'radar') {\n base.scales = {\n r: {\n grid: { color: c.outlineVariant + '40' },\n angleLines: { color: c.outlineVariant + '40' },\n pointLabels: { color: c.onSurfaceVariant, font: { size: 11 } },\n ticks: { color: c.onSurfaceVariant, backdropColor: 'transparent' },\n },\n }\n }\n\n return deepMerge(base, props.options ?? {})\n})\n\nfunction deepMerge(target: any, source: any): any {\n const output = { ...target }\n for (const key of Object.keys(source)) {\n if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {\n output[key] = deepMerge(target[key] ?? {}, source[key])\n } else {\n output[key] = source[key]\n }\n }\n return output\n}\n</script>\n\n<template>\n <div class=\"rounded-lg border border-outline-variant bg-surface p-4\" :style=\"{ height }\">\n <component\n v-if=\"ready && chartComponent\"\n :is=\"chartComponent\"\n :data=\"data\"\n :options=\"mergedOptions\"\n />\n </div>\n</template>\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { default as MCodeEditor } from './components/MCodeEditor.vue';
2
+ export { default as MJsonEditor } from './components/MJsonEditor.vue';