diff --git a/com.woltlab.wcf/templates/shared_fontAwesomeJavaScript.tpl b/com.woltlab.wcf/templates/shared_fontAwesomeJavaScript.tpl
index d26e8e65231..64e34f5e764 100644
--- a/com.woltlab.wcf/templates/shared_fontAwesomeJavaScript.tpl
+++ b/com.woltlab.wcf/templates/shared_fontAwesomeJavaScript.tpl
@@ -1,12 +1,6 @@
diff --git a/ts/WoltLabSuite/Core/Ui/Style/FontAwesome.ts b/ts/WoltLabSuite/Core/Ui/Style/FontAwesome.ts
index 5aa87487d65..d87d35d4626 100644
--- a/ts/WoltLabSuite/Core/Ui/Style/FontAwesome.ts
+++ b/ts/WoltLabSuite/Core/Ui/Style/FontAwesome.ts
@@ -7,94 +7,86 @@
* @woltlabExcludeBundle tiny
*/
-import { DialogCallbackObject, DialogCallbackSetup } from "../Dialog/Data";
-import * as Language from "../../Language";
-import UiDialog from "../Dialog";
+import { getPhrase } from "WoltLabSuite/Core/Language";
import UiItemListFilter from "../ItemList/Filter";
+import { dialogFactory } from "WoltLabSuite/Core/Component/Dialog";
type CallbackSelect = (icon: string, forceSolid: boolean) => void;
+type IconData = { icon: string; forceSolid: boolean };
+
+function createIconList(): HTMLElement {
+ const ul = document.createElement("ul");
+ ul.classList.add("fontAwesome__icons");
+ ul.id = "fontAwesomeIcons";
+
+ const icons: string[] = [];
+ window.getFontAwesome7Metadata().forEach(([, hasRegular], name) => {
+ if (hasRegular) {
+ icons.push(
+ `
`,
+ );
+ }
+
+ icons.push(
+ ``,
+ );
+ });
-class UiStyleFontAwesome implements DialogCallbackObject {
- private callback?: CallbackSelect = undefined;
- private iconList?: HTMLElement = undefined;
- private itemListFilter?: UiItemListFilter = undefined;
-
- open(callback: CallbackSelect): void {
- this.callback = callback;
-
- UiDialog.open(this);
- }
-
- /**
- * Selects an icon, notifies the callback and closes the dialog.
- */
- protected click(event: MouseEvent): void {
- event.preventDefault();
+ ul.innerHTML = icons.join("");
- const target = event.target as HTMLElement;
- const item = target.closest("li") as HTMLLIElement;
- const icon = item.querySelector("fa-icon")!;
+ return ul;
+}
- UiDialog.close(this);
+let content: HTMLElement | undefined = undefined;
+function getContent(): HTMLElement {
+ if (content === undefined) {
+ const iconList = createIconList();
+ iconList.addEventListener("click", (event) => {
+ event.preventDefault();
+
+ const { target } = event;
+ if (!(target instanceof HTMLButtonElement)) {
+ return;
+ }
+
+ const icon = target.querySelector("fa-icon")!;
+ const selectedEvent = new CustomEvent("font-awesome:selected", {
+ bubbles: true,
+ detail: {
+ icon: icon.name,
+ forceSolid: icon.solid,
+ },
+ });
+ iconList.dispatchEvent(selectedEvent);
+ });
- this.callback!(icon.name, icon.solid);
+ content = document.createElement("div");
+ content.id = "fontAwesomeSelection";
+ content.append(iconList);
}
- _dialogSetup(): ReturnType {
- return {
- id: "fontAwesomeSelection",
- options: {
- onSetup: () => {
- this.iconList = document.getElementById("fontAwesomeIcons") as HTMLElement;
-
- const icons: string[] = [];
- window.getFontAwesome7Metadata().forEach(([, hasRegular], name) => {
- if (hasRegular) {
- icons.push(`${name}`);
- }
-
- icons.push(`${name}`);
- });
-
- // build icons
- this.iconList.innerHTML = icons.join("");
-
- this.iconList.addEventListener("click", (ev) => this.click(ev));
-
- this.itemListFilter = new UiItemListFilter("fontAwesomeIcons", {
- callbackPrepareItem: (item) => {
- const small = item.querySelector("small") as HTMLElement;
- const text = small.textContent.trim();
-
- return {
- item,
- span: small,
- text,
- };
- },
- enableVisibilityFilter: false,
- filterPosition: "top",
- });
- },
- onShow: () => {
- this.itemListFilter!.reset();
- },
- title: Language.get("wcf.global.fontAwesome.selectIcon"),
- },
- source: '',
- };
- }
+ return content;
}
-let uiStyleFontAwesome: UiStyleFontAwesome;
-
-/**
- * Sets the list of available icons, must be invoked prior to any call
- * to the `open()` method.
- */
-export function setup(): void {
- if (!uiStyleFontAwesome) {
- uiStyleFontAwesome = new UiStyleFontAwesome();
+let itemListFilter: UiItemListFilter | undefined = undefined;
+function setupListeners(): void {
+ if (itemListFilter === undefined) {
+ itemListFilter = new UiItemListFilter("fontAwesomeIcons", {
+ callbackPrepareItem: (item) => {
+ const small = item.querySelector("small") as HTMLElement;
+ const text = small.textContent.trim();
+
+ return {
+ item,
+ span: small,
+ text,
+ };
+ },
+ enableVisibilityFilter: false,
+ filterPosition: "top",
+ });
+ } else {
+ itemListFilter.reset();
}
}
@@ -103,11 +95,18 @@ export function setup(): void {
* invoked with the selection icon's name as the only argument.
*/
export function open(callback: CallbackSelect): void {
- if (!uiStyleFontAwesome) {
- throw new Error(
- "Missing icon data, please include the template before calling this method using `{include file='shared_fontAwesomeJavaScript'}`.",
- );
- }
+ const dialog = dialogFactory().fromElement(getContent()).asConfirmation();
+ dialog.addEventListener(
+ "font-awesome:selected",
+ (event: CustomEvent) => {
+ dialog.close();
+
+ callback(event.detail.icon, event.detail.forceSolid);
+ },
+ { once: true },
+ );
+
+ dialog.show(getPhrase("wcf.global.fontAwesome.selectIcon"));
- uiStyleFontAwesome.open(callback);
+ setupListeners();
}
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Style/FontAwesome.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Style/FontAwesome.js
index 409e125b59e..76f7d0ba805 100644
--- a/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Style/FontAwesome.js
+++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Style/FontAwesome.js
@@ -6,80 +6,70 @@
* @license GNU Lesser General Public License
* @woltlabExcludeBundle tiny
*/
-define(["require", "exports", "tslib", "../../Language", "../Dialog", "../ItemList/Filter"], function (require, exports, tslib_1, Language, Dialog_1, Filter_1) {
+define(["require", "exports", "tslib", "WoltLabSuite/Core/Language", "../ItemList/Filter", "WoltLabSuite/Core/Component/Dialog"], function (require, exports, tslib_1, Language_1, Filter_1, Dialog_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
- exports.setup = setup;
exports.open = open;
- Language = tslib_1.__importStar(Language);
- Dialog_1 = tslib_1.__importDefault(Dialog_1);
Filter_1 = tslib_1.__importDefault(Filter_1);
- class UiStyleFontAwesome {
- callback = undefined;
- iconList = undefined;
- itemListFilter = undefined;
- open(callback) {
- this.callback = callback;
- Dialog_1.default.open(this);
- }
- /**
- * Selects an icon, notifies the callback and closes the dialog.
- */
- click(event) {
- event.preventDefault();
- const target = event.target;
- const item = target.closest("li");
- const icon = item.querySelector("fa-icon");
- Dialog_1.default.close(this);
- this.callback(icon.name, icon.solid);
- }
- _dialogSetup() {
- return {
- id: "fontAwesomeSelection",
- options: {
- onSetup: () => {
- this.iconList = document.getElementById("fontAwesomeIcons");
- const icons = [];
- window.getFontAwesome7Metadata().forEach(([, hasRegular], name) => {
- if (hasRegular) {
- icons.push(`${name}`);
- }
- icons.push(`${name}`);
- });
- // build icons
- this.iconList.innerHTML = icons.join("");
- this.iconList.addEventListener("click", (ev) => this.click(ev));
- this.itemListFilter = new Filter_1.default("fontAwesomeIcons", {
- callbackPrepareItem: (item) => {
- const small = item.querySelector("small");
- const text = small.textContent.trim();
- return {
- item,
- span: small,
- text,
- };
- },
- enableVisibilityFilter: false,
- filterPosition: "top",
- });
- },
- onShow: () => {
- this.itemListFilter.reset();
+ function createIconList() {
+ const ul = document.createElement("ul");
+ ul.classList.add("fontAwesome__icons");
+ ul.id = "fontAwesomeIcons";
+ const icons = [];
+ window.getFontAwesome7Metadata().forEach(([, hasRegular], name) => {
+ if (hasRegular) {
+ icons.push(``);
+ }
+ icons.push(``);
+ });
+ ul.innerHTML = icons.join("");
+ return ul;
+ }
+ let content = undefined;
+ function getContent() {
+ if (content === undefined) {
+ const iconList = createIconList();
+ iconList.addEventListener("click", (event) => {
+ event.preventDefault();
+ const { target } = event;
+ if (!(target instanceof HTMLButtonElement)) {
+ return;
+ }
+ const icon = target.querySelector("fa-icon");
+ const selectedEvent = new CustomEvent("font-awesome:selected", {
+ bubbles: true,
+ detail: {
+ icon: icon.name,
+ forceSolid: icon.solid,
},
- title: Language.get("wcf.global.fontAwesome.selectIcon"),
- },
- source: '',
- };
+ });
+ iconList.dispatchEvent(selectedEvent);
+ });
+ content = document.createElement("div");
+ content.id = "fontAwesomeSelection";
+ content.append(iconList);
}
+ return content;
}
- let uiStyleFontAwesome;
- /**
- * Sets the list of available icons, must be invoked prior to any call
- * to the `open()` method.
- */
- function setup() {
- if (!uiStyleFontAwesome) {
- uiStyleFontAwesome = new UiStyleFontAwesome();
+ let itemListFilter = undefined;
+ function setupListeners() {
+ if (itemListFilter === undefined) {
+ itemListFilter = new Filter_1.default("fontAwesomeIcons", {
+ callbackPrepareItem: (item) => {
+ const small = item.querySelector("small");
+ const text = small.textContent.trim();
+ return {
+ item,
+ span: small,
+ text,
+ };
+ },
+ enableVisibilityFilter: false,
+ filterPosition: "top",
+ });
+ }
+ else {
+ itemListFilter.reset();
}
}
/**
@@ -87,9 +77,12 @@ define(["require", "exports", "tslib", "../../Language", "../Dialog", "../ItemLi
* invoked with the selection icon's name as the only argument.
*/
function open(callback) {
- if (!uiStyleFontAwesome) {
- throw new Error("Missing icon data, please include the template before calling this method using `{include file='shared_fontAwesomeJavaScript'}`.");
- }
- uiStyleFontAwesome.open(callback);
+ const dialog = (0, Dialog_1.dialogFactory)().fromElement(getContent()).asConfirmation();
+ dialog.addEventListener("font-awesome:selected", (event) => {
+ dialog.close();
+ callback(event.detail.icon, event.detail.forceSolid);
+ }, { once: true });
+ dialog.show((0, Language_1.getPhrase)("wcf.global.fontAwesome.selectIcon"));
+ setupListeners();
}
});
diff --git a/wcfsetup/install/files/style/ui/fontAwesome.scss b/wcfsetup/install/files/style/ui/fontAwesome.scss
index ebedd715abb..df98cb8351a 100644
--- a/wcfsetup/install/files/style/ui/fontAwesome.scss
+++ b/wcfsetup/install/files/style/ui/fontAwesome.scss
@@ -1,34 +1,35 @@
-.fontAwesomeIcons {
+.fontAwesome__icons {
border: 1px solid var(--wcfContentBorderInner);
+ display: grid;
+ grid-auto-flow: row;
+ grid-template-columns: repeat(3, 150px);
max-height: 540px;
overflow: auto;
@media only screen and (min-height: 700px) and (max-height: 800px) {
max-height: 450px;
}
+}
- > li {
- display: inline-flex;
- flex-wrap: wrap;
- justify-content: center;
- padding: 10px 0;
- width: 150px;
+.fontAwesome__icon {
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+ padding: 10px 0;
+ width: 100%;
+}
- &:hover {
- background-color: var(--wcfButtonBackgroundActive);
- color: var(--wcfButtonTextActive);
- cursor: pointer;
+.fontAwesome__icon__name {
+ color: var(--wcfContentDimmedText);
+}
- > small {
- color: inherit;
- cursor: pointer;
- }
- }
+@media (hover: hover) {
+ .fontAwesome__icon:hover {
+ background-color: var(--wcfButtonBackgroundActive);
+ color: var(--wcfButtonTextActive);
- > small {
- color: var(--wcfContentDimmedText);
- flex: 0 0 100%;
- text-align: center;
+ .fontAwesome__icon__name {
+ color: inherit;
}
}
}