@you-agent-factory/components 0.0.0 → 0.0.2

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 (182) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +38 -7
  3. package/dist/category-paths.d.ts +3 -0
  4. package/dist/charts/chart-state-panel.d.ts +11 -0
  5. package/dist/charts/chart.d.ts +35 -0
  6. package/dist/charts/index.d.ts +5 -0
  7. package/dist/charts/index.js +287 -0
  8. package/dist/chunks/action-row.js +39 -0
  9. package/dist/chunks/alert-panel.js +182 -0
  10. package/dist/chunks/button.js +193 -0
  11. package/dist/chunks/cn.js +6 -0
  12. package/dist/chunks/factory-emulator-controls.js +123 -0
  13. package/dist/chunks/package-form-field.js +546 -0
  14. package/dist/chunks/scroll-area.js +261 -0
  15. package/dist/chunks/surface-panel.js +73 -0
  16. package/dist/chunks/table-layout.js +292 -0
  17. package/dist/chunks/typography-roles.js +26 -0
  18. package/dist/chunks/typography.js +129 -0
  19. package/dist/chunks/widget-frame.js +344 -0
  20. package/dist/data-display/code-panel.d.ts +12 -0
  21. package/dist/data-display/data-table.d.ts +27 -0
  22. package/dist/data-display/description-list.d.ts +4 -0
  23. package/{src/data-display/index.ts → dist/data-display/index.d.ts} +4 -26
  24. package/dist/data-display/index.js +20 -0
  25. package/dist/data-display/table-layout.d.ts +8 -0
  26. package/dist/data-display/table.d.ts +14 -0
  27. package/dist/factory-emulator/factory-emulator-controls.d.ts +23 -0
  28. package/dist/factory-emulator/index.d.ts +6 -0
  29. package/dist/factory-emulator/index.js +6 -0
  30. package/dist/feedback/alert-panel-semantics.d.ts +11 -0
  31. package/dist/feedback/alert-panel.d.ts +29 -0
  32. package/dist/feedback/index.d.ts +6 -0
  33. package/dist/feedback/index.js +10 -0
  34. package/dist/feedback/skeleton.d.ts +2 -0
  35. package/dist/forms/index.d.ts +19 -0
  36. package/dist/forms/index.js +37 -0
  37. package/dist/forms/package-checkbox.d.ts +3 -0
  38. package/dist/forms/package-enum-select.d.ts +42 -0
  39. package/dist/forms/package-file-input.d.ts +3 -0
  40. package/dist/forms/package-form-field.d.ts +49 -0
  41. package/dist/forms/package-input.d.ts +6 -0
  42. package/dist/forms/package-native-select.d.ts +3 -0
  43. package/dist/forms/package-select.d.ts +32 -0
  44. package/dist/forms/package-textarea.d.ts +10 -0
  45. package/dist/forms/select-icons.d.ts +3 -0
  46. package/dist/graphs/graph-edge-path.d.ts +18 -0
  47. package/dist/graphs/graph-edge.d.ts +15 -0
  48. package/dist/graphs/graph-node-button.d.ts +11 -0
  49. package/dist/graphs/graph-node-handle-badge.d.ts +5 -0
  50. package/dist/graphs/graph-node-handle.d.ts +18 -0
  51. package/dist/graphs/graph-node-shell.d.ts +13 -0
  52. package/dist/graphs/graph-node-state-indicator.d.ts +6 -0
  53. package/dist/graphs/graph-node-state.d.ts +23 -0
  54. package/dist/graphs/graph-viewport-surface.d.ts +5 -0
  55. package/dist/graphs/index.d.ts +13 -0
  56. package/dist/graphs/index.js +614 -0
  57. package/{src/icons/index.ts → dist/icons/index.d.ts} +1 -2
  58. package/dist/icons/index.js +4 -0
  59. package/dist/index.d.ts +26 -0
  60. package/dist/index.js +145 -0
  61. package/dist/layout/action-row.d.ts +8 -0
  62. package/{src/layout/index.ts → dist/layout/index.d.ts} +1 -3
  63. package/dist/layout/index.js +9 -0
  64. package/dist/layout/surface-panel.d.ts +15 -0
  65. package/{src/navigation/index.ts → dist/navigation/index.d.ts} +1 -2
  66. package/dist/navigation/index.js +4 -0
  67. package/dist/overlays/collapsible.d.ts +5 -0
  68. package/dist/overlays/dialog.d.ts +16 -0
  69. package/dist/overlays/index.d.ts +10 -0
  70. package/dist/overlays/index.js +27 -0
  71. package/dist/overlays/overlay-layout.d.ts +6 -0
  72. package/dist/overlays/popover.d.ts +6 -0
  73. package/dist/overlays/scroll-area.d.ts +9 -0
  74. package/dist/primitives/button-link.d.ts +5 -0
  75. package/dist/primitives/button.d.ts +9 -0
  76. package/dist/primitives/icon-button-shell.d.ts +10 -0
  77. package/{src/primitives/index.ts → dist/primitives/index.d.ts} +2 -19
  78. package/dist/primitives/index.js +49 -0
  79. package/dist/primitives/package-text.d.ts +6 -0
  80. package/dist/primitives/typography-roles.d.ts +12 -0
  81. package/dist/primitives/typography.d.ts +36 -0
  82. package/dist/recipes/index.d.ts +14 -0
  83. package/dist/recipes/index.js +32 -0
  84. package/dist/recipes/widget-frame-content.d.ts +24 -0
  85. package/dist/recipes/widget-frame-disclosure.d.ts +33 -0
  86. package/dist/recipes/widget-frame-layout.d.ts +12 -0
  87. package/dist/recipes/widget-frame-skeleton.d.ts +2 -0
  88. package/dist/recipes/widget-frame-states.d.ts +15 -0
  89. package/dist/recipes/widget-frame-typography.d.ts +10 -0
  90. package/dist/recipes/widget-frame.d.ts +12 -0
  91. package/{src → dist}/styles.css +36 -0
  92. package/dist/testing/index.d.ts +4 -0
  93. package/dist/testing/index.js +16 -0
  94. package/dist/testing/render.d.ts +5 -0
  95. package/{src/tokens/index.ts → dist/tokens/index.d.ts} +1 -2
  96. package/dist/tokens/index.js +4 -0
  97. package/dist/utilities/cn.d.ts +1 -0
  98. package/{src/utilities/index.ts → dist/utilities/index.d.ts} +1 -3
  99. package/dist/utilities/index.js +6 -0
  100. package/package.json +65 -64
  101. package/docs/README.md +0 -83
  102. package/docs/button.md +0 -119
  103. package/docs/charts.md +0 -325
  104. package/docs/data-display-code-panel.md +0 -120
  105. package/docs/feedback-alert-panel.md +0 -117
  106. package/docs/feedback-skeleton.md +0 -54
  107. package/docs/forms-form-field.md +0 -490
  108. package/docs/forms-input-primitives.md +0 -311
  109. package/docs/forms-select-primitives.md +0 -362
  110. package/docs/graphs.md +0 -250
  111. package/docs/layout-display-primitives.md +0 -211
  112. package/docs/overlays.md +0 -414
  113. package/docs/table-data-table.md +0 -331
  114. package/docs/typography-roles.md +0 -182
  115. package/docs/widget-frame-recipes.md +0 -273
  116. package/src/category-paths.ts +0 -20
  117. package/src/charts/chart-state-panel.tsx +0 -103
  118. package/src/charts/chart.tsx +0 -287
  119. package/src/charts/index.ts +0 -21
  120. package/src/data-display/code-panel.tsx +0 -67
  121. package/src/data-display/data-table.tsx +0 -180
  122. package/src/data-display/description-list.tsx +0 -24
  123. package/src/data-display/table-layout.ts +0 -12
  124. package/src/data-display/table.tsx +0 -131
  125. package/src/feedback/alert-panel-semantics.ts +0 -75
  126. package/src/feedback/alert-panel.tsx +0 -187
  127. package/src/feedback/index.ts +0 -21
  128. package/src/feedback/skeleton.tsx +0 -16
  129. package/src/forms/index.ts +0 -73
  130. package/src/forms/package-checkbox.tsx +0 -50
  131. package/src/forms/package-enum-select.tsx +0 -185
  132. package/src/forms/package-file-input.tsx +0 -25
  133. package/src/forms/package-form-field.tsx +0 -202
  134. package/src/forms/package-input.tsx +0 -25
  135. package/src/forms/package-native-select.tsx +0 -25
  136. package/src/forms/package-select.tsx +0 -209
  137. package/src/forms/package-textarea.tsx +0 -35
  138. package/src/forms/select-icons.tsx +0 -35
  139. package/src/graphs/graph-edge-path.ts +0 -241
  140. package/src/graphs/graph-edge.tsx +0 -130
  141. package/src/graphs/graph-interactive-example.tsx +0 -187
  142. package/src/graphs/graph-node-button.tsx +0 -51
  143. package/src/graphs/graph-node-handle-badge.tsx +0 -108
  144. package/src/graphs/graph-node-handle.ts +0 -28
  145. package/src/graphs/graph-node-shell.tsx +0 -111
  146. package/src/graphs/graph-node-state-indicator.tsx +0 -47
  147. package/src/graphs/graph-node-state.ts +0 -111
  148. package/src/graphs/graph-viewport-surface.tsx +0 -27
  149. package/src/graphs/index.ts +0 -41
  150. package/src/index.ts +0 -209
  151. package/src/layout/action-row.tsx +0 -53
  152. package/src/layout/surface-panel.tsx +0 -91
  153. package/src/overlays/collapsible.tsx +0 -22
  154. package/src/overlays/dialog.tsx +0 -148
  155. package/src/overlays/index.ts +0 -31
  156. package/src/overlays/overlay-layout.ts +0 -9
  157. package/src/overlays/popover.tsx +0 -29
  158. package/src/overlays/scroll-area.tsx +0 -78
  159. package/src/primitives/button-link.tsx +0 -22
  160. package/src/primitives/button.tsx +0 -258
  161. package/src/primitives/icon-button-shell.tsx +0 -49
  162. package/src/primitives/package-text.tsx +0 -29
  163. package/src/primitives/typography-roles.ts +0 -12
  164. package/src/primitives/typography.tsx +0 -165
  165. package/src/recipes/index.ts +0 -61
  166. package/src/recipes/widget-frame-content.tsx +0 -114
  167. package/src/recipes/widget-frame-disclosure.tsx +0 -161
  168. package/src/recipes/widget-frame-layout.ts +0 -40
  169. package/src/recipes/widget-frame-skeleton.tsx +0 -16
  170. package/src/recipes/widget-frame-states.tsx +0 -99
  171. package/src/recipes/widget-frame-typography.ts +0 -19
  172. package/src/recipes/widget-frame.tsx +0 -84
  173. package/src/testing/index.ts +0 -13
  174. package/src/testing/render.tsx +0 -16
  175. package/src/utilities/cn.ts +0 -5
  176. /package/{src → dist}/styles/color-palette-presets.css +0 -0
  177. /package/{src → dist}/styles/color-role-tokens.css +0 -0
  178. /package/{src → dist}/styles/layout-role-tokens.css +0 -0
  179. /package/{src → dist}/styles/text-color-role-tokens.css +0 -0
  180. /package/{src → dist}/styles/typography-role-tokens.css +0 -0
  181. /package/{src → dist}/styles/typography-role-utilities.css +0 -0
  182. /package/{src → dist}/styles/typography-roles.css +0 -0
@@ -1,209 +0,0 @@
1
- import * as SelectPrimitive from "@radix-ui/react-select";
2
- import {
3
- type ComponentProps,
4
- type ComponentRef,
5
- forwardRef,
6
- type ReactNode,
7
- } from "react";
8
-
9
- import { cn } from "../utilities/cn";
10
- import { inputVariants } from "./package-input";
11
- import { SelectCheckIcon, SelectChevronDownIcon } from "./select-icons";
12
-
13
- export const Select = SelectPrimitive.Root;
14
- export const SelectGroup = SelectPrimitive.Group;
15
- export const SelectValue = SelectPrimitive.Value;
16
-
17
- export type SelectTriggerProps = ComponentProps<typeof SelectPrimitive.Trigger>;
18
-
19
- export const SelectTrigger = forwardRef<
20
- ComponentRef<typeof SelectPrimitive.Trigger>,
21
- SelectTriggerProps
22
- >(function SelectTrigger({ className, children, ...props }, ref) {
23
- return (
24
- <SelectPrimitive.Trigger
25
- className={cn(
26
- inputVariants({
27
- className:
28
- "flex items-center justify-between gap-2 text-left data-[placeholder]:text-on-surface-disabled [&>span]:line-clamp-1",
29
- }),
30
- className,
31
- )}
32
- ref={ref}
33
- {...props}
34
- >
35
- {children}
36
- <SelectPrimitive.Icon asChild>
37
- <SelectChevronDownIcon className="h-4 w-4 shrink-0 text-af-text-subtle" />
38
- </SelectPrimitive.Icon>
39
- </SelectPrimitive.Trigger>
40
- );
41
- });
42
-
43
- export type SelectContentProps = ComponentProps<typeof SelectPrimitive.Content>;
44
-
45
- // tailwind-exception: intrinsic-sizing
46
- const SELECT_CONTENT_POPPER_CLASS = "min-w-[var(--radix-select-trigger-width)]";
47
- // tailwind-exception: intrinsic-sizing
48
- const SELECT_VIEWPORT_POPPER_CLASS =
49
- "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]";
50
-
51
- export function SelectContent({
52
- children,
53
- className,
54
- onCloseAutoFocus,
55
- position = "popper",
56
- ...props
57
- }: SelectContentProps) {
58
- return (
59
- <SelectPrimitive.Portal>
60
- <SelectPrimitive.Content
61
- className={cn(
62
- "relative z-50 max-h-72 overflow-hidden rounded-xl border border-outline bg-surface-container-high text-on-surface shadow-af-panel data-[state=closed]:animate-out data-[state=open]:animate-in",
63
- position === "popper" && SELECT_CONTENT_POPPER_CLASS,
64
- position === "popper" &&
65
- "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
66
- className,
67
- )}
68
- onCloseAutoFocus={onCloseAutoFocus}
69
- position={position}
70
- {...props}
71
- >
72
- <SelectPrimitive.Viewport
73
- className={cn(
74
- "p-1",
75
- position === "popper" && SELECT_VIEWPORT_POPPER_CLASS,
76
- )}
77
- >
78
- {children}
79
- </SelectPrimitive.Viewport>
80
- </SelectPrimitive.Content>
81
- </SelectPrimitive.Portal>
82
- );
83
- }
84
-
85
- export type SelectLabelProps = ComponentProps<typeof SelectPrimitive.Label>;
86
-
87
- export function SelectLabel({ className, ...props }: SelectLabelProps) {
88
- return (
89
- <SelectPrimitive.Label
90
- className={cn(
91
- "px-2 py-1.5 text-xs font-semibold uppercase tracking-[0.08em] text-on-surface-subtle",
92
- className,
93
- )}
94
- {...props}
95
- />
96
- );
97
- }
98
-
99
- export const SELECT_EMPTY_STATE_VALUE = "__select-empty-state__";
100
-
101
- export type SelectItemProps = ComponentProps<typeof SelectPrimitive.Item>;
102
-
103
- export const SelectItem = forwardRef<
104
- ComponentRef<typeof SelectPrimitive.Item>,
105
- SelectItemProps
106
- >(function SelectItem({ children, className, ...props }, ref) {
107
- return (
108
- <SelectPrimitive.Item
109
- className={cn(
110
- "relative flex w-full min-w-0 cursor-default select-none items-center rounded-lg py-2 pl-8 pr-2 text-sm outline-none focus:bg-surface-container-highest data-[disabled]:pointer-events-none data-[disabled]:text-on-surface-disabled data-[highlighted]:bg-surface-container-highest",
111
- className,
112
- )}
113
- ref={ref}
114
- {...props}
115
- >
116
- <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
117
- <SelectPrimitive.ItemIndicator>
118
- <SelectCheckIcon className="h-4 w-4" />
119
- </SelectPrimitive.ItemIndicator>
120
- </span>
121
- <SelectPrimitive.ItemText className="line-clamp-2 break-words">
122
- {children}
123
- </SelectPrimitive.ItemText>
124
- </SelectPrimitive.Item>
125
- );
126
- });
127
-
128
- export type SelectEmptyProps = {
129
- children: ReactNode;
130
- className?: string;
131
- };
132
-
133
- export function SelectEmpty({ children, className }: SelectEmptyProps) {
134
- return (
135
- <SelectPrimitive.Item
136
- className={cn(
137
- "relative flex w-full min-w-0 cursor-default select-none items-center rounded-lg px-2 py-2 text-sm text-on-surface-disabled data-[disabled]:pointer-events-none data-[disabled]:text-on-surface-disabled",
138
- className,
139
- )}
140
- disabled
141
- value={SELECT_EMPTY_STATE_VALUE}
142
- >
143
- <SelectPrimitive.ItemText className="line-clamp-2 break-words">
144
- {children}
145
- </SelectPrimitive.ItemText>
146
- </SelectPrimitive.Item>
147
- );
148
- }
149
-
150
- export type SelectSeparatorProps = ComponentProps<
151
- typeof SelectPrimitive.Separator
152
- >;
153
-
154
- export function SelectSeparator({ className, ...props }: SelectSeparatorProps) {
155
- return (
156
- <SelectPrimitive.Separator
157
- className={cn("-mx-1 my-1 h-px bg-outline", className)}
158
- {...props}
159
- />
160
- );
161
- }
162
-
163
- export interface SelectFieldProps {
164
- children: ReactNode;
165
- className?: string;
166
- description?: ReactNode;
167
- descriptionId?: string;
168
- error?: ReactNode;
169
- errorId?: string;
170
- inputId: string;
171
- label: ReactNode;
172
- }
173
-
174
- export function SelectField({
175
- children,
176
- className,
177
- description,
178
- descriptionId,
179
- error,
180
- errorId,
181
- inputId,
182
- label,
183
- }: SelectFieldProps) {
184
- return (
185
- <div className={cn("grid gap-2", className)}>
186
- <label
187
- className="text-xs font-bold uppercase tracking-[0.08em] text-af-text-subtle"
188
- htmlFor={inputId}
189
- >
190
- {label}
191
- </label>
192
- {children}
193
- {description ? (
194
- <p className="m-0 text-sm text-af-text-muted" id={descriptionId}>
195
- {description}
196
- </p>
197
- ) : null}
198
- {error ? (
199
- <p
200
- className="m-0 text-sm font-medium text-on-error-container"
201
- id={errorId}
202
- role="alert"
203
- >
204
- {error}
205
- </p>
206
- ) : null}
207
- </div>
208
- );
209
- }
@@ -1,35 +0,0 @@
1
- import { forwardRef, type TextareaHTMLAttributes } from "react";
2
-
3
- import { cn } from "../utilities/cn";
4
- import { inputVariants } from "./package-input";
5
-
6
- const TEXTAREA_PLAIN_CLASS =
7
- "m-0 w-full resize-none border-0 bg-transparent p-0 text-sm leading-6 text-on-surface outline-none";
8
-
9
- const TEXTAREA_FIELD_CLASS =
10
- "min-h-28 max-h-52 resize-none overflow-y-auto py-3";
11
-
12
- export type PackageTextareaProps = TextareaHTMLAttributes<HTMLTextAreaElement> & {
13
- variant?: "field" | "plain";
14
- };
15
-
16
- export function textareaVariants({ className }: { className?: string } = {}) {
17
- return inputVariants({ className: cn(TEXTAREA_FIELD_CLASS, className) });
18
- }
19
-
20
- export const PackageTextarea = forwardRef<
21
- HTMLTextAreaElement,
22
- PackageTextareaProps
23
- >(function PackageTextarea({ className, variant = "field", ...props }, ref) {
24
- return (
25
- <textarea
26
- className={
27
- variant === "plain"
28
- ? cn(TEXTAREA_PLAIN_CLASS, className)
29
- : textareaVariants({ className })
30
- }
31
- ref={ref}
32
- {...props}
33
- />
34
- );
35
- });
@@ -1,35 +0,0 @@
1
- import type { SVGProps } from "react";
2
-
3
- export function SelectChevronDownIcon(props: SVGProps<SVGSVGElement>) {
4
- return (
5
- <svg
6
- aria-hidden="true"
7
- fill="none"
8
- stroke="currentColor"
9
- strokeLinecap="round"
10
- strokeLinejoin="round"
11
- strokeWidth={1.8}
12
- viewBox="0 0 24 24"
13
- {...props}
14
- >
15
- <path d="m6 9 6 6 6-6" />
16
- </svg>
17
- );
18
- }
19
-
20
- export function SelectCheckIcon(props: SVGProps<SVGSVGElement>) {
21
- return (
22
- <svg
23
- aria-hidden="true"
24
- fill="none"
25
- stroke="currentColor"
26
- strokeLinecap="round"
27
- strokeLinejoin="round"
28
- strokeWidth={2}
29
- viewBox="0 0 24 24"
30
- {...props}
31
- >
32
- <path d="M20 6 9 17l-5-5" />
33
- </svg>
34
- );
35
- }
@@ -1,241 +0,0 @@
1
- import { getBezierPath, Position } from "@xyflow/react";
2
-
3
- export type GraphEdgeWaypoint = {
4
- x: number;
5
- y: number;
6
- };
7
-
8
- const CATMULL_ROM_ALPHA = 0.5;
9
- const MIN_PARAMETER_DISTANCE = 0.0001;
10
- const VIRTUAL_ENDPOINT_DISTANCE = 96;
11
-
12
- function positionVector(position: Position): GraphEdgeWaypoint {
13
- switch (position) {
14
- case Position.Left:
15
- return { x: -1, y: 0 };
16
- case Position.Right:
17
- return { x: 1, y: 0 };
18
- case Position.Top:
19
- return { x: 0, y: -1 };
20
- case Position.Bottom:
21
- return { x: 0, y: 1 };
22
- }
23
- }
24
-
25
- function pointDistance(
26
- first: GraphEdgeWaypoint,
27
- second: GraphEdgeWaypoint,
28
- ): number {
29
- return Math.hypot(second.x - first.x, second.y - first.y);
30
- }
31
-
32
- function catmullRomParameterDistance(
33
- first: GraphEdgeWaypoint,
34
- second: GraphEdgeWaypoint,
35
- ): number {
36
- return Math.max(
37
- MIN_PARAMETER_DISTANCE,
38
- pointDistance(first, second) ** CATMULL_ROM_ALPHA,
39
- );
40
- }
41
-
42
- function formatPathNumber(value: number): string {
43
- if (Object.is(value, -0)) {
44
- return "0";
45
- }
46
-
47
- return Number.isInteger(value) ? `${value}` : value.toFixed(3);
48
- }
49
-
50
- function compactConsecutiveRoutePoints(
51
- routePoints: readonly GraphEdgeWaypoint[],
52
- ): GraphEdgeWaypoint[] {
53
- const compacted: GraphEdgeWaypoint[] = [];
54
-
55
- for (const point of routePoints) {
56
- const previous = compacted.at(-1);
57
- if (previous && previous.x === point.x && previous.y === point.y) {
58
- continue;
59
- }
60
-
61
- compacted.push(point);
62
- }
63
-
64
- return compacted;
65
- }
66
-
67
- function virtualEndpoint(input: {
68
- direction: GraphEdgeWaypoint;
69
- from: GraphEdgeWaypoint;
70
- mode: "after" | "before";
71
- neighbor: GraphEdgeWaypoint;
72
- }): GraphEdgeWaypoint {
73
- const distance = Math.max(
74
- VIRTUAL_ENDPOINT_DISTANCE,
75
- pointDistance(input.from, input.neighbor),
76
- );
77
- const scalar = input.mode === "before" ? -distance : distance;
78
-
79
- return {
80
- x: input.from.x + input.direction.x * scalar,
81
- y: input.from.y + input.direction.y * scalar,
82
- };
83
- }
84
-
85
- function catmullRomTangent(input: {
86
- current: GraphEdgeWaypoint;
87
- next: GraphEdgeWaypoint;
88
- previous: GraphEdgeWaypoint;
89
- tCurrent: number;
90
- tNext: number;
91
- tPrevious: number;
92
- }): GraphEdgeWaypoint {
93
- const previousSpan = input.tCurrent - input.tPrevious;
94
- const nextSpan = input.tNext - input.tCurrent;
95
- const totalSpan = input.tNext - input.tPrevious;
96
-
97
- return {
98
- x:
99
- nextSpan *
100
- ((input.current.x - input.previous.x) / previousSpan -
101
- (input.next.x - input.previous.x) / totalSpan +
102
- (input.next.x - input.current.x) / nextSpan),
103
- y:
104
- nextSpan *
105
- ((input.current.y - input.previous.y) / previousSpan -
106
- (input.next.y - input.previous.y) / totalSpan +
107
- (input.next.y - input.current.y) / nextSpan),
108
- };
109
- }
110
-
111
- function buildWaypointCatmullRomPath(input: {
112
- routePoints: readonly GraphEdgeWaypoint[];
113
- sourcePosition: Position;
114
- targetPosition: Position;
115
- }): string {
116
- const routePoints = compactConsecutiveRoutePoints(input.routePoints);
117
- if (routePoints.length <= 1) {
118
- const [point] = routePoints;
119
- return point
120
- ? `M ${formatPathNumber(point.x)} ${formatPathNumber(point.y)}`
121
- : "";
122
- }
123
-
124
- const lastPointIndex = routePoints.length - 1;
125
- const [source] = routePoints;
126
- const points = [
127
- virtualEndpoint({
128
- direction: positionVector(input.sourcePosition),
129
- from: source,
130
- mode: "before",
131
- neighbor: routePoints[1],
132
- }),
133
- ...routePoints,
134
- virtualEndpoint({
135
- direction: {
136
- x: -positionVector(input.targetPosition).x,
137
- y: -positionVector(input.targetPosition).y,
138
- },
139
- from: routePoints[lastPointIndex],
140
- mode: "after",
141
- neighbor: routePoints[lastPointIndex - 1],
142
- }),
143
- ];
144
- const segments = [
145
- `M ${formatPathNumber(source.x)} ${formatPathNumber(source.y)}`,
146
- ];
147
-
148
- for (let index = 1; index <= lastPointIndex; index += 1) {
149
- const previous = points[index - 1];
150
- const start = points[index];
151
- const end = points[index + 1];
152
- const next = points[index + 2];
153
- const tPrevious = 0;
154
- const tStart = tPrevious + catmullRomParameterDistance(previous, start);
155
- const tEnd = tStart + catmullRomParameterDistance(start, end);
156
- const tNext = tEnd + catmullRomParameterDistance(end, next);
157
- const startTangent = catmullRomTangent({
158
- current: start,
159
- next: end,
160
- previous,
161
- tCurrent: tStart,
162
- tNext: tEnd,
163
- tPrevious,
164
- });
165
- const endTangent = catmullRomTangent({
166
- current: end,
167
- next,
168
- previous: start,
169
- tCurrent: tEnd,
170
- tNext,
171
- tPrevious: tStart,
172
- });
173
- const firstControl = {
174
- x: start.x + startTangent.x / 3,
175
- y: start.y + startTangent.y / 3,
176
- };
177
- const secondControl = {
178
- x: end.x - endTangent.x / 3,
179
- y: end.y - endTangent.y / 3,
180
- };
181
-
182
- segments.push(
183
- [
184
- "C",
185
- formatPathNumber(firstControl.x),
186
- formatPathNumber(firstControl.y),
187
- `${formatPathNumber(secondControl.x)},`,
188
- formatPathNumber(secondControl.y),
189
- `${formatPathNumber(end.x)},`,
190
- formatPathNumber(end.y),
191
- ].join(" "),
192
- );
193
- }
194
-
195
- return segments.join(" ");
196
- }
197
-
198
- export function buildGraphEdgePathThroughWaypoints(input: {
199
- sourceX: number;
200
- sourceY: number;
201
- sourcePosition: Position;
202
- targetX: number;
203
- targetY: number;
204
- targetPosition: Position;
205
- waypoints?: readonly GraphEdgeWaypoint[];
206
- }): {
207
- labelX: number;
208
- labelY: number;
209
- path: string;
210
- } {
211
- const routePoints = [
212
- { x: input.sourceX, y: input.sourceY },
213
- ...(input.waypoints ?? []),
214
- { x: input.targetX, y: input.targetY },
215
- ];
216
-
217
- if (routePoints.length <= 2) {
218
- const [path, labelX, labelY] = getBezierPath({
219
- sourcePosition: input.sourcePosition,
220
- sourceX: input.sourceX,
221
- sourceY: input.sourceY,
222
- targetPosition: input.targetPosition,
223
- targetX: input.targetX,
224
- targetY: input.targetY,
225
- });
226
- return { labelX, labelY, path };
227
- }
228
-
229
- const path = buildWaypointCatmullRomPath({
230
- routePoints,
231
- sourcePosition: input.sourcePosition,
232
- targetPosition: input.targetPosition,
233
- });
234
- const midpointIndex = Math.floor((routePoints.length - 1) / 2);
235
- const labelPoint = routePoints[midpointIndex];
236
- return {
237
- labelX: labelPoint.x,
238
- labelY: labelPoint.y,
239
- path,
240
- };
241
- }
@@ -1,130 +0,0 @@
1
- import { BaseEdge, type EdgeProps, getBezierPath } from "@xyflow/react";
2
- import { useEffect, useRef, useState } from "react";
3
-
4
- import {
5
- buildGraphEdgePathThroughWaypoints,
6
- type GraphEdgeWaypoint,
7
- } from "./graph-edge-path";
8
-
9
- export type GraphEdgeData = {
10
- alwaysShowLabel?: boolean;
11
- label?: string;
12
- waypoints?: GraphEdgeWaypoint[];
13
- };
14
-
15
- export const GRAPH_EDGE_TYPES = {
16
- graphEdge: GraphEdge,
17
- };
18
-
19
- export type GraphEdgeProps = EdgeProps & {
20
- edgeClassName?: string;
21
- labelClassName?: string;
22
- };
23
-
24
- export function GraphEdge({
25
- data,
26
- edgeClassName = "graph-edge",
27
- id,
28
- interactionWidth,
29
- labelClassName = "graph-edge-label pointer-events-none fill-on-surface-subtle text-[11px] font-semibold",
30
- markerEnd,
31
- selected,
32
- sourcePosition,
33
- sourceX,
34
- sourceY,
35
- style,
36
- targetPosition,
37
- targetX,
38
- targetY,
39
- }: GraphEdgeProps) {
40
- const edgeRef = useRef<SVGGElement | null>(null);
41
- const [inspected, setInspected] = useState(false);
42
- const edgeData = (data ?? {}) as GraphEdgeData;
43
- const routedPath = buildGraphEdgePathThroughWaypoints({
44
- sourcePosition,
45
- sourceX,
46
- sourceY,
47
- targetPosition,
48
- targetX,
49
- targetY,
50
- waypoints: edgeData.waypoints,
51
- });
52
- const [fallbackPath, fallbackLabelX, fallbackLabelY] = getBezierPath({
53
- sourcePosition,
54
- sourceX,
55
- sourceY,
56
- targetPosition,
57
- targetX,
58
- targetY,
59
- });
60
- const edgePath =
61
- edgeData.waypoints && edgeData.waypoints.length > 0
62
- ? routedPath.path
63
- : fallbackPath;
64
- const labelX =
65
- edgeData.waypoints && edgeData.waypoints.length > 0
66
- ? routedPath.labelX
67
- : fallbackLabelX;
68
- const labelY =
69
- edgeData.waypoints && edgeData.waypoints.length > 0
70
- ? routedPath.labelY
71
- : fallbackLabelY;
72
-
73
- useEffect(() => {
74
- const edgeElement = edgeRef.current?.parentElement;
75
- if (!edgeElement) {
76
- return;
77
- }
78
-
79
- const show = () => setInspected(true);
80
- const hide = () => setInspected(false);
81
-
82
- edgeElement.addEventListener("mouseenter", show);
83
- edgeElement.addEventListener("mouseleave", hide);
84
- edgeElement.addEventListener("focusin", show);
85
- edgeElement.addEventListener("focusout", hide);
86
-
87
- return () => {
88
- edgeElement.removeEventListener("mouseenter", show);
89
- edgeElement.removeEventListener("mouseleave", hide);
90
- edgeElement.removeEventListener("focusin", show);
91
- edgeElement.removeEventListener("focusout", hide);
92
- };
93
- }, []);
94
-
95
- const revealLabel = Boolean(
96
- edgeData.label && (edgeData.alwaysShowLabel || inspected || selected),
97
- );
98
-
99
- return (
100
- <g
101
- className={edgeClassName}
102
- data-edge-id={id}
103
- data-label-visible={revealLabel ? "true" : "false"}
104
- ref={edgeRef}
105
- >
106
- <BaseEdge
107
- interactionWidth={interactionWidth}
108
- markerEnd={markerEnd}
109
- path={edgePath}
110
- style={style}
111
- />
112
- {edgeData.label ? (
113
- <text
114
- className={labelClassName}
115
- style={{
116
- paintOrder: "stroke",
117
- stroke: "var(--color-surface)",
118
- strokeLinejoin: "round",
119
- strokeWidth: 8,
120
- }}
121
- textAnchor="middle"
122
- x={labelX}
123
- y={labelY}
124
- >
125
- {edgeData.label}
126
- </text>
127
- ) : null}
128
- </g>
129
- );
130
- }