@yuneta/gobj-ui 2.6.0 → 4.0.0
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/README.md +331 -11
- package/dist/gobj-ui.cjs.js +21386 -17919
- package/dist/gobj-ui.es.js +26059 -22613
- package/index.js +45 -9
- package/package.json +4 -4
- package/src/c_g6_nodes_tree.js +128 -40
- package/src/c_yui_form.css +9 -0
- package/src/c_yui_form.js +113 -53
- package/src/c_yui_gobj_tree_js.js +58 -36
- package/src/c_yui_json.css +139 -0
- package/src/c_yui_json.js +928 -0
- package/src/c_yui_json_graph.js +110 -20
- package/src/c_yui_map.js +18 -36
- package/src/c_yui_nav.js +6 -9
- package/src/c_yui_period.css +184 -0
- package/src/c_yui_period.js +1441 -0
- package/src/c_yui_shell.css +120 -0
- package/src/c_yui_shell.js +672 -111
- package/src/c_yui_treedb_graph.js +639 -37
- package/src/c_yui_treedb_schema.js +478 -0
- package/src/c_yui_treedb_topic_with_form.css +18 -0
- package/src/c_yui_treedb_topic_with_form.js +153 -103
- package/src/c_yui_treedb_topics.css +73 -0
- package/src/c_yui_treedb_topics.js +1070 -29
- package/src/c_yui_window.css +22 -0
- package/src/c_yui_window.js +182 -97
- package/src/c_yui_window_manager.js +38 -4
- package/src/json_view_helpers.js +214 -0
- package/src/json_view_helpers.test.js +135 -0
- package/src/route_map_model.js +317 -0
- package/src/route_map_model.test.js +209 -0
- package/src/route_resolver.js +24 -1
- package/src/route_resolver.test.js +40 -1
- package/src/shell_modals.js +162 -52
- package/src/shell_route_map.css +225 -0
- package/src/shell_route_map.js +363 -0
- package/src/tabulator.css +245 -0
- package/src/yui_dev.js +130 -8
- package/src/yui_frontend_view.js +106 -0
- package/src/yui_icons.css +62 -0
- package/src/yui_inputs.css +8 -3
- package/src/yui_inputs.js +51 -8
- package/src/yui_tabulator_i18n.js +128 -0
- package/src/yui_theme.js +147 -0
- package/src/yui_time.js +666 -0
- package/src/yui_time.test.js +330 -0
- package/src/yui_toolbar.css +28 -0
- package/src/yui_toolbar.js +86 -43
- package/src/c_yui_main.css +0 -501
- package/src/c_yui_main.js +0 -1623
- package/src/c_yui_routing.css +0 -18
- package/src/c_yui_routing.js +0 -837
- package/src/c_yui_tabs.js +0 -487
- package/src/themes.js +0 -215
- package/src/ytable.css +0 -63
- package/src/ytable.js +0 -505
package/src/yui_dev.js
CHANGED
|
@@ -15,9 +15,10 @@ import {
|
|
|
15
15
|
gobj_write_attr,
|
|
16
16
|
gobj_create_service,
|
|
17
17
|
gobj_find_service,
|
|
18
|
+
gobj_start,
|
|
18
19
|
set_log_callback,
|
|
20
|
+
set_console_log_enabled,
|
|
19
21
|
gobj_set_trace_machine_format,
|
|
20
|
-
trace_json,
|
|
21
22
|
} from "@yuneta/gobj-js";
|
|
22
23
|
|
|
23
24
|
import i18next from 'i18next';
|
|
@@ -37,6 +38,13 @@ let TRAFFIC_LOG = []; // [{title,event,command,sig,dir,size,ts,kw,
|
|
|
37
38
|
let TRAFFIC_COUNTS = new Map(); // signature -> occurrences (for periodic detection)
|
|
38
39
|
let SEARCH_TEXT = ""; // session-only free-text filter (not persisted)
|
|
39
40
|
|
|
41
|
+
/* Running totals of framework errors/warnings seen since page load (or the
|
|
42
|
+
* last Clear). Kept apart from TRAFFIC_LOG so the 600-entry cap can't rotate
|
|
43
|
+
* an error out of the count — the whole point of the status-line tally is to
|
|
44
|
+
* not lose that signal under a flood of automata/debug lines. */
|
|
45
|
+
let LOG_ERR_COUNT = 0;
|
|
46
|
+
let LOG_WARN_COUNT = 0;
|
|
47
|
+
|
|
40
48
|
/* Field names whose numeric value is a Unix timestamp (seconds). */
|
|
41
49
|
const TRAFFIC_TS_FIELDS = {
|
|
42
50
|
"__t__": 1, "__tm__": 1, "tm": 1, "t": 1,
|
|
@@ -161,6 +169,41 @@ function dev_hide_periodic()
|
|
|
161
169
|
return dev_num("dev_hide_periodic", 0) ? true : false;
|
|
162
170
|
}
|
|
163
171
|
|
|
172
|
+
/* Where dev output (traffic + all logs + automata) is routed:
|
|
173
|
+
* "window" → dev window only (browser console silenced framework-wide)
|
|
174
|
+
* "console" → browser console only (nothing appended to the window)
|
|
175
|
+
* "both" → console + window (default; unchanged from prior behaviour)
|
|
176
|
+
* The console side of logs is gated in gobj-js (set_console_log_enabled);
|
|
177
|
+
* the window side is gated here, in info_traffic / info_log. */
|
|
178
|
+
function dev_route()
|
|
179
|
+
{
|
|
180
|
+
let v = kw_get_local_storage_value("dev_output_route", "both", false);
|
|
181
|
+
return (v === "window" || v === "console") ? v : "both";
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* Push the current route's console decision down to gobj-js. Called from
|
|
185
|
+
* apply_dev_traces (startup) and whenever the Output selector changes. */
|
|
186
|
+
function apply_console_route()
|
|
187
|
+
{
|
|
188
|
+
set_console_log_enabled(dev_route() !== "window");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/* Emit one inter-event traffic line to the browser console (routes
|
|
192
|
+
* "console" and "both"). gobj-js only knows about framework logs, not this
|
|
193
|
+
* traffic feed, so the console mirror is produced here. */
|
|
194
|
+
function console_traffic(title, jn, direction, size)
|
|
195
|
+
{
|
|
196
|
+
let event = (jn && jn.event) ? String(jn.event) : "(no event)";
|
|
197
|
+
let kw = (jn && jn.kw && typeof jn.kw === "object") ? jn.kw : jn;
|
|
198
|
+
let color = (direction === 2) ? "#16a34a" : (direction === 3) ? "#dc2626" : "#2563eb";
|
|
199
|
+
window.console.log(
|
|
200
|
+
"%c" + dir_arrow(direction) + " " + (title ? "[" + title + "] " : "") + event +
|
|
201
|
+
(size ? " (" + size + "b)" : ""),
|
|
202
|
+
"color:" + color,
|
|
203
|
+
kw
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
164
207
|
function dev_muted()
|
|
165
208
|
{
|
|
166
209
|
let a = kw_get_local_storage_value("dev_muted_events", [], false);
|
|
@@ -182,6 +225,17 @@ function set_view(v)
|
|
|
182
225
|
refresh_dev_chrome();
|
|
183
226
|
}
|
|
184
227
|
|
|
228
|
+
function set_output_route(v)
|
|
229
|
+
{
|
|
230
|
+
if(v !== "window" && v !== "console" && v !== "both") {
|
|
231
|
+
v = "both";
|
|
232
|
+
}
|
|
233
|
+
kw_set_local_storage_value("dev_output_route", v);
|
|
234
|
+
apply_console_route();
|
|
235
|
+
rerender_all();
|
|
236
|
+
refresh_dev_chrome();
|
|
237
|
+
}
|
|
238
|
+
|
|
185
239
|
function toggle_pref(key, def)
|
|
186
240
|
{
|
|
187
241
|
let v = dev_num(key, def) ? 0 : 1;
|
|
@@ -353,6 +407,8 @@ function ensure_dev_style()
|
|
|
353
407
|
background: rgba(217,119,6,0.12); color: #b45309; cursor: pointer;
|
|
354
408
|
}
|
|
355
409
|
.YDEV_STAT.s-out { color: #2563eb; } .YDEV_STAT.s-in { color: #059669; } .YDEV_STAT.s-err { color: #dc2626; }
|
|
410
|
+
.YDEV_STAT.s-warn { color: #d97706; }
|
|
411
|
+
.YDEV_STAT.is-strong { font-weight: 700; }
|
|
356
412
|
.YDEV_TITLE { display: flex; align-items: baseline; gap: 8px; }
|
|
357
413
|
.YDEV_TITLE_MAIN { font-weight: 700; }
|
|
358
414
|
.YDEV_TITLE_SUB { opacity: 0.7; font-size: 12px; }
|
|
@@ -419,6 +475,7 @@ details.TRAFFIC_NEST > summary::-webkit-details-marker { display: none; }
|
|
|
419
475
|
:root[data-theme="dark"] .dir-in .TRAFFIC_ARROW, :root[data-theme="dark"] .dir-in .TRAFFIC_EVENT { color: #34d399; }
|
|
420
476
|
:root[data-theme="dark"] .dir-err .TRAFFIC_ARROW, :root[data-theme="dark"] .dir-err .TRAFFIC_EVENT { color: #f87171; }
|
|
421
477
|
:root[data-theme="dark"] .YDEV_STAT.s-out { color: #60a5fa; } :root[data-theme="dark"] .YDEV_STAT.s-in { color: #34d399; } :root[data-theme="dark"] .YDEV_STAT.s-err { color: #f87171; }
|
|
478
|
+
:root[data-theme="dark"] .YDEV_STAT.s-warn { color: #fbbf24; }
|
|
422
479
|
:root[data-theme="dark"] .TRAFFIC_VAL.t-num { color: #22d3ee; }
|
|
423
480
|
:root[data-theme="dark"] .TRAFFIC_VAL.t-bool, :root[data-theme="dark"] .TRAFFIC_VAL.t-null { color: #c084fc; }
|
|
424
481
|
:root[data-theme="dark"] .YDEV_CHIP.is-active { background: rgba(96,165,250,0.2); border-color: #60a5fa; color: #93c5fd; }
|
|
@@ -726,6 +783,8 @@ function clear_traffic()
|
|
|
726
783
|
{
|
|
727
784
|
TRAFFIC_LOG.length = 0;
|
|
728
785
|
TRAFFIC_COUNTS.clear();
|
|
786
|
+
LOG_ERR_COUNT = 0;
|
|
787
|
+
LOG_WARN_COUNT = 0;
|
|
729
788
|
let logger = document.getElementById('developer-traffic-logger');
|
|
730
789
|
if(logger) {
|
|
731
790
|
logger.replaceChildren();
|
|
@@ -792,7 +851,11 @@ function update_stats()
|
|
|
792
851
|
}
|
|
793
852
|
}
|
|
794
853
|
$s.replaceChildren();
|
|
854
|
+
/* Errors/warnings first — the signal you don't want to miss. Session
|
|
855
|
+
* totals (see LOG_ERR_COUNT), bold when non-zero so they stand out. */
|
|
795
856
|
let cells = [
|
|
857
|
+
[`✖ ${LOG_ERR_COUNT} err`, 's-err' + (LOG_ERR_COUNT ? ' is-strong' : '')],
|
|
858
|
+
[`▲ ${LOG_WARN_COUNT} warn`, 's-warn' + (LOG_WARN_COUNT ? ' is-strong' : '')],
|
|
796
859
|
[`${shown}/${total} shown`, ''],
|
|
797
860
|
[`⇢ ${out}`, 's-out'],
|
|
798
861
|
[`⇠ ${inc}`, 's-in'],
|
|
@@ -834,12 +897,6 @@ function append_and_follow(logger, node)
|
|
|
834
897
|
************************************************************/
|
|
835
898
|
function info_traffic(title, msg, direction, size)
|
|
836
899
|
{
|
|
837
|
-
let logger = document.getElementById('developer-traffic-logger');
|
|
838
|
-
if(!logger) {
|
|
839
|
-
trace_json(msg);
|
|
840
|
-
return;
|
|
841
|
-
}
|
|
842
|
-
|
|
843
900
|
if(!size) {
|
|
844
901
|
size = 0;
|
|
845
902
|
}
|
|
@@ -851,6 +908,21 @@ function info_traffic(title, msg, direction, size)
|
|
|
851
908
|
return;
|
|
852
909
|
}
|
|
853
910
|
|
|
911
|
+
let route = dev_route();
|
|
912
|
+
|
|
913
|
+
/* Console side (routes "console" / "both"). */
|
|
914
|
+
if(route !== "window") {
|
|
915
|
+
console_traffic(title, jn, direction, size);
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
/* Window side: skip when routed to the console only, or when the window
|
|
919
|
+
* is not mounted (closed). No fallback console dump — console_traffic
|
|
920
|
+
* above already covered every route that wants console output. */
|
|
921
|
+
let logger = document.getElementById('developer-traffic-logger');
|
|
922
|
+
if(!logger || route === "console") {
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
|
|
854
926
|
ensure_dev_style();
|
|
855
927
|
|
|
856
928
|
let event = (jn && jn.event) ? String(jn.event) : "(no event)";
|
|
@@ -923,6 +995,21 @@ function info_log(level, msg, hora)
|
|
|
923
995
|
if(__in_info_log__) {
|
|
924
996
|
return;
|
|
925
997
|
}
|
|
998
|
+
/* Tally errors/warnings for the status line, always — before any routing
|
|
999
|
+
* or window-open guard, so the count reflects the whole session even
|
|
1000
|
+
* while the window is closed or output is routed to the console. */
|
|
1001
|
+
if(level === "error") {
|
|
1002
|
+
LOG_ERR_COUNT++;
|
|
1003
|
+
} else if(level === "warning") {
|
|
1004
|
+
LOG_WARN_COUNT++;
|
|
1005
|
+
}
|
|
1006
|
+
/* Routed to the console only: the line already reached the browser
|
|
1007
|
+
* console (gobj-js gate left on), so don't mirror it into the window —
|
|
1008
|
+
* but keep the status-line tally live if the window is open. */
|
|
1009
|
+
if(dev_route() === "console") {
|
|
1010
|
+
update_stats();
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
926
1013
|
let logger = document.getElementById('developer-traffic-logger');
|
|
927
1014
|
if(!logger) {
|
|
928
1015
|
return;
|
|
@@ -1084,6 +1171,11 @@ function refresh_dev_chrome()
|
|
|
1084
1171
|
$b.classList.toggle('is-active', $b.getAttribute('data-view') === view);
|
|
1085
1172
|
});
|
|
1086
1173
|
|
|
1174
|
+
let route = dev_route();
|
|
1175
|
+
document.querySelectorAll('.YDEV_SEG_BTN[data-output]').forEach(($b) => {
|
|
1176
|
+
$b.classList.toggle('is-active', $b.getAttribute('data-output') === route);
|
|
1177
|
+
});
|
|
1178
|
+
|
|
1087
1179
|
/* The Expand section toggles only apply to the Expanded view — show
|
|
1088
1180
|
* the group only there, and reflect each toggle's persisted state. */
|
|
1089
1181
|
let $eg = document.getElementById('ydev-expand-grp');
|
|
@@ -1236,6 +1328,27 @@ function build_control_bar()
|
|
|
1236
1328
|
mk_view('name', 'Name only'),
|
|
1237
1329
|
]];
|
|
1238
1330
|
|
|
1331
|
+
/* Output routing: send traffic + all logs + automata to the dev window,
|
|
1332
|
+
* the browser console, or both. */
|
|
1333
|
+
let OUT_TITLES = {
|
|
1334
|
+
window: 'Dev window only (browser console stays clean)',
|
|
1335
|
+
console: 'Browser console only (nothing shown in this window)',
|
|
1336
|
+
both: 'Dev window and browser console',
|
|
1337
|
+
};
|
|
1338
|
+
let mk_out = (v, label) => ['button', {
|
|
1339
|
+
class: 'YDEV_SEG_BTN', 'data-output': v, type: 'button', title: OUT_TITLES[v],
|
|
1340
|
+
}, label, {
|
|
1341
|
+
click: (ev) => {
|
|
1342
|
+
ev.stopPropagation();
|
|
1343
|
+
set_output_route(v);
|
|
1344
|
+
}
|
|
1345
|
+
}];
|
|
1346
|
+
let output_seg = ['div', {class: 'YDEV_SEG', id: 'ydev-output'}, [
|
|
1347
|
+
mk_out('window', 'Window'),
|
|
1348
|
+
mk_out('console', 'Console'),
|
|
1349
|
+
mk_out('both', 'Both'),
|
|
1350
|
+
]];
|
|
1351
|
+
|
|
1239
1352
|
/* Expanded-view section toggles (only meaningful in the 'full' view;
|
|
1240
1353
|
* the group is shown/hidden by refresh_dev_chrome). */
|
|
1241
1354
|
let mk_expand = (key, label) => ['button', {
|
|
@@ -1312,6 +1425,7 @@ function build_control_bar()
|
|
|
1312
1425
|
|
|
1313
1426
|
return createElement2(['div', {class: 'YDEV_BAR'}, [
|
|
1314
1427
|
grp('Traces', [...trace_chips, simple_mach]), sep(),
|
|
1428
|
+
grp('Output', [output_seg]), sep(),
|
|
1315
1429
|
grp('View', [view_seg]), expand_grp, sep(),
|
|
1316
1430
|
grp('Show', [...dir_chips, periodic_chip]), sep(),
|
|
1317
1431
|
grp('Find', [search]), sep(),
|
|
@@ -1393,6 +1507,10 @@ function apply_dev_traces()
|
|
|
1393
1507
|
* automata FSM trace arrives as debug) into the monitor. info_log no-ops
|
|
1394
1508
|
* while the window is closed, so this is safe to leave armed. */
|
|
1395
1509
|
set_log_callback(info_log);
|
|
1510
|
+
|
|
1511
|
+
/* Honour the persisted Window / Console / Both routing at startup so a
|
|
1512
|
+
* refresh keeps the console silenced when "Window only" was chosen. */
|
|
1513
|
+
apply_console_route();
|
|
1396
1514
|
}
|
|
1397
1515
|
|
|
1398
1516
|
/************************************************************
|
|
@@ -1409,7 +1527,7 @@ function setup_dev(self, show)
|
|
|
1409
1527
|
if(show) {
|
|
1410
1528
|
ensure_dev_style();
|
|
1411
1529
|
|
|
1412
|
-
gobj_create_service(
|
|
1530
|
+
let win = gobj_create_service(
|
|
1413
1531
|
"Developer-Window",
|
|
1414
1532
|
"C_YUI_WINDOW",
|
|
1415
1533
|
{
|
|
@@ -1435,6 +1553,10 @@ function setup_dev(self, show)
|
|
|
1435
1553
|
},
|
|
1436
1554
|
self
|
|
1437
1555
|
);
|
|
1556
|
+
/* c_yuno's mt_play only starts the DEFAULT service, so a service
|
|
1557
|
+
* created here is ours to start; unstarted, it shows up in every
|
|
1558
|
+
* trace line as `!!C_YUI_WINDOW^Developer-Window`. */
|
|
1559
|
+
gobj_start(win);
|
|
1438
1560
|
|
|
1439
1561
|
kw_set_local_storage_value("open_developer_window", 1);
|
|
1440
1562
|
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/***********************************************************************
|
|
2
|
+
* yui_frontend_view.js
|
|
3
|
+
*
|
|
4
|
+
* Frontend view — the gobj tree of the own yuno in a
|
|
5
|
+
* floating window, peer of the developer window (yui_dev.js).
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2026, ArtGins.
|
|
8
|
+
* All Rights Reserved.
|
|
9
|
+
***********************************************************************/
|
|
10
|
+
import {
|
|
11
|
+
createElement2,
|
|
12
|
+
gobj_create_service,
|
|
13
|
+
gobj_create_pure_child,
|
|
14
|
+
gobj_find_service,
|
|
15
|
+
gobj_read_attr,
|
|
16
|
+
gobj_start_tree,
|
|
17
|
+
log_error,
|
|
18
|
+
} from "@yuneta/gobj-js";
|
|
19
|
+
|
|
20
|
+
/* Service name of the window. The host toggles the entry by looking
|
|
21
|
+
* it up, exactly as it does with "Developer-Window". */
|
|
22
|
+
const WIN_NAME = "Frontend-View-Window";
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
/******************************
|
|
26
|
+
* Public API
|
|
27
|
+
******************************/
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/************************************************************
|
|
31
|
+
* Open the gobj tree (C_YUI_GOBJ_TREE_JS) inside a non-modal
|
|
32
|
+
* C_YUI_WINDOW (title bar + maximize + close + resize), the
|
|
33
|
+
* same shape as the developer window.
|
|
34
|
+
*
|
|
35
|
+
* Shell-agnostic: the legacy C_YUI_MAIN shell has a
|
|
36
|
+
* '#top-layer' stacking element; the new C_YUI_SHELL does not.
|
|
37
|
+
* We pass that element when present, otherwise null — C_YUI_WINDOW
|
|
38
|
+
* falls back to document.body by contract.
|
|
39
|
+
*
|
|
40
|
+
* Returns the window gobj, or null.
|
|
41
|
+
************************************************************/
|
|
42
|
+
function setup_frontend_view(self)
|
|
43
|
+
{
|
|
44
|
+
if(gobj_find_service(WIN_NAME, false)) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* The tree is created AFTER the window, as a pure child of it, so
|
|
49
|
+
* every teardown path (the ✕, or the host destroying the window to
|
|
50
|
+
* toggle the entry off) takes the tree down with it. That is why
|
|
51
|
+
* the body is this placeholder: C_YUI_WINDOW builds its UI in
|
|
52
|
+
* mt_create, so it cannot be handed a gobj that does not exist yet. */
|
|
53
|
+
let $body = createElement2(
|
|
54
|
+
["div", {class: "YFRONT_BODY",
|
|
55
|
+
style: "height:100%; display:flex; flex-direction:column;"}, []]
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
let win = gobj_create_service(
|
|
59
|
+
WIN_NAME,
|
|
60
|
+
"C_YUI_WINDOW",
|
|
61
|
+
{
|
|
62
|
+
$parent: (typeof document !== "undefined" &&
|
|
63
|
+
document.getElementById("top-layer")) || null,
|
|
64
|
+
subscriber: null,
|
|
65
|
+
modal: false,
|
|
66
|
+
showMax: true,
|
|
67
|
+
showFooter: false,
|
|
68
|
+
resizable: true,
|
|
69
|
+
center: false,
|
|
70
|
+
auto_save_size_and_position: true,
|
|
71
|
+
width: 900,
|
|
72
|
+
height: 640,
|
|
73
|
+
logical_class: "FRONTEND_VIEW_WINDOW",
|
|
74
|
+
title: "frontend view",
|
|
75
|
+
icon: "yi-hexagon-nodes",
|
|
76
|
+
body: $body,
|
|
77
|
+
/* Opt into the dock/taskbar if the app provides one. `|| null`
|
|
78
|
+
* because gobj_find_service returns undefined when absent, and
|
|
79
|
+
* an undefined attr value logs "attr undefined: manager" (apps
|
|
80
|
+
* without a window manager, e.g. wattyzer). null = no dock. */
|
|
81
|
+
manager: gobj_find_service("__window_manager__", false) || null,
|
|
82
|
+
},
|
|
83
|
+
self
|
|
84
|
+
);
|
|
85
|
+
if(!win) {
|
|
86
|
+
log_error("yui_frontend_view: cannot create the frontend-view window");
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* The window is mounted by its mt_create, so $body is already live
|
|
91
|
+
* DOM here: the tree's own mt_start (build_graph + load_tree) and its
|
|
92
|
+
* ResizeObserver need the canvas attached to measure it. */
|
|
93
|
+
let tree = gobj_create_pure_child("frontend_view_tree", "C_YUI_GOBJ_TREE_JS", {}, win);
|
|
94
|
+
let $tree = gobj_read_attr(tree, "$container");
|
|
95
|
+
if(!$tree) {
|
|
96
|
+
log_error("yui_frontend_view: C_YUI_GOBJ_TREE_JS without $container");
|
|
97
|
+
return win;
|
|
98
|
+
}
|
|
99
|
+
$body.appendChild($tree);
|
|
100
|
+
|
|
101
|
+
gobj_start_tree(win);
|
|
102
|
+
|
|
103
|
+
return win;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export {setup_frontend_view};
|
package/src/yui_icons.css
CHANGED
|
@@ -82,6 +82,17 @@
|
|
|
82
82
|
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M256 64c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 160-160 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l160 0 0 160c0 17.7 14.3 32 32 32s32-14.3 32-32l0-160 160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-160 0 0-160z'/%3E%3C/svg%3E");
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
/* yi-plug / yi-plug-slash: hand-drawn masks (connect / disconnect). */
|
|
86
|
+
.yi-plug::before {
|
|
87
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Crect x='64' y='0' width='64' height='168' rx='32'/%3E%3Crect x='256' y='0' width='64' height='168' rx='32'/%3E%3Cpath d='M32 128h320c17.7 0 32 14.3 32 32v48c0 88.4-71.6 160-160 160v112c0 17.7-14.3 32-32 32s-32-14.3-32-32V368C71.6 368 0 296.4 0 208v-48c0-17.7 14.3-32 32-32z'/%3E%3C/svg%3E");
|
|
88
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Crect x='64' y='0' width='64' height='168' rx='32'/%3E%3Crect x='256' y='0' width='64' height='168' rx='32'/%3E%3Cpath d='M32 128h320c17.7 0 32 14.3 32 32v48c0 88.4-71.6 160-160 160v112c0 17.7-14.3 32-32 32s-32-14.3-32-32V368C71.6 368 0 296.4 0 208v-48c0-17.7 14.3-32 32-32z'/%3E%3C/svg%3E");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.yi-plug-slash::before {
|
|
92
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Crect x='64' y='0' width='64' height='168' rx='32'/%3E%3Crect x='256' y='0' width='64' height='168' rx='32'/%3E%3Cpath d='M32 128h320c17.7 0 32 14.3 32 32v48c0 88.4-71.6 160-160 160v112c0 17.7-14.3 32-32 32s-32-14.3-32-32V368C71.6 368 0 296.4 0 208v-48c0-17.7 14.3-32 32-32z'/%3E%3Cpath d='M10.5 81.9 53.5 46.1 373.5 430.1 330.5 465.9z'/%3E%3C/svg%3E");
|
|
93
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Crect x='64' y='0' width='64' height='168' rx='32'/%3E%3Crect x='256' y='0' width='64' height='168' rx='32'/%3E%3Cpath d='M32 128h320c17.7 0 32 14.3 32 32v48c0 88.4-71.6 160-160 160v112c0 17.7-14.3 32-32 32s-32-14.3-32-32V368C71.6 368 0 296.4 0 208v-48c0-17.7 14.3-32 32-32z'/%3E%3Cpath d='M10.5 81.9 53.5 46.1 373.5 430.1 330.5 465.9z'/%3E%3C/svg%3E");
|
|
94
|
+
}
|
|
95
|
+
|
|
85
96
|
.yi-question::before {
|
|
86
97
|
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M64 160c0-53 43-96 96-96s96 43 96 96c0 42.7-27.9 78.9-66.5 91.4-28.4 9.2-61.5 35.3-61.5 76.6l0 24c0 17.7 14.3 32 32 32s32-14.3 32-32l0-24c0-1.7 .6-4.1 3.5-7.3 3-3.3 7.9-6.5 13.7-8.4 64.3-20.7 110.8-81 110.8-152.3 0-88.4-71.6-160-160-160S0 71.6 0 160c0 17.7 14.3 32 32 32s32-14.3 32-32zm96 352c22.1 0 40-17.9 40-40s-17.9-40-40-40-40 17.9-40 40 17.9 40 40 40z'/%3E%3C/svg%3E");
|
|
87
98
|
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M64 160c0-53 43-96 96-96s96 43 96 96c0 42.7-27.9 78.9-66.5 91.4-28.4 9.2-61.5 35.3-61.5 76.6l0 24c0 17.7 14.3 32 32 32s32-14.3 32-32l0-24c0-1.7 .6-4.1 3.5-7.3 3-3.3 7.9-6.5 13.7-8.4 64.3-20.7 110.8-81 110.8-152.3 0-88.4-71.6-160-160-160S0 71.6 0 160c0 17.7 14.3 32 32 32s32-14.3 32-32zm96 352c22.1 0 40-17.9 40-40s-17.9-40-40-40-40 17.9-40 40 17.9 40 40 40z'/%3E%3C/svg%3E");
|
|
@@ -254,3 +265,54 @@
|
|
|
254
265
|
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zm32 224a32 32 0 1 1 -64 0 32 32 0 1 1 64 0z'/%3E%3C/svg%3E");
|
|
255
266
|
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zm0-384c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zm32 224a32 32 0 1 1 -64 0 32 32 0 1 1 64 0z'/%3E%3C/svg%3E");
|
|
256
267
|
}
|
|
268
|
+
|
|
269
|
+
.yi-pause::before {
|
|
270
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M48 64C21.5 64 0 85.5 0 112L0 400c0 26.5 21.5 48 48 48l32 0c26.5 0 48-21.5 48-48l0-288c0-26.5-21.5-48-48-48L48 64zm192 0c-26.5 0-48 21.5-48 48l0 288c0 26.5 21.5 48 48 48l32 0c26.5 0 48-21.5 48-48l0-288c0-26.5-21.5-48-48-48l-32 0z'/%3E%3C/svg%3E");
|
|
271
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M48 64C21.5 64 0 85.5 0 112L0 400c0 26.5 21.5 48 48 48l32 0c26.5 0 48-21.5 48-48l0-288c0-26.5-21.5-48-48-48L48 64zm192 0c-26.5 0-48 21.5-48 48l0 288c0 26.5 21.5 48 48 48l32 0c26.5 0 48-21.5 48-48l0-288c0-26.5-21.5-48-48-48l-32 0z'/%3E%3C/svg%3E");
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.yi-play::before {
|
|
275
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath d='M73 39c-14.8-9.1-33.4-9.4-48.5-.9S0 62.6 0 80L0 432c0 17.4 9.4 33.4 24.5 41.9s33.7 8.1 48.5-.9L361 297c14.3-8.7 23-24.2 23-41s-8.7-32.2-23-41L73 39z'/%3E%3C/svg%3E");
|
|
276
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 384 512'%3E%3Cpath d='M73 39c-14.8-9.1-33.4-9.4-48.5-.9S0 62.6 0 80L0 432c0 17.4 9.4 33.4 24.5 41.9s33.7 8.1 48.5-.9L361 297c14.3-8.7 23-24.2 23-41s-8.7-32.2-23-41L73 39z'/%3E%3C/svg%3E");
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.yi-download::before {
|
|
280
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M288 32c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 242.7-73.4-73.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l128 128c12.5 12.5 32.8 12.5 45.3 0l128-128c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L288 274.7 288 32zM64 352c-35.3 0-64 28.7-64 64l0 32c0 35.3 28.7 64 64 64l384 0c35.3 0 64-28.7 64-64l0-32c0-35.3-28.7-64-64-64l-101.5 0-45.3 45.3c-25 25-65.5 25-90.5 0L165.5 352 64 352zm368 56a24 24 0 1 1 0 48 24 24 0 1 1 0-48z'/%3E%3C/svg%3E");
|
|
281
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M288 32c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 242.7-73.4-73.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l128 128c12.5 12.5 32.8 12.5 45.3 0l128-128c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L288 274.7 288 32zM64 352c-35.3 0-64 28.7-64 64l0 32c0 35.3 28.7 64 64 64l384 0c35.3 0 64-28.7 64-64l0-32c0-35.3-28.7-64-64-64l-101.5 0-45.3 45.3c-25 25-65.5 25-90.5 0L165.5 352 64 352zm368 56a24 24 0 1 1 0 48 24 24 0 1 1 0-48z'/%3E%3C/svg%3E");
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.yi-link::before {
|
|
285
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 512'%3E%3Cpath d='M579.8 267.7c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-1.1 1.6C206.5 251.2 213 330 263 380c56.5 56.5 148 56.5 204.5 0L579.8 267.7zM60.2 244.3c-56.5 56.5-56.5 148 0 204.5c50 50 128.8 56.5 186.3 15.4l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C74 372 74 321 105.5 289.5L217.7 177.2c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.9l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6C433.5 260.8 427 182 377 132c-56.5-56.5-148-56.5-204.5 0L60.2 244.3z'/%3E%3C/svg%3E");
|
|
286
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 640 512'%3E%3Cpath d='M579.8 267.7c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-1.1 1.6C206.5 251.2 213 330 263 380c56.5 56.5 148 56.5 204.5 0L579.8 267.7zM60.2 244.3c-56.5 56.5-56.5 148 0 204.5c50 50 128.8 56.5 186.3 15.4l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C74 372 74 321 105.5 289.5L217.7 177.2c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.9l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6C433.5 260.8 427 182 377 132c-56.5-56.5-148-56.5-204.5 0L60.2 244.3z'/%3E%3C/svg%3E");
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/* --- Date navigator (C_YUI_PERIOD) --- */
|
|
290
|
+
.yi-chevron-left::before {
|
|
291
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 246.6 86.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z'/%3E%3C/svg%3E");
|
|
292
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 246.6 86.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z'/%3E%3C/svg%3E");
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.yi-chevron-right::before {
|
|
296
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M310.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L242.7 256 73.4 86.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z'/%3E%3C/svg%3E");
|
|
297
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M310.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-192 192c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L242.7 256 73.4 86.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l192 192z'/%3E%3C/svg%3E");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.yi-forward-step::before {
|
|
301
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M52.5 440.6c-9.5 7.9-22.8 9.7-34.1 4.4S0 428.4 0 416L0 96C0 83.6 7.2 72.3 18.4 67s24.5-3.6 34.1 4.4l192 160L256 241l0-145c0-17.7 14.3-32 32-32s32 14.3 32 32l0 320c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-145-11.5 9.6-192 160z'/%3E%3C/svg%3E");
|
|
302
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M52.5 440.6c-9.5 7.9-22.8 9.7-34.1 4.4S0 428.4 0 416L0 96C0 83.6 7.2 72.3 18.4 67s24.5-3.6 34.1 4.4l192 160L256 241l0-145c0-17.7 14.3-32 32-32s32 14.3 32 32l0 320c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-145-11.5 9.6-192 160z'/%3E%3C/svg%3E");
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.yi-calendar-days::before {
|
|
306
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M128 0c17.7 0 32 14.3 32 32l0 32 128 0 0-32c0-17.7 14.3-32 32-32s32 14.3 32 32l0 32 48 0c26.5 0 48 21.5 48 48l0 48L0 160l0-48C0 85.5 21.5 64 48 64l48 0 0-32c0-17.7 14.3-32 32-32zM0 192l448 0 0 272c0 26.5-21.5 48-48 48L48 512c-26.5 0-48-21.5-48-48L0 192zm64 80l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0c-8.8 0-16 7.2-16 16zm128 0l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0c-8.8 0-16 7.2-16 16zm144-16c-8.8 0-16 7.2-16 16l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0zM64 400l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0c-8.8 0-16 7.2-16 16zm144-16c-8.8 0-16 7.2-16 16l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0zm112 16l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0c-8.8 0-16 7.2-16 16z'/%3E%3C/svg%3E");
|
|
307
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M128 0c17.7 0 32 14.3 32 32l0 32 128 0 0-32c0-17.7 14.3-32 32-32s32 14.3 32 32l0 32 48 0c26.5 0 48 21.5 48 48l0 48L0 160l0-48C0 85.5 21.5 64 48 64l48 0 0-32c0-17.7 14.3-32 32-32zM0 192l448 0 0 272c0 26.5-21.5 48-48 48L48 512c-26.5 0-48-21.5-48-48L0 192zm64 80l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0c-8.8 0-16 7.2-16 16zm128 0l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0c-8.8 0-16 7.2-16 16zm144-16c-8.8 0-16 7.2-16 16l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0zM64 400l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0c-8.8 0-16 7.2-16 16zm144-16c-8.8 0-16 7.2-16 16l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0zm112 16l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0c-8.8 0-16 7.2-16 16z'/%3E%3C/svg%3E");
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.yi-ellipsis::before {
|
|
311
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M8 256a56 56 0 1 1 112 0A56 56 0 1 1 8 256zm160 0a56 56 0 1 1 112 0 56 56 0 1 1 -112 0zm216-56a56 56 0 1 1 0 112 56 56 0 1 1 0-112z'/%3E%3C/svg%3E");
|
|
312
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M8 256a56 56 0 1 1 112 0A56 56 0 1 1 8 256zm160 0a56 56 0 1 1 112 0 56 56 0 1 1 -112 0zm216-56a56 56 0 1 1 0 112 56 56 0 1 1 0-112z'/%3E%3C/svg%3E");
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.yi-backward-step::before {
|
|
316
|
+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M267.5 440.6c9.5 7.9 22.8 9.7 34.1 4.4s18.4-16.6 18.4-29l0-320c0-12.4-7.2-23.7-18.4-29s-24.5-3.6-34.1 4.4l-192 160L64 241l0-145c0-17.7-14.3-32-32-32S0 78.3 0 96L0 416c0 17.7 14.3 32 32 32s32-14.3 32-32l0-145 11.5 9.6 192 160z'/%3E%3C/svg%3E");
|
|
317
|
+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M267.5 440.6c9.5 7.9 22.8 9.7 34.1 4.4s18.4-16.6 18.4-29l0-320c0-12.4-7.2-23.7-18.4-29s-24.5-3.6-34.1 4.4l-192 160L64 241l0-145c0-17.7-14.3-32-32-32S0 78.3 0 96L0 416c0 17.7 14.3 32 32 32s32-14.3 32-32l0-145 11.5 9.6 192 160z'/%3E%3C/svg%3E");
|
|
318
|
+
}
|
package/src/yui_inputs.css
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* Styling for the editable-input helpers in yui_inputs.js.
|
|
5
5
|
*
|
|
6
6
|
* The clear button itself is Bulma's `.delete`; here we only
|
|
7
|
-
* position it over the input's right padding and
|
|
8
|
-
* while the field has content
|
|
7
|
+
* position it over the input's right padding and reveal it only
|
|
8
|
+
* while the field has content AND is focused for editing — so a
|
|
9
|
+
* form full of pre-filled fields shows the ✕ on just the field the
|
|
10
|
+
* user is on, not on every populated one at once.
|
|
9
11
|
*
|
|
10
12
|
* Copyright (c) 2026, ArtGins.
|
|
11
13
|
* All Rights Reserved.
|
|
@@ -27,6 +29,9 @@
|
|
|
27
29
|
display: none;
|
|
28
30
|
z-index: 4;
|
|
29
31
|
}
|
|
30
|
-
|
|
32
|
+
/* `.is-visible` (JS-toggled) means "has content"; the ✕ only actually
|
|
33
|
+
* appears while the control also holds focus, so an edit form doesn't
|
|
34
|
+
* light up an ✕ on every filled field — only on the one being edited. */
|
|
35
|
+
.control.has-clear:focus-within .yui-input-clear.is-visible {
|
|
31
36
|
display: inline-block;
|
|
32
37
|
}
|
package/src/yui_inputs.js
CHANGED
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
* Reusable editable-input helpers.
|
|
5
5
|
*
|
|
6
6
|
* NORM: every editable text/search input gets a clear (✕) button
|
|
7
|
-
* that appears only while the field has content
|
|
7
|
+
* that appears only while the field has content AND is focused for
|
|
8
|
+
* editing (`:focus-within`, see yui_inputs.css) — so a form full of
|
|
9
|
+
* pre-filled fields shows the ✕ on the field the user is on, not on
|
|
10
|
+
* every populated field at once. `attach_clear()`
|
|
8
11
|
* wires it onto any Bulma `.control` that wraps an `<input>`:
|
|
9
12
|
*
|
|
10
13
|
* let $input = createElement2(["input", {class:"input"}, ...]);
|
|
@@ -28,6 +31,16 @@ import {createElement2} from "@yuneta/gobj-js";
|
|
|
28
31
|
import i18next from "i18next";
|
|
29
32
|
|
|
30
33
|
|
|
34
|
+
/***************************************************************
|
|
35
|
+
* The ✕ shows only when there is something to clear AND the field
|
|
36
|
+
* can actually be edited — a readonly/disabled input (e.g. the pkey
|
|
37
|
+
* in "update" mode) must not offer it.
|
|
38
|
+
***************************************************************/
|
|
39
|
+
function clear_visible($input)
|
|
40
|
+
{
|
|
41
|
+
return !!$input.value && !$input.readOnly && !$input.disabled;
|
|
42
|
+
}
|
|
43
|
+
|
|
31
44
|
/***************************************************************
|
|
32
45
|
* Add a clear (✕) button to a Bulma control wrapping an input.
|
|
33
46
|
* Returns the button element (already appended to $control).
|
|
@@ -39,21 +52,29 @@ function attach_clear($control, $input, on_clear)
|
|
|
39
52
|
}
|
|
40
53
|
$control.classList.add("has-clear");
|
|
41
54
|
|
|
55
|
+
/* The key travels with the button: a `title` set from t() at build time
|
|
56
|
+
* is invisible to refresh_language(), so the tooltip stayed in the old
|
|
57
|
+
* language for the life of the input. */
|
|
42
58
|
let $btn = createElement2(["button", {
|
|
43
|
-
type:
|
|
44
|
-
class:
|
|
45
|
-
tabindex:
|
|
46
|
-
title:
|
|
47
|
-
"aria-label":
|
|
59
|
+
type: "button",
|
|
60
|
+
class: "delete is-medium yui-input-clear",
|
|
61
|
+
tabindex: "-1",
|
|
62
|
+
title: i18next.t("clear"),
|
|
63
|
+
"aria-label": i18next.t("clear"),
|
|
64
|
+
"data-i18n-title": "clear",
|
|
65
|
+
"data-i18n-aria-label": "clear"
|
|
48
66
|
}]);
|
|
49
67
|
|
|
50
68
|
function sync()
|
|
51
69
|
{
|
|
52
|
-
$btn.classList.toggle("is-visible",
|
|
70
|
+
$btn.classList.toggle("is-visible", clear_visible($input));
|
|
53
71
|
}
|
|
54
72
|
|
|
55
73
|
$input.addEventListener("input", sync);
|
|
56
74
|
$btn.addEventListener("click", () => {
|
|
75
|
+
if($input.readOnly || $input.disabled) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
57
78
|
$input.value = "";
|
|
58
79
|
$input.dispatchEvent(new Event("input", {bubbles: true}));
|
|
59
80
|
if(typeof on_clear === "function") {
|
|
@@ -68,4 +89,26 @@ function attach_clear($control, $input, on_clear)
|
|
|
68
89
|
return $btn;
|
|
69
90
|
}
|
|
70
91
|
|
|
71
|
-
|
|
92
|
+
/***************************************************************
|
|
93
|
+
* Re-evaluate a clear (✕) after a PROGRAMMATIC change to its input
|
|
94
|
+
* — a value loaded into the form, or `readonly` toggled by the form
|
|
95
|
+
* mode — neither of which fires an `input` event. No-op on inputs
|
|
96
|
+
* that never got a clear.
|
|
97
|
+
***************************************************************/
|
|
98
|
+
function refresh_clear($input)
|
|
99
|
+
{
|
|
100
|
+
if(!$input) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
let $control = $input.closest(".control.has-clear");
|
|
104
|
+
if(!$control) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
let $btn = $control.querySelector(".yui-input-clear");
|
|
108
|
+
if(!$btn) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
$btn.classList.toggle("is-visible", clear_visible($input));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export {attach_clear, refresh_clear};
|