-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3c4db37
commit 3c51d46
Showing
68 changed files
with
5,654 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
<!-- eslint-disable vue/no-mutating-props --> | ||
<script setup lang="ts"> | ||
import { onMounted, ref, computed } from 'vue' | ||
import type { CarbonObject, Connection, HookType } from '../../types' | ||
import CarbonHooks from './CarbonHooks.vue' | ||
import { hooks } from '../../data/index' | ||
import { gsap } from 'gsap' | ||
import { Draggable } from 'gsap/Draggable' | ||
import { InertiaPlugin } from 'gsap-trial/InertiaPlugin' | ||
gsap.registerPlugin(InertiaPlugin) | ||
gsap.registerPlugin(Draggable) | ||
const title = 'Carbon' | ||
const props = defineProps<{ | ||
carbon: CarbonObject | ||
carbons: CarbonObject[] | ||
bounds?: HTMLDivElement | ||
connections: Connection[] | ||
}>() | ||
const carbonref = ref<HTMLDivElement>() | ||
const draggHandle = ref<HTMLDivElement>() | ||
const inputs = ref<InstanceType<typeof CarbonHooks>>() | ||
const outputs = ref<InstanceType<typeof CarbonHooks>>() | ||
const top = computed(() => `${props.carbon.position[1]}px`) | ||
const left = computed(() => `${props.carbon.position[0]}px`) | ||
function updateReferences() { | ||
connections.value.forEach((connection) => { | ||
// Stores carbon reference in connection object | ||
const isFrom = connection.output.carbon === props.carbon.id | ||
isFrom | ||
? (connection.output.component = props.carbon.component) | ||
: (connection.input.component = props.carbon.component) | ||
}) | ||
} | ||
defineExpose({ inputs, outputs, updateReferences }) | ||
const connections = computed(() => props.connections.filter(isRelatedConnection)) | ||
onMounted(() => { | ||
const carbonEl = carbonref.value | ||
if (!carbonEl) return | ||
updateReferences() | ||
Draggable.create(carbonEl, { | ||
bounds: props.bounds, | ||
trigger: draggHandle.value, | ||
inertia: false, | ||
edgeResistance: 0.9, | ||
onDrag: updateFibers | ||
}) | ||
}) | ||
function updateFibers() { | ||
// Updates the path out of and into the carbon | ||
connections.value.forEach((connection) => { | ||
connection.component?.update() | ||
}) | ||
} | ||
function setFibers(carbonId: string) { | ||
const parentCarbon = props.carbons.find((carbon) => carbon.id === carbonId) | ||
parentCarbon?.component?.updateReferences() | ||
setTimeout(() => updateFibers(), 0) | ||
} | ||
function addHookedCarbon(carbonId: string, type: HookType, hookIndex: number) { | ||
const childId = 'carbon-' + props.carbons.length | ||
props.carbons.push({ | ||
id: childId, | ||
position: [200, 200], | ||
component: undefined, | ||
connections: [carbonId], | ||
hooks: hooks | ||
}) | ||
addConnection(carbonId, childId, type, hookIndex) | ||
setFibers(carbonId) | ||
} | ||
function addConnection(carbonId: string, childId: string, type: HookType, hookIndex: number) { | ||
const fromOutput = type === 'output' || type === 'sink' // Is this connection being dragged out from a carbon output? | ||
const isOutputInout = type === 'output' || type === 'input' // Is this connection an output to input connection? | ||
props.connections.push({ | ||
id: 'connection-' + props.connections.length, | ||
type: isOutputInout ? 'output-input' : 'source-sink', | ||
output: { | ||
carbon: fromOutput ? carbonId : childId, | ||
hook: fromOutput ? hookIndex : 0 | ||
}, | ||
input: { | ||
carbon: fromOutput ? childId : carbonId, | ||
hook: fromOutput ? 0 : hookIndex | ||
} | ||
}) | ||
} | ||
function isRelatedConnection(connection: Connection) { | ||
const isFrom = connection.output.carbon === props.carbon.id | ||
const isTo = connection.input.carbon === props.carbon.id | ||
return isFrom || isTo | ||
} | ||
</script> | ||
|
||
<template> | ||
<div ref="carbonref" id="carbon"> | ||
<CarbonHooks | ||
ref="inputs" | ||
:carbon="carbon" | ||
type="input" | ||
@hookClick="(index) => addHookedCarbon(carbon.id, 'input', index)" | ||
/> | ||
<div class="core"> | ||
<CarbonHooks | ||
:carbon="carbon" | ||
type="input" | ||
@hookClick="(index) => addHookedCarbon(carbon.id, 'input', index)" | ||
/> | ||
<div ref="draggHandle" class="content"> | ||
<p> | ||
<strong>{{ title }}</strong> | ||
</p> | ||
</div> | ||
<CarbonHooks | ||
:carbon="carbon" | ||
type="output" | ||
@hookClick="(index) => addHookedCarbon(carbon.id, 'output', index)" | ||
/> | ||
</div> | ||
<CarbonHooks | ||
ref="outputs" | ||
:carbon="carbon" | ||
type="output" | ||
@hookClick="(index) => addHookedCarbon(carbon.id, 'output', index)" | ||
/> | ||
</div> | ||
</template> | ||
|
||
<style> | ||
#carbon { | ||
position: absolute; | ||
top: v-bind(top); | ||
left: v-bind(left); | ||
z-index: 1; | ||
display: grid; | ||
grid-template-columns: auto 1fr auto; | ||
justify-items: center; | ||
align-items: center; | ||
background-color: var(--accent-120); | ||
color: var(--base-20); | ||
border-radius: var(--radius); | ||
} | ||
#carbon .core { | ||
display: grid; | ||
min-height: var(--space-6); | ||
} | ||
#carbon .core p { | ||
line-height: 1; | ||
} | ||
#carbon .core .edges { | ||
flex-direction: row; | ||
} | ||
#carbon .core .content { | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
padding: var(--space-2); | ||
min-height: var(--space-5); | ||
border: 2px solid var(--accent-60); | ||
border-radius: var(--radius); | ||
height: 100%; | ||
width: 100%; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<script setup lang="ts"> | ||
import { ref, computed } from 'vue' | ||
import type { CarbonObject } from '../../types' | ||
import { gsap } from 'gsap' | ||
import { Draggable } from 'gsap/Draggable' | ||
import { InertiaPlugin } from 'gsap-trial/InertiaPlugin' | ||
gsap.registerPlugin(InertiaPlugin) | ||
gsap.registerPlugin(Draggable) | ||
const props = defineProps<{ | ||
carbon: CarbonObject | ||
type: string | ||
}>() | ||
const emit = defineEmits({ | ||
hookClick: (index: number) => true | ||
}) | ||
const hooks = ref<HTMLDivElement[]>([]) | ||
const carbonHooks = computed(() => props.carbon.hooks.filter((hook) => hook.type === props.type)) | ||
defineExpose({ hooks }) | ||
function storeRef(el: any, index: number) { | ||
hooks.value[index] = el | ||
} | ||
</script> | ||
|
||
<template> | ||
<div class="edges"> | ||
<div | ||
v-for="hook in carbonHooks" | ||
:key="hook.index" | ||
:ref="(e) => storeRef(e, hook.index)" | ||
class="hook" | ||
@click="emit('hookClick', hook.index)" | ||
></div> | ||
</div> | ||
</template> | ||
|
||
<style> | ||
#carbon .hook { | ||
height: var(--space-atom); | ||
aspect-ratio: 1 / 1; | ||
background: var(--accent); | ||
} | ||
#carbon .hook:hover { | ||
background: var(--accent-40); | ||
} | ||
#carbon .edges { | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
flex-direction: column; | ||
gap: var(--space-1); | ||
height: 100%; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<script setup lang="ts"> | ||
import type { Connection } from '../types' | ||
import FiberPath from './Fiber.vue' | ||
type FiberType = InstanceType<typeof FiberPath> | ||
defineProps<{ | ||
bounds?: HTMLDivElement | ||
connections: Connection[] | ||
}>() | ||
</script> | ||
|
||
<template> | ||
<div v-for="connection in connections" :key="connection.id"> | ||
<FiberPath | ||
v-if="connection.output.component && connection.input.component" | ||
:ref="(e) => (connection.component = e as FiberType)" | ||
:bounds="bounds" | ||
:output="connection.output.component?.outputs?.hooks[connection.output.hook]" | ||
:input="connection.input.component?.inputs?.hooks[connection.input.hook]" | ||
/> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
<script setup lang="ts"> | ||
import { computed, defineProps, onMounted, defineExpose } from 'vue' | ||
import { useResizeObserver } from '@vueuse/core' | ||
import { useFiber } from '../composables/useFiber' | ||
interface FiberProps { | ||
bounds?: HTMLDivElement | ||
output?: HTMLDivElement | ||
input?: HTMLDivElement | ||
} | ||
const { output, input, bounds } = defineProps<FiberProps>() | ||
const fiber = useFiber({ | ||
board: bounds, | ||
output: output, | ||
input: input | ||
}) | ||
defineExpose({ update: fiber.update }) | ||
const data = computed(() => { | ||
const path = fiber.path.value | ||
const flipped = path.reversed ? !path.flipped : path.flipped | ||
return createPathData(flipped) | ||
}) | ||
function createPathData(flipped: boolean) { | ||
const path = fiber.path.value | ||
const width = path.width - path.padding | ||
const height = path.height | ||
const curve = width * path.curve | ||
const strokeOffset = path.stroke / 2 | ||
const top = strokeOffset + path.padding | ||
const bottom = height - strokeOffset - path.padding | ||
const start = flipped ? top : bottom | ||
const end = `${width}, ${flipped ? bottom : top}` | ||
const startCurve = `${curve}, ${flipped ? top : bottom}` | ||
const endCurve = `${width - curve}, ${flipped ? bottom : top}` | ||
return `M${path.padding}, ${start} C${startCurve}, ${endCurve}, ${end}` | ||
} | ||
onMounted(() => { | ||
setTimeout(() => fiber.update(), 0) | ||
useResizeObserver(bounds, () => { | ||
fiber.update() | ||
}) | ||
}) | ||
</script> | ||
|
||
<template> | ||
<div :ref="(e) => fiber.set(e as HTMLDivElement)" id="rome" class="ancor"> | ||
<svg | ||
:width="fiber.path.value.width" | ||
:height="fiber.path.value.height" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path :d="data" :stroke-width="fiber.path.value.stroke" stroke-linecap="round" /> | ||
</svg> | ||
</div> | ||
</template> | ||
|
||
<style scoped> | ||
#rome { | ||
position: absolute; | ||
z-index: 0; | ||
} | ||
#rome svg path { | ||
fill: transparent; | ||
stroke: var(--accent); | ||
} | ||
</style> | ||
../composables/useFiber |
Oops, something went wrong.