aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.dockerignore1
-rw-r--r--.gitignore1
-rw-r--r--Makefile2
-rw-r--r--package-lock.json15
-rw-r--r--package.json2
-rw-r--r--templates/projects/view.tmpl8
-rw-r--r--templates/repo/issue/labels/edit_delete_label.tmpl4
-rw-r--r--templates/repo/issue/labels/label_new.tmpl4
-rw-r--r--web_src/css/base.css5
-rw-r--r--web_src/css/features/colorpicker.css164
-rw-r--r--web_src/css/features/projects.css23
-rw-r--r--web_src/css/repo.css18
-rw-r--r--web_src/js/features/colorpicker.js35
-rw-r--r--web_src/js/features/common-global.js6
-rw-r--r--web_src/js/features/comp/ColorPicker.js16
-rw-r--r--web_src/js/features/comp/LabelEdit.js17
-rw-r--r--web_src/js/index.js2
-rw-r--r--webpack.config.js7
18 files changed, 224 insertions, 106 deletions
diff --git a/.dockerignore b/.dockerignore
index 7143c039fd..b299c7313d 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -78,7 +78,6 @@ cpu.out
/public/assets/css
/public/assets/fonts
/public/assets/img/avatar
-/public/assets/img/webpack
/vendor
/web_src/fomantic/node_modules
/web_src/fomantic/build/*
diff --git a/.gitignore b/.gitignore
index abf9565cff..501fef7dcf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -77,7 +77,6 @@ cpu.out
/public/assets/css
/public/assets/fonts
/public/assets/licenses.txt
-/public/assets/img/webpack
/vendor
/web_src/fomantic/node_modules
/web_src/fomantic/build/*
diff --git a/Makefile b/Makefile
index b4fa62e05e..8489520920 100644
--- a/Makefile
+++ b/Makefile
@@ -119,7 +119,7 @@ FOMANTIC_WORK_DIR := web_src/fomantic
WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f)
WEBPACK_CONFIGS := webpack.config.js tailwind.config.js
WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
-WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts public/assets/img/webpack
+WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
diff --git a/package-lock.json b/package-lock.json
index fa4f80fbe8..25fe14e1a6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,11 +9,11 @@
"@citation-js/plugin-bibtex": "0.7.9",
"@citation-js/plugin-csl": "0.7.9",
"@citation-js/plugin-software-formats": "0.6.1",
- "@claviska/jquery-minicolors": "2.3.6",
"@github/markdown-toolbar-element": "2.2.3",
"@github/relative-time-element": "4.4.0",
"@github/text-expander-element": "2.6.1",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
+ "@melloware/coloris": "0.23.0",
"@primer/octicons": "19.9.0",
"add-asset-webpack-plugin": "2.0.1",
"ansi_up": "6.0.2",
@@ -394,14 +394,6 @@
"node": ">=14.0.0"
}
},
- "node_modules/@claviska/jquery-minicolors": {
- "version": "2.3.6",
- "resolved": "https://registry.npmjs.org/@claviska/jquery-minicolors/-/jquery-minicolors-2.3.6.tgz",
- "integrity": "sha512-8Ro6D4GCrmOl41+6w4NFhEOpx8vjxwVRI69bulXsFDt49uVRKhLU5TnzEV7AmOJrylkVq+ugnYNMiGHBieeKUQ==",
- "peerDependencies": {
- "jquery": ">= 1.7.x"
- }
- },
"node_modules/@csstools/css-parser-algorithms": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.1.tgz",
@@ -1297,6 +1289,11 @@
"@mcaptcha/core-glue": "^0.1.0-alpha-5"
}
},
+ "node_modules/@melloware/coloris": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@melloware/coloris/-/coloris-0.23.0.tgz",
+ "integrity": "sha512-VGIjI9+IQwg6BHjIE10yl0K2ARYz5bsjn6BgFEs1y1ErPAQymgdoxwVcSVL4Ai5t9OVs8xaCB7JKHqFu2N96Ow=="
+ },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
diff --git a/package.json b/package.json
index b5bfda9dc6..d5a1d46056 100644
--- a/package.json
+++ b/package.json
@@ -8,11 +8,11 @@
"@citation-js/plugin-bibtex": "0.7.9",
"@citation-js/plugin-csl": "0.7.9",
"@citation-js/plugin-software-formats": "0.6.1",
- "@claviska/jquery-minicolors": "2.3.6",
"@github/markdown-toolbar-element": "2.2.3",
"@github/relative-time-element": "4.4.0",
"@github/text-expander-element": "2.6.1",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
+ "@melloware/coloris": "0.23.0",
"@primer/octicons": "19.9.0",
"add-asset-webpack-plugin": "2.0.1",
"ansi_up": "6.0.2",
diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl
index b45174b086..33dd758c79 100644
--- a/templates/projects/view.tmpl
+++ b/templates/projects/view.tmpl
@@ -42,8 +42,8 @@
<div class="field color-field">
<label for="new_project_column_color_picker">{{ctx.Locale.Tr "repo.projects.column.color"}}</label>
- <div class="color picker column">
- <input class="color-picker" maxlength="7" placeholder="#c320f6" id="new_project_column_color_picker" name="color">
+ <div class="js-color-picker-input column">
+ <input maxlength="7" placeholder="#c320f6" id="new_project_column_color_picker" name="color">
{{template "repo/issue/label_precolors"}}
</div>
</div>
@@ -114,8 +114,8 @@
<div class="field color-field">
<label for="new_project_column_color">{{ctx.Locale.Tr "repo.projects.column.color"}}</label>
- <div class="color picker column">
- <input class="color-picker" maxlength="7" placeholder="#c320f6" id="new_project_column_color" name="color" value="{{.Color}}">
+ <div class="js-color-picker-input column">
+ <input maxlength="7" placeholder="#c320f6" id="new_project_column_color" name="color" value="{{.Color}}">
{{template "repo/issue/label_precolors"}}
</div>
</div>
diff --git a/templates/repo/issue/labels/edit_delete_label.tmpl b/templates/repo/issue/labels/edit_delete_label.tmpl
index 98e0f47020..fcf69217ea 100644
--- a/templates/repo/issue/labels/edit_delete_label.tmpl
+++ b/templates/repo/issue/labels/edit_delete_label.tmpl
@@ -52,8 +52,8 @@
</div>
<div class="field color-field">
<label for="color">{{ctx.Locale.Tr "repo.issues.label_color"}}</label>
- <div class="color picker column">
- <input class="color-picker" name="color" value="#70c24a" required maxlength="7">
+ <div class="column js-color-picker-input">
+ <input name="color" value="#70c24a"placeholder="#c320f6" required maxlength="7">
{{template "repo/issue/label_precolors"}}
</div>
</div>
diff --git a/templates/repo/issue/labels/label_new.tmpl b/templates/repo/issue/labels/label_new.tmpl
index 2b2b2336c4..32fd8e76d7 100644
--- a/templates/repo/issue/labels/label_new.tmpl
+++ b/templates/repo/issue/labels/label_new.tmpl
@@ -27,8 +27,8 @@
</div>
<div class="field color-field">
<label for="color">{{ctx.Locale.Tr "repo.issues.label_color"}}</label>
- <div class="color picker column">
- <input class="color-picker" name="color" value="#70c24a" required maxlength="7">
+ <div class="js-color-picker-input column">
+ <input name="color" value="#70c24a" placeholder="#c320f6" required maxlength="7">
{{template "repo/issue/label_precolors"}}
</div>
</div>
diff --git a/web_src/css/base.css b/web_src/css/base.css
index 368bc56126..21090f67ba 100644
--- a/web_src/css/base.css
+++ b/web_src/css/base.css
@@ -1436,11 +1436,6 @@ table th[data-sortt-desc] .svg {
vertical-align: -0.15em;
}
-/* for the jquery.minicolors plugin */
-.minicolors-panel {
- background: var(--color-secondary-dark-1) !important;
-}
-
.ui.tabular.menu {
border-color: var(--color-secondary);
}
diff --git a/web_src/css/features/colorpicker.css b/web_src/css/features/colorpicker.css
new file mode 100644
index 0000000000..0c651cfeb3
--- /dev/null
+++ b/web_src/css/features/colorpicker.css
@@ -0,0 +1,164 @@
+/* This is a stripped-down version of coloris's CSS tailored to our needs. It does only include
+ opaqua colors, and if more features like opacity are needed, the CSS needs to be extended
+ based on upstream: https://github.com/mdbassit/Coloris/blob/main/src/coloris.css. */
+
+.js-color-picker-input {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.js-color-picker-input input {
+ padding-top: 8px !important;
+ padding-bottom: 8px !important;
+ padding-left: 32px !important;
+}
+
+.clr-picker {
+ display: none;
+ flex-wrap: wrap;
+ position: absolute;
+ width: 200px;
+ z-index: 1002; /* above .ui.modal which has 1001 */
+ border-radius: var(--border-radius);
+ background-color: var(--color-menu);
+ justify-content: flex-end;
+ direction: ltr;
+ box-shadow: 0 5px 20px var(--color-shadow);
+ user-select: none;
+}
+
+.clr-picker.clr-open {
+ display: flex;
+}
+
+.clr-gradient {
+ position: relative;
+ width: 100%;
+ height: 100px;
+ border-radius: 3px 3px 0 0;
+ background: linear-gradient(rgba(0,0,0,0), #000), linear-gradient(90deg, #fff, currentcolor); /* stylelint-disable-line scale-unlimited/declaration-strict-value */
+ cursor: pointer;
+}
+
+.clr-marker {
+ position: absolute;
+ width: 12px;
+ height: 12px;
+ margin: -6px 0 0 -6px;
+ border: 1px solid var(--color-white);
+ border-radius: 50%;
+ background-color: currentcolor;
+ cursor: pointer;
+}
+
+.clr-picker input[type="range"]::-webkit-slider-runnable-track {
+ width: 100%;
+ height: 16px;
+}
+
+.clr-picker input[type="range"]::-webkit-slider-thumb {
+ width: 16px;
+ height: 16px;
+ -webkit-appearance: none;
+}
+
+.clr-picker input[type="range"]::-moz-range-track {
+ width: 100%;
+ height: 16px;
+ border: 0;
+}
+
+.clr-picker input[type="range"]::-moz-range-thumb {
+ width: 16px;
+ height: 16px;
+ border: 0;
+}
+
+.clr-hue {
+ background: linear-gradient(to right, #f00 0%, #ff0 16.66%, #0f0 33.33%, #0ff 50%, #00f 66.66%, #f0f 83.33%, #f00 100%); /* stylelint-disable-line scale-unlimited/declaration-strict-value */
+ position: relative;
+ width: calc(100% - 40px);
+ height: 10px;
+ margin: 10px 20px;
+ border-radius: 4px;
+}
+
+.clr-hue input[type="range"] {
+ position: absolute;
+ width: calc(100% + 32px);
+ margin: 0;
+ background-color: transparent;
+ opacity: 0;
+ cursor: pointer;
+ appearance: none;
+}
+
+.clr-hue div {
+ position: absolute;
+ width: 16px;
+ height: 16px;
+ left: 0;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ border: 2px solid var(--color-white);
+ border-radius: 50%;
+ background-color: currentcolor;
+ box-shadow: 0 0 1px var(--color-shadow);
+ pointer-events: none;
+}
+
+.clr-field {
+ flex: 1;
+ position: relative;
+ color: transparent;
+}
+
+.clr-field button {
+ position: absolute;
+ aspect-ratio: 1;
+ height: 16px;
+ left: 10px;
+ top: 50%;
+ transform: translateY(-50%);
+ margin: 0;
+ padding: 0;
+ border: 0;
+ color: inherit;
+ pointer-events: none;
+ border-radius: 2px;
+ background: repeating-linear-gradient(45deg, #aaa 25%, transparent 25%, transparent 75%, #aaa 75%, #aaa), repeating-linear-gradient(45deg, #aaa 25%, #fff 25%, #fff 75%, #aaa 75%, #aaa); /* stylelint-disable-line scale-unlimited/declaration-strict-value */
+ background-position: 0 0, 4px 4px;
+ background-size: 8px 8px;
+}
+
+.clr-field button::after {
+ content: "";
+ display: block;
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ left: 0;
+ top: 0;
+ border-radius: inherit;
+ background-color: currentcolor;
+}
+
+.clr-marker:focus {
+ outline: none;
+}
+
+.clr-keyboard-nav .clr-marker:focus,
+.clr-keyboard-nav .clr-hue input:focus + div,
+.clr-keyboard-nav .clr-alpha input:focus + div {
+ outline: none;
+ box-shadow: 0 0 2px 2px var(--color-white);
+}
+
+.clr-picker .clr-preview,
+.clr-picker .clr-clear,
+.clr-picker .clr-swatches,
+.clr-picker .clr-format,
+.clr-picker .clr-alpha,
+.clr-picker .clr-color {
+ display: none;
+}
diff --git a/web_src/css/features/projects.css b/web_src/css/features/projects.css
index 30df994c38..cec5e6fc64 100644
--- a/web_src/css/features/projects.css
+++ b/web_src/css/features/projects.css
@@ -102,26 +102,3 @@
.card-ghost * {
opacity: 0;
}
-
-.color-field .minicolors.minicolors-theme-default {
- display: block;
-}
-
-.color-field .minicolors.minicolors-theme-default .minicolors-input {
- height: 38px;
- padding-left: 2rem;
-}
-
-.color-field .minicolors.minicolors-theme-default .minicolors-swatch {
- top: 10px;
-}
-
-.edit-project-column-modal .color.picker.column,
-.new-project-column-modal .color.picker.column {
- display: flex;
-}
-
-.edit-project-column-modal .color.picker.column .minicolors,
-.new-project-column-modal .color.picker.column .minicolors {
- flex: 1;
-}
diff --git a/web_src/css/repo.css b/web_src/css/repo.css
index 18f28dc4a6..780093fb7f 100644
--- a/web_src/css/repo.css
+++ b/web_src/css/repo.css
@@ -2260,24 +2260,6 @@
padding-top: 15px;
}
-.edit-label.modal .form .color.picker.column,
-.new-label.modal .form .color.picker.column {
- display: flex;
-}
-
-.edit-label.modal .form .color.picker.column .minicolors,
-.new-label.modal .form .color.picker.column .minicolors {
- flex: 1;
-}
-
-.edit-label.modal .form .minicolors-swatch.minicolors-sprite,
-.new-label.modal .form .minicolors-swatch.minicolors-sprite {
- top: 10px;
- left: 10px;
- width: 15px;
- height: 15px;
-}
-
.tab-size-1 {
tab-size: 1 !important;
-moz-tab-size: 1 !important;
diff --git a/web_src/js/features/colorpicker.js b/web_src/js/features/colorpicker.js
index df0353376d..f342598e66 100644
--- a/web_src/js/features/colorpicker.js
+++ b/web_src/js/features/colorpicker.js
@@ -1,12 +1,31 @@
-import $ from 'jquery';
+export async function initColorPickers(selector = '.js-color-picker-input input', opts = {}) {
+ const inputEls = document.querySelectorAll(selector);
+ if (!inputEls.length) return;
-export async function createColorPicker(els) {
- if (!els.length) return;
-
- await Promise.all([
- import(/* webpackChunkName: "minicolors" */'@claviska/jquery-minicolors'),
- import(/* webpackChunkName: "minicolors" */'@claviska/jquery-minicolors/jquery.minicolors.css'),
+ const [{coloris, init}] = await Promise.all([
+ import(/* webpackChunkName: "colorpicker" */'@melloware/coloris'),
+ import(/* webpackChunkName: "colorpicker" */'../../css/features/colorpicker.css'),
]);
- return $(els).minicolors();
+ init();
+ coloris({
+ el: selector,
+ alpha: false,
+ focusInput: true,
+ selectInput: false,
+ ...opts,
+ });
+
+ for (const inputEl of inputEls) {
+ const parent = inputEl.closest('.js-color-picker-input');
+ // prevent tabbing on the color preview `button` inside the input
+ parent.querySelector('button').tabIndex = -1;
+ // init precolors
+ for (const el of parent.querySelectorAll('.precolors .color')) {
+ el.addEventListener('click', (e) => {
+ inputEl.value = e.target.getAttribute('data-color-hex');
+ inputEl.dispatchEvent(new Event('input', {bubbles: true}));
+ });
+ }
+ }
}
diff --git a/web_src/js/features/common-global.js b/web_src/js/features/common-global.js
index 18849ba7c1..ce702f041f 100644
--- a/web_src/js/features/common-global.js
+++ b/web_src/js/features/common-global.js
@@ -2,7 +2,6 @@ import $ from 'jquery';
import '../vendor/jquery.are-you-sure.js';
import {clippie} from 'clippie';
import {createDropzone} from './dropzone.js';
-import {initCompColorPicker} from './comp/ColorPicker.js';
import {showGlobalErrorMessage} from '../bootstrap.js';
import {handleGlobalEnterQuickSubmit} from './comp/QuickSubmit.js';
import {svg} from '../svg.js';
@@ -379,10 +378,7 @@ function initGlobalShowModal() {
$attrTarget.text(attrib.value); // FIXME: it should be more strict here, only handle div/span/p
}
}
- const $colorPickers = $modal.find('.color-picker');
- if ($colorPickers.length > 0) {
- initCompColorPicker(); // FIXME: this might cause duplicate init
- }
+
$modal.modal('setting', {
onApprove: () => {
// "form-fetch-action" can handle network errors gracefully,
diff --git a/web_src/js/features/comp/ColorPicker.js b/web_src/js/features/comp/ColorPicker.js
deleted file mode 100644
index d7e7038803..0000000000
--- a/web_src/js/features/comp/ColorPicker.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import $ from 'jquery';
-import {createColorPicker} from '../colorpicker.js';
-
-export function initCompColorPicker() {
- (async () => {
- await createColorPicker(document.querySelectorAll('.color-picker'));
-
- for (const el of document.querySelectorAll('.precolors .color')) {
- el.addEventListener('click', (e) => {
- const color = e.target.getAttribute('data-color-hex');
- const parent = e.target.closest('.color.picker');
- $(parent.querySelector('.color-picker')).minicolors('value', color);
- });
- }
- })();
-}
diff --git a/web_src/js/features/comp/LabelEdit.js b/web_src/js/features/comp/LabelEdit.js
index 843657a6b6..2cc75cc6b0 100644
--- a/web_src/js/features/comp/LabelEdit.js
+++ b/web_src/js/features/comp/LabelEdit.js
@@ -1,5 +1,4 @@
import $ from 'jquery';
-import {initCompColorPicker} from './ColorPicker.js';
function isExclusiveScopeName(name) {
return /.*[^/]\/[^/].*/.test(name);
@@ -28,13 +27,17 @@ function updateExclusiveLabelEdit(form) {
export function initCompLabelEdit(selector) {
if (!$(selector).length) return;
- initCompColorPicker();
// Create label
$('.new-label.button').on('click', () => {
updateExclusiveLabelEdit('.new-label');
$('.new-label.modal').modal({
onApprove() {
+ const form = document.querySelector('.new-label.form');
+ if (!form.checkValidity()) {
+ form.reportValidity();
+ return false;
+ }
$('.new-label.form').trigger('submit');
},
}).modal('show');
@@ -60,10 +63,18 @@ export function initCompLabelEdit(selector) {
updateExclusiveLabelEdit('.edit-label');
$('.edit-label .label-desc-input').val(this.getAttribute('data-description'));
- $('.edit-label .color-picker').minicolors('value', this.getAttribute('data-color'));
+
+ const colorInput = document.querySelector('.edit-label .js-color-picker-input input');
+ colorInput.value = this.getAttribute('data-color');
+ colorInput.dispatchEvent(new Event('input', {bubbles: true}));
$('.edit-label.modal').modal({
onApprove() {
+ const form = document.querySelector('.edit-label.form');
+ if (!form.checkValidity()) {
+ form.reportValidity();
+ return false;
+ }
$('.edit-label.form').trigger('submit');
},
}).modal('show');
diff --git a/web_src/js/index.js b/web_src/js/index.js
index 4c707486bd..fc2f6b9b0b 100644
--- a/web_src/js/index.js
+++ b/web_src/js/index.js
@@ -86,6 +86,7 @@ import {initRepoRecentCommits} from './features/recent-commits.js';
import {initRepoDiffCommitBranchesAndTags} from './features/repo-diff-commit.js';
import {initDirAuto} from './modules/dirauto.js';
import {initRepositorySearch} from './features/repo-search.js';
+import {initColorPickers} from './features/colorpicker.js';
// Init Gitea's Fomantic settings
initGiteaFomantic();
@@ -188,4 +189,5 @@ onDomReady(() => {
initRepoDiffView();
initPdfViewer();
initScopedAccessTokenCategories();
+ initColorPickers();
});
diff --git a/webpack.config.js b/webpack.config.js
index 0b0e7403e8..fdf80a5313 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -192,13 +192,6 @@ export default {
filename: 'fonts/[name].[contenthash:8][ext]',
},
},
- {
- test: /\.png$/i,
- type: 'asset/resource',
- generator: {
- filename: 'img/webpack/[name].[contenthash:8][ext]',
- },
- },
],
},
plugins: [