Skip to content

Feature/popover-container #561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 53 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
86bb08f
init
JesmoDev Aug 23, 2023
889347e
change to use translate
JesmoDev Aug 23, 2023
40f7c32
package lock
JesmoDev Aug 24, 2023
f458b4f
WIP placement
JesmoDev Aug 24, 2023
5ced391
placement fix
JesmoDev Aug 24, 2023
80376be
working clamps
JesmoDev Aug 24, 2023
ac2ed77
if outside screen, close and remove eventlistener
JesmoDev Aug 24, 2023
192e1bd
add overflow: visisble
JesmoDev Aug 24, 2023
d3ed616
remove test code from component
JesmoDev Aug 25, 2023
af22154
update story
JesmoDev Aug 25, 2023
8ce38e7
use padding instead
JesmoDev Aug 25, 2023
36166a6
add custom docs
JesmoDev Aug 29, 2023
7ded70c
update docs
JesmoDev Aug 29, 2023
92a78a8
add browser support alert
JesmoDev Aug 29, 2023
4560e50
change story to use uui-button
JesmoDev Aug 30, 2023
b0fb4bf
add hack to make it somewhat work with uui-button
JesmoDev Aug 30, 2023
51ccf8a
fix story
JesmoDev Aug 31, 2023
a6990d3
add flipping
JesmoDev Aug 31, 2023
47f2e74
update story
JesmoDev Aug 31, 2023
be46936
better naming
JesmoDev Aug 31, 2023
9e6488a
added comments and changed names for better readability
JesmoDev Aug 31, 2023
e8a487d
fix button
JesmoDev Aug 31, 2023
9eb3979
remove story from docs
JesmoDev Aug 31, 2023
2f39071
use margin property
JesmoDev Aug 31, 2023
869be98
update story
JesmoDev Aug 31, 2023
840a641
add warnings to docs
JesmoDev Aug 31, 2023
d188008
remove auto
JesmoDev Sep 1, 2023
706cd23
add stories to displays folder
JesmoDev Sep 1, 2023
6ef5007
add controls and more examples to docs
JesmoDev Sep 1, 2023
1ef5378
add more stories and descriptions
JesmoDev Sep 1, 2023
aa1259e
fix types and descriptions
JesmoDev Sep 1, 2023
ce0f188
fix typo
JesmoDev Sep 1, 2023
12a9339
add open property to prevent unnecessary updates
JesmoDev Sep 1, 2023
a1cd3d0
add readonly jsdocs to open
JesmoDev Sep 1, 2023
21a88b2
remove storybook control for open property
JesmoDev Sep 1, 2023
de41d3f
Merge branch 'v1/contrib' into feature/popover-v2
nielslyngsoe Sep 1, 2023
2864622
add findAncestorByAttributeValue function to utils in uui-base
JesmoDev Sep 4, 2023
433dbf8
fix export of function
JesmoDev Sep 4, 2023
860a15f
use the utils function in uui button and popover container
JesmoDev Sep 4, 2023
c073cda
add popovertarget mixin
JesmoDev Sep 4, 2023
44bf4c6
use popovertarget mixin
JesmoDev Sep 4, 2023
abeabc5
export popover-container in uui package
nielslyngsoe Sep 5, 2023
0967474
Merge branch 'v1/contrib' into feature/popover-container
JesmoDev Sep 8, 2023
1804537
package lock
JesmoDev Sep 11, 2023
64a8017
fix findAncestorByAttribute so that it also checks shadow-doms
JesmoDev Sep 11, 2023
6a4288d
Merge remote-tracking branch 'origin/v1/contrib' into feature/popover…
JesmoDev Sep 12, 2023
332c953
Merge branch 'v1/contrib' into feature/popover-v2
iOvergaard Sep 13, 2023
75200ca
update typescript + vite
iOvergaard Sep 13, 2023
7c9509b
set base branch
iOvergaard Sep 13, 2023
fb3466f
set lib to es2020
iOvergaard Sep 13, 2023
df42ab9
fix import path
iOvergaard Sep 13, 2023
f6f7b0a
set esbuild to 0.17 to prevent upstream errors
iOvergaard Sep 13, 2023
71db838
add readme to popover-container
iOvergaard Sep 13, 2023
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ If you want to develop a component or contribute to the repository go to ["Get s
| [`<uui-modal>`](packages/uui-modal) | [![npm](https://img.shields.io/npm/v/@umbraco-ui/uui-modal?logoColor=%231B264F)](https://www.npmjs.com/package/@umbraco-ui/uui-modal) |
| [`<uui-pagination>`](packages/uui-pagination) | [![npm](https://img.shields.io/npm/v/@umbraco-ui/uui-pagination?logoColor=%231B264F)](https://www.npmjs.com/package/@umbraco-ui/uui-pagination) |
| [`<uui-popover>`](packages/uui-popover) | [![npm](https://img.shields.io/npm/v/@umbraco-ui/uui-popover?logoColor=%231B264F)](https://www.npmjs.com/package/@umbraco-ui/uui-popover) |
| [`<uui-popover-container>`](packages/uui-popover-container) | [![npm](https://img.shields.io/npm/v/@umbraco-ui/uui-popover-container?logoColor=%231B264F)](https://www.npmjs.com/package/@umbraco-ui/uui-popover-container) |
| [`<uui-progress-bar>`](packages/uui-progress-bar) | [![npm](https://img.shields.io/npm/v/@umbraco-ui/uui-progress-bar?logoColor=%231B264F)](https://www.npmjs.com/package/@umbraco-ui/uui-progress-bar) |
| [`<uui-range-slider>`](packages/uui-range-slider) | [![npm](https://img.shields.io/npm/v/@umbraco-ui/uui-range-slider?logoColor=%231B264F)](https://www.npmjs.com/package/@umbraco-ui/uui-range-slider) |
| [`<uui-radio>`](packages/uui-radio) | [![npm](https://img.shields.io/npm/v/@umbraco-ui/uui-radio?logoColor=%231B264F)](https://www.npmjs.com/package/@umbraco-ui/uui-radio) |
Expand Down
10,902 changes: 6,337 additions & 4,565 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"babel-loader": "9.1.3",
"chromatic": "6.20.0",
"element-internals-polyfill": "1.3.5",
"esbuild": "0.17.18",
"eslint": "8.45.0",
"eslint-config-prettier": "8.9.0",
"eslint-import-resolver-typescript": "3.5.5",
Expand Down Expand Up @@ -125,8 +126,8 @@
"storybook": "7.2.2",
"tsc-files": "1.1.4",
"turbo": "^1.10.12",
"typescript": "5.0.4",
"vite": "4.4.4",
"typescript": "5.2.2",
"vite": "4.4.9",
"vite-tsconfig-paths": "4.2.0",
"web-component-analyzer": "1.1.7"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/rollup-package.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import importCss from 'rollup-plugin-import-css';

// @ts-ignore-start
// eslint-disable-next-line -- // @typescript-eslint/ban-ts-comment // @ts-ignore
import properties from '../packages/uui-css/custom-properties.module.js'; // eslint-disable-line
import properties from './uui-css/custom-properties.module.js'; // eslint-disable-line
// @ts-ignore-end

const esbuidOptions = { minify: true };
Expand Down
77 changes: 77 additions & 0 deletions packages/uui-base/lib/mixins/PopoverTargetMixin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { LitElement } from 'lit';
import { property } from 'lit/decorators.js';
import { findAncestorByAttributeValue } from '../utils';

type Constructor<T = {}> = new (...args: any[]) => T;

export declare class PopoverTargetMixinInterface {
/**
* Set a popovertarget.
* @type {string}
* @attr
* @default undefined
*/
public popoverContainerElement?: string;

/**
* Toggle the popover.
*/
protected _togglePopover(): void;
}

/**
* This mixin provides popover target functionality to other components.
*
* @param {Object} superClass - superclass to be extended.
* @mixin
*/
export const PopoverTargetMixin = <T extends Constructor<LitElement>>(
superClass: T
) => {
/**
* Popover target mixin class containing the popover target functionality.
*/
class PopoverTargetMixinClass extends superClass {
/**
* Set a popovertarget.
* @type {string}
* @attr
* @default undefined
*/
@property({ type: String, attribute: 'popovertarget' })
public popoverContainerElement?: string;

#popoverIsOpen = false;

constructor(...args: any[]) {
super(...args);
this.addEventListener('uui-popover-before-toggle', this.#popoverListener);
}

protected _togglePopover = () => {
if (!this.popoverContainerElement) return;

const popoverContainerElement = findAncestorByAttributeValue(
this,
'id',
this.popoverContainerElement
);
if (!popoverContainerElement) return;

this.#popoverIsOpen
? // @ts-ignore - This is part of the new popover API, but typescript doesn't recognize it yet.
popoverContainerElement.hidePopover()
: // @ts-ignore - This is part of the new popover API, but typescript doesn't recognize it yet.
popoverContainerElement.showPopover();
};

#popoverListener = (event: any) => {
// Wait for the click event to finish before updating the popover state
requestAnimationFrame(() => {
this.#popoverIsOpen = event.detail.newState === 'open';
});
};
}
return PopoverTargetMixinClass as unknown as Constructor<PopoverTargetMixinInterface> &
T;
};
1 change: 1 addition & 0 deletions packages/uui-base/lib/mixins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './LabelMixin';
export * from './SelectableMixin';
export * from './SelectOnlyMixin';
export * from './FormControlMixin';
export * from './PopoverTargetMixin';
40 changes: 40 additions & 0 deletions packages/uui-base/lib/utils/findAncestorByAttributeValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Recursively find an ancestor element by attribute name and value. This also checks children of the ancestor.
* @func findAncestorByAttributeValue
* @param {HTMLElement} startNode - Origin node of the search.
* @param {string} attributeName - Name of the attribute to search for.
* @param {string} attributeValue - Value of the attribute to search for.
*/
export const findAncestorByAttributeValue = (
startNode: HTMLElement | ParentNode,
attributeName: string,
attributeValue: string
): HTMLElement | null => {
let currentNode: typeof startNode | null = startNode;

while (currentNode !== null) {
// Check if the current element has the specified attribute
const elementHasAttribute =
currentNode instanceof HTMLElement &&
currentNode.hasAttribute(attributeName) &&
currentNode.getAttribute(attributeName) === attributeValue;

// Check if the current element contains an element with the specified attribute
const elementContainsAttribute =
currentNode.querySelector(`[${attributeName}="${attributeValue}"]`) !==
null;

if (elementHasAttribute) {
return currentNode as HTMLElement; // Found a matching ancestor
} else if (elementContainsAttribute) {
return currentNode.querySelector(
`[${attributeName}="${attributeValue}"]`
) as HTMLElement; // Found a matching ancestor
}

// Move up the DOM tree to the parent or parentNode, whichever is available
currentNode = currentNode.parentElement || currentNode.parentNode || null;
}

return null; // No matching ancestor found
};
1 change: 1 addition & 0 deletions packages/uui-base/lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './Timer';
export * from './demandCustomElement';
export * from './drag';
export * from './math';
export * from './findAncestorByAttributeValue';
10 changes: 8 additions & 2 deletions packages/uui-button/lib/uui-button.element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import {
UUIHorizontalShakeKeyframes,
} from '@umbraco-ui/uui-base/lib/animations';
import { demandCustomElement } from '@umbraco-ui/uui-base/lib/utils';
import { FormControlMixin, LabelMixin } from '@umbraco-ui/uui-base/lib/mixins';
import {
FormControlMixin,
LabelMixin,
PopoverTargetMixin,
} from '@umbraco-ui/uui-base/lib/mixins';
import { defineElement } from '@umbraco-ui/uui-base/lib/registration';
import {
iconCheck,
Expand Down Expand Up @@ -43,7 +47,7 @@ export type UUIButtonType = 'submit' | 'button' | 'reset';
*/
@defineElement('uui-button')
export class UUIButtonElement extends FormControlMixin(
LabelMixin('', LitElement)
LabelMixin('', PopoverTargetMixin(LitElement))
) {
static styles = [
UUIHorizontalShakeKeyframes,
Expand Down Expand Up @@ -459,6 +463,8 @@ export class UUIButtonElement extends FormControlMixin(
break;
}
}

this._togglePopover();
}

private _resetStateTimeout?: number;
Expand Down
31 changes: 31 additions & 0 deletions packages/uui-popover-container/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# uui-popover-container

![npm](https://img.shields.io/npm/v/@umbraco-ui/uui-popover-container?logoColor=%231B264F)

Umbraco style popover-container component.

## Installation

### ES imports

```zsh
npm i @umbraco-ui/uui-popover-container
```

Import the registration of `<uui-popover-container>` via:

```javascript
import '@umbraco-ui/uui-popover-container';
```

When looking to leverage the `UUIPopoverContainerElement` base class as a type and/or for extension purposes, do so via:

```javascript
import { UUIPopoverContainerElement } from '@umbraco-ui/uui-popover-container';
```

## Usage

```html
<uui-popover-container></uui-popover-container>
```
1 change: 1 addition & 0 deletions packages/uui-popover-container/lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './uui-popover-container.element';
Loading