Skip to content

Commit

Permalink
feat: add popover component
Browse files Browse the repository at this point in the history
  • Loading branch information
chaxus committed Jan 28, 2024
1 parent 0c93b89 commit 27bcd35
Show file tree
Hide file tree
Showing 14 changed files with 809 additions and 185 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"brotli",
"chaxus",
"classname",
"colorpicker",
"componentization",
"Crossentropy",
"dataavailable",
Expand Down
14 changes: 10 additions & 4 deletions packages/ranui/components/checkbox/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,25 @@ export class Checkbox extends (HTMLElementSSR()!) {
checkInner: HTMLSpanElement;
context: Context;
static get observedAttributes(): string[] {
return ['disabled', 'icon', 'effect', 'iconSize', 'sheet'];
return ['disabled', 'checked'];
}
constructor() {
super();
this.setAttribute('class', 'ran-checkbox')
this.checkInput = document.createElement('input')
this.checkInput.setAttribute('class', 'ran-checkbox-input')
this.checkInput.setAttribute('type', 'checkbox')
this.checkInner = document.createElement('span')
this.checkInner.setAttribute('class', 'ran-checkbox-inner')
this.appendChild(this.checkInput)
this.appendChild(this.checkInner)
this.context = {
checked: false
}
}
get disabled(): string {
return this.getAttribute('disabled') || ''
}
set disabled(value: string) {
this.setAttribute('disabled', value);
}
get checked(): boolean {
return this.context.checked
}
Expand Down Expand Up @@ -60,6 +63,9 @@ export class Checkbox extends (HTMLElementSSR()!) {
this.update()
}
connectedCallback(): void {
this.setAttribute('class', 'ran-checkbox')
this.appendChild(this.checkInput)
this.appendChild(this.checkInner)
this.addEventListener('click', this.onChange)
}
disconnectCallback(): void {
Expand Down
33 changes: 33 additions & 0 deletions packages/ranui/components/colorpicker/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.ran-colorpicker {
box-sizing: border-box;
min-width: 32px;
height: 32px;
border-radius: 6px;
border: 1px solid #d9d9d9;
cursor: pointer;
display: inline-flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
background: #ffffff;
padding: 3px;
&-block {
position: relative;
border-radius: 4px;
width: 24px;
height: 24px;
box-shadow: inset 0 0 1px 0 rgba(0, 0, 0, 0.25);
background-image: conic-gradient(
rgba(0, 0, 0, 0.06) 0 25%,
transparent 0 50%,
rgba(0, 0, 0, 0.06) 0 75%,
transparent 0
);
background-size: 50% 50%;
}
&-inner {
width: 100%;
height: 100%;
border-radius: inherit;
}
}
87 changes: 87 additions & 0 deletions packages/ranui/components/colorpicker/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { addClassToElement, removeClassToElement } from 'ranuts';
import { HTMLElementSSR, createCustomError } from '@/utils/index';
import '@/components/popover'
import '@/components/content'
import './index.less'

// RGBA: red、green、blue, 透明度
// HSL: 色相、饱和度、亮度,透明度
// HSB: 色相、饱和度、明度,透明度
// HSV: 色相、饱和度、明度,透明度

interface Context {
disabled: boolean;
value: string
}

export class ColorPicker extends (HTMLElementSSR()!) {
colorpicker: HTMLDivElement;
colorpickerInner: HTMLDivElement;
context: Context;
popoverBlock: HTMLElement;
popoverContent: HTMLElement;
static get observedAttributes(): string[] {
return ['disabled', 'value'];
}
constructor() {
super();
this.setAttribute('class', 'ran-colorpicker')
this.popoverBlock = document.createElement('r-popover')
this.popoverBlock.setAttribute('class', 'ran-popover')
this.popoverContent = document.createElement('r-content')
this.popoverContent.setAttribute('class', 'ran-content')
this.colorpicker = document.createElement('div')
this.colorpicker.setAttribute('class', 'ran-colorpicker-block')
this.colorpickerInner = document.createElement('div')
this.colorpickerInner.setAttribute('class', 'ran-colorpicker-inner')
this.popoverBlock.appendChild(this.colorpicker)
this.popoverBlock.appendChild(this.popoverContent)
this.colorpicker.appendChild(this.colorpickerInner)
this.appendChild(this.popoverBlock)
this.context = {
value: '',
disabled: false
}
}
get value(): string {
return this.context.value
}
set value(value: string) {
this.setAttribute('value', value);
this.updateColorValue(value)
}
updateColorValue = (value: string): void => {
if (value !== this.context.value) {
this.colorpickerInner.style.setProperty('background', value)
this.context.value = value
}
}
openColorPicker = (): void => {
this.popoverContent.innerHTML = '1111'
}
connectedCallback(): void {
this.addEventListener('click', this.openColorPicker)
}
disconnectCallback(): void {
this.removeEventListener('click', this.openColorPicker)
}
attributeChangedCallback(n: string, o: string, v: string): void {
if (o !== v) {
if (n === 'value') {
this.updateColorValue(v)
}
}

}
}

function Custom() {
if (typeof document !== 'undefined' && !customElements.get('r-colorpicker')) {
customElements.define('r-colorpicker', ColorPicker);
return ColorPicker;
} else {
return createCustomError('document is undefined or r-colorpicker is exist');
}
}

export default Custom();
3 changes: 3 additions & 0 deletions packages/ranui/components/content/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.ran-content {
display: none;
}
50 changes: 50 additions & 0 deletions packages/ranui/components/content/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { HTMLElementSSR, createCustomError } from '@/utils/index';
import './index.less'


export class Content extends (HTMLElementSSR()!) {
observer: MutationObserver;
constructor() {
super();
this.observer = new MutationObserver(this.callback);
}
callback = (mutations: MutationRecord[], observer: MutationObserver): void => {
for (const mutation of mutations) {
if (mutation.type === "childList") {
// A child node has been added or removed.
this.onChange(mutation)
} else if (mutation.type === "attributes") {
// "The " + mutation.attributeName + " attribute was modified."
this.onChange(mutation)
}
}
};
onChange = (mutation: MutationRecord): void => {
this.dispatchEvent(
new CustomEvent('change', {
detail: {
type: mutation.type,
value: { content: this.innerHTML, mutation }
},
}),
);
}
connectedCallback(): void {
this.setAttribute('class', 'ran-content')
this.observer.observe(this, { attributes: true, childList: true, subtree: true });
}
disconnectCallback(): void {
this.observer.disconnect()
}
}

function Custom() {
if (typeof document !== 'undefined' && !customElements.get('r-content')) {
customElements.define('r-content', Content);
return Content;
} else {
return createCustomError('document is undefined or r-content is exist');
}
}

export default Custom();
78 changes: 78 additions & 0 deletions packages/ranui/components/popover/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
.ran-popover {
box-sizing: border-box;
position: relative;
display: inline-block;
margin: 0;
padding: 0;
&-content {
box-sizing: border-box;
margin: 0;
padding: 0;
color: rgba(0, 0, 0, 0.88);
font-size: 14px;
list-style: none;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
"Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
position: absolute;
z-index: 1030;
font-weight: normal;
white-space: normal;
text-align: start;
cursor: auto;
user-select: text;
transform-origin: var(--ran-x, 50%) var(--ran-y, 50%);
background: #fff;
transition: opacity 0.2s;
&-inner {
background-color: #fff;
background-clip: padding-box;
border-radius: 8px;
box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08),
0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
padding: 12px;
}
&-arrow {
transform: translateX(-50%) translateY(100%) rotate(180deg);
z-index: 1;
display: block;
pointer-events: none;
width: 16px;
height: 16px;
overflow: hidden;
position: absolute;
&::before {
position: absolute;
bottom: 0;
inset-inline-start: 0;
width: 16px;
height: 8px;
background: #fff;
clip-path: polygon(
1.6568542494923806px 100%,
50% 1.6568542494923806px,
14.34314575050762px 100%,
1.6568542494923806px 100%
);
clip-path: path(
"M 0 8 A 4 4 0 0 0 2.82842712474619 6.82842712474619 L 6.585786437626905 3.0710678118654755 A 2 2 0 0 1 9.414213562373096 3.0710678118654755 L 13.17157287525381 6.82842712474619 A 4 4 0 0 0 16 8 Z"
);
content: "";
}
&::after {
content: "";
position: absolute;
width: 8.970562748477143px;
height: 8.970562748477143px;
bottom: 0;
inset-inline: 0;
margin: auto;
border-radius: 0 0 2px 0;
transform: translateY(50%) rotate(-135deg);
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.05);
z-index: 0;
background: transparent;
}
}
}
}
Loading

0 comments on commit 27bcd35

Please sign in to comment.