Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
f467b28
Added ObjectTranlation type
Dec 13, 2023
032288f
Added useObjectTranslation hook
Dec 13, 2023
e8a6560
Renamed CaptureCaptureHUDButtons to PhotoCaptureHUDButtons
Dec 13, 2023
bdda7a4
Added PhotoCaptureHUDSightsSlider component: display a scrolling sigh…
Dec 13, 2023
11a3602
Added PhotoCaptureHUDCounter component
Dec 13, 2023
8fc01cf
Added PhotoCaptureHUDPreview component that render SightsSlider and C…
Dec 13, 2023
83ae2cb
Added PhotoCaptureHUD that render the HUDPreview and HUDButtons
Dec 13, 2023
9cc3b44
Fix: lint
dlymonk Dec 13, 2023
b763122
fix: applying feedback review, Sights liftup in PhotoCaptureHUD
dlymonk Dec 14, 2023
730e020
rename Slider to SightsSlider
dlymonk Dec 14, 2023
9aea4d7
useObjectTranslation/CaptureHUDPreviewtests added + fix
dlymonk Dec 20, 2023
412cee7
directory structure changed by PreviewSight and PreviewAddDamage view
dlymonk Dec 20, 2023
5b81177
TSDoc added to i18n language types
dlymonk Dec 20, 2023
f8c6a40
fix on tests and import
dlymonk Dec 20, 2023
6074784
useSightLabel's hook moved to @monkvision/common + SightSlider compon…
dlymonk Dec 21, 2023
3790fbe
SightsSlider tests done
dlymonk Dec 21, 2023
6f160fd
sight overlay now take all preview screen space
dlymonk Dec 21, 2023
1ea642d
sight centered in slider when selected
dlymonk Dec 22, 2023
b54053a
responsive style added when portrait view
dlymonk Dec 22, 2023
8ecd16f
when the picture is taken, the sight button(in the slider) changed to…
dlymonk Dec 22, 2023
7c3f7ca
TSDoc useSightLabel
dlymonk Dec 22, 2023
603f619
keep sight button selected in the center when switching back to main …
dlymonk Dec 22, 2023
e6ee87e
TSDoc useObjectTranslation & useSightLabel hooks
dlymonk Dec 26, 2023
181f6a1
fixing PR review comments
dlymonk Dec 26, 2023
abf9a22
PhotoCapture logic and component plug to camera. refacto + rename fun…
dlymonk Dec 28, 2023
484dc7c
renaming component for more readability + callback mode (avoiding rer…
dlymonk Dec 28, 2023
93794b9
tests + i18nAddDamage instance moved to separate file
dlymonk Dec 29, 2023
3abe6f8
SightOverlay stays in CameraPreview frame in both landscape and portr…
dlymonk Jan 2, 2024
6244d51
SightOverlay equals CameraPreview in aspect ratio
dlymonk Jan 2, 2024
b59f3ca
fixing PR (check comments)
dlymonk Jan 3, 2024
d016fed
fixing PR (check comments)
dlymonk Jan 4, 2024
fd1fd92
Created SwitchButton component (#656)
souyahia-monk Jan 5, 2024
aaedcb5
import changeAlpha function in usePhotoHUDButtonBackground hook
dlymonk Jan 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const {
toCamelCase,
getRGBAFromString,
getHexFromRGBA,
changeAlpha,
shadeColor,
InteractiveVariation,
getInteractiveVariants,
Expand All @@ -30,6 +31,7 @@ export = {
toCamelCase,
getRGBAFromString,
getHexFromRGBA,
changeAlpha,
shadeColor,
InteractiveVariation,
getInteractiveVariants,
Expand Down Expand Up @@ -71,4 +73,6 @@ export = {
})),
useResponsiveStyle: jest.fn(() => ({ responsive: jest.fn(() => null) })),
useWindowDimensions: jest.fn(() => ({ width: 0, height: 0, isPortrait: false })),
useObjectTranslation: jest.fn(() => ({ tObj: jest.fn(() => {}) })),
useSightLabel: jest.fn(() => ({ label: jest.fn(() => {}) })),
};

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export = {
/* Actual exports */
/* Mocks */
PhotoCaptureHUDButtons: jest.fn(() => <></>),
PhotoCaptureHUDAddDamagePreview: jest.fn(() => <></>),
PhotoCaptureHUDSightPreview: jest.fn(() => <></>),
SightsCounter: jest.fn(() => <></>),
AddDamageButton: jest.fn(() => <></>),
SightsSlider: jest.fn(() => <></>),
PhotoCaptureHUD: jest.fn(() => <></>),
PhotoCapture: jest.fn(() => <></>),
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ export = {
/* Mocks */
initReactI18next: {},
I18nextProvider: jest.fn(({ children }) => <>{children}</>),
useTranslation: jest.fn(() => ({ t: jest.fn((str) => str) })),
useTranslation: jest.fn(() => ({ t: jest.fn((str) => str), i18n: { language: 'en' } })),
};
1 change: 1 addition & 0 deletions packages/private/test-utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './expects';
export * from './dom';
export * from './styles';
7 changes: 7 additions & 0 deletions packages/private/test-utils/src/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function getNumberFromCSSProperty(prop: string | undefined | null): number {
expect(typeof prop).toBe('string');
const reg = /^(\d+)\D*$/;
expect(prop).toMatch(reg);
const result = (prop as string).match(reg);
return Number((result as string[])[1]);
}
5 changes: 4 additions & 1 deletion packages/public/camera-web/src/Camera/Camera.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ export function Camera({
);

return HUDComponent ? (
<HUDComponent handle={{ takePicture, error, retry, isLoading }} cameraPreview={cameraPreview} />
<HUDComponent
handle={{ takePicture, error, retry, isLoading, dimensions }}
cameraPreview={cameraPreview}
/>
) : (
<>{cameraPreview}</>
);
Expand Down
8 changes: 7 additions & 1 deletion packages/public/camera-web/src/Camera/CameraHUD.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ComponentType, ReactElement } from 'react';
import { PixelDimensions } from '@monkvision/types';
import { MonkPicture, UserMediaError } from './hooks';

/**
Expand All @@ -21,6 +22,11 @@ export interface CameraHandle {
* A function to retry the camera stream fetching in case of error.
*/
retry: () => void;
/**
* The dimensions of the resulting camera stream. Note that these dimensions can differ from the ones given in the
* stream constraints if they are not supported or available on the current device.
*/
dimensions: PixelDimensions | null;
}

/**
Expand All @@ -40,7 +46,7 @@ export interface CameraEventHandlers {
*/
export interface CameraHUDProps {
/**
* The camera preview element. The HUD component is exepcted to take this element as a prop and display it however it
* The camera preview element. The HUD component is expected to take this element as a prop and display it however it
* wants to.
*/
cameraPreview: ReactElement;
Expand Down
1 change: 1 addition & 0 deletions packages/public/camera-web/test/Camera/Camera.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ describe('Camera component', () => {
error: useCameraPreviewResultMock.error,
retry: useCameraPreviewResultMock.retry,
isLoading: useCameraPreviewResultMock.isLoading || useTakePictureResultMock.isLoading,
dimensions: useCameraPreviewResultMock.dimensions,
},
cameraPreview: expect.anything(),
});
Expand Down
32 changes: 32 additions & 0 deletions packages/public/common-ui-web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,35 @@ function MyComponent() {
| sight | Sight | The sight to display the SVG overlay of. | ✔️ | |
| getAttributes | <code>(element: Element, groupIds: string[]) => SVGProps<SVGSVGElement> &#124; null</code> | A customization function that lets you specify custom HTML attributes to give to the tags in the SVG file based on the HTML element itself and the IDs of the groups it is part of. | | |
| getInnerText | <code>(element: Element, groupIds: string[]) => string &#124; null</code> | A customization function that lets you specify the innner text of the tags in the SVG file based on the HTML element itself and the IDs of the groups it is part of. | | |

## SwitchButton
### Description
Switch button component that can be used to turn ON or OFF a feature.

### Example
```tsx
import { SwitchButton } from '@monkvision/common-ui-web';

export function MyComponent() {
const [checked, setChecked] = useState(false);
return (
<div>
<SwitchButton checked={checked} onSwitch={(value) => setChecked(value)} />
</div>
);
}
```

### Props
| Prop | Type | Description | Required | Default Value |
|-------------------------|----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-----------------|
| size | `'normal' &#124; 'small'` | The size of the button. Normal buttons are bigger and have their icon and labels inside the button. Small buttons are smaller, accept no label and have their icon inside the knob. | | 'normal' |
| checked | boolean | Boolean used to control the SwitchButton. Set to `true` to make the Button switched on and `false` for off. | | false |
| onSwitch | `(value: boolean) => void` | Callback called when the SwitchButton is switched. The value passed as the first parameter is the result `checked` value. | | |
| disabled | boolean | Boolean indicating if the button is disabled or not. | | false |
| checkedPrimaryColor | ColorProp | Primary color (background and knob overlay color) of the button when it is checked. | | 'primary' |
| checkedSecondaryColor | ColorProp | Secondary color (knob, labels and icons color) of the button when it is checked. | | 'text-white' |
| uncheckedPrimaryColor | ColorProp | Primary color (background and knob overlay color) of the button when it is unchecked. | | 'text-tertiary' |
| uncheckedSecondaryColor | ColorProp | Secondary color (knob, labels and icons color) of the button when it is unchecked. | | 'text-white' |
| checkedLabel | ColorProp | Custom label that can be displayed instead of the check icon when the button is checked. This prop is ignored for small buttons. | | |
| uncheckedLabel | ColorProp | Custom label that can be displayed when the button is unchecked. This prop is ignored for small buttons. | | |
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { Styles } from '@monkvision/types';

export const slideTransitionFrames = '0.3s ease-out';

export const sizes = {
normal: {
width: 65,
height: 30,
knobPadding: 2,
labelPadding: 10,
knobOverlayExpansion: 3,
iconSize: 18,
},
small: {
width: 36,
height: 22,
knobPadding: 2,
knobOverlayExpansion: 2,
iconSize: 10,
},
};

export const styles: Styles = {
button: {
width: sizes.normal.width,
height: sizes.normal.height,
padding: `0 ${sizes.normal.labelPadding}px`,
overflow: 'visible',
borderRadius: 9999999,
position: 'relative',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
border: 'none',
cursor: 'pointer',
transition: `background-color ${slideTransitionFrames}`,
},
buttonDisabled: {
opacity: 0.37,
cursor: 'default',
},
buttonSmall: {
padding: 0,
width: sizes.small.width,
height: sizes.small.height,
},
knobOverlay: {
width: sizes.normal.height + 2 * sizes.normal.knobOverlayExpansion,
height: sizes.normal.height + 2 * sizes.normal.knobOverlayExpansion,
borderRadius: '50%',
position: 'absolute',
top: -sizes.normal.knobOverlayExpansion,
left: -sizes.normal.knobOverlayExpansion,
transition: `left ${slideTransitionFrames}`,
},
knobOverlaySmall: {
width: sizes.small.height + 2 * sizes.small.knobOverlayExpansion,
height: sizes.small.height + 2 * sizes.small.knobOverlayExpansion,
top: -sizes.small.knobOverlayExpansion,
left: -sizes.small.knobOverlayExpansion,
},
knobOverlayChecked: {
left: sizes.normal.width - sizes.normal.height - sizes.normal.knobOverlayExpansion,
},
knobOverlaySmallChecked: {
left: sizes.small.width - sizes.small.height - sizes.small.knobOverlayExpansion,
},
knob: {
width: sizes.normal.height - 2 * sizes.normal.knobPadding,
height: sizes.normal.height - 2 * sizes.normal.knobPadding,
borderRadius: '50%',
position: 'absolute',
top: sizes.normal.knobPadding,
left: sizes.normal.knobPadding,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transition: `left ${slideTransitionFrames}`,
},
knobSmall: {
width: sizes.small.height - 2 * sizes.small.knobPadding,
height: sizes.small.height - 2 * sizes.small.knobPadding,
top: sizes.small.knobPadding,
left: sizes.small.knobPadding,
},
knobChecked: {
left: sizes.normal.width - sizes.normal.height + sizes.normal.knobPadding,
},
knobSmallChecked: {
left: sizes.small.width - sizes.small.height + sizes.small.knobPadding,
},
label: {
fontSize: 12,
fontWeight: 400,
lineHeight: '18px',
letterSpacing: '0.4px',
transition: `opacity ${slideTransitionFrames}`,
},
icon: {
transition: `opacity ${slideTransitionFrames}`,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { useInteractiveStatus } from '@monkvision/common';
import { SwitchButtonProps, useSwitchButtonStyles } from './hooks';
import { Icon } from '../../icons';

/**
* Switch button component that can be used to turn ON or OFF a feature.
*
* @see https://uxplanet.org/checkbox-vs-toggle-switch-7fc6e83f10b8
* @example
* export function MyComponent() {
* const [checked, setChecked] = useState(false);
* return (
* <div>
* <SwitchButton checked={checked} onSwitch={(value) => setChecked(value)} />
* </div>
* );
* }
*/
export function SwitchButton({
size = 'normal',
checked = false,
onSwitch,
disabled = false,
checkedPrimaryColor = 'primary',
checkedSecondaryColor = 'text-white',
uncheckedPrimaryColor = 'text-tertiary',
uncheckedSecondaryColor = 'text-white',
checkedLabel,
uncheckedLabel,
}: SwitchButtonProps) {
const { status, eventHandlers } = useInteractiveStatus({ disabled });
const switchButtonStyles = useSwitchButtonStyles({
size,
checked,
checkedPrimaryColor,
checkedSecondaryColor,
uncheckedPrimaryColor,
uncheckedSecondaryColor,
status,
});

const handleSwitch = () => {
if (onSwitch) {
onSwitch(!checked);
}
};

return (
<button
style={switchButtonStyles.buttonStyle}
onClick={handleSwitch}
disabled={disabled}
{...eventHandlers}
data-testid='switch-btn'
>
{size === 'normal' && !checkedLabel && (
<Icon
icon='check'
primaryColor={switchButtonStyles.icon.color}
size={switchButtonStyles.icon.size}
style={switchButtonStyles.icon.style}
/>
)}
{size === 'normal' && checkedLabel && (
<div style={switchButtonStyles.checkedLabelStyle}>{checkedLabel ?? ''}</div>
)}
{size === 'normal' && (
<div style={switchButtonStyles.uncheckedLabelStyle}>{uncheckedLabel ?? ''}</div>
)}
<div style={switchButtonStyles.knobStyle} data-testid='switch-knob'>
{size === 'small' && checked && (
<Icon
icon='check'
primaryColor={switchButtonStyles.iconSmall.color}
size={switchButtonStyles.iconSmall.size}
style={switchButtonStyles.iconSmall.style}
/>
)}
</div>
<div style={switchButtonStyles.knobOverlayStyle}></div>
</button>
);
}
Loading