Updated icons.

This commit is contained in:
Mike Cao 2025-09-22 20:11:31 -07:00
parent d8b3c8d13c
commit bf16ade184
23 changed files with 159 additions and 163 deletions

View file

@ -82,7 +82,7 @@
"@react-spring/web": "^10.0.1",
"@svgr/cli": "^8.1.0",
"@tanstack/react-query": "^5.85.5",
"@umami/react-zen": "^0.181.0",
"@umami/react-zen": "^0.183.0",
"@umami/redis-client": "^0.29.0",
"bcryptjs": "^3.0.2",
"chalk": "^5.6.0",

58
pnpm-lock.yaml generated
View file

@ -45,8 +45,8 @@ importers:
specifier: ^5.85.5
version: 5.85.5(react@19.1.1)
'@umami/react-zen':
specifier: ^0.181.0
version: 0.181.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))
specifier: ^0.183.0
version: 0.183.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))
'@umami/redis-client':
specifier: ^0.29.0
version: 0.29.0
@ -1061,8 +1061,8 @@ packages:
'@fontsource/inter@5.2.6':
resolution: {integrity: sha512-CZs9S1CrjD0jPwsNy9W6j0BhsmRSQrgwlTNkgQXTsAeDRM42LBRLo3eo9gCzfH4GvV7zpyf78Ozfl773826csw==}
'@fontsource/jetbrains-mono@5.2.6':
resolution: {integrity: sha512-nz//dBr99hXZmHp10wgNI00qThWImkzRR5PQjvRM+rpmuHO5rYBJCqPPWufidCvmkkryXx/GOP/lgqsM3R3Org==}
'@fontsource/jetbrains-mono@5.2.8':
resolution: {integrity: sha512-6w8/SG4kqvIMu7xd7wt6x3idn1Qux3p9N62s6G3rfldOUYHpWcc2FKrqf+Vo44jRvqWj2oAtTHrZXEP23oSKwQ==}
'@formatjs/cli@4.8.4':
resolution: {integrity: sha512-zZI8QYVl5CHaT6j9OHjS+0mMnWzopBVH0un4n5b4IhIJRzIKnxwFTkxBp5Ifqj6FntrwzIGqP+D6v8u7MPYsmw==}
@ -1539,8 +1539,8 @@ packages:
'@prisma/get-platform@6.16.0':
resolution: {integrity: sha512-eaJOOvAoGslSUTjiQrtE9E0hoBdfL43j8SymOGD6LbdrKRNtIoiy6qiBaEr2fNYD+R/Qns7QOwPhl7SVHJayKA==}
'@react-aria/autocomplete@3.0.0-rc.1':
resolution: {integrity: sha512-4/+XHkCq9nkC0TNfgPsbuMTu3iwM6Gz4j67rTQRMXrWwCTAqAHJJEmDz/YDt/04Rg+dkGPsauHHMqDxwxZV24Q==}
'@react-aria/autocomplete@3.0.0-rc.2':
resolution: {integrity: sha512-55KVj5FePFTHk8nWfUUNN8m7rBL+aSRE0CxHI2t8JG3uam3nY7jyuAJy34RBuDEdTsVlMO9Fri/1JragePC2dg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
@ -1569,8 +1569,8 @@ packages:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
'@react-aria/collections@3.0.0-rc.6':
resolution: {integrity: sha512-N4AzRqzFJ4BztM1x56ot33smDUUsYQ6pzlbz6m4f8ARSqQYl0a2FsM13PYDtuNI5Dt9KtkL6rK/tLaZlTghLyg==}
'@react-aria/collections@3.0.0-rc.7':
resolution: {integrity: sha512-JMktVhe+OT6rZVcGdmSWgNj3VBq4Owm3L5LD8iMwJrV6SgPGmyzpguX7JTnz1hnSWO/wD2vrwMWEAlcuL7acBg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
@ -2735,8 +2735,8 @@ packages:
'@prisma/client': ^6.1.0
'@prisma/extension-read-replicas': ^0.4.1
'@umami/react-zen@0.181.0':
resolution: {integrity: sha512-Hs5dXPWVOtgHwAksolVTZw8n8EucHq+Xj+++a6RpfzHix3m2sWQXo1qNwd11GasxytqDf6JSxETj109LCUJiSA==}
'@umami/react-zen@0.183.0':
resolution: {integrity: sha512-snzfp87NElKbQn5lHUs3jTdCkXww4FHNJAGzyXVUcTv/5Bqv9mAmW+6htELychvQnO259t8GL/qJrcC5V/e4cg==}
'@umami/redis-client@0.29.0':
resolution: {integrity: sha512-Jaqh++jskqDB7ny75pfC02OvKp1JTS4asGDsFrRL3qy8sxL3PAl9+/mybCJe4/6vWrXDJKqpgkSfUDJq2bFjyw==}
@ -6302,14 +6302,14 @@ packages:
rc9@2.1.2:
resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==}
react-aria-components@1.12.1:
resolution: {integrity: sha512-UTn2y2Pr1QuapXLRoGE/GWHrjcZZSuMf+zhbJjInOHgS+MC4hqXiINufvjQrdjQDzS1llc2aepP9op6+z6QSxA==}
react-aria-components@1.12.2:
resolution: {integrity: sha512-BTA697VWy6Who9cpSbll447kqqpwxYvN6QF3/+AmXO+M+KgUXtPZAaNXu/9Sv2LdshU0zhIea4w27ZOt57UzPQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
react-aria@3.43.1:
resolution: {integrity: sha512-/PmZGiw+Ya/YtzXmiLW4ALD4SMuDnbwhMaVh33VCduTl8vVujIUzUTIi5g4C+YHLDs/Z4edsN3aQsPMqFfg1xA==}
react-aria@3.43.2:
resolution: {integrity: sha512-CfaXi3S69SeOkpp6pGc1w5FH8OvGPFphiMrO2tNSlqpYIecgk3gKoXjkqaAr6N+O1gasLMfAAF9sxtvS141qWg==}
peerDependencies:
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1
@ -6324,8 +6324,8 @@ packages:
peerDependencies:
react: '>=16.13.1'
react-hook-form@7.62.0:
resolution: {integrity: sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==}
react-hook-form@7.63.0:
resolution: {integrity: sha512-ZwueDMvUeucovM2VjkCf7zIHcs1aAlDimZu2Hvel5C5907gUzMpm4xCrQXtRzCvsBqFjonB4m3x4LzCFI1ZKWA==}
engines: {node: '>=18.0.0'}
peerDependencies:
react: ^16.8.0 || ^17 || ^18 || ^19
@ -8062,7 +8062,7 @@ snapshots:
'@fontsource/inter@5.2.6': {}
'@fontsource/jetbrains-mono@5.2.6': {}
'@fontsource/jetbrains-mono@5.2.8': {}
'@formatjs/cli@4.8.4(ts-jest@29.4.1(@babel/core@7.28.3)(@jest/transform@29.7.0)(@jest/types@30.0.5)(babel-jest@29.7.0(@babel/core@7.28.3))(esbuild@0.25.9)(jest-util@30.0.5)(jest@29.7.0(@types/node@24.3.0)(ts-node@10.9.2(@types/node@24.3.0)(typescript@5.9.2)))(typescript@5.9.2))':
dependencies:
@ -8650,7 +8650,7 @@ snapshots:
dependencies:
'@prisma/debug': 6.16.0
'@react-aria/autocomplete@3.0.0-rc.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
'@react-aria/autocomplete@3.0.0-rc.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
dependencies:
'@react-aria/combobox': 3.13.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-aria/focus': 3.21.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
@ -8723,7 +8723,7 @@ snapshots:
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
'@react-aria/collections@3.0.0-rc.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
'@react-aria/collections@3.0.0-rc.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
dependencies:
'@react-aria/interactions': 3.25.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-aria/ssr': 3.9.10(react@19.1.1)
@ -10323,9 +10323,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@umami/react-zen@0.181.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))':
'@umami/react-zen@0.183.0(@babel/core@7.28.3)(@types/react@19.1.12)(babel-plugin-react-compiler@19.1.0-rc.2)(immer@10.1.1)(use-sync-external-store@1.5.0(react@19.1.1))':
dependencies:
'@fontsource/jetbrains-mono': 5.2.6
'@fontsource/jetbrains-mono': 5.2.8
'@internationalized/date': 3.9.0
'@react-aria/focus': 3.21.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-spring/web': 9.7.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
@ -10335,9 +10335,9 @@ snapshots:
lucide-react: 0.511.0(react@19.1.1)
next: 15.5.3(@babel/core@7.28.3)(babel-plugin-react-compiler@19.1.0-rc.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
react: 19.1.1
react-aria-components: 1.12.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
react-aria-components: 1.12.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
react-dom: 19.1.1(react@19.1.1)
react-hook-form: 7.62.0(react@19.1.1)
react-hook-form: 7.63.0(react@19.1.1)
react-icons: 5.5.0(react@19.1.1)
thenby: 1.3.4
zustand: 5.0.8(@types/react@19.1.12)(immer@10.1.1)(react@19.1.1)(use-sync-external-store@1.5.0(react@19.1.1))
@ -14375,12 +14375,12 @@ snapshots:
defu: 6.1.4
destr: 2.0.5
react-aria-components@1.12.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
react-aria-components@1.12.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
dependencies:
'@internationalized/date': 3.9.0
'@internationalized/string': 3.2.7
'@react-aria/autocomplete': 3.0.0-rc.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-aria/collections': 3.0.0-rc.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-aria/autocomplete': 3.0.0-rc.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-aria/collections': 3.0.0-rc.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-aria/dnd': 3.11.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-aria/focus': 3.21.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-aria/interactions': 3.25.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
@ -14404,12 +14404,12 @@ snapshots:
'@swc/helpers': 0.5.17
client-only: 0.0.1
react: 19.1.1
react-aria: 3.43.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
react-aria: 3.43.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
react-dom: 19.1.1(react@19.1.1)
react-stately: 3.41.0(react@19.1.1)
use-sync-external-store: 1.5.0(react@19.1.1)
react-aria@3.43.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
react-aria@3.43.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
dependencies:
'@internationalized/string': 3.2.7
'@react-aria/breadcrumbs': 3.5.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
@ -14466,7 +14466,7 @@ snapshots:
'@babel/runtime': 7.28.3
react: 19.1.1
react-hook-form@7.62.0(react@19.1.1):
react-hook-form@7.63.0(react@19.1.1):
dependencies:
react: 19.1.1

View file

@ -8,7 +8,7 @@ import {
SidebarProps,
ThemeButton,
} from '@umami/react-zen';
import { Globe, Link as LinkIcon, Logo, Pixel, PanelLeft } from '@/components/icons';
import { Globe, LinkIcon, LogoSvg, Grid2x2, PanelLeft } from '@/components/icons';
import { useMessages, useNavigation, useGlobalState } from '@/components/hooks';
import { TeamsButton } from '@/components/input/TeamsButton';
import { PanelButton } from '@/components/input/PanelButton';
@ -39,7 +39,7 @@ export function SideNav(props: SidebarProps) {
id: 'pixels',
label: formatMessage(labels.pixels),
path: '/pixels',
icon: <Pixel />,
icon: <Grid2x2 />,
},
];
@ -53,7 +53,7 @@ export function SideNav(props: SidebarProps) {
<SidebarSection onClick={() => setIsCollapsed(false)}>
<SidebarHeader
label="umami"
icon={isCollapsed && !hasNav ? <PanelLeft /> : <Logo />}
icon={isCollapsed && !hasNav ? <PanelLeft /> : <LogoSvg />}
style={{ maxHeight: 40 }}
>
{!isCollapsed && !hasNav && <PanelButton />}

View file

@ -13,7 +13,7 @@ import {
} from '@umami/react-zen';
import { useConfig, useLinkQuery } from '@/components/hooks';
import { useMessages } from '@/components/hooks';
import { Refresh } from '@/components/icons';
import { RefreshCw } from '@/components/icons';
import { getRandomChars } from '@/lib/generate';
import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery';
import { LINKS_URL } from '@/lib/constants';
@ -127,7 +127,7 @@ export function LinkEditForm({
onPress={() => setValue('slug', handleSlug(), { shouldDirty: true })}
>
<Icon>
<Refresh />
<RefreshCw />
</Icon>
</Button>
</Row>

View file

@ -12,7 +12,7 @@ import {
} from '@umami/react-zen';
import { useConfig, usePixelQuery } from '@/components/hooks';
import { useMessages } from '@/components/hooks';
import { Refresh } from '@/components/icons';
import { RefreshCw } from '@/components/icons';
import { getRandomChars } from '@/lib/generate';
import { useUpdateQuery } from '@/components/hooks/queries/useUpdateQuery';
import { useEffect, useState } from 'react';
@ -111,7 +111,7 @@ export function PixelEditForm({
onPress={() => setValue('slug', handleSlug(), { shouldDirty: true })}
>
<Icon>
<Refresh />
<RefreshCw />
</Icon>
</Button>
</Row>

View file

@ -1,7 +1,7 @@
import { Grid, Row, Column, Text, Icon, ProgressBar, Dialog } from '@umami/react-zen';
import { ReportEditButton } from '@/components/input/ReportEditButton';
import { useMessages, useResultQuery } from '@/components/hooks';
import { File, Lightning, User } from '@/components/icons';
import { File, LightningSvg, User } from '@/components/icons';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { formatLongNumber } from '@/lib/format';
import { GoalEditForm } from './GoalEditForm';
@ -68,7 +68,7 @@ export function Goal({ id, name, type, parameters, websiteId, startDate, endDate
</Row>
<Row alignItems="center" justifyContent="space-between" gap>
<Row alignItems="center" gap>
<Icon>{parameters.type === 'path' ? <File /> : <Lightning />}</Icon>
<Icon>{parameters.type === 'path' ? <File /> : <LightningSvg />}</Icon>
<Text>{parameters.value}</Text>
</Row>
<Row alignItems="center" gap>

View file

@ -2,6 +2,27 @@ import { Grid, Column } from '@umami/react-zen';
import { useMessages, useNavigation } from '@/components/hooks';
import { MetricsExpandedTable } from '@/components/metrics/MetricsExpandedTable';
import { SideMenu } from '@/components/common/SideMenu';
import {
Link,
LogOut,
LogIn,
Search,
Type,
ArrowRight,
Megaphone,
Earth,
Globe,
Landmark,
MapPin,
AppWindow,
Laptop,
Languages,
Monitor,
Cpu,
LightningSvg,
LucideCaseSensitive,
Tag,
} from '@/components/icons';
export function WebsiteExpandedView({
websiteId,
@ -24,26 +45,31 @@ export function WebsiteExpandedView({
id: 'path',
label: formatMessage(labels.path),
path: updateParams({ view: 'path' }),
icon: <Link />,
},
{
id: 'entry',
label: formatMessage(labels.entry),
path: updateParams({ view: 'entry' }),
icon: <LogIn />,
},
{
id: 'exit',
label: formatMessage(labels.exit),
path: updateParams({ view: 'exit' }),
icon: <LogOut />,
},
{
id: 'title',
label: formatMessage(labels.title),
path: updateParams({ view: 'title' }),
icon: <Type />,
},
{
id: 'query',
label: formatMessage(labels.query),
path: updateParams({ view: 'query' }),
icon: <Search />,
},
],
},
@ -54,16 +80,19 @@ export function WebsiteExpandedView({
id: 'referrer',
label: formatMessage(labels.referrer),
path: updateParams({ view: 'referrer' }),
icon: <ArrowRight />,
},
{
id: 'channel',
label: formatMessage(labels.channel),
path: updateParams({ view: 'channel' }),
icon: <Megaphone />,
},
{
id: 'domain',
label: formatMessage(labels.domain),
path: updateParams({ view: 'domain' }),
icon: <Globe />,
},
],
},
@ -74,16 +103,19 @@ export function WebsiteExpandedView({
id: 'country',
label: formatMessage(labels.country),
path: updateParams({ view: 'country' }),
icon: <Earth />,
},
{
id: 'region',
label: formatMessage(labels.region),
path: updateParams({ view: 'region' }),
icon: <MapPin />,
},
{
id: 'city',
label: formatMessage(labels.city),
path: updateParams({ view: 'city' }),
icon: <Landmark />,
},
],
},
@ -94,26 +126,31 @@ export function WebsiteExpandedView({
id: 'browser',
label: formatMessage(labels.browser),
path: updateParams({ view: 'browser' }),
icon: <AppWindow />,
},
{
id: 'os',
label: formatMessage(labels.os),
path: updateParams({ view: 'os' }),
icon: <Cpu />,
},
{
id: 'device',
label: formatMessage(labels.device),
path: updateParams({ view: 'device' }),
icon: <Laptop />,
},
{
id: 'language',
label: formatMessage(labels.language),
path: updateParams({ view: 'language' }),
icon: <Languages />,
},
{
id: 'screen',
label: formatMessage(labels.screen),
path: updateParams({ view: 'screen' }),
icon: <Monitor />,
},
],
},
@ -124,16 +161,19 @@ export function WebsiteExpandedView({
id: 'event',
label: formatMessage(labels.event),
path: updateParams({ view: 'event' }),
icon: <LightningSvg />,
},
{
id: 'hostname',
label: formatMessage(labels.hostname),
path: updateParams({ view: 'hostname' }),
icon: <LucideCaseSensitive />,
},
{
id: 'tag',
label: formatMessage(labels.tag),
path: updateParams({ view: 'tag' }),
icon: <Tag />,
},
],
},
@ -142,7 +182,7 @@ export function WebsiteExpandedView({
return (
<Grid columns="auto 1fr" gap="6" height="100%" overflow="hidden">
<Column gap="6" border="right" paddingRight="3">
<SideMenu items={items} selectedKey={view} />
<SideMenu items={items} selectedKey={view} muteItems={false} />
</Column>
<Column overflow="hidden">
<MetricsExpandedTable

View file

@ -1,19 +1,19 @@
import {
Eye,
Lightning,
LightningSvg,
User,
Clock,
Sheet,
Target,
Funnel,
Path,
Magnet,
TargetSvg,
FunnelSvg,
PathSvg,
MagnetSvg,
Tag,
Money,
MoneySvg,
Network,
ChartPie,
UserPlus,
Compare,
CompareSvg,
} from '@/components/icons';
import { useMessages, useNavigation } from '@/components/hooks';
import { SideMenu } from '@/components/common/SideMenu';
@ -44,7 +44,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{
id: 'events',
label: formatMessage(labels.events),
icon: <Lightning />,
icon: <LightningSvg />,
path: renderPath('/events'),
},
{
@ -62,7 +62,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{
id: 'compare',
label: formatMessage(labels.compare),
icon: <Compare />,
icon: <CompareSvg />,
path: renderPath('/compare'),
},
{
@ -79,25 +79,25 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{
id: 'goals',
label: formatMessage(labels.goals),
icon: <Target />,
icon: <TargetSvg />,
path: renderPath('/goals'),
},
{
id: 'funnel',
label: formatMessage(labels.funnels),
icon: <Funnel />,
icon: <FunnelSvg />,
path: renderPath('/funnels'),
},
{
id: 'journeys',
label: formatMessage(labels.journeys),
icon: <Path />,
icon: <PathSvg />,
path: renderPath('/journeys'),
},
{
id: 'retention',
label: formatMessage(labels.retention),
icon: <Magnet />,
icon: <MagnetSvg />,
path: renderPath('/retention'),
},
],
@ -131,7 +131,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{
id: 'revenue',
label: formatMessage(labels.revenue),
icon: <Money />,
icon: <MoneySvg />,
path: renderPath('/revenue'),
},
{

View file

@ -2,7 +2,7 @@ import { ReactNode } from 'react';
import { Icon, TextField, Column, Row, Label, Text } from '@umami/react-zen';
import { useFormat, useLocale, useMessages, useRegionNames } from '@/components/hooks';
import { TypeIcon } from '@/components/common/TypeIcon';
import { Location, KeyRound, Calendar } from '@/components/icons';
import { LocationSvg, KeyRound, Calendar } from '@/components/icons';
import { DateDistance } from '@/components/common/DateDistance';
export function SessionInfo({ data }) {
@ -36,11 +36,11 @@ export function SessionInfo({ data }) {
{formatValue(data?.country, 'country')}
</Info>
<Info label={formatMessage(labels.region)} icon={<Location />}>
<Info label={formatMessage(labels.region)} icon={<LocationSvg />}>
{getRegionName(data?.region)}
</Info>
<Info label={formatMessage(labels.city)} icon={<Location />}>
<Info label={formatMessage(labels.city)} icon={<LocationSvg />}>
{data?.city}
</Info>

View file

@ -13,7 +13,7 @@ import { useRouter } from 'next/navigation';
import { useMessages, useUpdateQuery } from '@/components/hooks';
import { setUser } from '@/store/app';
import { setClientAuthToken } from '@/lib/client';
import { Logo } from '@/components/icons';
import { LogoSvg } from '@/components/icons';
export function LoginForm() {
const { formatMessage, labels, getErrorMessage } = useMessages();
@ -34,7 +34,7 @@ export function LoginForm() {
return (
<Column justifyContent="center" alignItems="center" gap="6">
<Icon size="lg">
<Logo />
<LogoSvg />
</Icon>
<Heading>umami</Heading>
<Form onSubmit={handleSubmit} error={getErrorMessage(error)}>

View file

@ -1,6 +1,6 @@
import { Icon, Text, Row } from '@umami/react-zen';
import { useMessages } from '@/components/hooks';
import { Alert } from '@/components/icons';
import { AlertTriangle } from '@/components/icons';
export function ErrorMessage() {
const { formatMessage, messages } = useMessages();
@ -8,7 +8,7 @@ export function ErrorMessage() {
return (
<Row alignItems="center" justifyContent="center" gap>
<Icon>
<Alert />
<AlertTriangle />
</Icon>
<Text>{formatMessage(messages.error)}</Text>
</Row>

View file

@ -1,7 +1,7 @@
import { useState } from 'react';
import { Grid, Column, TextField, Label, Select, Icon, Button, ListItem } from '@umami/react-zen';
import { useFilters, useFormat, useWebsiteValuesQuery } from '@/components/hooks';
import { Close } from '@/components/icons';
import { X } from '@/components/icons';
import { isSearchOperator } from '@/lib/params';
import { Empty } from '@/components/common/Empty';
@ -107,7 +107,7 @@ export function FilterRecord({
<Column justifyContent="flex-end">
<Button variant="quiet" onPress={() => onRemove?.(name)}>
<Icon>
<Close />
<X />
</Icon>
</Button>
</Column>

View file

@ -1,6 +1,6 @@
import { Button, Icon, Row, Text } from '@umami/react-zen';
import { useMessages } from '@/components/hooks';
import { Chevron } from '@/components/icons';
import { ChevronRight } from '@/components/icons';
export interface PagerProps {
page: string | number;
@ -45,12 +45,12 @@ export function Pager({ page, pageSize, count, onPageChange }: PagerProps) {
<Row gap="1">
<Button variant="outline" onPress={() => handlePageChange(-1)} isDisabled={firstPage}>
<Icon size="sm" rotate={180}>
<Chevron />
<ChevronRight />
</Icon>
</Button>
<Button variant="outline" onPress={() => handlePageChange(1)} isDisabled={lastPage}>
<Icon size="sm">
<Chevron />
<ChevronRight />
</Icon>
</Button>
</Row>

View file

@ -9,7 +9,7 @@ import {
Tooltip,
Heading,
} from '@umami/react-zen';
import { Maximize, Close } from '@/components/icons';
import { Maximize, X } from '@/components/icons';
import { useMessages } from '@/components/hooks';
export interface PanelProps extends ColumnProps {
@ -59,7 +59,7 @@ export function Panel({
<Row justifyContent="flex-end" alignItems="center">
<TooltipTrigger delay={0} isDisabled={isFullscreen}>
<Button variant="quiet" onPress={handleFullscreen}>
<Icon>{isFullscreen ? <Close /> : <Maximize />}</Icon>
<Icon>{isFullscreen ? <X /> : <Maximize />}</Icon>
</Button>
<Tooltip>{formatMessage(labels.maximize)}</Tooltip>
</TooltipTrigger>

View file

@ -1,71 +1,17 @@
export * from 'lucide-react';
export {
AlertTriangle as Alert,
ArrowRight as Arrow,
Bookmark,
Calendar,
ChartPie,
ChevronRight as Chevron,
Clock,
Copy,
Database,
Download,
Edit,
Ellipsis,
Equal,
Eye,
ExternalLink,
File,
FileJson,
FileText,
Globe,
Grid2X2 as Pixel,
KeyRound,
LayoutDashboard,
Link,
ListCheck,
ListFilter,
LockKeyhole,
LogOut,
Maximize,
Menu,
Minimize,
Moon,
MoreHorizontal as More,
Paperclip,
PanelLeft,
Plus,
RefreshCw as Refresh,
Settings,
Settings2 as Knobs,
Share,
Sheet,
Slash,
SquarePen,
SquarePlus,
Sun,
Trash,
Upload,
User,
CircleUserRound as UserCircle,
Users,
UserPlus,
X as Close,
} from 'lucide-react';
export {
Logo,
Bolt,
Change,
Compare,
Funnel,
Lightbulb,
Lightning,
Location,
Magnet,
Money,
Network,
Path,
Tag,
Target,
AddUser,
Visitor,
Logo as LogoSvg,
Bolt as BoltSvg,
Change as ChangeSvg,
Compare as CompareSvg,
Funnel as FunnelSvg,
Lightbulb as LightbulbSvg,
Lightning as LightningSvg,
Location as LocationSvg,
Magnet as MagnetSvg,
Money as MoneySvg,
Network as NetworkSvg,
Path as PathSvg,
Tag as TagSvg,
Target as TargetSvg,
} from '@/components/svg';

View file

@ -16,7 +16,7 @@ import {
useFilters,
useWebsiteSegmentQuery,
} from '@/components/hooks';
import { Close, Bookmark } from '@/components/icons';
import { X, Bookmark } from '@/components/icons';
import { isSearchOperator } from '@/lib/params';
import { SegmentEditForm } from '@/app/(main)/websites/[websiteId]/segments/SegmentEditForm';
@ -111,7 +111,7 @@ export function FilterBar({ websiteId }: { websiteId: string }) {
<TooltipTrigger delay={0}>
<Button variant="zero" onPress={handleResetFilter}>
<Icon>
<Close />
<X />
</Icon>
</Button>
<Tooltip>
@ -146,7 +146,7 @@ const FilterItem = ({ name, label, operator, value, onRemove }) => {
</Text>
</Row>
<Icon onClick={() => onRemove(name)} size="xs" style={{ cursor: 'pointer' }}>
<Close />
<X />
</Icon>
</Row>
</Row>

View file

@ -13,7 +13,7 @@ import {
Text,
Row,
} from '@umami/react-zen';
import { Edit, More, Trash } from '@/components/icons';
import { Edit, MoreHorizontal, Trash } from '@/components/icons';
export function ReportEditButton({
id,
@ -61,7 +61,7 @@ export function ReportEditButton({
<MenuTrigger>
<Button variant="quiet">
<Icon>
<More />
<MoreHorizontal />
</Icon>
</Button>
<Popover placement="bottom">
@ -90,9 +90,7 @@ export function ReportEditButton({
onCancel={handleClose}
isDanger
>
<Row gap="1">
{formatMessage(messages.confirmDelete, { target: <b key={name}>{name}</b> })}
</Row>
<Row gap="1">{formatMessage(messages.confirmDelete, { target: name })}</Row>
</AlertDialog>
)}
</Modal>

View file

@ -13,7 +13,7 @@ import {
Loading,
} from '@umami/react-zen';
import { useLoginQuery, useMessages, useUserTeamsQuery, useNavigation } from '@/components/hooks';
import { Chevron, User, Users } from '@/components/icons';
import { ChevronRight, User, Users } from '@/components/icons';
export interface TeamsButtonProps {
showText?: boolean;
@ -50,7 +50,7 @@ export function TeamsButton({ showText = true, onAction }: TeamsButtonProps) {
</Row>
{showText && (
<Icon rotate={90} size="sm">
<Chevron />
<ChevronRight />
</Icon>
)}
</Row>

View file

@ -1,6 +1,6 @@
import { Button, Icon, Row, Text, Select, ListItem } from '@umami/react-zen';
import { isAfter } from 'date-fns';
import { Chevron } from '@/components/icons';
import { ChevronRight } from '@/components/icons';
import { useDateRange, useMessages, useNavigation } from '@/components/hooks';
import { DateFilter } from './DateFilter';
@ -49,12 +49,12 @@ export function WebsiteDateFilter({
<Row gap="1">
<Button onPress={() => handleIncrement(-1)} variant="outline">
<Icon rotate={180}>
<Chevron />
<ChevronRight />
</Icon>
</Button>
<Button onPress={() => handleIncrement(1)} variant="outline" isDisabled={disableForward}>
<Icon>
<Chevron />
<ChevronRight />
</Icon>
</Button>
</Row>

View file

@ -1,6 +1,6 @@
import { Icon, Text, Row, RowProps } from '@umami/react-zen';
import { ReactNode } from 'react';
import { Arrow } from '@/components/icons';
import { ArrowRight } from '@/components/icons';
const STYLES = {
positive: {
@ -51,7 +51,7 @@ export function ChangeLabel({
>
{!neutral && (
<Icon rotate={positive ? -90 : 90} size={size}>
<Arrow />
<ArrowRight />
</Icon>
)}
<Text>{children || value}</Text>

View file

@ -2,7 +2,7 @@ import { ReactNode, useState } from 'react';
import { Button, Column, DataColumn, DataTable, Icon, Row, SearchField } from '@umami/react-zen';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useMessages, useWebsiteExpandedMetricsQuery } from '@/components/hooks';
import { Close } from '@/components/icons';
import { X } from '@/components/icons';
import { DownloadButton } from '@/components/input/DownloadButton';
import { formatShortTime } from '@/lib/format';
import { MetricLabel } from '@/components/metrics/MetricLabel';
@ -55,7 +55,7 @@ export function MetricsExpandedTable({
{onClose && (
<Button onPress={onClose} variant="quiet">
<Icon>
<Close />
<X />
</Icon>
</Button>
)}

View file

@ -14,6 +14,10 @@ export async function canViewWebsite({ user, shareToken }: Auth, websiteId: stri
const website = await getWebsite(websiteId);
if (!website) {
return false;
}
if (website.userId) {
return user.id === website.userId;
}
@ -46,6 +50,10 @@ export async function canUpdateWebsite({ user }: Auth, websiteId: string) {
const website = await getWebsite(websiteId);
if (!website) {
return false;
}
if (website.userId) {
return user.id === website.userId;
}
@ -66,6 +74,10 @@ export async function canDeleteWebsite({ user }: Auth, websiteId: string) {
const website = await getWebsite(websiteId);
if (!website) {
return false;
}
if (website.userId) {
return user.id === website.userId;
}
@ -82,6 +94,10 @@ export async function canDeleteWebsite({ user }: Auth, websiteId: string) {
export async function canTransferWebsiteToUser({ user }: Auth, websiteId: string, userId: string) {
const website = await getWebsite(websiteId);
if (!website) {
return false;
}
if (website.teamId && user.id === userId) {
const teamUser = await getTeamUser(website.teamId, userId);
@ -94,6 +110,10 @@ export async function canTransferWebsiteToUser({ user }: Auth, websiteId: string
export async function canTransferWebsiteToTeam({ user }: Auth, websiteId: string, teamId: string) {
const website = await getWebsite(websiteId);
if (!website) {
return false;
}
if (website.userId && website.userId === user.id) {
const teamUser = await getTeamUser(teamId, user.id);

View file

@ -11,17 +11,9 @@ import {
import { getItem } from '@/lib/storage';
import { getTimezone } from '@/lib/date';
function getDefaultTheme() {
return typeof window !== 'undefined'
? window?.matchMedia('(prefers-color-scheme: dark)')?.matches
? 'dark'
: 'light'
: 'light';
}
const initialState = {
locale: getItem(LOCALE_CONFIG) || process.env.defaultLocale || DEFAULT_LOCALE,
theme: getItem(THEME_CONFIG) || getDefaultTheme() || DEFAULT_THEME,
theme: getItem(THEME_CONFIG) || DEFAULT_THEME,
timezone: getItem(TIMEZONE_CONFIG) || getTimezone(),
dateRangeValue: getItem(DATE_RANGE_CONFIG) || DEFAULT_DATE_RANGE_VALUE,
shareToken: null,