Skip to content

Commit fb91c6b

Browse files
authored
Conversation tagging (#53)
* Additions to dropdown & svg icon * wip tag changes * Small extension * fixes typing on translated enum
1 parent 1f1dc08 commit fb91c6b

File tree

6 files changed

+86
-32
lines changed

6 files changed

+86
-32
lines changed

components/KernDropdown.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export default function KernDropdown(props: KernDropdownProps) {
8484
case "bottom": return "-translate-x-1/2 left-1/2 top-full";
8585
case "left": return "-translate-y-1/2 top-1/2 right-full";
8686
case "right": return "-translate-y-1/2 top-1/2 left-full";
87+
case "leftBottom": return "top-3/4 right-full";
8788
}
8889
}, [props.positionDropdown]);
8990

components/SVGIcon.tsx

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,66 @@
11
import { IconHammer, IconSettingsFilled, IconZoomIn, IconZoomOut } from '@tabler/icons-react';
2-
import { MemoIconBolt, MemoIconChevronDown, MemoIconCode, MemoIconDotsVertical, MemoIconEdit, MemoIconExternalLink, MemoIconFileInfo, MemoIconFilePencil, MemoIconLoader, MemoIconPlayerPlayFilled, MemoIconPlus, MemoIconSettings, MemoIconShieldCheckFilled, MemoIconShieldFilled, MemoIconSquare, MemoIconSquareCheck, MemoIconTrash } from './kern-icons/icons';
2+
import { MemoIconBolt, MemoIconChevronDown, MemoIconCode, MemoIconDotsVertical, MemoIconEdit, MemoIconExternalLink, MemoIconFileInfo, MemoIconFilePencil, MemoIconLoader, MemoIconPlayerPlayFilled, MemoIconPlus, MemoIconSettings, MemoIconShieldCheckFilled, MemoIconShieldFilled, MemoIconSquare, MemoIconSquareCheck, MemoIconTag, MemoIconTrash } from './kern-icons/icons';
33

44
export const SUPPORTED_ICONS = ['IconCode', 'IconBolt', 'IconSquareCheck', 'IconSquare', 'IconPlayerPlayFilled', 'IconTrash', 'IconExternalLink',
55
'IconLoader', 'IconFilePencil', 'IconFileInfo', 'IconEdit', 'IconShieldFilled', 'IconShieldCheckFilled', 'IconPlus', 'IconSettings', 'IconSettingsFilled',
6-
'IconHammer', 'IconZoomIn', 'IconZoomOut'
7-
6+
'IconHammer', 'IconZoomIn', 'IconZoomOut', 'IconTag'
87
]
98

109
type SVGIconProps = {
1110
icon: string,
1211
size?: number,
1312
strokeWidth?: number,
14-
useFillForIcons?: boolean
13+
useFillForIcons?: boolean,
14+
addClasses?: string
1515
}
1616

1717
export default function SVGIcon(props: SVGIconProps) {
1818
switch (props.icon) {
19+
case 'IconTag':
20+
return <MemoIconTag size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
1921
case 'IconCode':
20-
return <MemoIconCode size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
22+
return <MemoIconCode size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
2123
case 'IconBolt':
22-
return <MemoIconBolt size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
24+
return <MemoIconBolt size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
2325
case 'IconSquareCheck':
24-
return <MemoIconSquareCheck size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
26+
return <MemoIconSquareCheck size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
2527
case 'IconSquare':
26-
return <MemoIconSquare size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
28+
return <MemoIconSquare size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
2729
case 'IconPlayerPlayFilled':
28-
return <MemoIconPlayerPlayFilled size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
30+
return <MemoIconPlayerPlayFilled size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
2931
case 'IconTrash':
30-
return <MemoIconTrash size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
32+
return <MemoIconTrash size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
3133
case 'IconExternalLink':
32-
return <MemoIconExternalLink size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
34+
return <MemoIconExternalLink size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
3335
case 'IconChevronDown':
34-
return <MemoIconChevronDown size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
36+
return <MemoIconChevronDown size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
3537
case 'IconDotsVertical':
36-
return <MemoIconDotsVertical size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
38+
return <MemoIconDotsVertical size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
3739
case 'IconLoader':
38-
return <MemoIconLoader size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
40+
return <MemoIconLoader size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
3941
case 'IconFilePencil':
40-
return <MemoIconFilePencil size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
42+
return <MemoIconFilePencil size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
4143
case 'IconFileInfo':
42-
return <MemoIconFileInfo size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
44+
return <MemoIconFileInfo size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
4345
case 'IconEdit':
44-
return <MemoIconEdit size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
46+
return <MemoIconEdit size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
4547
case 'IconShieldFilled':
46-
return <MemoIconShieldFilled size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
48+
return <MemoIconShieldFilled size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
4749
case 'IconShieldCheckFilled':
48-
return <MemoIconShieldCheckFilled size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
50+
return <MemoIconShieldCheckFilled size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
4951
case 'IconPlus':
50-
return <MemoIconPlus size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
52+
return <MemoIconPlus size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
5153
case 'IconSettings':
52-
return <MemoIconSettings size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
54+
return <MemoIconSettings size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
5355
case 'IconSettingsFilled':
54-
return <IconSettingsFilled size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
56+
return <IconSettingsFilled size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
5557
case 'IconHammer':
56-
return <IconHammer size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
58+
return <IconHammer size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
5759
case 'IconZoomIn':
58-
return <IconZoomIn size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
60+
return <IconZoomIn size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
5961
case 'IconZoomOut':
60-
return <IconZoomOut size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
61-
default: return <MemoIconLoader size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''}`} />
62+
return <IconZoomOut size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
63+
default: return <MemoIconLoader size={props.size} strokeWidth={props.strokeWidth} className={`${props.useFillForIcons ? 'fill-gray-800' : ''} ${props.addClasses}`} />
6264
}
6365

6466
}

components/SwitchWithLabel.tsx

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { combineClassNames } from "@/submodules/javascript-functions/general";
2+
import { Switch } from "@headlessui/react";
3+
import { Tooltip } from "@nextui-org/react";
4+
import { useMemo } from "react";
5+
import { MemoIconAlertCircle, MemoIconAlertTriangle } from "./kern-icons/icons";
6+
7+
8+
type Props = {
9+
checked: boolean;
10+
onChange: () => void;
11+
label: string;
12+
colorLabel?: string;
13+
colorActive?: string;
14+
colorInactive?: string;
15+
addClassesGroup?: string;
16+
tooltip?: string;
17+
}
18+
19+
export default function SwitchWithLabel(props: Props) {
20+
21+
const finalColorActive = props.colorActive || 'bg-green-600';
22+
const finalColorInactive = props.colorInactive || 'bg-gray-200';
23+
const finalColorLabel = props.colorLabel || 'text-gray-700';
24+
25+
const tooltip = useMemo(() => props.tooltip ? <Tooltip content={props.tooltip} color="invert" placement="top"><MemoIconAlertTriangle className="w-6 h-6" /></Tooltip> : null, [props.tooltip])
26+
27+
return <Switch.Group as="div" className={combineClassNames("flex items-center justify-between", props.addClassesGroup)}>
28+
<Switch.Description as="span" className={`font-medium ${finalColorLabel}`}>
29+
{props.label}
30+
</Switch.Description>
31+
<div className="flex flex-row gap-x-2 items-center">
32+
<Switch
33+
checked={props.checked}
34+
onChange={props.onChange}
35+
className={combineClassNames(
36+
props.checked ? finalColorActive : finalColorInactive,
37+
'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-green-600 focus:ring-offset-2'
38+
)}
39+
>
40+
<span
41+
aria-hidden="true"
42+
className={combineClassNames(
43+
props.checked ? 'translate-x-5' : 'translate-x-0',
44+
'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out'
45+
)}
46+
/>
47+
</Switch>
48+
{tooltip}
49+
</div>
50+
</Switch.Group>
51+
}

hooks/enums/useEnumOptionsTranslated.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next';
55

66
const cache = {};
77

8-
function getEnumOptionsForLanguage<T>(enumObj: T, lookupKey: string, t: any, language: string): { name: string, value: T }[] {
8+
function getEnumOptionsForLanguage<T>(enumObj: T, lookupKey: string, t: any, language: string): { name: string, value: T[keyof T] }[] {
99
if (!(lookupKey in cache)) cache[lookupKey] = {};
1010
if (cache[lookupKey][language]) return cache[lookupKey][language];
1111
const finalArray = enumToArray(enumObj, { nameFunction: (s) => { return t(`${lookupKey}.${s}`) } });
@@ -16,7 +16,7 @@ function getEnumOptionsForLanguage<T>(enumObj: T, lookupKey: string, t: any, lan
1616
// unfortunately we need to provide the lookupKey ourselves which is the Enum name itself.
1717
// there is no way to get the name of the enum at runtime since they are compiled away
1818
// https://stackoverflow.com/a/59824941/19801189
19-
export default function useEnumOptionsTranslated<T>(enumObj: T, lookupKey: string, translationScope: string): { name: string, value: T }[] {
19+
export default function useEnumOptionsTranslated<T>(enumObj: T, lookupKey: string, translationScope: string): { name: string, value: T[keyof T] }[] {
2020
const { t, i18n } = useTranslation(translationScope);
2121
const values = useMemo(() => getEnumOptionsForLanguage(enumObj, lookupKey, t, i18n.language), [i18n.language]);
2222
return values;

hooks/enums/useEnumStateTranslated.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import useRefState from "../useRefState";
66
// only works if the corresponding enum is translated in the i18n file with the lookupKey
77
// example: cognition-ui> PATExpiresAt
88
export default function useEnumStateTranslated<T>(enumObj: T, lookupKey: string, translationScope?: string): [
9-
{ name: string, value: T },
10-
Dispatch<SetStateAction<{ name: string; value: T; }>>,
11-
{ name: string, value: T }[]
9+
{ name: string, value: T[keyof T] },
10+
Dispatch<SetStateAction<{ name: string; value: T[keyof T]; }>>,
11+
{ name: string, value: T[keyof T] }[]
1212
] {
1313
const _translationScope = translationScope || 'enums';
1414
const options = useEnumOptionsTranslated(enumObj, lookupKey, _translationScope);

types/dropdown.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export type KernDropdownProps = {
8989
fontSizeClass?: string;
9090
filteredOptions?: (option: string) => void;
9191
ignoreDisabledForSearch?: boolean;
92-
positionDropdown?: "top" | "bottom" | "left" | "right";
92+
positionDropdown?: "top" | "bottom" | "left" | "right" | "leftBottom";
9393
scrollAfterNOptions?: number;
9494
dropdownAdd?: JSX.Element[];
9595
forceOverwriteOpen?: boolean;

0 commit comments

Comments
 (0)