Skip to content

Commit

Permalink
Add configuration options for full screen mode breakpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
ljwagerfield committed Feb 6, 2024
1 parent ef785d3 commit 8caf29d
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 84 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,10 @@ Bytescale.UploadWidget.open({
showFinishButton: true, // Show/hide the "finish" button in the widget.
showRemoveButton: true, // Show/hide the "remove" button next to each file.
styles: {
breakpoints: {
fullScreenWidth: 750, // Full-screen mode activates when the screen is at or below this width.
fullScreenHeight: 420 // Full-screen mode activates when the screen is at or below this height.
},
colors: {
primary: "#377dff", // Primary buttons & links
active: "#528fff", // Primary buttons & links (hover). Inferred if undefined.
Expand Down
3 changes: 2 additions & 1 deletion examples/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ const openUploader = (): void => {
},
fontSizes: {
base: 16
}
},
breakpoints: {}
}
}).then(
(f: UploadWidgetResult[]) => {
Expand Down
13 changes: 12 additions & 1 deletion lib/src/components/RootContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ModalContainer } from "@bytescale/upload-widget/components/modal/ModalC
import { useEffect, useState } from "preact/compat";
import cn from "classnames";
import { UploadWidgetConfigRequired } from "@bytescale/upload-widget/config/UploadWidgetConfig";
import { getElementDimensionsOnResize } from "@bytescale/upload-widget/modules/common/UseDimensionsFromElement";

interface Props {
widgetProps: UploadWidgetContainerProps;
Expand All @@ -15,6 +16,7 @@ interface Props {
export const RootContainer = ({ widgetProps }: Props): JSX.Element => {
const [refreshKey, setRefreshKey] = useState(0);
const [options, setOptions] = useState(widgetProps.options);
const [dimensions, containerRef] = getElementDimensionsOnResize(true, []);
const widgetPropsUpdated: UploadWidgetContainerProps = {
...widgetProps,
options
Expand All @@ -37,10 +39,19 @@ export const RootContainer = ({ widgetProps }: Props): JSX.Element => {
});
}, []);

const isFullScreen =
dimensions !== undefined &&
(dimensions.width <= options.styles.breakpoints.fullScreenWidth ||
dimensions.height <= options.styles.breakpoints.fullScreenHeight);

return (
<Fragment key={refreshKey}>
<div
className={cn("upload-widget", { "upload-widget--with-modal": options.layout === "modal" })}
ref={containerRef}
className={cn("upload-widget", {
"upload-widget--with-modal": options.layout === "modal",
"upload-widget--full-screen": isFullScreen
})}
style={{
"--error-color": options.styles.colors.error,
"--primary-color": options.styles.colors.primary,
Expand Down
23 changes: 13 additions & 10 deletions lib/src/components/modal/Modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,11 @@
max-width: 1050 * $px;
max-height: 660 * $px;

@media (max-height: $desktop-short-height) {
@media (max-height: $short-mode-height-max) {
top: -1%;
height: 80%;
}

@media (max-width: $mobile-width-max), (max-height: $mobile-height-max) {
top: 0;
height: 100%;
width: 100%;
max-width: none;
max-height: none;
border-radius: 0;
}

&__close {
position: absolute;
right: 0;
Expand All @@ -60,6 +51,18 @@
}
}
}

&--full-screen {
.upload-widget__modal {
top: 0;
height: 100%;
width: 100%;
max-width: none;
max-height: none;
border-radius: 0;
}
}

&__backdrop {
content: " ";
background: rgba(0, 0, 0, 0.5);
Expand Down
6 changes: 3 additions & 3 deletions lib/src/components/widgets/configError/ConfigError.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { JSX } from "preact";
import { WidgetBase } from "@bytescale/upload-widget/components/widgets/widgetBase/WidgetBase";
import { UploadWidgetInternal } from "@bytescale/upload-widget/components/widgets/uploadWidget/components/internal/UploadWidgetInternal";
import { UploadWidgetLayout } from "@bytescale/upload-widget/config/UploadWidgetLayout";
import { RightSvg } from "@bytescale/upload-widget/assets/svgs/RightSvg";

Expand All @@ -12,7 +12,7 @@ export const ConfigError = ({ error, layout }: Props): JSX.Element => {
const errorMessage = (error.message ?? "unknown error").replace("[upload-js] ", "");
const isApiKeyError = errorMessage.toLowerCase().includes("api key");
return (
<WidgetBase layout={layout} multi={false}>
<UploadWidgetInternal layout={layout} multi={false}>
<h1>{isApiKeyError ? "Almost there..." : "Oops!"}</h1>
<p>{errorMessage}</p>
{isApiKeyError ? (
Expand All @@ -24,6 +24,6 @@ export const ConfigError = ({ error, layout }: Props): JSX.Element => {
) : (
<></>
)}
</WidgetBase>
</UploadWidgetInternal>
);
};
6 changes: 3 additions & 3 deletions lib/src/components/widgets/uploadWidget/UploadWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
UploadedFileContainer,
UploadingFile
} from "@bytescale/upload-widget/components/widgets/uploadWidget/model/SubmittedFile";
import { WidgetBase } from "@bytescale/upload-widget/components/widgets/widgetBase/WidgetBase";
import { UploadWidgetInternal } from "@bytescale/upload-widget/components/widgets/uploadWidget/components/internal/UploadWidgetInternal";
import { useDragDrop } from "@bytescale/upload-widget/modules/common/UseDragDrop";
import { humanFileSize } from "@bytescale/upload-widget/modules/common/FormatUtils";
import {
Expand Down Expand Up @@ -312,7 +312,7 @@ export const UploadWidget = ({ resolve, options, upload }: Props): JSX.Element =
const isImageUploader = mimeTypes.length > 0 && mimeTypes.every(x => x.trim().toLowerCase().startsWith("image/"));

return (
<WidgetBase
<UploadWidgetInternal
htmlProps={rootProps}
isDraggable={true}
isDragging={isDragging}
Expand All @@ -338,6 +338,6 @@ export const UploadWidget = ({ resolve, options, upload }: Props): JSX.Element =
isImageUploader={isImageUploader}
/>
)}
</WidgetBase>
</UploadWidgetInternal>
);
};
6 changes: 1 addition & 5 deletions lib/src/components/widgets/uploadWidget/Variables.scss
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
$base-size: 16;
$px: (1 / $base-size) * 1em;
$mobile-width-max: 750px; // Use real pixels here
$mobile-width-min: $mobile-width-max + 1px; // Use real pixels here
$mobile-height-max: 420px; // Use real pixels here
$mobile-height-min: $mobile-height-max + 1px; // Use real pixels here
$desktop-short-height: 700px; // Use real pixels here
$short-mode-height-max: 700px; // Use real pixels here
$modal-bg-z-index: 1;
$file-gutter: 5;
$controls-padding: 15;
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

$large: 1200px;

.breakpoint {
&-md .upload-widget__submitted-file {
.upload-widget__internal {
&--md .upload-widget__submitted-file {
max-width: 100%;
width: 100%;
}
&-lg .upload-widget__submitted-file {
&--lg .upload-widget__submitted-file {
max-width: 50%;
width: 50%;
}
&-xl .upload-widget__submitted-file {
&--xl .upload-widget__submitted-file {
max-width: 33.333333%;
width: 33.333333%;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@import "~@bytescale/upload-widget/components/widgets/uploadWidget/Variables";

.upload-widget__widget-base {
.upload-widget__internal {
$margin: 15 * $px;
$border-color: var(--shade-600);
border-radius: 5 * $px;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { ReactNode } from "@bytescale/upload-widget/modules/common/React";
import { JSX } from "preact";
import cn from "classnames";
import "./UploadWidgetInternal.scss";
import { UploadWidgetLayout } from "@bytescale/upload-widget/config/UploadWidgetLayout";
import { UploadWidgetInternalBorder } from "@bytescale/upload-widget/components/widgets/uploadWidget/components/internal/border/UploadWidgetInternalBorder";
import { modalCloseButtonPadding, modalCloseButtonSize } from "@bytescale/upload-widget/components/modal/Modal";
import { getElementDimensionsOnResize } from "@bytescale/upload-widget/modules/common/UseDimensionsFromElement";

interface Props {
children: ReactNode;
htmlProps?: any;
isDraggable?: boolean;
isDragging?: boolean;
layout: UploadWidgetLayout;
multi: boolean;
}

export const UploadWidgetInternal = ({ children, htmlProps, isDraggable, isDragging, layout }: Props): JSX.Element => {
const [dimensions, containerRef] = getElementDimensionsOnResize(true, []);

// Size is relative to the internal dimensions of the upload widget, as opposed to the screen. This caters for the
// widget entering "full screen" mode when being shrunk, which causes the internal dimensions of the widget to become
// larger. Hence, we measure these breakpoints based off the internal widget size, rather than the screen size.
const internalBreakpoints = [
{ width: 650, value: "md" },
{ width: 930, value: "lg" }
];

const lastBreakpoint = "xl";
const breakpoint =
(dimensions === undefined ? undefined : internalBreakpoints.find(x => dimensions.width <= x.width)?.value) ??
lastBreakpoint;

return (
<div
ref={containerRef}
className={cn("upload-widget__internal", `upload-widget__internal--${breakpoint}`, {
"upload-widget__internal--draggable": isDraggable === true && layout !== "modal",
"upload-widget__internal--dragging": isDragging === true && layout !== "modal"
})}
{...htmlProps}>
{isDraggable === true && layout === "modal" && (
<UploadWidgetInternalBorder
isDragging={isDragging === true}
dimensions={dimensions}
closeButtonSize={modalCloseButtonSize + modalCloseButtonPadding}
/>
)}
<div
className={cn("upload-widget__internal__children", {
"upload-widget__internal__children--is-modal": layout === "modal"
})}>
{children}
</div>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface Props {
isDragging: boolean;
}

export const WidgetBaseBackground = ({ closeButtonSize, isDragging, dimensions }: Props): JSX.Element => {
export const UploadWidgetInternalBorder = ({ closeButtonSize, isDragging, dimensions }: Props): JSX.Element => {
if (dimensions === undefined) {
return <></>;
}
Expand All @@ -19,8 +19,8 @@ export const WidgetBaseBackground = ({ closeButtonSize, isDragging, dimensions }
width={dimensions.width}
height={dimensions.height}
notchSize={closeButtonSize}
className={cn("upload-widget__widget-base__modal-bg", {
"upload-widget__widget-base__modal-bg--dragging": isDragging
className={cn("upload-widget__internal__modal-bg", {
"upload-widget__internal__modal-bg--dragging": isDragging
})}
/>
);
Expand Down
53 changes: 0 additions & 53 deletions lib/src/components/widgets/widgetBase/WidgetBase.tsx

This file was deleted.

18 changes: 18 additions & 0 deletions lib/src/config/UploadWidgetBreakpoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export interface UploadWidgetBreakpoints {
fullScreenHeight?: number;
fullScreenWidth?: number;
}

export interface UploadWidgetBreakpointsRequired {
fullScreenHeight: number;
fullScreenWidth: number;
}

export namespace UploadWidgetBreakpointsRequired {
export function from(options: UploadWidgetBreakpoints | undefined): UploadWidgetBreakpointsRequired {
return {
fullScreenWidth: options?.fullScreenWidth ?? 750,
fullScreenHeight: options?.fullScreenHeight ?? 420
};
}
}
7 changes: 7 additions & 0 deletions lib/src/config/UploadWidgetStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,20 @@ import {
UploadWidgetFontFamily,
UploadWidgetFontFamilyRequired
} from "@bytescale/upload-widget/config/UploadWidgetFontFamily";
import {
UploadWidgetBreakpoints,
UploadWidgetBreakpointsRequired
} from "@bytescale/upload-widget/config/UploadWidgetBreakpoints";

export interface UploadWidgetStyles {
breakpoints?: UploadWidgetBreakpoints;
colors?: UploadWidgetColors;
fontFamilies?: UploadWidgetFontFamily;
fontSizes?: UploadWidgetFontSize;
}

export interface UploadWidgetStylesRequired {
breakpoints: UploadWidgetBreakpointsRequired;
colors: UploaderColorOptionsRequired;
fontFamilies: UploadWidgetFontFamilyRequired;
fontSizes: UploadWidgetFontSizeRequired;
Expand All @@ -23,6 +29,7 @@ export interface UploadWidgetStylesRequired {
export namespace UploadWidgetStylesRequired {
export function from(options: UploadWidgetStyles | undefined): UploadWidgetStylesRequired {
return {
breakpoints: UploadWidgetBreakpointsRequired.from(options?.breakpoints),
colors: UploaderColorOptionsRequired.from(options?.colors),
fontFamilies: UploadWidgetFontFamilyRequired.from(options?.fontFamilies),
fontSizes: UploadWidgetFontSizeRequired.from(options?.fontSizes)
Expand Down

0 comments on commit 8caf29d

Please sign in to comment.