Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@
"@tanstack/react-query": "catalog:",
"@workspace/db": "workspace:*",
"@workspace/db-react": "workspace:*",
"@workspace/i18n": "workspace:*",
"@workspace/keypair": "workspace:*",
"@workspace/portfolio": "workspace:*",
"@workspace/settings": "workspace:*",
Expand Down
1 change: 1 addition & 0 deletions packages/dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"@tanstack/react-query": "catalog:",
"@workspace/db": "workspace:*",
"@workspace/db-react": "workspace:*",
"@workspace/i18n": "workspace:*",
"@workspace/keypair": "workspace:*",
"@workspace/portfolio": "workspace:*",
"@workspace/settings": "workspace:*",
Expand Down
62 changes: 62 additions & 0 deletions packages/dev/src/dev-feature-ui-inputs-solana-address.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { solanaAddressSchema } from '@workspace/db/solana/solana-address-schema'
import { Button } from '@workspace/ui/components/button'
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@workspace/ui/components/form'
import { InputGroup, InputGroupAddon, InputGroupInput } from '@workspace/ui/components/input-group'
import { UiDebug } from '@workspace/ui/components/ui-debug'
import { UiIcon } from '@workspace/ui/components/ui-icon'
import { cn } from '@workspace/ui/lib/utils'
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import { z } from 'zod'

const formSchema = z.object({
address: solanaAddressSchema,
})

type FormSchemaType = z.infer<typeof formSchema>
export function DevFeatureUiInputsSolanaAddress() {
const [result, setResult] = useState<FormSchemaType | null>(null)

const form = useForm({
defaultValues: {
address: '',
},
mode: 'all',
resolver: zodResolver(formSchema),
})
function onSubmit(values: z.infer<typeof formSchema>) {
setResult(values)
}

return (
<Form {...form}>
<form className="space-y-8" onSubmit={form.handleSubmit(onSubmit)}>
<FormField
control={form.control}
name="address"
render={({ field, fieldState }) => (
<FormItem>
<FormLabel>Address</FormLabel>
<FormControl>
<InputGroup>
<InputGroupInput placeholder="Enter a Solana address" {...field} />
<InputGroupAddon align="inline-end">
<UiIcon className={cn({ 'text-green-400': !!field.value && !fieldState.invalid })} icon="check" />
</InputGroupAddon>
</InputGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="flex justify-end space-x-2">
<Button disabled={!form.formState.isValid} type="submit">
Submit
</Button>
</div>
{result ? <UiDebug data={result} /> : null}
</form>
</Form>
)
}
88 changes: 88 additions & 0 deletions packages/dev/src/dev-feature-ui-inputs-solana-addresses.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { solanaAddressSchema } from '@workspace/db/solana/solana-address-schema'
import { useTranslation } from '@workspace/i18n'
import { Button } from '@workspace/ui/components/button'
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@workspace/ui/components/form'
import { InputGroup, InputGroupAddon, InputGroupInput } from '@workspace/ui/components/input-group'
import { UiDebug } from '@workspace/ui/components/ui-debug'
import { UiIcon } from '@workspace/ui/components/ui-icon'
import { useState } from 'react'
import { useFieldArray, useForm } from 'react-hook-form'
import { z } from 'zod'

const formSchema = z.object({
addresses: z.array(z.object({ value: solanaAddressSchema })),
})

type FormSchemaType = z.infer<typeof formSchema>
export function DevFeatureUiInputsSolanaAddresses() {
const { t } = useTranslation('ui')
const [result, setResult] = useState<FormSchemaType | null>(null)

const form = useForm({
defaultValues: {
addresses: [{ value: '' }],
},
mode: 'all',
resolver: zodResolver(formSchema),
})
const { fields, append, remove } = useFieldArray({
control: form.control,
name: 'addresses',
})

function onSubmit(values: z.infer<typeof formSchema>) {
setResult(values)
}

return (
<Form {...form}>
<form className="space-y-2 md:space-y-6" onSubmit={form.handleSubmit(onSubmit)}>
{fields.map((field, index) => (
<FormField
control={form.control}
key={field.id}
name={`addresses.${index}.value`}
render={({ field }) => (
<FormItem>
<FormLabel className="justify-between">Address {index + 1}</FormLabel>
<FormControl>
<InputGroup>
<InputGroupInput placeholder="Enter a Solana address" {...field} />
<InputGroupAddon align="inline-end">
<Button
disabled={index === 0}
onClick={() => remove(index)}
size="sm"
title={t(($) => $.actionRemove)}
type="button"
variant="ghost"
>
<UiIcon icon="x" />
</Button>
</InputGroupAddon>
</InputGroup>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
))}
<div className="flex justify-end space-x-2">
<Button
disabled={fields.length > 9 || !form.formState.isValid}
onClick={() => append({ value: '' })}
type="button"
variant="secondary"
>
<UiIcon icon="plus" /> {t(($) => $.actionAdd)}
</Button>
<Button disabled={!form.formState.isValid} type="submit">
{t(($) => $.actionSave)}
</Button>
</div>
{result ? <UiDebug data={result} /> : null}
</form>
</Form>
)
}
14 changes: 14 additions & 0 deletions packages/dev/src/dev-feature-ui-inputs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { UiCard } from '@workspace/ui/components/ui-card'
import { DevFeatureUiInputsSolanaAddress } from './dev-feature-ui-inputs-solana-address.tsx'
import { DevFeatureUiInputsSolanaAddresses } from './dev-feature-ui-inputs-solana-addresses.tsx'

export function DevFeatureUiInputs() {
return (
<UiCard title="ui inputs">
<div className="space-y-2 md:space-y-6">
<DevFeatureUiInputsSolanaAddress />
<DevFeatureUiInputsSolanaAddresses />
</div>
</UiCard>
)
}
2 changes: 2 additions & 0 deletions packages/dev/src/dev-feature-ui.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { DevFeatureUiAvatars } from './dev-feature-ui-avatars.tsx'
import { DevFeatureUiColors } from './dev-feature-ui-colors.tsx'
import { DevFeatureUiIcons } from './dev-feature-ui-icons.tsx'
import { DevFeatureUiInputs } from './dev-feature-ui-inputs.tsx'

export default function DevFeatureUi() {
return (
<div className="space-y-6">
<DevFeatureUiInputs />
<DevFeatureUiIcons />
<DevFeatureUiAvatars />
<DevFeatureUiColors />
Expand Down
3 changes: 3 additions & 0 deletions packages/i18n/locales/en/ui.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"actionAdd": "Add",
"actionRemove": "Remove",
"actionSave": "Save",
"errorTitle": "Oops, an error occurred",
"experimentalWarningDescription": "Use this wallet at your own risk. Do not use any real funds.",
"experimentalWarningTitle": "This is experimental software.",
Expand Down
3 changes: 3 additions & 0 deletions packages/i18n/locales/es/ui.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"actionAdd": "Agregar",
"actionRemove": "Eliminar",
"actionSave": "Guardar",
"errorTitle": "Uy, ocurrió un error",
"experimentalWarningDescription": "Utilice esta billetera bajo su propio riesgo. No use fondos reales.",
"experimentalWarningTitle": "Este es un software experimental.",
Expand Down
3 changes: 3 additions & 0 deletions packages/i18n/src/resources.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,9 @@ interface Resources {
languageSpanish: 'Spanish'
}
ui: {
actionAdd: 'Add'
actionRemove: 'Remove'
actionSave: 'Save'
errorTitle: 'Oops, an error occurred'
experimentalWarningDescription: 'Use this wallet at your own risk. Do not use any real funds.'
experimentalWarningTitle: 'This is experimental software.'
Expand Down
3 changes: 3 additions & 0 deletions packages/ui/src/components/ui-icon-map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
LucideUmbrella,
LucideUploadCloud,
LucideWallet2,
LucideX,
} from 'lucide-react'
import type * as react from 'react'
import type { ForwardRefExoticComponent } from 'react'
Expand Down Expand Up @@ -93,6 +94,7 @@ export type UiIconName =
| 'upload'
| 'wallet'
| 'watch'
| 'x'

const uiIconMap = new Map<UiIconName, UiIconLucide>()
.set('add', LucidePlus)
Expand Down Expand Up @@ -139,6 +141,7 @@ const uiIconMap = new Map<UiIconName, UiIconLucide>()
.set('upload', LucideUploadCloud)
.set('wallet', LucideWallet2)
.set('watch', LucideEye)
.set('x', LucideX)

export function getIcon(type: UiIconName) {
if (!uiIconMap.has(type)) {
Expand Down
Loading