mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-25 16:18:12 +08:00
Add support for adding/removing a graph's primary imports/exports separately from the secondary (#3089)
* Primary Import/Export * Primary Import/Export * Complete import exports * Final changes * Improve line width * Code review --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
co-authored by
Keavon Chambers
parent
ce1cd1706b
commit
f1a1275601
@@ -4,8 +4,7 @@
|
||||
import { fade } from "svelte/transition";
|
||||
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import type { Node } from "@graphite/messages";
|
||||
import type { FrontendNode, FrontendGraphInput, FrontendGraphOutput } from "@graphite/messages";
|
||||
import type { FrontendGraphInput, FrontendGraphOutput } from "@graphite/messages";
|
||||
import type { NodeGraphState } from "@graphite/state-providers/node-graph";
|
||||
import type { IconName } from "@graphite/utility-functions/icons";
|
||||
|
||||
@@ -178,7 +177,7 @@
|
||||
}
|
||||
|
||||
function dataTypeTooltip(value: FrontendGraphInput | FrontendGraphOutput): string {
|
||||
return value.resolvedType ? `Data Type:\n${value.resolvedType}` : `Data Type (Unresolved):\n${value.dataType}`;
|
||||
return `Data Type: ${value.resolvedType}`;
|
||||
}
|
||||
|
||||
function validTypesText(value: FrontendGraphInput): string {
|
||||
@@ -189,37 +188,11 @@
|
||||
function outputConnectedToText(output: FrontendGraphOutput): string {
|
||||
if (output.connectedTo.length === 0) return "Connected to nothing";
|
||||
|
||||
return output.connectedTo
|
||||
.map((inputConnector) => {
|
||||
if ((inputConnector as Node).nodeId === undefined) return `Connected to export index ${inputConnector.index}`;
|
||||
return `Connected to ${(inputConnector as Node).nodeId}, connector index ${inputConnector.index}`;
|
||||
})
|
||||
.join("\n");
|
||||
return `Connected to:\n${output.connectedTo.join("\n")}`;
|
||||
}
|
||||
|
||||
function inputConnectedToText(input: FrontendGraphInput): string {
|
||||
if (input.connectedTo === undefined) return "Connected to nothing";
|
||||
if ((input.connectedTo as Node).nodeId === undefined) return `Connected to import index ${input.connectedTo.index}`;
|
||||
return `Connected to ${(input.connectedTo as Node).nodeId}, connector index ${input.connectedTo.index}`;
|
||||
}
|
||||
|
||||
function primaryOutputConnectedToLayer(node: FrontendNode): boolean {
|
||||
let firstConnectedNode = Array.from($nodeGraph.nodes.values()).find((n) =>
|
||||
node.primaryOutput?.connectedTo.some((connector) => {
|
||||
if ((connector as Node).nodeId === undefined) return false;
|
||||
if (connector.index !== 0n) return false;
|
||||
return n.id === (connector as Node).nodeId || false;
|
||||
}),
|
||||
);
|
||||
return firstConnectedNode?.isLayer || false;
|
||||
}
|
||||
|
||||
function primaryInputConnectedToLayer(node: FrontendNode): boolean {
|
||||
const connectedNode = Array.from($nodeGraph.nodes.values()).find((n) => {
|
||||
if ((node.primaryInput?.connectedTo as Node) === undefined) return false;
|
||||
return n.id === (node.primaryInput?.connectedTo as Node).nodeId;
|
||||
});
|
||||
return connectedNode?.isLayer || false;
|
||||
return `Connected to:\n${input.connectedTo}`;
|
||||
}
|
||||
|
||||
function zipWithUndefined(arr1: FrontendGraphInput[], arr2: FrontendGraphOutput[]) {
|
||||
@@ -265,16 +238,12 @@
|
||||
{
|
||||
value: "node",
|
||||
label: "Node",
|
||||
action: () => {
|
||||
toggleLayerDisplay(false, contextMenuData.nodeId);
|
||||
},
|
||||
action: () => toggleLayerDisplay(false, contextMenuData.nodeId),
|
||||
},
|
||||
{
|
||||
value: "layer",
|
||||
label: "Layer",
|
||||
action: () => {
|
||||
toggleLayerDisplay(true, contextMenuData.nodeId);
|
||||
},
|
||||
action: () => toggleLayerDisplay(true, contextMenuData.nodeId),
|
||||
},
|
||||
]}
|
||||
disabled={!canBeToggledBetweenNodeAndLayer(contextMenuData.nodeId)}
|
||||
@@ -334,149 +303,181 @@
|
||||
|
||||
<!-- Import and Export connectors -->
|
||||
<div class="imports-and-exports" style:transform-origin={`0 0`} style:transform={`translate(${$nodeGraph.transform.x}px, ${$nodeGraph.transform.y}px) scale(${$nodeGraph.transform.scale})`}>
|
||||
{#each $nodeGraph.imports as { outputMetadata, position }, index}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 8 8"
|
||||
class="connector"
|
||||
data-connector="output"
|
||||
data-datatype={outputMetadata.dataType}
|
||||
style:--data-color={`var(--color-data-${outputMetadata.dataType.toLowerCase()})`}
|
||||
style:--data-color-dim={`var(--color-data-${outputMetadata.dataType.toLowerCase()}-dim)`}
|
||||
style:--offset-left={position.x / 24}
|
||||
style:--offset-top={position.y / 24}
|
||||
>
|
||||
<title>{`${dataTypeTooltip(outputMetadata)}\n\n${outputConnectedToText(outputMetadata)}`}</title>
|
||||
{#if outputMetadata.connectedTo !== undefined}
|
||||
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
|
||||
{:else}
|
||||
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color-dim)" />
|
||||
{/if}
|
||||
</svg>
|
||||
{#if $nodeGraph.updateImportsExports}
|
||||
{#each $nodeGraph.updateImportsExports.imports as frontendOutput, index}
|
||||
{#if frontendOutput}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 8 8"
|
||||
class="connector"
|
||||
data-connector="output"
|
||||
data-datatype={frontendOutput.dataType}
|
||||
style:--data-color={`var(--color-data-${frontendOutput.dataType.toLowerCase()})`}
|
||||
style:--data-color-dim={`var(--color-data-${frontendOutput.dataType.toLowerCase()}-dim)`}
|
||||
style:--offset-left={($nodeGraph.updateImportsExports.importPosition.x - 8) / 24}
|
||||
style:--offset-top={($nodeGraph.updateImportsExports.importPosition.y - 8) / 24 + index}
|
||||
>
|
||||
<title>{`${dataTypeTooltip(frontendOutput)}\n\n${outputConnectedToText(frontendOutput)}`}</title>
|
||||
{#if frontendOutput.connectedTo.length > 0}
|
||||
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
|
||||
{:else}
|
||||
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color-dim)" />
|
||||
{/if}
|
||||
</svg>
|
||||
|
||||
<div
|
||||
class="edit-import-export import"
|
||||
on:pointerenter={() => (hoveringImportIndex = index)}
|
||||
on:pointerleave={() => (hoveringImportIndex = undefined)}
|
||||
style:--offset-left={position.x / 24}
|
||||
style:--offset-top={position.y / 24}
|
||||
>
|
||||
{#if editingNameImportIndex == index}
|
||||
<input
|
||||
class="import-text-input"
|
||||
type="text"
|
||||
style:width={importsToEdgeTextInputWidth()}
|
||||
bind:this={inputElement}
|
||||
bind:value={editingNameText}
|
||||
on:blur={setEditingImportName}
|
||||
on:keydown={(e) => e.key === "Enter" && setEditingImportName(e)}
|
||||
/>
|
||||
<div
|
||||
on:pointerenter={() => (hoveringImportIndex = index)}
|
||||
on:pointerleave={() => (hoveringImportIndex = undefined)}
|
||||
class="edit-import-export import"
|
||||
class:separator-bottom={index === 0 && $nodeGraph.updateImportsExports.addImportExport}
|
||||
class:separator-top={index === 1 && $nodeGraph.updateImportsExports.addImportExport}
|
||||
style:--offset-left={($nodeGraph.updateImportsExports.importPosition.x - 8) / 24}
|
||||
style:--offset-top={($nodeGraph.updateImportsExports.importPosition.y - 8) / 24 + index}
|
||||
>
|
||||
{#if editingNameImportIndex == index}
|
||||
<input
|
||||
class="import-text-input"
|
||||
type="text"
|
||||
style:width={importsToEdgeTextInputWidth()}
|
||||
bind:this={inputElement}
|
||||
bind:value={editingNameText}
|
||||
on:blur={setEditingImportName}
|
||||
on:keydown={(e) => e.key === "Enter" && setEditingImportName(e)}
|
||||
/>
|
||||
{:else}
|
||||
<p class="import-text" on:dblclick={() => setEditingImportNameIndex(index, frontendOutput.name)}>
|
||||
{frontendOutput.name}
|
||||
</p>
|
||||
{/if}
|
||||
{#if (hoveringImportIndex === index || editingNameImportIndex === index) && $nodeGraph.updateImportsExports.addImportExport}
|
||||
<IconButton
|
||||
size={16}
|
||||
icon={"Remove"}
|
||||
class="remove-button-import"
|
||||
data-index={index}
|
||||
data-import-text-edge
|
||||
action={() => {
|
||||
/* Button is purely visual, clicking is handled in NodeGraphMessage::PointerDown */
|
||||
}}
|
||||
/>
|
||||
{#if index > 0}
|
||||
<div class="reorder-drag-grip" title="Reorder this export" />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<p class="import-text" on:dblclick={() => setEditingImportNameIndex(index, outputMetadata.name)}>{outputMetadata.name}</p>
|
||||
<div
|
||||
class="plus"
|
||||
style:--offset-top={($nodeGraph.updateImportsExports.importPosition.y - 12) / 24}
|
||||
style:--offset-left={($nodeGraph.updateImportsExports.importPosition.x - 12) / 24}
|
||||
>
|
||||
<IconButton size={24} icon="Add" action={() => editor.handle.addPrimaryImport()} />
|
||||
</div>
|
||||
{/if}
|
||||
{#if hoveringImportIndex === index || editingNameImportIndex === index}
|
||||
<IconButton
|
||||
size={16}
|
||||
icon={"Remove"}
|
||||
class="remove-button-import"
|
||||
data-index={index}
|
||||
data-import-text-edge
|
||||
action={() => {
|
||||
/* Button is purely visual, clicking is handled in NodeGraphMessage::PointerDown */
|
||||
}}
|
||||
/>
|
||||
<div class="reorder-drag-grip" title="Reorder this import"></div>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{#if $nodeGraph.reorderImportIndex !== undefined}
|
||||
{@const position = {
|
||||
x: Number($nodeGraph.imports[0].position.x),
|
||||
y: Number($nodeGraph.imports[0].position.y) + Number($nodeGraph.reorderImportIndex) * 24,
|
||||
}}
|
||||
<div class="reorder-bar" style:--offset-left={(position.x - 48) / 24} style:--offset-top={(position.y - 4) / 24} />
|
||||
{/if}
|
||||
{#if $nodeGraph.addImport !== undefined}
|
||||
<div class="plus" style:--offset-left={$nodeGraph.addImport.x / 24} style:--offset-top={$nodeGraph.addImport.y / 24}>
|
||||
<IconButton
|
||||
size={24}
|
||||
icon="Add"
|
||||
action={() => {
|
||||
/* Button is purely visual, clicking is handled in NodeGraphMessage::PointerDown */
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{#each $nodeGraph.exports as { inputMetadata, position }, index}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 8 8"
|
||||
class="connector"
|
||||
data-connector="input"
|
||||
data-datatype={inputMetadata.dataType}
|
||||
style:--data-color={`var(--color-data-${inputMetadata.dataType.toLowerCase()})`}
|
||||
style:--data-color-dim={`var(--color-data-${inputMetadata.dataType.toLowerCase()}-dim)`}
|
||||
style:--offset-left={position.x / 24}
|
||||
style:--offset-top={position.y / 24}
|
||||
>
|
||||
<title>{`${dataTypeTooltip(inputMetadata)}\n\n${inputConnectedToText(inputMetadata)}`}</title>
|
||||
{#if inputMetadata.connectedTo !== undefined}
|
||||
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
|
||||
{/each}
|
||||
|
||||
{#each $nodeGraph.updateImportsExports.exports as frontendInput, index}
|
||||
{#if frontendInput}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 8 8"
|
||||
class="connector"
|
||||
data-connector="input"
|
||||
data-datatype={frontendInput.dataType}
|
||||
style:--data-color={`var(--color-data-${frontendInput.dataType.toLowerCase()})`}
|
||||
style:--data-color-dim={`var(--color-data-${frontendInput.dataType.toLowerCase()}-dim)`}
|
||||
style:--offset-left={($nodeGraph.updateImportsExports.exportPosition.x - 8) / 24}
|
||||
style:--offset-top={($nodeGraph.updateImportsExports.exportPosition.y - 8) / 24 + index}
|
||||
>
|
||||
<title>{`${dataTypeTooltip(frontendInput)}\n\n${inputConnectedToText(frontendInput)}`}</title>
|
||||
{#if frontendInput.connectedTo !== "nothing"}
|
||||
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
|
||||
{:else}
|
||||
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color-dim)" />
|
||||
{/if}
|
||||
</svg>
|
||||
<div
|
||||
on:pointerenter={() => (hoveringExportIndex = index)}
|
||||
on:pointerleave={() => (hoveringExportIndex = undefined)}
|
||||
class="edit-import-export export"
|
||||
class:separator-bottom={index === 0 && $nodeGraph.updateImportsExports.addImportExport}
|
||||
class:separator-top={index === 1 && $nodeGraph.updateImportsExports.addImportExport}
|
||||
style:--offset-left={($nodeGraph.updateImportsExports.exportPosition.x - 8) / 24}
|
||||
style:--offset-top={($nodeGraph.updateImportsExports.exportPosition.y - 8) / 24 + index}
|
||||
>
|
||||
{#if (hoveringExportIndex === index || editingNameExportIndex === index) && $nodeGraph.updateImportsExports.addImportExport}
|
||||
{#if index > 0}
|
||||
<div class="reorder-drag-grip" title="Reorder this export" />
|
||||
{/if}
|
||||
<IconButton
|
||||
size={16}
|
||||
icon={"Remove"}
|
||||
class="remove-button-export"
|
||||
data-index={index}
|
||||
data-export-text-edge
|
||||
action={() => {
|
||||
/* Button is purely visual, clicking is handled in NodeGraphMessage::PointerDown */
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
{#if editingNameExportIndex === index}
|
||||
<input
|
||||
type="text"
|
||||
style:width={exportsToEdgeTextInputWidth()}
|
||||
bind:this={inputElement}
|
||||
bind:value={editingNameText}
|
||||
on:blur={setEditingExportName}
|
||||
on:keydown={(e) => e.key === "Enter" && setEditingExportName(e)}
|
||||
/>
|
||||
{:else}
|
||||
<p class="export-text" on:dblclick={() => setEditingExportNameIndex(index, frontendInput.name)}>
|
||||
{frontendInput.name}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color-dim)" />
|
||||
<div
|
||||
class="plus"
|
||||
style:--offset-left={($nodeGraph.updateImportsExports.exportPosition.x - 12) / 24}
|
||||
style:--offset-top={($nodeGraph.updateImportsExports.exportPosition.y - 12) / 24}
|
||||
>
|
||||
<IconButton size={24} icon="Add" action={() => editor.handle.addPrimaryExport()} />
|
||||
</div>
|
||||
{/if}
|
||||
</svg>
|
||||
<div
|
||||
class="edit-import-export export"
|
||||
on:pointerenter={() => (hoveringExportIndex = index)}
|
||||
on:pointerleave={() => (hoveringExportIndex = undefined)}
|
||||
style:--offset-left={position.x / 24}
|
||||
style:--offset-top={position.y / 24}
|
||||
>
|
||||
{#if hoveringExportIndex === index || editingNameExportIndex === index}
|
||||
<div class="reorder-drag-grip" title="Reorder this export"></div>
|
||||
<IconButton
|
||||
size={16}
|
||||
icon={"Remove"}
|
||||
class="remove-button-export"
|
||||
data-index={index}
|
||||
data-export-text-edge
|
||||
action={() => {
|
||||
/* Button is purely visual, clicking is handled in NodeGraphMessage::PointerDown */
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
{#if editingNameExportIndex === index}
|
||||
<input
|
||||
type="text"
|
||||
style:width={exportsToEdgeTextInputWidth()}
|
||||
bind:this={inputElement}
|
||||
bind:value={editingNameText}
|
||||
on:blur={setEditingExportName}
|
||||
on:keydown={(e) => e.key === "Enter" && setEditingExportName(e)}
|
||||
/>
|
||||
{:else}
|
||||
<p class="export-text" on:dblclick={() => setEditingExportNameIndex(index, inputMetadata.name)}>{inputMetadata.name}</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{#if $nodeGraph.reorderExportIndex !== undefined}
|
||||
{@const position = {
|
||||
x: Number($nodeGraph.exports[0].position.x),
|
||||
y: Number($nodeGraph.exports[0].position.y) + Number($nodeGraph.reorderExportIndex) * 24,
|
||||
}}
|
||||
<div class="reorder-bar" style:--offset-left={position.x / 24} style:--offset-top={(position.y - 4) / 24} />
|
||||
{/if}
|
||||
{#if $nodeGraph.addExport !== undefined}
|
||||
<div class="plus" style:--offset-left={$nodeGraph.addExport.x / 24} style:--offset-top={$nodeGraph.addExport.y / 24}>
|
||||
<IconButton
|
||||
size={24}
|
||||
icon={"Add"}
|
||||
action={() => {
|
||||
/* Button is purely visual, clicking is handled in NodeGraphMessage::PointerDown */
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
{#if $nodeGraph.updateImportsExports.addImportExport == true}
|
||||
<div
|
||||
class="plus"
|
||||
style:--offset-left={($nodeGraph.updateImportsExports.importPosition.x - 12) / 24}
|
||||
style:--offset-top={($nodeGraph.updateImportsExports.importPosition.y - 12) / 24 + $nodeGraph.updateImportsExports.imports.length}
|
||||
>
|
||||
<IconButton size={24} icon="Add" action={() => editor.handle.addSecondaryImport()} />
|
||||
</div>
|
||||
<div
|
||||
class="plus"
|
||||
style:--offset-left={($nodeGraph.updateImportsExports.exportPosition.x - 12) / 24}
|
||||
style:--offset-top={($nodeGraph.updateImportsExports.exportPosition.y - 12) / 24 + $nodeGraph.updateImportsExports.exports.length}
|
||||
>
|
||||
<IconButton size={24} icon={"Add"} action={() => editor.handle.addSecondaryExport()} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if $nodeGraph.reorderImportIndex !== undefined}
|
||||
{@const position = {
|
||||
x: Number($nodeGraph.updateImportsExports.importPosition.x),
|
||||
y: Number($nodeGraph.updateImportsExports.importPosition.y) + Number($nodeGraph.reorderImportIndex) * 24,
|
||||
}}
|
||||
<div class="reorder-bar" style:--offset-left={(position.x - 48) / 24} style:--offset-top={(position.y - 12) / 24} />
|
||||
{/if}
|
||||
|
||||
{#if $nodeGraph.reorderExportIndex !== undefined}
|
||||
{@const position = {
|
||||
x: Number($nodeGraph.updateImportsExports.exportPosition.x),
|
||||
y: Number($nodeGraph.updateImportsExports.exportPosition.y) + Number($nodeGraph.reorderExportIndex) * 24,
|
||||
}}
|
||||
<div class="reorder-bar" style:--offset-left={position.x / 24} style:--offset-top={(position.y - 12) / 24} />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -530,7 +531,7 @@
|
||||
<title>{`${dataTypeTooltip(node.primaryOutput)}\n\n${outputConnectedToText(node.primaryOutput)}`}</title>
|
||||
{#if node.primaryOutput.connectedTo.length > 0}
|
||||
<path d="M0,6.953l2.521,-1.694a2.649,2.649,0,0,1,2.959,0l2.52,1.694v5.047h-8z" fill="var(--data-color)" />
|
||||
{#if primaryOutputConnectedToLayer(node)}
|
||||
{#if node.primaryOutputConnectedToLayer}
|
||||
<path d="M0,-3.5h8v8l-2.521,-1.681a2.666,2.666,0,0,0,-2.959,0l-2.52,1.681z" fill="var(--data-color-dim)" />
|
||||
{/if}
|
||||
{:else}
|
||||
@@ -551,9 +552,9 @@
|
||||
{#if node.primaryInput}
|
||||
<title>{`${dataTypeTooltip(node.primaryInput)}\n\n${validTypesText(node.primaryInput)}\n\n${inputConnectedToText(node.primaryInput)}`}</title>
|
||||
{/if}
|
||||
{#if node.primaryInput?.connectedTo !== undefined}
|
||||
{#if node.primaryInput?.connectedTo !== "nothing"}
|
||||
<path d="M0,0H8V8L5.479,6.319a2.666,2.666,0,0,0-2.959,0L0,8Z" fill="var(--data-color)" />
|
||||
{#if primaryInputConnectedToLayer(node)}
|
||||
{#if node.primaryInputConnectedToLayer}
|
||||
<path d="M0,10.95l2.52,-1.69c0.89,-0.6,2.06,-0.6,2.96,0l2.52,1.69v5.05h-8v-5.05z" fill="var(--data-color-dim)" />
|
||||
{/if}
|
||||
{:else}
|
||||
@@ -937,6 +938,24 @@
|
||||
margin-top: -5px;
|
||||
height: 24px;
|
||||
|
||||
&.separator-bottom::after,
|
||||
&.separator-top::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background: var(--color-8-uppergray);
|
||||
height: 1px;
|
||||
left: -4px;
|
||||
right: -4px;
|
||||
}
|
||||
|
||||
&.separator-bottom::after {
|
||||
bottom: -1px;
|
||||
}
|
||||
|
||||
&.separator-top::before {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
&.import {
|
||||
right: calc(100% - var(--offset-left) * 24px);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user