From 5e81329dd6997aab41439df5b9955d4a213131a4 Mon Sep 17 00:00:00 2001
From: Joe Karow <58997957+JoeKarow@users.noreply.github.com>
Date: Thu, 2 May 2024 17:37:16 -0400
Subject: [PATCH] refactor(IN-954): ActionButton component (#1205)
# Pull Request type
Please check the type of change your PR introduces:
- [ ] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, renaming)
- [x] Refactoring (no functional changes, no API changes)
- [ ] Build-related changes
- [ ] Documentation content changes
- [ ] Other (please describe):
## What is the current behavior?
- This one component tries to do EVERYTHING.
Issue Number: IN-954
## What is the new behavior?
- Separate out variants and use a compound component like `Badge`
## Does this introduce a breaking change?
- [ ] Yes
- [x] No
## Other information
---------
Signed-off-by: InReach [bot] <108850934+InReach-svc@users.noreply.github.com>
Signed-off-by: Joe Karow <58997957+JoeKarow@users.noreply.github.com>
Co-authored-by: InReach [bot] <108850934+InReach-svc@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
---
apps/app/sentry.client.config.ts | 4 +-
apps/app/sentry.edge.config.ts | 4 +-
apps/app/sentry.server.config.ts | 4 +-
.../pages/org/[slug]/[orgLocationId]/edit.tsx | 5 +-
.../org/[slug]/[orgLocationId]/index.tsx | 5 +-
apps/app/src/pages/org/[slug]/index.tsx | 3 +-
.../organization/query.forOrgPage.handler.ts | 8 +-
.../savedLists/mutation.deleteItem.handler.ts | 17 +-
.../savedLists/mutation.deleteItem.schema.ts | 21 +-
.../savedLists/mutation.saveItem.handler.ts | 17 +-
.../savedLists/mutation.saveItem.schema.ts | 21 +-
.../savedLists/query.isSaved.handler.ts | 2 +-
packages/ui/.storybook/main.ts | 16 +-
packages/ui/.storybook/preview.tsx | 11 +-
packages/ui/.storybook/viewports.ts | 12 +-
.../components/core/ActionButtons.stories.tsx | 114 ----
packages/ui/components/core/ActionButtons.tsx | 556 ------------------
.../components/core/ActionButtons/Group.tsx | 112 ++++
.../ui/components/core/ActionButtons/Menu.tsx | 110 ++++
.../components/core/ActionButtons/Print.tsx | 40 ++
.../components/core/ActionButtons/Review.tsx | 47 ++
.../ui/components/core/ActionButtons/Save.tsx | 241 ++++++++
.../components/core/ActionButtons/Share.tsx | 62 ++
.../core/ActionButtons/index.stories.tsx | 123 ++++
.../components/core/ActionButtons/index.tsx | 19 +
.../components/core/ActionButtons/styles.ts | 74 +++
packages/ui/components/core/Breadcrumb.tsx | 2 +-
packages/ui/components/core/Button.tsx | 12 +-
.../ui/components/core/SearchResultCard.tsx | 3 +-
packages/ui/components/core/Toolbar.tsx | 43 +-
packages/ui/components/core/index.tsx | 1 -
packages/ui/components/sections/Reviews.tsx | 2 +-
.../components/sections/SuggestOrg/context.ts | 10 +-
.../components/sections/SuggestOrg/index.tsx | 217 ++++---
.../components/sections/SuggestOrg/modals.tsx | 208 ++++---
packages/ui/icon/iconList.ts | 2 +-
packages/ui/icon/index.tsx | 16 +-
packages/ui/mockData/fieldOpt.ts | 127 +++-
packages/ui/mockData/orgPhone.ts | 5 -
packages/ui/modals/ModalTitle.tsx | 22 +-
packages/ui/modals/QuickPromotion.tsx | 17 +-
packages/ui/modals/Review.tsx | 7 +-
packages/ui/theme/common.tsx | 4 +-
43 files changed, 1331 insertions(+), 1015 deletions(-)
delete mode 100644 packages/ui/components/core/ActionButtons.stories.tsx
delete mode 100644 packages/ui/components/core/ActionButtons.tsx
create mode 100644 packages/ui/components/core/ActionButtons/Group.tsx
create mode 100644 packages/ui/components/core/ActionButtons/Menu.tsx
create mode 100644 packages/ui/components/core/ActionButtons/Print.tsx
create mode 100644 packages/ui/components/core/ActionButtons/Review.tsx
create mode 100644 packages/ui/components/core/ActionButtons/Save.tsx
create mode 100644 packages/ui/components/core/ActionButtons/Share.tsx
create mode 100644 packages/ui/components/core/ActionButtons/index.stories.tsx
create mode 100644 packages/ui/components/core/ActionButtons/index.tsx
create mode 100644 packages/ui/components/core/ActionButtons/styles.ts
diff --git a/apps/app/sentry.client.config.ts b/apps/app/sentry.client.config.ts
index 8e7ec58459..c8b81fe5ea 100644
--- a/apps/app/sentry.client.config.ts
+++ b/apps/app/sentry.client.config.ts
@@ -10,10 +10,10 @@ import {
} from '@sentry/integrations'
import * as Sentry from '@sentry/nextjs'
-const isVercelProd = process.env.VERCEL_ENV === 'production'
+const isVercel = process.env.VERCEL === '1'
Sentry.init({
dsn: 'https://3398c2248c86498ab42fa8533e4f83f1@o1412293.ingest.us.sentry.io/6751163',
- enabled: isVercelProd,
+ enabled: isVercel,
// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: !!process.env.SENTRY_DEBUG,
diff --git a/apps/app/sentry.edge.config.ts b/apps/app/sentry.edge.config.ts
index 5b84d4c7dc..321cb680ee 100644
--- a/apps/app/sentry.edge.config.ts
+++ b/apps/app/sentry.edge.config.ts
@@ -6,11 +6,11 @@
import * as Sentry from '@sentry/nextjs'
-const isVercelProd = process.env.VERCEL_ENV === 'production'
+const isVercel = process.env.VERCEL === '1'
Sentry.init({
dsn: 'https://3398c2248c86498ab42fa8533e4f83f1@o1412293.ingest.us.sentry.io/6751163',
- enabled: isVercelProd,
+ enabled: isVercel,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 0.5,
diff --git a/apps/app/sentry.server.config.ts b/apps/app/sentry.server.config.ts
index bd8009335f..7799cbe9c2 100644
--- a/apps/app/sentry.server.config.ts
+++ b/apps/app/sentry.server.config.ts
@@ -8,11 +8,11 @@ import { nodeProfilingIntegration } from '@sentry/profiling-node'
import { prisma } from '@weareinreach/db'
-const isVercelProd = process.env.VERCEL_ENV === 'production'
+const isVercel = process.env.VERCEL === '1'
Sentry.init({
dsn: 'https://3398c2248c86498ab42fa8533e4f83f1@o1412293.ingest.us.sentry.io/6751163',
- enabled: isVercelProd,
+ enabled: isVercel,
debug: !!process.env.SENTRY_DEBUG,
// Tracing rates
tracesSampleRate: 0.5,
diff --git a/apps/app/src/pages/org/[slug]/[orgLocationId]/edit.tsx b/apps/app/src/pages/org/[slug]/[orgLocationId]/edit.tsx
index 5f2c82f6cc..f55bd72fa8 100644
--- a/apps/app/src/pages/org/[slug]/[orgLocationId]/edit.tsx
+++ b/apps/app/src/pages/org/[slug]/[orgLocationId]/edit.tsx
@@ -53,9 +53,7 @@ const OrgLocationPage: NextPage
{hasAlerts &&
diff --git a/apps/app/src/pages/org/[slug]/[orgLocationId]/index.tsx b/apps/app/src/pages/org/[slug]/[orgLocationId]/index.tsx
index 5da0064e75..81b928c280 100644
--- a/apps/app/src/pages/org/[slug]/[orgLocationId]/index.tsx
+++ b/apps/app/src/pages/org/[slug]/[orgLocationId]/index.tsx
@@ -48,9 +48,7 @@ const OrgLocationPage: NextPage = () => {
{ id: orgLocationId },
{ enabled: router.isReady }
)
- const { data: isSaved } = api.savedList.isSaved.useQuery(orgData?.id as string, {
- enabled: orgDataStatus === 'success' && Boolean(orgData?.id),
- })
+
const { data: alertData } = api.location.getAlerts.useQuery(
{ id: orgLocationId },
{ enabled: router.isReady }
@@ -110,7 +108,6 @@ const OrgLocationPage: NextPage = () => {
},
}}
organizationId={orgData.id}
- saved={Boolean(isSaved)}
/>
{hasAlerts &&
diff --git a/apps/app/src/pages/org/[slug]/index.tsx b/apps/app/src/pages/org/[slug]/index.tsx
index 24a1a58ea7..9b35231716 100644
--- a/apps/app/src/pages/org/[slug]/index.tsx
+++ b/apps/app/src/pages/org/[slug]/index.tsx
@@ -135,7 +135,7 @@ const OrganizationPage = ({
return
}
- const { userLists, attributes, description, reviews, locations, isClaimed, id: organizationId } = data
+ const { attributes, description, reviews, locations, isClaimed, id: organizationId } = data
const body =
locations?.length <= 1 ? (
@@ -185,7 +185,6 @@ const OrganizationPage = ({
option: 'back',
backTo: 'search',
}}
- saved={Boolean(userLists?.length)}
organizationId={organizationId}
/>
diff --git a/packages/api/router/organization/query.forOrgPage.handler.ts b/packages/api/router/organization/query.forOrgPage.handler.ts
index 3f9b0c470f..91aacfbfad 100644
--- a/packages/api/router/organization/query.forOrgPage.handler.ts
+++ b/packages/api/router/organization/query.forOrgPage.handler.ts
@@ -4,7 +4,7 @@ import { type TRPCHandlerParams } from '~api/types/handler'
import { type TForOrgPageSchema } from './query.forOrgPage.schema'
-const forOrgPage = async ({ ctx, input }: TRPCHandlerParams) => {
+const forOrgPage = async ({ input }: TRPCHandlerParams) => {
const { slug } = input
const org = await prisma.organization.findUniqueOrThrow({
where: {
@@ -19,12 +19,6 @@ const forOrgPage = async ({ ctx, input }: TRPCHandlerParams)
lastVerified: true,
allowedEditors: { where: { authorized: true }, select: { userId: true } },
description: freeText,
- userLists: ctx.session?.user.id
- ? {
- where: { list: { ownedById: ctx.session.user.id } },
- select: { list: { select: { id: true, name: true } } },
- }
- : undefined,
reviews: {
where: { visible: true, deleted: false },
diff --git a/packages/api/router/savedLists/mutation.deleteItem.handler.ts b/packages/api/router/savedLists/mutation.deleteItem.handler.ts
index c608e3345d..c72a127305 100644
--- a/packages/api/router/savedLists/mutation.deleteItem.handler.ts
+++ b/packages/api/router/savedLists/mutation.deleteItem.handler.ts
@@ -1,4 +1,4 @@
-import { getAuditedClient } from '@weareinreach/db'
+import { getAuditedClient, isIdFor } from '@weareinreach/db'
import { checkListOwnership } from '~api/lib/checkListOwnership'
import { type TRPCHandlerParams } from '~api/types/handler'
@@ -6,7 +6,7 @@ import { type TDeleteItemSchema } from './mutation.deleteItem.schema'
const deleteItem = async ({ ctx, input }: TRPCHandlerParams) => {
const prisma = getAuditedClient(ctx.actorId)
- const { id, organizationId, serviceId } = input
+ const { id, itemId } = input
checkListOwnership({ listId: id, userId: ctx.session.user.id })
const result = await prisma.userSavedList.update({
@@ -16,30 +16,27 @@ const deleteItem = async ({ ctx, input }: TRPCHandlerParams Boolean(organizationId ?? serviceId ?? itemId), {
+ message: 'Must provide either organizationId, serviceId, or itemId',
+ })
+ .transform(({ id, organizationId, serviceId, itemId }) => {
+ if (itemId !== undefined) {
+ return { id, itemId }
+ }
+ return { id, itemId: (organizationId ?? serviceId) as string }
+ })
export type TDeleteItemSchema = z.infer
diff --git a/packages/api/router/savedLists/mutation.saveItem.handler.ts b/packages/api/router/savedLists/mutation.saveItem.handler.ts
index e90d98f9f7..036e17961d 100644
--- a/packages/api/router/savedLists/mutation.saveItem.handler.ts
+++ b/packages/api/router/savedLists/mutation.saveItem.handler.ts
@@ -1,4 +1,4 @@
-import { getAuditedClient } from '@weareinreach/db'
+import { getAuditedClient, isIdFor } from '@weareinreach/db'
import { checkListOwnership } from '~api/lib/checkListOwnership'
import { type TRPCHandlerParams } from '~api/types/handler'
@@ -6,7 +6,7 @@ import { type TSaveItemSchema } from './mutation.saveItem.schema'
const saveItem = async ({ ctx, input }: TRPCHandlerParams) => {
const prisma = getAuditedClient(ctx.actorId)
- const { id, organizationId, serviceId } = input
+ const { id, itemId } = input
checkListOwnership({ listId: id, userId: ctx.session.user.id })
@@ -16,24 +16,21 @@ const saveItem = async ({ ctx, input }: TRPCHandlerParams Boolean(organizationId ?? serviceId ?? itemId), {
+ message: 'Must provide either organizationId, serviceId, or itemId',
+ })
+ .transform(({ id, organizationId, serviceId, itemId }) => {
+ if (itemId !== undefined) {
+ return { id, itemId }
+ }
+ return { id, itemId: (organizationId ?? serviceId) as string }
+ })
export type TSaveItemSchema = z.infer
diff --git a/packages/api/router/savedLists/query.isSaved.handler.ts b/packages/api/router/savedLists/query.isSaved.handler.ts
index c67a18c462..f38ba44d9a 100644
--- a/packages/api/router/savedLists/query.isSaved.handler.ts
+++ b/packages/api/router/savedLists/query.isSaved.handler.ts
@@ -26,7 +26,7 @@ const isSaved = async ({ ctx, input }: TRPCHandlerParams) => {
},
})
if (!result.length) {
- return false
+ return null
}
return result
}
diff --git a/packages/ui/.storybook/main.ts b/packages/ui/.storybook/main.ts
index d8fb696a3d..b920212ec2 100644
--- a/packages/ui/.storybook/main.ts
+++ b/packages/ui/.storybook/main.ts
@@ -20,7 +20,7 @@ const getAbsolutePath = (value: string) => {
const publicStatic = path.resolve(__dirname, '../../../apps/app/public')
-const config: StorybookConfig = {
+const storybookConfig: StorybookConfig = {
stories: [
'../components/**/*.stories.{ts,tsx}',
'../hooks/**/*.stories.{ts,tsx}',
@@ -41,12 +41,12 @@ const config: StorybookConfig = {
getAbsolutePath('@storybook/addon-essentials'),
getAbsolutePath('@geometricpanda/storybook-addon-badges'),
getAbsolutePath('@storybook/addon-a11y'),
- // eslint-disable-next-line storybook/no-uninstalled-addons
- '@tomfreudenberg/next-auth-mock/storybook', // This addon doesn't like to be wrapped.
getAbsolutePath('@storybook/addon-designs'),
getAbsolutePath('storybook-addon-pseudo-states'),
getAbsolutePath('@storybook/addon-interactions'),
'@storybook/addon-webpack5-compiler-swc',
+ // eslint-disable-next-line storybook/no-uninstalled-addons
+ '@tomfreudenberg/next-auth-mock/storybook', // This addon doesn't like to be wrapped.
],
framework: {
name: '@storybook/nextjs',
@@ -105,7 +105,7 @@ const config: StorybookConfig = {
stats: {
colors: true,
},
- devtool: options.configType === 'DEVELOPMENT' ? 'eval-source-map' : undefined,
+ // devtool: options.configType === 'DEVELOPMENT' ? 'eval-source-map' : undefined,
}
/** I18 HMR */
@@ -113,7 +113,11 @@ const config: StorybookConfig = {
const plugin = new I18NextHMRPlugin({
localesDir: path.resolve(__dirname, '../../../apps/app/public/locales'),
})
- Array.isArray(config.plugins) ? config.plugins.push(plugin) : (config.plugins = [plugin])
+ if (Array.isArray(config.plugins)) {
+ config.plugins.push(plugin)
+ } else {
+ config.plugins = [plugin]
+ }
}
const mergedConfig = mergeAndConcat(config, configAdditions)
@@ -131,4 +135,4 @@ const config: StorybookConfig = {
STORYBOOK_PROJECT_ROOT: path.resolve(__dirname, '../'),
},
}
-export default config
+export default storybookConfig
diff --git a/packages/ui/.storybook/preview.tsx b/packages/ui/.storybook/preview.tsx
index 2532169539..023da8cce4 100644
--- a/packages/ui/.storybook/preview.tsx
+++ b/packages/ui/.storybook/preview.tsx
@@ -1,6 +1,7 @@
import './wdyr'
import './font.css'
import { type BADGE } from '@geometricpanda/storybook-addon-badges'
+import { type ViewportAddonParameter } from '@storybook/addon-viewport'
import { type Preview } from '@storybook/react'
import { type WhyDidYouRenderOptions } from '@welldone-software/why-did-you-render'
import { http, passthrough, type RequestHandler } from 'msw'
@@ -24,7 +25,7 @@ import {
WithWhyDidYouRender,
} from './decorators'
import { i18n } from './i18next'
-import { viewport, type ViewportConfig } from './viewports'
+import { viewport } from './viewports'
import type authStates from './mockAuthStates'
@@ -35,7 +36,7 @@ initializeMsw({
},
},
onUnhandledRequest: ({ method, url }) => {
- if (url.startsWith('/trpc' || '/api')) {
+ if (url.startsWith('/trpc') || url.startsWith('/api')) {
console.error(`Unhandled ${method} request to ${url}.
This exception has been only logged in the console, however, it's strongly recommended to resolve this error as you don't want unmocked data in Storybook stories.
@@ -64,8 +65,6 @@ const preview: Preview = {
excludeDecorators: true,
},
},
- i18n,
- viewport,
chromatic: {
delay: 1000,
},
@@ -80,6 +79,8 @@ const preview: Preview = {
}),
},
},
+ i18n,
+ viewport,
},
globalTypes: {
...i18NextGlobalTypes,
@@ -110,7 +111,7 @@ declare module '@storybook/react' {
}
locale?: LocaleCodes
i18n?: typeof i18n
- viewport?: ViewportConfig
+ viewport?: ViewportAddonParameter
design?: DesignParams | DesignParams[]
msw?: RequestHandler[] | { handlers: RequestHandler[] | Record }
nextAuthMock?: { session: keyof typeof authStates }
diff --git a/packages/ui/.storybook/viewports.ts b/packages/ui/.storybook/viewports.ts
index b9f8ef3f04..791d750514 100644
--- a/packages/ui/.storybook/viewports.ts
+++ b/packages/ui/.storybook/viewports.ts
@@ -1,14 +1,6 @@
-import { type INITIAL_VIEWPORTS } from '@storybook/addon-viewport'
+import { type ViewportAddonParameter } from '@storybook/addon-viewport'
-import { type Viewports } from './types'
-
-type ViewportMap = typeof INITIAL_VIEWPORTS
-export interface ViewportConfig {
- viewports?: ViewportMap
- defaultViewport?: Viewports
-}
-
-export const viewport: ViewportConfig = {
+export const viewport: ViewportAddonParameter = {
viewports: {
iphonex: {
name: 'iPhone X',
diff --git a/packages/ui/components/core/ActionButtons.stories.tsx b/packages/ui/components/core/ActionButtons.stories.tsx
deleted file mode 100644
index 29d62dd9bf..0000000000
--- a/packages/ui/components/core/ActionButtons.stories.tsx
+++ /dev/null
@@ -1,114 +0,0 @@
-import { type Meta, type StoryObj } from '@storybook/react'
-
-import { getTRPCMock } from '~ui/lib/getTrpcMock'
-import { organization } from '~ui/mockData/organization'
-import { review } from '~ui/mockData/review'
-import { savedList } from '~ui/mockData/savedList'
-
-import { ActionButtons as ActionButtonsComponent } from './ActionButtons'
-
-export default {
- title: 'Design System/Action Buttons',
- component: ActionButtonsComponent,
- parameters: {
- design: {
- type: 'figma',
- url: 'https://www.figma.com/file/gl8ppgnhpSq1Dr7Daohk55/Design-System-(2023)?node-id=52%3A1420&t=sleVeGl2lJv7Df18-4',
- },
- layout: 'fullscreen',
- layoutWrapper: 'centeredHalf',
- msw: [
- organization.getIdFromSlug,
- review.create,
- savedList.getAll,
- savedList.saveItem,
- savedList.createAndSaveItem,
- ],
- nextjs: {
- router: {
- pathname: '/org/[slug]',
- asPath: '/org/mockOrg',
- query: {
- slug: 'mockOrg',
- },
- },
- },
- },
-} satisfies Meta
-
-type StoryDef = StoryObj
-
-export const Save = {
- parameters: {
- nextAuthMock: {
- session: 'userPic',
- },
- },
- args: {
- iconKey: 'save',
- },
-}
-
-export const SaveLoggedOut = {
- parameters: {
- nextAuthMock: {
- session: 'noAuth',
- },
- },
- args: {
- iconKey: 'save',
- },
-} satisfies StoryDef
-
-export const SavedToSingleList = {
- args: {
- iconKey: 'save',
- },
- parameters: {
- nextAuthMock: {
- session: 'userPic',
- },
- msw: [savedList.isSavedSingle, savedList.deleteItem, organization.getIdFromSlug],
- },
-} satisfies StoryDef
-export const SavedToMultipleLists = {
- args: {
- iconKey: 'save',
- },
- parameters: {
- nextAuthMock: {
- session: 'userPic',
- },
- msw: [savedList.isSavedMultiple, savedList.getAll, savedList.deleteItem, organization.getIdFromSlug],
- },
-} satisfies StoryDef
-export const Share = {
- args: {
- iconKey: 'share',
- },
-} satisfies StoryDef
-export const Print = {
- args: {
- iconKey: 'print',
- },
-} satisfies StoryDef
-export const Delete = {
- args: {
- iconKey: 'delete',
- },
-} satisfies StoryDef
-export const Review = {
- args: {
- iconKey: 'review',
- },
-} satisfies StoryDef
-export const More = {
- parameters: {
- nextAuthMock: {
- session: 'userPic',
- },
- },
- args: {
- iconKey: 'more',
- },
-} satisfies StoryDef
diff --git a/packages/ui/components/core/ActionButtons.tsx b/packages/ui/components/core/ActionButtons.tsx
deleted file mode 100644
index 5374a76d38..0000000000
--- a/packages/ui/components/core/ActionButtons.tsx
+++ /dev/null
@@ -1,556 +0,0 @@
-import {
- Box,
- Button,
- type ButtonProps,
- Center,
- createPolymorphicComponent,
- createStyles,
- Group,
- Loader,
- Menu,
- rem,
- Skeleton,
- Text,
- useMantineTheme,
-} from '@mantine/core'
-import { useClipboard } from '@mantine/hooks'
-import { useRouter } from 'next/router'
-import { useSession } from 'next-auth/react'
-import { useTranslation } from 'next-i18next'
-import { type ComponentType, forwardRef, type JSX, useState } from 'react'
-
-import { type ApiInput } from '@weareinreach/api'
-import { useNewNotification, useScreenSize } from '~ui/hooks'
-import { Icon } from '~ui/icon'
-import { trpc as api } from '~ui/lib/trpcClient'
-import { CreateNewList } from '~ui/modals/CreateNewList'
-import { QuickPromotionModal } from '~ui/modals/QuickPromotion'
-import { ReviewModal } from '~ui/modals/Review'
-
-const useStyles = createStyles((theme) => ({
- button: {
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- minWidth: rem(48),
- height: rem(48),
- padding: rem(12),
- gap: rem(8),
- backgroundColor: theme.other.colors.secondary.white,
- border: 0,
- borderRadius: rem(8),
- '&:not([data-disabled])': theme.fn.hover({
- backgroundColor: theme.other.colors.primary.lightGray,
- }),
- },
- buttonPressed: {
- display: 'flex',
- flexDirection: 'row',
- alignItems: 'center',
- minWidth: rem(48),
- height: rem(48),
- padding: rem(12),
- gap: rem(8),
- backgroundColor: theme.other.colors.primary.lightGray,
- '&:not([data-disabled])': theme.fn.hover({
- backgroundColor: theme.other.colors.primary.lightGray,
- }),
- },
- icon: {},
- text: {
- fontWeight: theme.other.fontWeight.semibold,
- marginLeft: rem(8),
- },
- dropdown: {
- background: theme.other.colors.secondary.black,
- borderRadius: theme.radius.md,
- paddingTop: rem(2),
- paddingBottom: rem(2),
- },
- item: {
- '& > *': {
- color: 'white !important',
- },
- color: 'white',
- fontWeight: theme.other.fontWeight.semibold,
- fontSize: theme.fontSizes.md,
- '&[data-hovered]': {
- backgroundColor: 'inherit',
- // color: 'black',
- textDecoration: 'underline',
- },
- },
-}))
-
-export const actionButtonIcons = {
- save: {
- icon: 'carbon:favorite',
- labelKey: 'words.save',
- },
- share: { icon: 'carbon:share', labelKey: 'words.share' },
- print: { icon: 'carbon:printer', labelKey: 'words.print' },
- review: { icon: 'carbon:star', labelKey: 'words.review' },
- delete: { icon: 'carbon:delete', labelKey: 'words.delete' },
- more: {
- icon: 'carbon:overflow-menu-horizontal',
- useMenu: true,
- },
-} as const
-
-/**
- * Returns a Menu Item with the new of an existing list. When clicked it saves the current organization or
- * service to the list.
- *
- * @param data - Contains information about the list
- * @param data.id - List id : string
- * @param data.organizationId - String | undefined
- * @param data.serviceId - String | undefined
- * @param name - List name : string
- * @returns JSX.Element
- */
-const ListItem = ({ data, name, action }: ListMenuProps) => {
- const { t } = useTranslation()
- const utils = api.useUtils()
-
- const savedInList = useNewNotification({
- icon: 'heartFilled',
- displayText: t('list.added', { name }),
- })
- const errorSaving = useNewNotification({
- icon: 'warning',
- displayText: t('list.error-add'),
- })
- const deletedInList = useNewNotification({
- icon: 'heartEmpty',
- displayText: t('list.removedMulti', { name }),
- })
- const errorRemoving = useNewNotification({
- icon: 'warning',
- displayText: t('list.error-remove'),
- })
-
- const saveItem = api.savedList.saveItem.useMutation({
- onSuccess: (_, { organizationId, serviceId }) => {
- savedInList()
- utils.savedList.isSaved.invalidate(serviceId ?? organizationId)
- },
- onError: errorSaving,
- })
- const removeItem = api.savedList.deleteItem.useMutation({
- onSuccess: (_, { organizationId, serviceId }) => {
- deletedInList()
- utils.savedList.isSaved.invalidate(serviceId ?? organizationId)
- },
- onError: errorRemoving,
- })
- const clickHandler = () => {
- if (action === 'save') {
- saveItem.mutate(data)
- } else {
- removeItem.mutate(data)
- }
- }
-
- return clickHandler()}>{name}
-}
-
-export const SaveToggleButton = forwardRef(
- ({ omitLabel, serviceId, organizationId, isMenu, ...rest }, ref) => {
- const [isSaved, setIsSaved] = useState(false)
- const [opened, setOpened] = useState(false)
- const [singleListId, setSingleListId] = useState()
- const [singleListName, setSingleListName] = useState()
- const [menuChildren, setMenuChildren] = useState(
-
-
-
-
-
- )
- const { classes } = useStyles()
- const { status: sessionStatus } = useSession()
- const { t } = useTranslation('common')
- const theme = useMantineTheme()
- const utils = api.useUtils()
- const buttonIcon = isSaved ? 'carbon:favorite-filled' : 'carbon:favorite'
-
- api.savedList.isSaved.useQuery(serviceId ?? (organizationId as string), {
- enabled: sessionStatus === 'authenticated' && Boolean(organizationId || serviceId),
- refetchOnWindowFocus: false,
- onSuccess: (data) => {
- setIsSaved(Boolean(data))
- if (!data) return
- if (data.length === 1) {
- const record = data[0]
- setMenuChildren(null)
- if (!record) return
- setSingleListId(record.id)
- setSingleListName(record.name)
- return
- }
- setMenuChildren(
- data.map(({ id, name }) => (
-
- ))
- )
- },
- })
- const savedLists = api.savedList.getAll.useQuery(undefined, {
- refetchOnWindowFocus: false,
- enabled: sessionStatus === 'authenticated',
- onError: () => {
- if (isSaved) return
- setMenuChildren(
- savedLists.refetch()} closeMenuOnClick={false}>
- {t('retry')}
-
- )
- },
- onSuccess: (data) => {
- if (isSaved) return
- setMenuChildren(
- data ? (
- [
-
- {t('list.create-new')}
- ,
- ...data.map(({ id, name }) => (
-
- )),
- ]
- ) : (
-
- {t('list.create-new')}
-
- )
- )
- },
- })
- const deletedInList = useNewNotification({
- icon: 'heartEmpty',
- displayText: t('list.removedMulti', { name: singleListName }),
- })
- const errorRemoving = useNewNotification({
- icon: 'warning',
- displayText: t('list.error-remove'),
- })
- const removeItem = api.savedList.deleteItem.useMutation({
- onSuccess: () => {
- deletedInList()
- utils.savedList.isSaved.invalidate(serviceId ?? organizationId)
- setIsSaved(false)
- utils.savedList.getAll.invalidate()
- },
- onError: errorRemoving,
- })
-
- let ButtonInner = (
- <>
-
- {!omitLabel && (
-
- {t(isSaved ? 'words.saved' : 'words.save')}
-
- )}
- >
- )
-
- if (isMenu) ButtonInner = {ButtonInner}
-
- // BUG: [IN-808] "Save" not receving correct styles when it's in the overflow menu.
- if (sessionStatus !== 'authenticated') {
- if (isMenu)
- return (
-
- {ButtonInner}
-
- )
- return (
-
- {ButtonInner}
-
- )
- }
-
- if (isSaved && singleListId) {
- return (
-
-
-
- )
- }
- return (
-
- )
- }
-)
-SaveToggleButton.displayName = 'SaveToggleButton'
-
-const SaveButton = createPolymorphicComponent<'button', SaveToggleButtonProps>(SaveToggleButton)
-
-/**
- * Polymorphic component, returns a button. When clicked saves the current url to the clients clipboard
- *
- * @returns Polymorphic button component
- */
-const CopyToClipBoard = forwardRef((props, ref) => {
- const { t } = useTranslation()
- const { asPath } = useRouter()
- const clipboard = useClipboard({ timeout: 500 })
- const copiedToClipboard = useNewNotification({ icon: 'info', displayText: t('link-copied') })
- /** Strip out unused props to prevent react errors */
- const { organizationId: _org, serviceId: _serv, isMenu: _isMenu, ...restProps } = props
-
- const handleCopy = () => {
- const href = `${window.location.origin}${asPath}`
- clipboard.copy(href)
- copiedToClipboard()
- }
-
- return
-})
-
-CopyToClipBoard.displayName = 'CopyToClipboard'
-
-const ShareLink = createPolymorphicComponent<'button', PolyButtonProps>(CopyToClipBoard)
-
-/**
- * Polymorphic element, returns a button. When clicked takes a screenshot of the current client view
- *
- * @returns Polymorphic button component
- */
-const PrintBody = forwardRef((props, ref) => {
- /** Strip out unused props to prevent react errors */
- const { organizationId: _org, serviceId: _serv, isMenu: _isMenu, ...restProps } = props
- return window.print()} {...restProps} />
-})
-
-PrintBody.displayName = 'Print'
-
-const PrintButton = createPolymorphicComponent<'button', PolyButtonProps>(PrintBody)
-
-// TODO: [IN-786] Associate ActionButton click actions
-
-// Previous actions object is now a hook to check user session before using save or saved actions
-const useActions = () => {
- const { classes } = useStyles()
- const { status: sessionStatus } = useSession()
- /**
- * Curried function which accepts a Polymorphic button element as its base param. The inner function returns
- * a JSX component.
- *
- * @param Component - Accepts the return value of the createPolymorphicComponent function
- * @param isMenu - Boolean. If true, the component prop for the Polymorphic element will be Menu.Item, else
- * it will be Button
- * @param children - JSX.Element
- * @param props - ButtonProps. Its main use is to handle component styling
- * @returns A function which returns a JSX.Element
- */
- const generic = (Component: Polymorphic | ComponentType) => {
- const action = ({ isMenu, children, props }: Generic) => {
- if (isMenu)
- return (
-
- {children}
-
- )
-
- return (
-
- {children}
-
- )
- }
- return action
- }
-
- return {
- // TODO: assign behaviour to delete button
- delete: generic(QuickPromotionModal),
- more: generic(createPolymorphicComponent<'button', PolyButtonProps>(Button)),
- print: generic(PrintButton),
- review: generic(sessionStatus === 'authenticated' ? ReviewModal : QuickPromotionModal),
- save: generic(SaveToggleButton),
- share: generic(ShareLink),
- } as const
-}
-
-/**
- * Used to display the action buttons when viewing an organization/location/service.
- *
- * When using the save or unsave buttons for services, you need to pass the serviceId prop.
- *
- * When trying to save or unsave an organization, the component parses the current URL to find the
- * organization's id, so you don't need to pass it as a prop.
- */
-export const ActionButtons = ({
- iconKey,
- omitLabel = false,
- serviceId,
- organizationId,
- outsideMoreMenu,
- children,
-}: ActionButtonProps) => {
- const { classes } = useStyles()
- const theme = useMantineTheme()
- const { t } = useTranslation()
- const iconRender = actionButtonIcons[iconKey]
- const { more: _, ...overFlowItems } = actionButtonIcons
- const actions = useActions()
- const [opened, setOpened] = useState(false)
- const { query: rawQuery } = useRouter()
- const { slug } = rawQuery
- const { isMobile, isTablet } = useScreenSize()
-
- const { data: orgQuery } = api.organization.getIdFromSlug.useQuery(
- { slug: slug as string },
- { enabled: typeof slug === 'string' }
- )
-
- const orgId = orgQuery?.id || organizationId
-
- const orgOrServiceId = { organizationId: orgId ?? '', serviceId }
-
- let filteredOverflowItems = Object.entries(overFlowItems).filter(
- ([key, _item]) => !(isMobile || isTablet) || key !== 'print'
- )
-
- if (outsideMoreMenu)
- /* Keep overFlowItems where the key is not in outsideMoreMenu array */
- filteredOverflowItems = filteredOverflowItems.filter(([key, _item]) => !outsideMoreMenu.includes(key))
-
- const overflowMenuItems = filteredOverflowItems.map(([key, item]) => {
- const children = (
-
-
- {t(item.labelKey)}
-
- )
-
- return actions[key as keyof typeof actionButtonIcons]({
- isMenu: true,
- children,
- props: { ...orgOrServiceId, key },
- })
- })
-
- const menuThings = overflowMenuItems
-
- const buttonProps = {
- className: opened ? classes.buttonPressed : classes.button,
- radius: 'md',
- ...orgOrServiceId,
- }
-
- /** The button component */
- const buttonIcon = (
- <>
-
- {!omitLabel && 'labelKey' in iconRender && (
- {children ? children : t(iconRender.labelKey, { count: 1 })}
- )}
- >
- )
-
- const buttonComponent = actions[iconKey]({ children: buttonIcon, props: buttonProps })
-
- /** The menu component */
- const menuComponent = (
-
- )
-
- return 'useMenu' in iconRender ? menuComponent : buttonComponent
-}
-const Loading = () =>
-
-ActionButtons.Loading = Loading
-
-interface ActionButtonProps {
- /**
- * The action button is created using an iconKey, which, depending on the value supplied, will display
- * either an icon and a label or just an icon
- */
- iconKey: keyof typeof actionButtonIcons
- /** Display icon only */
- omitLabel?: boolean
- /** Specify which buttons will be displayed in the 'more' dropdown menu */
- outsideMoreMenu?: string[]
- children?: string
- /** Information for save button */
- serviceId?: string
- organizationId?: string
-}
-
-type Polymorphic = typeof QuickPromotionModal | typeof ReviewModal | typeof SaveButton
-
-type PropAdditions = { serviceId?: string; organizationId: string; key?: string; isMenu?: boolean }
-
-type PolymorphicProps = ButtonProps & PropAdditions
-type PolyButtonProps = ButtonProps & Partial
-
-type Generic = {
- children?: JSX.Element
- isMenu?: boolean
- props?: PolyButtonProps | PolymorphicProps
-}
-
-export interface SaveToggleButtonProps extends Omit {
- organizationId?: string
- serviceId?: string
- isMenu?: boolean
-}
-
-type ListMenuProps = SaveMenuProps | DeleteMenuProps
-interface SaveMenuProps extends ButtonProps {
- data: ApiInput['savedList']['saveItem']
- name: string
- action: 'save'
-}
-interface DeleteMenuProps extends ButtonProps {
- data: ApiInput['savedList']['deleteItem']
- name: string
- action: 'delete'
-}
diff --git a/packages/ui/components/core/ActionButtons/Group.tsx b/packages/ui/components/core/ActionButtons/Group.tsx
new file mode 100644
index 0000000000..2d5f8966b5
--- /dev/null
+++ b/packages/ui/components/core/ActionButtons/Group.tsx
@@ -0,0 +1,112 @@
+import { Box, createStyles } from '@mantine/core'
+import { Children, cloneElement, type ReactElement, useCallback, useEffect, useRef, useState } from 'react'
+
+import { OverflowMenu } from './Menu'
+
+const useStyles = createStyles(() => ({
+ visible: {
+ order: 0,
+ visibility: 'visible',
+ opacity: 1,
+ },
+ inVisible: {
+ order: 100,
+ visibility: 'hidden',
+ pointerEvents: 'none',
+ },
+ groupWrapper: {
+ display: 'flex',
+ overflow: 'hidden',
+ flexWrap: 'nowrap',
+ maxWidth: '100%',
+ },
+ overflowStyle: {
+ order: 99,
+ position: 'sticky',
+ right: 0,
+ },
+}))
+
+const isHTMLElement = (e: unknown): e is HTMLElement => e instanceof HTMLElement
+
+const getTargetId = (e: ReactElement) => {
+ const targetId = typeof e.props['data-targetid'] === 'string' && e.props['data-targetid']
+ if (!targetId) {
+ return null
+ }
+ return targetId
+}
+
+export const ActionButtonGroup = ({ children }: ActionButtonGroupProps) => {
+ const { classes, cx } = useStyles()
+ const containerRef = useRef(null)
+ const [visibilityMap, setVisibilityMap] = useState>({})
+ const handleIntersection: IntersectionObserverCallbackFn = useCallback((entries) => {
+ const updatedEntries: Record = {}
+ entries.forEach((entry) => {
+ if (isHTMLElement(entry.target)) {
+ const targetid = entry.target.dataset.targetid
+ if (!targetid) {
+ return
+ }
+ if (entry.isIntersecting) {
+ updatedEntries[targetid] = true
+ } else {
+ updatedEntries[targetid] = false
+ }
+ }
+ })
+
+ setVisibilityMap((prev) => ({
+ ...prev,
+ ...updatedEntries,
+ }))
+ }, [])
+ useEffect(() => {
+ const observer = new IntersectionObserver(handleIntersection, {
+ root: containerRef.current,
+ threshold: 1,
+ })
+
+ // We are addting observers to child elements of the container div
+ // with ref as navRef. Notice that we are adding observers
+ // only if we have the data attribute observerid on the child elemeent
+ containerRef.current &&
+ Array.from(containerRef.current.children).forEach((item) => {
+ if (isHTMLElement(item) && item.dataset.targetid) {
+ observer.observe(item)
+ }
+ })
+ return () => observer.disconnect()
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [])
+
+ return (
+
+ {...Children.map(children, (child) => {
+ const targetId = getTargetId(child)
+ if (!targetId) {
+ return child
+ }
+ const isVisible = visibilityMap[targetId] ?? false
+ const clonedChild = cloneElement(child, {
+ ...child.props,
+ className: cx(child.props.className, {
+ [classes.visible]: isVisible,
+ [classes.inVisible]: !isVisible,
+ }),
+ })
+ return clonedChild
+ })}
+
+ {children}
+
+
+ )
+}
+
+interface ActionButtonGroupProps {
+ children: ReactElement | ReactElement[]
+}
+
+type IntersectionObserverCallbackFn = ConstructorParameters[0]
diff --git a/packages/ui/components/core/ActionButtons/Menu.tsx b/packages/ui/components/core/ActionButtons/Menu.tsx
new file mode 100644
index 0000000000..ae1c3144b9
--- /dev/null
+++ b/packages/ui/components/core/ActionButtons/Menu.tsx
@@ -0,0 +1,110 @@
+import { Menu, type MenuProps, useMantineTheme } from '@mantine/core'
+import {
+ Children,
+ cloneElement,
+ forwardRef,
+ isValidElement,
+ type MouseEventHandler,
+ type ReactElement,
+ useCallback,
+ useMemo,
+ useState,
+} from 'react'
+
+import { Button } from '~ui/components/core/Button'
+import { Icon, type IconifyIconHTMLElement } from '~ui/icon'
+
+import { useStyles } from './styles'
+
+const getTargetId = (e: ReactElement) => {
+ const targetId = typeof e.props['data-targetid'] === 'string' && e.props['data-targetid']
+ if (!targetId) {
+ return null
+ }
+ return targetId
+}
+
+export const OverflowMenu = forwardRef(
+ ({ children, className, visibilityMap, ...props }, ref) => {
+ const { classes, cx } = useStyles()
+ const theme = useMantineTheme()
+ const [anchorEl, setAnchorEl] = useState<
+ (EventTarget & IconifyIconHTMLElement) | (EventTarget & HTMLElement) | null
+ >(null)
+ const open = Boolean(anchorEl)
+
+ const handleClick: MouseEventHandler & MouseEventHandler =
+ useCallback(
+ (event) => {
+ setAnchorEl(event.currentTarget)
+ },
+ [setAnchorEl]
+ )
+
+ const handleClose = useCallback(() => {
+ setAnchorEl(null)
+ }, [setAnchorEl])
+
+ const shouldShowMenu = useMemo(
+ () => Object.values(visibilityMap).some((v) => v === false),
+ [visibilityMap]
+ )
+
+ if (!shouldShowMenu) {
+ return null
+ }
+ const { inOverflowMenu: _inOverflowMenu, ...menuClassNames } = classes
+ return (
+
+ )
+ }
+)
+OverflowMenu.displayName = 'ActionButtons.Menu'
+
+export interface ActionButtonMenuProps extends MenuProps {
+ className: string
+ visibilityMap: Record
+}
diff --git a/packages/ui/components/core/ActionButtons/Print.tsx b/packages/ui/components/core/ActionButtons/Print.tsx
new file mode 100644
index 0000000000..766697b63f
--- /dev/null
+++ b/packages/ui/components/core/ActionButtons/Print.tsx
@@ -0,0 +1,40 @@
+import { Box, Group, Text, useMantineTheme } from '@mantine/core'
+import { useTranslation } from 'next-i18next'
+import { forwardRef } from 'react'
+
+import { Button, type ButtonProps } from '~ui/components/core/Button'
+import { Icon } from '~ui/icon'
+
+import { useStyles } from './styles'
+
+export const Print = forwardRef(({ omitLabel, className, ...props }, ref) => {
+ const { classes, cx } = useStyles()
+ const theme = useMantineTheme()
+ const { t } = useTranslation('common')
+
+ return (
+
+
+
+ {!omitLabel && {t('words.print')}}
+
+
+ )
+})
+Print.displayName = 'ActionButtons.Print'
+
+export interface PrintProps extends ButtonProps {
+ omitLabel?: boolean
+}
diff --git a/packages/ui/components/core/ActionButtons/Review.tsx b/packages/ui/components/core/ActionButtons/Review.tsx
new file mode 100644
index 0000000000..44008216e8
--- /dev/null
+++ b/packages/ui/components/core/ActionButtons/Review.tsx
@@ -0,0 +1,47 @@
+import { Box, Group, Text, useMantineTheme } from '@mantine/core'
+import { useSession } from 'next-auth/react'
+import { useTranslation } from 'next-i18next'
+import { forwardRef, useMemo } from 'react'
+
+import { type ButtonProps } from '~ui/components/core/Button'
+import { Icon } from '~ui/icon'
+import { QuickPromotionModal } from '~ui/modals/QuickPromotion'
+import { ReviewModal } from '~ui/modals/Review'
+
+import { useStyles } from './styles'
+
+export const Review = forwardRef(
+ ({ omitLabel, className, ...props }, ref) => {
+ const { classes, cx } = useStyles()
+ const theme = useMantineTheme()
+ const { t } = useTranslation('common')
+ const { status: sessionStatus } = useSession()
+
+ const BaseComponent = useMemo(() => {
+ if (sessionStatus === 'authenticated') {
+ return ReviewModal
+ }
+ return QuickPromotionModal
+ }, [sessionStatus])
+
+ return (
+
+
+
+ {!omitLabel && {t('words.review')}}
+
+
+ )
+ }
+)
+Review.displayName = 'ActionButtons.Review'
+
+export interface ReviewProps extends ButtonProps {
+ omitLabel?: boolean
+}
diff --git a/packages/ui/components/core/ActionButtons/Save.tsx b/packages/ui/components/core/ActionButtons/Save.tsx
new file mode 100644
index 0000000000..921b2e5cc8
--- /dev/null
+++ b/packages/ui/components/core/ActionButtons/Save.tsx
@@ -0,0 +1,241 @@
+import { Box, Center, Group, Menu, Text, useMantineTheme } from '@mantine/core'
+import { useDisclosure } from '@mantine/hooks'
+import { useSession } from 'next-auth/react'
+import { useTranslation } from 'next-i18next'
+import { type ComponentPropsWithRef, forwardRef, useCallback, useMemo } from 'react'
+
+import { type ApiInput } from '@weareinreach/api'
+import { Button, type ButtonProps } from '~ui/components/core/Button'
+import { useNewNotification } from '~ui/hooks/useNewNotification'
+import { Icon } from '~ui/icon'
+import { trpc as api } from '~ui/lib/trpcClient'
+import { CreateNewList } from '~ui/modals'
+import { QuickPromotionModal } from '~ui/modals/QuickPromotion'
+
+import { useStyles } from './styles'
+
+const useNotifications = (listName: string) => {
+ const { t } = useTranslation('common')
+
+ return {
+ saved: useNewNotification({
+ icon: 'heartFilled',
+ displayText: t('list.added', { name: listName }),
+ }),
+ deleted: useNewNotification({
+ icon: 'heartEmpty',
+ displayText: t('list.removedMulti', { name: listName }),
+ }),
+ errorSave: useNewNotification({
+ icon: 'warning',
+ displayText: t('list.error-add'),
+ }),
+ errorDelete: useNewNotification({
+ icon: 'warning',
+ displayText: t('list.error-remove'),
+ }),
+ }
+}
+
+/**
+ * Returns a Menu Item with the new of an existing list. When clicked it saves the current organization or
+ * service to the list.
+ *
+ * @param data - Contains information about the list
+ * @param data.id - List id : string
+ * @param data.organizationId - String | undefined
+ * @param data.serviceId - String | undefined
+ * @param name - List name : string
+ * @returns JSX.Element
+ */
+const ListItem = ({ data, name, action }: ListMenuProps) => {
+ const { t } = useTranslation()
+ const utils = api.useUtils()
+
+ const savedInList = useNewNotification({
+ icon: 'heartFilled',
+ displayText: t('list.added', { name }),
+ })
+ const errorSaving = useNewNotification({
+ icon: 'warning',
+ displayText: t('list.error-add'),
+ })
+ const deletedInList = useNewNotification({
+ icon: 'heartEmpty',
+ displayText: t('list.removedMulti', { name }),
+ })
+ const errorRemoving = useNewNotification({
+ icon: 'warning',
+ displayText: t('list.error-remove'),
+ })
+
+ const saveItem = api.savedList.saveItem.useMutation({
+ onSuccess: (_, { itemId }) => {
+ savedInList()
+ utils.savedList.isSaved.invalidate(itemId)
+ },
+ onError: errorSaving,
+ })
+ const removeItem = api.savedList.deleteItem.useMutation({
+ onSuccess: (_, { itemId }) => {
+ deletedInList()
+ utils.savedList.isSaved.invalidate(itemId)
+ },
+ onError: errorRemoving,
+ })
+ const clickHandler = useCallback(() => {
+ if (action === 'save') {
+ saveItem.mutate(data)
+ } else {
+ removeItem.mutate(data)
+ }
+ }, [action, data, removeItem, saveItem])
+
+ return {name}
+}
+
+export const Save = forwardRef(
+ ({ itemId, itemName, menuItem, omitLabel, className, ...rest }, ref) => {
+ const [menuOpened, menuHandler] = useDisclosure(false)
+ const { classes, cx } = useStyles()
+ const { status: sessionStatus } = useSession()
+ const { t } = useTranslation('common')
+ const utils = api.useUtils()
+ const notifications = useNotifications(itemName)
+ const theme = useMantineTheme()
+
+ const userIsLoggedIn = useMemo(() => sessionStatus === 'authenticated', [sessionStatus])
+
+ const { data: savedToLists } = api.savedList.isSaved.useQuery(itemId, {
+ enabled: userIsLoggedIn,
+ })
+ const {
+ data: availableLists,
+ isError: availableListsError,
+ refetch: refetchAvailableLists,
+ } = api.savedList.getAll.useQuery(undefined, {
+ refetchOnWindowFocus: false,
+ enabled: sessionStatus === 'authenticated',
+ })
+ const removeItem = api.savedList.deleteItem.useMutation({
+ onSuccess: () => {
+ notifications.deleted()
+ utils.savedList.isSaved.invalidate(itemId)
+ utils.savedList.getAll.invalidate()
+ },
+ onError: notifications.errorDelete,
+ })
+
+ const isSaved = Boolean(savedToLists)
+ const isLoggedIn = sessionStatus === 'authenticated'
+ const buttonIcon = isSaved ? 'carbon:favorite-filled' : 'carbon:favorite'
+ const savedToSingleList = savedToLists && savedToLists.length === 1
+
+ const baseClassname = menuItem ? undefined : classes.button
+ const iconColor = menuItem ? theme.other.colors.secondary.white : theme.other.colors.secondary.black
+
+ const modalProps: ComponentPropsWithRef = menuItem
+ ? { ref, component: Menu.Item, radius: 'md' }
+ : { ref, component: Button, className: classes.button, radius: 'md' }
+
+ const handleRemoveFromList = useCallback(
+ (listId: string) => () => removeItem.mutate({ id: listId, itemId }),
+ [itemId, removeItem]
+ )
+ const handleRefetchAvailableLists = useCallback(() => refetchAvailableLists(), [refetchAvailableLists])
+
+ const DisplayedInfo = (
+
+
+ {!omitLabel && (
+
+ {t(isSaved ? 'words.saved' : 'words.save')}
+
+ )}
+
+ )
+
+ if (!isLoggedIn) {
+ return (
+
+ {DisplayedInfo}
+
+ )
+ }
+
+ if (isSaved && savedToSingleList) {
+ const listId = savedToLists.at(0)?.id
+
+ if (!listId) {
+ return <>Error>
+ }
+
+ return (
+
+ {DisplayedInfo}
+
+ )
+ }
+
+ return (
+
+ )
+ }
+)
+Save.displayName = 'ActionButtons.Save'
+
+export interface ActionButtonSaveProps extends ButtonProps {
+ itemId: string
+ itemName: string
+ menuItem?: boolean
+ omitLabel?: boolean
+}
+
+type ListMenuProps = SaveMenuProps | DeleteMenuProps
+interface SaveMenuProps extends ButtonProps {
+ data: ApiInput['savedList']['saveItem']
+ name: string
+ action: 'save'
+}
+interface DeleteMenuProps extends ButtonProps {
+ data: ApiInput['savedList']['deleteItem']
+ name: string
+ action: 'delete'
+}
diff --git a/packages/ui/components/core/ActionButtons/Share.tsx b/packages/ui/components/core/ActionButtons/Share.tsx
new file mode 100644
index 0000000000..ac05a0949a
--- /dev/null
+++ b/packages/ui/components/core/ActionButtons/Share.tsx
@@ -0,0 +1,62 @@
+import { Box, Group, Text, useMantineTheme } from '@mantine/core'
+import { useClipboard } from '@mantine/hooks'
+import { useRouter } from 'next/router'
+import { useTranslation } from 'next-i18next'
+import { forwardRef, useCallback } from 'react'
+
+import { Button, type ButtonProps } from '~ui/components/core/Button'
+import { useNewNotification } from '~ui/hooks'
+import { Icon } from '~ui/icon'
+
+import { useStyles } from './styles'
+
+export const Share = forwardRef(({ omitLabel, className, ...props }, ref) => {
+ const { classes, cx } = useStyles()
+ const theme = useMantineTheme()
+ const { t } = useTranslation('common')
+ const { asPath } = useRouter()
+ const href = `${window.location.origin}${asPath}`
+
+ const clipboard = useClipboard({ timeout: 500 })
+ const copiedToClipboard = useNewNotification({ icon: 'info', displayText: t('link-copied') })
+
+ const handleCopy = useCallback(async () => {
+ if (navigator.canShare instanceof Function && navigator?.canShare?.({ url: href })) {
+ try {
+ await navigator.share({ url: href })
+ } catch {
+ clipboard.copy(href)
+ copiedToClipboard()
+ }
+ } else {
+ clipboard.copy(href)
+ copiedToClipboard()
+ }
+ }, [clipboard, copiedToClipboard, href])
+
+ return (
+
+
+
+ {!omitLabel && {t('words.share')}}
+
+
+ )
+})
+Share.displayName = 'ActionButtons.Share'
+
+export interface ShareProps extends ButtonProps {
+ omitLabel?: boolean
+}
diff --git a/packages/ui/components/core/ActionButtons/index.stories.tsx b/packages/ui/components/core/ActionButtons/index.stories.tsx
new file mode 100644
index 0000000000..0dc436ac96
--- /dev/null
+++ b/packages/ui/components/core/ActionButtons/index.stories.tsx
@@ -0,0 +1,123 @@
+import { type Meta, type StoryObj } from '@storybook/react'
+
+import { organization } from '~ui/mockData/organization'
+import { review } from '~ui/mockData/review'
+import { savedList } from '~ui/mockData/savedList'
+
+import { ActionButtons as ActionButtonsComponent } from './index'
+
+export default {
+ title: 'Design System/Action Buttons',
+ component: ActionButtonsComponent,
+ parameters: {
+ design: {
+ type: 'figma',
+ url: 'https://www.figma.com/file/gl8ppgnhpSq1Dr7Daohk55/Design-System-(2023)?node-id=52%3A1420&t=sleVeGl2lJv7Df18-4',
+ },
+ layout: 'fullscreen',
+ layoutWrapper: 'centeredHalf',
+ msw: [
+ organization.getIdFromSlug,
+ review.create,
+ savedList.getAll,
+ savedList.saveItem,
+ savedList.createAndSaveItem,
+ ],
+ nextjs: {
+ router: {
+ pathname: '/org/[slug]',
+ asPath: '/org/mockOrg',
+ query: {
+ slug: 'mockOrg',
+ },
+ },
+ },
+ nextAuthMock: { session: 'noAuth' },
+ },
+} satisfies Meta
+
+type StoryDef = StoryObj
+
+export const Save = {
+ parameters: {
+ nextAuthMock: {
+ session: 'userPic',
+ },
+ },
+ args: { itemId: 'orgn_1234', itemName: 'Test item name' },
+ render: (args) => ,
+} satisfies StoryObj
+
+export const SaveLoggedOut = {
+ parameters: {
+ nextAuthMock: {
+ session: 'noAuth',
+ },
+ },
+ args: { itemId: 'orgn_1234', itemName: 'Test item name' },
+ render: (args) => ,
+} satisfies StoryObj
+
+export const SavedToSingleList = {
+ parameters: {
+ nextAuthMock: {
+ session: 'userPic',
+ },
+ msw: [savedList.isSavedSingle, savedList.deleteItem, organization.getIdFromSlug],
+ },
+ args: { itemId: 'orgn_1234', itemName: 'Test item name' },
+ render: (args) => ,
+} satisfies StoryObj
+export const SavedToMultipleLists = {
+ parameters: {
+ nextAuthMock: {
+ session: 'userPic',
+ },
+ msw: [savedList.isSavedMultiple, savedList.getAll, savedList.deleteItem, organization.getIdFromSlug],
+ },
+ args: { itemId: 'orgn_1234', itemName: 'Test item name' },
+ render: (args) => ,
+} satisfies StoryObj
+export const Share = {
+ render: (args) => ,
+} satisfies StoryObj
+export const Print = {
+ render: (args) => ,
+} satisfies StoryObj
+export const Delete = {
+ args: {
+ iconKey: 'delete',
+ },
+} satisfies StoryDef
+export const Review = {
+ render: (args) => ,
+} satisfies StoryObj
+export const More = {
+ parameters: {
+ nextAuthMock: {
+ session: 'userPic',
+ },
+ },
+ args: {
+ containerWidth: 100,
+ },
+ argTypes: {
+ containerWidth: {
+ control: 'range',
+ min: 1,
+ max: 100,
+ step: 5,
+ },
+ },
+ // @ts-expect-error Stop yelling about the `containerWidth` prop.
+ render: ({ containerWidth }: { containerWidth: number }) => (
+
+ ),
+} satisfies StoryObj
diff --git a/packages/ui/components/core/ActionButtons/index.tsx b/packages/ui/components/core/ActionButtons/index.tsx
new file mode 100644
index 0000000000..96d20c15f7
--- /dev/null
+++ b/packages/ui/components/core/ActionButtons/index.tsx
@@ -0,0 +1,19 @@
+import { Skeleton } from '@mantine/core'
+
+import { ActionButtonGroup } from './Group'
+import { OverflowMenu } from './Menu'
+import { Print } from './Print'
+import { Review } from './Review'
+import { Save } from './Save'
+import { Share } from './Share'
+
+const Loading = () =>
+export const ActionButtons = () => null
+
+ActionButtons.Loading = Loading
+ActionButtons.Save = Save
+ActionButtons.Share = Share
+ActionButtons.Print = Print
+ActionButtons.Review = Review
+ActionButtons.Menu = OverflowMenu
+ActionButtons.Group = ActionButtonGroup
diff --git a/packages/ui/components/core/ActionButtons/styles.ts b/packages/ui/components/core/ActionButtons/styles.ts
new file mode 100644
index 0000000000..158daa93fb
--- /dev/null
+++ b/packages/ui/components/core/ActionButtons/styles.ts
@@ -0,0 +1,74 @@
+import { createStyles, rem } from '@mantine/core'
+
+export const useStyles = createStyles((theme) => ({
+ button: {
+ display: 'flex',
+ flexDirection: 'row',
+ alignItems: 'center',
+ // minWidth: rem(48),
+ minWidth: 'fit-content',
+ height: rem(48),
+ padding: rem(12),
+ gap: rem(8),
+ backgroundColor: theme.other.colors.secondary.white,
+ border: 0,
+ borderRadius: rem(8),
+ '&:not([data-disabled])': theme.fn.hover({
+ backgroundColor: theme.other.colors.primary.lightGray,
+ }),
+ },
+ buttonPressed: {
+ display: 'flex',
+ flexDirection: 'row',
+ alignItems: 'center',
+ minWidth: rem(48),
+ height: rem(48),
+ padding: rem(12),
+ gap: rem(8),
+ backgroundColor: theme.other.colors.primary.lightGray,
+ '&:not([data-disabled])': theme.fn.hover({
+ backgroundColor: theme.other.colors.primary.lightGray,
+ }),
+ },
+ icon: {
+ color: theme.other.colors.secondary.black,
+ },
+ text: {
+ fontWeight: theme.other.fontWeight.semibold,
+ marginLeft: rem(8),
+ },
+ dropdown: {
+ background: theme.other.colors.secondary.black,
+ borderRadius: theme.radius.md,
+ paddingTop: rem(2),
+ paddingBottom: rem(2),
+ },
+ item: {
+ '& > *': {
+ color: 'white !important',
+ },
+ color: 'white',
+ fontWeight: theme.other.fontWeight.semibold,
+ fontSize: theme.fontSizes.md,
+ '&[data-hovered]': {
+ backgroundColor: 'inherit',
+ // color: 'black',
+ textDecoration: 'underline',
+ },
+ },
+ inOverflowMenu: {
+ border: 'none !important',
+ padding: 0,
+ backgroundColor: 'inherit',
+ ...theme.fn.hover({
+ backgroundColor: 'transparent !important',
+ }),
+ height: 'unset',
+ '&.mantine-Group-root, .mantine-Text-root, .iconify-icon-root, .mantine-Menu-item': {
+ color: theme.other.colors.secondary.white,
+ // ...theme.fn.hover({
+ // backgroundColor: 'transparent !important',
+ // }),
+ },
+ },
+}))
diff --git a/packages/ui/components/core/Breadcrumb.tsx b/packages/ui/components/core/Breadcrumb.tsx
index ab8842e128..6b0e26b658 100644
--- a/packages/ui/components/core/Breadcrumb.tsx
+++ b/packages/ui/components/core/Breadcrumb.tsx
@@ -119,7 +119,7 @@ export const Breadcrumb = (props: BreadcrumbProps) => {
return (
-
+
>(
+export const Button = forwardRef>(
(props, ref) => {
const isCustom = (customVariants as ReadonlyArray).includes(props.variant ?? 'filled')
const { classes: baseClasses } = useVariantStyles({ variant: props.variant ?? 'filled' })
- const { children, variant, classNames, ...others } = props as ButtonProps
+ const { children, variant, classNames, ...others } = props as MantineButtonProps
const mantineVariant = isCustom ? undefined : (variant as ButtonVariant)
@@ -192,12 +192,8 @@ Button.displayName = '@weareinreach/ui/components/core/Button'
interface ButtonStylesParams {
variant?: CustomVariants | 'filled' | 'outline'
}
-// type MantineButtonProps = Pick<
-// ButtonProps,
-// 'type' | 'fullWidth' | 'uppercase' | 'loaderProps' | 'loaderPosition'
-// >
-interface CustomButtonProps extends ButtonProps {
+export interface ButtonProps extends MantineButtonProps {
/** Button style/design */
variant?: CustomVariants | 'filled' | 'outline'
/** Label Text */
diff --git a/packages/ui/components/core/SearchResultCard.tsx b/packages/ui/components/core/SearchResultCard.tsx
index bbb40733b8..f8fb37f610 100644
--- a/packages/ui/components/core/SearchResultCard.tsx
+++ b/packages/ui/components/core/SearchResultCard.tsx
@@ -157,6 +157,7 @@ const SearchResultData = ({ result }: SearchResultHasData) => {
className={classes.hoverText}
{...(hovered && { 'data-hovered': hovered })}
mb={12}
+ {...(hovered && { 'data-hovered': hovered })}
>
{
{leaderBadgeGroup}
-
+
({
toolbar: {
// padding: `${rem(0)} ${rem(8)} ${rem(0)} ${rem(12)}`,
@@ -14,41 +10,26 @@ const useStyles = createStyles(() => ({
},
}))
-export const Toolbar = ({ saved = false, breadcrumbProps, hideBreadcrumb, ...ids }: Props) => {
- const theme = useMantineTheme()
- const isMobile = useMediaQuery(`(max-width: ${theme.breakpoints.sm})`)
- const { width } = useViewportSize()
+export const Toolbar = ({ breadcrumbProps, hideBreadcrumb, ...ids }: Props) => {
const { classes } = useStyles()
- const buttons = ['review', 'share', 'save']
-
- const buttonsInViewPort = isMobile ? Math.ceil((width - BREACRUMB_WIDTH) / MIN_BUTTON_WIDTH) % 3 : 4
-
- /* Contains the actionButtons displayed outside the 'more' actionButton menu */
- const inToolbar = buttonsInViewPort > 3 ? buttons : buttons.slice(-(buttonsInViewPort + 1))
-
- const displayButtons = inToolbar.map((button) => (
-
- ))
-
- // If organization is not saved do not display saved button
- if (!saved) inToolbar.push('saved')
-
- // No delete button in toolbar
- inToolbar.push('delete')
return (
{hideBreadcrumb ? : }
-
- {displayButtons}
-
-
+
+
+
+
+
)
}
type Props = {
- saved: boolean
breadcrumbProps: BreadcrumbProps
organizationId: string
serviceId?: string
diff --git a/packages/ui/components/core/index.tsx b/packages/ui/components/core/index.tsx
index 4ebc965d65..8ff028db7e 100644
--- a/packages/ui/components/core/index.tsx
+++ b/packages/ui/components/core/index.tsx
@@ -1,5 +1,4 @@
// codegen:start {preset: barrel, include: ./*.ts*, exclude: "*.stories.*"}
-export * from './ActionButtons'
export * from './AlertMessage'
export * from './AntiHateMessage'
export * from './Breadcrumb'
diff --git a/packages/ui/components/sections/Reviews.tsx b/packages/ui/components/sections/Reviews.tsx
index 3972b6ccbe..7e3f0787e3 100644
--- a/packages/ui/components/sections/Reviews.tsx
+++ b/packages/ui/components/sections/Reviews.tsx
@@ -62,7 +62,7 @@ export const ReviewSection = (props: ReviewSectionProps) => {
{t('review', { count: 2 })}
- {t('add', { ns: 'common', item: '$t(review)' })}
+ {t('add', { ns: 'common', item: '$t(review)' })}
{Boolean(props.reviews.length) && }
{props.reviews.length ? reviews : noReviews}
diff --git a/packages/ui/components/sections/SuggestOrg/context.ts b/packages/ui/components/sections/SuggestOrg/context.ts
index 7e8be02e0d..a07af900b3 100644
--- a/packages/ui/components/sections/SuggestOrg/context.ts
+++ b/packages/ui/components/sections/SuggestOrg/context.ts
@@ -1,7 +1,5 @@
import { createFormContext } from '@mantine/form'
-import { type ApiOutput } from '@weareinreach/api'
-
export const [SuggestionFormProvider, useFormContext, useForm] = createFormContext()
export interface SuggestionForm {
//data for submission
@@ -19,11 +17,5 @@ export interface SuggestionForm {
communityFocus?: string[]
//supportive data
- communityParent?: string[]
- searchLocation: string
- locationOptions: {
- value: string
- placeId: string
- }[]
- formOptions: ApiOutput['organization']['suggestionOptions']
+ // communityParent?: string[]
}
diff --git a/packages/ui/components/sections/SuggestOrg/index.tsx b/packages/ui/components/sections/SuggestOrg/index.tsx
index eaf9525478..aa4119b1a5 100644
--- a/packages/ui/components/sections/SuggestOrg/index.tsx
+++ b/packages/ui/components/sections/SuggestOrg/index.tsx
@@ -1,5 +1,6 @@
import {
Autocomplete,
+ type AutocompleteItem,
Button,
createStyles,
Divider,
@@ -19,9 +20,12 @@ import { Trans, useTranslation } from 'next-i18next'
import {
type ComponentPropsWithRef,
type Dispatch,
+ type FocusEventHandler,
forwardRef,
type SetStateAction,
+ useCallback,
useEffect,
+ useMemo,
useState,
} from 'react'
@@ -94,9 +98,17 @@ interface SuggestOrgProps {
const OrgExistsError = ({ queryResult, form, setGenerateSlug }: OrgExistsErrorProps) => {
const variants = useCustomVariant()
- if (!queryResult) return null
+ const handleDismiss = useCallback(() => {
+ form.clearFieldError('orgName')
+ setGenerateSlug(true)
+ }, [form, setGenerateSlug])
+
+ if (!queryResult) {
+ return null
+ }
const { name, published, slug } = queryResult
const key = published ? 'form.error-exists-active' : 'form.error-exists-inactive'
+
return (
<>
{
- form.clearFieldError('orgName')
- setGenerateSlug(true)
- }}
- >
+
.
),
@@ -148,78 +154,79 @@ export const SuggestOrg = ({ authPromptState }: SuggestOrgProps) => {
const { t } = useTranslation(['suggestOrg', 'services', 'attribute'])
const simpleLocale = (locale: string) => (locale.length === 2 ? locale : locale.substring(0, 1))
const variants = useCustomVariant()
- const [locationSearch, setLocationSearch] = useState('')
+ const [placeId, setPlaceId] = useState('')
const [loading, setLoading] = useState(true)
- const [locSearchInput] = useDebouncedValue(form.values.searchLocation, 400)
+ const [searchLocation, setSearchLocation] = useState('')
+ const [locSearchInput] = useDebouncedValue(searchLocation, 400)
const [orgName, setOrgName] = useState()
const [generateSlug, setGenerateSlug] = useState(false)
const router = useRouter()
const countrySelected = Boolean(form.values.countryId)
- const {
- data: formOptions,
- isLoading,
- isSuccess,
- } = api.organization.suggestionOptions.useQuery(undefined, {
- onSuccess: (data) => {
- form.setValues({ formOptions: data })
- },
- })
+ const { data: formOptions, isLoading, isSuccess } = api.organization.suggestionOptions.useQuery()
- api.geo.autocomplete.useQuery(
+ const { data: addressCandidates } = api.geo.autocomplete.useQuery(
{ search: locSearchInput, locale: simpleLocale(router.locale), fullAddress: true },
{
enabled: Boolean(locSearchInput) && locSearchInput !== '',
- onSuccess: ({ results }) =>
- form.setValues({
- locationOptions: results.map((result) => ({
- value: `${result.value}, ${result.subheading}`,
- label: `${result.value}, ${result.subheading}`,
- placeId: result.placeId,
- })),
- }),
refetchOnWindowFocus: false,
}
)
- api.geo.geoByPlaceId.useQuery(locationSearch, {
- enabled: Boolean(locationSearch) && locationSearch !== '',
- onSuccess: ({ result }) => {
- if (result)
- form.setFieldValue('orgAddress', {
- street1: `${result.streetNumber} ${result.streetName}`,
- city: result.city,
- govDist: result.govDist,
- postCode: result.postCode,
- })
- },
+ const addressAutocompleteOptions = useMemo(
+ () =>
+ addressCandidates?.results.map((result) => ({
+ value: `${result.value}, ${result.subheading}`,
+ label: `${result.value}, ${result.subheading}`,
+ placeId: result.placeId,
+ })) ?? [],
+ [addressCandidates]
+ )
+
+ const { data: addressResult } = api.geo.geoByPlaceId.useQuery(placeId, {
+ enabled: Boolean(placeId) && placeId !== '',
})
+ useEffect(() => {
+ if (addressResult?.result) {
+ const { result } = addressResult
+ form.setFieldValue('orgAddress', {
+ street1: `${result.streetNumber} ${result.streetName}`,
+ city: result.city,
+ govDist: result.govDist,
+ postCode: result.postCode,
+ })
+ }
+ }, [addressResult, form])
- api.organization.checkForExisting.useQuery(orgName ?? '', {
+ const { data: existingOrg } = api.organization.checkForExisting.useQuery(orgName ?? '', {
enabled: Boolean(orgName && orgName !== ''),
- onSuccess: (data) => {
- if (!data) {
- form.clearFieldError('orgName')
- setGenerateSlug(true)
- } else {
- form.setFieldError('orgName', )
- }
- },
})
- api.organization.generateSlug.useQuery(orgName ?? '', {
+ useEffect(() => {
+ if (!existingOrg && !generateSlug) {
+ form.clearFieldError('orgName')
+ setGenerateSlug(true)
+ } else if (existingOrg) {
+ form.setFieldError(
+ 'orgName',
+
+ )
+ }
+ }, [existingOrg, generateSlug, form])
+
+ const { data: generatedSlug } = api.organization.generateSlug.useQuery(orgName ?? '', {
enabled: Boolean(orgName && orgName !== '' && generateSlug),
- onSuccess: (data) => {
- if (data) form.setFieldValue('orgSlug', data)
- setGenerateSlug(false)
- },
})
+ useEffect(() => {
+ if (generatedSlug) {
+ form.setFieldValue('orgSlug', generatedSlug)
+ setGenerateSlug(false)
+ }
+ }, [form, generatedSlug])
useEffect(() => {
if (loading && formOptions && isSuccess && !isLoading) {
- form.setValues({ formOptions })
setLoading(false)
}
- // eslint-disable-next-line react-hooks/exhaustive-deps
}, [loading, formOptions, isSuccess, isLoading])
useEffect(() => {
@@ -227,27 +234,56 @@ export const SuggestOrg = ({ authPromptState }: SuggestOrgProps) => {
setOverlay(true)
form.setFieldValue('countryId', '')
}
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [hasAuth, overlay, form.values.countryId])
+ }, [hasAuth, overlay, form.values.countryId, form, setOverlay])
- if (loading) return null
+ const countryTranslation = useMemo(
+ () =>
+ new Intl.DisplayNames([router.locale.toLowerCase()], {
+ type: 'region',
+ }),
+ [router.locale]
+ )
- const countryTranslation = new Intl.DisplayNames([router.locale.toLowerCase()], {
- type: 'region',
- })
+ const countrySelections = useMemo(
+ () =>
+ Array.isArray(formOptions?.countries)
+ ? formOptions.countries.map(({ id, cca2 }) => {
+ return
+ })
+ : null,
+ [formOptions?.countries, countryTranslation]
+ )
- const countrySelections = Array.isArray(form.values.formOptions?.countries)
- ? form.values.formOptions?.countries.map(({ id, cca2 }, i) => {
- return (
-
- )
- })
- : null
+ const handleOrgNameBlur = useCallback>(
+ (e) => {
+ setOrgName(e.target.value)
+ },
+ [setOrgName]
+ )
+
+ const handleAddressSelection = useCallback(
+ (e: AutocompleteItem) => {
+ setPlaceId(e.placeId)
+ },
+ [setPlaceId]
+ )
+
+ const handleDismiss = useCallback(() => {
+ form.setValues({
+ communityFocus: [],
+ // communityParent: [],
+ countryId: '',
+ orgName: '',
+ orgSlug: '',
+ orgWebsite: '',
+ orgAddress: {},
+ })
+ modalHandler.close()
+ }, [form, modalHandler])
+ if (loading) {
+ return null
+ }
return (
>
)
}
-export const Communities = ({ disabled }: ModalProps) => {
+interface CommunitiesModalProps extends ModalProps {
+ communities: NonNullable['communities']
+}
+
+export const Communities = ({ disabled, communities }: CommunitiesModalProps) => {
+ const { classes } = useStyles()
const form = useFormContext()
const variants = useCustomVariant()
- const [open, handler] = useDisclosure(false)
+ const [modalOpen, modalHandler] = useDisclosure(false)
const { t } = useTranslation(['suggestOrg', 'attribute'])
- const selectedCurr = form.values.communityFocus ?? []
- // const childRecords = form.values.formOptions?.communities.flatMap(({ children }) => children)
+ const selectedCurr = useMemo(() => form.values.communityFocus ?? [], [form.values.communityFocus])
const unique = (ids: string[]) => [...new Set(ids)]
- const hasChildren = (parentId: string) =>
- form.values.formOptions?.communities.find(({ id, children }) => id === parentId && children.length)
+ const selectedCountIcon = useMemo(() => {
+ const selectedItems = form.values.communityFocus?.length ?? 0
+ return selectedItems > 0 ? {selectedItems} : null
+ }, [classes.count, form.values.communityFocus?.length])
+
+ const hasChildren = useCallback(
+ (parentId: string) => communities.find(({ id, children }) => id === parentId && children.length),
+ [communities]
+ )
- const getChildIds = (parentId: string) => {
- const parentRecord = form.values.formOptions?.communities.find(({ id }) => id === parentId)
- if (!parentRecord) return []
- return parentRecord.children.map(({ id }) => id)
- }
+ const getChildIds = useCallback(
+ (parentId: string) => {
+ const parentRecord = communities.find(({ id }) => id === parentId)
+ return parentRecord?.children.map(({ id }) => id) ?? []
+ },
+ [communities]
+ )
- const selectedChildren = (parentId: string, all?: boolean, none?: boolean): boolean => {
- const parentRecord = form.values.formOptions?.communities.find(({ id }) => id === parentId)
- if (!parentRecord || !hasChildren(parentId)) return false
- if (all) {
- const allChecked = parentRecord.children.every(({ id }) => selectedCurr.includes(id))
- return allChecked
- }
- if (none) {
- const noneChecked = parentRecord.children.every(({ id }) => !selectedCurr.includes(id))
- return noneChecked
- }
- return Boolean(
- !selectedChildren(parentId, true) && parentRecord.children.some(({ id }) => selectedCurr.includes(id))
- )
- }
- const toggleCategory = (parentId: string) => {
- const parentRecord = form.values.formOptions?.communities.find(({ id }) => id === parentId)
- if (!parentRecord) return
- const childIds = getChildIds(parentId)
- if (selectedChildren(parentId, true)) {
- // all selected -> deselect all
- form.setFieldValue(
- 'communityFocus',
- selectedCurr.filter((id) => !childIds.includes(id))
+ const selectedChildren = useCallback(
+ (parentId: string, all?: boolean, none?: boolean): boolean => {
+ const parentRecord = communities.find(({ id }) => id === parentId)
+ if (!parentRecord || !hasChildren(parentId)) {
+ return false
+ }
+ if (all) {
+ const allChecked = parentRecord.children.every(({ id }) => selectedCurr.includes(id))
+ return allChecked
+ }
+ if (none) {
+ const noneChecked = parentRecord.children.every(({ id }) => !selectedCurr.includes(id))
+ return noneChecked
+ }
+ return Boolean(
+ !selectedChildren(parentId, true) && parentRecord.children.some(({ id }) => selectedCurr.includes(id))
)
- return
- }
- form.setFieldValue('communityFocus', unique([...selectedCurr, ...childIds]))
- return
- }
+ },
+ [communities, hasChildren, selectedCurr]
+ )
+ const toggleCategory = useCallback(
+ (parentId: string) => {
+ const parentRecord = communities.find(({ id }) => id === parentId)
+ if (!parentRecord) {
+ return void 0
+ }
+ const childIds = getChildIds(parentId)
+ if (selectedChildren(parentId, true)) {
+ // all selected -> deselect all
+ form.setFieldValue(
+ 'communityFocus',
+ selectedCurr.filter((id) => !childIds.includes(id))
+ )
+ return void 0
+ }
+ form.setFieldValue('communityFocus', unique([...selectedCurr, ...childIds]))
+ return void 0
+ },
+ [communities, form, getChildIds, selectedChildren, selectedCurr]
+ )
+ const handleCategoryToggle = useCallback((id: string) => () => toggleCategory(id), [toggleCategory])
+
+ const wrapInStack = useCallback((children: ReactNode) => {children}, [])
- const options = Array.isArray(form.values.formOptions?.communities)
- ? form.values.formOptions?.communities.map((item, par) => {
+ const options = useMemo(
+ () =>
+ communities.map((item, par) => {
if (item.children.length) {
const indeterminate = selectedChildren(item.id)
const checked = selectedChildren(item.id, true)
@@ -124,19 +176,16 @@ export const Communities = ({ disabled }: ModalProps) => {
label={`${item.icon} ${t(item.tsKey, { ns: item.tsNs })}`}
indeterminate={indeterminate}
checked={checked}
- onClick={() => toggleCategory(item.id)}
+ onClick={handleCategoryToggle(item.id)}
// onChange={() => noop}
/>
- {children}}
- >
+
{item.children.map((child, i) => (
))}
@@ -146,27 +195,25 @@ export const Communities = ({ disabled }: ModalProps) => {
return (
- {children}}
- >
+
)
- })
- : null
+ }),
+ [communities, form, handleCategoryToggle, selectedChildren, t, wrapInStack]
+ )
return (
<>
handler.close()}
- title={}
+ opened={modalOpen}
+ onClose={modalHandler.close}
+ title={}
scrollAreaComponent={Modal.NativeScrollArea}
>
@@ -177,7 +224,7 @@ export const Communities = ({ disabled }: ModalProps) => {
{options}
-
@@ -188,10 +235,13 @@ export const Communities = ({ disabled }: ModalProps) => {
handler.open()}
+ onClick={modalHandler.open}
w='fit-content'
>
- {t('form.btn-community')}
+
+ {t('form.btn-community')}
+ {selectedCountIcon}
+
>
diff --git a/packages/ui/icon/iconList.ts b/packages/ui/icon/iconList.ts
index 6c8e6f8d18..e81b7ead42 100644
--- a/packages/ui/icon/iconList.ts
+++ b/packages/ui/icon/iconList.ts
@@ -1,3 +1,3 @@
// generated file - do not modify directly
// prettier-ignore
-export const iconList = ["carbon:3d-cursor","carbon:3d-cursor-alt","carbon:3d-curve-auto-colon","carbon:3d-curve-auto-vessels","carbon:3d-curve-manual","carbon:3d-ica","carbon:3d-mpr-toggle","carbon:3d-print-mesh","carbon:3d-software","carbon:3rd-party-connected","carbon:4k","carbon:4k-filled","carbon:accessibility","carbon:accessibility-alt","carbon:accessibility-color","carbon:accessibility-color-filled","carbon:account","carbon:accumulation-ice","carbon:accumulation-precipitation","carbon:accumulation-rain","carbon:accumulation-snow","carbon:activity","carbon:add","carbon:add-alt","carbon:add-comment","carbon:add-filled","carbon:add-large","carbon:agriculture-analytics","carbon:ai","carbon:ai-governance-lifecycle","carbon:ai-governance-tracked","carbon:ai-governance-untracked","carbon:ai-launch","carbon:ai-results","carbon:ai-results-high","carbon:ai-results-low","carbon:ai-results-medium","carbon:ai-results-urgent","carbon:ai-results-very-high","carbon:ai-status","carbon:ai-status-complete","carbon:ai-status-failed","carbon:ai-status-in-progress","carbon:ai-status-queued","carbon:ai-status-rejected","carbon:airline-digital-gate","carbon:airline-manage-gates","carbon:airline-passenger-care","carbon:airline-rapid-board","carbon:airplay","carbon:airplay-filled","carbon:airport-01","carbon:airport-02","carbon:airport-location","carbon:alarm","carbon:alarm-add","carbon:alarm-subtract","carbon:align-box-bottom-center","carbon:align-box-bottom-left","carbon:align-box-bottom-right","carbon:align-box-middle-center","carbon:align-box-middle-left","carbon:align-box-middle-right","carbon:align-box-top-center","carbon:align-box-top-left","carbon:align-box-top-right","carbon:align-horizontal-center","carbon:align-horizontal-left","carbon:align-horizontal-right","carbon:align-vertical-bottom","carbon:align-vertical-center","carbon:align-vertical-top","carbon:analytics","carbon:analytics-custom","carbon:analytics-reference","carbon:angle","carbon:annotation-visibility","carbon:aperture","carbon:api","carbon:api-1","carbon:app","carbon:app-connectivity","carbon:app-switcher","carbon:apple","carbon:apple-dash","carbon:application","carbon:application-mobile","carbon:application-virtual","carbon:application-web","carbon:apps","carbon:archive","carbon:area","carbon:area-custom","carbon:arithmetic-mean","carbon:arithmetic-median","carbon:arrival","carbon:arrow-annotation","carbon:arrow-down","carbon:arrow-down-left","carbon:arrow-down-right","carbon:arrow-left","carbon:arrow-right","carbon:arrow-shift-down","carbon:arrow-up","carbon:arrow-up-left","carbon:arrow-up-right","carbon:arrows","carbon:arrows-horizontal","carbon:arrows-vertical","carbon:asleep","carbon:asleep-filled","carbon:assembly","carbon:assembly-cluster","carbon:assembly-reference","carbon:asset","carbon:asset-confirm","carbon:asset-digital-twin","carbon:asset-view","carbon:asterisk","carbon:async","carbon:at","carbon:attachment","carbon:audio-console","carbon:augmented-reality","carbon:auto-scroll","carbon:automatic","carbon:autoscaling","carbon:awake","carbon:back-to-top","carbon:badge","carbon:baggage-claim","carbon:bar","carbon:barcode","carbon:bare-metal-server","carbon:bare-metal-server-01","carbon:bare-metal-server-02","carbon:barrier","carbon:basketball","carbon:bastion-host","carbon:bat","carbon:batch-job","carbon:batch-job-step","carbon:battery-charging","carbon:battery-empty","carbon:battery-full","carbon:battery-half","carbon:battery-low","carbon:battery-quarter","carbon:bee","carbon:bee-bat","carbon:beta","carbon:bicycle","carbon:binoculars","carbon:bloch-sphere","carbon:block-storage","carbon:block-storage-alt","carbon:blockchain","carbon:blog","carbon:bluetooth","carbon:bluetooth-off","carbon:book","carbon:bookmark","carbon:bookmark-add","carbon:bookmark-filled","carbon:boolean","carbon:boot","carbon:boot-volume","carbon:boot-volume-alt","carbon:border-bottom","carbon:border-full","carbon:border-left","carbon:border-none","carbon:border-right","carbon:border-top","carbon:bot","carbon:bottles-01","carbon:bottles-01-dash","carbon:bottles-02","carbon:bottles-02-dash","carbon:bottles-container","carbon:box","carbon:box-extra-large","carbon:box-large","carbon:box-medium","carbon:box-plot","carbon:box-small","carbon:branch","carbon:breaking-change","carbon:brightness-contrast","carbon:bring-forward","carbon:bring-to-front","carbon:brush-freehand","carbon:brush-polygon","carbon:build-tool","carbon:building","carbon:building-insights-1","carbon:building-insights-2","carbon:building-insights-3","carbon:bullhorn","carbon:buoy","carbon:bus","carbon:business-processes","carbon:button-centered","carbon:button-flush-left","carbon:cabin-care","carbon:cabin-care-alert","carbon:cabin-care-alt","carbon:cad","carbon:cafe","carbon:calculation","carbon:calculation-alt","carbon:calculator","carbon:calculator-check","carbon:calendar","carbon:calendar-add","carbon:calendar-add-alt","carbon:calendar-heat-map","carbon:calendar-settings","carbon:calendar-tools","carbon:calibrate","carbon:calls","carbon:calls-all","carbon:calls-incoming","carbon:camera","carbon:camera-action","carbon:campsite","carbon:car","carbon:car-front","carbon:carbon","carbon:carbon-accounting","carbon:carbon-for-ibm-dotcom","carbon:carbon-for-ibm-product","carbon:carbon-for-mobile","carbon:carbon-for-salesforce","carbon:carbon-ui-builder","carbon:caret-down","carbon:caret-left","carbon:caret-right","carbon:caret-sort","carbon:caret-sort-down","carbon:caret-sort-up","carbon:caret-up","carbon:carousel-horizontal","carbon:carousel-vertical","carbon:catalog","carbon:catalog-publish","carbon:categories","carbon:category","carbon:category-add","carbon:category-and","carbon:category-new","carbon:category-new-each","carbon:ccx","carbon:cd-archive","carbon:cd-create-archive","carbon:cd-create-exchange","carbon:cda","carbon:cell-tower","carbon:center-circle","carbon:center-square","carbon:center-to-fit","carbon:certificate","carbon:certificate-check","carbon:change-catalog","carbon:character-decimal","carbon:character-fraction","carbon:character-integer","carbon:character-lower-case","carbon:character-negative-number","carbon:character-patterns","carbon:character-sentence-case","carbon:character-upper-case","carbon:character-whole-number","carbon:charging-station","carbon:charging-station-filled","carbon:chart-3d","carbon:chart-area","carbon:chart-area-smooth","carbon:chart-area-stepper","carbon:chart-average","carbon:chart-bar","carbon:chart-bar-floating","carbon:chart-bar-overlay","carbon:chart-bar-stacked","carbon:chart-bar-target","carbon:chart-bubble","carbon:chart-bubble-packed","carbon:chart-bullet","carbon:chart-candlestick","carbon:chart-cluster-bar","carbon:chart-column","carbon:chart-column-floating","carbon:chart-column-target","carbon:chart-combo","carbon:chart-combo-stacked","carbon:chart-custom","carbon:chart-dual-y-axis","carbon:chart-error-bar","carbon:chart-error-bar-alt","carbon:chart-evaluation","carbon:chart-high-low","carbon:chart-histogram","carbon:chart-line","carbon:chart-line-data","carbon:chart-line-smooth","carbon:chart-logistic-regression","carbon:chart-marimekko","carbon:chart-maximum","carbon:chart-median","carbon:chart-minimum","carbon:chart-multi-line","carbon:chart-multitype","carbon:chart-network","carbon:chart-parallel","carbon:chart-pie","carbon:chart-planning-waterfall","carbon:chart-point","carbon:chart-population","carbon:chart-radar","carbon:chart-radial","carbon:chart-relationship","carbon:chart-ring","carbon:chart-river","carbon:chart-rose","carbon:chart-scatter","carbon:chart-spiral","carbon:chart-stacked","carbon:chart-stepper","carbon:chart-sunburst","carbon:chart-t-sne","carbon:chart-treemap","carbon:chart-venn-diagram","carbon:chart-violin-plot","carbon:chart-waterfall","carbon:chart-win-loss","carbon:chat","carbon:chat-bot","carbon:chat-launch","carbon:chat-off","carbon:chat-operational","carbon:checkbox","carbon:checkbox-checked","carbon:checkbox-checked-filled","carbon:checkbox-indeterminate","carbon:checkbox-indeterminate-filled","carbon:checkbox-undeterminate","carbon:checkbox-undeterminate-filled","carbon:checkmark","carbon:checkmark-filled","carbon:checkmark-filled-error","carbon:checkmark-filled-warning","carbon:checkmark-outline","carbon:checkmark-outline-error","carbon:checkmark-outline-warning","carbon:chemistry","carbon:chemistry-reference","carbon:chevron-down","carbon:chevron-down-outline","carbon:chevron-left","carbon:chevron-mini","carbon:chevron-right","carbon:chevron-sort","carbon:chevron-sort-down","carbon:chevron-sort-up","carbon:chevron-up","carbon:chevron-up-outline","carbon:chip","carbon:choices","carbon:choose-item","carbon:choropleth-map","carbon:cics-cmas","carbon:cics-db2-connection","carbon:cics-explorer","carbon:cics-program","carbon:cics-region","carbon:cics-region-alt","carbon:cics-region-routing","carbon:cics-region-target","carbon:cics-sit","carbon:cics-sit-overrides","carbon:cics-system-group","carbon:cics-transaction-server-zos","carbon:cics-wui-region","carbon:cicsplex","carbon:circle-dash","carbon:circle-filled","carbon:circle-measurement","carbon:circle-packing","carbon:circle-solid","carbon:circuit-composer","carbon:classification","carbon:classifier-language","carbon:clean","carbon:close","carbon:close-filled","carbon:close-large","carbon:close-outline","carbon:closed-caption","carbon:closed-caption-alt","carbon:closed-caption-filled","carbon:cloud","carbon:cloud-alerting","carbon:cloud-app","carbon:cloud-auditing","carbon:cloud-ceiling","carbon:cloud-data-ops","carbon:cloud-download","carbon:cloud-foundry-1","carbon:cloud-foundry-2","carbon:cloud-lightning","carbon:cloud-logging","carbon:cloud-monitoring","carbon:cloud-offline","carbon:cloud-rain","carbon:cloud-registry","carbon:cloud-satellite","carbon:cloud-satellite-config","carbon:cloud-satellite-link","carbon:cloud-satellite-services","carbon:cloud-service-management","carbon:cloud-services","carbon:cloud-snow","carbon:cloud-upload","carbon:cloudy","carbon:cobb-angle","carbon:code","carbon:code-hide","carbon:code-reference","carbon:code-signing-service","carbon:cognitive","carbon:collaborate","carbon:collapse-all","carbon:collapse-categories","carbon:color-palette","carbon:color-switch","carbon:column","carbon:column-delete","carbon:column-dependency","carbon:column-insert","carbon:commit","carbon:communication-unified","carbon:compare","carbon:compass","carbon:composer-edit","carbon:concept","carbon:condition-point","carbon:condition-wait-point","carbon:connect","carbon:connect-recursive","carbon:connect-reference","carbon:connect-source","carbon:connect-target","carbon:connection-receive","carbon:connection-send","carbon:connection-signal","carbon:connection-signal-off","carbon:connection-two-way","carbon:construction","carbon:container-registry","carbon:container-services","carbon:container-software","carbon:content-delivery-network","carbon:content-view","carbon:continue","carbon:continue-filled","carbon:continuous-deployment","carbon:continuous-integration","carbon:contour-draw","carbon:contour-edit","carbon:contour-finding","carbon:contrast","carbon:convert-to-cloud","carbon:cookie","carbon:copy","carbon:copy-file","carbon:copy-link","carbon:corn","carbon:corner","carbon:coronavirus","carbon:cost","carbon:cost-total","carbon:cough","carbon:course","carbon:covariate","carbon:credentials","carbon:crop","carbon:crop-growth","carbon:crop-health","carbon:cross-reference","carbon:cross-tab","carbon:crossroads","carbon:crowd-report","carbon:crowd-report-filled","carbon:csv","carbon:cu1","carbon:cu3","carbon:cube","carbon:cube-view","carbon:currency","carbon:currency-baht","carbon:currency-dollar","carbon:currency-euro","carbon:currency-lira","carbon:currency-pound","carbon:currency-ruble","carbon:currency-rupee","carbon:currency-shekel","carbon:currency-won","carbon:currency-yen","carbon:cursor-1","carbon:cursor-2","carbon:customer","carbon:customer-service","carbon:cut","carbon:cut-in-half","carbon:cut-out","carbon:cy","carbon:cyclist","carbon:cz","carbon:dashboard","carbon:dashboard-reference","carbon:data-1","carbon:data-2","carbon:data-accessor","carbon:data-analytics","carbon:data-backup","carbon:data-base","carbon:data-base-alt","carbon:data-bin","carbon:data-blob","carbon:data-categorical","carbon:data-center","carbon:data-check","carbon:data-class","carbon:data-collection","carbon:data-connected","carbon:data-definition","carbon:data-diode","carbon:data-enrichment","carbon:data-enrichment-add","carbon:data-error","carbon:data-format","carbon:data-player","carbon:data-quality-definition","carbon:data-reference","carbon:data-refinery","carbon:data-refinery-reference","carbon:data-regular","carbon:data-set","carbon:data-share","carbon:data-structured","carbon:data-table","carbon:data-table-reference","carbon:data-unreal","carbon:data-unstructured","carbon:data-view","carbon:data-view-alt","carbon:data-vis-1","carbon:data-vis-2","carbon:data-vis-3","carbon:data-vis-4","carbon:data-volume","carbon:data-volume-alt","carbon:database-datastax","carbon:database-elastic","carbon:database-enterprise-db2","carbon:database-enterprisedb","carbon:database-etcd","carbon:database-messaging","carbon:database-mongodb","carbon:database-postgresql","carbon:database-rabbit","carbon:database-redis","carbon:datastore","carbon:db2-buffer-pool","carbon:db2-data-sharing-group","carbon:db2-database","carbon:debug","carbon:decision-tree","carbon:delete","carbon:delivery","carbon:delivery-add","carbon:delivery-parcel","carbon:delivery-truck","carbon:demo","carbon:denominate","carbon:departure","carbon:deploy","carbon:deploy-rules","carbon:deployment-pattern","carbon:deployment-policy","carbon:deployment-unit-data","carbon:deployment-unit-execution","carbon:deployment-unit-installation","carbon:deployment-unit-presentation","carbon:deployment-unit-technical-data","carbon:deployment-unit-technical-execution","carbon:deployment-unit-technical-installation","carbon:deployment-unit-technical-presentation","carbon:desk-adjustable","carbon:development","carbon:devices","carbon:devices-apps","carbon:dew-point","carbon:dew-point-filled","carbon:diagram","carbon:diagram-reference","carbon:dicom-6000","carbon:dicom-overlay","carbon:direct-link","carbon:direction-bear-right-01","carbon:direction-bear-right-01-filled","carbon:direction-bear-right-02","carbon:direction-bear-right-02-filled","carbon:direction-curve","carbon:direction-curve-filled","carbon:direction-fork","carbon:direction-fork-filled","carbon:direction-loop-left","carbon:direction-loop-left-filled","carbon:direction-loop-right","carbon:direction-loop-right-filled","carbon:direction-merge","carbon:direction-merge-filled","carbon:direction-right-01","carbon:direction-right-01-filled","carbon:direction-right-02","carbon:direction-right-02-filled","carbon:direction-rotary-first-right","carbon:direction-rotary-first-right-filled","carbon:direction-rotary-right","carbon:direction-rotary-right-filled","carbon:direction-rotary-straight","carbon:direction-rotary-straight-filled","carbon:direction-sharp-turn","carbon:direction-sharp-turn-filled","carbon:direction-straight","carbon:direction-straight-filled","carbon:direction-straight-right","carbon:direction-straight-right-filled","carbon:direction-u-turn","carbon:direction-u-turn-filled","carbon:directory-domain","carbon:distribute-horizontal-center","carbon:distribute-horizontal-left","carbon:distribute-horizontal-right","carbon:distribute-vertical-bottom","carbon:distribute-vertical-center","carbon:distribute-vertical-top","carbon:dna","carbon:dns-services","carbon:doc","carbon:document","carbon:document-add","carbon:document-attachment","carbon:document-audio","carbon:document-blank","carbon:document-download","carbon:document-epdf","carbon:document-export","carbon:document-horizontal","carbon:document-import","carbon:document-multiple-01","carbon:document-multiple-02","carbon:document-pdf","carbon:document-preliminary","carbon:document-protected","carbon:document-security","carbon:document-sentiment","carbon:document-signed","carbon:document-sketch","carbon:document-subtract","carbon:document-tasks","carbon:document-unknown","carbon:document-unprotected","carbon:document-vertical","carbon:document-video","carbon:document-view","carbon:document-word-processor","carbon:document-word-processor-reference","carbon:dog-walker","carbon:dot-mark","carbon:double-integer","carbon:down-to-bottom","carbon:download","carbon:download-study","carbon:downstream","carbon:drag-horizontal","carbon:drag-vertical","carbon:draggable","carbon:draw","carbon:drill-back","carbon:drill-down","carbon:drill-through","carbon:drink-01","carbon:drink-02","carbon:driver-analysis","carbon:drone","carbon:drone-delivery","carbon:drone-front","carbon:drone-video","carbon:drop-photo","carbon:drop-photo-filled","carbon:drought","carbon:dvr","carbon:earth","carbon:earth-americas","carbon:earth-americas-filled","carbon:earth-europe-africa","carbon:earth-europe-africa-filled","carbon:earth-filled","carbon:earth-southeast-asia","carbon:earth-southeast-asia-filled","carbon:earthquake","carbon:edge-cluster","carbon:edge-device","carbon:edge-enhancement","carbon:edge-enhancement-01","carbon:edge-enhancement-02","carbon:edge-enhancement-03","carbon:edge-node","carbon:edge-node-alt","carbon:edge-service","carbon:edit","carbon:edit-filter","carbon:edit-off","carbon:edt-loop","carbon:education","carbon:email","carbon:email-new","carbon:encryption","carbon:energy-renewable","carbon:enterprise","carbon:equal-approximately","carbon:equalizer","carbon:erase","carbon:erase-3d","carbon:error","carbon:error-filled","carbon:error-outline","carbon:event","carbon:event-change","carbon:event-incident","carbon:event-schedule","carbon:event-warning","carbon:events","carbon:events-alt","carbon:exam-mode","carbon:executable-program","carbon:exit","carbon:expand-all","carbon:expand-categories","carbon:explore","carbon:export","carbon:eyedropper","carbon:face-activated","carbon:face-activated-add","carbon:face-activated-filled","carbon:face-add","carbon:face-cool","carbon:face-dissatisfied","carbon:face-dissatisfied-filled","carbon:face-dizzy","carbon:face-dizzy-filled","carbon:face-mask","carbon:face-neutral","carbon:face-neutral-filled","carbon:face-pending","carbon:face-pending-filled","carbon:face-satisfied","carbon:face-satisfied-filled","carbon:face-wink","carbon:face-wink-filled","carbon:factor","carbon:fade","carbon:favorite","carbon:favorite-filled","carbon:favorite-half","carbon:fetch-upload","carbon:fetch-upload-cloud","carbon:file-storage","carbon:filter","carbon:filter-edit","carbon:filter-remove","carbon:filter-reset","carbon:finance","carbon:fingerprint-recognition","carbon:fire","carbon:firewall","carbon:firewall-classic","carbon:fish","carbon:fish-multiple","carbon:fit-to-height","carbon:fit-to-screen","carbon:fit-to-width","carbon:flag","carbon:flag-filled","carbon:flagging-taxi","carbon:flash","carbon:flash-filled","carbon:flash-off","carbon:flash-off-filled","carbon:flight-international","carbon:flight-roster","carbon:flight-schedule","carbon:floating-ip","carbon:flood","carbon:flood-warning","carbon:floorplan","carbon:flow","carbon:flow-connection","carbon:flow-data","carbon:flow-logs-vpc","carbon:flow-modeler","carbon:flow-modeler-reference","carbon:flow-stream","carbon:flow-stream-reference","carbon:fog","carbon:folder","carbon:folder-add","carbon:folder-details","carbon:folder-details-reference","carbon:folder-move-to","carbon:folder-off","carbon:folder-open","carbon:folder-parent","carbon:folder-shared","carbon:folders","carbon:forecast-hail","carbon:forecast-hail-30","carbon:forecast-lightning","carbon:forecast-lightning-30","carbon:fork","carbon:forum","carbon:forward-10","carbon:forward-30","carbon:forward-5","carbon:foundation-model","carbon:fragile","carbon:friendship","carbon:fruit-bowl","carbon:function","carbon:function-math","carbon:fusion-blender","carbon:game-console","carbon:game-wireless","carbon:gamification","carbon:gas-station","carbon:gas-station-filled","carbon:gateway","carbon:gateway-api","carbon:gateway-mail","carbon:gateway-public","carbon:gateway-security","carbon:gateway-user-access","carbon:gateway-vpn","carbon:gender-female","carbon:gender-male","carbon:generate-pdf","carbon:gif","carbon:gift","carbon:global-loan-and-trial","carbon:globe","carbon:gradient","carbon:graphical-data-flow","carbon:grid","carbon:group","carbon:group-access","carbon:group-account","carbon:group-objects","carbon:group-objects-new","carbon:group-objects-save","carbon:group-presentation","carbon:group-resource","carbon:group-security","carbon:growth","carbon:gui","carbon:gui-management","carbon:h","carbon:hail","carbon:hanging-protocol","carbon:harbor","carbon:hardware-security-module","carbon:hashtag","carbon:haze","carbon:haze-night","carbon:hd","carbon:hd-filled","carbon:hdr","carbon:headphones","carbon:headset","carbon:health-cross","carbon:hearing","carbon:heat-map","carbon:heat-map-02","carbon:heat-map-03","carbon:heat-map-stocks","carbon:helicopter","carbon:help","carbon:help-desk","carbon:help-filled","carbon:hinton-plot","carbon:hl7-attributes","carbon:hole-filling","carbon:hole-filling-cursor","carbon:home","carbon:horizontal-view","carbon:hospital","carbon:hospital-bed","carbon:hotel","carbon:hourglass","carbon:html","carbon:html-reference","carbon:http","carbon:humidity","carbon:humidity-alt","carbon:hurricane","carbon:hybrid-networking","carbon:hybrid-networking-alt","carbon:ibm-ai-on-z","carbon:ibm-aiops-insights","carbon:ibm-bluepay","carbon:ibm-cloud","carbon:ibm-cloud-app-id","carbon:ibm-cloud-bare-metal-server","carbon:ibm-cloud-bare-metal-servers-vpc","carbon:ibm-cloud-citrix-daas","carbon:ibm-cloud-continuous-delivery","carbon:ibm-cloud-dedicated-host","carbon:ibm-cloud-direct-link-1-connect","carbon:ibm-cloud-direct-link-1-dedicated","carbon:ibm-cloud-direct-link-1-dedicated-hosting","carbon:ibm-cloud-direct-link-1-exchange","carbon:ibm-cloud-direct-link-2-connect","carbon:ibm-cloud-direct-link-2-dedicated","carbon:ibm-cloud-direct-link-2-dedicated-hosting","carbon:ibm-cloud-event-notification","carbon:ibm-cloud-event-streams","carbon:ibm-cloud-for-education","carbon:ibm-cloud-hpc","carbon:ibm-cloud-hsm","carbon:ibm-cloud-hyper-protect-crypto-services","carbon:ibm-cloud-hyper-protect-dbaas","carbon:ibm-cloud-hyper-protect-vs","carbon:ibm-cloud-internet-services","carbon:ibm-cloud-ipsec-vpn","carbon:ibm-cloud-key-protect","carbon:ibm-cloud-kubernetes-service","carbon:ibm-cloud-logging","carbon:ibm-cloud-mass-data-migration","carbon:ibm-cloud-pak-applications","carbon:ibm-cloud-pak-business-automation","carbon:ibm-cloud-pak-data","carbon:ibm-cloud-pak-integration","carbon:ibm-cloud-pak-manta-automated-data-lineage","carbon:ibm-cloud-pak-multicloud-mgmt","carbon:ibm-cloud-pak-netezza","carbon:ibm-cloud-pak-network-automation","carbon:ibm-cloud-pak-security","carbon:ibm-cloud-pak-system","carbon:ibm-cloud-pak-watson-aiops","carbon:ibm-cloud-pal","carbon:ibm-cloud-privileged-access-gateway","carbon:ibm-cloud-projects","carbon:ibm-cloud-resiliency","carbon:ibm-cloud-secrets-manager","carbon:ibm-cloud-security-compliance-center","carbon:ibm-cloud-security-compliance-center-workload-protection","carbon:ibm-cloud-subnets","carbon:ibm-cloud-sysdig-secure","carbon:ibm-cloud-transit-gateway","carbon:ibm-cloud-virtual-server-classic","carbon:ibm-cloud-virtual-server-vpc","carbon:ibm-cloud-vpc","carbon:ibm-cloud-vpc-endpoints","carbon:ibm-cloudant","carbon:ibm-content-services","carbon:ibm-data-product-exchange","carbon:ibm-data-replication","carbon:ibm-datastage","carbon:ibm-db2","carbon:ibm-db2-alt","carbon:ibm-db2-warehouse","carbon:ibm-dynamic-route-server","carbon:ibm-engineering-systems-design-rhapsody-model-manager","carbon:ibm-engineering-systems-design-rhapsody-sn1","carbon:ibm-engineering-systems-design-rhapsody-sn2","carbon:ibm-event-automation","carbon:ibm-event-endpoint-mgmt","carbon:ibm-event-processing","carbon:ibm-event-streams","carbon:ibm-ibv","carbon:ibm-instana","carbon:ibm-match-360","carbon:ibm-mq","carbon:ibm-open-enterprise-languages","carbon:ibm-openshift-container-platform-on-vpc-for-regulated-industries","carbon:ibm-power-vs","carbon:ibm-power-vs-private-cloud","carbon:ibm-power-with-vpc","carbon:ibm-private-path-services","carbon:ibm-process-mining","carbon:ibm-saas-console","carbon:ibm-sap-on-power","carbon:ibm-secure-infrastructure-on-vpc-for-regulated-industries","carbon:ibm-security","carbon:ibm-security-services","carbon:ibm-telehealth","carbon:ibm-tenet","carbon:ibm-toolchain","carbon:ibm-turbonomic","carbon:ibm-vpn-for-vpc","carbon:ibm-vsi-on-vpc-for-regulated-industries","carbon:ibm-watson-assistant","carbon:ibm-watson-discovery","carbon:ibm-watson-knowledge-catalog","carbon:ibm-watson-knowledge-studio","carbon:ibm-watson-language-translator","carbon:ibm-watson-machine-learning","carbon:ibm-watson-natural-language-classifier","carbon:ibm-watson-natural-language-understanding","carbon:ibm-watson-openscale","carbon:ibm-watson-orders","carbon:ibm-watson-query","carbon:ibm-watson-speech-to-text","carbon:ibm-watson-studio","carbon:ibm-watson-text-to-speech","carbon:ibm-watson-tone-analyzer","carbon:ibm-watsonx-assistant","carbon:ibm-watsonx-code-assistant","carbon:ibm-watsonx-code-assistant-for-z","carbon:ibm-watsonx-code-assistant-for-z-refactor","carbon:ibm-watsonx-orchestrate","carbon:ibm-wazi-deploy","carbon:ibm-z-cloud-mod-stack","carbon:ibm-z-cloud-provisioning","carbon:ibm-z-environments-dev-sec-ops","carbon:ibm-z-os","carbon:ibm-z-os-ai-control-interface","carbon:ibm-z-os-containers","carbon:ibm-z-os-package-manager","carbon:ibm-z-processor-capacity-reference","carbon:ica-2d","carbon:ice-accretion","carbon:ice-vision","carbon:id","carbon:id-management","carbon:idea","carbon:identification","carbon:image","carbon:image-copy","carbon:image-medical","carbon:image-reference","carbon:image-search","carbon:image-search-alt","carbon:image-service","carbon:import-export","carbon:improve-relevance","carbon:in-progress","carbon:in-progress-error","carbon:in-progress-warning","carbon:incomplete","carbon:incomplete-cancel","carbon:incomplete-error","carbon:incomplete-warning","carbon:increase-level","carbon:industry","carbon:infinity","carbon:infinity-symbol","carbon:information","carbon:information-disabled","carbon:information-filled","carbon:information-square","carbon:information-square-filled","carbon:infrastructure-classic","carbon:insert","carbon:insert-page","carbon:insert-syntax","carbon:inspection","carbon:instance-bx","carbon:instance-classic","carbon:instance-cx","carbon:instance-mx","carbon:instance-virtual","carbon:integration","carbon:intent-request-active","carbon:intent-request-create","carbon:intent-request-heal","carbon:intent-request-inactive","carbon:intent-request-scale-in","carbon:intent-request-scale-out","carbon:intent-request-uninstall","carbon:intent-request-upgrade","carbon:interactions","carbon:interactive-segmentation-cursor","carbon:intersect","carbon:intrusion-prevention","carbon:inventory-management","carbon:iot-connect","carbon:iot-platform","carbon:ip","carbon:iso","carbon:iso-filled","carbon:iso-outline","carbon:join-full","carbon:join-inner","carbon:join-left","carbon:join-outer","carbon:join-right","carbon:jpg","carbon:js-error","carbon:json","carbon:json-reference","carbon:jump-link","carbon:keep-dry","carbon:keyboard","carbon:keyboard-off","carbon:kubernetes","carbon:kubernetes-ip-address","carbon:kubernetes-pod","carbon:label","carbon:language","carbon:laptop","carbon:lasso","carbon:lasso-polygon","carbon:launch","carbon:launch-study-1","carbon:launch-study-2","carbon:launch-study-3","carbon:layers","carbon:legend","carbon:letter-aa","carbon:letter-aa-large","carbon:letter-bb","carbon:letter-cc","carbon:letter-dd","carbon:letter-ee","carbon:letter-ff","carbon:letter-gg","carbon:letter-hh","carbon:letter-ii","carbon:letter-jj","carbon:letter-kk","carbon:letter-ll","carbon:letter-mm","carbon:letter-nn","carbon:letter-oo","carbon:letter-pp","carbon:letter-qq","carbon:letter-rr","carbon:letter-ss","carbon:letter-tt","carbon:letter-uu","carbon:letter-vv","carbon:letter-ww","carbon:letter-xx","carbon:letter-yy","carbon:letter-zz","carbon:license","carbon:license-draft","carbon:license-global","carbon:license-maintenance","carbon:license-maintenance-draft","carbon:license-third-party","carbon:license-third-party-draft","carbon:lifesaver","carbon:light","carbon:light-filled","carbon:lightning","carbon:link","carbon:linux","carbon:linux-alt","carbon:list","carbon:list-boxes","carbon:list-bulleted","carbon:list-checked","carbon:list-checked-mirror","carbon:list-dropdown","carbon:list-numbered","carbon:list-numbered-mirror","carbon:load-balancer-application","carbon:load-balancer-classic","carbon:load-balancer-global","carbon:load-balancer-listener","carbon:load-balancer-local","carbon:load-balancer-network","carbon:load-balancer-pool","carbon:load-balancer-vpc","carbon:location","carbon:location-company","carbon:location-company-filled","carbon:location-current","carbon:location-filled","carbon:location-hazard","carbon:location-hazard-filled","carbon:location-heart","carbon:location-heart-filled","carbon:location-person","carbon:location-person-filled","carbon:location-save","carbon:location-star","carbon:location-star-filled","carbon:locked","carbon:logical-partition","carbon:login","carbon:logo-angular","carbon:logo-ansible-community","carbon:logo-delicious","carbon:logo-digg","carbon:logo-discord","carbon:logo-facebook","carbon:logo-figma","carbon:logo-flickr","carbon:logo-github","carbon:logo-gitlab","carbon:logo-glassdoor","carbon:logo-google","carbon:logo-instagram","carbon:logo-invision","carbon:logo-jupyter","carbon:logo-keybase","carbon:logo-kubernetes","carbon:logo-linkedin","carbon:logo-livestream","carbon:logo-mastodon","carbon:logo-medium","carbon:logo-npm","carbon:logo-openshift","carbon:logo-pinterest","carbon:logo-python","carbon:logo-quora","carbon:logo-r-script","carbon:logo-react","carbon:logo-red-hat-ansible","carbon:logo-sketch","carbon:logo-skype","carbon:logo-slack","carbon:logo-snapchat","carbon:logo-stumbleupon","carbon:logo-svelte","carbon:logo-tumblr","carbon:logo-twitter","carbon:logo-vmware","carbon:logo-vmware-alt","carbon:logo-vue","carbon:logo-wechat","carbon:logo-x","carbon:logo-xing","carbon:logo-yelp","carbon:logo-youtube","carbon:logout","carbon:loop","carbon:mac","carbon:mac-command","carbon:mac-option","carbon:mac-shift","carbon:machine-learning","carbon:machine-learning-model","carbon:magic-wand","carbon:magic-wand-filled","carbon:magnify","carbon:mail-all","carbon:mail-reply","carbon:mammogram","carbon:mammogram-stacked","carbon:manage-protection","carbon:managed-solutions","carbon:map","carbon:map-boundary","carbon:map-boundary-vegetation","carbon:map-center","carbon:map-identify","carbon:marine-warning","carbon:math-curve","carbon:matrix","carbon:maximize","carbon:media-cast","carbon:media-library","carbon:media-library-filled","carbon:medication","carbon:medication-alert","carbon:medication-reminder","carbon:menu","carbon:message-queue","carbon:meter","carbon:meter-alt","carbon:microphone","carbon:microphone-filled","carbon:microphone-off","carbon:microphone-off-filled","carbon:microscope","carbon:microservices-1","carbon:microservices-2","carbon:migrate","carbon:migrate-alt","carbon:milestone","carbon:military-camp","carbon:minimize","carbon:misuse","carbon:misuse-alt","carbon:misuse-outline","carbon:mixed-rain-hail","carbon:mobile","carbon:mobile-add","carbon:mobile-audio","carbon:mobile-check","carbon:mobile-crash","carbon:mobile-download","carbon:mobile-event","carbon:mobile-landscape","carbon:mobile-request","carbon:mobile-session","carbon:mobile-view","carbon:mobile-view-orientation","carbon:mobility-services","carbon:model","carbon:model-alt","carbon:model-builder","carbon:model-builder-reference","carbon:model-reference","carbon:model-tuned","carbon:money","carbon:monster","carbon:monument","carbon:moon","carbon:moonrise","carbon:moonset","carbon:mostly-cloudy","carbon:mostly-cloudy-night","carbon:mountain","carbon:mov","carbon:move","carbon:movement","carbon:mp3","carbon:mp4","carbon:mpeg","carbon:mpg2","carbon:music","carbon:music-add","carbon:music-remove","carbon:mysql","carbon:name-space","carbon:navaid-civil","carbon:navaid-dme","carbon:navaid-helipad","carbon:navaid-military","carbon:navaid-military-civil","carbon:navaid-ndb","carbon:navaid-ndb-dme","carbon:navaid-private","carbon:navaid-seaplane","carbon:navaid-tacan","carbon:navaid-vhfor","carbon:navaid-vor","carbon:navaid-vordme","carbon:navaid-vortac","carbon:need","carbon:network-1","carbon:network-2","carbon:network-3","carbon:network-3-reference","carbon:network-4","carbon:network-4-reference","carbon:network-admin-control","carbon:network-enterprise","carbon:network-interface","carbon:network-overlay","carbon:network-public","carbon:new-tab","carbon:next-filled","carbon:next-outline","carbon:no-image","carbon:no-ticket","carbon:nominal","carbon:nominate","carbon:non-certified","carbon:noodle-bowl","carbon:not-available","carbon:not-sent","carbon:not-sent-filled","carbon:notebook","carbon:notebook-reference","carbon:notification","carbon:notification-filled","carbon:notification-new","carbon:notification-off","carbon:notification-off-filled","carbon:number-0","carbon:number-1","carbon:number-2","carbon:number-3","carbon:number-4","carbon:number-5","carbon:number-6","carbon:number-7","carbon:number-8","carbon:number-9","carbon:number-small-0","carbon:number-small-1","carbon:number-small-2","carbon:number-small-3","carbon:number-small-4","carbon:number-small-5","carbon:number-small-6","carbon:number-small-7","carbon:number-small-8","carbon:number-small-9","carbon:object-storage","carbon:object-storage-alt","carbon:observed-hail","carbon:observed-lightning","carbon:omega","carbon:opacity","carbon:open-panel-bottom","carbon:open-panel-filled-bottom","carbon:open-panel-filled-left","carbon:open-panel-filled-right","carbon:open-panel-filled-top","carbon:open-panel-left","carbon:open-panel-right","carbon:open-panel-top","carbon:operation","carbon:operation-gauge","carbon:operation-if","carbon:operations-field","carbon:operations-record","carbon:order-details","carbon:ordinal","carbon:outage","carbon:outlook-severe","carbon:overflow-menu-horizontal","carbon:overflow-menu-vertical","carbon:overlay","carbon:package","carbon:package-text-analysis","carbon:page-break","carbon:page-first","carbon:page-last","carbon:page-number","carbon:page-scroll","carbon:paint-brush","carbon:paint-brush-alt","carbon:palm-tree","carbon:pan-horizontal","carbon:pan-vertical","carbon:panel-expansion","carbon:paragraph","carbon:parameter","carbon:parent-child","carbon:partition-auto","carbon:partition-collection","carbon:partition-repartition","carbon:partition-same","carbon:partition-specific","carbon:partly-cloudy","carbon:partly-cloudy-night","carbon:partnership","carbon:passenger-drinks","carbon:passenger-plus","carbon:password","carbon:paste","carbon:pause","carbon:pause-filled","carbon:pause-future","carbon:pause-outline","carbon:pause-outline-filled","carbon:pause-past","carbon:pcn-e-node","carbon:pcn-military","carbon:pcn-p-node","carbon:pcn-z-node","carbon:pdf","carbon:pdf-reference","carbon:pedestrian","carbon:pedestrian-child","carbon:pedestrian-family","carbon:pen","carbon:pen-fountain","carbon:pending","carbon:pending-filled","carbon:percentage","carbon:percentage-filled","carbon:person","carbon:person-favorite","carbon:pest","carbon:pet-image-b","carbon:pet-image-o","carbon:phone","carbon:phone-application","carbon:phone-block","carbon:phone-block-filled","carbon:phone-filled","carbon:phone-incoming","carbon:phone-incoming-filled","carbon:phone-ip","carbon:phone-off","carbon:phone-off-filled","carbon:phone-outgoing","carbon:phone-outgoing-filled","carbon:phone-settings","carbon:phone-voice","carbon:phone-voice-filled","carbon:phrase-sentiment","carbon:picnic-area","carbon:piggy-bank","carbon:piggy-bank-slot","carbon:pills","carbon:pills-add","carbon:pills-subtract","carbon:pin","carbon:pin-filled","carbon:plan","carbon:plane","carbon:plane-private","carbon:plane-sea","carbon:platforms","carbon:play","carbon:play-filled","carbon:play-filled-alt","carbon:play-outline","carbon:play-outline-filled","carbon:playlist","carbon:plug","carbon:plug-filled","carbon:png","carbon:point-of-presence","carbon:pointer-text","carbon:police","carbon:policy","carbon:popup","carbon:port-input","carbon:port-output","carbon:portfolio","carbon:power","carbon:ppt","carbon:presentation-file","carbon:pressure","carbon:pressure-filled","carbon:previous-filled","carbon:previous-outline","carbon:printer","carbon:process","carbon:process-automate","carbon:product","carbon:progress-bar","carbon:progress-bar-round","carbon:promote","carbon:prompt-session","carbon:prompt-template","carbon:property-relationship","carbon:purchase","carbon:qc-launch","carbon:qq-plot","carbon:qr-code","carbon:quadrant-plot","carbon:query","carbon:query-queue","carbon:queued","carbon:quotes","carbon:radar","carbon:radar-enhanced","carbon:radar-weather","carbon:radio","carbon:radio-button","carbon:radio-button-checked","carbon:radio-combat","carbon:radio-push-to-talk","carbon:rain","carbon:rain-drizzle","carbon:rain-drop","carbon:rain-heavy","carbon:rain-scattered","carbon:rain-scattered-night","carbon:raw","carbon:receipt","carbon:recently-viewed","carbon:recommend","carbon:recording","carbon:recording-filled","carbon:recording-filled-alt","carbon:recycle","carbon:redo","carbon:ref-evapotranspiration","carbon:reference-architecture","carbon:reflect-horizontal","carbon:reflect-vertical","carbon:region-analysis-area","carbon:region-analysis-volume","carbon:registration","carbon:reminder","carbon:reminder-medical","carbon:renew","carbon:repeat","carbon:repeat-one","carbon:replicate","carbon:reply","carbon:reply-all","carbon:repo-artifact","carbon:repo-source-code","carbon:report","carbon:report-data","carbon:request-quote","carbon:research-bloch-sphere","carbon:research-hinton-plot","carbon:research-matrix","carbon:reset","carbon:reset-alt","carbon:restart","carbon:restaurant","carbon:restaurant-fine","carbon:result","carbon:result-draft","carbon:result-new","carbon:result-old","carbon:retry-failed","carbon:return","carbon:review","carbon:rewind-10","carbon:rewind-30","carbon:rewind-5","carbon:right-panel-close","carbon:right-panel-close-filled","carbon:right-panel-open","carbon:right-panel-open-filled","carbon:road","carbon:road-weather","carbon:roadmap","carbon:rocket","carbon:rotate","carbon:rotate-180","carbon:rotate-360","carbon:rotate-clockwise","carbon:rotate-clockwise-alt","carbon:rotate-clockwise-alt-filled","carbon:rotate-clockwise-filled","carbon:rotate-counterclockwise","carbon:rotate-counterclockwise-alt","carbon:rotate-counterclockwise-alt-filled","carbon:rotate-counterclockwise-filled","carbon:router","carbon:router-voice","carbon:router-wifi","carbon:row","carbon:row-collapse","carbon:row-delete","carbon:row-expand","carbon:row-insert","carbon:rss","carbon:rule","carbon:rule-cancelled","carbon:rule-data-quality","carbon:rule-draft","carbon:rule-filled","carbon:rule-locked","carbon:rule-partial","carbon:rule-test","carbon:ruler","carbon:ruler-alt","carbon:run","carbon:run-mirror","carbon:running","carbon:s","carbon:s-alt","carbon:sailboat-coastal","carbon:sailboat-offshore","carbon:sales-ops","carbon:sankey-diagram","carbon:sankey-diagram-alt","carbon:satellite","carbon:satellite-radar","carbon:satellite-weather","carbon:save","carbon:save-annotation","carbon:save-image","carbon:save-model","carbon:save-series","carbon:scale","carbon:scales","carbon:scales-tipped","carbon:scalpel","carbon:scalpel-cursor","carbon:scalpel-lasso","carbon:scalpel-select","carbon:scan","carbon:scan-alt","carbon:scan-disabled","carbon:scatter-matrix","carbon:schematics","carbon:scis-control-tower","carbon:scis-transparent-supply","carbon:scooter","carbon:scooter-front","carbon:screen","carbon:screen-map","carbon:screen-map-set","carbon:screen-off","carbon:script","carbon:script-reference","carbon:sdk","carbon:search","carbon:search-advanced","carbon:search-locate","carbon:search-locate-mirror","carbon:security","carbon:security-services","carbon:select-01","carbon:select-02","carbon:select-window","carbon:send","carbon:send-alt","carbon:send-alt-filled","carbon:send-backward","carbon:send-filled","carbon:send-to-back","carbon:server-dns","carbon:server-proxy","carbon:server-time","carbon:service-desk","carbon:service-id","carbon:service-levels","carbon:session-border-control","carbon:settings","carbon:settings-adjust","carbon:settings-check","carbon:settings-edit","carbon:settings-services","carbon:settings-view","carbon:shape-except","carbon:shape-exclude","carbon:shape-intersect","carbon:shape-join","carbon:shape-unite","carbon:share","carbon:share-knowledge","carbon:shopping-bag","carbon:shopping-cart","carbon:shopping-cart-arrow-down","carbon:shopping-cart-arrow-up","carbon:shopping-cart-clear","carbon:shopping-cart-error","carbon:shopping-cart-minus","carbon:shopping-cart-plus","carbon:shopping-catalog","carbon:show-data-cards","carbon:shrink-screen","carbon:shrink-screen-filled","carbon:shuffle","carbon:shuttle","carbon:side-panel-close","carbon:side-panel-close-filled","carbon:side-panel-open","carbon:side-panel-open-filled","carbon:sight","carbon:sigma","carbon:signal-strength","carbon:sim-card","carbon:skill-level","carbon:skill-level-advanced","carbon:skill-level-basic","carbon:skill-level-intermediate","carbon:skip-back","carbon:skip-back-filled","carbon:skip-back-outline","carbon:skip-back-outline-filled","carbon:skip-back-outline-solid","carbon:skip-back-solid-filled","carbon:skip-forward","carbon:skip-forward-filled","carbon:skip-forward-outline","carbon:skip-forward-outline-filled","carbon:skip-forward-outline-solid","carbon:skip-forward-solid-filled","carbon:sleet","carbon:slisor","carbon:slm","carbon:smell","carbon:smoke","carbon:smoothing","carbon:smoothing-cursor","carbon:snooze","carbon:snow","carbon:snow-blizzard","carbon:snow-density","carbon:snow-heavy","carbon:snow-scattered","carbon:snow-scattered-night","carbon:snowflake","carbon:soccer","carbon:software-resource","carbon:software-resource-cluster","carbon:software-resource-resource","carbon:soil-moisture","carbon:soil-moisture-field","carbon:soil-moisture-global","carbon:soil-temperature","carbon:soil-temperature-field","carbon:soil-temperature-global","carbon:solar-panel","carbon:sort-ascending","carbon:sort-descending","carbon:sort-remove","carbon:spell-check","carbon:spine-label","carbon:split","carbon:split-discard","carbon:split-screen","carbon:spray-paint","carbon:sprout","carbon:sql","carbon:stack-limitation","carbon:stacked-move","carbon:stacked-scrolling-1","carbon:stacked-scrolling-2","carbon:stamp","carbon:star","carbon:star-filled","carbon:star-half","carbon:star-review","carbon:status-acknowledge","carbon:status-change","carbon:status-partial-fail","carbon:status-resolved","carbon:stay-inside","carbon:stem-leaf-plot","carbon:stethoscope","carbon:stop","carbon:stop-filled","carbon:stop-filled-alt","carbon:stop-outline","carbon:stop-outline-filled","carbon:stop-sign","carbon:stop-sign-filled","carbon:storage-pool","carbon:storage-request","carbon:store","carbon:storm-tracker","carbon:strawberry","carbon:stress-breath-editor","carbon:string-integer","carbon:string-text","carbon:study-next","carbon:study-previous","carbon:study-read","carbon:study-skip","carbon:study-transfer","carbon:study-unread","carbon:study-view","carbon:sub-volume","carbon:subdirectory","carbon:subflow","carbon:subflow-local","carbon:subnet-acl-rules","carbon:subtract","carbon:subtract-alt","carbon:subtract-filled","carbon:subtract-large","carbon:summary-kpi","carbon:summary-kpi-mirror","carbon:sun","carbon:sunny","carbon:sunrise","carbon:sunset","carbon:support-vector-machine","carbon:sustainability","carbon:svg","carbon:swim","carbon:switch-layer-2","carbon:switch-layer-3","carbon:switcher","carbon:sync-settings","carbon:sys-provision","carbon:t","carbon:t-alt","carbon:table","carbon:table-alias","carbon:table-built","carbon:table-of-contents","carbon:table-shortcut","carbon:table-split","carbon:tablet","carbon:tablet-landscape","carbon:tag","carbon:tag-edit","carbon:tag-export","carbon:tag-group","carbon:tag-import","carbon:tag-none","carbon:tank","carbon:task","carbon:task-add","carbon:task-approved","carbon:task-asset-view","carbon:task-complete","carbon:task-location","carbon:task-remove","carbon:task-settings","carbon:task-star","carbon:task-tools","carbon:task-view","carbon:taste","carbon:taxi","carbon:tcp-ip-service","carbon:temperature","carbon:temperature-celsius","carbon:temperature-celsius-alt","carbon:temperature-fahrenheit","carbon:temperature-fahrenheit-alt","carbon:temperature-feels-like","carbon:temperature-frigid","carbon:temperature-hot","carbon:temperature-inversion","carbon:temperature-max","carbon:temperature-min","carbon:temperature-water","carbon:template","carbon:tennis","carbon:tennis-ball","carbon:term","carbon:terminal","carbon:terminal-3270","carbon:test-tool","carbon:text-align-center","carbon:text-align-justify","carbon:text-align-left","carbon:text-align-mixed","carbon:text-align-right","carbon:text-all-caps","carbon:text-annotation-toggle","carbon:text-bold","carbon:text-clear-format","carbon:text-color","carbon:text-creation","carbon:text-fill","carbon:text-font","carbon:text-footnote","carbon:text-highlight","carbon:text-indent","carbon:text-indent-less","carbon:text-indent-more","carbon:text-italic","carbon:text-kerning","carbon:text-leading","carbon:text-line-spacing","carbon:text-link","carbon:text-link-analysis","carbon:text-long-paragraph","carbon:text-mining","carbon:text-mining-applier","carbon:text-new-line","carbon:text-scale","carbon:text-selection","carbon:text-short-paragraph","carbon:text-small-caps","carbon:text-strikethrough","carbon:text-subscript","carbon:text-superscript","carbon:text-tracking","carbon:text-underline","carbon:text-vertical-alignment","carbon:text-wrap","carbon:theater","carbon:this-side-up","carbon:threshold","carbon:thumbnail-1","carbon:thumbnail-2","carbon:thumbnail-preview","carbon:thumbs-down","carbon:thumbs-down-filled","carbon:thumbs-up","carbon:thumbs-up-filled","carbon:thunderstorm","carbon:thunderstorm-scattered","carbon:thunderstorm-scattered-night","carbon:thunderstorm-severe","carbon:thunderstorm-strong","carbon:ticket","carbon:tides","carbon:tif","carbon:time","carbon:time-filled","carbon:time-plot","carbon:timer","carbon:tool-box","carbon:tool-kit","carbon:tools","carbon:tools-alt","carbon:tornado","carbon:tornado-warning","carbon:touch-1","carbon:touch-1-down","carbon:touch-1-down-filled","carbon:touch-1-filled","carbon:touch-2","carbon:touch-2-filled","carbon:touch-interaction","carbon:tour","carbon:traffic-cone","carbon:traffic-event","carbon:traffic-flow","carbon:traffic-flow-incident","carbon:traffic-incident","carbon:traffic-weather-incident","carbon:train","carbon:train-heart","carbon:train-profile","carbon:train-speed","carbon:train-ticket","carbon:train-time","carbon:tram","carbon:transform-binary","carbon:transform-instructions","carbon:transform-language","carbon:transgender","carbon:translate","carbon:transmission-lte","carbon:transpose","carbon:trash-can","carbon:tree","carbon:tree-fall-risk","carbon:tree-view","carbon:tree-view-alt","carbon:trophy","carbon:trophy-filled","carbon:tropical-storm","carbon:tropical-storm-model-tracks","carbon:tropical-storm-tracks","carbon:tropical-warning","carbon:tsq","carbon:tsunami","carbon:tsv","carbon:tuning","carbon:two-factor-authentication","carbon:two-person-lift","carbon:txt","carbon:txt-reference","carbon:type-pattern","carbon:types","carbon:u1","carbon:u2","carbon:u3","carbon:umbrella","carbon:undefined","carbon:undefined-filled","carbon:undo","carbon:ungroup-objects","carbon:unknown","carbon:unknown-filled","carbon:unlink","carbon:unlocked","carbon:unsaved","carbon:up-to-top","carbon:update-now","carbon:upgrade","carbon:upload","carbon:upstream","carbon:url","carbon:usb","carbon:user","carbon:user-access","carbon:user-activity","carbon:user-admin","carbon:user-avatar","carbon:user-avatar-filled","carbon:user-avatar-filled-alt","carbon:user-certification","carbon:user-data","carbon:user-favorite","carbon:user-favorite-alt","carbon:user-favorite-alt-filled","carbon:user-filled","carbon:user-follow","carbon:user-identification","carbon:user-military","carbon:user-multiple","carbon:user-online","carbon:user-profile","carbon:user-profile-alt","carbon:user-role","carbon:user-service-desk","carbon:user-settings","carbon:user-simulation","carbon:user-speaker","carbon:user-sponsor","carbon:user-x-ray","carbon:uv-index","carbon:uv-index-alt","carbon:uv-index-filled","carbon:value-variable","carbon:van","carbon:vegetation-asset","carbon:vegetation-encroachment","carbon:vegetation-height","carbon:vehicle-api","carbon:vehicle-connected","carbon:vehicle-insights","carbon:vehicle-services","carbon:version","carbon:version-major","carbon:version-minor","carbon:version-patch","carbon:vertical-view","carbon:video","carbon:video-add","carbon:video-chat","carbon:video-filled","carbon:video-off","carbon:video-off-filled","carbon:video-player","carbon:view","carbon:view-filled","carbon:view-mode-1","carbon:view-mode-2","carbon:view-next","carbon:view-off","carbon:view-off-filled","carbon:virtual-column","carbon:virtual-column-key","carbon:virtual-desktop","carbon:virtual-machine","carbon:virtual-private-cloud","carbon:virtual-private-cloud-alt","carbon:visual-recognition","carbon:vlan","carbon:vlan-ibm","carbon:vmdk-disk","carbon:voice-activate","carbon:voicemail","carbon:volume-block-storage","carbon:volume-down","carbon:volume-down-alt","carbon:volume-down-filled","carbon:volume-down-filled-alt","carbon:volume-file-storage","carbon:volume-mute","carbon:volume-mute-filled","carbon:volume-object-storage","carbon:volume-up","carbon:volume-up-alt","carbon:volume-up-filled","carbon:volume-up-filled-alt","carbon:vpn","carbon:vpn-connection","carbon:vpn-policy","carbon:wallet","carbon:warning","carbon:warning-alt","carbon:warning-alt-filled","carbon:warning-alt-inverted","carbon:warning-alt-inverted-filled","carbon:warning-diamond","carbon:warning-filled","carbon:warning-hex","carbon:warning-hex-filled","carbon:warning-multiple","carbon:warning-other","carbon:warning-square","carbon:warning-square-filled","carbon:watch","carbon:watson","carbon:watson-machine-learning","carbon:watsonx","carbon:watsonx-ai","carbon:watsonx-data","carbon:watsonx-governance","carbon:wave-direction","carbon:wave-height","carbon:wave-period","carbon:weather-front-cold","carbon:weather-front-stationary","carbon:weather-front-warm","carbon:weather-station","carbon:web-services-cluster","carbon:web-services-container","carbon:web-services-definition","carbon:web-services-service","carbon:web-services-task","carbon:web-services-task-definition-version","carbon:webhook","carbon:websheet","carbon:wheat","carbon:white-paper","carbon:wifi","carbon:wifi-bridge","carbon:wifi-bridge-alt","carbon:wifi-controller","carbon:wifi-not-secure","carbon:wifi-off","carbon:wifi-secure","carbon:wikis","carbon:wind-gusts","carbon:wind-power","carbon:wind-stream","carbon:window-auto","carbon:window-base","carbon:window-black-saturation","carbon:window-overlay","carbon:window-preset","carbon:windy","carbon:windy-dust","carbon:windy-snow","carbon:windy-strong","carbon:winter-warning","carbon:wintry-mix","carbon:wireless-checkout","carbon:wmv","carbon:word-cloud","carbon:workflow-automation","carbon:workspace","carbon:workspace-import","carbon:worship","carbon:worship-christian","carbon:worship-jewish","carbon:worship-muslim","carbon:x","carbon:x-axis","carbon:xls","carbon:xml","carbon:y","carbon:y-axis","carbon:z","carbon:z-axis","carbon:z-lpar","carbon:z-systems","carbon:zip","carbon:zip-reference","carbon:zoom-area","carbon:zoom-fit","carbon:zoom-in","carbon:zoom-in-area","carbon:zoom-out","carbon:zoom-out-area","carbon:zoom-pan","carbon:zoom-reset","carbon:zos","carbon:zos-sysplex","fluent-mdl2:remove-from-trash","mdi:content-save","mdi:map-marker","ph:map-pin-fill","simple-icons:tiktok"] as const
+export const iconList = ["carbon:3d-cursor","carbon:3d-cursor-alt","carbon:3d-curve-auto-colon","carbon:3d-curve-auto-vessels","carbon:3d-curve-manual","carbon:3d-ica","carbon:3d-mpr-toggle","carbon:3d-print-mesh","carbon:3d-software","carbon:3rd-party-connected","carbon:4k","carbon:4k-filled","carbon:accessibility","carbon:accessibility-alt","carbon:accessibility-color","carbon:accessibility-color-filled","carbon:account","carbon:accumulation-ice","carbon:accumulation-precipitation","carbon:accumulation-rain","carbon:accumulation-snow","carbon:activity","carbon:add","carbon:add-alt","carbon:add-comment","carbon:add-filled","carbon:add-large","carbon:agriculture-analytics","carbon:ai","carbon:ai-governance-lifecycle","carbon:ai-governance-tracked","carbon:ai-governance-untracked","carbon:ai-launch","carbon:ai-results","carbon:ai-results-high","carbon:ai-results-low","carbon:ai-results-medium","carbon:ai-results-urgent","carbon:ai-results-very-high","carbon:ai-status","carbon:ai-status-complete","carbon:ai-status-failed","carbon:ai-status-in-progress","carbon:ai-status-queued","carbon:ai-status-rejected","carbon:airline-digital-gate","carbon:airline-manage-gates","carbon:airline-passenger-care","carbon:airline-rapid-board","carbon:airplay","carbon:airplay-filled","carbon:airport-01","carbon:airport-02","carbon:airport-location","carbon:alarm","carbon:alarm-add","carbon:alarm-subtract","carbon:align-box-bottom-center","carbon:align-box-bottom-left","carbon:align-box-bottom-right","carbon:align-box-middle-center","carbon:align-box-middle-left","carbon:align-box-middle-right","carbon:align-box-top-center","carbon:align-box-top-left","carbon:align-box-top-right","carbon:align-horizontal-center","carbon:align-horizontal-left","carbon:align-horizontal-right","carbon:align-vertical-bottom","carbon:align-vertical-center","carbon:align-vertical-top","carbon:analytics","carbon:analytics-custom","carbon:analytics-reference","carbon:angle","carbon:annotation-visibility","carbon:aperture","carbon:api","carbon:api-1","carbon:app","carbon:app-connectivity","carbon:app-switcher","carbon:apple","carbon:apple-dash","carbon:application","carbon:application-mobile","carbon:application-virtual","carbon:application-web","carbon:apps","carbon:archive","carbon:area","carbon:area-custom","carbon:arithmetic-mean","carbon:arithmetic-median","carbon:arrival","carbon:arrow-annotation","carbon:arrow-down","carbon:arrow-down-left","carbon:arrow-down-right","carbon:arrow-left","carbon:arrow-right","carbon:arrow-shift-down","carbon:arrow-up","carbon:arrow-up-left","carbon:arrow-up-right","carbon:arrows","carbon:arrows-horizontal","carbon:arrows-vertical","carbon:asleep","carbon:asleep-filled","carbon:assembly","carbon:assembly-cluster","carbon:assembly-reference","carbon:asset","carbon:asset-confirm","carbon:asset-digital-twin","carbon:asset-view","carbon:asterisk","carbon:async","carbon:at","carbon:attachment","carbon:audio-console","carbon:augmented-reality","carbon:auto-scroll","carbon:automatic","carbon:autoscaling","carbon:awake","carbon:back-to-top","carbon:badge","carbon:baggage-claim","carbon:bar","carbon:barcode","carbon:bare-metal-server","carbon:bare-metal-server-01","carbon:bare-metal-server-02","carbon:barrier","carbon:basketball","carbon:bastion-host","carbon:bat","carbon:batch-job","carbon:batch-job-step","carbon:battery-charging","carbon:battery-empty","carbon:battery-full","carbon:battery-half","carbon:battery-low","carbon:battery-quarter","carbon:bee","carbon:bee-bat","carbon:beta","carbon:bicycle","carbon:binoculars","carbon:bloch-sphere","carbon:block-storage","carbon:block-storage-alt","carbon:blockchain","carbon:blog","carbon:bluetooth","carbon:bluetooth-off","carbon:book","carbon:bookmark","carbon:bookmark-add","carbon:bookmark-filled","carbon:boolean","carbon:boot","carbon:boot-volume","carbon:boot-volume-alt","carbon:border-bottom","carbon:border-full","carbon:border-left","carbon:border-none","carbon:border-right","carbon:border-top","carbon:bot","carbon:bottles-01","carbon:bottles-01-dash","carbon:bottles-02","carbon:bottles-02-dash","carbon:bottles-container","carbon:box","carbon:box-extra-large","carbon:box-large","carbon:box-medium","carbon:box-plot","carbon:box-small","carbon:branch","carbon:breaking-change","carbon:brightness-contrast","carbon:bring-forward","carbon:bring-to-front","carbon:brush-freehand","carbon:brush-polygon","carbon:build-tool","carbon:building","carbon:building-insights-1","carbon:building-insights-2","carbon:building-insights-3","carbon:bullhorn","carbon:buoy","carbon:bus","carbon:business-processes","carbon:button-centered","carbon:button-flush-left","carbon:cabin-care","carbon:cabin-care-alert","carbon:cabin-care-alt","carbon:cad","carbon:cafe","carbon:calculation","carbon:calculation-alt","carbon:calculator","carbon:calculator-check","carbon:calendar","carbon:calendar-add","carbon:calendar-add-alt","carbon:calendar-heat-map","carbon:calendar-settings","carbon:calendar-tools","carbon:calibrate","carbon:calls","carbon:calls-all","carbon:calls-incoming","carbon:camera","carbon:camera-action","carbon:campsite","carbon:car","carbon:car-front","carbon:carbon","carbon:carbon-accounting","carbon:carbon-for-ibm-dotcom","carbon:carbon-for-ibm-product","carbon:carbon-for-mobile","carbon:carbon-for-salesforce","carbon:carbon-ui-builder","carbon:caret-down","carbon:caret-left","carbon:caret-right","carbon:caret-sort","carbon:caret-sort-down","carbon:caret-sort-up","carbon:caret-up","carbon:carousel-horizontal","carbon:carousel-vertical","carbon:catalog","carbon:catalog-publish","carbon:categories","carbon:category","carbon:category-add","carbon:category-and","carbon:category-new","carbon:category-new-each","carbon:ccx","carbon:cd-archive","carbon:cd-create-archive","carbon:cd-create-exchange","carbon:cda","carbon:cell-tower","carbon:center-circle","carbon:center-square","carbon:center-to-fit","carbon:certificate","carbon:certificate-check","carbon:change-catalog","carbon:character-decimal","carbon:character-fraction","carbon:character-integer","carbon:character-lower-case","carbon:character-negative-number","carbon:character-patterns","carbon:character-sentence-case","carbon:character-upper-case","carbon:character-whole-number","carbon:charging-station","carbon:charging-station-filled","carbon:chart-3d","carbon:chart-area","carbon:chart-area-smooth","carbon:chart-area-stepper","carbon:chart-average","carbon:chart-bar","carbon:chart-bar-floating","carbon:chart-bar-overlay","carbon:chart-bar-stacked","carbon:chart-bar-target","carbon:chart-bubble","carbon:chart-bubble-packed","carbon:chart-bullet","carbon:chart-candlestick","carbon:chart-cluster-bar","carbon:chart-column","carbon:chart-column-floating","carbon:chart-column-target","carbon:chart-combo","carbon:chart-combo-stacked","carbon:chart-custom","carbon:chart-dual-y-axis","carbon:chart-error-bar","carbon:chart-error-bar-alt","carbon:chart-evaluation","carbon:chart-high-low","carbon:chart-histogram","carbon:chart-line","carbon:chart-line-data","carbon:chart-line-smooth","carbon:chart-logistic-regression","carbon:chart-marimekko","carbon:chart-maximum","carbon:chart-median","carbon:chart-minimum","carbon:chart-multi-line","carbon:chart-multitype","carbon:chart-network","carbon:chart-parallel","carbon:chart-pie","carbon:chart-planning-waterfall","carbon:chart-point","carbon:chart-population","carbon:chart-radar","carbon:chart-radial","carbon:chart-relationship","carbon:chart-ring","carbon:chart-river","carbon:chart-rose","carbon:chart-scatter","carbon:chart-spiral","carbon:chart-stacked","carbon:chart-stepper","carbon:chart-sunburst","carbon:chart-t-sne","carbon:chart-treemap","carbon:chart-venn-diagram","carbon:chart-violin-plot","carbon:chart-waterfall","carbon:chart-win-loss","carbon:chat","carbon:chat-bot","carbon:chat-launch","carbon:chat-off","carbon:chat-operational","carbon:checkbox","carbon:checkbox-checked","carbon:checkbox-checked-filled","carbon:checkbox-indeterminate","carbon:checkbox-indeterminate-filled","carbon:checkbox-undeterminate","carbon:checkbox-undeterminate-filled","carbon:checkmark","carbon:checkmark-filled","carbon:checkmark-filled-error","carbon:checkmark-filled-warning","carbon:checkmark-outline","carbon:checkmark-outline-error","carbon:checkmark-outline-warning","carbon:chemistry","carbon:chemistry-reference","carbon:chevron-down","carbon:chevron-down-outline","carbon:chevron-left","carbon:chevron-mini","carbon:chevron-right","carbon:chevron-sort","carbon:chevron-sort-down","carbon:chevron-sort-up","carbon:chevron-up","carbon:chevron-up-outline","carbon:chip","carbon:choices","carbon:choose-item","carbon:choropleth-map","carbon:cics-cmas","carbon:cics-db2-connection","carbon:cics-explorer","carbon:cics-program","carbon:cics-region","carbon:cics-region-alt","carbon:cics-region-routing","carbon:cics-region-target","carbon:cics-sit","carbon:cics-sit-overrides","carbon:cics-system-group","carbon:cics-transaction-server-zos","carbon:cics-wui-region","carbon:cicsplex","carbon:circle-dash","carbon:circle-filled","carbon:circle-measurement","carbon:circle-outline","carbon:circle-packing","carbon:circle-solid","carbon:circuit-composer","carbon:classification","carbon:classifier-language","carbon:clean","carbon:close","carbon:close-filled","carbon:close-large","carbon:close-outline","carbon:closed-caption","carbon:closed-caption-alt","carbon:closed-caption-filled","carbon:cloud","carbon:cloud-alerting","carbon:cloud-app","carbon:cloud-auditing","carbon:cloud-ceiling","carbon:cloud-data-ops","carbon:cloud-download","carbon:cloud-foundry-1","carbon:cloud-foundry-2","carbon:cloud-lightning","carbon:cloud-logging","carbon:cloud-monitoring","carbon:cloud-offline","carbon:cloud-rain","carbon:cloud-registry","carbon:cloud-satellite","carbon:cloud-satellite-config","carbon:cloud-satellite-link","carbon:cloud-satellite-services","carbon:cloud-service-management","carbon:cloud-services","carbon:cloud-snow","carbon:cloud-upload","carbon:cloudy","carbon:cobb-angle","carbon:code","carbon:code-hide","carbon:code-reference","carbon:code-signing-service","carbon:cognitive","carbon:collaborate","carbon:collapse-all","carbon:collapse-categories","carbon:color-palette","carbon:color-switch","carbon:column","carbon:column-delete","carbon:column-dependency","carbon:column-insert","carbon:commit","carbon:communication-unified","carbon:compare","carbon:compass","carbon:composer-edit","carbon:concept","carbon:condition-point","carbon:condition-wait-point","carbon:connect","carbon:connect-recursive","carbon:connect-reference","carbon:connect-source","carbon:connect-target","carbon:connection-receive","carbon:connection-send","carbon:connection-signal","carbon:connection-signal-off","carbon:connection-two-way","carbon:construction","carbon:container-registry","carbon:container-services","carbon:container-software","carbon:content-delivery-network","carbon:content-view","carbon:continue","carbon:continue-filled","carbon:continuous-deployment","carbon:continuous-integration","carbon:contour-draw","carbon:contour-edit","carbon:contour-finding","carbon:contrast","carbon:convert-to-cloud","carbon:cookie","carbon:copy","carbon:copy-file","carbon:copy-link","carbon:corn","carbon:corner","carbon:coronavirus","carbon:cost","carbon:cost-total","carbon:cough","carbon:course","carbon:covariate","carbon:credentials","carbon:crop","carbon:crop-growth","carbon:crop-health","carbon:cross-reference","carbon:cross-tab","carbon:crossroads","carbon:crowd-report","carbon:crowd-report-filled","carbon:csv","carbon:cu1","carbon:cu3","carbon:cube","carbon:cube-view","carbon:currency","carbon:currency-baht","carbon:currency-dollar","carbon:currency-euro","carbon:currency-lira","carbon:currency-pound","carbon:currency-ruble","carbon:currency-rupee","carbon:currency-shekel","carbon:currency-won","carbon:currency-yen","carbon:cursor-1","carbon:cursor-2","carbon:customer","carbon:customer-service","carbon:cut","carbon:cut-in-half","carbon:cut-out","carbon:cy","carbon:cyclist","carbon:cz","carbon:dashboard","carbon:dashboard-reference","carbon:data-1","carbon:data-2","carbon:data-accessor","carbon:data-analytics","carbon:data-backup","carbon:data-base","carbon:data-base-alt","carbon:data-bin","carbon:data-blob","carbon:data-categorical","carbon:data-center","carbon:data-check","carbon:data-class","carbon:data-collection","carbon:data-connected","carbon:data-definition","carbon:data-diode","carbon:data-enrichment","carbon:data-enrichment-add","carbon:data-error","carbon:data-format","carbon:data-player","carbon:data-quality-definition","carbon:data-reference","carbon:data-refinery","carbon:data-refinery-reference","carbon:data-regular","carbon:data-set","carbon:data-share","carbon:data-structured","carbon:data-table","carbon:data-table-reference","carbon:data-unreal","carbon:data-unstructured","carbon:data-view","carbon:data-view-alt","carbon:data-vis-1","carbon:data-vis-2","carbon:data-vis-3","carbon:data-vis-4","carbon:data-volume","carbon:data-volume-alt","carbon:database-datastax","carbon:database-elastic","carbon:database-enterprise-db2","carbon:database-enterprisedb","carbon:database-etcd","carbon:database-messaging","carbon:database-mongodb","carbon:database-postgresql","carbon:database-rabbit","carbon:database-redis","carbon:datastore","carbon:db2-buffer-pool","carbon:db2-data-sharing-group","carbon:db2-database","carbon:debug","carbon:decision-tree","carbon:delete","carbon:delivery","carbon:delivery-add","carbon:delivery-parcel","carbon:delivery-truck","carbon:demo","carbon:denominate","carbon:departure","carbon:deploy","carbon:deploy-rules","carbon:deployment-pattern","carbon:deployment-policy","carbon:deployment-unit-data","carbon:deployment-unit-execution","carbon:deployment-unit-installation","carbon:deployment-unit-presentation","carbon:deployment-unit-technical-data","carbon:deployment-unit-technical-execution","carbon:deployment-unit-technical-installation","carbon:deployment-unit-technical-presentation","carbon:desk-adjustable","carbon:development","carbon:devices","carbon:devices-apps","carbon:dew-point","carbon:dew-point-filled","carbon:diagram","carbon:diagram-reference","carbon:diamond-outline","carbon:diamond-solid","carbon:dicom-6000","carbon:dicom-overlay","carbon:direct-link","carbon:direction-bear-right-01","carbon:direction-bear-right-01-filled","carbon:direction-bear-right-02","carbon:direction-bear-right-02-filled","carbon:direction-curve","carbon:direction-curve-filled","carbon:direction-fork","carbon:direction-fork-filled","carbon:direction-loop-left","carbon:direction-loop-left-filled","carbon:direction-loop-right","carbon:direction-loop-right-filled","carbon:direction-merge","carbon:direction-merge-filled","carbon:direction-right-01","carbon:direction-right-01-filled","carbon:direction-right-02","carbon:direction-right-02-filled","carbon:direction-rotary-first-right","carbon:direction-rotary-first-right-filled","carbon:direction-rotary-right","carbon:direction-rotary-right-filled","carbon:direction-rotary-straight","carbon:direction-rotary-straight-filled","carbon:direction-sharp-turn","carbon:direction-sharp-turn-filled","carbon:direction-straight","carbon:direction-straight-filled","carbon:direction-straight-right","carbon:direction-straight-right-filled","carbon:direction-u-turn","carbon:direction-u-turn-filled","carbon:directory-domain","carbon:distribute-horizontal-center","carbon:distribute-horizontal-left","carbon:distribute-horizontal-right","carbon:distribute-vertical-bottom","carbon:distribute-vertical-center","carbon:distribute-vertical-top","carbon:dna","carbon:dns-services","carbon:doc","carbon:document","carbon:document-add","carbon:document-attachment","carbon:document-audio","carbon:document-blank","carbon:document-download","carbon:document-epdf","carbon:document-export","carbon:document-horizontal","carbon:document-import","carbon:document-multiple-01","carbon:document-multiple-02","carbon:document-pdf","carbon:document-preliminary","carbon:document-protected","carbon:document-security","carbon:document-sentiment","carbon:document-signed","carbon:document-sketch","carbon:document-subtract","carbon:document-tasks","carbon:document-unknown","carbon:document-unprotected","carbon:document-vertical","carbon:document-video","carbon:document-view","carbon:document-word-processor","carbon:document-word-processor-reference","carbon:dog-walker","carbon:dot-mark","carbon:double-integer","carbon:down-to-bottom","carbon:download","carbon:download-study","carbon:downstream","carbon:drag-horizontal","carbon:drag-vertical","carbon:draggable","carbon:draw","carbon:drill-back","carbon:drill-down","carbon:drill-through","carbon:drink-01","carbon:drink-02","carbon:driver-analysis","carbon:drone","carbon:drone-delivery","carbon:drone-front","carbon:drone-video","carbon:drop-photo","carbon:drop-photo-filled","carbon:drought","carbon:dvr","carbon:earth","carbon:earth-americas","carbon:earth-americas-filled","carbon:earth-europe-africa","carbon:earth-europe-africa-filled","carbon:earth-filled","carbon:earth-southeast-asia","carbon:earth-southeast-asia-filled","carbon:earthquake","carbon:edge-cluster","carbon:edge-device","carbon:edge-enhancement","carbon:edge-enhancement-01","carbon:edge-enhancement-02","carbon:edge-enhancement-03","carbon:edge-node","carbon:edge-node-alt","carbon:edge-service","carbon:edit","carbon:edit-filter","carbon:edit-off","carbon:edt-loop","carbon:education","carbon:email","carbon:email-new","carbon:encryption","carbon:energy-renewable","carbon:enterprise","carbon:equal-approximately","carbon:equalizer","carbon:erase","carbon:erase-3d","carbon:error","carbon:error-filled","carbon:error-outline","carbon:event","carbon:event-change","carbon:event-incident","carbon:event-schedule","carbon:event-warning","carbon:events","carbon:events-alt","carbon:exam-mode","carbon:executable-program","carbon:exit","carbon:expand-all","carbon:expand-categories","carbon:explore","carbon:export","carbon:eyedropper","carbon:face-activated","carbon:face-activated-add","carbon:face-activated-filled","carbon:face-add","carbon:face-cool","carbon:face-dissatisfied","carbon:face-dissatisfied-filled","carbon:face-dizzy","carbon:face-dizzy-filled","carbon:face-mask","carbon:face-neutral","carbon:face-neutral-filled","carbon:face-pending","carbon:face-pending-filled","carbon:face-satisfied","carbon:face-satisfied-filled","carbon:face-wink","carbon:face-wink-filled","carbon:factor","carbon:fade","carbon:favorite","carbon:favorite-filled","carbon:favorite-half","carbon:fetch-upload","carbon:fetch-upload-cloud","carbon:file-storage","carbon:filter","carbon:filter-edit","carbon:filter-remove","carbon:filter-reset","carbon:finance","carbon:fingerprint-recognition","carbon:fire","carbon:firewall","carbon:firewall-classic","carbon:fish","carbon:fish-multiple","carbon:fit-to-height","carbon:fit-to-screen","carbon:fit-to-width","carbon:flag","carbon:flag-filled","carbon:flagging-taxi","carbon:flash","carbon:flash-filled","carbon:flash-off","carbon:flash-off-filled","carbon:flight-international","carbon:flight-roster","carbon:flight-schedule","carbon:floating-ip","carbon:flood","carbon:flood-warning","carbon:floorplan","carbon:flow","carbon:flow-connection","carbon:flow-data","carbon:flow-logs-vpc","carbon:flow-modeler","carbon:flow-modeler-reference","carbon:flow-stream","carbon:flow-stream-reference","carbon:fog","carbon:folder","carbon:folder-add","carbon:folder-details","carbon:folder-details-reference","carbon:folder-move-to","carbon:folder-off","carbon:folder-open","carbon:folder-parent","carbon:folder-shared","carbon:folders","carbon:forecast-hail","carbon:forecast-hail-30","carbon:forecast-lightning","carbon:forecast-lightning-30","carbon:fork","carbon:forum","carbon:forward-10","carbon:forward-30","carbon:forward-5","carbon:foundation-model","carbon:fragile","carbon:friendship","carbon:fruit-bowl","carbon:function","carbon:function-math","carbon:fusion-blender","carbon:game-console","carbon:game-wireless","carbon:gamification","carbon:gas-station","carbon:gas-station-filled","carbon:gateway","carbon:gateway-api","carbon:gateway-mail","carbon:gateway-public","carbon:gateway-security","carbon:gateway-user-access","carbon:gateway-vpn","carbon:gender-female","carbon:gender-male","carbon:generate-pdf","carbon:gif","carbon:gift","carbon:global-loan-and-trial","carbon:globe","carbon:gradient","carbon:graphical-data-flow","carbon:grid","carbon:group","carbon:group-access","carbon:group-account","carbon:group-objects","carbon:group-objects-new","carbon:group-objects-save","carbon:group-presentation","carbon:group-resource","carbon:group-security","carbon:growth","carbon:gui","carbon:gui-management","carbon:h","carbon:hail","carbon:hanging-protocol","carbon:harbor","carbon:hardware-security-module","carbon:hashtag","carbon:haze","carbon:haze-night","carbon:hd","carbon:hd-filled","carbon:hdr","carbon:headphones","carbon:headset","carbon:health-cross","carbon:hearing","carbon:heat-map","carbon:heat-map-02","carbon:heat-map-03","carbon:heat-map-stocks","carbon:helicopter","carbon:help","carbon:help-desk","carbon:help-filled","carbon:hexagon-outline","carbon:hexagon-solid","carbon:hexagon-vertical-outline","carbon:hexagon-vertical-solid","carbon:hinton-plot","carbon:hl7-attributes","carbon:hole-filling","carbon:hole-filling-cursor","carbon:home","carbon:horizontal-view","carbon:hospital","carbon:hospital-bed","carbon:hotel","carbon:hourglass","carbon:html","carbon:html-reference","carbon:http","carbon:humidity","carbon:humidity-alt","carbon:hurricane","carbon:hybrid-networking","carbon:hybrid-networking-alt","carbon:ibm-ai-on-z","carbon:ibm-aiops-insights","carbon:ibm-bluepay","carbon:ibm-cloud","carbon:ibm-cloud-app-id","carbon:ibm-cloud-bare-metal-server","carbon:ibm-cloud-bare-metal-servers-vpc","carbon:ibm-cloud-citrix-daas","carbon:ibm-cloud-continuous-delivery","carbon:ibm-cloud-dedicated-host","carbon:ibm-cloud-direct-link-1-connect","carbon:ibm-cloud-direct-link-1-dedicated","carbon:ibm-cloud-direct-link-1-dedicated-hosting","carbon:ibm-cloud-direct-link-1-exchange","carbon:ibm-cloud-direct-link-2-connect","carbon:ibm-cloud-direct-link-2-dedicated","carbon:ibm-cloud-direct-link-2-dedicated-hosting","carbon:ibm-cloud-event-notification","carbon:ibm-cloud-event-streams","carbon:ibm-cloud-for-education","carbon:ibm-cloud-hpc","carbon:ibm-cloud-hsm","carbon:ibm-cloud-hyper-protect-crypto-services","carbon:ibm-cloud-hyper-protect-dbaas","carbon:ibm-cloud-hyper-protect-vs","carbon:ibm-cloud-internet-services","carbon:ibm-cloud-ipsec-vpn","carbon:ibm-cloud-key-protect","carbon:ibm-cloud-kubernetes-service","carbon:ibm-cloud-logging","carbon:ibm-cloud-mass-data-migration","carbon:ibm-cloud-pak-applications","carbon:ibm-cloud-pak-business-automation","carbon:ibm-cloud-pak-data","carbon:ibm-cloud-pak-integration","carbon:ibm-cloud-pak-manta-automated-data-lineage","carbon:ibm-cloud-pak-multicloud-mgmt","carbon:ibm-cloud-pak-netezza","carbon:ibm-cloud-pak-network-automation","carbon:ibm-cloud-pak-security","carbon:ibm-cloud-pak-system","carbon:ibm-cloud-pak-watson-aiops","carbon:ibm-cloud-pal","carbon:ibm-cloud-privileged-access-gateway","carbon:ibm-cloud-projects","carbon:ibm-cloud-resiliency","carbon:ibm-cloud-secrets-manager","carbon:ibm-cloud-security-compliance-center","carbon:ibm-cloud-security-compliance-center-workload-protection","carbon:ibm-cloud-subnets","carbon:ibm-cloud-sysdig-secure","carbon:ibm-cloud-transit-gateway","carbon:ibm-cloud-virtual-server-classic","carbon:ibm-cloud-virtual-server-vpc","carbon:ibm-cloud-vpc","carbon:ibm-cloud-vpc-endpoints","carbon:ibm-cloudant","carbon:ibm-content-services","carbon:ibm-data-product-exchange","carbon:ibm-data-replication","carbon:ibm-datastage","carbon:ibm-db2","carbon:ibm-db2-alt","carbon:ibm-db2-warehouse","carbon:ibm-dynamic-route-server","carbon:ibm-engineering-systems-design-rhapsody-model-manager","carbon:ibm-engineering-systems-design-rhapsody-sn1","carbon:ibm-engineering-systems-design-rhapsody-sn2","carbon:ibm-event-automation","carbon:ibm-event-endpoint-mgmt","carbon:ibm-event-processing","carbon:ibm-event-streams","carbon:ibm-ibv","carbon:ibm-instana","carbon:ibm-match-360","carbon:ibm-mq","carbon:ibm-open-enterprise-languages","carbon:ibm-openshift-container-platform-on-vpc-for-regulated-industries","carbon:ibm-power-vs","carbon:ibm-power-vs-private-cloud","carbon:ibm-power-with-vpc","carbon:ibm-private-path-services","carbon:ibm-process-mining","carbon:ibm-saas-console","carbon:ibm-sap-on-power","carbon:ibm-secure-infrastructure-on-vpc-for-regulated-industries","carbon:ibm-security","carbon:ibm-security-services","carbon:ibm-telehealth","carbon:ibm-tenet","carbon:ibm-toolchain","carbon:ibm-turbonomic","carbon:ibm-vpn-for-vpc","carbon:ibm-vsi-on-vpc-for-regulated-industries","carbon:ibm-watson-assistant","carbon:ibm-watson-discovery","carbon:ibm-watson-knowledge-catalog","carbon:ibm-watson-knowledge-studio","carbon:ibm-watson-language-translator","carbon:ibm-watson-machine-learning","carbon:ibm-watson-natural-language-classifier","carbon:ibm-watson-natural-language-understanding","carbon:ibm-watson-openscale","carbon:ibm-watson-orders","carbon:ibm-watson-query","carbon:ibm-watson-speech-to-text","carbon:ibm-watson-studio","carbon:ibm-watson-text-to-speech","carbon:ibm-watson-tone-analyzer","carbon:ibm-watsonx-assistant","carbon:ibm-watsonx-code-assistant","carbon:ibm-watsonx-code-assistant-for-z","carbon:ibm-watsonx-code-assistant-for-z-refactor","carbon:ibm-watsonx-orchestrate","carbon:ibm-wazi-deploy","carbon:ibm-z-cloud-mod-stack","carbon:ibm-z-cloud-provisioning","carbon:ibm-z-environments-dev-sec-ops","carbon:ibm-z-os","carbon:ibm-z-os-ai-control-interface","carbon:ibm-z-os-containers","carbon:ibm-z-os-package-manager","carbon:ibm-z-processor-capacity-reference","carbon:ica-2d","carbon:ice-accretion","carbon:ice-vision","carbon:id","carbon:id-management","carbon:idea","carbon:identification","carbon:image","carbon:image-copy","carbon:image-medical","carbon:image-reference","carbon:image-search","carbon:image-search-alt","carbon:image-service","carbon:import-export","carbon:improve-relevance","carbon:in-progress","carbon:in-progress-error","carbon:in-progress-warning","carbon:incomplete","carbon:incomplete-cancel","carbon:incomplete-error","carbon:incomplete-warning","carbon:increase-level","carbon:industry","carbon:infinity","carbon:infinity-symbol","carbon:information","carbon:information-disabled","carbon:information-filled","carbon:information-square","carbon:information-square-filled","carbon:infrastructure-classic","carbon:insert","carbon:insert-page","carbon:insert-syntax","carbon:inspection","carbon:instance-bx","carbon:instance-classic","carbon:instance-cx","carbon:instance-mx","carbon:instance-virtual","carbon:integration","carbon:intent-request-active","carbon:intent-request-create","carbon:intent-request-heal","carbon:intent-request-inactive","carbon:intent-request-scale-in","carbon:intent-request-scale-out","carbon:intent-request-uninstall","carbon:intent-request-upgrade","carbon:interactions","carbon:interactive-segmentation-cursor","carbon:intersect","carbon:intrusion-prevention","carbon:inventory-management","carbon:iot-connect","carbon:iot-platform","carbon:ip","carbon:iso","carbon:iso-filled","carbon:iso-outline","carbon:join-full","carbon:join-inner","carbon:join-left","carbon:join-outer","carbon:join-right","carbon:jpg","carbon:js-error","carbon:json","carbon:json-reference","carbon:jump-link","carbon:keep-dry","carbon:keyboard","carbon:keyboard-off","carbon:kubernetes","carbon:kubernetes-ip-address","carbon:kubernetes-pod","carbon:label","carbon:language","carbon:laptop","carbon:lasso","carbon:lasso-polygon","carbon:launch","carbon:launch-study-1","carbon:launch-study-2","carbon:launch-study-3","carbon:layers","carbon:legend","carbon:letter-aa","carbon:letter-aa-large","carbon:letter-bb","carbon:letter-cc","carbon:letter-dd","carbon:letter-ee","carbon:letter-ff","carbon:letter-gg","carbon:letter-hh","carbon:letter-ii","carbon:letter-jj","carbon:letter-kk","carbon:letter-ll","carbon:letter-mm","carbon:letter-nn","carbon:letter-oo","carbon:letter-pp","carbon:letter-qq","carbon:letter-rr","carbon:letter-ss","carbon:letter-tt","carbon:letter-uu","carbon:letter-vv","carbon:letter-ww","carbon:letter-xx","carbon:letter-yy","carbon:letter-zz","carbon:license","carbon:license-draft","carbon:license-global","carbon:license-maintenance","carbon:license-maintenance-draft","carbon:license-third-party","carbon:license-third-party-draft","carbon:lifesaver","carbon:light","carbon:light-filled","carbon:lightning","carbon:link","carbon:linux","carbon:linux-alt","carbon:list","carbon:list-boxes","carbon:list-bulleted","carbon:list-checked","carbon:list-checked-mirror","carbon:list-dropdown","carbon:list-numbered","carbon:list-numbered-mirror","carbon:load-balancer-application","carbon:load-balancer-classic","carbon:load-balancer-global","carbon:load-balancer-listener","carbon:load-balancer-local","carbon:load-balancer-network","carbon:load-balancer-pool","carbon:load-balancer-vpc","carbon:location","carbon:location-company","carbon:location-company-filled","carbon:location-current","carbon:location-filled","carbon:location-hazard","carbon:location-hazard-filled","carbon:location-heart","carbon:location-heart-filled","carbon:location-person","carbon:location-person-filled","carbon:location-save","carbon:location-star","carbon:location-star-filled","carbon:locked","carbon:logical-partition","carbon:login","carbon:logo-angular","carbon:logo-ansible-community","carbon:logo-delicious","carbon:logo-digg","carbon:logo-discord","carbon:logo-facebook","carbon:logo-figma","carbon:logo-flickr","carbon:logo-github","carbon:logo-gitlab","carbon:logo-glassdoor","carbon:logo-google","carbon:logo-instagram","carbon:logo-invision","carbon:logo-jupyter","carbon:logo-keybase","carbon:logo-kubernetes","carbon:logo-linkedin","carbon:logo-livestream","carbon:logo-mastodon","carbon:logo-medium","carbon:logo-npm","carbon:logo-openshift","carbon:logo-pinterest","carbon:logo-python","carbon:logo-quora","carbon:logo-r-script","carbon:logo-react","carbon:logo-red-hat-ansible","carbon:logo-sketch","carbon:logo-skype","carbon:logo-slack","carbon:logo-snapchat","carbon:logo-stumbleupon","carbon:logo-svelte","carbon:logo-tumblr","carbon:logo-twitter","carbon:logo-vmware","carbon:logo-vmware-alt","carbon:logo-vue","carbon:logo-wechat","carbon:logo-x","carbon:logo-xing","carbon:logo-yelp","carbon:logo-youtube","carbon:logout","carbon:loop","carbon:mac","carbon:mac-command","carbon:mac-option","carbon:mac-shift","carbon:machine-learning","carbon:machine-learning-model","carbon:magic-wand","carbon:magic-wand-filled","carbon:magnify","carbon:mail-all","carbon:mail-reply","carbon:mammogram","carbon:mammogram-stacked","carbon:manage-protection","carbon:managed-solutions","carbon:map","carbon:map-boundary","carbon:map-boundary-vegetation","carbon:map-center","carbon:map-identify","carbon:marine-warning","carbon:math-curve","carbon:matrix","carbon:maximize","carbon:media-cast","carbon:media-library","carbon:media-library-filled","carbon:medication","carbon:medication-alert","carbon:medication-reminder","carbon:menu","carbon:message-queue","carbon:meter","carbon:meter-alt","carbon:microphone","carbon:microphone-filled","carbon:microphone-off","carbon:microphone-off-filled","carbon:microscope","carbon:microservices-1","carbon:microservices-2","carbon:migrate","carbon:migrate-alt","carbon:milestone","carbon:military-camp","carbon:minimize","carbon:misuse","carbon:misuse-alt","carbon:misuse-outline","carbon:mixed-rain-hail","carbon:mobile","carbon:mobile-add","carbon:mobile-audio","carbon:mobile-check","carbon:mobile-crash","carbon:mobile-download","carbon:mobile-event","carbon:mobile-landscape","carbon:mobile-request","carbon:mobile-session","carbon:mobile-view","carbon:mobile-view-orientation","carbon:mobility-services","carbon:model","carbon:model-alt","carbon:model-builder","carbon:model-builder-reference","carbon:model-reference","carbon:model-tuned","carbon:money","carbon:monster","carbon:monument","carbon:moon","carbon:moonrise","carbon:moonset","carbon:mostly-cloudy","carbon:mostly-cloudy-night","carbon:mountain","carbon:mov","carbon:move","carbon:movement","carbon:mp3","carbon:mp4","carbon:mpeg","carbon:mpg2","carbon:music","carbon:music-add","carbon:music-remove","carbon:mysql","carbon:name-space","carbon:navaid-civil","carbon:navaid-dme","carbon:navaid-helipad","carbon:navaid-military","carbon:navaid-military-civil","carbon:navaid-ndb","carbon:navaid-ndb-dme","carbon:navaid-private","carbon:navaid-seaplane","carbon:navaid-tacan","carbon:navaid-vhfor","carbon:navaid-vor","carbon:navaid-vordme","carbon:navaid-vortac","carbon:need","carbon:network-1","carbon:network-2","carbon:network-3","carbon:network-3-reference","carbon:network-4","carbon:network-4-reference","carbon:network-admin-control","carbon:network-enterprise","carbon:network-interface","carbon:network-overlay","carbon:network-public","carbon:new-tab","carbon:next-filled","carbon:next-outline","carbon:no-image","carbon:no-ticket","carbon:nominal","carbon:nominate","carbon:non-certified","carbon:noodle-bowl","carbon:not-available","carbon:not-sent","carbon:not-sent-filled","carbon:notebook","carbon:notebook-reference","carbon:notification","carbon:notification-filled","carbon:notification-new","carbon:notification-off","carbon:notification-off-filled","carbon:number-0","carbon:number-1","carbon:number-2","carbon:number-3","carbon:number-4","carbon:number-5","carbon:number-6","carbon:number-7","carbon:number-8","carbon:number-9","carbon:number-small-0","carbon:number-small-1","carbon:number-small-2","carbon:number-small-3","carbon:number-small-4","carbon:number-small-5","carbon:number-small-6","carbon:number-small-7","carbon:number-small-8","carbon:number-small-9","carbon:object-storage","carbon:object-storage-alt","carbon:observed-hail","carbon:observed-lightning","carbon:omega","carbon:opacity","carbon:open-panel-bottom","carbon:open-panel-filled-bottom","carbon:open-panel-filled-left","carbon:open-panel-filled-right","carbon:open-panel-filled-top","carbon:open-panel-left","carbon:open-panel-right","carbon:open-panel-top","carbon:operation","carbon:operation-gauge","carbon:operation-if","carbon:operations-field","carbon:operations-record","carbon:order-details","carbon:ordinal","carbon:outage","carbon:outlook-severe","carbon:overflow-menu-horizontal","carbon:overflow-menu-vertical","carbon:overlay","carbon:package","carbon:package-text-analysis","carbon:page-break","carbon:page-first","carbon:page-last","carbon:page-number","carbon:page-scroll","carbon:paint-brush","carbon:paint-brush-alt","carbon:palm-tree","carbon:pan-horizontal","carbon:pan-vertical","carbon:panel-expansion","carbon:paragraph","carbon:parameter","carbon:parent-child","carbon:partition-auto","carbon:partition-collection","carbon:partition-repartition","carbon:partition-same","carbon:partition-specific","carbon:partly-cloudy","carbon:partly-cloudy-night","carbon:partnership","carbon:passenger-drinks","carbon:passenger-plus","carbon:password","carbon:paste","carbon:pause","carbon:pause-filled","carbon:pause-future","carbon:pause-outline","carbon:pause-outline-filled","carbon:pause-past","carbon:pcn-e-node","carbon:pcn-military","carbon:pcn-p-node","carbon:pcn-z-node","carbon:pdf","carbon:pdf-reference","carbon:pedestrian","carbon:pedestrian-child","carbon:pedestrian-family","carbon:pen","carbon:pen-fountain","carbon:pending","carbon:pending-filled","carbon:pentagon-down-outline","carbon:pentagon-down-solid","carbon:pentagon-left-outline","carbon:pentagon-left-solid","carbon:pentagon-outline","carbon:pentagon-right-outline","carbon:pentagon-right-solid","carbon:pentagon-solid","carbon:percentage","carbon:percentage-filled","carbon:person","carbon:person-favorite","carbon:pest","carbon:pet-image-b","carbon:pet-image-o","carbon:phone","carbon:phone-application","carbon:phone-block","carbon:phone-block-filled","carbon:phone-filled","carbon:phone-incoming","carbon:phone-incoming-filled","carbon:phone-ip","carbon:phone-off","carbon:phone-off-filled","carbon:phone-outgoing","carbon:phone-outgoing-filled","carbon:phone-settings","carbon:phone-voice","carbon:phone-voice-filled","carbon:phrase-sentiment","carbon:picnic-area","carbon:piggy-bank","carbon:piggy-bank-slot","carbon:pills","carbon:pills-add","carbon:pills-subtract","carbon:pin","carbon:pin-filled","carbon:plan","carbon:plane","carbon:plane-private","carbon:plane-sea","carbon:platforms","carbon:play","carbon:play-filled","carbon:play-filled-alt","carbon:play-outline","carbon:play-outline-filled","carbon:playlist","carbon:plug","carbon:plug-filled","carbon:png","carbon:point-of-presence","carbon:pointer-text","carbon:police","carbon:policy","carbon:popup","carbon:port-input","carbon:port-output","carbon:portfolio","carbon:power","carbon:ppt","carbon:presentation-file","carbon:pressure","carbon:pressure-filled","carbon:previous-filled","carbon:previous-outline","carbon:printer","carbon:process","carbon:process-automate","carbon:product","carbon:progress-bar","carbon:progress-bar-round","carbon:promote","carbon:prompt-session","carbon:prompt-template","carbon:property-relationship","carbon:purchase","carbon:qc-launch","carbon:qq-plot","carbon:qr-code","carbon:quadrant-plot","carbon:query","carbon:query-queue","carbon:queued","carbon:quotes","carbon:radar","carbon:radar-enhanced","carbon:radar-weather","carbon:radio","carbon:radio-button","carbon:radio-button-checked","carbon:radio-combat","carbon:radio-push-to-talk","carbon:rain","carbon:rain-drizzle","carbon:rain-drop","carbon:rain-heavy","carbon:rain-scattered","carbon:rain-scattered-night","carbon:raw","carbon:receipt","carbon:recently-viewed","carbon:recommend","carbon:recording","carbon:recording-filled","carbon:recording-filled-alt","carbon:recycle","carbon:redo","carbon:ref-evapotranspiration","carbon:reference-architecture","carbon:reflect-horizontal","carbon:reflect-vertical","carbon:region-analysis-area","carbon:region-analysis-volume","carbon:registration","carbon:reminder","carbon:reminder-medical","carbon:renew","carbon:repeat","carbon:repeat-one","carbon:replicate","carbon:reply","carbon:reply-all","carbon:repo-artifact","carbon:repo-source-code","carbon:report","carbon:report-data","carbon:request-quote","carbon:research-bloch-sphere","carbon:research-hinton-plot","carbon:research-matrix","carbon:reset","carbon:reset-alt","carbon:restart","carbon:restaurant","carbon:restaurant-fine","carbon:result","carbon:result-draft","carbon:result-new","carbon:result-old","carbon:retry-failed","carbon:return","carbon:review","carbon:rewind-10","carbon:rewind-30","carbon:rewind-5","carbon:right-panel-close","carbon:right-panel-close-filled","carbon:right-panel-open","carbon:right-panel-open-filled","carbon:road","carbon:road-weather","carbon:roadmap","carbon:rocket","carbon:rotate","carbon:rotate-180","carbon:rotate-360","carbon:rotate-clockwise","carbon:rotate-clockwise-alt","carbon:rotate-clockwise-alt-filled","carbon:rotate-clockwise-filled","carbon:rotate-counterclockwise","carbon:rotate-counterclockwise-alt","carbon:rotate-counterclockwise-alt-filled","carbon:rotate-counterclockwise-filled","carbon:router","carbon:router-voice","carbon:router-wifi","carbon:row","carbon:row-collapse","carbon:row-delete","carbon:row-expand","carbon:row-insert","carbon:rss","carbon:rule","carbon:rule-cancelled","carbon:rule-data-quality","carbon:rule-draft","carbon:rule-filled","carbon:rule-locked","carbon:rule-partial","carbon:rule-test","carbon:ruler","carbon:ruler-alt","carbon:run","carbon:run-mirror","carbon:running","carbon:s","carbon:s-alt","carbon:sailboat-coastal","carbon:sailboat-offshore","carbon:sales-ops","carbon:sankey-diagram","carbon:sankey-diagram-alt","carbon:satellite","carbon:satellite-radar","carbon:satellite-weather","carbon:save","carbon:save-annotation","carbon:save-image","carbon:save-model","carbon:save-series","carbon:scale","carbon:scales","carbon:scales-tipped","carbon:scalpel","carbon:scalpel-cursor","carbon:scalpel-lasso","carbon:scalpel-select","carbon:scan","carbon:scan-alt","carbon:scan-disabled","carbon:scatter-matrix","carbon:schematics","carbon:scis-control-tower","carbon:scis-transparent-supply","carbon:scooter","carbon:scooter-front","carbon:screen","carbon:screen-map","carbon:screen-map-set","carbon:screen-off","carbon:script","carbon:script-reference","carbon:sdk","carbon:search","carbon:search-advanced","carbon:search-locate","carbon:search-locate-mirror","carbon:security","carbon:security-services","carbon:select-01","carbon:select-02","carbon:select-window","carbon:send","carbon:send-alt","carbon:send-alt-filled","carbon:send-backward","carbon:send-filled","carbon:send-to-back","carbon:server-dns","carbon:server-proxy","carbon:server-time","carbon:service-desk","carbon:service-id","carbon:service-levels","carbon:session-border-control","carbon:settings","carbon:settings-adjust","carbon:settings-check","carbon:settings-edit","carbon:settings-services","carbon:settings-view","carbon:shape-except","carbon:shape-exclude","carbon:shape-intersect","carbon:shape-join","carbon:shape-unite","carbon:share","carbon:share-knowledge","carbon:shopping-bag","carbon:shopping-cart","carbon:shopping-cart-arrow-down","carbon:shopping-cart-arrow-up","carbon:shopping-cart-clear","carbon:shopping-cart-error","carbon:shopping-cart-minus","carbon:shopping-cart-plus","carbon:shopping-catalog","carbon:show-data-cards","carbon:shrink-screen","carbon:shrink-screen-filled","carbon:shuffle","carbon:shuttle","carbon:side-panel-close","carbon:side-panel-close-filled","carbon:side-panel-open","carbon:side-panel-open-filled","carbon:sight","carbon:sigma","carbon:signal-strength","carbon:sim-card","carbon:skill-level","carbon:skill-level-advanced","carbon:skill-level-basic","carbon:skill-level-intermediate","carbon:skip-back","carbon:skip-back-filled","carbon:skip-back-outline","carbon:skip-back-outline-filled","carbon:skip-back-outline-solid","carbon:skip-back-solid-filled","carbon:skip-forward","carbon:skip-forward-filled","carbon:skip-forward-outline","carbon:skip-forward-outline-filled","carbon:skip-forward-outline-solid","carbon:skip-forward-solid-filled","carbon:sleet","carbon:slisor","carbon:slm","carbon:smell","carbon:smoke","carbon:smoothing","carbon:smoothing-cursor","carbon:snooze","carbon:snow","carbon:snow-blizzard","carbon:snow-density","carbon:snow-heavy","carbon:snow-scattered","carbon:snow-scattered-night","carbon:snowflake","carbon:soccer","carbon:software-resource","carbon:software-resource-cluster","carbon:software-resource-resource","carbon:soil-moisture","carbon:soil-moisture-field","carbon:soil-moisture-global","carbon:soil-temperature","carbon:soil-temperature-field","carbon:soil-temperature-global","carbon:solar-panel","carbon:sort-ascending","carbon:sort-descending","carbon:sort-remove","carbon:spell-check","carbon:spine-label","carbon:split","carbon:split-discard","carbon:split-screen","carbon:spray-paint","carbon:sprout","carbon:sql","carbon:square-outline","carbon:stack-limitation","carbon:stacked-move","carbon:stacked-scrolling-1","carbon:stacked-scrolling-2","carbon:stamp","carbon:star","carbon:star-filled","carbon:star-half","carbon:star-review","carbon:status-acknowledge","carbon:status-change","carbon:status-partial-fail","carbon:status-resolved","carbon:stay-inside","carbon:stem-leaf-plot","carbon:stethoscope","carbon:stop","carbon:stop-filled","carbon:stop-filled-alt","carbon:stop-outline","carbon:stop-outline-filled","carbon:stop-sign","carbon:stop-sign-filled","carbon:storage-pool","carbon:storage-request","carbon:store","carbon:storm-tracker","carbon:strawberry","carbon:stress-breath-editor","carbon:string-integer","carbon:string-text","carbon:study-next","carbon:study-previous","carbon:study-read","carbon:study-skip","carbon:study-transfer","carbon:study-unread","carbon:study-view","carbon:sub-volume","carbon:subdirectory","carbon:subflow","carbon:subflow-local","carbon:subnet-acl-rules","carbon:subtract","carbon:subtract-alt","carbon:subtract-filled","carbon:subtract-large","carbon:summary-kpi","carbon:summary-kpi-mirror","carbon:sun","carbon:sunny","carbon:sunrise","carbon:sunset","carbon:support-vector-machine","carbon:sustainability","carbon:svg","carbon:swim","carbon:switch-layer-2","carbon:switch-layer-3","carbon:switcher","carbon:sync-settings","carbon:sys-provision","carbon:t","carbon:t-alt","carbon:table","carbon:table-alias","carbon:table-built","carbon:table-of-contents","carbon:table-shortcut","carbon:table-split","carbon:tablet","carbon:tablet-landscape","carbon:tag","carbon:tag-edit","carbon:tag-export","carbon:tag-group","carbon:tag-import","carbon:tag-none","carbon:tank","carbon:task","carbon:task-add","carbon:task-approved","carbon:task-asset-view","carbon:task-complete","carbon:task-location","carbon:task-remove","carbon:task-settings","carbon:task-star","carbon:task-tools","carbon:task-view","carbon:taste","carbon:taxi","carbon:tcp-ip-service","carbon:temperature","carbon:temperature-celsius","carbon:temperature-celsius-alt","carbon:temperature-fahrenheit","carbon:temperature-fahrenheit-alt","carbon:temperature-feels-like","carbon:temperature-frigid","carbon:temperature-hot","carbon:temperature-inversion","carbon:temperature-max","carbon:temperature-min","carbon:temperature-water","carbon:template","carbon:tennis","carbon:tennis-ball","carbon:term","carbon:terminal","carbon:terminal-3270","carbon:test-tool","carbon:text-align-center","carbon:text-align-justify","carbon:text-align-left","carbon:text-align-mixed","carbon:text-align-right","carbon:text-all-caps","carbon:text-annotation-toggle","carbon:text-bold","carbon:text-clear-format","carbon:text-color","carbon:text-creation","carbon:text-fill","carbon:text-font","carbon:text-footnote","carbon:text-highlight","carbon:text-indent","carbon:text-indent-less","carbon:text-indent-more","carbon:text-italic","carbon:text-kerning","carbon:text-leading","carbon:text-line-spacing","carbon:text-link","carbon:text-link-analysis","carbon:text-long-paragraph","carbon:text-mining","carbon:text-mining-applier","carbon:text-new-line","carbon:text-scale","carbon:text-selection","carbon:text-short-paragraph","carbon:text-small-caps","carbon:text-strikethrough","carbon:text-subscript","carbon:text-superscript","carbon:text-tracking","carbon:text-underline","carbon:text-vertical-alignment","carbon:text-wrap","carbon:theater","carbon:this-side-up","carbon:threshold","carbon:thumbnail-1","carbon:thumbnail-2","carbon:thumbnail-preview","carbon:thumbs-down","carbon:thumbs-down-filled","carbon:thumbs-up","carbon:thumbs-up-filled","carbon:thunderstorm","carbon:thunderstorm-scattered","carbon:thunderstorm-scattered-night","carbon:thunderstorm-severe","carbon:thunderstorm-strong","carbon:ticket","carbon:tides","carbon:tif","carbon:time","carbon:time-filled","carbon:time-plot","carbon:timer","carbon:tool-box","carbon:tool-kit","carbon:tools","carbon:tools-alt","carbon:tornado","carbon:tornado-warning","carbon:touch-1","carbon:touch-1-down","carbon:touch-1-down-filled","carbon:touch-1-filled","carbon:touch-2","carbon:touch-2-filled","carbon:touch-interaction","carbon:tour","carbon:traffic-cone","carbon:traffic-event","carbon:traffic-flow","carbon:traffic-flow-incident","carbon:traffic-incident","carbon:traffic-weather-incident","carbon:train","carbon:train-heart","carbon:train-profile","carbon:train-speed","carbon:train-ticket","carbon:train-time","carbon:tram","carbon:transform-binary","carbon:transform-instructions","carbon:transform-language","carbon:transgender","carbon:translate","carbon:transmission-lte","carbon:transpose","carbon:trash-can","carbon:tree","carbon:tree-fall-risk","carbon:tree-view","carbon:tree-view-alt","carbon:triangle-down-outline","carbon:triangle-down-solid","carbon:triangle-left-outline","carbon:triangle-left-solid","carbon:triangle-outline","carbon:triangle-right-outline","carbon:triangle-right-solid","carbon:triangle-solid","carbon:trophy","carbon:trophy-filled","carbon:tropical-storm","carbon:tropical-storm-model-tracks","carbon:tropical-storm-tracks","carbon:tropical-warning","carbon:tsq","carbon:tsunami","carbon:tsv","carbon:tuning","carbon:two-factor-authentication","carbon:two-person-lift","carbon:txt","carbon:txt-reference","carbon:type-pattern","carbon:types","carbon:u1","carbon:u2","carbon:u3","carbon:umbrella","carbon:undefined","carbon:undefined-filled","carbon:undo","carbon:ungroup-objects","carbon:unknown","carbon:unknown-filled","carbon:unlink","carbon:unlocked","carbon:unsaved","carbon:up-to-top","carbon:update-now","carbon:upgrade","carbon:upload","carbon:upstream","carbon:url","carbon:usb","carbon:user","carbon:user-access","carbon:user-activity","carbon:user-admin","carbon:user-avatar","carbon:user-avatar-filled","carbon:user-avatar-filled-alt","carbon:user-certification","carbon:user-data","carbon:user-favorite","carbon:user-favorite-alt","carbon:user-favorite-alt-filled","carbon:user-filled","carbon:user-follow","carbon:user-identification","carbon:user-military","carbon:user-multiple","carbon:user-online","carbon:user-profile","carbon:user-profile-alt","carbon:user-role","carbon:user-service-desk","carbon:user-settings","carbon:user-simulation","carbon:user-speaker","carbon:user-sponsor","carbon:user-x-ray","carbon:uv-index","carbon:uv-index-alt","carbon:uv-index-filled","carbon:value-variable","carbon:van","carbon:vegetation-asset","carbon:vegetation-encroachment","carbon:vegetation-height","carbon:vehicle-api","carbon:vehicle-connected","carbon:vehicle-insights","carbon:vehicle-services","carbon:version","carbon:version-major","carbon:version-minor","carbon:version-patch","carbon:vertical-view","carbon:video","carbon:video-add","carbon:video-chat","carbon:video-filled","carbon:video-off","carbon:video-off-filled","carbon:video-player","carbon:view","carbon:view-filled","carbon:view-mode-1","carbon:view-mode-2","carbon:view-next","carbon:view-off","carbon:view-off-filled","carbon:virtual-column","carbon:virtual-column-key","carbon:virtual-desktop","carbon:virtual-machine","carbon:virtual-private-cloud","carbon:virtual-private-cloud-alt","carbon:visual-recognition","carbon:vlan","carbon:vlan-ibm","carbon:vmdk-disk","carbon:voice-activate","carbon:voicemail","carbon:volume-block-storage","carbon:volume-down","carbon:volume-down-alt","carbon:volume-down-filled","carbon:volume-down-filled-alt","carbon:volume-file-storage","carbon:volume-mute","carbon:volume-mute-filled","carbon:volume-object-storage","carbon:volume-up","carbon:volume-up-alt","carbon:volume-up-filled","carbon:volume-up-filled-alt","carbon:vpn","carbon:vpn-connection","carbon:vpn-policy","carbon:wallet","carbon:warning","carbon:warning-alt","carbon:warning-alt-filled","carbon:warning-alt-inverted","carbon:warning-alt-inverted-filled","carbon:warning-diamond","carbon:warning-filled","carbon:warning-hex","carbon:warning-hex-filled","carbon:warning-multiple","carbon:warning-other","carbon:warning-square","carbon:warning-square-filled","carbon:watch","carbon:watson","carbon:watson-machine-learning","carbon:watsonx","carbon:watsonx-ai","carbon:watsonx-data","carbon:watsonx-governance","carbon:wave-direction","carbon:wave-height","carbon:wave-period","carbon:weather-front-cold","carbon:weather-front-stationary","carbon:weather-front-warm","carbon:weather-station","carbon:web-services-cluster","carbon:web-services-container","carbon:web-services-definition","carbon:web-services-service","carbon:web-services-task","carbon:web-services-task-definition-version","carbon:webhook","carbon:websheet","carbon:wheat","carbon:white-paper","carbon:wifi","carbon:wifi-bridge","carbon:wifi-bridge-alt","carbon:wifi-controller","carbon:wifi-not-secure","carbon:wifi-off","carbon:wifi-secure","carbon:wikis","carbon:wind-gusts","carbon:wind-power","carbon:wind-stream","carbon:window-auto","carbon:window-base","carbon:window-black-saturation","carbon:window-overlay","carbon:window-preset","carbon:windy","carbon:windy-dust","carbon:windy-snow","carbon:windy-strong","carbon:winter-warning","carbon:wintry-mix","carbon:wireless-checkout","carbon:wmv","carbon:word-cloud","carbon:workflow-automation","carbon:workspace","carbon:workspace-import","carbon:worship","carbon:worship-christian","carbon:worship-jewish","carbon:worship-muslim","carbon:x","carbon:x-axis","carbon:xls","carbon:xml","carbon:y","carbon:y-axis","carbon:z","carbon:z-axis","carbon:z-lpar","carbon:z-systems","carbon:zip","carbon:zip-reference","carbon:zoom-area","carbon:zoom-fit","carbon:zoom-in","carbon:zoom-in-area","carbon:zoom-out","carbon:zoom-out-area","carbon:zoom-pan","carbon:zoom-reset","carbon:zos","carbon:zos-sysplex","fluent-mdl2:remove-from-trash","mdi:content-save","mdi:map-marker","ph:map-pin-fill","simple-icons:tiktok"] as const
diff --git a/packages/ui/icon/index.tsx b/packages/ui/icon/index.tsx
index 561b2ab2c8..4ca34f59e8 100644
--- a/packages/ui/icon/index.tsx
+++ b/packages/ui/icon/index.tsx
@@ -9,11 +9,13 @@ export const isValidIcon = (icon: unknown): icon is IconList =>
typeof icon === 'string' && iconList.includes(icon as IconList)
export const validateIcon = (icon: unknown): IconList => {
- if (isValidIcon(icon)) return icon
+ if (isValidIcon(icon)) {
+ return icon
+ }
return 'carbon:unknown-filled'
}
-const useStyles = createStyles((theme, { block, color }: IconStylesParams) => ({
+const useStyles = createStyles((_theme, { block, color }: IconStylesParams) => ({
root: {
display: block ? 'block' : undefined,
color,
@@ -23,7 +25,14 @@ const useStyles = createStyles((theme, { block, color }: IconStylesParams) => ({
export const Icon = memo(({ icon, block, className, ref, color, ...props }: CustomIconProps) => {
const { classes, cx } = useStyles({ block, color })
Iconify.displayName = 'Iconify'
- return
+ return (
+
+ )
})
Icon.displayName = '@weareinreach/ui/icon'
@@ -40,3 +49,4 @@ interface CustomIconifyIconProps extends IconifyIconProps, IconStylesParams {
type IconElementProps = SVGProps
type CustomIconProps = IconElementProps & CustomIconifyIconProps & { ref?: Ref }
+export { IconifyIconHTMLElement }
diff --git a/packages/ui/mockData/fieldOpt.ts b/packages/ui/mockData/fieldOpt.ts
index 7ac50baa08..f83763e8b9 100644
--- a/packages/ui/mockData/fieldOpt.ts
+++ b/packages/ui/mockData/fieldOpt.ts
@@ -57,6 +57,7 @@ const queryLanguages: MockAPIHandler<'fieldOpt', 'languages'> = async (query) =>
return activelyTranslated === record.activelyTranslated
}
}
+ return false
})
}
return languages
@@ -77,13 +78,17 @@ const queryCountries: MockAPIHandler<'fieldOpt', 'countries'> = async (query) =>
const queryGovDistsByCountry: MockAPIHandler<'fieldOpt', 'govDistsByCountry'> = async (query) => {
const govDistsByCountry = (await import('./json/fieldOpt.govDistsByCountry.json')).default
- if (query) return govDistsByCountry.filter(({ cca2 }) => cca2 === query)
+ if (query) {
+ return govDistsByCountry.filter(({ cca2 }) => cca2 === query)
+ }
return govDistsByCountry
}
const queryGovDistsByCountryNoSub: MockAPIHandler<'fieldOpt', 'govDistsByCountryNoSub'> = async (query) => {
const govDistByCountryNoSub = (await import('./json/fieldOpt.govDistsByCountryNoSub.json')).default
- if (query) return govDistByCountryNoSub.filter(({ cca2 }) => cca2 === query)
+ if (query) {
+ return govDistByCountryNoSub.filter(({ cca2 }) => cca2 === query)
+ }
return govDistByCountryNoSub
}
@@ -146,13 +151,15 @@ const countryGovDistMapSchema = z
.array()
const countryGovDistMap = async () => {
- const countryGovDistMapData = (await import('./json/fieldOpt.countryGovDistMap.json')).default
+ const { default: countryGovDistMapData } = (await import('./json/fieldOpt.countryGovDistMap.json')) as {
+ default: unknown
+ }
return new Map(countryGovDistMapSchema.parse(countryGovDistMapData))
}
const getSubDistricts: MockAPIHandler<'fieldOpt', 'getSubDistricts'> = async (id) => {
const data = (await import('./json/fieldOpt.getSubDistricts.json')).default
const filtered = data.filter(({ parentId }) => parentId === id)
- const formatted = filtered.map(({ parentId, ...data }) => data)
+ const formatted = filtered.map(({ parentId: _parentId, ...rest }) => rest)
return formatted
}
export const fieldOpt = {
@@ -199,7 +206,7 @@ export const fieldOpt = {
govDists: getTRPCMock({
path: ['fieldOpt', 'govDists'],
response: async (input) => {
- const data = (await import('./json/fieldOpt.govDists.json')).default
+ const data = (await import('./json/fieldOpt.govDists.json')).default as GovDistFieldOpts[]
if (input) {
const { parentsOnly, ...search } = input
@@ -212,10 +219,10 @@ export const fieldOpt = {
}
return isMatch
})
- const formatted = filtered.map(({ parentId, ...data }) => data)
- return formatted
+ const formattedFiltered = filtered.map(({ parentId: _parentId, ...rest }) => rest)
+ return formattedFiltered
}
- const formatted = data.map(({ parentId, ...data }) => data)
+ const formatted = data.map(({ parentId: _parentId, ...rest }) => rest)
return formatted
},
}),
@@ -262,3 +269,107 @@ interface CountryGovDistMapItem {
children: CountryGovDistMapItemBasic[]
parent?: CountryGovDistMapItemBasic & { parent?: CountryGovDistMapItemBasic }
}
+
+export interface GovDistFieldOpts {
+ id: string
+ tsKey: string
+ tsNs: TsNS
+ abbrev: null | string
+ country: Country
+ govDistType: GovDistType
+ parentId: ParentID | null
+ name: string
+ slug: string
+ iso: null | string
+ countryId: CountryID
+}
+
+export interface Country {
+ cca2: Cca2
+}
+
+export enum Cca2 {
+ CA = 'CA',
+ MX = 'MX',
+ PR = 'PR',
+ Us = 'US',
+}
+
+export enum CountryID {
+ Ctry01GW2HHDK7PACTC9GJ2XBMVPKY = 'ctry_01GW2HHDK7PACTC9GJ2XBMVPKY',
+ Ctry01GW2HHDK9M26M80SG63T21SVH = 'ctry_01GW2HHDK9M26M80SG63T21SVH',
+ Ctry01GW2HHDKAWXWYHAAESAA5HH94 = 'ctry_01GW2HHDKAWXWYHAAESAA5HH94',
+ Ctry01GW2HHDKB9DG2T2YZM5MFFVX9 = 'ctry_01GW2HHDKB9DG2T2YZM5MFFVX9',
+}
+
+export interface GovDistType {
+ tsKey: TsKey
+ tsNs: TsNS
+}
+
+export enum TsKey {
+ TypeCity = 'type-city',
+ TypeCounty = 'type-county',
+ TypeDistrict = 'type-district',
+ TypeProvince = 'type-province',
+ TypeState = 'type-state',
+ TypeTerritory = 'type-territory',
+}
+
+export enum TsNS {
+ GovDist = 'gov-dist',
+}
+
+export enum ParentID {
+ Gdst01GW2HHY0735M7CQSXR31HP114 = 'gdst_01GW2HHY0735M7CQSXR31HP114',
+ Gdst01GW2HHZ3C061BT60QBAD8WVJZ = 'gdst_01GW2HHZ3C061BT60QBAD8WVJZ',
+ Gdst01GW2HJ0MERT6FW07XV7PZWZWE = 'gdst_01GW2HJ0MERT6FW07XV7PZWZWE',
+ Gdst01GW2HJ1D3W61ZMBGY0FGKY9EC = 'gdst_01GW2HJ1D3W61ZMBGY0FGKY9EC',
+ Gdst01GW2HJ23GMD17FBJMJWD16PZ1 = 'gdst_01GW2HJ23GMD17FBJMJWD16PZ1',
+ Gdst01GW2HJ35FAMD0V0YSSPYPMG46 = 'gdst_01GW2HJ35FAMD0V0YSSPYPMG46',
+ Gdst01GW2HJ48BS27DYW8W4GNH4P2W = 'gdst_01GW2HJ48BS27DYW8W4GNH4P2W',
+ Gdst01GW2HJ4XTJT4GBEWDBY057B01 = 'gdst_01GW2HJ4XTJT4GBEWDBY057B01',
+ Gdst01GW2HJ5A278S2G84AB3N9FCW0 = 'gdst_01GW2HJ5A278S2G84AB3N9FCW0',
+ Gdst01GW2HJ5XJRY6B6JNVZ8G8NFJY = 'gdst_01GW2HJ5XJRY6B6JNVZ8G8NFJY',
+ Gdst01GW2HJ6WC0EDHHCHG998QT3N0 = 'gdst_01GW2HJ6WC0EDHHCHG998QT3N0',
+ Gdst01GW2HJ7VX37RF69KKXAYE05QN = 'gdst_01GW2HJ7VX37RF69KKXAYE05QN',
+ Gdst01GW2HJ8HJJWY8F1GKEM5R8QZ4 = 'gdst_01GW2HJ8HJJWY8F1GKEM5R8QZ4',
+ Gdst01GW2HJ9GVN301XN2SKRWE8Q3M = 'gdst_01GW2HJ9GVN301XN2SKRWE8Q3M',
+ Gdst01GW2HJAD7VVT46D0BHXQRV2WF = 'gdst_01GW2HJAD7VVT46D0BHXQRV2WF',
+ Gdst01GW2HJC4WJWMZA8VDNVVE5RZQ = 'gdst_01GW2HJC4WJWMZA8VDNVVE5RZQ',
+ Gdst01GW2HJDE344VFWCSNBYYSFDDW = 'gdst_01GW2HJDE344VFWCSNBYYSFDDW',
+ Gdst01GW2HJF2WCKZ47HGSYQFANCDZ = 'gdst_01GW2HJF2WCKZ47HGSYQFANCDZ',
+ Gdst01GW2HJG2676AX4NRXHWA4PB8B = 'gdst_01GW2HJG2676AX4NRXHWA4PB8B',
+ Gdst01GW2HJH13NCXACKZGG242PM97 = 'gdst_01GW2HJH13NCXACKZGG242PM97',
+ Gdst01GW2HJHQBKA67H0WWG35J4PV7 = 'gdst_01GW2HJHQBKA67H0WWG35J4PV7',
+ Gdst01GW2HJJGA979WFBS7S7ECK0JK = 'gdst_01GW2HJJGA979WFBS7S7ECK0JK',
+ Gdst01GW2HJK994XZPC3KNCPVST015 = 'gdst_01GW2HJK994XZPC3KNCPVST015',
+ Gdst01GW2HJMBQGM1ZDVR1TJX4N6DY = 'gdst_01GW2HJMBQGM1ZDVR1TJX4N6DY',
+ Gdst01GW2HJMYCBT3EWB9XCX2VSMK9 = 'gdst_01GW2HJMYCBT3EWB9XCX2VSMK9',
+ Gdst01GW2HJPZYX059W3SHQW8D9F7M = 'gdst_01GW2HJPZYX059W3SHQW8D9F7M',
+ Gdst01GW2HJQZ5J517QW02C84M80WD = 'gdst_01GW2HJQZ5J517QW02C84M80WD',
+ Gdst01GW2HJRVH0VX93NDHEJ0QK158 = 'gdst_01GW2HJRVH0VX93NDHEJ0QK158',
+ Gdst01GW2HJSQZ19Y230FJHNKHSW89 = 'gdst_01GW2HJSQZ19Y230FJHNKHSW89',
+ Gdst01GW2HJTSK0AMAVYF9QD9GXBAR = 'gdst_01GW2HJTSK0AMAVYF9QD9GXBAR',
+ Gdst01GW2HJVFHMQEZZ1AKH9QETVP6 = 'gdst_01GW2HJVFHMQEZZ1AKH9QETVP6',
+ Gdst01GW2HJW29RXPB0ZW6ZTTPH7DY = 'gdst_01GW2HJW29RXPB0ZW6ZTTPH7DY',
+ Gdst01GW2HJXH936VB5WWAHK8S8X0A = 'gdst_01GW2HJXH936VB5WWAHK8S8X0A',
+ Gdst01GW2HJY7KQKE8XCP6BM8WC459 = 'gdst_01GW2HJY7KQKE8XCP6BM8WC459',
+ Gdst01GW2HJZG4VMQ7QWQ3MHXG3S8K = 'gdst_01GW2HJZG4VMQ7QWQ3MHXG3S8K',
+ Gdst01GW2HK0N4V9YBGBSQVN4JRKKW = 'gdst_01GW2HK0N4V9YBGBSQVN4JRKKW',
+ Gdst01GW2HK1MBAAXAR655YEESJRB1 = 'gdst_01GW2HK1MBAAXAR655YEESJRB1',
+ Gdst01GW2HK2PW0GCZATZ6YX9RG8FE = 'gdst_01GW2HK2PW0GCZATZ6YX9RG8FE',
+ Gdst01GW2HK3G7JGSCMVRQERYCRQGY = 'gdst_01GW2HK3G7JGSCMVRQERYCRQGY',
+ Gdst01GW2HK49A5XQ8ZDFKQSF098SJ = 'gdst_01GW2HK49A5XQ8ZDFKQSF098SJ',
+ Gdst01GW2HK51XDFN3Q0ND2NCGBN14 = 'gdst_01GW2HK51XDFN3Q0ND2NCGBN14',
+ Gdst01GW2HK5R9S8ZRWG9Z3BPFAXND = 'gdst_01GW2HK5R9S8ZRWG9Z3BPFAXND',
+ Gdst01GW2HK6H7B5T82KZ82DZSFNR0 = 'gdst_01GW2HK6H7B5T82KZ82DZSFNR0',
+ Gdst01GW2HK7G3WV9NP68CJ02WPMV7 = 'gdst_01GW2HK7G3WV9NP68CJ02WPMV7',
+ Gdst01GW2HK8W4ZDJSZDPWZH2XH023 = 'gdst_01GW2HK8W4ZDJSZDPWZH2XH023',
+ Gdst01GW2HK9J2HNR9ZCJJHF8WAGDT = 'gdst_01GW2HK9J2HNR9ZCJJHF8WAGDT',
+ Gdst01GW2HKADSS3SDS9XJV1WHMTVY = 'gdst_01GW2HKADSS3SDS9XJV1WHMTVY',
+ Gdst01GW2HKC6JBVM1S4P89T664V0A = 'gdst_01GW2HKC6JBVM1S4P89T664V0A',
+ Gdst01GW2HKD240CAP65TPYPT32MRR = 'gdst_01GW2HKD240CAP65TPYPT32MRR',
+ Gdst01GW2HKDJ5VV91D7JP3V6DE3DK = 'gdst_01GW2HKDJ5VV91D7JP3V6DE3DK',
+ Gdst01GW2HKEDZ2K9QXJ96SKR44EGV = 'gdst_01GW2HKEDZ2K9QXJ96SKR44EGV',
+}
diff --git a/packages/ui/mockData/orgPhone.ts b/packages/ui/mockData/orgPhone.ts
index 8cc9bb2d45..6ddf00146d 100644
--- a/packages/ui/mockData/orgPhone.ts
+++ b/packages/ui/mockData/orgPhone.ts
@@ -8,11 +8,6 @@ export const orgPhone = {
return data
},
}),
- upsertMany: getTRPCMock({
- path: ['orgPhone', 'upsertMany'],
- type: 'mutation',
- response: () => [],
- }),
update: getTRPCMock({
path: ['orgPhone', 'update'],
type: 'mutation',
diff --git a/packages/ui/modals/ModalTitle.tsx b/packages/ui/modals/ModalTitle.tsx
index c44ef17131..8586acdedc 100644
--- a/packages/ui/modals/ModalTitle.tsx
+++ b/packages/ui/modals/ModalTitle.tsx
@@ -5,15 +5,22 @@ import { ActionButtons } from '~ui/components/core/ActionButtons'
import { Breadcrumb, type BreadcrumbProps, isValidBreadcrumbProps } from '~ui/components/core/Breadcrumb'
import { useCustomVariant } from '~ui/hooks'
-export const ModalTitle = (props: ModalTitleProps) => {
+export const ModalTitle = (props: _ModalTitleProps) => {
const { breadcrumb, icons, rightText, serviceId } = props
const variants = useCustomVariant()
if (!isValidBreadcrumbProps(breadcrumb)) {
throw new Error('invalid Breadcrumb props')
}
const iconMap = {
- save: ,
- share: ,
+ save: (
+
+ ),
+ share: ,
} as const
const displayIcons = icons?.length ? icons.map((item) => iconMap[item]) : undefined
@@ -43,11 +50,14 @@ export const ModalTitle = (props: ModalTitleProps) => {
// type TitleIcons = keyof typeof iconMap
-export type ModalTitleProps = {
+type ToolbarIcons = 'save' | 'share'
+
+type _ModalTitleProps = {
breadcrumb: Omit & {
onClick: MouseEventHandler | (() => void)
}
- icons?: ('save' | 'share')[]
+ icons?: TIcons
rightText?: string
- serviceId?: string
+ serviceId?: 'save' extends TIcons[number] ? string : never
}
+export type ModalTitleProps = _ModalTitleProps
diff --git a/packages/ui/modals/QuickPromotion.tsx b/packages/ui/modals/QuickPromotion.tsx
index 55bd84d555..7a8180913b 100644
--- a/packages/ui/modals/QuickPromotion.tsx
+++ b/packages/ui/modals/QuickPromotion.tsx
@@ -1,13 +1,4 @@
-import {
- Box,
- type ButtonProps,
- createPolymorphicComponent,
- Group,
- Modal,
- Stack,
- Text,
- Title,
-} from '@mantine/core'
+import { Box, createPolymorphicComponent, Group, Modal, Stack, Text, Title } from '@mantine/core'
import { useDisclosure } from '@mantine/hooks'
import { useRouter } from 'next/router'
import { useSession } from 'next-auth/react'
@@ -15,7 +6,7 @@ import { Trans, useTranslation } from 'next-i18next'
import { forwardRef, type MouseEventHandler, useCallback, useEffect, useMemo } from 'react'
import { Breadcrumb, type BreadcrumbProps } from '~ui/components/core/Breadcrumb'
-import { Button } from '~ui/components/core/Button'
+import { Button, type ButtonProps } from '~ui/components/core/Button'
import { Link } from '~ui/components/core/Link'
import { useCustomVariant, useScreenSize } from '~ui/hooks'
@@ -115,14 +106,14 @@ const QuickPromotionModalBody = forwardRef{t('dont-have-account')}
- {!autoLaunch && }
+ {!autoLaunch && }
>
)
}
)
QuickPromotionModalBody.displayName = 'QuickPromotionModal'
-export const QuickPromotionModal = createPolymorphicComponent<'button', QuickPromotionModalProps>(
+export const QuickPromotionModal = createPolymorphicComponent(
QuickPromotionModalBody
)
diff --git a/packages/ui/modals/Review.tsx b/packages/ui/modals/Review.tsx
index 251f905785..3f687561a8 100644
--- a/packages/ui/modals/Review.tsx
+++ b/packages/ui/modals/Review.tsx
@@ -1,8 +1,9 @@
-import { Box, type ButtonProps, createPolymorphicComponent, Group, Modal } from '@mantine/core'
+import { Box, createPolymorphicComponent, Group, Modal } from '@mantine/core'
import { useDisclosure } from '@mantine/hooks'
import { forwardRef } from 'react'
import { Breadcrumb } from '~ui/components/core/Breadcrumb'
+import { Button, type ButtonProps } from '~ui/components/core/Button'
import { UserReviewSubmit } from '~ui/components/core/UserReviewSubmit'
import { useScreenSize } from '~ui/hooks/useScreenSize'
@@ -22,13 +23,13 @@ const ReviewModalBody = forwardRef((props,
-
+
>
)
})
ReviewModalBody.displayName = 'ReviewModal'
-export const ReviewModal = createPolymorphicComponent<'button', ReviewModalProps>(ReviewModalBody)
+export const ReviewModal = createPolymorphicComponent(ReviewModalBody)
export type ReviewModalProps = ButtonProps
diff --git a/packages/ui/theme/common.tsx b/packages/ui/theme/common.tsx
index f143c860aa..0480f94ae7 100644
--- a/packages/ui/theme/common.tsx
+++ b/packages/ui/theme/common.tsx
@@ -120,10 +120,10 @@ const themeCustomObj = {
border: {
default: '1px solid #d9d9d9',
},
- colors,
animations: {
shake,
},
+ colors,
} as const //satisfies MantineThemeOther
export const commonTheme = {
@@ -655,7 +655,7 @@ export const commonTheme = {
({
radius: 'xl',
}) satisfies SkeletonProps,
- styles: (theme, { circle }: SkeletonStylesParams) =>
+ styles: (_theme, { circle }: SkeletonStylesParams) =>
({
root: {
minWidth: circle ? undefined : rem(100),