@spaethtech/svelte-ui 0.1.10

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.
Files changed (116) hide show
  1. package/README.md +81 -0
  2. package/dist/components/Badge/Badge.svelte +80 -0
  3. package/dist/components/Badge/Badge.svelte.d.ts +14 -0
  4. package/dist/components/Badge/index.d.ts +1 -0
  5. package/dist/components/Badge/index.js +1 -0
  6. package/dist/components/Button/Button.svelte +172 -0
  7. package/dist/components/Button/Button.svelte.d.ts +32 -0
  8. package/dist/components/Button/index.d.ts +1 -0
  9. package/dist/components/Button/index.js +1 -0
  10. package/dist/components/Dialog/Dialog.svelte +101 -0
  11. package/dist/components/Dialog/Dialog.svelte.d.ts +18 -0
  12. package/dist/components/Dialog/index.d.ts +1 -0
  13. package/dist/components/Dialog/index.js +1 -0
  14. package/dist/components/ElementManager/ElementManager.svelte +397 -0
  15. package/dist/components/ElementManager/ElementManager.svelte.d.ts +43 -0
  16. package/dist/components/ElementManager/index.d.ts +1 -0
  17. package/dist/components/ElementManager/index.js +1 -0
  18. package/dist/components/EmailInput/EmailInput.svelte +47 -0
  19. package/dist/components/EmailInput/EmailInput.svelte.d.ts +14 -0
  20. package/dist/components/EmailInput/index.d.ts +1 -0
  21. package/dist/components/EmailInput/index.js +1 -0
  22. package/dist/components/Icon/Icon.svelte +74 -0
  23. package/dist/components/Icon/Icon.svelte.d.ts +13 -0
  24. package/dist/components/Icon/index.d.ts +1 -0
  25. package/dist/components/Icon/index.js +1 -0
  26. package/dist/components/Input/Input.svelte +268 -0
  27. package/dist/components/Input/Input.svelte.d.ts +18 -0
  28. package/dist/components/Input/index.d.ts +1 -0
  29. package/dist/components/Input/index.js +1 -0
  30. package/dist/components/List/List.svelte +580 -0
  31. package/dist/components/List/List.svelte.d.ts +38 -0
  32. package/dist/components/List/index.d.ts +1 -0
  33. package/dist/components/List/index.js +1 -0
  34. package/dist/components/ListItem/ListItem.svelte +175 -0
  35. package/dist/components/ListItem/ListItem.svelte.d.ts +24 -0
  36. package/dist/components/ListItem/index.d.ts +2 -0
  37. package/dist/components/ListItem/index.js +2 -0
  38. package/dist/components/ListView/ListView.svelte +463 -0
  39. package/dist/components/ListView/ListView.svelte.d.ts +37 -0
  40. package/dist/components/ListView/index.d.ts +2 -0
  41. package/dist/components/ListView/index.js +2 -0
  42. package/dist/components/NodeGraph/BaseNode.d.ts +57 -0
  43. package/dist/components/NodeGraph/BaseNode.js +30 -0
  44. package/dist/components/NodeGraph/Edge.svelte +60 -0
  45. package/dist/components/NodeGraph/Edge.svelte.d.ts +16 -0
  46. package/dist/components/NodeGraph/ExpressionEvaluator.d.ts +82 -0
  47. package/dist/components/NodeGraph/ExpressionEvaluator.js +152 -0
  48. package/dist/components/NodeGraph/Node.svelte +100 -0
  49. package/dist/components/NodeGraph/Node.svelte.d.ts +10 -0
  50. package/dist/components/NodeGraph/NodeGraph.svelte +52 -0
  51. package/dist/components/NodeGraph/NodeGraph.svelte.d.ts +14 -0
  52. package/dist/components/NodeGraph/NodeInstance.svelte.d.ts +80 -0
  53. package/dist/components/NodeGraph/NodeInstance.svelte.js +241 -0
  54. package/dist/components/NodeGraph/NodePort.svelte +75 -0
  55. package/dist/components/NodeGraph/NodePort.svelte.d.ts +11 -0
  56. package/dist/components/NodeGraph/decorators.d.ts +81 -0
  57. package/dist/components/NodeGraph/decorators.js +148 -0
  58. package/dist/components/NodeGraph/index.d.ts +9 -0
  59. package/dist/components/NodeGraph/index.js +9 -0
  60. package/dist/components/NodeGraph/types.d.ts +94 -0
  61. package/dist/components/NodeGraph/types.js +33 -0
  62. package/dist/components/NotesEditor/NotesEditor.svelte +203 -0
  63. package/dist/components/NotesEditor/NotesEditor.svelte.d.ts +9 -0
  64. package/dist/components/NotesEditor/index.d.ts +1 -0
  65. package/dist/components/NotesEditor/index.js +1 -0
  66. package/dist/components/NumberInput/NumberInput.svelte +353 -0
  67. package/dist/components/NumberInput/NumberInput.svelte.d.ts +26 -0
  68. package/dist/components/NumberInput/index.d.ts +1 -0
  69. package/dist/components/NumberInput/index.js +1 -0
  70. package/dist/components/PasswordInput/PasswordInput.svelte +41 -0
  71. package/dist/components/PasswordInput/PasswordInput.svelte.d.ts +13 -0
  72. package/dist/components/PasswordInput/index.d.ts +1 -0
  73. package/dist/components/PasswordInput/index.js +1 -0
  74. package/dist/components/Popup/index.d.ts +1 -0
  75. package/dist/components/Popup/index.js +1 -0
  76. package/dist/components/Rating/Rating.svelte +77 -0
  77. package/dist/components/Rating/Rating.svelte.d.ts +7 -0
  78. package/dist/components/Rating/index.d.ts +1 -0
  79. package/dist/components/Rating/index.js +1 -0
  80. package/dist/components/ScrollView/ScrollView.svelte +285 -0
  81. package/dist/components/ScrollView/ScrollView.svelte.d.ts +19 -0
  82. package/dist/components/ScrollView/index.d.ts +1 -0
  83. package/dist/components/ScrollView/index.js +1 -0
  84. package/dist/components/SearchInput/SearchInput.svelte +50 -0
  85. package/dist/components/SearchInput/SearchInput.svelte.d.ts +15 -0
  86. package/dist/components/SearchInput/index.d.ts +1 -0
  87. package/dist/components/SearchInput/index.js +1 -0
  88. package/dist/components/Select/Select.svelte +278 -0
  89. package/dist/components/Select/Select.svelte.d.ts +35 -0
  90. package/dist/components/Select/index.d.ts +1 -0
  91. package/dist/components/Select/index.js +1 -0
  92. package/dist/components/TextArea/TextArea.svelte +734 -0
  93. package/dist/components/TextArea/TextArea.svelte.d.ts +19 -0
  94. package/dist/components/TextArea/index.d.ts +1 -0
  95. package/dist/components/TextArea/index.js +1 -0
  96. package/dist/components/ThemeSelector/ThemeSelector.svelte +64 -0
  97. package/dist/components/ThemeSelector/ThemeSelector.svelte.d.ts +3 -0
  98. package/dist/components/ThemeSelector/index.d.ts +1 -0
  99. package/dist/components/ThemeSelector/index.js +1 -0
  100. package/dist/components/TooltipHandler/TooltipHandler.svelte +593 -0
  101. package/dist/components/TooltipHandler/TooltipHandler.svelte.d.ts +10 -0
  102. package/dist/components/TooltipHandler/index.d.ts +1 -0
  103. package/dist/components/TooltipHandler/index.js +1 -0
  104. package/dist/index.d.ts +24 -0
  105. package/dist/index.js +26 -0
  106. package/dist/styles/sizes.d.ts +78 -0
  107. package/dist/styles/sizes.js +120 -0
  108. package/dist/styles/variants.d.ts +106 -0
  109. package/dist/styles/variants.js +194 -0
  110. package/dist/types/ManagerTypes.d.ts +42 -0
  111. package/dist/types/ManagerTypes.js +1 -0
  112. package/dist/types/sizes.d.ts +5 -0
  113. package/dist/types/sizes.js +1 -0
  114. package/dist/types/variants.d.ts +1 -0
  115. package/dist/types/variants.js +1 -0
  116. package/package.json +65 -0
@@ -0,0 +1,37 @@
1
+ import type { Snippet } from "svelte";
2
+ type Option = Record<string, any> & {
3
+ value: string;
4
+ label: string;
5
+ };
6
+ interface Props {
7
+ options?: Option[];
8
+ value?: string | string[];
9
+ multiSelect?: boolean;
10
+ showCheckboxes?: boolean;
11
+ maxVisibleItems?: number;
12
+ itemHeight?: number;
13
+ minHeight?: number;
14
+ class?: string;
15
+ containerClass?: string;
16
+ disabled?: boolean;
17
+ children?: Snippet;
18
+ url?: string;
19
+ searchParam?: string;
20
+ transform?: (apiResponse: any) => Option[];
21
+ debounceMs?: number;
22
+ maxResults?: number;
23
+ headers?: Record<string, string>;
24
+ searchTerm?: string;
25
+ showLoading?: boolean;
26
+ loadingText?: string;
27
+ showError?: boolean;
28
+ errorText?: string;
29
+ emptyText?: string;
30
+ onError?: (error: Error) => void;
31
+ onLoadStart?: () => void;
32
+ onLoadEnd?: () => void;
33
+ onSelection?: (option: Option | Option[]) => void;
34
+ }
35
+ declare const ListView: import("svelte").Component<Props, {}, "value" | "searchTerm">;
36
+ type ListView = ReturnType<typeof ListView>;
37
+ export default ListView;
@@ -0,0 +1,2 @@
1
+ export { default } from './ListView.svelte';
2
+ export { default as ListView } from './ListView.svelte';
@@ -0,0 +1,2 @@
1
+ export { default } from './ListView.svelte';
2
+ export { default as ListView } from './ListView.svelte';
@@ -0,0 +1,57 @@
1
+ /**
2
+ * BaseNode - Abstract base class for all node definitions
3
+ *
4
+ * All custom nodes must extend this class and implement the execute() method.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * @Node({
9
+ * title: 'Math Operation',
10
+ * color: '#10b981',
11
+ * executeInEditor: true
12
+ * })
13
+ * export class MathNode extends BaseNode {
14
+ * @Input({ label: 'A', dataType: 'number' })
15
+ * a: number = 0;
16
+ *
17
+ * @Input({ label: 'B', dataType: 'number' })
18
+ * b: number = 0;
19
+ *
20
+ * @Output({ label: 'Result', dataType: 'number' })
21
+ * result: number = 0;
22
+ *
23
+ * execute() {
24
+ * this.result = this.a + this.b;
25
+ * }
26
+ * }
27
+ * ```
28
+ */
29
+ export declare abstract class BaseNode {
30
+ /**
31
+ * Execute the node's logic
32
+ *
33
+ * - For data nodes: Update output properties based on input properties
34
+ * - For flow nodes: Perform side effects and optionally return the flow output to follow
35
+ *
36
+ * @returns void for normal execution, or string (flow output key) for branching nodes
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // Data node
41
+ * execute() {
42
+ * this.result = this.a + this.b;
43
+ * }
44
+ *
45
+ * // Flow node
46
+ * execute() {
47
+ * console.log(this.message);
48
+ * }
49
+ *
50
+ * // Branch node (multiple flow outputs)
51
+ * execute() {
52
+ * return this.condition ? 'onTrue' : 'onFalse';
53
+ * }
54
+ * ```
55
+ */
56
+ abstract execute(): void | string;
57
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * BaseNode - Abstract base class for all node definitions
3
+ *
4
+ * All custom nodes must extend this class and implement the execute() method.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * @Node({
9
+ * title: 'Math Operation',
10
+ * color: '#10b981',
11
+ * executeInEditor: true
12
+ * })
13
+ * export class MathNode extends BaseNode {
14
+ * @Input({ label: 'A', dataType: 'number' })
15
+ * a: number = 0;
16
+ *
17
+ * @Input({ label: 'B', dataType: 'number' })
18
+ * b: number = 0;
19
+ *
20
+ * @Output({ label: 'Result', dataType: 'number' })
21
+ * result: number = 0;
22
+ *
23
+ * execute() {
24
+ * this.result = this.a + this.b;
25
+ * }
26
+ * }
27
+ * ```
28
+ */
29
+ export class BaseNode {
30
+ }
@@ -0,0 +1,60 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ from: { x: number; y: number };
4
+ to: { x: number; y: number };
5
+ selected?: boolean;
6
+ color?: string;
7
+ animated?: boolean;
8
+ }
9
+
10
+ let {
11
+ from,
12
+ to,
13
+ selected = false,
14
+ color = "var(--color-border)",
15
+ animated = false,
16
+ }: Props = $props();
17
+
18
+ // Calculate SVG path for bezier curve
19
+ const path = $derived.by(() => {
20
+ const dx = to.x - from.x;
21
+ const dy = to.y - from.y;
22
+
23
+ // Control point offset for smooth curves
24
+ const offset = Math.min(Math.abs(dx) * 0.5, 100);
25
+
26
+ return `M ${from.x} ${from.y} C ${from.x + offset} ${from.y}, ${to.x - offset} ${to.y}, ${to.x} ${to.y}`;
27
+ });
28
+ </script>
29
+
30
+ <svg
31
+ class="edge absolute inset-0 pointer-events-none"
32
+ style="overflow: visible;"
33
+ >
34
+ <path
35
+ d={path}
36
+ fill="none"
37
+ stroke={selected ? "var(--color-primary)" : color}
38
+ stroke-width={selected ? "3" : "2"}
39
+ class:animated
40
+ />
41
+ </svg>
42
+
43
+ <style>
44
+ .edge path {
45
+ transition:
46
+ stroke 0.2s,
47
+ stroke-width 0.2s;
48
+ }
49
+
50
+ .edge path.animated {
51
+ stroke-dasharray: 5, 5;
52
+ animation: dash 1s linear infinite;
53
+ }
54
+
55
+ @keyframes dash {
56
+ to {
57
+ stroke-dashoffset: -10;
58
+ }
59
+ }
60
+ </style>
@@ -0,0 +1,16 @@
1
+ interface Props {
2
+ from: {
3
+ x: number;
4
+ y: number;
5
+ };
6
+ to: {
7
+ x: number;
8
+ y: number;
9
+ };
10
+ selected?: boolean;
11
+ color?: string;
12
+ animated?: boolean;
13
+ }
14
+ declare const Edge: import("svelte").Component<Props, {}, "">;
15
+ type Edge = ReturnType<typeof Edge>;
16
+ export default Edge;
@@ -0,0 +1,82 @@
1
+ import { VariableScope } from './types.js';
2
+ /**
3
+ * Variable store with three-level scope hierarchy
4
+ */
5
+ export interface VariableStore {
6
+ global: Record<string, any>;
7
+ project: Record<string, any>;
8
+ workflow: Record<string, any>;
9
+ }
10
+ /**
11
+ * ExpressionEvaluator - Evaluates JavaScript expressions with variable substitution
12
+ *
13
+ * Supports:
14
+ * - Single expressions: `{{ age * 2 }}` → returns number
15
+ * - Template strings: `Hello {{ firstName }}!` → returns string
16
+ * - Object properties: `{{ user.name }}`
17
+ * - Complex expressions: `{{ items.length > 0 }}`
18
+ *
19
+ * Variable resolution order: Workflow → Project → Global
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const evaluator = new ExpressionEvaluator({
24
+ * global: { pi: 3.14159 },
25
+ * project: { projectName: 'MyProject' },
26
+ * workflow: { age: 25 }
27
+ * });
28
+ *
29
+ * evaluator.evaluate('{{ age * 2 }}'); // 50
30
+ * evaluator.evaluate('Hello {{ projectName }}!'); // "Hello MyProject!"
31
+ * evaluator.evaluate('{{ pi * 2 }}'); // 6.28318
32
+ * ```
33
+ */
34
+ export declare class ExpressionEvaluator {
35
+ private variables;
36
+ constructor(variables?: Partial<VariableStore>);
37
+ /**
38
+ * Set a variable in the specified scope
39
+ */
40
+ setVariable(name: string, value: any, scope?: VariableScope): void;
41
+ /**
42
+ * Get a variable with automatic scope resolution
43
+ * Resolution order: Workflow → Project → Global
44
+ */
45
+ getVariable(name: string): any;
46
+ /**
47
+ * Get all variables merged with proper precedence
48
+ */
49
+ private getAllVariables;
50
+ /**
51
+ * Evaluate an expression string
52
+ *
53
+ * @param input - The expression string (may contain {{ }} delimiters)
54
+ * @returns The evaluated result
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * evaluate('{{ age }}') // Variable lookup
59
+ * evaluate('{{ age * 2 }}') // Expression evaluation
60
+ * evaluate('Hello {{ name }}!') // Template string
61
+ * evaluate('{{ user.name }}') // Object property
62
+ * evaluate('{{ items.length > 0 }}') // Boolean expression
63
+ * ```
64
+ */
65
+ evaluate(input: string): any;
66
+ /**
67
+ * Evaluate a single expression (without {{ }} delimiters)
68
+ */
69
+ private evaluateExpression;
70
+ /**
71
+ * Update the variable store
72
+ */
73
+ updateVariables(variables: Partial<VariableStore>): void;
74
+ /**
75
+ * Clear variables in a specific scope
76
+ */
77
+ clearScope(scope: VariableScope): void;
78
+ /**
79
+ * Get all variables in a specific scope
80
+ */
81
+ getScope(scope: VariableScope): Record<string, any>;
82
+ }
@@ -0,0 +1,152 @@
1
+ import { VariableScope } from './types.js';
2
+ /**
3
+ * ExpressionEvaluator - Evaluates JavaScript expressions with variable substitution
4
+ *
5
+ * Supports:
6
+ * - Single expressions: `{{ age * 2 }}` → returns number
7
+ * - Template strings: `Hello {{ firstName }}!` → returns string
8
+ * - Object properties: `{{ user.name }}`
9
+ * - Complex expressions: `{{ items.length > 0 }}`
10
+ *
11
+ * Variable resolution order: Workflow → Project → Global
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const evaluator = new ExpressionEvaluator({
16
+ * global: { pi: 3.14159 },
17
+ * project: { projectName: 'MyProject' },
18
+ * workflow: { age: 25 }
19
+ * });
20
+ *
21
+ * evaluator.evaluate('{{ age * 2 }}'); // 50
22
+ * evaluator.evaluate('Hello {{ projectName }}!'); // "Hello MyProject!"
23
+ * evaluator.evaluate('{{ pi * 2 }}'); // 6.28318
24
+ * ```
25
+ */
26
+ export class ExpressionEvaluator {
27
+ variables;
28
+ constructor(variables) {
29
+ this.variables = {
30
+ global: variables?.global || {},
31
+ project: variables?.project || {},
32
+ workflow: variables?.workflow || {}
33
+ };
34
+ }
35
+ /**
36
+ * Set a variable in the specified scope
37
+ */
38
+ setVariable(name, value, scope = VariableScope.Workflow) {
39
+ this.variables[scope][name] = value;
40
+ }
41
+ /**
42
+ * Get a variable with automatic scope resolution
43
+ * Resolution order: Workflow → Project → Global
44
+ */
45
+ getVariable(name) {
46
+ if (name in this.variables.workflow) {
47
+ return this.variables.workflow[name];
48
+ }
49
+ if (name in this.variables.project) {
50
+ return this.variables.project[name];
51
+ }
52
+ if (name in this.variables.global) {
53
+ return this.variables.global[name];
54
+ }
55
+ return undefined;
56
+ }
57
+ /**
58
+ * Get all variables merged with proper precedence
59
+ */
60
+ getAllVariables() {
61
+ return {
62
+ ...this.variables.global,
63
+ ...this.variables.project,
64
+ ...this.variables.workflow
65
+ };
66
+ }
67
+ /**
68
+ * Evaluate an expression string
69
+ *
70
+ * @param input - The expression string (may contain {{ }} delimiters)
71
+ * @returns The evaluated result
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * evaluate('{{ age }}') // Variable lookup
76
+ * evaluate('{{ age * 2 }}') // Expression evaluation
77
+ * evaluate('Hello {{ name }}!') // Template string
78
+ * evaluate('{{ user.name }}') // Object property
79
+ * evaluate('{{ items.length > 0 }}') // Boolean expression
80
+ * ```
81
+ */
82
+ evaluate(input) {
83
+ if (typeof input !== 'string') {
84
+ return input;
85
+ }
86
+ const expressionRegex = /\{\{([^}]+)\}\}/g;
87
+ const matches = input.match(expressionRegex);
88
+ // No expressions found - return as is
89
+ if (!matches) {
90
+ return input;
91
+ }
92
+ // Single expression that spans entire string - return evaluated value
93
+ if (matches.length === 1 && input.trim() === matches[0].trim()) {
94
+ const expression = matches[0].replace(/\{\{|\}\}/g, '').trim();
95
+ return this.evaluateExpression(expression);
96
+ }
97
+ // Template string with multiple expressions - replace each and return string
98
+ let result = input;
99
+ for (const match of matches) {
100
+ const expression = match.replace(/\{\{|\}\}/g, '').trim();
101
+ const value = this.evaluateExpression(expression);
102
+ result = result.replace(match, String(value ?? ''));
103
+ }
104
+ return result;
105
+ }
106
+ /**
107
+ * Evaluate a single expression (without {{ }} delimiters)
108
+ */
109
+ evaluateExpression(expression) {
110
+ try {
111
+ // Create a function that evaluates the expression with variables in scope
112
+ const variables = this.getAllVariables();
113
+ const varNames = Object.keys(variables);
114
+ const varValues = Object.values(variables);
115
+ // Create function with variables as parameters
116
+ // eslint-disable-next-line no-new-func
117
+ const fn = new Function(...varNames, `return (${expression});`);
118
+ // Execute with variable values
119
+ return fn(...varValues);
120
+ }
121
+ catch (error) {
122
+ console.error(`Error evaluating expression: ${expression}`, error);
123
+ return undefined;
124
+ }
125
+ }
126
+ /**
127
+ * Update the variable store
128
+ */
129
+ updateVariables(variables) {
130
+ if (variables.global) {
131
+ this.variables.global = { ...this.variables.global, ...variables.global };
132
+ }
133
+ if (variables.project) {
134
+ this.variables.project = { ...this.variables.project, ...variables.project };
135
+ }
136
+ if (variables.workflow) {
137
+ this.variables.workflow = { ...this.variables.workflow, ...variables.workflow };
138
+ }
139
+ }
140
+ /**
141
+ * Clear variables in a specific scope
142
+ */
143
+ clearScope(scope) {
144
+ this.variables[scope] = {};
145
+ }
146
+ /**
147
+ * Get all variables in a specific scope
148
+ */
149
+ getScope(scope) {
150
+ return { ...this.variables[scope] };
151
+ }
152
+ }
@@ -0,0 +1,100 @@
1
+ <script lang="ts">
2
+ import type { NodeInstance } from "./NodeInstance.svelte.js";
3
+ import type { Snippet } from "svelte";
4
+
5
+ interface Props {
6
+ instance: NodeInstance;
7
+ selected?: boolean;
8
+ children?: Snippet;
9
+ }
10
+
11
+ let { instance, selected = false, children }: Props = $props();
12
+
13
+ const metadata = instance.metadata;
14
+ </script>
15
+
16
+ <div
17
+ class="node"
18
+ class:selected
19
+ class:executing={instance.executing}
20
+ class:error={instance.error}
21
+ style:left="{instance.position.x}px"
22
+ style:top="{instance.position.y}px"
23
+ style:border-color={selected
24
+ ? "var(--color-primary)"
25
+ : "var(--color-border)"}
26
+ >
27
+ <!-- Header -->
28
+ <div
29
+ class="node-header px-3 py-2 text-white font-medium text-sm"
30
+ style:background-color={metadata.node.color || "var(--color-primary)"}
31
+ >
32
+ {metadata.node.title}
33
+ </div>
34
+
35
+ <!-- Body -->
36
+ <div class="node-body p-3 bg-[var(--color-background)]">
37
+ <!-- Input ports -->
38
+ <div class="inputs space-y-2">
39
+ {#each instance.getAllInputs() as port}
40
+ <div class="port-row flex items-center justify-between gap-2">
41
+ <span class="text-sm text-[var(--color-text)]"
42
+ >{port.label}</span
43
+ >
44
+ <!-- Port rendering TODO -->
45
+ </div>
46
+ {/each}
47
+ </div>
48
+
49
+ <!-- Custom content -->
50
+ {#if children}
51
+ {@render children()}
52
+ {/if}
53
+
54
+ <!-- Output ports -->
55
+ <div class="outputs space-y-2 mt-2">
56
+ {#each instance.getAllOutputs() as port}
57
+ <div class="port-row flex items-center justify-between gap-2">
58
+ <span class="text-sm text-[var(--color-text)]"
59
+ >{port.label}</span
60
+ >
61
+ <!-- Port rendering TODO -->
62
+ </div>
63
+ {/each}
64
+ </div>
65
+ </div>
66
+
67
+ {#if instance.error}
68
+ <div class="node-error px-3 py-1 bg-red-100 text-red-700 text-xs">
69
+ {instance.error}
70
+ </div>
71
+ {/if}
72
+ </div>
73
+
74
+ <style>
75
+ .node {
76
+ position: absolute;
77
+ min-width: 200px;
78
+ border: 2px solid;
79
+ border-radius: 8px;
80
+ overflow: hidden;
81
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
82
+ cursor: move;
83
+ }
84
+
85
+ .node.selected {
86
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
87
+ }
88
+
89
+ .node.executing {
90
+ opacity: 0.8;
91
+ }
92
+
93
+ .node.error {
94
+ border-color: #dc2626 !important;
95
+ }
96
+
97
+ .node-header {
98
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
99
+ }
100
+ </style>
@@ -0,0 +1,10 @@
1
+ import type { NodeInstance } from "./NodeInstance.svelte.js";
2
+ import type { Snippet } from "svelte";
3
+ interface Props {
4
+ instance: NodeInstance;
5
+ selected?: boolean;
6
+ children?: Snippet;
7
+ }
8
+ declare const Node: import("svelte").Component<Props, {}, "">;
9
+ type Node = ReturnType<typeof Node>;
10
+ export default Node;
@@ -0,0 +1,52 @@
1
+ <script lang="ts">
2
+ import type { NodeInstance } from './NodeInstance.svelte.js';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ interface Props {
6
+ nodes?: NodeInstance[];
7
+ width?: number;
8
+ height?: number;
9
+ gridSize?: number;
10
+ showGrid?: boolean;
11
+ editable?: boolean;
12
+ children?: Snippet;
13
+ }
14
+
15
+ let {
16
+ nodes = [],
17
+ width,
18
+ height,
19
+ gridSize = 20,
20
+ showGrid = true,
21
+ editable = true,
22
+ children
23
+ }: Props = $props();
24
+ </script>
25
+
26
+ <div
27
+ class="nodegraph-canvas relative overflow-hidden bg-[var(--color-background)]"
28
+ style:width={width ? `${width}px` : '100%'}
29
+ style:height={height ? `${height}px` : '100%'}
30
+ >
31
+ {#if showGrid}
32
+ <div class="grid-pattern absolute inset-0 pointer-events-none"></div>
33
+ {/if}
34
+
35
+ <!-- Nodes and edges will be rendered here -->
36
+ <div class="nodes-container absolute inset-0">
37
+ <!-- TODO: Render nodes and edges -->
38
+ </div>
39
+
40
+ {#if children}
41
+ {@render children()}
42
+ {/if}
43
+ </div>
44
+
45
+ <style>
46
+ .grid-pattern {
47
+ background-image:
48
+ linear-gradient(to right, rgba(128, 128, 128, 0.1) 1px, transparent 1px),
49
+ linear-gradient(to bottom, rgba(128, 128, 128, 0.1) 1px, transparent 1px);
50
+ background-size: 20px 20px;
51
+ }
52
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { NodeInstance } from './NodeInstance.svelte.js';
2
+ import type { Snippet } from 'svelte';
3
+ interface Props {
4
+ nodes?: NodeInstance[];
5
+ width?: number;
6
+ height?: number;
7
+ gridSize?: number;
8
+ showGrid?: boolean;
9
+ editable?: boolean;
10
+ children?: Snippet;
11
+ }
12
+ declare const NodeGraph: import("svelte").Component<Props, {}, "">;
13
+ type NodeGraph = ReturnType<typeof NodeGraph>;
14
+ export default NodeGraph;