@mdbase-dev/ui 0.1.0-beta.126 → 0.1.0-beta.148
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 +168 -0
- package/css/collections.css +978 -0
- package/css/controls.css +33 -1
- package/css/screens.css +44 -2
- package/dist/AppSwitcher.js +187 -33
- package/dist/Checkbox.d.ts +14 -0
- package/dist/Checkbox.js +32 -0
- package/dist/CollectionModeControl.d.ts +11 -0
- package/dist/CollectionModeControl.js +290 -0
- package/dist/CommandPalette.d.ts +4 -2
- package/dist/CommandPalette.js +275 -103
- package/dist/Dialog.js +72 -25
- package/dist/Feedback.js +763 -229
- package/dist/FeedbackMarkup.d.ts +1 -1
- package/dist/FeedbackMarkup.js +326 -125
- package/dist/FeedbackVerification.js +115 -68
- package/dist/SaveNotice.js +71 -28
- package/dist/Select.js +183 -135
- package/dist/SelectList.js +59 -14
- package/dist/ThemeSelect.js +55 -4
- package/dist/apps.d.ts +1 -0
- package/dist/apps.js +50 -29
- package/dist/brand.js +251 -68
- package/dist/codemirror.js +116 -87
- package/dist/collections/CollectionGate.d.ts +52 -0
- package/dist/collections/CollectionGate.js +456 -0
- package/dist/collections/CollectionSaveWarning.d.ts +10 -0
- package/dist/collections/CollectionSaveWarning.js +28 -0
- package/dist/collections/CollectionSwitcher.d.ts +51 -0
- package/dist/collections/CollectionSwitcher.js +598 -0
- package/dist/collections/SetupReview.d.ts +9 -0
- package/dist/collections/SetupReview.js +216 -0
- package/dist/collections/copy.d.ts +100 -0
- package/dist/collections/copy.js +937 -0
- package/dist/collections/dialogs.d.ts +27 -0
- package/dist/collections/dialogs.js +169 -0
- package/dist/collections/model.d.ts +146 -0
- package/dist/collections/model.js +337 -0
- package/dist/collections/mount.d.ts +19 -0
- package/dist/collections/mount.js +56 -0
- package/dist/collections/parts.d.ts +86 -0
- package/dist/collections/parts.js +439 -0
- package/dist/collections/testing.d.ts +19 -0
- package/dist/collections/testing.js +39 -0
- package/dist/collections/use-collection-ui.d.ts +140 -0
- package/dist/collections/use-collection-ui.js +236 -0
- package/dist/collections.d.ts +19 -0
- package/dist/collections.js +13 -0
- package/dist/feedback-data.d.ts +13 -12
- package/dist/feedback-data.js +365 -168
- package/dist/flock.d.ts +63 -0
- package/dist/flock.js +140 -0
- package/dist/i18n.d.ts +6 -0
- package/dist/i18n.js +71 -0
- package/dist/locales/de/messages.json +1 -0
- package/dist/locales/en/messages.json +1 -0
- package/dist/locales/es/messages.json +1 -0
- package/dist/locales/fr/messages.json +1 -0
- package/dist/locales/it/messages.json +1 -0
- package/dist/locales/ja/messages.json +1 -0
- package/dist/locales/ko/messages.json +1 -0
- package/dist/locales/pt/messages.json +1 -0
- package/dist/locales/ru/messages.json +1 -0
- package/dist/locales/zh/messages.json +1 -0
- package/dist/mark-activity.js +82 -75
- package/dist/permission-selection.js +27 -17
- package/dist/popover.js +138 -130
- package/dist/screens.d.ts +20 -3
- package/dist/screens.js +275 -6
- package/dist/select-model.js +34 -28
- package/dist/text-diff.d.ts +1 -0
- package/dist/text-diff.js +106 -74
- package/dist/theme.js +34 -40
- package/package.json +56 -7
package/css/controls.css
CHANGED
|
@@ -598,6 +598,31 @@ textarea.mdbase-field {
|
|
|
598
598
|
outline-offset: 2px;
|
|
599
599
|
}
|
|
600
600
|
|
|
601
|
+
/* Checkbox row: the label is the 44px target; the box keeps its size. */
|
|
602
|
+
.mdbase-check {
|
|
603
|
+
display: flex;
|
|
604
|
+
align-items: center;
|
|
605
|
+
gap: var(--space-2);
|
|
606
|
+
min-height: 44px;
|
|
607
|
+
cursor: pointer;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
.mdbase-check:has(.mdbase-checkbox:disabled) {
|
|
611
|
+
cursor: not-allowed;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
.mdbase-check-group {
|
|
615
|
+
min-width: 0;
|
|
616
|
+
margin: 0;
|
|
617
|
+
padding: 0;
|
|
618
|
+
border: 0;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
.mdbase-check-group > legend {
|
|
622
|
+
margin-bottom: var(--space-2);
|
|
623
|
+
padding: 0;
|
|
624
|
+
}
|
|
625
|
+
|
|
601
626
|
@media (pointer: coarse) {
|
|
602
627
|
/* Expand the hit target, not the visual control or its containing row. */
|
|
603
628
|
.mdbase-checkbox::before,
|
|
@@ -677,7 +702,7 @@ textarea.mdbase-field {
|
|
|
677
702
|
}
|
|
678
703
|
|
|
679
704
|
@keyframes mdbase-popover-in {
|
|
680
|
-
from {
|
|
705
|
+
from { transform: translateY(-3px); }
|
|
681
706
|
}
|
|
682
707
|
|
|
683
708
|
/* Save notices: small, quiet, and gone once there is nothing to act on. */
|
|
@@ -761,3 +786,10 @@ textarea.mdbase-field {
|
|
|
761
786
|
transition: none;
|
|
762
787
|
}
|
|
763
788
|
}
|
|
789
|
+
|
|
790
|
+
/* Mode changes stay inline; progress is text, never an optimistic toggle. */
|
|
791
|
+
.mdbase-collection-mode { display: grid; gap: var(--space-3); min-inline-size: 0; }
|
|
792
|
+
.mdbase-collection-mode :is(h3, p, ul) { margin-block: 0; }
|
|
793
|
+
.mdbase-collection-mode h3 { font-size: var(--font-size-section); font-weight: var(--font-weight-medium); }
|
|
794
|
+
.mdbase-collection-mode > div:last-child { display: flex; flex-wrap: wrap; gap: var(--space-2); }
|
|
795
|
+
.mdbase-collection-mode code { overflow-wrap: anywhere; }
|
package/css/screens.css
CHANGED
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
text-align: center;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
.mdbase-opening .wordmark-mark > .mdbase-mark {
|
|
21
|
+
display: block;
|
|
22
|
+
width: 100%;
|
|
23
|
+
height: 100%;
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
.mdbase-opening-message p,
|
|
21
27
|
.mdbase-opening-message small {
|
|
22
28
|
display: block;
|
|
@@ -38,18 +44,54 @@
|
|
|
38
44
|
color: var(--color-danger);
|
|
39
45
|
}
|
|
40
46
|
|
|
47
|
+
/* The launch screen: the mark the flock flies onto, then the quiet line. */
|
|
48
|
+
.mdbase-opening-launch-mark {
|
|
49
|
+
display: block;
|
|
50
|
+
width: 42px;
|
|
51
|
+
height: 42px;
|
|
52
|
+
margin-bottom: var(--space-2);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.mdbase-opening-launch-mark .mdbase-mark {
|
|
56
|
+
display: block;
|
|
57
|
+
width: 100%;
|
|
58
|
+
height: 100%;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* While the flock flies, the canvas draws the mark; the real one takes over when it lands. */
|
|
62
|
+
.mdbase-opening-launch[data-entrance="flying"] .mdbase-opening-launch-mark {
|
|
63
|
+
visibility: hidden;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.mdbase-opening-launch-text {
|
|
67
|
+
transition: opacity var(--motion-slow) var(--ease-out);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.mdbase-opening-launch[data-entrance="flying"] .mdbase-opening-launch-text {
|
|
71
|
+
opacity: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.mdbase-opening-flock {
|
|
75
|
+
position: fixed;
|
|
76
|
+
inset: 0;
|
|
77
|
+
width: 100vw;
|
|
78
|
+
height: 100vh;
|
|
79
|
+
pointer-events: none;
|
|
80
|
+
}
|
|
81
|
+
|
|
41
82
|
/* Before a collection is open. */
|
|
42
83
|
.mdbase-connect-screen {
|
|
43
84
|
min-height: 100%;
|
|
44
85
|
display: grid;
|
|
45
86
|
place-items: center;
|
|
46
|
-
padding
|
|
87
|
+
/* The extra bottom padding lifts short content slightly above centre; tall
|
|
88
|
+
* content just grows downward, so the top never clips (no negative margin). */
|
|
89
|
+
padding: 32px 32px calc(32px + 8vh);
|
|
47
90
|
background: var(--color-canvas);
|
|
48
91
|
}
|
|
49
92
|
|
|
50
93
|
.mdbase-connect-screen section {
|
|
51
94
|
width: min(100%, 520px);
|
|
52
|
-
margin-top: -4vh;
|
|
53
95
|
}
|
|
54
96
|
|
|
55
97
|
.mdbase-connect-screen h1 {
|
package/dist/AppSwitcher.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { i18n as _i18n } from "@lingui/core";
|
|
3
|
+
import { useLocaleRevision } from "./i18n.js";
|
|
2
4
|
import { useId, useRef, useState } from "react";
|
|
3
5
|
import { mdbaseAppHref, withAppUrls } from "./apps.js";
|
|
4
6
|
import { MdbaseAppMark, Wordmark } from "./brand.js";
|
|
@@ -13,39 +15,191 @@ let entrancePlayed = false;
|
|
|
13
15
|
* Its mark shows the page's activity (see `mark-activity`): progress, then a held loop,
|
|
14
16
|
* then `motion`. Without a `motion` it plays `keys-first` the first time it appears.
|
|
15
17
|
*/
|
|
16
|
-
export function AppSwitcher({
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
18
|
+
export function AppSwitcher({
|
|
19
|
+
current,
|
|
20
|
+
urls = {},
|
|
21
|
+
motion
|
|
22
|
+
}) {
|
|
23
|
+
useLocaleRevision();
|
|
24
|
+
const menuId = useId();
|
|
25
|
+
const triggerRef = useRef(null);
|
|
26
|
+
const [open, setOpen] = useState(false);
|
|
27
|
+
const [entrance] = useState(() => {
|
|
28
|
+
if (motion || entrancePlayed || typeof window === "undefined") return undefined;
|
|
29
|
+
entrancePlayed = true;
|
|
30
|
+
return "keys-first";
|
|
31
|
+
});
|
|
32
|
+
const activity = useMdbaseMarkActivity();
|
|
33
|
+
const close = refocus => {
|
|
34
|
+
setOpen(false);
|
|
35
|
+
if (refocus) triggerRef.current?.focus();
|
|
36
|
+
};
|
|
37
|
+
return _jsxs(_Fragment, {
|
|
38
|
+
children: [_jsxs("button", {
|
|
39
|
+
ref: triggerRef,
|
|
40
|
+
type: "button",
|
|
41
|
+
className: "mdbase-app-switcher",
|
|
42
|
+
"aria-label": _i18n._(
|
|
43
|
+
/** i18n */
|
|
44
|
+
{
|
|
45
|
+
id: "54P3Y1",
|
|
46
|
+
message: "mdbase {current}: open this collection in another app",
|
|
47
|
+
values: {
|
|
48
|
+
current: current
|
|
49
|
+
}
|
|
50
|
+
}),
|
|
51
|
+
"aria-haspopup": "menu",
|
|
52
|
+
"aria-expanded": open,
|
|
53
|
+
"aria-controls": open ? menuId : undefined,
|
|
54
|
+
title: _i18n._(
|
|
55
|
+
/** i18n */
|
|
56
|
+
{
|
|
57
|
+
id: "38fGkV",
|
|
58
|
+
message: "Open in another mdbase app"
|
|
59
|
+
}),
|
|
60
|
+
onClick: () => open ? close(false) : setOpen(true),
|
|
61
|
+
onKeyDown: event => {
|
|
62
|
+
if (!open && (event.key === "ArrowDown" || event.key === "ArrowUp")) {
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
setOpen(true);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
children: [_jsx(Wordmark, {
|
|
68
|
+
app: current,
|
|
69
|
+
motion: activity.busy ?? motion ?? entrance,
|
|
70
|
+
signal: activity.signal,
|
|
71
|
+
progress: activity.progress
|
|
72
|
+
}), _jsx("svg", {
|
|
73
|
+
className: "mdbase-app-switcher-chevron",
|
|
74
|
+
viewBox: "0 0 24 24",
|
|
75
|
+
"aria-hidden": "true",
|
|
76
|
+
children: _jsx("path", {
|
|
77
|
+
d: "m7 10 5 5 5-5"
|
|
78
|
+
})
|
|
79
|
+
})]
|
|
80
|
+
}), open ? _jsx(AppMenu, {
|
|
81
|
+
id: menuId,
|
|
82
|
+
apps: withAppUrls(urls),
|
|
83
|
+
current: current,
|
|
84
|
+
triggerRef: triggerRef,
|
|
85
|
+
onClose: close
|
|
86
|
+
}) : null]
|
|
87
|
+
});
|
|
38
88
|
}
|
|
39
|
-
function AppMenu({
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
89
|
+
function AppMenu({
|
|
90
|
+
id,
|
|
91
|
+
apps,
|
|
92
|
+
current,
|
|
93
|
+
triggerRef,
|
|
94
|
+
onClose
|
|
95
|
+
}) {
|
|
96
|
+
useLocaleRevision();
|
|
97
|
+
const menuRef = useRef(null);
|
|
98
|
+
useMenuPopover(menuRef, triggerRef, onClose, {
|
|
99
|
+
width: 320,
|
|
100
|
+
focus: 'a[role="menuitem"]'
|
|
101
|
+
});
|
|
102
|
+
const heading = new URL(location.href).searchParams.has("collection") ? _i18n._(
|
|
103
|
+
/** i18n */
|
|
104
|
+
{
|
|
105
|
+
id: "xxbaLR",
|
|
106
|
+
message: "Open this collection in"
|
|
107
|
+
}) : _i18n._(
|
|
108
|
+
/** i18n */
|
|
109
|
+
{
|
|
110
|
+
id: "vDwCOr",
|
|
111
|
+
message: "mdbase apps"
|
|
112
|
+
});
|
|
113
|
+
return _jsxs("div", {
|
|
114
|
+
ref: menuRef,
|
|
115
|
+
id: id,
|
|
116
|
+
className: "mdbase-menu",
|
|
117
|
+
popover: "manual",
|
|
118
|
+
role: "menu",
|
|
119
|
+
"aria-label": heading,
|
|
120
|
+
tabIndex: -1,
|
|
121
|
+
onKeyDown: event => moveMenuFocus(event, menuRef.current),
|
|
122
|
+
children: [_jsx("div", {
|
|
123
|
+
className: "mdbase-menu-heading",
|
|
124
|
+
role: "presentation",
|
|
125
|
+
children: heading
|
|
126
|
+
}), _jsx("div", {
|
|
127
|
+
className: "mdbase-menu-list",
|
|
128
|
+
children: apps.map(app => _jsx(AppItem, {
|
|
129
|
+
app: app,
|
|
130
|
+
current: app.id === current,
|
|
131
|
+
onOpen: () => onClose(false)
|
|
132
|
+
}, app.id))
|
|
133
|
+
}), _jsx("p", {
|
|
134
|
+
className: "mdbase-menu-note",
|
|
135
|
+
children: _i18n._(
|
|
136
|
+
/** i18n */
|
|
137
|
+
{
|
|
138
|
+
id: "XDzAnp",
|
|
139
|
+
message: "Opens in a new tab"
|
|
140
|
+
})
|
|
141
|
+
})]
|
|
142
|
+
});
|
|
44
143
|
}
|
|
45
|
-
function AppItem({
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
144
|
+
function AppItem({
|
|
145
|
+
app,
|
|
146
|
+
current,
|
|
147
|
+
onOpen
|
|
148
|
+
}) {
|
|
149
|
+
useLocaleRevision();
|
|
150
|
+
const copy = _jsxs(_Fragment, {
|
|
151
|
+
children: [_jsx(MdbaseAppMark, {
|
|
152
|
+
app: app.id,
|
|
153
|
+
className: "mdbase-app-menu-mark"
|
|
154
|
+
}), _jsxs("span", {
|
|
155
|
+
className: "mdbase-menu-copy",
|
|
156
|
+
children: [_jsx("strong", {
|
|
157
|
+
children: app.name
|
|
158
|
+
}), _jsx("small", {
|
|
159
|
+
children: app.description
|
|
160
|
+
})]
|
|
161
|
+
})]
|
|
162
|
+
});
|
|
163
|
+
if (current) {
|
|
164
|
+
return _jsxs("div", {
|
|
165
|
+
className: "mdbase-menu-item is-current",
|
|
166
|
+
role: "menuitem",
|
|
167
|
+
"aria-current": "page",
|
|
168
|
+
"aria-disabled": "true",
|
|
169
|
+
tabIndex: -1,
|
|
170
|
+
children: [copy, _jsx("span", {
|
|
171
|
+
className: "mdbase-app-menu-current",
|
|
172
|
+
children: _i18n._(
|
|
173
|
+
/** i18n */
|
|
174
|
+
{
|
|
175
|
+
id: "Hp1l6f",
|
|
176
|
+
message: "Current"
|
|
177
|
+
})
|
|
178
|
+
})]
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return _jsxs("a", {
|
|
182
|
+
className: "mdbase-menu-item",
|
|
183
|
+
role: "menuitem",
|
|
184
|
+
href: mdbaseAppHref(app.url, location.href),
|
|
185
|
+
target: "_blank",
|
|
186
|
+
rel: "noopener",
|
|
187
|
+
onClick: onOpen,
|
|
188
|
+
children: [copy, _jsx("svg", {
|
|
189
|
+
className: "mdbase-app-menu-external",
|
|
190
|
+
viewBox: "0 0 24 24",
|
|
191
|
+
"aria-hidden": "true",
|
|
192
|
+
children: _jsx("path", {
|
|
193
|
+
d: "M10 5.5H5.5v13h13V14M13.5 5.5h5v5M18.5 5.5 11 13"
|
|
194
|
+
})
|
|
195
|
+
}), _jsxs("span", {
|
|
196
|
+
className: "mdbase-visually-hidden",
|
|
197
|
+
children: [" ", _i18n._(
|
|
198
|
+
/** i18n */
|
|
199
|
+
{
|
|
200
|
+
id: "75iTY6",
|
|
201
|
+
message: "(opens in a new tab)"
|
|
202
|
+
})]
|
|
203
|
+
})]
|
|
204
|
+
});
|
|
51
205
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { InputHTMLAttributes, JSX, ReactNode } from "react";
|
|
2
|
+
type InputAttributes = Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "className" | "children">;
|
|
3
|
+
/** A native checkbox and its text in one label: the row is the 44px target,
|
|
4
|
+
* the box keeps its own size. */
|
|
5
|
+
export declare function Checkbox({ children, ...input }: InputAttributes & {
|
|
6
|
+
readonly children: ReactNode;
|
|
7
|
+
}): JSX.Element;
|
|
8
|
+
/** Related checkboxes under a legend, without the browser's fieldset outline. */
|
|
9
|
+
export declare function CheckboxGroup({ legend, disabled, children }: {
|
|
10
|
+
readonly legend: ReactNode;
|
|
11
|
+
readonly disabled?: boolean | undefined;
|
|
12
|
+
readonly children: ReactNode;
|
|
13
|
+
}): JSX.Element;
|
|
14
|
+
export {};
|
package/dist/Checkbox.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/** A native checkbox and its text in one label: the row is the 44px target,
|
|
3
|
+
* the box keeps its own size. */
|
|
4
|
+
export function Checkbox({
|
|
5
|
+
children,
|
|
6
|
+
...input
|
|
7
|
+
}) {
|
|
8
|
+
return _jsxs("label", {
|
|
9
|
+
className: "mdbase-check",
|
|
10
|
+
children: [_jsx("input", {
|
|
11
|
+
...input,
|
|
12
|
+
type: "checkbox",
|
|
13
|
+
className: "mdbase-checkbox"
|
|
14
|
+
}), _jsx("span", {
|
|
15
|
+
children: children
|
|
16
|
+
})]
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
/** Related checkboxes under a legend, without the browser's fieldset outline. */
|
|
20
|
+
export function CheckboxGroup({
|
|
21
|
+
legend,
|
|
22
|
+
disabled,
|
|
23
|
+
children
|
|
24
|
+
}) {
|
|
25
|
+
return _jsxs("fieldset", {
|
|
26
|
+
className: "mdbase-check-group",
|
|
27
|
+
disabled: disabled,
|
|
28
|
+
children: [_jsx("legend", {
|
|
29
|
+
children: legend
|
|
30
|
+
}), children]
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type Mode = "private" | "cloud_copy";
|
|
2
|
+
/** Owner controls only. Visibility follows actual executor registration, not a
|
|
3
|
+
* mode flag. Browser intent cannot produce native key/source consent. */
|
|
4
|
+
export declare function CollectionModeControl({ collectionId, load, change, cancel, native }: {
|
|
5
|
+
collectionId: string;
|
|
6
|
+
load(): Promise<unknown>;
|
|
7
|
+
change(target: Mode, requestId: string): Promise<unknown>;
|
|
8
|
+
native?: boolean;
|
|
9
|
+
cancel?(target: Mode, requestId: string): Promise<unknown>;
|
|
10
|
+
}): import("react").JSX.Element | null;
|
|
11
|
+
export {};
|