@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.
- package/README.md +159 -0
- package/css/brand.css +10 -10
- package/css/collections.css +978 -0
- package/css/controls.css +220 -43
- package/css/feedback.css +20 -20
- package/css/fonts.css +2 -3
- package/css/palette.css +10 -10
- package/css/screens.css +58 -16
- package/css/tokens.css +43 -3
- package/dist/AppSwitcher.js +187 -33
- package/dist/Checkbox.d.ts +14 -0
- package/dist/Checkbox.js +32 -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 +26 -0
- package/dist/collections/CollectionSwitcher.js +579 -0
- package/dist/collections/SetupReview.d.ts +9 -0
- package/dist/collections/SetupReview.js +175 -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 +18 -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 +53 -8
package/README.md
CHANGED
|
@@ -36,6 +36,165 @@ applyThemePreference(loadThemePreference());
|
|
|
36
36
|
collection in another app. Lab and local builds pass their own URLs to
|
|
37
37
|
`withAppUrls`.
|
|
38
38
|
|
|
39
|
+
## Languages
|
|
40
|
+
|
|
41
|
+
The `/i18n` entry exports `uiCatalogues: CatalogueSource` with synchronous
|
|
42
|
+
English and lazy local-deployment JSON for `fr de es ja ko pt ru zh`.
|
|
43
|
+
Compose it once with the app's catalogue using `@mdbase-dev/i18n`:
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { i18n, uiCatalogues } from "@mdbase-dev/ui/i18n";
|
|
47
|
+
const runtime = createI18nRuntime({ i18n, english: appEnglish, loadLocale, libraries: [uiCatalogues] });
|
|
48
|
+
// Wrap the app once in LocaleProvider with this runtime.
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Core-macro presentation helpers use the shared Lingui singleton; do not compose
|
|
52
|
+
into an unrelated isolated instance. Keep React and Lingui deduplicated in app
|
|
53
|
+
bundlers. No form is remounted on a locale switch. Build output includes all
|
|
54
|
+
ten catalogues and transformed macros; consumers do not compile library source.
|
|
55
|
+
PO files are the only authoring format. Builds use the kit CLI to prune obsolete PO
|
|
56
|
+
entries before compilation, including English fallback; `prepack` runs strict catalogue
|
|
57
|
+
checks and rebuilds so stale compiled messages cannot enter a fresh tarball.
|
|
58
|
+
Run strict `i18n:check` before release: a fallback-capable development build does
|
|
59
|
+
not prove a language is complete.
|
|
60
|
+
Reviewed identical terms are Esc/ID, the literal example email, and French
|
|
61
|
+
Collection/Collections (allowlisted per generated ID).
|
|
62
|
+
|
|
63
|
+
## Command palette
|
|
64
|
+
|
|
65
|
+
`CommandPalette` from `@mdbase-dev/ui/command-palette` accepts an optional
|
|
66
|
+
`groupLabel(groupId: string): string` callback for localized group headings.
|
|
67
|
+
For example, pass `groupLabel={readerCommandGroupLabel}`. Without it, the heading
|
|
68
|
+
remains the command's `group` string. This is presentation only: keep `Command.group`
|
|
69
|
+
and `showAll` values as stable IDs. Group order, browsing limits and search matching
|
|
70
|
+
still use those IDs; translated headings do not change matching or merge groups.
|
|
71
|
+
Re-render with the current locale's callback to update the presentation.
|
|
72
|
+
|
|
73
|
+
## Collections
|
|
74
|
+
|
|
75
|
+
Import `@mdbase-dev/ui/collections` and `@mdbase-dev/ui/collections.css`.
|
|
76
|
+
`tokens.css` is optional: without it every value falls back to a built-in one.
|
|
77
|
+
Every component takes the SDK front door from `createMdbase` (an optional peer
|
|
78
|
+
dependency) and `app: { name, mark? }`.
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { CollectionGate, CollectionSwitcher } from "@mdbase-dev/ui/collections";
|
|
82
|
+
import "@mdbase-dev/ui/collections.css";
|
|
83
|
+
|
|
84
|
+
<CollectionGate mdbase={mdbase} app={{ name: "Reader" }} extraActions={<TrySample />}>
|
|
85
|
+
{(connection) => <Shell header={<CollectionSwitcher mdbase={mdbase} app={app} />} />}
|
|
86
|
+
</CollectionGate>;
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
- `CollectionGate` covers sign-in, choosing, approval, setup review and
|
|
90
|
+
problems, and renders its children once the phase is `ready`. A live problem
|
|
91
|
+
then shows as a banner above them. `layout="panel"` fits inside a shell or a
|
|
92
|
+
dialog.
|
|
93
|
+
- The gate calls `mdbase.start()` itself while the front door hasn't started
|
|
94
|
+
(`autoStart`, default `true`). It makes one call however many gates render,
|
|
95
|
+
and none once the app has started it, so apps can drop their own `start()`.
|
|
96
|
+
Pass `autoStart={false}` to start it yourself. `CollectionPanel` does the same.
|
|
97
|
+
- `extraActions` holds the app's own actions. On the signed-out screen they sit
|
|
98
|
+
beside Sign in. On every other gate screen they lead the footer, never under
|
|
99
|
+
a problem. Pass a function `(view) => node` to vary them by `view.kind`, or
|
|
100
|
+
return `null` to hide them.
|
|
101
|
+
- `CollectionSwitcher` (`variant` `full`, `compact` or `icon`) is the header
|
|
102
|
+
switcher: a popover, and a bottom sheet below 640px. `icon` puts the app's
|
|
103
|
+
icon before the name, or `icon="mark"` the open collection's initials. In
|
|
104
|
+
the `icon` variant it replaces the folder glyph.
|
|
105
|
+
- `rowDetail(row)` adds a second line to each collection row, such as where it
|
|
106
|
+
lives or which account it belongs to. `row.entry` is the SDK's entry.
|
|
107
|
+
- `sections` lists collections the app knows about and the SDK doesn't (local
|
|
108
|
+
or private ones). Each section is `{ id, title, items, onSelect, onClose?,
|
|
109
|
+
empty? }`, and each item is `{ id, name, detail?, current?, disabled? }`.
|
|
110
|
+
Sections appear after "Your collections" on the gate's choosing and
|
|
111
|
+
signed-out screens and in the switcher. Selecting an item asks
|
|
112
|
+
`onBeforeLeave("switch")` when something is open, closes any other open
|
|
113
|
+
item, then calls `onSelect` from the click. Mark the open item `current`.
|
|
114
|
+
The gate then renders `renderAppCollection(item, { section, chooseAnother })`
|
|
115
|
+
instead of its screens, and `chooseAnother()` (or "Choose a different
|
|
116
|
+
collection" in the switcher) calls `onClose` to return to the list. Choosing
|
|
117
|
+
an SDK collection also calls `onClose` first.
|
|
118
|
+
- A section item's `actions` fill its row menu, the same "…" menu SDK
|
|
119
|
+
collections have: `{ id, label, onSelect(item, context), danger?, disabled? }`.
|
|
120
|
+
`danger` actions show in the danger colour; confirm before acting.
|
|
121
|
+
`context.confirmDelete(onClose?)` opens `DeleteCollectionDialog` for the
|
|
122
|
+
item (the person types its name; the SDK deletes it by the item's `id`), and
|
|
123
|
+
`onClose(outcome)` reports how it ended:
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
actions: isOwner ? [{ id: "delete", label: "Delete collection…", danger: true,
|
|
127
|
+
onSelect: (_item, { confirmDelete }) => confirmDelete((outcome) => { if (outcome === "deleted") reload(); }) }] : []
|
|
128
|
+
```
|
|
129
|
+
- `CollectionPanel` combines the gate screens with the switcher list, for
|
|
130
|
+
settings dialogs. `CollectionProblem` shows one problem with its fix, either
|
|
131
|
+
the current one or an error the app passes in.
|
|
132
|
+
- `onBeforeLeave(intent)` lets the app confirm before a switch, an add, choosing
|
|
133
|
+
another collection or signing out. Return `true` or a promise. The Connect
|
|
134
|
+
window opens straight after it, with no other await in between.
|
|
135
|
+
- `allowDelete` enables "Delete collection…" for owners. `copy` overrides
|
|
136
|
+
strings from `defaultCollectionCopy`. `DeleteCollectionDialog`'s
|
|
137
|
+
`onClose(outcome)` reports `"deleted"`, `"cancelled"` (closed without trying)
|
|
138
|
+
or `"failed"` (closed after a refused delete).
|
|
139
|
+
- `collectionView(snapshot)` is the headless model behind the components:
|
|
140
|
+
heading, rows and a notice with its control.
|
|
141
|
+
- Hosts that don't use React call
|
|
142
|
+
`mountCollectionUi(element, { part: "panel" | "switcher" | "problem", ...options })`,
|
|
143
|
+
which returns `{ update, unmount }`. React and react-dom must be installed.
|
|
144
|
+
|
|
145
|
+
### Testing
|
|
146
|
+
|
|
147
|
+
The focus and popover code reads the global `window` and `document`, not the
|
|
148
|
+
rendered element's document. Test files that use a jsdom environment
|
|
149
|
+
(`// @vitest-environment jsdom`) already have them. A Node test that creates
|
|
150
|
+
its own window has to make it global before rendering:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import { shareTestDocument } from "@mdbase-dev/ui/collections/testing";
|
|
154
|
+
import { JSDOM } from "jsdom";
|
|
155
|
+
|
|
156
|
+
const restore = shareTestDocument(new JSDOM("<!doctype html><body></body>").window);
|
|
157
|
+
afterAll(restore);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Restyling
|
|
161
|
+
|
|
162
|
+
Map these properties anywhere up the tree (`:root` is fine) instead of
|
|
163
|
+
overriding internals. Each one falls back to the app-ui token, then to the
|
|
164
|
+
built-in value.
|
|
165
|
+
|
|
166
|
+
| Property (`--mdbase-collections-…`) | Used for | app-ui token | Built-in |
|
|
167
|
+
| --- | --- | --- | --- |
|
|
168
|
+
| `accent` | filled actions, focus, the current row | `--color-accent` | blue |
|
|
169
|
+
| `on-accent` | text on the accent | `--color-on-accent` | near white |
|
|
170
|
+
| `surface` | popovers, sheets, dialogs, rows | `--color-surface` | near white |
|
|
171
|
+
| `canvas` | the gate page background | `--color-canvas` | near white |
|
|
172
|
+
| `text` | primary text | `--color-text` | near black |
|
|
173
|
+
| `text-soft` | secondary text | `--color-text-soft` | grey |
|
|
174
|
+
| `border` | hairlines | `--color-border-strong` | light grey |
|
|
175
|
+
| `danger` | errors and destructive actions | `--color-danger` | red |
|
|
176
|
+
| `warning` | warning text | `--color-warning-text` | amber |
|
|
177
|
+
| `warning-edge` | the warning notice's edge | `--color-warning` | amber |
|
|
178
|
+
| `scrim` | behind dialogs and sheets | `--color-scrim` | `rgb(0 0 0 / 0.3)` |
|
|
179
|
+
| `current-bg` | the open collection's row | (none) | accent 9% into surface, mixed in oklab |
|
|
180
|
+
| `font` | font family | `--sans` | `system-ui, sans-serif` |
|
|
181
|
+
| `font-size` | body text | `--font-size-ui` | `0.8125rem` |
|
|
182
|
+
| `font-size-caption` | row details, chips, labels | `--font-size-caption` | `0.75rem` |
|
|
183
|
+
| `font-size-section` | leads, panel headings | `--font-size-section` | `0.9375rem` |
|
|
184
|
+
| `font-size-heading` | the gate heading | `--font-size-heading` | `1.5rem` |
|
|
185
|
+
| `font-weight-strong` | names, headings, buttons | `--font-weight-semibold` | `600` |
|
|
186
|
+
| `radius-sm` | rows, buttons, fields | `--radius-sm` | `4px` |
|
|
187
|
+
| `radius` | lists and cards | `--radius-md` | `8px` |
|
|
188
|
+
| `radius-lg` | popovers, dialogs, sheets | `--radius-lg` | `12px` |
|
|
189
|
+
| `elevation-low` | menus | `--elevation-low` | soft shadow |
|
|
190
|
+
| `elevation-high` | popovers and dialogs | `--elevation-high` | deeper shadow |
|
|
191
|
+
| `control-height` | button and row height | (none) | `36px`, `44px` on touch |
|
|
192
|
+
|
|
193
|
+
Motion reads `--ease-standard`, `--motion-quick` and `--motion-spin`
|
|
194
|
+
(`150ms` and `700ms` built in), and reduced motion slows the spinner. The
|
|
195
|
+
built-in colours are light-theme values: an app with a dark theme and no
|
|
196
|
+
`tokens.css` maps the colour properties.
|
|
197
|
+
|
|
39
198
|
## Shared feedback
|
|
40
199
|
|
|
41
200
|
Import `@mdbase-dev/ui/feedback` and `@mdbase-dev/ui/feedback.css`, alongside
|
package/css/brand.css
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
.mdbase-mark .mdbase-mark-progress-fill {
|
|
41
|
-
transition: width
|
|
41
|
+
transition: width var(--motion-slow) var(--ease-out);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
gap: 8px;
|
|
54
54
|
color: var(--color-text);
|
|
55
55
|
font-family: var(--mono);
|
|
56
|
-
font-size:
|
|
57
|
-
font-weight:
|
|
56
|
+
font-size: var(--font-size-caption);
|
|
57
|
+
font-weight: var(--font-weight-medium);
|
|
58
58
|
line-height: 1;
|
|
59
59
|
letter-spacing: -0.02em;
|
|
60
60
|
}
|
|
@@ -72,19 +72,19 @@
|
|
|
72
72
|
gap: 0.65ch;
|
|
73
73
|
white-space: nowrap;
|
|
74
74
|
transition:
|
|
75
|
-
opacity
|
|
76
|
-
transform
|
|
77
|
-
display
|
|
75
|
+
opacity var(--motion-quick) var(--ease-out),
|
|
76
|
+
transform var(--motion-quick) var(--ease-out),
|
|
77
|
+
display var(--motion-quick) allow-discrete;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
.wordmark strong {
|
|
81
81
|
display: inline-block;
|
|
82
82
|
color: var(--color-text-muted);
|
|
83
|
-
font-weight:
|
|
83
|
+
font-weight: var(--font-weight-medium);
|
|
84
84
|
transition:
|
|
85
|
-
opacity
|
|
86
|
-
transform
|
|
87
|
-
display
|
|
85
|
+
opacity var(--motion-quick) var(--ease-out),
|
|
86
|
+
transform var(--motion-quick) var(--ease-out),
|
|
87
|
+
display var(--motion-quick) allow-discrete;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
@starting-style {
|