@mdbase-dev/ui 0.1.0-beta.125 → 0.1.0-beta.147

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.
Files changed (77) hide show
  1. package/README.md +159 -0
  2. package/css/brand.css +10 -10
  3. package/css/collections.css +978 -0
  4. package/css/controls.css +220 -43
  5. package/css/feedback.css +20 -20
  6. package/css/fonts.css +2 -3
  7. package/css/palette.css +10 -10
  8. package/css/screens.css +58 -16
  9. package/css/tokens.css +43 -3
  10. package/dist/AppSwitcher.js +187 -33
  11. package/dist/Checkbox.d.ts +14 -0
  12. package/dist/Checkbox.js +32 -0
  13. package/dist/CommandPalette.d.ts +4 -2
  14. package/dist/CommandPalette.js +275 -103
  15. package/dist/Dialog.js +72 -25
  16. package/dist/Feedback.js +763 -229
  17. package/dist/FeedbackMarkup.d.ts +1 -1
  18. package/dist/FeedbackMarkup.js +326 -125
  19. package/dist/FeedbackVerification.js +115 -68
  20. package/dist/SaveNotice.js +71 -28
  21. package/dist/Select.js +183 -135
  22. package/dist/SelectList.js +59 -14
  23. package/dist/ThemeSelect.js +55 -4
  24. package/dist/apps.d.ts +1 -0
  25. package/dist/apps.js +50 -29
  26. package/dist/brand.js +251 -68
  27. package/dist/codemirror.js +116 -87
  28. package/dist/collections/CollectionGate.d.ts +52 -0
  29. package/dist/collections/CollectionGate.js +456 -0
  30. package/dist/collections/CollectionSaveWarning.d.ts +10 -0
  31. package/dist/collections/CollectionSaveWarning.js +28 -0
  32. package/dist/collections/CollectionSwitcher.d.ts +26 -0
  33. package/dist/collections/CollectionSwitcher.js +579 -0
  34. package/dist/collections/SetupReview.d.ts +9 -0
  35. package/dist/collections/SetupReview.js +175 -0
  36. package/dist/collections/copy.d.ts +100 -0
  37. package/dist/collections/copy.js +937 -0
  38. package/dist/collections/dialogs.d.ts +27 -0
  39. package/dist/collections/dialogs.js +169 -0
  40. package/dist/collections/model.d.ts +146 -0
  41. package/dist/collections/model.js +337 -0
  42. package/dist/collections/mount.d.ts +18 -0
  43. package/dist/collections/mount.js +56 -0
  44. package/dist/collections/parts.d.ts +86 -0
  45. package/dist/collections/parts.js +439 -0
  46. package/dist/collections/testing.d.ts +19 -0
  47. package/dist/collections/testing.js +39 -0
  48. package/dist/collections/use-collection-ui.d.ts +140 -0
  49. package/dist/collections/use-collection-ui.js +236 -0
  50. package/dist/collections.d.ts +19 -0
  51. package/dist/collections.js +13 -0
  52. package/dist/feedback-data.d.ts +13 -12
  53. package/dist/feedback-data.js +365 -168
  54. package/dist/flock.d.ts +63 -0
  55. package/dist/flock.js +140 -0
  56. package/dist/i18n.d.ts +6 -0
  57. package/dist/i18n.js +71 -0
  58. package/dist/locales/de/messages.json +1 -0
  59. package/dist/locales/en/messages.json +1 -0
  60. package/dist/locales/es/messages.json +1 -0
  61. package/dist/locales/fr/messages.json +1 -0
  62. package/dist/locales/it/messages.json +1 -0
  63. package/dist/locales/ja/messages.json +1 -0
  64. package/dist/locales/ko/messages.json +1 -0
  65. package/dist/locales/pt/messages.json +1 -0
  66. package/dist/locales/ru/messages.json +1 -0
  67. package/dist/locales/zh/messages.json +1 -0
  68. package/dist/mark-activity.js +82 -75
  69. package/dist/permission-selection.js +27 -17
  70. package/dist/popover.js +138 -130
  71. package/dist/screens.d.ts +20 -3
  72. package/dist/screens.js +275 -6
  73. package/dist/select-model.js +34 -28
  74. package/dist/text-diff.d.ts +1 -0
  75. package/dist/text-diff.js +106 -74
  76. package/dist/theme.js +34 -40
  77. package/package.json +53 -8
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;
@@ -25,38 +31,74 @@
25
31
 
26
32
  .mdbase-opening-message p {
27
33
  max-width: 44ch;
28
- font-size: 13px;
34
+ font-size: var(--font-size-ui);
29
35
  }
30
36
 
31
37
  .mdbase-opening-message small {
32
38
  margin-top: 4px;
33
39
  color: var(--color-text-muted);
34
- font-size: 11px;
40
+ font-size: var(--font-size-caption);
35
41
  }
36
42
 
37
43
  .mdbase-opening[data-loading-state="failed"] .mdbase-opening-message p {
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: 32px;
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 {
56
98
  margin: 44px 0 22px;
57
99
  color: var(--color-text);
58
- font-size: 48px;
59
- font-weight: 700;
100
+ font-size: var(--font-size-title);
101
+ font-weight: var(--font-weight-semibold);
60
102
  line-height: 0.98;
61
103
  letter-spacing: -0.045em;
62
104
  }
@@ -65,14 +107,14 @@
65
107
  max-width: 34ch;
66
108
  margin: 0;
67
109
  color: var(--color-text-soft);
68
- font-size: 17px;
110
+ font-size: var(--font-size-prose);
69
111
  line-height: 1.55;
70
112
  }
71
113
 
72
114
  .mdbase-connect-status {
73
115
  margin: 14px 0 0;
74
116
  color: var(--color-text-muted);
75
- font-size: 13px;
117
+ font-size: var(--font-size-ui);
76
118
  }
77
119
 
78
120
  /* The one strong action on the screen. */
@@ -88,10 +130,10 @@
88
130
  color: var(--color-text);
89
131
  background: var(--color-surface);
90
132
  font: inherit;
91
- font-size: 14px;
92
- font-weight: 700;
133
+ font-size: var(--font-size-ui);
134
+ font-weight: var(--font-weight-semibold);
93
135
  cursor: pointer;
94
- transition: border-color var(--motion-quick) ease, background var(--motion-quick) ease;
136
+ transition: border-color var(--motion-quick) var(--ease-standard), background var(--motion-quick) var(--ease-standard);
95
137
  }
96
138
 
97
139
  .mdbase-connect-action:hover:not(:disabled) {
@@ -113,28 +155,28 @@
113
155
  max-width: 47ch;
114
156
  margin: 18px 0 0;
115
157
  color: var(--color-text-muted);
116
- font-size: 12px;
158
+ font-size: var(--font-size-caption);
117
159
  line-height: 1.55;
118
160
  }
119
161
 
120
162
  .mdbase-connect-error {
121
163
  margin: 18px 0 0;
122
164
  color: var(--color-danger);
123
- font-size: 13px;
165
+ font-size: var(--font-size-ui);
124
166
  line-height: 1.45;
125
167
  }
126
168
 
127
169
  .mdbase-connect-detail {
128
170
  margin-top: 10px;
129
171
  color: var(--color-text-muted);
130
- font-size: 12px;
172
+ font-size: var(--font-size-caption);
131
173
  }
132
174
 
133
175
  .mdbase-connect-detail code {
134
176
  display: block;
135
177
  margin-top: 6px;
136
178
  font-family: var(--mono);
137
- font-size: 11px;
179
+ font-size: var(--font-size-caption);
138
180
  overflow-wrap: anywhere;
139
181
  }
140
182
 
@@ -150,6 +192,6 @@
150
192
 
151
193
  .mdbase-connect-screen h1 {
152
194
  margin-top: 48px;
153
- font-size: 43px;
195
+ font-size: var(--font-size-title);
154
196
  }
155
197
  }
package/css/tokens.css CHANGED
@@ -44,16 +44,56 @@
44
44
  --app-editor: #005c88;
45
45
  --app-reader: #a4467f;
46
46
  --app-writer: #d55e00;
47
- --sans: "Atkinson Hyperlegible", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
47
+ --sans: "Atkinson Hyperlegible Next Variable", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
48
48
  --mono: "Azeret Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
49
- /* Motion: popovers and small entrances are quick and ease out; a settled
50
- confirmation holds, then fades away (see controls.css). */
49
+ /* Six steps: captions, UI chrome, section titles, prose, headings, document titles. */
50
+ --font-size-caption: 12px;
51
+ --font-size-ui: 13px;
52
+ --font-size-section: 15px;
53
+ --font-size-prose: 17px;
54
+ --font-size-heading: 24px;
55
+ --font-size-title: 34px;
56
+ --font-weight-regular: 400;
57
+ --font-weight-medium: 500;
58
+ --font-weight-semibold: 600;
59
+ --font-weight-bold: 700;
60
+ --radius-sm: 4px;
61
+ --radius-md: 8px;
62
+ --radius-lg: 12px;
63
+ --elevation-low: 0 4px 12px var(--color-shadow);
64
+ --elevation-high: 0 12px 32px var(--color-shadow);
65
+ --space-0: 0;
66
+ --space-1: 4px;
67
+ --space-2: 8px;
68
+ --space-3: 12px;
69
+ --space-4: 16px;
70
+ --space-6: 24px;
71
+ --space-8: 32px;
72
+ --space-12: 48px;
73
+ --space-16: 64px;
74
+ /* Transitions share durations and easing; settled confirmations hold then fade. */
51
75
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
76
+ --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
77
+ --motion-fast: 120ms;
52
78
  --motion-quick: 150ms;
53
79
  --motion-base: 180ms;
80
+ --motion-slow: 240ms;
81
+ --motion-spin: 700ms;
82
+ --motion-pulse: 1.1s;
54
83
  --motion-settle: 2.4s;
55
84
  }
56
85
 
86
+ @media (prefers-reduced-motion: reduce) {
87
+ :root {
88
+ --motion-fast: 0ms;
89
+ --motion-quick: 0ms;
90
+ --motion-base: 0ms;
91
+ --motion-slow: 0ms;
92
+ --motion-spin: 0ms;
93
+ --motion-pulse: 0ms;
94
+ }
95
+ }
96
+
57
97
  :root[data-theme="dark"] {
58
98
  color-scheme: dark;
59
99
  --color-canvas: oklch(17.5% 0.012 255);
@@ -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({ current, urls = {}, motion }) {
17
- const menuId = useId();
18
- const triggerRef = useRef(null);
19
- const [open, setOpen] = useState(false);
20
- const [entrance] = useState(() => {
21
- if (motion || entrancePlayed || typeof window === "undefined")
22
- return undefined;
23
- entrancePlayed = true;
24
- return "keys-first";
25
- });
26
- const activity = useMdbaseMarkActivity();
27
- const close = (refocus) => {
28
- setOpen(false);
29
- if (refocus)
30
- triggerRef.current?.focus();
31
- };
32
- return _jsxs(_Fragment, { children: [_jsxs("button", { ref: triggerRef, type: "button", className: "mdbase-app-switcher", "aria-label": `mdbase ${current}: open this collection in another app`, "aria-haspopup": "menu", "aria-expanded": open, "aria-controls": open ? menuId : undefined, title: "Open in another mdbase app", onClick: () => (open ? close(false) : setOpen(true)), onKeyDown: (event) => {
33
- if (!open && (event.key === "ArrowDown" || event.key === "ArrowUp")) {
34
- event.preventDefault();
35
- setOpen(true);
36
- }
37
- }, children: [_jsx(Wordmark, { app: current, motion: activity.busy ?? motion ?? entrance, signal: activity.signal, progress: activity.progress }), _jsx("svg", { className: "mdbase-app-switcher-chevron", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "m7 10 5 5 5-5" }) })] }), open ? _jsx(AppMenu, { id: menuId, apps: withAppUrls(urls), current: current, triggerRef: triggerRef, onClose: close }) : null] });
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({ id, apps, current, triggerRef, onClose }) {
40
- const menuRef = useRef(null);
41
- useMenuPopover(menuRef, triggerRef, onClose, { width: 320, focus: 'a[role="menuitem"]' });
42
- const heading = new URL(location.href).searchParams.has("collection") ? "Open this collection in" : "mdbase apps";
43
- return _jsxs("div", { ref: menuRef, id: id, className: "mdbase-menu", popover: "manual", role: "menu", "aria-label": heading, tabIndex: -1, onKeyDown: (event) => moveMenuFocus(event, menuRef.current), children: [_jsx("div", { className: "mdbase-menu-heading", role: "presentation", children: heading }), _jsx("div", { className: "mdbase-menu-list", children: apps.map((app) => _jsx(AppItem, { app: app, current: app.id === current, onOpen: () => onClose(false) }, app.id)) }), _jsx("p", { className: "mdbase-menu-note", children: "Opens in a new tab" })] });
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({ app, current, onOpen }) {
46
- const copy = _jsxs(_Fragment, { children: [_jsx(MdbaseAppMark, { app: app.id, className: "mdbase-app-menu-mark" }), _jsxs("span", { className: "mdbase-menu-copy", children: [_jsx("strong", { children: app.name }), _jsx("small", { children: app.description })] })] });
47
- if (current) {
48
- return _jsxs("div", { className: "mdbase-menu-item is-current", role: "menuitem", "aria-current": "page", "aria-disabled": "true", tabIndex: -1, children: [copy, _jsx("span", { className: "mdbase-app-menu-current", children: "Current" })] });
49
- }
50
- return _jsxs("a", { className: "mdbase-menu-item", role: "menuitem", href: mdbaseAppHref(app.url, location.href), target: "_blank", rel: "noopener", onClick: onOpen, children: [copy, _jsx("svg", { className: "mdbase-app-menu-external", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "M10 5.5H5.5v13h13V14M13.5 5.5h5v5M18.5 5.5 11 13" }) }), _jsx("span", { className: "mdbase-visually-hidden", children: " (opens in a new tab)" })] });
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 {};
@@ -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
+ }
@@ -3,7 +3,7 @@ export interface Command {
3
3
  readonly id: string;
4
4
  readonly label: string;
5
5
  readonly detail?: string | undefined;
6
- /** Commands show under their group's heading, in the order the groups first appear. */
6
+ /** Stable group ID; headings follow first appearance and may be presented by groupLabel. */
7
7
  readonly group: string;
8
8
  readonly keywords?: string | undefined;
9
9
  /** For example "mod+shift+f"; see shortcutLabel. */
@@ -27,11 +27,13 @@ export declare function matchingCommands(commands: readonly Command[], query: st
27
27
  * Find or run anything: every mdbase app opens it with Mod+K. Typing filters commands; the
28
28
  * arrows move, Enter runs, Shift+Enter runs a command's alternate, Escape closes.
29
29
  */
30
- export declare function CommandPalette({ open, commands, onClose, label, placeholder, showAll }: {
30
+ export declare function CommandPalette({ open, commands, onClose, label, placeholder, showAll, groupLabel }: {
31
31
  readonly open: boolean;
32
32
  readonly commands: readonly Command[];
33
33
  readonly onClose: () => void;
34
34
  readonly label?: string | undefined;
35
35
  readonly placeholder?: string | undefined;
36
36
  readonly showAll?: readonly string[] | undefined;
37
+ /** Presentation only: translate headings without changing group or showAll IDs. */
38
+ readonly groupLabel?: ((group: string) => string) | undefined;
37
39
  }): JSX.Element | null;