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", "@react-spring/web": "^10.0.1",
"@svgr/cli": "^8.1.0", "@svgr/cli": "^8.1.0",
"@tanstack/react-query": "^5.85.5", "@tanstack/react-query": "^5.85.5",
"@umami/react-zen": "^0.181.0", "@umami/react-zen": "^0.183.0",
"@umami/redis-client": "^0.29.0", "@umami/redis-client": "^0.29.0",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
"chalk": "^5.6.0", "chalk": "^5.6.0",

58
pnpm-lock.yaml generated
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,19 +1,19 @@
import { import {
Eye, Eye,
Lightning, LightningSvg,
User, User,
Clock, Clock,
Sheet, Sheet,
Target, TargetSvg,
Funnel, FunnelSvg,
Path, PathSvg,
Magnet, MagnetSvg,
Tag, Tag,
Money, MoneySvg,
Network, Network,
ChartPie, ChartPie,
UserPlus, UserPlus,
Compare, CompareSvg,
} from '@/components/icons'; } from '@/components/icons';
import { useMessages, useNavigation } from '@/components/hooks'; import { useMessages, useNavigation } from '@/components/hooks';
import { SideMenu } from '@/components/common/SideMenu'; import { SideMenu } from '@/components/common/SideMenu';
@ -44,7 +44,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{ {
id: 'events', id: 'events',
label: formatMessage(labels.events), label: formatMessage(labels.events),
icon: <Lightning />, icon: <LightningSvg />,
path: renderPath('/events'), path: renderPath('/events'),
}, },
{ {
@ -62,7 +62,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{ {
id: 'compare', id: 'compare',
label: formatMessage(labels.compare), label: formatMessage(labels.compare),
icon: <Compare />, icon: <CompareSvg />,
path: renderPath('/compare'), path: renderPath('/compare'),
}, },
{ {
@ -79,25 +79,25 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{ {
id: 'goals', id: 'goals',
label: formatMessage(labels.goals), label: formatMessage(labels.goals),
icon: <Target />, icon: <TargetSvg />,
path: renderPath('/goals'), path: renderPath('/goals'),
}, },
{ {
id: 'funnel', id: 'funnel',
label: formatMessage(labels.funnels), label: formatMessage(labels.funnels),
icon: <Funnel />, icon: <FunnelSvg />,
path: renderPath('/funnels'), path: renderPath('/funnels'),
}, },
{ {
id: 'journeys', id: 'journeys',
label: formatMessage(labels.journeys), label: formatMessage(labels.journeys),
icon: <Path />, icon: <PathSvg />,
path: renderPath('/journeys'), path: renderPath('/journeys'),
}, },
{ {
id: 'retention', id: 'retention',
label: formatMessage(labels.retention), label: formatMessage(labels.retention),
icon: <Magnet />, icon: <MagnetSvg />,
path: renderPath('/retention'), path: renderPath('/retention'),
}, },
], ],
@ -131,7 +131,7 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{ {
id: 'revenue', id: 'revenue',
label: formatMessage(labels.revenue), label: formatMessage(labels.revenue),
icon: <Money />, icon: <MoneySvg />,
path: renderPath('/revenue'), 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 { Icon, TextField, Column, Row, Label, Text } from '@umami/react-zen';
import { useFormat, useLocale, useMessages, useRegionNames } from '@/components/hooks'; import { useFormat, useLocale, useMessages, useRegionNames } from '@/components/hooks';
import { TypeIcon } from '@/components/common/TypeIcon'; 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'; import { DateDistance } from '@/components/common/DateDistance';
export function SessionInfo({ data }) { export function SessionInfo({ data }) {
@ -36,11 +36,11 @@ export function SessionInfo({ data }) {
{formatValue(data?.country, 'country')} {formatValue(data?.country, 'country')}
</Info> </Info>
<Info label={formatMessage(labels.region)} icon={<Location />}> <Info label={formatMessage(labels.region)} icon={<LocationSvg />}>
{getRegionName(data?.region)} {getRegionName(data?.region)}
</Info> </Info>
<Info label={formatMessage(labels.city)} icon={<Location />}> <Info label={formatMessage(labels.city)} icon={<LocationSvg />}>
{data?.city} {data?.city}
</Info> </Info>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,71 +1,17 @@
export * from 'lucide-react';
export { export {
AlertTriangle as Alert, Logo as LogoSvg,
ArrowRight as Arrow, Bolt as BoltSvg,
Bookmark, Change as ChangeSvg,
Calendar, Compare as CompareSvg,
ChartPie, Funnel as FunnelSvg,
ChevronRight as Chevron, Lightbulb as LightbulbSvg,
Clock, Lightning as LightningSvg,
Copy, Location as LocationSvg,
Database, Magnet as MagnetSvg,
Download, Money as MoneySvg,
Edit, Network as NetworkSvg,
Ellipsis, Path as PathSvg,
Equal, Tag as TagSvg,
Eye, Target as TargetSvg,
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,
} from '@/components/svg'; } from '@/components/svg';

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
import { Icon, Text, Row, RowProps } from '@umami/react-zen'; import { Icon, Text, Row, RowProps } from '@umami/react-zen';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { Arrow } from '@/components/icons'; import { ArrowRight } from '@/components/icons';
const STYLES = { const STYLES = {
positive: { positive: {
@ -51,7 +51,7 @@ export function ChangeLabel({
> >
{!neutral && ( {!neutral && (
<Icon rotate={positive ? -90 : 90} size={size}> <Icon rotate={positive ? -90 : 90} size={size}>
<Arrow /> <ArrowRight />
</Icon> </Icon>
)} )}
<Text>{children || value}</Text> <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 { Button, Column, DataColumn, DataTable, Icon, Row, SearchField } from '@umami/react-zen';
import { LoadingPanel } from '@/components/common/LoadingPanel'; import { LoadingPanel } from '@/components/common/LoadingPanel';
import { useMessages, useWebsiteExpandedMetricsQuery } from '@/components/hooks'; import { useMessages, useWebsiteExpandedMetricsQuery } from '@/components/hooks';
import { Close } from '@/components/icons'; import { X } from '@/components/icons';
import { DownloadButton } from '@/components/input/DownloadButton'; import { DownloadButton } from '@/components/input/DownloadButton';
import { formatShortTime } from '@/lib/format'; import { formatShortTime } from '@/lib/format';
import { MetricLabel } from '@/components/metrics/MetricLabel'; import { MetricLabel } from '@/components/metrics/MetricLabel';
@ -55,7 +55,7 @@ export function MetricsExpandedTable({
{onClose && ( {onClose && (
<Button onPress={onClose} variant="quiet"> <Button onPress={onClose} variant="quiet">
<Icon> <Icon>
<Close /> <X />
</Icon> </Icon>
</Button> </Button>
)} )}

View file

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

View file

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