Skip to content

Commit d981044

Browse files
authored
Merge pull request #139 from Automattic/border
Block border
2 parents 8dc9556 + eaa095c commit d981044

File tree

15 files changed

+348
-94
lines changed

15 files changed

+348
-94
lines changed

README.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,3 @@ add_filter( 'chatrix_instances', function ( array $default_instances ) {
5050
);
5151
} );
5252
~~~
53-
54-
### How can I add a border around the block?
55-
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.

block/attributes.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
interface Attributes {
2+
defaultHomeserver?: string,
3+
roomId?: string,
4+
height: Height,
5+
borderWidth: BorderWidth,
6+
borderRadius: BorderRadius,
7+
borderStyle: string,
8+
borderColor: string,
9+
}
10+
11+
export function parseAttributes(attributes): Attributes {
12+
return {
13+
defaultHomeserver: attributes.defaultHomeserver ?? '',
14+
roomId: attributes.roomId ?? '',
15+
height: new Height(attributes.height.value, attributes.height.unit),
16+
borderWidth: new BorderWidth(attributes.borderWidth.value, attributes.borderWidth.unit),
17+
borderRadius: new BorderRadius(attributes.borderRadius.value, attributes.borderRadius.unit),
18+
borderStyle: attributes.borderStyle,
19+
borderColor: attributes.borderColor,
20+
};
21+
}
22+
23+
export enum Unit {
24+
px = "px",
25+
}
26+
27+
function unitFromString(value: string): Unit | undefined {
28+
switch (value) {
29+
case Unit.px:
30+
return Unit.px;
31+
}
32+
return undefined;
33+
}
34+
35+
class ValueWithUnit {
36+
protected readonly value: number;
37+
protected readonly unit?: Unit;
38+
39+
constructor(value: number, unit: Unit | string) {
40+
this.value = value;
41+
42+
if (typeof unit === "string") {
43+
this.unit = unitFromString(unit);
44+
} else {
45+
this.unit = unit;
46+
}
47+
}
48+
49+
public toString(): string {
50+
return this.value && this.unit ? `${this.value}${this.unit}` : '';
51+
}
52+
}
53+
54+
export class Height extends ValueWithUnit {
55+
constructor(value: number, unit: Unit | string) {
56+
super(value, unit);
57+
}
58+
}
59+
60+
export class BorderWidth extends ValueWithUnit {
61+
constructor(value: number, unit: Unit | string) {
62+
super(value, unit);
63+
}
64+
65+
public toString(): string {
66+
return this.value && this.unit ? `${this.value}${this.unit}` : '0';
67+
}
68+
}
69+
70+
export class BorderRadius extends ValueWithUnit {
71+
constructor(value: number, unit: Unit | string) {
72+
super(value, unit);
73+
}
74+
}

block/block.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,28 @@
2222
"value": 600,
2323
"unit": "px"
2424
}
25+
},
26+
"borderWidth": {
27+
"type": "object",
28+
"default": {
29+
"value": 1,
30+
"unit": "px"
31+
}
32+
},
33+
"borderRadius": {
34+
"type": "object",
35+
"default": {
36+
"value": 10,
37+
"unit": "px"
38+
}
39+
},
40+
"borderStyle": {
41+
"type": "string",
42+
"default": "solid"
43+
},
44+
"borderColor": {
45+
"type": "string",
46+
"default": "black"
2547
}
2648
},
2749
"supports": {

block/edit.tsx

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
import { useBlockProps } from "@wordpress/block-editor";
22
import { ResizableBox } from "@wordpress/components";
33
import { WPElement } from '@wordpress/element';
4+
import { parseAttributes } from "./attributes";
45
import './editor.scss';
5-
import IFrame from "./iframe";
6-
import InspectorControls from "./inspector";
6+
import IFrame, { IframeProps } from "./iframe";
7+
import InspectorControls from "./inspector/InspectorControls";
78

8-
type Height = {
9-
value: number
10-
unit: string
9+
interface Props {
10+
attributes: object,
11+
setAttributes: Function,
1112
}
1213

13-
export default function Edit({ attributes, setAttributes }): WPElement {
14-
const height: Height = attributes.height;
14+
export default function Edit(props: Props): WPElement {
15+
const { setAttributes } = props;
16+
const attributes = parseAttributes(props.attributes);
1517

16-
const heightWithUnit =
17-
height.value && height.unit
18-
? `${height.value}${height.unit}`
19-
: '';
18+
const iframeProps: IframeProps = {
19+
focusable: true,
20+
...attributes
21+
};
2022

2123
return (
2224
<>
@@ -25,7 +27,7 @@ export default function Edit({ attributes, setAttributes }): WPElement {
2527
<ResizableBox
2628
size={{
2729
width: "100%",
28-
height: heightWithUnit,
30+
height: attributes.height.toString(),
2931
}}
3032
enable={{
3133
top: false,
@@ -41,7 +43,7 @@ export default function Edit({ attributes, setAttributes }): WPElement {
4143
setAttributes({ height: { value: elt.clientHeight, unit: "px" } });
4244
}}
4345
>
44-
<IFrame props={{ height: heightWithUnit }} attributes={attributes} focusable={true}/>
46+
<IFrame {...iframeProps}/>
4547
</ResizableBox>
4648
</div>
4749
</>

block/editor.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,22 @@
44

55
.wp-block-automattic-chatrix {
66
}
7+
8+
.chatrix-inspector-controls {
9+
.chatrix-text-control-with-unit {
10+
width: 100%;
11+
}
12+
13+
// Place input and unit on the same line.
14+
.chatrix-text-control-with-unit {
15+
.components-base-control__field > span {
16+
display: flex;
17+
align-items: center;
18+
justify-content: center;
19+
20+
& > span {
21+
margin-left: 5px;
22+
}
23+
}
24+
}
25+
}

block/iframe.tsx

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,37 @@
11
import { useFocusableIframe } from "@wordpress/compose";
22
import { WPElement } from "@wordpress/element";
3-
import { IframeUrl } from "../frontend/parent/iframe";
3+
import { IframeParams, IframeUrl } from "../frontend/parent/iframe";
44
import { containerClass, iframeClass } from "../frontend/parent/util";
5+
import { BorderRadius, BorderWidth, Height } from "./attributes";
56

6-
export default function IFrame({ props, attributes, focusable = false }): WPElement {
7-
const ref = focusable ? useFocusableIframe() : undefined;
8-
const url = iframeUrl(attributes);
7+
export type IframeProps = {
8+
focusable: boolean,
9+
defaultHomeserver?: string,
10+
roomId?: string,
11+
height: Height,
12+
borderWidth: BorderWidth,
13+
borderRadius: BorderRadius,
14+
borderStyle: string,
15+
borderColor: string,
16+
}
17+
18+
export default function IFrame(props: IframeProps): WPElement {
19+
const ref = props.focusable ? useFocusableIframe() : undefined;
20+
const style = {
21+
height: props.height.toString(),
22+
borderWidth: props.borderWidth ? props.borderWidth.toString() : 0,
23+
borderRadius: props.borderRadius ? props.borderRadius.toString() : "",
24+
borderStyle: props.borderStyle,
25+
borderColor: props.borderColor,
26+
};
27+
28+
const url = iframeUrl({
29+
defaultHomeserver: props.defaultHomeserver,
30+
roomId: props.roomId,
31+
});
932

1033
return (
11-
<div className={containerClass()} style={{ height: props.height || undefined }}>
34+
<div className={containerClass()} style={style}>
1235
<iframe className={iframeClass()}
1336
// @ts-ignore
1437
ref={ref}
@@ -18,13 +41,13 @@ export default function IFrame({ props, attributes, focusable = false }): WPElem
1841
);
1942
}
2043

21-
function iframeUrl(attributes): string {
44+
function iframeUrl(params: IframeParams): string {
2245
const config = window.automattic_chatrix_block_config;
2346
if (!config) {
2447
throw new Error("Failed to initialize Chatrix block: window.automattic_chatrix_block_config is not defined");
2548
}
2649

27-
const url = new IframeUrl(config.rootUrl, attributes);
50+
const url = new IframeUrl(config.rootUrl, params);
2851
return url.toString();
2952
}
3053

block/inspector.tsx

Lines changed: 0 additions & 63 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { PanelBody, PanelRow, TextControl } from "@wordpress/components";
2+
import { WPElement } from "@wordpress/element";
3+
import { __ } from "@wordpress/i18n";
4+
5+
export default function HomeserverPanel({ attributes, setAttributes }): WPElement {
6+
return (
7+
<PanelBody
8+
title={__("Homeserver", "chatrix")}
9+
initialOpen={true}
10+
>
11+
<PanelRow>
12+
<TextControl
13+
label={__("Default Homeserver", "chatrix")}
14+
value={attributes.defaultHomeserver}
15+
onChange={(value) => setAttributes({ defaultHomeserver: value })}
16+
/>
17+
</PanelRow>
18+
</PanelBody>
19+
);
20+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { InspectorControls as BaseInspectorControls } from "@wordpress/block-editor";
2+
import { WPElement } from "@wordpress/element";
3+
import HomeserverPanel from "./HomeserverPanel";
4+
import RoomPanel from "./RoomPanel";
5+
import StylePanel from "./StylePanel";
6+
7+
export default function InspectorControls({ attributes, setAttributes }): WPElement {
8+
return (
9+
<BaseInspectorControls>
10+
<div className={"chatrix-inspector-controls"}>
11+
<HomeserverPanel attributes={attributes} setAttributes={setAttributes}/>
12+
<RoomPanel attributes={attributes} setAttributes={setAttributes}/>
13+
<StylePanel attributes={attributes} setAttributes={setAttributes}/>
14+
</div>
15+
</BaseInspectorControls>
16+
);
17+
}

block/inspector/RoomPanel.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { PanelBody, PanelRow, TextControl } from "@wordpress/components";
2+
import { WPElement } from "@wordpress/element";
3+
import { __ } from "@wordpress/i18n";
4+
5+
export default function RoomPanel({ attributes, setAttributes }): WPElement {
6+
return (
7+
<PanelBody
8+
title={__("Room", "chatrix")}
9+
initialOpen={false}
10+
>
11+
<PanelRow>
12+
<TextControl
13+
label={__("Room id (optional)", "chatrix")}
14+
value={attributes.roomId}
15+
onChange={(value) => setAttributes({ roomId: value })}
16+
help={<RoomIdHelp/>}
17+
/>
18+
</PanelRow>
19+
</PanelBody>
20+
);
21+
}
22+
23+
function RoomIdHelp() {
24+
return (
25+
<>
26+
<span>{__("When a room id is specified, the client will be in single-room mode.", "chatrix")}</span><br/><br/>
27+
<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/>
28+
<span>{__("The room must be public, so that the user can join without requiring an invitation.", "chatrix")}</span><br/><br/>
29+
<span>{__("The room id must be the room's actual id, it must not be an alias.", "chatrix")}</span><br/><br/>
30+
<span>{__("Example: !abc123:example.com", "chatrix")}</span><br/>
31+
</>
32+
);
33+
}

0 commit comments

Comments
 (0)