@k2b/cloud 0.21.1 → 0.22.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/package.json +2 -2
- package/src/ssr/GlobalAnnouncements.island.tsx +8 -33
- package/src/styles/effects.css +6 -30
- package/src/styles/global.css +5 -0
- package/src/styles/tokens.css +5 -1
- package/src/styles/utilities-feedback.css +15 -5
- package/src/styles/utilities-layout.css +4 -0
- package/src/styles/utilities-markdown-editor.css +20 -2
- package/src/styles/utilities-markdown-table.css +35 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k2b/cloud",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Application platform library for independently deployed Hono and SolidJS services behind a dynamic gateway.",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"repository": {
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"@tailwindcss/typography": "0.5.20",
|
|
99
99
|
"@k2b/nessi": "0.12.1",
|
|
100
100
|
"@k2b/ssr": "0.14.0",
|
|
101
|
-
"@k2b/ui": "0.
|
|
101
|
+
"@k2b/ui": "0.12.0",
|
|
102
102
|
"@k2b/stdlib": "0.27.0",
|
|
103
103
|
"@k2b/sync": "7.0.0",
|
|
104
104
|
"@nats-io/jetstream": "3.4.0",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Button, dialogCore, MarkdownView, PanelDialog, panelDialogOptions, useLocale } from "@k2b/ui";
|
|
1
|
+
import { Button, dialogCore, IconButton, MarkdownView, NoticeCard, PanelDialog, panelDialogOptions, useLocale } from "@k2b/ui";
|
|
2
2
|
import { createSignal, For, onMount, Show } from "solid-js";
|
|
3
3
|
import {
|
|
4
4
|
ANNOUNCEMENTS_COOKIE,
|
|
@@ -21,22 +21,6 @@ const writeCookieState = (state: AnnouncementCookieState) => {
|
|
|
21
21
|
document.cookie = `${ANNOUNCEMENTS_COOKIE}=${serializeAnnouncementCookieState(state)}; Path=/; Max-Age=${ANNOUNCEMENTS_COOKIE_MAX_AGE_SECONDS}; SameSite=Lax`;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
const toneClass = (tone: AnnouncementDisplayEntry["tone"]) => {
|
|
25
|
-
if (tone === "success")
|
|
26
|
-
return "border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-900/60 dark:bg-emerald-950/40 dark:text-emerald-100";
|
|
27
|
-
if (tone === "warning")
|
|
28
|
-
return "border-amber-200 bg-amber-50 text-amber-950 dark:border-amber-900/60 dark:bg-amber-950/40 dark:text-amber-100";
|
|
29
|
-
if (tone === "danger") return "border-red-200 bg-red-50 text-red-950 dark:border-red-900/60 dark:bg-red-950/40 dark:text-red-100";
|
|
30
|
-
return "border-blue-200 bg-blue-50 text-blue-950 dark:border-blue-900/60 dark:bg-blue-950/40 dark:text-blue-100";
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const toneIcon = (tone: AnnouncementDisplayEntry["tone"]) => {
|
|
34
|
-
if (tone === "success") return "ti ti-circle-check";
|
|
35
|
-
if (tone === "warning") return "ti ti-alert-triangle";
|
|
36
|
-
if (tone === "danger") return "ti ti-alert-circle";
|
|
37
|
-
return "ti ti-info-circle";
|
|
38
|
-
};
|
|
39
|
-
|
|
40
24
|
export default function GlobalAnnouncements(props: Props) {
|
|
41
25
|
const locale = useLocale();
|
|
42
26
|
const t = () => platformMessages.resolve([locale()]).t;
|
|
@@ -113,27 +97,18 @@ export default function GlobalAnnouncements(props: Props) {
|
|
|
113
97
|
<div class="flex shrink-0 flex-col gap-1">
|
|
114
98
|
<For each={banners()}>
|
|
115
99
|
{(banner) => (
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
>
|
|
119
|
-
<i class={`${toneIcon(banner.tone)} mt-0.5 shrink-0`} />
|
|
120
|
-
<div class="min-h-0 min-w-0 flex-1">
|
|
121
|
-
<p class="font-semibold">{banner.title}</p>
|
|
100
|
+
<div class="cloud-announcement">
|
|
101
|
+
<NoticeCard tone={banner.tone} title={banner.title}>
|
|
122
102
|
<MarkdownView
|
|
123
103
|
trustedHtml={banner.bodyHtml}
|
|
124
104
|
headingScale="compact"
|
|
125
105
|
class="mt-1 max-h-36 overflow-y-auto overscroll-contain pr-1 [&_p]:my-0"
|
|
126
106
|
/>
|
|
127
|
-
</
|
|
128
|
-
<
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
onClick={() => dismissBanner(banner.version)}
|
|
133
|
-
>
|
|
134
|
-
<i class="ti ti-x" />
|
|
135
|
-
</button>
|
|
136
|
-
</section>
|
|
107
|
+
</NoticeCard>
|
|
108
|
+
<IconButton size="sm" label={t().dismissBanner} onClick={() => dismissBanner(banner.version)}>
|
|
109
|
+
<i class="ti ti-x" aria-hidden="true" />
|
|
110
|
+
</IconButton>
|
|
111
|
+
</div>
|
|
137
112
|
)}
|
|
138
113
|
</For>
|
|
139
114
|
</div>
|
package/src/styles/effects.css
CHANGED
|
@@ -514,12 +514,10 @@
|
|
|
514
514
|
display: none;
|
|
515
515
|
}
|
|
516
516
|
|
|
517
|
+
/* The fill without a frame comes from the shared `.md-code-block pre` rule;
|
|
518
|
+
Help keeps its own spacing and syntax colours. */
|
|
517
519
|
.help-document .md-code-block pre {
|
|
518
520
|
margin: 0;
|
|
519
|
-
border: 0 !important;
|
|
520
|
-
border-radius: var(--ui-radius-surface) !important;
|
|
521
|
-
background: var(--ui-surface-subtle) !important;
|
|
522
|
-
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ui-border) 72%, transparent);
|
|
523
521
|
padding: 0.875rem 1rem;
|
|
524
522
|
}
|
|
525
523
|
|
|
@@ -602,15 +600,6 @@
|
|
|
602
600
|
padding: 0;
|
|
603
601
|
}
|
|
604
602
|
|
|
605
|
-
.help-document :where(blockquote) {
|
|
606
|
-
margin: 1.25rem 0;
|
|
607
|
-
border: 0;
|
|
608
|
-
border-radius: var(--ui-radius-surface);
|
|
609
|
-
background: var(--ui-surface-subtle);
|
|
610
|
-
color: var(--color-zinc-600);
|
|
611
|
-
padding: 0.875rem 1rem;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
603
|
.help-document .md-table-wrap {
|
|
615
604
|
overflow: hidden;
|
|
616
605
|
margin-block: 0.875rem 1.5rem;
|
|
@@ -623,13 +612,11 @@
|
|
|
623
612
|
border-spacing: 0;
|
|
624
613
|
}
|
|
625
614
|
|
|
626
|
-
/* `MarkdownView
|
|
627
|
-
|
|
628
|
-
through the wrapper's rounded clipping corners. */
|
|
615
|
+
/* Help renders inside `MarkdownView`, which draws the table's row lines. The
|
|
616
|
+
inner `.md-table-cell` owns the padding. */
|
|
629
617
|
.help-document .md-table :is(th, td) {
|
|
630
618
|
min-width: 0;
|
|
631
619
|
height: auto;
|
|
632
|
-
border: 0;
|
|
633
620
|
padding: 0;
|
|
634
621
|
}
|
|
635
622
|
|
|
@@ -651,10 +638,6 @@
|
|
|
651
638
|
word-break: normal;
|
|
652
639
|
}
|
|
653
640
|
|
|
654
|
-
.help-document .md-table thead {
|
|
655
|
-
background: var(--ui-surface-subtle);
|
|
656
|
-
}
|
|
657
|
-
|
|
658
641
|
.help-document .md-table thead .md-table-cell {
|
|
659
642
|
color: var(--color-zinc-700);
|
|
660
643
|
font-size: 0.75rem;
|
|
@@ -672,7 +655,8 @@
|
|
|
672
655
|
font-weight: 400;
|
|
673
656
|
}
|
|
674
657
|
|
|
675
|
-
|
|
658
|
+
/* Element specificity, so it outranks MarkdownView's inline-code fill. */
|
|
659
|
+
.help-document .md-table-cell code {
|
|
676
660
|
border-radius: 0;
|
|
677
661
|
background: transparent;
|
|
678
662
|
color: inherit;
|
|
@@ -681,18 +665,10 @@
|
|
|
681
665
|
padding: 0;
|
|
682
666
|
}
|
|
683
667
|
|
|
684
|
-
.dark .help-document .md-table thead {
|
|
685
|
-
background: var(--ui-surface-subtle);
|
|
686
|
-
}
|
|
687
|
-
|
|
688
668
|
.dark .help-document .md-table thead .md-table-cell {
|
|
689
669
|
color: var(--color-zinc-200);
|
|
690
670
|
}
|
|
691
671
|
|
|
692
|
-
.dark .help-document :where(blockquote) {
|
|
693
|
-
color: var(--color-zinc-400);
|
|
694
|
-
}
|
|
695
|
-
|
|
696
672
|
.help-document :where(hr) {
|
|
697
673
|
height: 0;
|
|
698
674
|
margin-block: 2rem;
|
package/src/styles/global.css
CHANGED
|
@@ -294,6 +294,11 @@ solid-island {
|
|
|
294
294
|
border-radius: 0; border: 0; border-bottom: 1px solid var(--ui-border);
|
|
295
295
|
box-shadow: none !important;
|
|
296
296
|
}
|
|
297
|
+
/* Toasts at the top edge of a phone start below the header instead of
|
|
298
|
+
covering its menu and search buttons. */
|
|
299
|
+
:root:has(.cloud-app-canvas .layout-header) {
|
|
300
|
+
--k2b-toast-offset-top: 2.875rem;
|
|
301
|
+
}
|
|
297
302
|
|
|
298
303
|
}
|
|
299
304
|
|
package/src/styles/tokens.css
CHANGED
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
--ui-surface-subtle: rgb(248 248 248 / 0.96);
|
|
8
8
|
--ui-surface-muted: rgb(243 244 243 / 0.96);
|
|
9
9
|
--ui-surface-raised: rgb(255 255 255 / 0.99);
|
|
10
|
+
/* Dimmed text stays at WCAG AA on the muted surfaces it often sits on, such
|
|
11
|
+
as dialog section groups, not only on the plain surface. */
|
|
12
|
+
--ui-text-dimmed: color-mix(in srgb, var(--color-zinc-500) 80%, var(--color-zinc-600));
|
|
10
13
|
--ui-border: rgb(218 220 219 / 0.68);
|
|
11
14
|
--ui-border-strong: rgb(207 210 208 / 0.9);
|
|
12
15
|
--ui-hover: rgb(239 240 239 / 0.9);
|
|
@@ -135,6 +138,7 @@
|
|
|
135
138
|
--ui-surface-subtle: color-mix(in srgb, var(--ui-surface) 68%, var(--ui-surface-muted));
|
|
136
139
|
--ui-surface-muted: #20242a;
|
|
137
140
|
--ui-surface-raised: #181d24;
|
|
141
|
+
--ui-text-dimmed: color-mix(in srgb, var(--color-zinc-500) 40%, var(--color-zinc-400));
|
|
138
142
|
--ui-border: #29313a;
|
|
139
143
|
--ui-border-strong: #3a4552;
|
|
140
144
|
--ui-hover: #252c35;
|
|
@@ -222,7 +226,7 @@
|
|
|
222
226
|
}
|
|
223
227
|
|
|
224
228
|
@utility text-dimmed {
|
|
225
|
-
|
|
229
|
+
color: var(--ui-text-dimmed);
|
|
226
230
|
}
|
|
227
231
|
|
|
228
232
|
@utility text-label {
|
|
@@ -224,11 +224,21 @@
|
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
227
|
+
/* Operator banners: a NoticeCard with its close button in the top corner. */
|
|
228
|
+
.k2b-ui .cloud-announcement {
|
|
229
|
+
position: relative;
|
|
230
|
+
}
|
|
231
|
+
.k2b-ui .cloud-announcement .k2b-notice-card__content {
|
|
232
|
+
padding-right: 1.75rem;
|
|
233
|
+
}
|
|
234
|
+
.k2b-ui .cloud-announcement .k2b-content-markdown {
|
|
235
|
+
font-size: inherit;
|
|
236
|
+
line-height: inherit;
|
|
237
|
+
}
|
|
238
|
+
.k2b-ui .cloud-announcement > .k2b-icon-button {
|
|
239
|
+
position: absolute;
|
|
240
|
+
top: 0.4375rem;
|
|
241
|
+
right: 0.4375rem;
|
|
232
242
|
}
|
|
233
243
|
|
|
234
244
|
/* Approval prose follows the surrounding review fields, not document typography. */
|
|
@@ -22,6 +22,10 @@
|
|
|
22
22
|
background: var(--ui-surface);
|
|
23
23
|
/* Shared surface depth stays consistent with the Layout header. */
|
|
24
24
|
box-shadow: var(--ui-shadow-surface);
|
|
25
|
+
/* A paper card inside a dialog section group paints its own surface, so its
|
|
26
|
+
fields return to the muted well instead of the group's white one. */
|
|
27
|
+
--k2b-field-surface: initial;
|
|
28
|
+
--k2b-field-hover: initial;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
@utility dialog-panel {
|
|
@@ -431,6 +431,12 @@
|
|
|
431
431
|
color: var(--ui-app-accent-text);
|
|
432
432
|
}
|
|
433
433
|
|
|
434
|
+
/* The brackets, weight and icon already mark the widget as a link, so it
|
|
435
|
+
keeps no underline inside MarkdownView, the same as in Assistant chat. */
|
|
436
|
+
.k2b-ui .k2b-content-markdown a.md-link-widget {
|
|
437
|
+
text-decoration: none;
|
|
438
|
+
}
|
|
439
|
+
|
|
434
440
|
.md-link-widget:focus-visible {
|
|
435
441
|
border-radius: 0.125rem;
|
|
436
442
|
outline: var(--k2b-focus-width) solid var(--ui-app-accent-border);
|
|
@@ -464,7 +470,20 @@
|
|
|
464
470
|
@apply bg-zinc-200/40 dark:bg-zinc-800;
|
|
465
471
|
}
|
|
466
472
|
|
|
467
|
-
|
|
473
|
+
/* Rendered code blocks match MarkdownView: a fill without a frame that
|
|
474
|
+
follows `--k2b-field-surface`, so it stays visible on a tinted group. The
|
|
475
|
+
transparent border keeps the edge visible in forced colours. The rendered
|
|
476
|
+
wrapper shares the editor's line class, so it drops the line fill. */
|
|
477
|
+
.md-code-block:has(> pre) {
|
|
478
|
+
background: transparent;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.md-code-block pre {
|
|
482
|
+
border: 1px solid transparent !important;
|
|
483
|
+
border-radius: var(--ui-radius-control) !important;
|
|
484
|
+
background: var(--k2b-field-surface, var(--ui-surface-muted)) !important;
|
|
485
|
+
}
|
|
486
|
+
|
|
468
487
|
.md-mermaid-block,
|
|
469
488
|
.md-katex-block {
|
|
470
489
|
border: 1px solid rgb(228 228 231 / 0.72) !important;
|
|
@@ -479,7 +498,6 @@
|
|
|
479
498
|
padding: 0.75rem;
|
|
480
499
|
}
|
|
481
500
|
|
|
482
|
-
.dark .md-code-block pre,
|
|
483
501
|
.dark .md-mermaid-block,
|
|
484
502
|
.dark .md-katex-block {
|
|
485
503
|
border-color: rgb(63 63 70 / 0.72) !important;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
/* Markdown tables use the same
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/* Markdown tables use the same hairline language as @k2b/ui MarkdownView:
|
|
2
|
+
no frame or header fill, a stronger line under the header, hairline row
|
|
3
|
+
separators, and the outer columns flush with the prose. Used by both the
|
|
4
|
+
server-side `marked` renderer and the CodeMirror table widget so read-mode
|
|
5
|
+
and edit-mode look identical.
|
|
5
6
|
|
|
6
7
|
Three-layer markup:
|
|
7
8
|
<div class="md-table-wrap"> ← horizontal scroll owner
|
|
@@ -13,10 +14,13 @@
|
|
|
13
14
|
overflow: clip;
|
|
14
15
|
margin-top: 0.5rem;
|
|
15
16
|
margin-bottom: 0.5rem;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* Inside MarkdownView a table takes the same block spacing as its own
|
|
20
|
+
tables, so two tables in a row do not read as one. Hosts such as Help keep
|
|
21
|
+
their own spacing. */
|
|
22
|
+
:where(.k2b-ui .k2b-content-markdown) .md-table-wrap {
|
|
23
|
+
margin-block: 1em;
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
.md-table {
|
|
@@ -39,12 +43,8 @@
|
|
|
39
43
|
border: 0;
|
|
40
44
|
}
|
|
41
45
|
|
|
42
|
-
.md-table thead {
|
|
43
|
-
background: var(--ui-data-header);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
46
|
.md-table thead tr {
|
|
47
|
-
border-bottom: 1px solid var(--ui-
|
|
47
|
+
border-bottom: 1px solid var(--ui-border-strong);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
.md-table tbody tr:not(:last-child) {
|
|
@@ -87,12 +87,29 @@
|
|
|
87
87
|
color: inherit;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
/* Headers inherit the single shared band instead of drawing per-cell fills. */
|
|
91
90
|
.md-table thead .md-table-cell {
|
|
91
|
+
padding-top: 0;
|
|
92
92
|
background: transparent;
|
|
93
93
|
font-weight: 600;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
.md-table th:first-child > .md-table-cell,
|
|
97
|
+
.md-table td:first-child > .md-table-cell {
|
|
98
|
+
padding-left: 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.md-table th:last-child > .md-table-cell,
|
|
102
|
+
.md-table td:last-child > .md-table-cell {
|
|
103
|
+
padding-right: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Inside MarkdownView the span stays the only padding owner. */
|
|
107
|
+
.k2b-ui .k2b-content-markdown .md-table th,
|
|
108
|
+
.k2b-ui .k2b-content-markdown .md-table td {
|
|
109
|
+
padding: 0;
|
|
110
|
+
font-size: inherit;
|
|
111
|
+
}
|
|
112
|
+
|
|
96
113
|
.dark .md-table thead .md-table-cell {
|
|
97
114
|
background: transparent;
|
|
98
115
|
}
|
|
@@ -109,9 +126,10 @@
|
|
|
109
126
|
justify-content: center;
|
|
110
127
|
}
|
|
111
128
|
|
|
112
|
-
/*
|
|
113
|
-
|
|
114
|
-
|
|
129
|
+
/* A summary row sits under the same stronger line as the header. The line is
|
|
130
|
+
on the cells, so it also wins over a row separator or MarkdownView's. */
|
|
131
|
+
.k2b-ui .md-table tbody tr.md-table-total-row > td {
|
|
132
|
+
border-top: 1px solid var(--ui-border-strong);
|
|
115
133
|
}
|
|
116
134
|
|
|
117
135
|
.md-table tbody tr.md-table-total-row .md-table-cell {
|