@yuneta/gobj-ui 7.23.40 → 7.23.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/gobj-ui.cjs.js +73 -4
- package/dist/gobj-ui.es.js +73 -4
- package/package.json +1 -1
- package/src/bulma_is_light.test.js +160 -0
- package/src/bulma_tint.js +71 -0
- package/src/c_yui_schema_editor.js +27 -3
- package/src/shell_modals.js +2 -1
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -44,6 +44,75 @@ maplibre_gl = __toESM(maplibre_gl, 1);
|
|
|
44
44
|
let uplot = require("uplot");
|
|
45
45
|
uplot = __toESM(uplot, 1);
|
|
46
46
|
let _antv_g6 = require("@antv/g6");
|
|
47
|
+
//#region src/bulma_tint.js
|
|
48
|
+
/***********************************************************************
|
|
49
|
+
* bulma_tint.js
|
|
50
|
+
*
|
|
51
|
+
* Bulma's "soften this colour" modifier, applied so that it cannot
|
|
52
|
+
* be applied alone.
|
|
53
|
+
*
|
|
54
|
+
* WHY THIS IS A FUNCTION AND NOT A STRING. 'light' is one of
|
|
55
|
+
* Bulma's colours, so `is-light` is BOTH a colour and the modifier
|
|
56
|
+
* that softens another one. A compound selector may match the same
|
|
57
|
+
* class twice, so `.tag.is-light.is-light` matches an element that
|
|
58
|
+
* carries the class ONCE -- and that rule sets the text to
|
|
59
|
+
* var(--bulma-light-light-invert-l), WHICH BULMA NEVER DEFINES:
|
|
60
|
+
* referenced four times in bulma.css, declared zero times. The
|
|
61
|
+
* colour declaration is then invalid while the background still
|
|
62
|
+
* resolves, so what is left on screen is a pill with no readable
|
|
63
|
+
* label.
|
|
64
|
+
*
|
|
65
|
+
* Two selectors of Bulma 1 reach that undefined variable:
|
|
66
|
+
*
|
|
67
|
+
* .tag.is-light.is-light
|
|
68
|
+
* .notification.is-light.is-light
|
|
69
|
+
*
|
|
70
|
+
* It cost three unreadable chips in the schema editor -- the topic
|
|
71
|
+
* count, the schema version, and every column flag with no colour of
|
|
72
|
+
* its own ('writable', 'image', 'wild'...). They read as empty
|
|
73
|
+
* pills, which looks like a bug in the DATA and is a missing CSS
|
|
74
|
+
* variable.
|
|
75
|
+
*
|
|
76
|
+
* The neutral chip is a bare element with no modifier at all: it
|
|
77
|
+
* takes --bulma-background-l and --bulma-text-l, follows the theme
|
|
78
|
+
* and stays legible in both.
|
|
79
|
+
*
|
|
80
|
+
* Copyright (c) 2026, ArtGins.
|
|
81
|
+
* All Rights Reserved.
|
|
82
|
+
***********************************************************************/
|
|
83
|
+
var TINTABLE = [
|
|
84
|
+
"primary",
|
|
85
|
+
"link",
|
|
86
|
+
"info",
|
|
87
|
+
"success",
|
|
88
|
+
"warning",
|
|
89
|
+
"danger",
|
|
90
|
+
"black",
|
|
91
|
+
"dark",
|
|
92
|
+
"white",
|
|
93
|
+
"text",
|
|
94
|
+
"ghost"
|
|
95
|
+
];
|
|
96
|
+
/***************************************************************
|
|
97
|
+
* A softened colour, or nothing.
|
|
98
|
+
*
|
|
99
|
+
* yui_tint("warning") -> "is-warning is-light"
|
|
100
|
+
* yui_tint("is-warning") -> "is-warning is-light"
|
|
101
|
+
* yui_tint("light") -> "" (there is nothing to soften)
|
|
102
|
+
* yui_tint("") -> ""
|
|
103
|
+
* yui_tint(undefined) -> ""
|
|
104
|
+
*
|
|
105
|
+
* Anything it does not recognise comes back empty rather than being
|
|
106
|
+
* passed through: a class this function cannot vouch for is exactly the
|
|
107
|
+
* case it exists to stop.
|
|
108
|
+
***************************************************************/
|
|
109
|
+
function yui_tint(colour) {
|
|
110
|
+
if (typeof colour !== "string") return "";
|
|
111
|
+
const name = colour.trim().replace(/^is-/, "");
|
|
112
|
+
if (TINTABLE.indexOf(name) < 0) return "";
|
|
113
|
+
return `is-${name} is-light`;
|
|
114
|
+
}
|
|
115
|
+
//#endregion
|
|
47
116
|
//#region src/shell_focus_trap.js
|
|
48
117
|
/***********************************************************************
|
|
49
118
|
* shell_focus_trap.js
|
|
@@ -2858,7 +2927,7 @@ function show_notification(shell, kind, message, opts) {
|
|
|
2858
2927
|
let $note = (0, _yuneta_gobj_js.createElement2)([
|
|
2859
2928
|
"div",
|
|
2860
2929
|
{
|
|
2861
|
-
class: `TOAST notification yui-notification
|
|
2930
|
+
class: `TOAST notification yui-notification ${yui_tint(kind)}`,
|
|
2862
2931
|
role: kind === "danger" ? "alert" : "status"
|
|
2863
2932
|
},
|
|
2864
2933
|
[["button", {
|
|
@@ -62413,7 +62482,7 @@ function open_card(gobj, logical, title, icon, tags, event, kw) {
|
|
|
62413
62482
|
let $tags = tags.map((tag) => {
|
|
62414
62483
|
return [
|
|
62415
62484
|
"span",
|
|
62416
|
-
{ class: `${logical}_TAG tag ${tag.style || "
|
|
62485
|
+
{ class: `${logical}_TAG tag ${tag.style || ""}`.trimEnd() },
|
|
62417
62486
|
tag.i18n ? [[
|
|
62418
62487
|
"span",
|
|
62419
62488
|
{ i18n: tag.i18n },
|
|
@@ -62560,7 +62629,7 @@ function render_topics(gobj, $body) {
|
|
|
62560
62629
|
topic.system_topic ? [
|
|
62561
62630
|
"span",
|
|
62562
62631
|
{
|
|
62563
|
-
class: "SCHEMA_TOPIC_SYSTEM tag
|
|
62632
|
+
class: "SCHEMA_TOPIC_SYSTEM tag ml-2",
|
|
62564
62633
|
i18n: "system"
|
|
62565
62634
|
},
|
|
62566
62635
|
(0, i18next.t)("system")
|
|
@@ -62909,7 +62978,7 @@ function column_row(gobj, topic, col, index, readonly, twice) {
|
|
|
62909
62978
|
let $flags = flags.map((flag) => {
|
|
62910
62979
|
return [
|
|
62911
62980
|
"span",
|
|
62912
|
-
{ class: `SCHEMA_COL_FLAG tag
|
|
62981
|
+
{ class: `SCHEMA_COL_FLAG tag ${yui_tint(flag_style(flag))}`.trimEnd() },
|
|
62913
62982
|
`${flag}`
|
|
62914
62983
|
];
|
|
62915
62984
|
});
|
package/dist/gobj-ui.es.js
CHANGED
|
@@ -39,6 +39,75 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
39
39
|
enumerable: true
|
|
40
40
|
}) : target, mod));
|
|
41
41
|
//#endregion
|
|
42
|
+
//#region src/bulma_tint.js
|
|
43
|
+
/***********************************************************************
|
|
44
|
+
* bulma_tint.js
|
|
45
|
+
*
|
|
46
|
+
* Bulma's "soften this colour" modifier, applied so that it cannot
|
|
47
|
+
* be applied alone.
|
|
48
|
+
*
|
|
49
|
+
* WHY THIS IS A FUNCTION AND NOT A STRING. 'light' is one of
|
|
50
|
+
* Bulma's colours, so `is-light` is BOTH a colour and the modifier
|
|
51
|
+
* that softens another one. A compound selector may match the same
|
|
52
|
+
* class twice, so `.tag.is-light.is-light` matches an element that
|
|
53
|
+
* carries the class ONCE -- and that rule sets the text to
|
|
54
|
+
* var(--bulma-light-light-invert-l), WHICH BULMA NEVER DEFINES:
|
|
55
|
+
* referenced four times in bulma.css, declared zero times. The
|
|
56
|
+
* colour declaration is then invalid while the background still
|
|
57
|
+
* resolves, so what is left on screen is a pill with no readable
|
|
58
|
+
* label.
|
|
59
|
+
*
|
|
60
|
+
* Two selectors of Bulma 1 reach that undefined variable:
|
|
61
|
+
*
|
|
62
|
+
* .tag.is-light.is-light
|
|
63
|
+
* .notification.is-light.is-light
|
|
64
|
+
*
|
|
65
|
+
* It cost three unreadable chips in the schema editor -- the topic
|
|
66
|
+
* count, the schema version, and every column flag with no colour of
|
|
67
|
+
* its own ('writable', 'image', 'wild'...). They read as empty
|
|
68
|
+
* pills, which looks like a bug in the DATA and is a missing CSS
|
|
69
|
+
* variable.
|
|
70
|
+
*
|
|
71
|
+
* The neutral chip is a bare element with no modifier at all: it
|
|
72
|
+
* takes --bulma-background-l and --bulma-text-l, follows the theme
|
|
73
|
+
* and stays legible in both.
|
|
74
|
+
*
|
|
75
|
+
* Copyright (c) 2026, ArtGins.
|
|
76
|
+
* All Rights Reserved.
|
|
77
|
+
***********************************************************************/
|
|
78
|
+
var TINTABLE = [
|
|
79
|
+
"primary",
|
|
80
|
+
"link",
|
|
81
|
+
"info",
|
|
82
|
+
"success",
|
|
83
|
+
"warning",
|
|
84
|
+
"danger",
|
|
85
|
+
"black",
|
|
86
|
+
"dark",
|
|
87
|
+
"white",
|
|
88
|
+
"text",
|
|
89
|
+
"ghost"
|
|
90
|
+
];
|
|
91
|
+
/***************************************************************
|
|
92
|
+
* A softened colour, or nothing.
|
|
93
|
+
*
|
|
94
|
+
* yui_tint("warning") -> "is-warning is-light"
|
|
95
|
+
* yui_tint("is-warning") -> "is-warning is-light"
|
|
96
|
+
* yui_tint("light") -> "" (there is nothing to soften)
|
|
97
|
+
* yui_tint("") -> ""
|
|
98
|
+
* yui_tint(undefined) -> ""
|
|
99
|
+
*
|
|
100
|
+
* Anything it does not recognise comes back empty rather than being
|
|
101
|
+
* passed through: a class this function cannot vouch for is exactly the
|
|
102
|
+
* case it exists to stop.
|
|
103
|
+
***************************************************************/
|
|
104
|
+
function yui_tint(colour) {
|
|
105
|
+
if (typeof colour !== "string") return "";
|
|
106
|
+
const name = colour.trim().replace(/^is-/, "");
|
|
107
|
+
if (TINTABLE.indexOf(name) < 0) return "";
|
|
108
|
+
return `is-${name} is-light`;
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
42
111
|
//#region src/shell_focus_trap.js
|
|
43
112
|
/***********************************************************************
|
|
44
113
|
* shell_focus_trap.js
|
|
@@ -2853,7 +2922,7 @@ function show_notification(shell, kind, message, opts) {
|
|
|
2853
2922
|
let $note = createElement2([
|
|
2854
2923
|
"div",
|
|
2855
2924
|
{
|
|
2856
|
-
class: `TOAST notification yui-notification
|
|
2925
|
+
class: `TOAST notification yui-notification ${yui_tint(kind)}`,
|
|
2857
2926
|
role: kind === "danger" ? "alert" : "status"
|
|
2858
2927
|
},
|
|
2859
2928
|
[["button", {
|
|
@@ -62408,7 +62477,7 @@ function open_card(gobj, logical, title, icon, tags, event, kw) {
|
|
|
62408
62477
|
let $tags = tags.map((tag) => {
|
|
62409
62478
|
return [
|
|
62410
62479
|
"span",
|
|
62411
|
-
{ class: `${logical}_TAG tag ${tag.style || "
|
|
62480
|
+
{ class: `${logical}_TAG tag ${tag.style || ""}`.trimEnd() },
|
|
62412
62481
|
tag.i18n ? [[
|
|
62413
62482
|
"span",
|
|
62414
62483
|
{ i18n: tag.i18n },
|
|
@@ -62555,7 +62624,7 @@ function render_topics(gobj, $body) {
|
|
|
62555
62624
|
topic.system_topic ? [
|
|
62556
62625
|
"span",
|
|
62557
62626
|
{
|
|
62558
|
-
class: "SCHEMA_TOPIC_SYSTEM tag
|
|
62627
|
+
class: "SCHEMA_TOPIC_SYSTEM tag ml-2",
|
|
62559
62628
|
i18n: "system"
|
|
62560
62629
|
},
|
|
62561
62630
|
t("system")
|
|
@@ -62904,7 +62973,7 @@ function column_row(gobj, topic, col, index, readonly, twice) {
|
|
|
62904
62973
|
let $flags = flags.map((flag) => {
|
|
62905
62974
|
return [
|
|
62906
62975
|
"span",
|
|
62907
|
-
{ class: `SCHEMA_COL_FLAG tag
|
|
62976
|
+
{ class: `SCHEMA_COL_FLAG tag ${yui_tint(flag_style(flag))}`.trimEnd() },
|
|
62908
62977
|
`${flag}`
|
|
62909
62978
|
];
|
|
62910
62979
|
});
|
package/package.json
CHANGED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/***********************************************************************
|
|
2
|
+
* bulma_is_light.test.js
|
|
3
|
+
*
|
|
4
|
+
* `is-light` MUST NEVER BE THE ONLY BULMA COLOUR ON AN ELEMENT.
|
|
5
|
+
*
|
|
6
|
+
* 'light' is one of Bulma's colours, so `is-light` is both a colour
|
|
7
|
+
* and the "soften it" modifier. A compound selector may match the
|
|
8
|
+
* same class twice, so `.tag.is-light.is-light` matches an element
|
|
9
|
+
* that carries the class ONCE -- and that rule sets the text to
|
|
10
|
+
* var(--bulma-light-light-invert-l), WHICH BULMA NEVER DEFINES:
|
|
11
|
+
* referenced four times in bulma.css, declared zero times. The
|
|
12
|
+
* colour declaration is then invalid while the background still
|
|
13
|
+
* resolves, and what is left on screen is a pill with no readable
|
|
14
|
+
* label.
|
|
15
|
+
*
|
|
16
|
+
* Two selectors in Bulma 1 reach that undefined variable:
|
|
17
|
+
*
|
|
18
|
+
* .tag.is-light.is-light
|
|
19
|
+
* .notification.is-light.is-light
|
|
20
|
+
*
|
|
21
|
+
* It cost three unreadable chips in the schema editor -- the topic
|
|
22
|
+
* count, the schema version, and every column flag without a colour
|
|
23
|
+
* of its own ('writable', 'image', 'wild'...). They looked like
|
|
24
|
+
* empty pills, which reads as a rendering bug in the data and is a
|
|
25
|
+
* missing CSS variable.
|
|
26
|
+
*
|
|
27
|
+
* THIS IS A SOURCE SCAN AND NOT A RENDER TEST ON PURPOSE: jsdom does
|
|
28
|
+
* not load Bulma, so no mounted test can see the contrast. What can
|
|
29
|
+
* be checked is the rule that produces it.
|
|
30
|
+
*
|
|
31
|
+
* Copyright (c) 2026, ArtGins.
|
|
32
|
+
* All Rights Reserved.
|
|
33
|
+
***********************************************************************/
|
|
34
|
+
import {describe, it, expect} from "vitest";
|
|
35
|
+
import {readdirSync, readFileSync} from "node:fs";
|
|
36
|
+
import {dirname, join} from "node:path";
|
|
37
|
+
import {fileURLToPath} from "node:url";
|
|
38
|
+
|
|
39
|
+
import {yui_tint, TINTABLE} from "./bulma_tint.js";
|
|
40
|
+
|
|
41
|
+
const SRC = dirname(fileURLToPath(import.meta.url));
|
|
42
|
+
|
|
43
|
+
/*
|
|
44
|
+
* The ONE file allowed to write the literal: yui_tint() emits it only
|
|
45
|
+
* next to a colour it has already checked against TINTABLE, and the
|
|
46
|
+
* colour is interpolated, so no source scan can see it. What guards
|
|
47
|
+
* that file is the behaviour suite at the bottom, not the scan.
|
|
48
|
+
*/
|
|
49
|
+
const EMITTER = "bulma_tint.js";
|
|
50
|
+
|
|
51
|
+
/* Every Bulma colour except 'light' itself. */
|
|
52
|
+
const COLOURS = [
|
|
53
|
+
"is-primary", "is-link", "is-info", "is-success", "is-warning",
|
|
54
|
+
"is-danger", "is-black", "is-dark", "is-white", "is-text", "is-ghost"
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
/*
|
|
58
|
+
* How far around an occurrence to look for its colour. The colour does
|
|
59
|
+
* not have to sit on the same line: it may come from a ternary, from a
|
|
60
|
+
* string concatenation split across two lines, or from a variable
|
|
61
|
+
* interpolated just before. A window is what covers all three without
|
|
62
|
+
* parsing javascript.
|
|
63
|
+
*/
|
|
64
|
+
const WINDOW = 260;
|
|
65
|
+
|
|
66
|
+
function offenders(source)
|
|
67
|
+
{
|
|
68
|
+
let out = [];
|
|
69
|
+
let at = source.indexOf("is-light");
|
|
70
|
+
while(at >= 0) {
|
|
71
|
+
const from = Math.max(0, at - WINDOW);
|
|
72
|
+
const to = Math.min(source.length, at + WINDOW);
|
|
73
|
+
const around = source.slice(from, to);
|
|
74
|
+
|
|
75
|
+
/* A comment ABOUT the rule is not a use of it. */
|
|
76
|
+
const line_start = source.lastIndexOf("\n", at) + 1;
|
|
77
|
+
const line = source.slice(line_start, source.indexOf("\n", at));
|
|
78
|
+
const is_comment = /^\s*(\*|\/\/|\/\*)/.test(line);
|
|
79
|
+
|
|
80
|
+
if(!is_comment && !COLOURS.some((c) => around.includes(c))) {
|
|
81
|
+
out.push(line.trim());
|
|
82
|
+
}
|
|
83
|
+
at = source.indexOf("is-light", at + 1);
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
describe("bulma: is-light never travels alone", () => {
|
|
89
|
+
const files = readdirSync(SRC).filter(
|
|
90
|
+
(f) => f.endsWith(".js") && !f.endsWith(".test.js") && f !== EMITTER
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
it("scans every source file of the library", () => {
|
|
94
|
+
expect(files.length).toBeGreaterThan(0);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
for(let file of files) {
|
|
98
|
+
it(`${file} carries no colourless is-light`, () => {
|
|
99
|
+
const source = readFileSync(join(SRC, file), "utf-8");
|
|
100
|
+
expect(offenders(source)).toEqual([]);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe("the scan itself", () => {
|
|
106
|
+
it("catches a colourless is-light", () => {
|
|
107
|
+
const bad = 'return ["span", {class: `SOMETHING tag is-light`}, "x"];';
|
|
108
|
+
expect(offenders(bad)).toHaveLength(1);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("accepts one that travels with a colour", () => {
|
|
112
|
+
const good = 'return ["span", {class: `SOMETHING tag is-warning is-light`}, "x"];';
|
|
113
|
+
expect(offenders(good)).toEqual([]);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("accepts a colour that arrives split across lines", () => {
|
|
117
|
+
const good = 'const c = `tag ${x ? "is-danger" : "is-warning"}`\n'
|
|
118
|
+
+ ' + " is-light";';
|
|
119
|
+
expect(offenders(good)).toEqual([]);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe("yui_tint", () => {
|
|
124
|
+
it("softens every colour that CAN be softened", () => {
|
|
125
|
+
for(let name of TINTABLE) {
|
|
126
|
+
expect(yui_tint(name)).toBe(`is-${name} is-light`);
|
|
127
|
+
expect(yui_tint(`is-${name}`)).toBe(`is-${name} is-light`);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("refuses to soften 'light' with itself", () => {
|
|
132
|
+
expect(yui_tint("light")).toBe("");
|
|
133
|
+
expect(yui_tint("is-light")).toBe("");
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("answers nothing for nothing", () => {
|
|
137
|
+
expect(yui_tint("")).toBe("");
|
|
138
|
+
expect(yui_tint(undefined)).toBe("");
|
|
139
|
+
expect(yui_tint(null)).toBe("");
|
|
140
|
+
expect(yui_tint(7)).toBe("");
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("does not pass through what it cannot vouch for", () => {
|
|
144
|
+
/* A class this function cannot recognise is exactly the case it
|
|
145
|
+
* exists to stop, so it comes back empty instead of forwarded. */
|
|
146
|
+
expect(yui_tint("is-whatever")).toBe("");
|
|
147
|
+
expect(yui_tint("has-text-danger")).toBe("");
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("never emits is-light on its own", () => {
|
|
151
|
+
for(let input of TINTABLE.concat(
|
|
152
|
+
["light", "is-light", "", "nope", "is-nope"]
|
|
153
|
+
)) {
|
|
154
|
+
const out = yui_tint(input);
|
|
155
|
+
if(out.includes("is-light")) {
|
|
156
|
+
expect(out).toMatch(/is-(primary|link|info|success|warning|danger|black|dark|white|text|ghost) is-light/);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/***********************************************************************
|
|
2
|
+
* bulma_tint.js
|
|
3
|
+
*
|
|
4
|
+
* Bulma's "soften this colour" modifier, applied so that it cannot
|
|
5
|
+
* be applied alone.
|
|
6
|
+
*
|
|
7
|
+
* WHY THIS IS A FUNCTION AND NOT A STRING. 'light' is one of
|
|
8
|
+
* Bulma's colours, so `is-light` is BOTH a colour and the modifier
|
|
9
|
+
* that softens another one. A compound selector may match the same
|
|
10
|
+
* class twice, so `.tag.is-light.is-light` matches an element that
|
|
11
|
+
* carries the class ONCE -- and that rule sets the text to
|
|
12
|
+
* var(--bulma-light-light-invert-l), WHICH BULMA NEVER DEFINES:
|
|
13
|
+
* referenced four times in bulma.css, declared zero times. The
|
|
14
|
+
* colour declaration is then invalid while the background still
|
|
15
|
+
* resolves, so what is left on screen is a pill with no readable
|
|
16
|
+
* label.
|
|
17
|
+
*
|
|
18
|
+
* Two selectors of Bulma 1 reach that undefined variable:
|
|
19
|
+
*
|
|
20
|
+
* .tag.is-light.is-light
|
|
21
|
+
* .notification.is-light.is-light
|
|
22
|
+
*
|
|
23
|
+
* It cost three unreadable chips in the schema editor -- the topic
|
|
24
|
+
* count, the schema version, and every column flag with no colour of
|
|
25
|
+
* its own ('writable', 'image', 'wild'...). They read as empty
|
|
26
|
+
* pills, which looks like a bug in the DATA and is a missing CSS
|
|
27
|
+
* variable.
|
|
28
|
+
*
|
|
29
|
+
* The neutral chip is a bare element with no modifier at all: it
|
|
30
|
+
* takes --bulma-background-l and --bulma-text-l, follows the theme
|
|
31
|
+
* and stays legible in both.
|
|
32
|
+
*
|
|
33
|
+
* Copyright (c) 2026, ArtGins.
|
|
34
|
+
* All Rights Reserved.
|
|
35
|
+
***********************************************************************/
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
* Bulma's colours, minus 'light' -- which is exactly the one that must
|
|
39
|
+
* never be softened with itself.
|
|
40
|
+
*/
|
|
41
|
+
const TINTABLE = [
|
|
42
|
+
"primary", "link", "info", "success", "warning",
|
|
43
|
+
"danger", "black", "dark", "white", "text", "ghost"
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
/***************************************************************
|
|
47
|
+
* A softened colour, or nothing.
|
|
48
|
+
*
|
|
49
|
+
* yui_tint("warning") -> "is-warning is-light"
|
|
50
|
+
* yui_tint("is-warning") -> "is-warning is-light"
|
|
51
|
+
* yui_tint("light") -> "" (there is nothing to soften)
|
|
52
|
+
* yui_tint("") -> ""
|
|
53
|
+
* yui_tint(undefined) -> ""
|
|
54
|
+
*
|
|
55
|
+
* Anything it does not recognise comes back empty rather than being
|
|
56
|
+
* passed through: a class this function cannot vouch for is exactly the
|
|
57
|
+
* case it exists to stop.
|
|
58
|
+
***************************************************************/
|
|
59
|
+
function yui_tint(colour)
|
|
60
|
+
{
|
|
61
|
+
if(typeof colour !== "string") {
|
|
62
|
+
return "";
|
|
63
|
+
}
|
|
64
|
+
const name = colour.trim().replace(/^is-/, "");
|
|
65
|
+
if(TINTABLE.indexOf(name) < 0) {
|
|
66
|
+
return "";
|
|
67
|
+
}
|
|
68
|
+
return `is-${name} is-light`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export {yui_tint, TINTABLE};
|
|
@@ -109,6 +109,7 @@ import {
|
|
|
109
109
|
is_object,
|
|
110
110
|
empty_string,
|
|
111
111
|
} from "@yuneta/gobj-js";
|
|
112
|
+
import {yui_tint} from "./bulma_tint.js";
|
|
112
113
|
|
|
113
114
|
import "./c_yui_schema_editor.css";
|
|
114
115
|
|
|
@@ -871,7 +872,24 @@ function render(gobj)
|
|
|
871
872
|
function open_card(gobj, logical, title, icon, tags, event, kw)
|
|
872
873
|
{
|
|
873
874
|
let $tags = tags.map((tag) => {
|
|
874
|
-
|
|
875
|
+
/*
|
|
876
|
+
* `is-light` ALONE IS NOT A NEUTRAL CHIP, IT IS AN UNREADABLE ONE.
|
|
877
|
+
*
|
|
878
|
+
* 'light' is one of Bulma's colours, so `is-light` is both the
|
|
879
|
+
* colour and the modifier -- and `.tag.is-light.is-light` matches
|
|
880
|
+
* an element carrying the class ONCE (a compound selector may
|
|
881
|
+
* match the same class twice). That rule sets the text to
|
|
882
|
+
* var(--bulma-light-light-invert-l), WHICH BULMA NEVER DEFINES:
|
|
883
|
+
* used four times in its stylesheet, declared zero. The colour
|
|
884
|
+
* declaration is then invalid, the background still resolves, and
|
|
885
|
+
* what is left is a pill with no readable label.
|
|
886
|
+
*
|
|
887
|
+
* A bare `.tag` is the neutral chip: it takes --bulma-background-l
|
|
888
|
+
* and --bulma-text-l, so it follows the theme and stays legible in
|
|
889
|
+
* both. `is-light` goes on only NEXT TO a real colour, where the
|
|
890
|
+
* variable it needs does exist.
|
|
891
|
+
*/
|
|
892
|
+
return ["span", {class: `${logical}_TAG tag ${tag.style || ""}`.trimEnd()},
|
|
875
893
|
tag.i18n
|
|
876
894
|
? [["span", {i18n: tag.i18n}, t(tag.i18n)],
|
|
877
895
|
["span", {class: "ml-1"}, `${tag.text}`]]
|
|
@@ -989,7 +1007,7 @@ function render_topics(gobj, $body)
|
|
|
989
1007
|
["td", {class: "SCHEMA_TOPIC_NAME"}, [
|
|
990
1008
|
["span", {class: "has-text-weight-semibold"}, `${topic.name}`],
|
|
991
1009
|
topic.system_topic
|
|
992
|
-
? ["span", {class: "SCHEMA_TOPIC_SYSTEM tag
|
|
1010
|
+
? ["span", {class: "SCHEMA_TOPIC_SYSTEM tag ml-2",
|
|
993
1011
|
i18n: "system"}, t("system")]
|
|
994
1012
|
: ["span", {}, ""],
|
|
995
1013
|
ambiguous
|
|
@@ -1222,7 +1240,13 @@ function column_row(gobj, topic, col, index, readonly, twice)
|
|
|
1222
1240
|
let is_pkey = (col.name === (topic.pkey || "id"));
|
|
1223
1241
|
|
|
1224
1242
|
let $flags = flags.map((flag) => {
|
|
1225
|
-
|
|
1243
|
+
/* The colour carries the meaning, and `is-light` softens it. With
|
|
1244
|
+
* no colour there is nothing to soften: a bare tag is the neutral
|
|
1245
|
+
* one, and `is-light` on its own would erase the label -- see
|
|
1246
|
+
* open_card(). It is why 'writable', 'image', 'wild' and every
|
|
1247
|
+
* other unstyled flag rendered as an empty pill. */
|
|
1248
|
+
return ["span", {class: `SCHEMA_COL_FLAG tag ${yui_tint(flag_style(flag))}`.trimEnd()},
|
|
1249
|
+
`${flag}`];
|
|
1226
1250
|
});
|
|
1227
1251
|
|
|
1228
1252
|
/* An unset `blob` column comes back as `{}`, which is an object and
|
package/src/shell_modals.js
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
empty_string,
|
|
34
34
|
log_warning,
|
|
35
35
|
} from "@yuneta/gobj-js";
|
|
36
|
+
import {yui_tint} from "./bulma_tint.js";
|
|
36
37
|
|
|
37
38
|
import {
|
|
38
39
|
activate_focus_trap_on,
|
|
@@ -121,7 +122,7 @@ function show_notification(shell, kind, message, opts)
|
|
|
121
122
|
? {i18n: message}
|
|
122
123
|
: {};
|
|
123
124
|
let $note = createElement2(
|
|
124
|
-
["div", {class: `TOAST notification yui-notification
|
|
125
|
+
["div", {class: `TOAST notification yui-notification ${yui_tint(kind)}`,
|
|
125
126
|
role: kind === "danger" ? "alert" : "status"},
|
|
126
127
|
[
|
|
127
128
|
["button", {class: "TOAST_CLOSE delete", "aria-label": "close"}],
|