@yuneta/gobj-ui 5.5.0 → 5.7.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 +40 -0
- package/dist/gobj-ui.cjs.js +319 -149
- package/dist/gobj-ui.es.js +319 -150
- package/index.js +1 -0
- package/package.json +2 -2
- package/src/c_yui_form.js +100 -75
- package/src/c_yui_nav.js +6 -1
- package/src/c_yui_shell.css +47 -0
- package/src/c_yui_shell.js +106 -2
- package/src/form_toolbar_plan.js +59 -0
- package/src/form_toolbar_plan.test.js +54 -0
package/README.md
CHANGED
|
@@ -464,6 +464,46 @@ host can use it to toggle. The tree is a **pure child of the window**, so every
|
|
|
464
464
|
teardown path (the ✕, or the host destroying the window to toggle the entry
|
|
465
465
|
off) takes it down too.
|
|
466
466
|
|
|
467
|
+
### Toolbar badge — a count pinned to an item's icon
|
|
468
|
+
|
|
469
|
+
```js
|
|
470
|
+
/* app_config.json — seeds the FIRST paint only */
|
|
471
|
+
{ "id": "alarms", "icon": "yi-triangle-exclamation", "align": "end",
|
|
472
|
+
"aria_label": "alarms", "badge": 0,
|
|
473
|
+
"action": {"type": "navigate", "route": "/alarms"} }
|
|
474
|
+
|
|
475
|
+
/* the interface that matters: a count is a RUNTIME fact */
|
|
476
|
+
yui_shell_set_toolbar_item_badge(shell, "alarms", 3);
|
|
477
|
+
yui_shell_set_toolbar_item_badge(shell, "alarms", 0); // clears it
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
An icon-only toolbar button is a link; the badge is what makes it a
|
|
481
|
+
**signal**. Without a number, an alarm bell cannot say whether anything needs
|
|
482
|
+
you — which is the reason to look at it at all.
|
|
483
|
+
|
|
484
|
+
Rules baked in, all for the same reason (a badge that lies costs more than no
|
|
485
|
+
badge):
|
|
486
|
+
|
|
487
|
+
- **`0`, `""`, `null` and `false` all clear it.** A badge reading "0" is worse
|
|
488
|
+
than none: it draws the eye to say nothing.
|
|
489
|
+
- **Over 99 renders `99+`.** The toolbar is a fixed-width row and a four-digit
|
|
490
|
+
pill pushes its neighbours off a phone screen.
|
|
491
|
+
- **A string passes through** for the states that are not counts (`"!"`, `"…"`).
|
|
492
|
+
- **Unknown item id is a silent no-op**, so an app whose toolbar has no such
|
|
493
|
+
item does not log an error on every tick of whatever feeds the number.
|
|
494
|
+
- Writing the **same** value again touches no DOM: the badge is a
|
|
495
|
+
`role="status"` live region, and rewriting it would have a screen reader
|
|
496
|
+
announce the same number on every tick.
|
|
497
|
+
|
|
498
|
+
`role="status"` and not `aria-hidden`, deliberately: the button carries an
|
|
499
|
+
explicit `aria-label`, and an explicit label **replaces** an element's content
|
|
500
|
+
for a screen reader — a badge inside it would otherwise be silent. As its own
|
|
501
|
+
live region it is both read and announced when it changes.
|
|
502
|
+
|
|
503
|
+
> `C_YUI_NAV` items do **not** have this. Its item contract listed `badge` for a
|
|
504
|
+
> long time and nothing ever rendered it; the claim is gone. Implement it there
|
|
505
|
+
> the day a menu entry needs one.
|
|
506
|
+
|
|
467
507
|
### Modals — `yui_shell_show_modal` and the `before_close` veto
|
|
468
508
|
|
|
469
509
|
`yui_shell_show_modal(shell, $box, opts)` is the standard popup: pass
|
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -890,7 +890,7 @@ function mt_start$15(gobj) {
|
|
|
890
890
|
if (typeof shell_cfg.remember_section_position === "boolean") (0, _yuneta_gobj_js.gobj_write_attr)(gobj, "remember_section_position", shell_cfg.remember_section_position);
|
|
891
891
|
build_item_index(gobj, config);
|
|
892
892
|
instantiate_menus(gobj, config);
|
|
893
|
-
build_toolbar(gobj, config);
|
|
893
|
+
build_toolbar$1(gobj, config);
|
|
894
894
|
preinstantiate_eager_views(gobj);
|
|
895
895
|
if ((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "use_hash")) {
|
|
896
896
|
priv.hash_handler = () => {
|
|
@@ -1616,7 +1616,7 @@ function safe_id(s) {
|
|
|
1616
1616
|
* Per-item `show_on` is honoured: each rendered item is wrapped with
|
|
1617
1617
|
* the same Bulma-helper logic as zones.
|
|
1618
1618
|
************************************************************/
|
|
1619
|
-
function build_toolbar(gobj, config) {
|
|
1619
|
+
function build_toolbar$1(gobj, config) {
|
|
1620
1620
|
let tb = config && config.toolbar;
|
|
1621
1621
|
if (!tb || !(0, _yuneta_gobj_js.is_array)(tb.items)) return;
|
|
1622
1622
|
let priv = gobj.priv;
|
|
@@ -1656,17 +1656,59 @@ function build_toolbar(gobj, config) {
|
|
|
1656
1656
|
$zone.appendChild($bar);
|
|
1657
1657
|
}
|
|
1658
1658
|
/************************************************************
|
|
1659
|
+
* The badge node of a toolbar item — the little count pinned to
|
|
1660
|
+
* the corner of its icon (unread notifications, active alarms).
|
|
1661
|
+
*
|
|
1662
|
+
* ALWAYS rendered, hidden when empty, so the runtime setter has a
|
|
1663
|
+
* node to write into and does not have to rebuild the button.
|
|
1664
|
+
*
|
|
1665
|
+
* EMPTY IS 0, "" AND null ALIKE: a badge reading "0" is worse than
|
|
1666
|
+
* no badge — it draws the eye to say nothing. A count is only
|
|
1667
|
+
* worth a pixel when there IS something.
|
|
1668
|
+
*
|
|
1669
|
+
* Capped at 99+: the toolbar is a fixed-width row, and a four
|
|
1670
|
+
* digit pill pushes the items next to it off a phone screen.
|
|
1671
|
+
*
|
|
1672
|
+
* role="status" and NOT aria-hidden, deliberately. The button
|
|
1673
|
+
* carries an explicit aria-label, and an explicit label REPLACES
|
|
1674
|
+
* the element's content for a screen reader — so a badge inside
|
|
1675
|
+
* it would be silent. As its own live region it is both read and
|
|
1676
|
+
* announced when the count changes, which is the whole point of a
|
|
1677
|
+
* badge that means "something needs you".
|
|
1678
|
+
************************************************************/
|
|
1679
|
+
function badge_text(value) {
|
|
1680
|
+
if (value === null || value === void 0 || value === false) return "";
|
|
1681
|
+
if (typeof value === "number") {
|
|
1682
|
+
if (!isFinite(value) || value <= 0) return "";
|
|
1683
|
+
return value > 99 ? "99+" : String(Math.floor(value));
|
|
1684
|
+
}
|
|
1685
|
+
return String(value).trim();
|
|
1686
|
+
}
|
|
1687
|
+
function badge_node(value) {
|
|
1688
|
+
let text = badge_text(value);
|
|
1689
|
+
let attrs = {
|
|
1690
|
+
class: "yui-toolbar-badge",
|
|
1691
|
+
role: "status"
|
|
1692
|
+
};
|
|
1693
|
+
if (!text) attrs.hidden = "hidden";
|
|
1694
|
+
return [
|
|
1695
|
+
"span",
|
|
1696
|
+
attrs,
|
|
1697
|
+
text
|
|
1698
|
+
];
|
|
1699
|
+
}
|
|
1700
|
+
/************************************************************
|
|
1659
1701
|
* Renderer for the default ("action") item kind.
|
|
1660
1702
|
************************************************************/
|
|
1661
1703
|
function build_toolbar_action_item(gobj, it) {
|
|
1662
1704
|
let children = [];
|
|
1663
1705
|
if (!(0, _yuneta_gobj_js.empty_string)(it.icon)) children.push([
|
|
1664
1706
|
"span",
|
|
1665
|
-
{ class: "icon" },
|
|
1666
|
-
["i", {
|
|
1707
|
+
{ class: "icon yui-toolbar-icon" },
|
|
1708
|
+
[["i", {
|
|
1667
1709
|
class: it.icon,
|
|
1668
1710
|
"aria-hidden": "true"
|
|
1669
|
-
}]
|
|
1711
|
+
}], badge_node(it.badge)]
|
|
1670
1712
|
]);
|
|
1671
1713
|
if (!(0, _yuneta_gobj_js.empty_string)(it.name)) children.push([
|
|
1672
1714
|
"span",
|
|
@@ -2677,6 +2719,41 @@ function yui_shell_set_toolbar_item_icon(shell_gobj, item_id, icon_class) {
|
|
|
2677
2719
|
if ($i) $i.className = icon_class;
|
|
2678
2720
|
}
|
|
2679
2721
|
/************************************************************
|
|
2722
|
+
* Set (or clear) a toolbar item's badge — the count pinned to
|
|
2723
|
+
* its icon.
|
|
2724
|
+
*
|
|
2725
|
+
* yui_shell_set_toolbar_item_badge(shell, "alarms", 3);
|
|
2726
|
+
* yui_shell_set_toolbar_item_badge(shell, "alarms", 0); // hidden
|
|
2727
|
+
*
|
|
2728
|
+
* This is the API that matters: a count is a RUNTIME fact. The
|
|
2729
|
+
* `badge` field of a toolbar item only seeds the first paint, and
|
|
2730
|
+
* an app whose number never changes did not need a badge.
|
|
2731
|
+
*
|
|
2732
|
+
* 0 / "" / null / false all clear it, and a number over 99 renders
|
|
2733
|
+
* "99+" — see badge_node(). Accepts a string for the states that
|
|
2734
|
+
* are not counts ("!", "…").
|
|
2735
|
+
*
|
|
2736
|
+
* Silent no-op on an unknown item id: a toolbar that does not
|
|
2737
|
+
* declare the item (an app without alarms) must not be an error
|
|
2738
|
+
* at every tick of whatever feeds the number.
|
|
2739
|
+
************************************************************/
|
|
2740
|
+
function yui_shell_set_toolbar_item_badge(shell_gobj, item_id, value) {
|
|
2741
|
+
if (!shell_gobj || !(0, _yuneta_gobj_js.is_gobj)(shell_gobj) || (0, _yuneta_gobj_js.empty_string)(item_id)) return;
|
|
2742
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(shell_gobj, "$container");
|
|
2743
|
+
if (!$container) return;
|
|
2744
|
+
let $badge = $container.querySelector(`[data-toolbar-item-id="${item_id}"] .yui-toolbar-badge`);
|
|
2745
|
+
if (!$badge) return;
|
|
2746
|
+
let text = badge_text(value);
|
|
2747
|
+
if (!text) {
|
|
2748
|
+
$badge.textContent = "";
|
|
2749
|
+
$badge.setAttribute("hidden", "hidden");
|
|
2750
|
+
return;
|
|
2751
|
+
}
|
|
2752
|
+
if ($badge.textContent === text && !$badge.hasAttribute("hidden")) return;
|
|
2753
|
+
$badge.textContent = text;
|
|
2754
|
+
$badge.removeAttribute("hidden");
|
|
2755
|
+
}
|
|
2756
|
+
/************************************************************
|
|
2680
2757
|
* Programmatic close of any open toolbar dropdown. Useful for
|
|
2681
2758
|
* external triggers (e.g. EV_LOGOUT firing from elsewhere) that
|
|
2682
2759
|
* want to dismiss whatever menu is on screen.
|
|
@@ -5683,6 +5760,59 @@ function refresh_clear($input) {
|
|
|
5683
5760
|
$btn.classList.toggle("is-visible", clear_visible($input));
|
|
5684
5761
|
}
|
|
5685
5762
|
//#endregion
|
|
5763
|
+
//#region src/form_toolbar_plan.js
|
|
5764
|
+
/***********************************************************************
|
|
5765
|
+
* form_toolbar_plan.js
|
|
5766
|
+
*
|
|
5767
|
+
* Which buttons the C_YUI_FORM toolbar shows, and where.
|
|
5768
|
+
*
|
|
5769
|
+
* Pure, so it can be tested without a DOM: the gclass turns the
|
|
5770
|
+
* plan into elements, this decides the plan.
|
|
5771
|
+
*
|
|
5772
|
+
* Copyright (c) 2026, ArtGins.
|
|
5773
|
+
* All Rights Reserved.
|
|
5774
|
+
***********************************************************************/
|
|
5775
|
+
var LEFT_BUTTONS = [
|
|
5776
|
+
"save",
|
|
5777
|
+
"undo",
|
|
5778
|
+
"clear"
|
|
5779
|
+
];
|
|
5780
|
+
var RIGHT_BUTTONS = ["copy", "paste"];
|
|
5781
|
+
var DEFAULT_TOOLBAR = [
|
|
5782
|
+
"save",
|
|
5783
|
+
"undo",
|
|
5784
|
+
"clear",
|
|
5785
|
+
"copy",
|
|
5786
|
+
"paste"
|
|
5787
|
+
];
|
|
5788
|
+
/***************************************************************
|
|
5789
|
+
* plan_toolbar(wanted) -> {left, right, unknown}
|
|
5790
|
+
*
|
|
5791
|
+
* wanted an array of button names, in the order asked for.
|
|
5792
|
+
* Anything that is not an array means "the default
|
|
5793
|
+
* five", so a caller that sets nothing keeps exactly
|
|
5794
|
+
* the toolbar this gclass always had.
|
|
5795
|
+
* [] means no toolbar at all.
|
|
5796
|
+
*
|
|
5797
|
+
* unknown names that match no button. They are reported and
|
|
5798
|
+
* NOT silently dropped: a typo in the list would
|
|
5799
|
+
* otherwise remove the save button with no trace.
|
|
5800
|
+
***************************************************************/
|
|
5801
|
+
function plan_toolbar(wanted) {
|
|
5802
|
+
if (!Array.isArray(wanted)) wanted = DEFAULT_TOOLBAR;
|
|
5803
|
+
let left = [];
|
|
5804
|
+
let right = [];
|
|
5805
|
+
let unknown = [];
|
|
5806
|
+
for (let name of wanted) if (LEFT_BUTTONS.indexOf(name) >= 0) left.push(name);
|
|
5807
|
+
else if (RIGHT_BUTTONS.indexOf(name) >= 0) right.push(name);
|
|
5808
|
+
else unknown.push(name);
|
|
5809
|
+
return {
|
|
5810
|
+
left,
|
|
5811
|
+
right,
|
|
5812
|
+
unknown
|
|
5813
|
+
};
|
|
5814
|
+
}
|
|
5815
|
+
//#endregion
|
|
5686
5816
|
//#region src/yui_theme.js
|
|
5687
5817
|
/***********************************************************************
|
|
5688
5818
|
* yui_theme.js
|
|
@@ -5814,6 +5944,13 @@ var attrs_table$13 = [
|
|
|
5814
5944
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "with_checkbox", 0, false, "Show a first column with checkbox to select rows"),
|
|
5815
5945
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "with_rownum", 0, false, "Print first column with row number"),
|
|
5816
5946
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "with_delete_row_btn", 0, false, "Print last column with delete row button"),
|
|
5947
|
+
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_JSON, "toolbar", 0, [
|
|
5948
|
+
"save",
|
|
5949
|
+
"undo",
|
|
5950
|
+
"clear",
|
|
5951
|
+
"copy",
|
|
5952
|
+
"paste"
|
|
5953
|
+
], "Toolbar buttons to show, in order: save, undo, clear, copy, paste. [] hides the toolbar"),
|
|
5817
5954
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_JSON, "tabulator_settings", 0, {
|
|
5818
5955
|
layout: "fitDataFill",
|
|
5819
5956
|
validationMode: "highlight",
|
|
@@ -5924,6 +6061,175 @@ async function readClipboard$1(gobj) {
|
|
|
5924
6061
|
}
|
|
5925
6062
|
}
|
|
5926
6063
|
/************************************************************
|
|
6064
|
+
* Bottom toolbar, from the `toolbar` attr.
|
|
6065
|
+
*
|
|
6066
|
+
* The five buttons it can show, and their order, are the
|
|
6067
|
+
* caller's: a dialog with a single action asks for ["save"],
|
|
6068
|
+
* and [] leaves no toolbar at all. Default is the five it
|
|
6069
|
+
* always had, so nothing moves for a caller that says nothing.
|
|
6070
|
+
************************************************************/
|
|
6071
|
+
function toolbar_button(gobj, name) {
|
|
6072
|
+
switch (name) {
|
|
6073
|
+
case "save": return [
|
|
6074
|
+
"button",
|
|
6075
|
+
{
|
|
6076
|
+
class: "button p-1 button-save",
|
|
6077
|
+
title: "save",
|
|
6078
|
+
"aria-label": "save",
|
|
6079
|
+
disabled: true
|
|
6080
|
+
},
|
|
6081
|
+
[[
|
|
6082
|
+
"span",
|
|
6083
|
+
{ class: "icon m-0" },
|
|
6084
|
+
"<i class=\"yi-floppy-disk\"></i>"
|
|
6085
|
+
], [
|
|
6086
|
+
"span",
|
|
6087
|
+
{
|
|
6088
|
+
class: "is-hidden-mobile pl-1 pr-1",
|
|
6089
|
+
i18n: "save"
|
|
6090
|
+
},
|
|
6091
|
+
"save"
|
|
6092
|
+
]],
|
|
6093
|
+
{ click: function(evt) {
|
|
6094
|
+
evt.stopPropagation();
|
|
6095
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_SAVE_RECORD", {}, gobj);
|
|
6096
|
+
} }
|
|
6097
|
+
];
|
|
6098
|
+
case "undo": return [
|
|
6099
|
+
"button",
|
|
6100
|
+
{
|
|
6101
|
+
class: "button p-1 button-undo",
|
|
6102
|
+
title: "undo",
|
|
6103
|
+
"aria-label": "undo",
|
|
6104
|
+
disabled: true
|
|
6105
|
+
},
|
|
6106
|
+
[[
|
|
6107
|
+
"span",
|
|
6108
|
+
{ class: "icon m-0" },
|
|
6109
|
+
"<i class=\"yi-arrow-rotate-left\"></i>"
|
|
6110
|
+
], [
|
|
6111
|
+
"span",
|
|
6112
|
+
{
|
|
6113
|
+
class: "is-hidden-mobile pl-1 pr-1",
|
|
6114
|
+
i18n: "undo"
|
|
6115
|
+
},
|
|
6116
|
+
"undo"
|
|
6117
|
+
]],
|
|
6118
|
+
{ click: function(evt) {
|
|
6119
|
+
evt.stopPropagation();
|
|
6120
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_UNDO_RECORD", {}, gobj);
|
|
6121
|
+
} }
|
|
6122
|
+
];
|
|
6123
|
+
case "clear": return [
|
|
6124
|
+
"button",
|
|
6125
|
+
{
|
|
6126
|
+
class: "button p-1",
|
|
6127
|
+
title: "clear",
|
|
6128
|
+
"aria-label": "clear"
|
|
6129
|
+
},
|
|
6130
|
+
[[
|
|
6131
|
+
"span",
|
|
6132
|
+
{ class: "icon m-0" },
|
|
6133
|
+
"<i class=\"yi-broom-wide\"></i>"
|
|
6134
|
+
], [
|
|
6135
|
+
"span",
|
|
6136
|
+
{
|
|
6137
|
+
class: "is-hidden-mobile pl-1 pr-1",
|
|
6138
|
+
i18n: "clear"
|
|
6139
|
+
},
|
|
6140
|
+
"clear"
|
|
6141
|
+
]],
|
|
6142
|
+
{ click: function(evt) {
|
|
6143
|
+
evt.stopPropagation();
|
|
6144
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_CLEAR_RECORD", {}, gobj);
|
|
6145
|
+
} }
|
|
6146
|
+
];
|
|
6147
|
+
case "copy": return [
|
|
6148
|
+
"button",
|
|
6149
|
+
{
|
|
6150
|
+
class: "button p-1",
|
|
6151
|
+
title: "copy",
|
|
6152
|
+
"aria-label": "copy"
|
|
6153
|
+
},
|
|
6154
|
+
[[
|
|
6155
|
+
"span",
|
|
6156
|
+
{ class: "icon m-0" },
|
|
6157
|
+
"<i class=\"yi-copy\"></i>"
|
|
6158
|
+
], [
|
|
6159
|
+
"span",
|
|
6160
|
+
{
|
|
6161
|
+
class: "is-hidden-mobile pl-1 pr-1",
|
|
6162
|
+
i18n: "copy"
|
|
6163
|
+
},
|
|
6164
|
+
"copy"
|
|
6165
|
+
]],
|
|
6166
|
+
{ click: function(evt) {
|
|
6167
|
+
evt.stopPropagation();
|
|
6168
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_COPY_RECORD", {}, gobj);
|
|
6169
|
+
} }
|
|
6170
|
+
];
|
|
6171
|
+
case "paste": return [
|
|
6172
|
+
"button",
|
|
6173
|
+
{
|
|
6174
|
+
class: "button p-1",
|
|
6175
|
+
title: "paste",
|
|
6176
|
+
"aria-label": "paste"
|
|
6177
|
+
},
|
|
6178
|
+
[[
|
|
6179
|
+
"span",
|
|
6180
|
+
{ class: "icon m-0" },
|
|
6181
|
+
"<i class=\"yi-paste\"></i>"
|
|
6182
|
+
], [
|
|
6183
|
+
"span",
|
|
6184
|
+
{
|
|
6185
|
+
class: "is-hidden-mobile pl-1 pr-1",
|
|
6186
|
+
i18n: "paste"
|
|
6187
|
+
},
|
|
6188
|
+
"paste"
|
|
6189
|
+
]],
|
|
6190
|
+
{ click: async function(evt) {
|
|
6191
|
+
evt.stopPropagation();
|
|
6192
|
+
await readClipboard$1(gobj);
|
|
6193
|
+
} }
|
|
6194
|
+
];
|
|
6195
|
+
default: return null;
|
|
6196
|
+
}
|
|
6197
|
+
}
|
|
6198
|
+
function build_toolbar(gobj) {
|
|
6199
|
+
const plan = plan_toolbar((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "toolbar"));
|
|
6200
|
+
for (let name of plan.unknown) (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: unknown toolbar button '${name}'`);
|
|
6201
|
+
if (!plan.left.length && !plan.right.length) return [
|
|
6202
|
+
"span",
|
|
6203
|
+
{
|
|
6204
|
+
class: "yui-toolbar-form-empty",
|
|
6205
|
+
style: "display:none;"
|
|
6206
|
+
},
|
|
6207
|
+
""
|
|
6208
|
+
];
|
|
6209
|
+
return [
|
|
6210
|
+
"div",
|
|
6211
|
+
{
|
|
6212
|
+
class: "yui-toolbar-form is-flex-shrink-0 is-flex is-flex-direction-row is-justify-content-space-between is-align-items-center",
|
|
6213
|
+
style: "width:100%; flex-wrap:wrap; row-gap:6px;"
|
|
6214
|
+
},
|
|
6215
|
+
[[
|
|
6216
|
+
"div",
|
|
6217
|
+
{
|
|
6218
|
+
class: "p-1 is-flex is-flex-direction-row is-align-items-center",
|
|
6219
|
+
style: "column-gap:6px;"
|
|
6220
|
+
},
|
|
6221
|
+
plan.left.map((n) => toolbar_button(gobj, n))
|
|
6222
|
+
], [
|
|
6223
|
+
"div",
|
|
6224
|
+
{
|
|
6225
|
+
class: "p-1 is-flex is-flex-direction-row is-align-items-center",
|
|
6226
|
+
style: "column-gap:6px;"
|
|
6227
|
+
},
|
|
6228
|
+
plan.right.map((n) => toolbar_button(gobj, n))
|
|
6229
|
+
]]
|
|
6230
|
+
];
|
|
6231
|
+
}
|
|
6232
|
+
/************************************************************
|
|
5927
6233
|
* Build UI
|
|
5928
6234
|
************************************************************/
|
|
5929
6235
|
function build_ui$11(gobj) {
|
|
@@ -5940,149 +6246,7 @@ function build_ui$11(gobj) {
|
|
|
5940
6246
|
style: "overflow-y:auto; min-height:0;"
|
|
5941
6247
|
},
|
|
5942
6248
|
build_form(gobj)
|
|
5943
|
-
],
|
|
5944
|
-
"div",
|
|
5945
|
-
{
|
|
5946
|
-
class: "yui-toolbar-form is-flex-shrink-0 is-flex is-flex-direction-row is-justify-content-space-between is-align-items-center",
|
|
5947
|
-
style: "width:100%; flex-wrap:wrap; row-gap:6px;"
|
|
5948
|
-
},
|
|
5949
|
-
[[
|
|
5950
|
-
"div",
|
|
5951
|
-
{
|
|
5952
|
-
class: "p-1 is-flex is-flex-direction-row is-align-items-center",
|
|
5953
|
-
style: "column-gap:6px;"
|
|
5954
|
-
},
|
|
5955
|
-
[
|
|
5956
|
-
[
|
|
5957
|
-
"button",
|
|
5958
|
-
{
|
|
5959
|
-
class: "button p-1 button-save",
|
|
5960
|
-
title: "save",
|
|
5961
|
-
"aria-label": "save",
|
|
5962
|
-
disabled: true
|
|
5963
|
-
},
|
|
5964
|
-
[[
|
|
5965
|
-
"span",
|
|
5966
|
-
{ class: "icon m-0" },
|
|
5967
|
-
"<i class=\"yi-floppy-disk\"></i>"
|
|
5968
|
-
], [
|
|
5969
|
-
"span",
|
|
5970
|
-
{
|
|
5971
|
-
class: "is-hidden-mobile pl-1 pr-1",
|
|
5972
|
-
i18n: "save"
|
|
5973
|
-
},
|
|
5974
|
-
"save"
|
|
5975
|
-
]],
|
|
5976
|
-
{ click: function(evt) {
|
|
5977
|
-
evt.stopPropagation();
|
|
5978
|
-
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_SAVE_RECORD", {}, gobj);
|
|
5979
|
-
} }
|
|
5980
|
-
],
|
|
5981
|
-
[
|
|
5982
|
-
"button",
|
|
5983
|
-
{
|
|
5984
|
-
class: "button p-1 button-undo",
|
|
5985
|
-
title: "undo",
|
|
5986
|
-
"aria-label": "undo",
|
|
5987
|
-
disabled: true
|
|
5988
|
-
},
|
|
5989
|
-
[[
|
|
5990
|
-
"span",
|
|
5991
|
-
{ class: "icon m-0" },
|
|
5992
|
-
"<i class=\"yi-arrow-rotate-left\"></i>"
|
|
5993
|
-
], [
|
|
5994
|
-
"span",
|
|
5995
|
-
{
|
|
5996
|
-
class: "is-hidden-mobile pl-1 pr-1",
|
|
5997
|
-
i18n: "undo"
|
|
5998
|
-
},
|
|
5999
|
-
"undo"
|
|
6000
|
-
]],
|
|
6001
|
-
{ click: function(evt) {
|
|
6002
|
-
evt.stopPropagation();
|
|
6003
|
-
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_UNDO_RECORD", {}, gobj);
|
|
6004
|
-
} }
|
|
6005
|
-
],
|
|
6006
|
-
[
|
|
6007
|
-
"button",
|
|
6008
|
-
{
|
|
6009
|
-
class: "button p-1",
|
|
6010
|
-
title: "clear",
|
|
6011
|
-
"aria-label": "clear"
|
|
6012
|
-
},
|
|
6013
|
-
[[
|
|
6014
|
-
"span",
|
|
6015
|
-
{ class: "icon m-0" },
|
|
6016
|
-
"<i class=\"yi-broom-wide\"></i>"
|
|
6017
|
-
], [
|
|
6018
|
-
"span",
|
|
6019
|
-
{
|
|
6020
|
-
class: "is-hidden-mobile pl-1 pr-1",
|
|
6021
|
-
i18n: "clear"
|
|
6022
|
-
},
|
|
6023
|
-
"clear"
|
|
6024
|
-
]],
|
|
6025
|
-
{ click: function(evt) {
|
|
6026
|
-
evt.stopPropagation();
|
|
6027
|
-
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_CLEAR_RECORD", {}, gobj);
|
|
6028
|
-
} }
|
|
6029
|
-
]
|
|
6030
|
-
]
|
|
6031
|
-
], [
|
|
6032
|
-
"div",
|
|
6033
|
-
{
|
|
6034
|
-
class: "p-1 is-flex is-flex-direction-row is-align-items-center",
|
|
6035
|
-
style: "column-gap:6px;"
|
|
6036
|
-
},
|
|
6037
|
-
[[
|
|
6038
|
-
"button",
|
|
6039
|
-
{
|
|
6040
|
-
class: "button p-1",
|
|
6041
|
-
title: "copy",
|
|
6042
|
-
"aria-label": "copy"
|
|
6043
|
-
},
|
|
6044
|
-
[[
|
|
6045
|
-
"span",
|
|
6046
|
-
{ class: "icon m-0" },
|
|
6047
|
-
"<i class=\"yi-copy\"></i>"
|
|
6048
|
-
], [
|
|
6049
|
-
"span",
|
|
6050
|
-
{
|
|
6051
|
-
class: "is-hidden-mobile pl-1 pr-1",
|
|
6052
|
-
i18n: "copy"
|
|
6053
|
-
},
|
|
6054
|
-
"copy"
|
|
6055
|
-
]],
|
|
6056
|
-
{ click: function(evt) {
|
|
6057
|
-
evt.stopPropagation();
|
|
6058
|
-
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_COPY_RECORD", {}, gobj);
|
|
6059
|
-
} }
|
|
6060
|
-
], [
|
|
6061
|
-
"button",
|
|
6062
|
-
{
|
|
6063
|
-
class: "button p-1",
|
|
6064
|
-
title: "paste",
|
|
6065
|
-
"aria-label": "paste"
|
|
6066
|
-
},
|
|
6067
|
-
[[
|
|
6068
|
-
"span",
|
|
6069
|
-
{ class: "icon m-0" },
|
|
6070
|
-
"<i class=\"yi-paste\"></i>"
|
|
6071
|
-
], [
|
|
6072
|
-
"span",
|
|
6073
|
-
{
|
|
6074
|
-
class: "is-hidden-mobile pl-1 pr-1",
|
|
6075
|
-
i18n: "paste"
|
|
6076
|
-
},
|
|
6077
|
-
"paste"
|
|
6078
|
-
]],
|
|
6079
|
-
{ click: async function(evt) {
|
|
6080
|
-
evt.stopPropagation();
|
|
6081
|
-
await readClipboard$1(gobj);
|
|
6082
|
-
} }
|
|
6083
|
-
]]
|
|
6084
|
-
]]
|
|
6085
|
-
]]
|
|
6249
|
+
], build_toolbar(gobj)]
|
|
6086
6250
|
]);
|
|
6087
6251
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "$container", $container);
|
|
6088
6252
|
apply_form_mode(gobj, $container.querySelector("form"));
|
|
@@ -12943,7 +13107,12 @@ function cards_grid_descriptor(items, show_label) {
|
|
|
12943
13107
|
* container; build_ui re-applies them on every rebuild.
|
|
12944
13108
|
*
|
|
12945
13109
|
* Each item supports:
|
|
12946
|
-
* id, name, icon (CSS class or svg id), route,
|
|
13110
|
+
* id, name, icon (CSS class or svg id), route, disabled
|
|
13111
|
+
* (`badge` was listed here for a long time and NOTHING ever
|
|
13112
|
+
* rendered it — a menu item cannot carry a count today. The
|
|
13113
|
+
* toolbar can: `badge` on a toolbar item plus
|
|
13114
|
+
* yui_shell_set_toolbar_item_badge(). Implement it here the
|
|
13115
|
+
* day a menu entry needs one, rather than re-listing it.)
|
|
12947
13116
|
* class — extra CSS class(es) on the item (tabs layout), e.g.
|
|
12948
13117
|
* a per-item state colour like "yui-nav-disconnected"
|
|
12949
13118
|
* closable — render a trailing ✕ that emits EV_NAV_ITEM_CLOSE
|
|
@@ -53622,6 +53791,7 @@ exports.yui_shell_register_overlay = yui_shell_register_overlay;
|
|
|
53622
53791
|
exports.yui_shell_set_avatar_provider = yui_shell_set_avatar_provider;
|
|
53623
53792
|
exports.yui_shell_set_connection_state = yui_shell_set_connection_state;
|
|
53624
53793
|
exports.yui_shell_set_sub_routes = yui_shell_set_sub_routes;
|
|
53794
|
+
exports.yui_shell_set_toolbar_item_badge = yui_shell_set_toolbar_item_badge;
|
|
53625
53795
|
exports.yui_shell_set_toolbar_item_icon = yui_shell_set_toolbar_item_icon;
|
|
53626
53796
|
exports.yui_shell_set_translator = yui_shell_set_translator;
|
|
53627
53797
|
exports.yui_shell_show_error = yui_shell_show_error;
|