You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.8 KiB
129 lines
4.8 KiB
<script setup lang="ts">
|
|
import { watch } from 'vue';
|
|
import useShape from '../../ng-mock/js-land/frontendAdapters/vue/useShape';
|
|
import { deepComputed } from '../../ng-mock/js-land/frontendAdapters/vue/deepComputed';
|
|
import flattenObject from '../utils/flattenObject';
|
|
|
|
// Acquire deep signal object (proxy) for a shape; scope second arg left empty string for parity
|
|
const shapeObj = useShape('TestShape', '');
|
|
|
|
// Expose for devtools exploration
|
|
// @ts-ignore
|
|
window.vueState = shapeObj;
|
|
|
|
// Helpers to read / write nested properties given a dot path produced by flattenObject
|
|
function getNestedValue(obj: any, path: string) {
|
|
return path.split('.').reduce((cur, k) => (cur == null ? cur : cur[k]), obj);
|
|
}
|
|
function setNestedValue(obj: any, path: string, value: any) {
|
|
const keys = path.split('.');
|
|
let cur = obj;
|
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
cur = cur[keys[i]];
|
|
if (cur == null) return;
|
|
}
|
|
cur[keys[keys.length - 1]] = value;
|
|
}
|
|
|
|
// Reactive flattened entries built via deepComputed bridging deepSignal dependencies to Vue.
|
|
const flatEntries = deepComputed(() => (shapeObj ? flattenObject(shapeObj.value as any) : []));
|
|
|
|
// log flatEntries
|
|
watch(flatEntries, (newVal) => {
|
|
console.log('flatEntries changed:', newVal);
|
|
}, { deep: true });
|
|
</script>
|
|
|
|
|
|
<template>
|
|
<div class="vue">
|
|
<p>Rendered in Vue</p>
|
|
<template v-if="shapeObj">
|
|
|
|
<table border="1" cellpadding="5" style="margin-top:1rem; max-width:100%; font-size:0.9rem;">
|
|
<thead>
|
|
<tr>
|
|
<th>Key</th>
|
|
<th>Value</th>
|
|
<th>Edit</th>
|
|
</tr>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<tr v-for="([key, value]) in flatEntries" :key="key">
|
|
<!-- Key-->
|
|
<td style="white-space:nowrap;">{{ key }}</td>
|
|
|
|
<!-- Value -->
|
|
<td>
|
|
<template v-if="value instanceof Set">
|
|
{{ Array.from(value).join(', ') }}
|
|
</template>
|
|
<template v-else-if="Array.isArray(value)">
|
|
[{{ value.join(', ') }}]
|
|
</template>
|
|
<template v-else>
|
|
{{ JSON.stringify(value) }}
|
|
</template>
|
|
</td>
|
|
|
|
<!-- Edit -->
|
|
<td>
|
|
<!-- String editing -->
|
|
<template v-if="typeof value === 'string'">
|
|
<template v-if="key.indexOf('.') === -1">
|
|
<input type="text" v-model="(shapeObj)[key]" />
|
|
</template>
|
|
<template v-else>
|
|
<input type="text" v-bind:value="value" />
|
|
</template>
|
|
</template>
|
|
<!-- Number editing -->
|
|
<template v-else-if="typeof value === 'number'">
|
|
<template v-if="key.indexOf('.') === -1">
|
|
<input type="number" v-model.number="(shapeObj)[key]" />
|
|
</template>
|
|
<template v-else>
|
|
<input type="number" v-bind:value="value" />
|
|
</template>
|
|
</template>
|
|
<!-- Boolean editing -->
|
|
<template v-else-if="typeof value === 'boolean'">
|
|
<template v-if="key.indexOf('.') === -1">
|
|
<input type="checkbox" v-model="(shapeObj as any)[key]" />
|
|
</template>
|
|
<template v-else>
|
|
<input type="checkbox" v-bind:value="value" />
|
|
</template>
|
|
</template>
|
|
<!-- Array editing -->
|
|
<template v-else-if="Array.isArray(value)">
|
|
<div style="display:flex; gap:.5rem;">
|
|
<button
|
|
@click="() => { const current = getNestedValue(shapeObj, key) || []; setNestedValue(shapeObj, key, [...current, current.length + 1]); }">Add</button>
|
|
<button
|
|
@click="() => { const current = getNestedValue(shapeObj, key) || []; if (current.length) setNestedValue(shapeObj, key, current.slice(0, -1)); }">Remove</button>
|
|
</div>
|
|
</template>
|
|
<!-- Set editing -->
|
|
<template v-else-if="value instanceof Set">
|
|
<div style="display:flex; gap:.5rem;">
|
|
<button
|
|
@click="() => { const currentSet: Set<any> = getNestedValue(shapeObj, key); currentSet.add(`item${currentSet.size + 1}`); }">Add</button>
|
|
<button
|
|
@click="() => { const currentSet: Set<any> = getNestedValue(shapeObj, key); const last = Array.from(currentSet).pop(); if (last !== undefined) currentSet.delete(last); }">Remove</button>
|
|
</div>
|
|
</template>
|
|
<template v-else>
|
|
N/A
|
|
</template>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</template>
|
|
<template v-else>
|
|
<p>Loading state</p>
|
|
</template>
|
|
</div>
|
|
</template> |