This commit unifies executable ID structure across categories and scripts, paving the way for more complex ID solutions for #262. It also refactors related code to adapt to the changes. Key changes: - Change numeric IDs to string IDs for categories - Use named types for string IDs to improve code clarity - Add unit tests to verify ID uniqueness Other supporting changes: - Separate concerns in entities for data access and executables by using separate abstractions (`Identifiable` and `RepositoryEntity`) - Simplify usage and construction of entities. - Remove `BaseEntity` for simplicity. - Move creation of categories/scripts to domain layer - Refactor CategoryCollection for better validation logic isolation - Rename some categories to keep the names (used as pseudo-IDs) unique on Windows.
84 lines
2.0 KiB
Vue
84 lines
2.0 KiB
Vue
<template>
|
|
<div
|
|
class="clickable-node focusable-node"
|
|
tabindex="-1"
|
|
:class="{
|
|
'keyboard-focus': hasKeyboardFocus,
|
|
}"
|
|
@click.stop="toggleCheckState"
|
|
@focus="onNodeFocus"
|
|
>
|
|
<slot />
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent, computed, toRef } from 'vue';
|
|
import { useCurrentTreeNodes } from '../UseCurrentTreeNodes';
|
|
import { useNodeState } from './UseNodeState';
|
|
import { useKeyboardInteractionState } from './UseKeyboardInteractionState';
|
|
import type { TreeRoot } from '../TreeRoot/TreeRoot';
|
|
import type { TreeNode, TreeNodeId } from './TreeNode';
|
|
import type { PropType } from 'vue';
|
|
|
|
export default defineComponent({
|
|
props: {
|
|
nodeId: {
|
|
type: String as PropType<TreeNodeId>,
|
|
required: true,
|
|
},
|
|
treeRoot: {
|
|
type: Object as PropType<TreeRoot>,
|
|
required: true,
|
|
},
|
|
},
|
|
setup(props) {
|
|
const { isKeyboardBeingUsed } = useKeyboardInteractionState();
|
|
const { nodes } = useCurrentTreeNodes(toRef(props, 'treeRoot'));
|
|
const currentNode = computed<TreeNode>(() => nodes.value.getNodeById(props.nodeId));
|
|
const { state } = useNodeState(currentNode);
|
|
|
|
const hasKeyboardFocus = computed<boolean>(() => {
|
|
if (!isKeyboardBeingUsed.value) {
|
|
return false;
|
|
}
|
|
return state.value.isFocused;
|
|
});
|
|
|
|
const onNodeFocus = () => {
|
|
props.treeRoot.focus.setSingleFocus(currentNode.value);
|
|
};
|
|
|
|
function toggleCheckState() {
|
|
currentNode.value.state.toggleCheck();
|
|
}
|
|
|
|
return {
|
|
onNodeFocus,
|
|
toggleCheckState,
|
|
currentNode,
|
|
hasKeyboardFocus,
|
|
};
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
@use "@/presentation/assets/styles/main" as *;
|
|
@use "./../tree-colors" as *;
|
|
|
|
.clickable-node {
|
|
@include clickable;
|
|
@include hover-or-touch {
|
|
background: $color-node-highlight-bg;
|
|
}
|
|
}
|
|
|
|
.focusable-node {
|
|
outline: none; // We handle keyboard focus through own styling
|
|
&.keyboard-focus {
|
|
background: $color-node-highlight-bg;
|
|
}
|
|
}
|
|
</style>
|