@yuneta/gobj-ui 2.5.0 → 3.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.
@@ -49,16 +49,36 @@ import {
49
49
  ***************************************************************/
50
50
  function notification_layer(shell)
51
51
  {
52
+ if(!shell) {
53
+ return null;
54
+ }
52
55
  let priv = gobj_read_attr(shell, "priv");
53
56
  return priv && priv.layers && priv.layers.notification;
54
57
  }
55
58
 
56
59
  function modal_layer(shell)
57
60
  {
61
+ if(!shell) {
62
+ return null;
63
+ }
58
64
  let priv = gobj_read_attr(shell, "priv");
59
65
  return priv && priv.layers && priv.layers.modal;
60
66
  }
61
67
 
68
+ /* Public: where a component should mount its own popup/dialog DOM
69
+ * (e.g. the treedb edit dialog). The popup layer (z 20) sits below
70
+ * the modal layer (z 99), so shell confirms always paint above the
71
+ * component's dialog — matching the Escape chain LIFO order. Null
72
+ * when there is no shell: the caller picks its legacy fallback. */
73
+ export function yui_shell_popup_layer(shell)
74
+ {
75
+ if(!shell) {
76
+ return null;
77
+ }
78
+ let priv = gobj_read_attr(shell, "priv");
79
+ return (priv && priv.layers && priv.layers.popup) || null;
80
+ }
81
+
62
82
 
63
83
  /***************************************************************
64
84
  * i18n bridge:
@@ -301,13 +321,28 @@ export function yui_shell_show_modal(shell, content, opts)
301
321
 
302
322
 
303
323
  /***************************************************************
304
- * Blocking dialogs (Bulma .modal-card)
324
+ * Blocking dialogs (icon-centric .modal-card)
305
325
  *
306
326
  * build_dialog returns a Promise that resolves with the
307
327
  * clicked button's `value`. Escape, the close button and
308
328
  * the dismiss action all resolve with the LAST button's value
309
329
  * (cancel/no/ok by convention — the safe-default action).
330
+ *
331
+ * Layout ported from the legacy volatil modals (2.5.0
332
+ * redesign, removed in 3.0.0): a narrow rounded card with a
333
+ * tinted round icon of the `opts.type`
334
+ * (question/success/info/warning/error, `danger` aliases
335
+ * error), optional capitalized title, centered message and
336
+ * buttons. Everything maps to Bulma vars (light and dark).
310
337
  ***************************************************************/
338
+ const CONFIRM_TYPE_ICONS = {
339
+ "info": "yi-circle-info",
340
+ "question": "yi-question",
341
+ "success": "yi-square-check",
342
+ "warning": "yi-triangle-exclamation",
343
+ "error": "yi-circle-exclamation",
344
+ };
345
+
311
346
  function build_dialog(shell, message, buttons, opts)
312
347
  {
313
348
  let $layer = modal_layer(shell);
@@ -319,16 +354,18 @@ function build_dialog(shell, message, buttons, opts)
319
354
  let title = (opts && opts.title) || "";
320
355
  let dismiss_value = buttons[buttons.length - 1].value;
321
356
 
357
+ let type = ((opts && opts.type) || "question").toLowerCase();
358
+ if(type === "danger") {
359
+ type = "error";
360
+ }
361
+ let icon = CONFIRM_TYPE_ICONS[type] || CONFIRM_TYPE_ICONS["question"];
362
+
322
363
  let $body_children = (typeof message === "string")
323
- ? [["p", {i18n: message}, message]]
364
+ ? [["p", {class: "yui-confirm-msg", i18n: message}, message]]
324
365
  : [message];
325
366
 
326
- let title_attrs = !empty_string(title)
327
- ? {class: "modal-card-title", i18n: title}
328
- : {class: "modal-card-title"};
329
-
330
367
  let $footer_children = buttons.map(b => {
331
- let cls = "button";
368
+ let cls = "button px-5";
332
369
  if(b.kind === "primary") {
333
370
  cls += " is-link";
334
371
  } else if(b.kind === "danger") {
@@ -342,24 +379,30 @@ function build_dialog(shell, message, buttons, opts)
342
379
  return ["button", btn_attrs, b.label];
343
380
  });
344
381
 
382
+ let $card_children = [
383
+ ["div", {class: "yui-confirm-icon"},
384
+ [["i", {class: icon, "aria-hidden": "true"}]]
385
+ ]
386
+ ];
387
+ if(!empty_string(title)) {
388
+ $card_children.push(
389
+ ["p", {class: "yui-confirm-title has-text-centered",
390
+ i18n: title}, title]
391
+ );
392
+ }
393
+ $card_children.push(
394
+ ["button", {class: "delete yui-confirm-x", "aria-label": "close"}],
395
+ ["section", {class: "modal-card-body has-text-centered"},
396
+ $body_children],
397
+ ["footer", {class: "modal-card-foot"}, $footer_children]
398
+ );
399
+
345
400
  let $modal = createElement2(
346
- ["div", {class: "modal yui-modal yui-confirm is-active",
401
+ ["div", {class: `modal yui-modal yui-confirm is-active is-${type}`,
347
402
  role: "dialog", "aria-modal": "true"},
348
403
  [
349
404
  ["div", {class: "modal-background"}],
350
- ["div", {class: "modal-card"},
351
- [
352
- ["header", {class: "modal-card-head"},
353
- [
354
- ["p", title_attrs, title],
355
- ["button", {class: "delete",
356
- "aria-label": "close"}]
357
- ]
358
- ],
359
- ["section", {class: "modal-card-body"}, $body_children],
360
- ["footer", {class: "modal-card-foot"}, $footer_children]
361
- ]
362
- ]
405
+ ["div", {class: "modal-card"}, $card_children]
363
406
  ]
364
407
  ]
365
408
  );
@@ -399,7 +442,7 @@ function build_dialog(shell, message, buttons, opts)
399
442
  $modal.querySelector(".modal-background").addEventListener(
400
443
  "click", () => close(dismiss_value)
401
444
  );
402
- $modal.querySelector(".modal-card-head .delete").addEventListener(
445
+ $modal.querySelector(".modal-card .delete").addEventListener(
403
446
  "click", () => close(dismiss_value)
404
447
  );
405
448
  let footer_buttons = $modal.querySelectorAll(
@@ -410,6 +453,12 @@ function build_dialog(shell, message, buttons, opts)
410
453
  close($btn.getAttribute("data-modal-button-value"));
411
454
  });
412
455
  });
456
+
457
+ /* Enter answers the primary action, like the volatil modals. */
458
+ let $primary = $modal.querySelector(".modal-card-foot button");
459
+ if($primary) {
460
+ $primary.focus();
461
+ }
413
462
  });
414
463
  }
415
464
 
@@ -417,6 +466,9 @@ function build_dialog(shell, message, buttons, opts)
417
466
  export function yui_shell_confirm_ok(shell, message, opts)
418
467
  {
419
468
  let label = (opts && opts.ok_label) || "OK";
469
+ if(!opts || !opts.type) {
470
+ opts = Object.assign({}, opts, {type: "success"});
471
+ }
420
472
  return build_dialog(shell, message, [
421
473
  {label: label, value: "ok", kind: "primary"}
422
474
  ], opts).then(() => undefined);
package/src/tabulator.css CHANGED
@@ -51,3 +51,181 @@
51
51
  [data-theme=dark] .tabulator-data-tree-control .tabulator-data-tree-control-collapse:after {
52
52
  background: #ffffff !important;
53
53
  }
54
+
55
+ /* Moved from c_yui_main.css (2.6.1): generic Tabulator theming
56
+ * (column separator, frozen columns, striping/hover, dark + system themes).
57
+ * Self-contained here so every consumer gets it without the
58
+ * legacy stack's stylesheet. */
59
+
60
+ /*********************************************************
61
+ * Tabulator
62
+ *********************************************************/
63
+
64
+ /* Visible column separator via pseudo-element on the right-side resize handle only.
65
+ .prev handles (left-side) are excluded so hidden columns (e.g. Select Row when
66
+ not in edit mode) don't leave a spurious line at the start of the table. */
67
+ .tabulator .tabulator-col-resize-handle:not(.prev)::after {
68
+ content: "";
69
+ position: absolute;
70
+ top: 0;
71
+ bottom: 0;
72
+ left: 50%;
73
+ width: 1px;
74
+ background-color: var(--bulma-border);
75
+ }
76
+
77
+ .tabulator-row .tabulator-cell.tabulator-frozen {
78
+ background-color: var(--bulma-background) !important;
79
+ }
80
+ .tabulator .tabulator-header .tabulator-frozen {
81
+ background-color: var(--bulma-background) !important;
82
+ }
83
+
84
+ /*
85
+ * Tabulator light theme — alternating row backgrounds
86
+ * scheme-main-ter (#f5f5f5) gives visible contrast against white odd rows.
87
+ * !important needed to override the tabulator_bulma.css theme.
88
+ */
89
+ .tabulator .tabulator-row,
90
+ .tabulator .tabulator-row.tabulator-row-odd {
91
+ background-color: var(--bulma-scheme-main, #fff) !important;
92
+ }
93
+
94
+ .tabulator .tabulator-row.tabulator-row-even {
95
+ background-color: var(--bulma-scheme-main-ter, #f5f5f5) !important;
96
+ }
97
+
98
+ .tabulator .tabulator-row.tabulator-selectable:hover {
99
+ background-color: var(--bulma-background, #ebebeb) !important;
100
+ }
101
+
102
+ /*
103
+ * Tabulator dark theme
104
+ * Activated by html[data-theme=dark] (set by the app's theme switcher)
105
+ */
106
+ [data-theme=dark] .tabulator {
107
+ background-color: var(--bulma-body-background-color);
108
+ border-color: var(--bulma-border);
109
+ color: var(--bulma-body-color);
110
+ }
111
+
112
+ [data-theme=dark] .tabulator .tabulator-header,
113
+ [data-theme=dark] .tabulator .tabulator-header .tabulator-col {
114
+ background-color: var(--bulma-background);
115
+ border-color: var(--bulma-border);
116
+ color: var(--bulma-text);
117
+ }
118
+
119
+ [data-theme=dark] .tabulator .tabulator-header .tabulator-col.tabulator-sortable:hover {
120
+ background-color: var(--bulma-background-bis, var(--bulma-background));
121
+ }
122
+
123
+ [data-theme=dark] .tabulator-row,
124
+ [data-theme=dark] .tabulator-row.tabulator-row-odd {
125
+ background-color: var(--bulma-body-background-color) !important;
126
+ color: var(--bulma-body-color);
127
+ border-color: var(--bulma-border);
128
+ }
129
+
130
+ [data-theme=dark] .tabulator-row.tabulator-row-even {
131
+ background-color: var(--bulma-background) !important;
132
+ color: var(--bulma-body-color);
133
+ border-color: var(--bulma-border);
134
+ }
135
+
136
+ [data-theme=dark] .tabulator-row .tabulator-cell {
137
+ border-color: var(--bulma-border);
138
+ color: var(--bulma-body-color);
139
+ }
140
+
141
+ [data-theme=dark] .tabulator-row.tabulator-selectable:hover {
142
+ background-color: var(--bulma-background) !important;
143
+ color: var(--bulma-text) !important;
144
+ }
145
+
146
+ [data-theme=dark] .tabulator-row.tabulator-selected {
147
+ background-color: var(--bulma-link) !important;
148
+ color: var(--bulma-link-invert) !important;
149
+ }
150
+
151
+ [data-theme=dark] .tabulator-row.tabulator-selected .tabulator-cell {
152
+ color: var(--bulma-link-invert) !important;
153
+ }
154
+
155
+ [data-theme=dark] .tabulator .tabulator-footer {
156
+ background-color: var(--bulma-background);
157
+ border-color: var(--bulma-border);
158
+ color: var(--bulma-text);
159
+ }
160
+
161
+ [data-theme=dark] .tabulator .tabulator-footer .tabulator-page {
162
+ background-color: transparent;
163
+ color: var(--bulma-text);
164
+ border-color: var(--bulma-border);
165
+ }
166
+
167
+ [data-theme=dark] .tabulator .tabulator-footer .tabulator-page:not(.disabled):hover {
168
+ background-color: var(--bulma-background);
169
+ color: var(--bulma-text);
170
+ }
171
+
172
+ [data-theme=dark] .tabulator .tabulator-footer .tabulator-page.active {
173
+ background-color: var(--bulma-link);
174
+ color: var(--bulma-link-invert);
175
+ }
176
+
177
+ [data-theme=dark] .tabulator-row .tabulator-cell.tabulator-frozen {
178
+ background-color: var(--bulma-background) !important;
179
+ }
180
+
181
+ /* system theme: follow OS preference */
182
+ @media (prefers-color-scheme: dark) {
183
+ [data-theme=system] .tabulator {
184
+ background-color: var(--bulma-body-background-color);
185
+ border-color: var(--bulma-border);
186
+ color: var(--bulma-body-color);
187
+ }
188
+ [data-theme=system] .tabulator .tabulator-header,
189
+ [data-theme=system] .tabulator .tabulator-header .tabulator-col {
190
+ background-color: var(--bulma-background);
191
+ border-color: var(--bulma-border);
192
+ color: var(--bulma-text);
193
+ }
194
+ [data-theme=system] .tabulator-row,
195
+ [data-theme=system] .tabulator-row.tabulator-row-odd {
196
+ background-color: var(--bulma-body-background-color) !important;
197
+ color: var(--bulma-body-color);
198
+ border-color: var(--bulma-border);
199
+ }
200
+ [data-theme=system] .tabulator-row.tabulator-row-even {
201
+ background-color: var(--bulma-background) !important;
202
+ color: var(--bulma-body-color);
203
+ border-color: var(--bulma-border);
204
+ }
205
+ [data-theme=system] .tabulator-row .tabulator-cell {
206
+ border-color: var(--bulma-border);
207
+ color: var(--bulma-body-color);
208
+ }
209
+ [data-theme=system] .tabulator-row.tabulator-selectable:hover {
210
+ background-color: var(--bulma-background) !important;
211
+ }
212
+ [data-theme=system] .tabulator-row.tabulator-selected {
213
+ background-color: var(--bulma-link) !important;
214
+ color: var(--bulma-link-invert) !important;
215
+ }
216
+ [data-theme=system] .tabulator .tabulator-footer {
217
+ background-color: var(--bulma-background);
218
+ border-color: var(--bulma-border);
219
+ color: var(--bulma-text);
220
+ }
221
+ [data-theme=system] .tabulator .tabulator-footer .tabulator-page {
222
+ background-color: transparent;
223
+ color: var(--bulma-text);
224
+ border-color: var(--bulma-border);
225
+ }
226
+ [data-theme=system] .tabulator .tabulator-footer .tabulator-page.active {
227
+ background-color: var(--bulma-link);
228
+ color: var(--bulma-link-invert);
229
+ }
230
+ }
231
+
@@ -48,3 +48,31 @@
48
48
  .yui-horizontal-toolbar-scroll-btn span {
49
49
  width: 1.2em;
50
50
  }
51
+
52
+ /* Moved from c_yui_main.css (2.6.1): horizontal toolbar section.
53
+ * Self-contained here so every consumer gets it without the
54
+ * legacy stack's stylesheet. */
55
+
56
+ /*********************************************************
57
+ * Toolbars
58
+ *********************************************************/
59
+ .yui-horizontal-toolbar-section {
60
+ display: flex;
61
+ height: auto;
62
+ flex-shrink: 0; /* Prevents resizing */
63
+ white-space: nowrap;
64
+ margin: 0 2px; /* Space between sections */
65
+ justify-content: space-between;
66
+ align-items: center;
67
+ }
68
+
69
+ a.flex-horizontal-section { /* To make flex any <a> */
70
+ display: flex;
71
+ flex-shrink: 0; /* Prevents resizing */
72
+ white-space: nowrap;
73
+ margin: 0 2px; /* Space between sections */
74
+ justify-content: space-between;
75
+ align-items: center;
76
+ padding-inline-end: 2rem;
77
+ }
78
+