Skip to content

Commit 8dff4e5

Browse files
committed
feat(352 | typesync.v2): working through publish flow
1 parent f336c9e commit 8dff4e5

File tree

12 files changed

+861
-289
lines changed

12 files changed

+861
-289
lines changed

apps/events/src/schema.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import { Entity, Type } from '@graphprotocol/hypergraph';
22

33
export class User extends Entity.Class<User>('User')({
44
name: Type.String,
5-
created: Type.Date,
5+
created: Type.Date
66
}) {}
77

88
export class Todo extends Entity.Class<Todo>('Todo')({
99
name: Type.String,
1010
completed: Type.Boolean,
11-
assignees: Type.Relation(User),
11+
assignees: Type.Relation(User)
1212
}) {}
1313

1414
export class Todo2 extends Entity.Class<Todo2>('Todo2')({
@@ -18,21 +18,22 @@ export class Todo2 extends Entity.Class<Todo2>('Todo2')({
1818
due: Type.Date,
1919
amount: Type.Number,
2020
point: Type.Point,
21-
website: Type.String,
21+
website: Type.String
2222
}) {}
2323

2424
export class JobOffer extends Entity.Class<JobOffer>('JobOffer')({
2525
name: Type.String,
26-
salary: Type.Number,
26+
salary: Type.Number
2727
}) {}
2828

2929
export class Company extends Entity.Class<Company>('Company')({
3030
name: Type.String,
31-
jobOffers: Type.Relation(JobOffer),
31+
jobOffers: Type.Relation(JobOffer)
3232
}) {}
3333

3434
export class Event extends Entity.Class<Event>('Event')({
3535
name: Type.String,
3636
description: Type.optional(Type.String),
3737
sponsors: Type.Relation(Company),
38-
}) {}
38+
createdAt: Type.Date
39+
}) {}

packages/hypergraph/typesync-studio/package.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,27 @@
1313
"lint:fix": "biome check --write --unsafe"
1414
},
1515
"dependencies": {
16-
"@base-ui-components/react": "1.0.0-beta.1",
17-
"@graphprotocol/grc-20": "^0.23.1",
16+
"@base-ui-components/react": "1.0.0-beta.2",
17+
"@graphprotocol/grc-20": "^0.24.1",
1818
"@graphprotocol/hypergraph": "workspace:*",
1919
"@graphprotocol/hypergraph-react": "workspace:*",
2020
"@graphql-typed-document-node/core": "^3.2.0",
2121
"@headlessui/react": "^2.2.7",
2222
"@phosphor-icons/react": "^2.1.10",
23-
"@tanstack/react-form": "^1.15.2",
24-
"@tanstack/react-query": "^5.84.1",
25-
"@tanstack/react-query-devtools": "^5.84.1",
26-
"@tanstack/react-router": "^1.130.11",
27-
"@tanstack/react-router-devtools": "^1.130.11",
28-
"@tanstack/router-plugin": "^1.130.11",
29-
"effect": "^3.17.6",
23+
"@tanstack/react-form": "^1.19.1",
24+
"@tanstack/react-query": "^5.85.0",
25+
"@tanstack/react-query-devtools": "^5.85.0",
26+
"@tanstack/react-router": "^1.131.7",
27+
"@tanstack/react-router-devtools": "^1.131.7",
28+
"@tanstack/router-plugin": "^1.131.7",
29+
"effect": "3.17.6",
3030
"graphql": "^16.11.0",
3131
"graphql-request": "^7.2.0",
3232
"lodash.debounce": "^4.0.8",
3333
"react": "^19.1.1",
3434
"react-dom": "^19.1.1",
3535
"tailwindcss": "^4.1.11",
36-
"zod": "^4.0.14"
36+
"zod": "^4.0.17"
3737
},
3838
"devDependencies": {
3939
"@graphql-codegen/cli": "^5.0.7",
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export function Arrow(props: React.ComponentProps<'svg'>) {
2+
return (
3+
<svg width="20" height="10" viewBox="0 0 20 10" fill="none" {...props}>
4+
<title>Tooltip positioner arrow</title>
5+
<path
6+
d="M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z"
7+
className="fill-gray-100 dark:fill-slate-900"
8+
/>
9+
<path
10+
d="M8.99542 1.85876C9.75604 1.17425 10.9106 1.17422 11.6713 1.85878L16.5281 6.22989C17.0789 6.72568 17.7938 7.00001 18.5349 7.00001L15.89 7L11.0023 2.60207C10.622 2.2598 10.0447 2.2598 9.66436 2.60207L4.77734 7L2.13171 7.00001C2.87284 7.00001 3.58774 6.72568 4.13861 6.22989L8.99542 1.85876Z"
11+
className="fill-gray-200 dark:fill-slate-900"
12+
/>
13+
<path
14+
d="M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z"
15+
className="fill-gray-300 dark:fill-slate-900"
16+
/>
17+
</svg>
18+
);
19+
}
Lines changed: 98 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,31 @@
1+
'use client';
2+
3+
import { Tooltip } from '@base-ui-components/react/tooltip';
14
import { CheckIcon, ExclamationMarkIcon } from '@phosphor-icons/react';
25

36
import { classnames } from '@/utils/classnames.ts';
7+
import { Arrow } from '../Arrow.tsx';
48
import { Loading } from '../Loading.tsx';
59
import { useFormContext } from './form.ts';
610

711
export function SubmitButton({
812
status,
13+
tooltip,
914
children,
10-
}: Readonly<{ status: 'idle' | 'error' | 'success' | 'submitting'; children: React.ReactNode }>) {
15+
}: Readonly<{
16+
status: 'idle' | 'error' | 'success' | 'submitting';
17+
/**
18+
* If provided, then render a rooltip around the button with additional details
19+
*/
20+
tooltip?:
21+
| {
22+
disabled?: boolean | undefined;
23+
content: React.ReactNode;
24+
}
25+
| null
26+
| undefined;
27+
children: React.ReactNode;
28+
}>) {
1129
const form = useFormContext();
1230

1331
return (
@@ -19,35 +37,85 @@ export function SubmitButton({
1937
dirty: state.isDirty,
2038
})}
2139
>
22-
{({ canSubmit, isSubmitting, valid, dirty }) => (
23-
<button
24-
type="submit"
25-
disabled={!canSubmit || !valid || !dirty || isSubmitting}
26-
data-state={status}
27-
className={classnames(
28-
'rounded-md bg-indigo-600 dark:bg-indigo-500 px-3 py-2 text-sm font-semibold text-white shadow-xs hover:bg-indigo-500 dark:hover:bg-indigo-400 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 dark:focus-visible:outline-indigo-500 inline-flex items-center gap-x-2 cursor-pointer',
29-
'disabled:bg-gray-400 disabled:text-gray-900 disabled:hover:bg-gray-400 disabled:focus-visible:outline-gray-400 disabled:cursor-not-allowed',
30-
'data-[state=error]:bg-red-600 data-[state=error]:hover:bg-red-500 data-[state=error]:focus-visible:bg-red-500 data-[state=success]:focus-visible:bg-green-500',
31-
'data-[state=success]:bg-green-600 data-[state=success]:hover:bg-green-500',
32-
)}
33-
>
34-
{status === 'submitting' ? (
35-
<Loading />
36-
) : status === 'success' ? (
37-
<>
38-
<CheckIcon className="size-5 text-white" aria-hidden="true" />
39-
{children}
40-
</>
41-
) : status === 'error' ? (
42-
<>
43-
<ExclamationMarkIcon className="size-5 text-white" aria-hidden="true" />
44-
Error
45-
</>
46-
) : (
47-
children
48-
)}
49-
</button>
50-
)}
40+
{({ canSubmit, isSubmitting, valid, dirty }) => {
41+
if (tooltip) {
42+
return (
43+
<Tooltip.Provider delay={300} closeDelay={1_000}>
44+
<Tooltip.Root disabled={tooltip.disabled || false}>
45+
<Tooltip.Trigger
46+
type="submit"
47+
disabled={!canSubmit || !valid || !dirty || isSubmitting}
48+
data-state={status}
49+
className={classnames(
50+
'rounded-md bg-indigo-600 dark:bg-indigo-500 px-3 py-2 text-sm font-semibold text-white shadow-xs hover:bg-indigo-500 dark:hover:bg-indigo-400 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 dark:focus-visible:outline-indigo-500 inline-flex items-center gap-x-2 cursor-pointer',
51+
'disabled:bg-gray-400 disabled:text-gray-900 disabled:hover:bg-gray-400 disabled:focus-visible:outline-gray-400 disabled:cursor-not-allowed',
52+
'data-[state=error]:bg-red-600 data-[state=error]:hover:bg-red-500 data-[state=error]:focus-visible:bg-red-500 data-[state=success]:focus-visible:bg-green-500',
53+
'data-[state=success]:bg-green-600 data-[state=success]:hover:bg-green-500',
54+
)}
55+
>
56+
{status === 'submitting' ? (
57+
<Loading />
58+
) : status === 'success' ? (
59+
<>
60+
<CheckIcon className="size-5 text-white" aria-hidden="true" />
61+
{children}
62+
</>
63+
) : status === 'error' ? (
64+
<>
65+
<ExclamationMarkIcon className="size-5 text-white" aria-hidden="true" />
66+
Error
67+
</>
68+
) : (
69+
children
70+
)}
71+
</Tooltip.Trigger>
72+
<Tooltip.Portal>
73+
<Tooltip.Positioner side="top" sideOffset={10}>
74+
<Tooltip.Popup className="box-border text-sm flex flex-col px-2 py-3 rounded-lg bg-gray-100 dark:bg-slate-900 transform-content data-[starting-style]:opacity-0 data-[ending-style]:opacity-0 w-fit max-w-xs">
75+
<Tooltip.Arrow className="flex data-[side=top]:-bottom-2 data-[side=top]:rotate-180 data-[side=bottom]:-top-2 data-[side=bottom]:rotate-0 data-[side=left]:-right-3 data-[side=left]:rotate-90 data-[side=right]:-left-3 data-[side=right]:-rotate-90">
76+
<Arrow />
77+
</Tooltip.Arrow>
78+
<span className="text-xs text-gray-700 dark:text-white whitespace-break-spaces w-full">
79+
{tooltip.content}
80+
</span>
81+
</Tooltip.Popup>
82+
</Tooltip.Positioner>
83+
</Tooltip.Portal>
84+
</Tooltip.Root>
85+
</Tooltip.Provider>
86+
);
87+
}
88+
89+
return (
90+
<button
91+
type="submit"
92+
disabled={!canSubmit || !valid || !dirty || isSubmitting}
93+
data-state={status}
94+
className={classnames(
95+
'rounded-md bg-indigo-600 dark:bg-indigo-500 px-3 py-2 text-sm font-semibold text-white shadow-xs hover:bg-indigo-500 dark:hover:bg-indigo-400 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 dark:focus-visible:outline-indigo-500 inline-flex items-center gap-x-2 cursor-pointer',
96+
'disabled:bg-gray-400 disabled:text-gray-900 disabled:hover:bg-gray-400 disabled:focus-visible:outline-gray-400 disabled:cursor-not-allowed',
97+
'data-[state=error]:bg-red-600 data-[state=error]:hover:bg-red-500 data-[state=error]:focus-visible:bg-red-500 data-[state=success]:focus-visible:bg-green-500',
98+
'data-[state=success]:bg-green-600 data-[state=success]:hover:bg-green-500',
99+
)}
100+
>
101+
{status === 'submitting' ? (
102+
<Loading />
103+
) : status === 'success' ? (
104+
<>
105+
<CheckIcon className="size-5 text-white" aria-hidden="true" />
106+
{children}
107+
</>
108+
) : status === 'error' ? (
109+
<>
110+
<ExclamationMarkIcon className="size-5 text-white" aria-hidden="true" />
111+
Error
112+
</>
113+
) : (
114+
children
115+
)}
116+
</button>
117+
);
118+
}}
51119
</form.Subscribe>
52120
);
53121
}

packages/hypergraph/typesync-studio/src/Components/InlineCode.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
export function InlineCode({ children }: Readonly<{ children: React.ReactNode }>) {
1+
export function InlineCode({ children, ...rest }: React.ComponentProps<'span'>) {
22
return (
3-
<span className="text-xs inline font-light text-gray-600 dark:text-gray-300 bg-gray-50 dark:bg-slate-600 ring-gray-500/10 rounded-md px-1.5 py-0.5 whitespace-nowrap ring-1 ring-inset">
3+
<span
4+
{...rest}
5+
className="text-xs inline font-light text-gray-600 dark:text-gray-300 bg-gray-50 dark:bg-slate-600 ring-gray-500/10 rounded-md px-1.5 py-0.5 whitespace-nowrap ring-1 ring-inset"
6+
>
47
{children}
58
</span>
69
);

0 commit comments

Comments
 (0)