@tailor-cms/tce-preview-runtime 0.0.4 → 0.0.16

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/package.json CHANGED
@@ -1,16 +1,18 @@
1
1
  {
2
2
  "name": "@tailor-cms/tce-preview-runtime",
3
- "version": "0.0.4",
3
+ "version": "0.0.16",
4
4
  "dependencies": {
5
5
  "@mdi/font": "^7.0.96",
6
6
  "@vitejs/plugin-vue": "^3.0.3",
7
7
  "@vueuse/core": "^9.1.1",
8
+ "ky": "^0.31.4",
8
9
  "split.js": "^1.6.4",
9
10
  "typescript": "^5.1.6",
10
- "vite-plugin-vuetify": "^1.0.2",
11
11
  "vite": "^3.0.7",
12
+ "vite-plugin-vuetify": "^1.0.2",
12
13
  "vue": "^3.2.37",
13
14
  "vue-tsc": "^0.39.5",
15
+ "vue3-ts-jsoneditor": "^2.9.0",
14
16
  "vuetify": "^3.3.14"
15
17
  },
16
18
  "devDependencies": {
package/src/App.vue CHANGED
@@ -1,12 +1,37 @@
1
1
  <script setup lang="ts">
2
+ import { onMounted, ref } from 'vue';
3
+ import ky from 'ky';
4
+
2
5
  import AppBar from './components/AppBar.vue';
3
6
  import MainLayout from './components/MainLayout.vue';
7
+
8
+ const SERVER_HOST = `localhost:${import.meta.env.VITE_TCE_SERVER_PORT || 8030}`;
9
+ const api = ky.create({ prefixUrl: `http://${SERVER_HOST}` });
10
+ const ws = new WebSocket(`ws://${SERVER_HOST}`);
11
+
12
+ const element = ref({});
13
+ onMounted(async () => {
14
+ element.value = await getElement();
15
+ ws.addEventListener('message', (event) => {
16
+ element.value = JSON.parse(event.data);
17
+ });
18
+ });
19
+
20
+ async function getElement() {
21
+ try {
22
+ const response = await api('content-element').json();
23
+ return response || {};
24
+ } catch (error) {
25
+ console.log('Error on element get', error);
26
+ return { msg: 'Error upon retrieving element state' };
27
+ }
28
+ }
4
29
  </script>
5
30
 
6
31
  <template>
7
32
  <v-app>
8
33
  <AppBar />
9
- <MainLayout class="mt-14" />
34
+ <MainLayout :element="element" class="mt-14" />
10
35
  </v-app>
11
36
  </template>
12
37
 
@@ -1,23 +1,37 @@
1
1
  <script setup lang="ts">
2
- import { useToggle } from '@vueuse/core';
3
-
4
2
  import logoUrl from '../assets/logo.png';
5
- import { useDarkGlobal } from '../utils';
3
+ import { useGlobalState } from '../state';
6
4
 
7
- const isDark = useDarkGlobal();
8
- const toggleDark = useToggle(isDark);
5
+ const { isDark, toggleDark, showEdit, showDisplay, showBothComponents } =
6
+ useGlobalState();
9
7
  </script>
10
8
 
11
9
  <template>
12
- <v-app-bar :color="isDark ? 'blue-grey-darken-4' : 'grey-lighten-4'">
10
+ <v-app-bar :color="isDark ? '#29292f' : 'grey-lighten-5'">
13
11
  <template #prepend>
14
- <v-app-bar-nav-icon>
15
- <img :src="logoUrl" alt="Tailor logo" width="32" />
12
+ <v-app-bar-nav-icon class="ml-3">
13
+ <v-avatar :color="isDark ? 'transparent' : '#29292f'" size="48">
14
+ <img :src="logoUrl" alt="Tailor logo" width="30" />
15
+ </v-avatar>
16
16
  </v-app-bar-nav-icon>
17
17
  </template>
18
- <v-app-bar-title> Dev Kit </v-app-bar-title>
18
+ <v-app-bar-title class="ml-3 font-weight-bold">Dev Kit</v-app-bar-title>
19
19
  <v-spacer />
20
- <v-btn icon>
20
+ <v-btn-toggle class="mr-4" density="compact" borderless>
21
+ <v-btn @click="showEdit">
22
+ <span>Edit</span>
23
+ <v-icon end>mdi-pencil</v-icon>
24
+ </v-btn>
25
+ <v-btn @click="showDisplay">
26
+ <span>Preview</span>
27
+ <v-icon end>mdi-fullscreen</v-icon>
28
+ </v-btn>
29
+ <v-btn @click="showBothComponents">
30
+ <span>Both</span>
31
+ <v-icon end>mdi-math-norm-box</v-icon>
32
+ </v-btn>
33
+ </v-btn-toggle>
34
+ <v-btn href="https://github.com/tailor-cms/t-xt" icon>
21
35
  <v-icon>mdi-github</v-icon>
22
36
  </v-btn>
23
37
  <v-btn icon @click.prevent="toggleDark()">
@@ -1,42 +1,79 @@
1
1
  <script setup lang="ts">
2
- import { onMounted, ref, watch } from 'vue';
2
+ import { onMounted } from 'vue';
3
+ import JsonEditor from 'vue3-ts-jsoneditor';
3
4
  import Split from 'split.js';
4
5
 
5
- import { useDarkGlobal } from '../utils';
6
- const isDark = useDarkGlobal();
7
- const iframe = ref<HTMLIFrameElement>();
6
+ import { PANELS, useGlobalState } from '../state';
8
7
 
9
- watch(isDark, (value) => {
10
- iframe.value?.contentWindow?.postMessage(
11
- `theme-${value ? 'dark' : 'light'}`,
12
- '*',
13
- );
14
- });
8
+ // TODO: Enforce order
9
+ // const SERVER_PROP_ORDER = [
10
+ // 'id',
11
+ // 'uid',
12
+ // 'type',
13
+ // 'position',
14
+ // 'data',
15
+ // 'meta',
16
+ // 'refs',
17
+ // 'contentId',
18
+ // 'contentSignature',
19
+ // 'linked',
20
+ // 'detached',
21
+ // 'createdAt',
22
+ // 'updatedAt',
23
+ // 'deletedAt',
24
+ // ];
25
+
26
+ const props = defineProps<{ element: any }>();
27
+ const { isDark, splitJs } = useGlobalState();
15
28
 
16
- onMounted(() => Split(['#splitA', '#splitB']));
29
+ onMounted(() => {
30
+ // Component preview split
31
+ splitJs.value = Split([`#${PANELS.EDIT}`, `#${PANELS.DISPLAY}`], {
32
+ minSize: [0, 0],
33
+ });
34
+ // Client/server vertical split
35
+ Split([`#panelTop`, `#panelBottom`], {
36
+ direction: 'vertical',
37
+ sizes: [70, 30],
38
+ });
39
+ });
17
40
  </script>
18
41
 
19
42
  <template>
20
- <main>
21
- <div class="d-flex flex-row h-100">
22
- <iframe
23
- id="splitA"
24
- ref="iframe"
25
- class="w-full p-4"
26
- frameBorder="0"
27
- sandbox="allow-scripts"
28
- src="http://localhost:8010"
29
- title="Edit component container"
30
- ></iframe>
31
- <iframe
32
- id="splitB"
33
- ref="iframe"
34
- class="w-full p-4"
35
- frameBorder="0"
36
- sandbox="allow-scripts"
37
- src="http://localhost:8020"
38
- title="Display component container"
39
- ></iframe>
43
+ <main :class="{ 'dark-theme': isDark }">
44
+ <div id="panelTop" class="d-flex panel">
45
+ <div class="d-flex flex-grow-1">
46
+ <iframe
47
+ :id="PANELS.EDIT"
48
+ frameBorder="0"
49
+ sandbox="allow-scripts"
50
+ src="http://localhost:8010"
51
+ title="Edit component container"
52
+ >
53
+ </iframe>
54
+ <iframe
55
+ :id="PANELS.DISPLAY"
56
+ frameBorder="0"
57
+ sandbox="allow-scripts"
58
+ src="http://localhost:8020"
59
+ title="Display component container"
60
+ >
61
+ </iframe>
62
+ </div>
63
+ </div>
64
+ <div id="panelBottom" class="panel">
65
+ <v-tabs density="compact" hide-slider>
66
+ <v-tab>Server state</v-tab>
67
+ </v-tabs>
68
+ <div class="pa-5">
69
+ <JsonEditor
70
+ :dark-theme="isDark"
71
+ :main-menu-bar="false"
72
+ :status-bar="false"
73
+ :value="props.element"
74
+ mode="text"
75
+ />
76
+ </div>
40
77
  </div>
41
78
  </main>
42
79
  </template>
@@ -44,6 +81,10 @@ onMounted(() => Split(['#splitA', '#splitB']));
44
81
  <style>
45
82
  main {
46
83
  height: calc(100vh - var(--nav-height));
84
+
85
+ .panel {
86
+ background-color: #eceff1;
87
+ }
47
88
  }
48
89
 
49
90
  .gutter {
@@ -51,8 +92,26 @@ main {
51
92
  }
52
93
 
53
94
  .gutter.gutter-horizontal {
54
- background-color: #333;
55
- background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
56
95
  cursor: col-resize;
96
+ background-color: #fff;
97
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
98
+ }
99
+
100
+ .gutter.gutter-vertical {
101
+ cursor: row-resize !important;
102
+ background-color: #fff;
103
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
104
+ }
105
+
106
+ .dark-theme {
107
+ .gutter.gutter-horizontal,
108
+ .gutter.gutter-vertical {
109
+ background-color: #333;
110
+ }
111
+
112
+ .jse-theme-dark .cm-content,
113
+ .jse-theme-dark .cm-gutters {
114
+ background-color: #29292f !important;
115
+ }
57
116
  }
58
117
  </style>
@@ -0,0 +1 @@
1
+ export * from './preview';
@@ -0,0 +1,40 @@
1
+ import { createGlobalState, useToggle } from '@vueuse/core';
2
+ import { ref } from 'vue';
3
+
4
+ export const PANELS = {
5
+ EDIT: 'editPanel',
6
+ DISPLAY: 'displayPanel',
7
+ STATE: 'statePanel',
8
+ };
9
+
10
+ export const useGlobalState = createGlobalState(() => {
11
+ // Control color scheme
12
+ const isDark = ref(false);
13
+ const toggleDark = useToggle(isDark);
14
+
15
+ // Control panels
16
+ const visiblePanels = ref(['EDIT', 'DISPLAY', 'STATE']);
17
+ const splitJs = ref();
18
+ const showEdit = () => {
19
+ visiblePanels.value = [PANELS.EDIT];
20
+ if (splitJs.value) splitJs.value?.setSizes([100, 0]);
21
+ };
22
+ const showDisplay = () => {
23
+ visiblePanels.value = [PANELS.DISPLAY];
24
+ if (splitJs.value) splitJs.value?.setSizes([0, 100]);
25
+ };
26
+ const showBothComponents = () => {
27
+ visiblePanels.value = [PANELS.EDIT, PANELS.DISPLAY];
28
+ if (splitJs.value) splitJs.value?.setSizes([50, 50]);
29
+ };
30
+
31
+ return {
32
+ isDark,
33
+ toggleDark,
34
+ visiblePanels,
35
+ splitJs,
36
+ showEdit,
37
+ showDisplay,
38
+ showBothComponents,
39
+ };
40
+ });
@@ -1,3 +0,0 @@
1
- import { createGlobalState, useDark } from '@vueuse/core';
2
-
3
- export const useDarkGlobal = createGlobalState(() => useDark());
@@ -1 +0,0 @@
1
- export * from './helpers';