Skip to content

Commit

Permalink
Merge pull request #9 from jjang16/main
Browse files Browse the repository at this point in the history
registers SafeAreaElement in browser only in order to prevent breaking evaluating SafeAreaController in SSR environments.
  • Loading branch information
Aashu-Dubey authored Jun 17, 2023
2 parents 8277622 + e181a2e commit 8408739
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 82 deletions.
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
})
```

You might also have to empty import the plugin in your root component or at the component level file where you're using the tag
You also have to register the custom element before using the tag

```ts
// app.component.ts or your-component.ts

import '@aashu-dubey/capacitor-statusbar-safe-area';
// or with named import if you're also using other APIs from plugin
// import { SafeArea } from '@aashu-dubey/capacitor-statusbar-safe-area';
import { registerSafeAreaElement } '@aashu-dubey/capacitor-statusbar-safe-area';

registerSafeAreaElement();
```
then just wrap the part you want to apply safe area padding on with `safe-area` tag as below
Expand All @@ -102,9 +102,9 @@ You will have to import the plugin in your component in order to make the web co
<summary>React</summary>
```jsx
import '@aashu-dubey/capacitor-statusbar-safe-area';
// or with named import if you're also using other APIs from plugin
// import { SafeArea } from '@aashu-dubey/capacitor-statusbar-safe-area';
import { registerSafeAreaElement } '@aashu-dubey/capacitor-statusbar-safe-area';

registerSafeAreaElement();

const MyComponent = () => {
return (
Expand All @@ -128,9 +128,9 @@ const MyComponent = () => {
</template>

<script setup lang="ts">
import '@aashu-dubey/capacitor-statusbar-safe-area';
// or with named import if you're also using other APIs from plugin
// import { SafeArea } from '@aashu-dubey/capacitor-statusbar-safe-area';
import { registerSafeAreaElement } '@aashu-dubey/capacitor-statusbar-safe-area';

registerSafeAreaElement();
</script>
```
Expand Down Expand Up @@ -195,6 +195,7 @@ Get the Safe area insets for Android and iOS, and on Web it returns 0 for all.
### Interfaces
#### SafeAreaType
| Prop | Type | Description |
Expand Down
70 changes: 3 additions & 67 deletions src/controller.ts
Original file line number Diff line number Diff line change
@@ -1,71 +1,9 @@
import { Capacitor } from '@capacitor/core';

import type { SafeAreaType } from './index';
import type { SafeAreaInset } from './index';
import { SafeArea } from './index';

class SafeAreaElement extends HTMLElement {
mode: 'padding' | 'margin';
edges?: string;

constructor() {
super();

this.mode = 'padding';
// Create a shadow root
this.attachShadow({ mode: 'open' });
}

connectedCallback() {
this.renderElement();
}

static get observedAttributes() {
return ['mode', 'edges'];
}

attributeChangedCallback(name: string, oldValue: string, newValue: string) {
if (oldValue === newValue) {
return;
}
(this as any)[name] = newValue;
this.renderElement();
}

async renderElement() {
if (this.shadowRoot) {
const safeAreaInset = await SafeArea.getSafeAreaInsets();

const isMargin = this.mode === 'margin';
const edges = this.edges?.split(',').map(item => item.trim());

const insets = {
top: edges && !edges?.includes('top') ? 0 : safeAreaInset.top,
bottom: edges && !edges?.includes('bottom') ? 0 : safeAreaInset.bottom,
left: edges && !edges?.includes('left') ? 0 : safeAreaInset.left,
right: edges && !edges?.includes('right') ? 0 : safeAreaInset.right,
};

this.shadowRoot.innerHTML = `
<style>
#wrapper {
${isMargin ? 'margin' : 'padding'}-top: ${insets.top}px;
${isMargin ? 'margin' : 'padding'}-bottom: ${insets.bottom}px;
${isMargin ? 'margin' : 'padding'}-left: ${insets.left}px;
${isMargin ? 'margin' : 'padding'}-right: ${insets.right}px;
}
</style>
<div id="wrapper">
<slot></slot>
</div>
`;
}
}
}

if (!customElements.get('safe-area'))
customElements.define('safe-area', SafeAreaElement);

class SafeAreaController {
export class SafeAreaController {
async injectCSSVariables(): Promise<void> {
this.addStatusBarHeight();
this.addSafeAreaVariables();
Expand All @@ -88,7 +26,7 @@ class SafeAreaController {
{
elStyle.setProperty(
`--safe-area-inset-${inset}`,
`${safeAreaInset[inset as keyof SafeAreaType]}px`,
`${safeAreaInset[inset as keyof SafeAreaInset]}px`,
);
}
break;
Expand All @@ -101,5 +39,3 @@ class SafeAreaController {
}
}
}

export default SafeAreaController;
8 changes: 6 additions & 2 deletions src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ export interface SafeAreaPlugin {
/**
* Get the Safe area insets for Android and iOS, and on Web it returns 0 for all.
*/
getSafeAreaInsets(): Promise<SafeAreaType>;
getSafeAreaInsets(): Promise<SafeAreaInset>;
}

export interface SafeAreaType {
export interface SafeAreaInset {
/**
* Safe Area inset value at top.
*/
Expand All @@ -29,6 +29,10 @@ export interface SafeAreaType {
right: number;
}

// SafeAreaType was renamed to SafeAreaInset;
// For backward compatibility, we'll expose the previous name too.
export type SafeAreaType = SafeAreaInset;

export interface SafeAreaHTMLProps {
/**
* Whether to apply safe area insets as `padding` or `margin`.
Expand Down
69 changes: 69 additions & 0 deletions src/element.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { SafeArea } from './index';

export class SafeAreaElement extends HTMLElement {
mode: 'padding' | 'margin';
edges?: string;

constructor() {
super();

this.mode = 'padding';
// Create a shadow root
this.attachShadow({ mode: 'open' });
}

connectedCallback(): void {
this.renderElement();
}

static get observedAttributes(): string[] {
return ['mode', 'edges'];
}

attributeChangedCallback(
name: string,
oldValue: string,
newValue: string,
): void {
if (oldValue === newValue) {
return;
}
(this as any)[name] = newValue;
this.renderElement();
}

async renderElement(): Promise<void> {
if (this.shadowRoot) {
const safeAreaInset = await SafeArea.getSafeAreaInsets();

const isMargin = this.mode === 'margin';
const edges = this.edges?.split(',').map(item => item.trim());

const insets = {
top: edges && !edges?.includes('top') ? 0 : safeAreaInset.top,
bottom: edges && !edges?.includes('bottom') ? 0 : safeAreaInset.bottom,
left: edges && !edges?.includes('left') ? 0 : safeAreaInset.left,
right: edges && !edges?.includes('right') ? 0 : safeAreaInset.right,
};

this.shadowRoot.innerHTML = `
<style>
#wrapper {
${isMargin ? 'margin' : 'padding'}-top: ${insets.top}px;
${isMargin ? 'margin' : 'padding'}-bottom: ${insets.bottom}px;
${isMargin ? 'margin' : 'padding'}-left: ${insets.left}px;
${isMargin ? 'margin' : 'padding'}-right: ${insets.right}px;
}
</style>
<div id="wrapper">
<slot></slot>
</div>
`;
}
}
}

export const registerSafeAreaElement = (): void => {
if (!customElements.get('safe-area'))
customElements.define('safe-area', SafeAreaElement);
};
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { registerPlugin } from '@capacitor/core';

import SafeAreaController from './controller';
import { SafeAreaController } from './controller';
import type { SafeAreaPlugin, SafeAreaHTMLProps } from './definitions';
import { SafeAreaElement, registerSafeAreaElement } from './element';

const SafeArea = registerPlugin<SafeAreaPlugin>('SafeArea', {
web: () => import('./web').then(m => new m.SafeAreaWeb()),
Expand All @@ -12,6 +13,7 @@ const controller = new SafeAreaController();
export * from './definitions';
export { SafeArea };
export { controller as SafeAreaController };
export { SafeAreaElement, registerSafeAreaElement };

declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
Expand Down
4 changes: 2 additions & 2 deletions src/web.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { WebPlugin } from '@capacitor/core';

import type { SafeAreaPlugin, SafeAreaType } from './definitions';
import type { SafeAreaPlugin, SafeAreaInset } from './definitions';

export class SafeAreaWeb extends WebPlugin implements SafeAreaPlugin {
async getStatusBarHeight(): Promise<{ height: number }> {
return { height: 0 };
}

async getSafeAreaInsets(): Promise<SafeAreaType> {
async getSafeAreaInsets(): Promise<SafeAreaInset> {
return { top: 0, bottom: 0, left: 0, right: 0 };
}
}

0 comments on commit 8408739

Please sign in to comment.