@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.
@@ -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 is-${kind} is-light`,
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 || "is-light"}` },
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 is-light ml-2",
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 is-light ${flag_style(flag)}` },
62981
+ { class: `SCHEMA_COL_FLAG tag ${yui_tint(flag_style(flag))}`.trimEnd() },
62913
62982
  `${flag}`
62914
62983
  ];
62915
62984
  });
@@ -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 is-${kind} is-light`,
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 || "is-light"}` },
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 is-light ml-2",
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 is-light ${flag_style(flag)}` },
62976
+ { class: `SCHEMA_COL_FLAG tag ${yui_tint(flag_style(flag))}`.trimEnd() },
62908
62977
  `${flag}`
62909
62978
  ];
62910
62979
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.23.40",
3
+ "version": "7.23.41",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
@@ -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
- return ["span", {class: `${logical}_TAG tag ${tag.style || "is-light"}`},
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 is-light ml-2",
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
- return ["span", {class: `SCHEMA_COL_FLAG tag is-light ${flag_style(flag)}`}, `${flag}`];
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
@@ -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 is-${kind} is-light`,
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"}],