Skip to content

Commit

Permalink
Merge pull request #139 from Automattic/border
Browse files Browse the repository at this point in the history
Block border
  • Loading branch information
psrpinto authored Dec 2, 2022
2 parents 8dc9556 + eaa095c commit d981044
Show file tree
Hide file tree
Showing 15 changed files with 348 additions and 94 deletions.
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,3 @@ add_filter( 'chatrix_instances', function ( array $default_instances ) {
);
} );
~~~

### How can I add a border around the block?
To add a border around the Chatrix block, you can place it inside a Group block. The Group block allows you to set a border, rounded corners, and other styling properties.
74 changes: 74 additions & 0 deletions block/attributes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
interface Attributes {
defaultHomeserver?: string,
roomId?: string,
height: Height,
borderWidth: BorderWidth,
borderRadius: BorderRadius,
borderStyle: string,
borderColor: string,
}

export function parseAttributes(attributes): Attributes {
return {
defaultHomeserver: attributes.defaultHomeserver ?? '',
roomId: attributes.roomId ?? '',
height: new Height(attributes.height.value, attributes.height.unit),
borderWidth: new BorderWidth(attributes.borderWidth.value, attributes.borderWidth.unit),
borderRadius: new BorderRadius(attributes.borderRadius.value, attributes.borderRadius.unit),
borderStyle: attributes.borderStyle,
borderColor: attributes.borderColor,
};
}

export enum Unit {
px = "px",
}

function unitFromString(value: string): Unit | undefined {
switch (value) {
case Unit.px:
return Unit.px;
}
return undefined;
}

class ValueWithUnit {
protected readonly value: number;
protected readonly unit?: Unit;

constructor(value: number, unit: Unit | string) {
this.value = value;

if (typeof unit === "string") {
this.unit = unitFromString(unit);
} else {
this.unit = unit;
}
}

public toString(): string {
return this.value && this.unit ? `${this.value}${this.unit}` : '';
}
}

export class Height extends ValueWithUnit {
constructor(value: number, unit: Unit | string) {
super(value, unit);
}
}

export class BorderWidth extends ValueWithUnit {
constructor(value: number, unit: Unit | string) {
super(value, unit);
}

public toString(): string {
return this.value && this.unit ? `${this.value}${this.unit}` : '0';
}
}

export class BorderRadius extends ValueWithUnit {
constructor(value: number, unit: Unit | string) {
super(value, unit);
}
}
22 changes: 22 additions & 0 deletions block/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,28 @@
"value": 600,
"unit": "px"
}
},
"borderWidth": {
"type": "object",
"default": {
"value": 1,
"unit": "px"
}
},
"borderRadius": {
"type": "object",
"default": {
"value": 10,
"unit": "px"
}
},
"borderStyle": {
"type": "string",
"default": "solid"
},
"borderColor": {
"type": "string",
"default": "black"
}
},
"supports": {
Expand Down
28 changes: 15 additions & 13 deletions block/edit.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import { useBlockProps } from "@wordpress/block-editor";
import { ResizableBox } from "@wordpress/components";
import { WPElement } from '@wordpress/element';
import { parseAttributes } from "./attributes";
import './editor.scss';
import IFrame from "./iframe";
import InspectorControls from "./inspector";
import IFrame, { IframeProps } from "./iframe";
import InspectorControls from "./inspector/InspectorControls";

type Height = {
value: number
unit: string
interface Props {
attributes: object,
setAttributes: Function,
}

export default function Edit({ attributes, setAttributes }): WPElement {
const height: Height = attributes.height;
export default function Edit(props: Props): WPElement {
const { setAttributes } = props;
const attributes = parseAttributes(props.attributes);

const heightWithUnit =
height.value && height.unit
? `${height.value}${height.unit}`
: '';
const iframeProps: IframeProps = {
focusable: true,
...attributes
};

return (
<>
Expand All @@ -25,7 +27,7 @@ export default function Edit({ attributes, setAttributes }): WPElement {
<ResizableBox
size={{
width: "100%",
height: heightWithUnit,
height: attributes.height.toString(),
}}
enable={{
top: false,
Expand All @@ -41,7 +43,7 @@ export default function Edit({ attributes, setAttributes }): WPElement {
setAttributes({ height: { value: elt.clientHeight, unit: "px" } });
}}
>
<IFrame props={{ height: heightWithUnit }} attributes={attributes} focusable={true}/>
<IFrame {...iframeProps}/>
</ResizableBox>
</div>
</>
Expand Down
19 changes: 19 additions & 0 deletions block/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,22 @@

.wp-block-automattic-chatrix {
}

.chatrix-inspector-controls {
.chatrix-text-control-with-unit {
width: 100%;
}

// Place input and unit on the same line.
.chatrix-text-control-with-unit {
.components-base-control__field > span {
display: flex;
align-items: center;
justify-content: center;

& > span {
margin-left: 5px;
}
}
}
}
37 changes: 30 additions & 7 deletions block/iframe.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,37 @@
import { useFocusableIframe } from "@wordpress/compose";
import { WPElement } from "@wordpress/element";
import { IframeUrl } from "../frontend/parent/iframe";
import { IframeParams, IframeUrl } from "../frontend/parent/iframe";
import { containerClass, iframeClass } from "../frontend/parent/util";
import { BorderRadius, BorderWidth, Height } from "./attributes";

export default function IFrame({ props, attributes, focusable = false }): WPElement {
const ref = focusable ? useFocusableIframe() : undefined;
const url = iframeUrl(attributes);
export type IframeProps = {
focusable: boolean,
defaultHomeserver?: string,
roomId?: string,
height: Height,
borderWidth: BorderWidth,
borderRadius: BorderRadius,
borderStyle: string,
borderColor: string,
}

export default function IFrame(props: IframeProps): WPElement {
const ref = props.focusable ? useFocusableIframe() : undefined;
const style = {
height: props.height.toString(),
borderWidth: props.borderWidth ? props.borderWidth.toString() : 0,
borderRadius: props.borderRadius ? props.borderRadius.toString() : "",
borderStyle: props.borderStyle,
borderColor: props.borderColor,
};

const url = iframeUrl({
defaultHomeserver: props.defaultHomeserver,
roomId: props.roomId,
});

return (
<div className={containerClass()} style={{ height: props.height || undefined }}>
<div className={containerClass()} style={style}>
<iframe className={iframeClass()}
// @ts-ignore
ref={ref}
Expand All @@ -18,13 +41,13 @@ export default function IFrame({ props, attributes, focusable = false }): WPElem
);
}

function iframeUrl(attributes): string {
function iframeUrl(params: IframeParams): string {
const config = window.automattic_chatrix_block_config;
if (!config) {
throw new Error("Failed to initialize Chatrix block: window.automattic_chatrix_block_config is not defined");
}

const url = new IframeUrl(config.rootUrl, attributes);
const url = new IframeUrl(config.rootUrl, params);
return url.toString();
}

Expand Down
63 changes: 0 additions & 63 deletions block/inspector.tsx

This file was deleted.

20 changes: 20 additions & 0 deletions block/inspector/HomeserverPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { PanelBody, PanelRow, TextControl } from "@wordpress/components";
import { WPElement } from "@wordpress/element";
import { __ } from "@wordpress/i18n";

export default function HomeserverPanel({ attributes, setAttributes }): WPElement {
return (
<PanelBody
title={__("Homeserver", "chatrix")}
initialOpen={true}
>
<PanelRow>
<TextControl
label={__("Default Homeserver", "chatrix")}
value={attributes.defaultHomeserver}
onChange={(value) => setAttributes({ defaultHomeserver: value })}
/>
</PanelRow>
</PanelBody>
);
}
17 changes: 17 additions & 0 deletions block/inspector/InspectorControls.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { InspectorControls as BaseInspectorControls } from "@wordpress/block-editor";
import { WPElement } from "@wordpress/element";
import HomeserverPanel from "./HomeserverPanel";
import RoomPanel from "./RoomPanel";
import StylePanel from "./StylePanel";

export default function InspectorControls({ attributes, setAttributes }): WPElement {
return (
<BaseInspectorControls>
<div className={"chatrix-inspector-controls"}>
<HomeserverPanel attributes={attributes} setAttributes={setAttributes}/>
<RoomPanel attributes={attributes} setAttributes={setAttributes}/>
<StylePanel attributes={attributes} setAttributes={setAttributes}/>
</div>
</BaseInspectorControls>
);
}
33 changes: 33 additions & 0 deletions block/inspector/RoomPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { PanelBody, PanelRow, TextControl } from "@wordpress/components";
import { WPElement } from "@wordpress/element";
import { __ } from "@wordpress/i18n";

export default function RoomPanel({ attributes, setAttributes }): WPElement {
return (
<PanelBody
title={__("Room", "chatrix")}
initialOpen={false}
>
<PanelRow>
<TextControl
label={__("Room id (optional)", "chatrix")}
value={attributes.roomId}
onChange={(value) => setAttributes({ roomId: value })}
help={<RoomIdHelp/>}
/>
</PanelRow>
</PanelBody>
);
}

function RoomIdHelp() {
return (
<>
<span>{__("When a room id is specified, the client will be in single-room mode.", "chatrix")}</span><br/><br/>
<span>{__("In this mode, the client opens directly in that room, with the user not having access to the screen that shows the list of rooms.", "chatrix")}</span><br/><br/>
<span>{__("The room must be public, so that the user can join without requiring an invitation.", "chatrix")}</span><br/><br/>
<span>{__("The room id must be the room's actual id, it must not be an alias.", "chatrix")}</span><br/><br/>
<span>{__("Example: !abc123:example.com", "chatrix")}</span><br/>
</>
);
}
Loading

0 comments on commit d981044

Please sign in to comment.