-
Notifications
You must be signed in to change notification settings - Fork 160
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
760 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
:host{ | ||
width: min-content; | ||
} | ||
label{ | ||
display: block; | ||
padding: 2px 5px; | ||
font-size: 12px; | ||
color: var(--text-color-secondary, rgba(0, 0, 0, .45)); | ||
} | ||
::slotted(xy-option){ | ||
text-indent: 1em; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import Base from "../xy-base.js"; | ||
import style from "./index.css?inline" assert { type: "css" }; | ||
|
||
export default class OptGroup extends Base { | ||
|
||
#label; | ||
|
||
static get observedAttributes() { | ||
return ["disabled", "label"]; | ||
} | ||
constructor() { | ||
super(); | ||
const shadowRoot = this.attachShadow({ mode: "open" }); | ||
this.adoptedStyle(style); | ||
shadowRoot.innerHTML = ` | ||
<label id="label"></label> | ||
<slot></slot> | ||
`; | ||
this.#label = shadowRoot.getElementById("label"); | ||
} | ||
|
||
get label() { | ||
return this.getAttribute("label") || "group"; | ||
} | ||
|
||
get disabled() { | ||
return this.getAttribute("disabled") !== null; | ||
} | ||
|
||
set disabled(value) { | ||
this.toggleAttribute("disabled", value) | ||
} | ||
|
||
set label(value) { | ||
return this.setAttribute("label", value); | ||
} | ||
|
||
connectedCallback() { | ||
|
||
} | ||
|
||
async attributeChangedCallback(name, oldValue, newValue) { | ||
await this.renderSlot(); | ||
if (name === "disabled") { | ||
const options = [...this.querySelectorAll(`xy-option`)]; | ||
options.forEach((el) => { | ||
el.toggleAttribute("disabled", newValue!==null) | ||
}); | ||
} | ||
if (name === "label") { | ||
this.#label.textContent = newValue | ||
} | ||
} | ||
} | ||
|
||
if (!customElements.get("xy-optgroup")) { | ||
customElements.define("xy-optgroup", OptGroup); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
xy-button::part(button){ | ||
justify-content: flex-start; | ||
padding: 4px 12px; | ||
} | ||
:host([selected]) xy-button::part(button){ | ||
background: var(--primary-color-opacity-100); | ||
color: var(--primary-color); | ||
} | ||
:host([disabled]) xy-button::part(button){ | ||
background-color: transparent; | ||
} | ||
xy-button::part(button):hover, | ||
xy-button::part(button):focus{ | ||
color: inherit; | ||
background-color: var(--primary-bg-secondary); | ||
outline: 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
import Base from "../xy-base.js"; | ||
import style from "./index.css?inline" assert { type: "css" }; | ||
import "../button/index.js"; | ||
|
||
export default class Option extends Base { | ||
|
||
#button; | ||
#mounted; | ||
|
||
static get observedAttributes() { | ||
return ["disabled", "selected"]; | ||
} | ||
constructor() { | ||
super(); | ||
const shadowRoot = this.attachShadow({ mode: "open" }); | ||
this.adoptedStyle(style); | ||
shadowRoot.innerHTML = ` | ||
<xy-button id="button" part="option" type="flat" block><slot></slot></xy-button> | ||
`; | ||
this.#button = shadowRoot.getElementById("button"); | ||
} | ||
|
||
focus() { | ||
this.#button.focus(); | ||
} | ||
|
||
get value() { | ||
return this.getAttribute("value") || this.textContent; | ||
} | ||
|
||
get label() { | ||
return this.textContent; | ||
} | ||
|
||
get disabled() { | ||
return this.getAttribute("disabled") !== null; | ||
} | ||
|
||
get selected() { | ||
return this.getAttribute("selected") !== null; | ||
} | ||
|
||
set selected(value) { | ||
this.toggleAttribute("selected", value) | ||
} | ||
|
||
set disabled(value) { | ||
this.toggleAttribute("disabled", value) | ||
} | ||
|
||
set value(value) { | ||
return this.setAttribute("value", value); | ||
} | ||
|
||
// 按方向键时自动选中 | ||
#focusSelect(dir) { | ||
const options = [...this.options]; | ||
const index = options.findIndex((el) => el === document.activeElement); | ||
let nextIndex = index + dir; | ||
if (nextIndex < 0) { | ||
nextIndex = options.length - 1; | ||
} | ||
if (nextIndex > options.length - 1) { | ||
nextIndex = 0; | ||
} | ||
const next = options[nextIndex]; | ||
next.focus(); | ||
} | ||
|
||
// 按 tab 键只聚焦一组radio中的一个,将其他radio设置为不可聚焦,inert = true | ||
#tabChange() { | ||
const options = [...this.options]; | ||
options.filter((el) => el !== this).forEach((el) => (el.inert = true)); | ||
} | ||
|
||
// 按 tab 聚焦到选中的 radio | ||
#tabFocus() { | ||
if (!document.activeElement.selected) { | ||
const options = [...this.options]; | ||
const current = options.find((el) => el.selected) || options[0]; | ||
current.focus(); | ||
} | ||
} | ||
|
||
// 按 tab 离开时还原 inert = false | ||
#tabBlur() { | ||
const options = [...this.options]; | ||
options.forEach((el) => (el.inert = false)); | ||
} | ||
|
||
connectedCallback() { | ||
if (this.#mounted) return | ||
this.#mounted = true | ||
if (this.parentNode.tagName === "XY-OPTGROUP") { | ||
this.options = this.parentNode.parentNode.querySelectorAll('xy-option:not([disabled])'); | ||
} else { | ||
this.options = this.parentNode.querySelectorAll('xy-option:not([disabled])'); | ||
} | ||
this.addEventListener("click", () => { | ||
this.focus() | ||
}) | ||
this.#button.addEventListener("keydown", (ev) => { | ||
if (!this.options.length) return; | ||
switch (ev.key) { | ||
case "ArrowDown": | ||
ev.preventDefault(); | ||
this.#focusSelect(1); | ||
break; | ||
case "ArrowUp": | ||
ev.preventDefault(); | ||
this.#focusSelect(-1); | ||
break; | ||
case "Tab": | ||
// this.#tabChange(); | ||
break; | ||
default: | ||
break; | ||
} | ||
}); | ||
this.#button.addEventListener("focus", () => { | ||
if (!this.options.length) return; | ||
// this.#tabFocus(); | ||
}); | ||
this.#button.addEventListener("blur", () => { | ||
if (!this.options.length) return; | ||
// this.#tabBlur(); | ||
}); | ||
} | ||
|
||
disconnectedCallback() { | ||
|
||
} | ||
|
||
attributeChangedCallback(name, oldValue, newValue) { | ||
if (name === "selected" && newValue!==null) { | ||
if (this.options?.length) { | ||
const prev = [...this.options].find( | ||
(el) => el.selected && el !== this | ||
); | ||
if (prev) { | ||
prev.selected = false; | ||
} | ||
} | ||
} | ||
if (name === "disabled") { | ||
this.#button.toggleAttribute("disabled", newValue!==null) | ||
} | ||
} | ||
} | ||
|
||
if (!customElements.get("xy-option")) { | ||
customElements.define("xy-option", Option); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.