@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.
Files changed (74) hide show
  1. package/README.md +168 -0
  2. package/css/collections.css +978 -0
  3. package/css/controls.css +33 -1
  4. package/css/screens.css +44 -2
  5. package/dist/AppSwitcher.js +187 -33
  6. package/dist/Checkbox.d.ts +14 -0
  7. package/dist/Checkbox.js +32 -0
  8. package/dist/CollectionModeControl.d.ts +11 -0
  9. package/dist/CollectionModeControl.js +290 -0
  10. package/dist/CommandPalette.d.ts +4 -2
  11. package/dist/CommandPalette.js +275 -103
  12. package/dist/Dialog.js +72 -25
  13. package/dist/Feedback.js +763 -229
  14. package/dist/FeedbackMarkup.d.ts +1 -1
  15. package/dist/FeedbackMarkup.js +326 -125
  16. package/dist/FeedbackVerification.js +115 -68
  17. package/dist/SaveNotice.js +71 -28
  18. package/dist/Select.js +183 -135
  19. package/dist/SelectList.js +59 -14
  20. package/dist/ThemeSelect.js +55 -4
  21. package/dist/apps.d.ts +1 -0
  22. package/dist/apps.js +50 -29
  23. package/dist/brand.js +251 -68
  24. package/dist/codemirror.js +116 -87
  25. package/dist/collections/CollectionGate.d.ts +52 -0
  26. package/dist/collections/CollectionGate.js +456 -0
  27. package/dist/collections/CollectionSaveWarning.d.ts +10 -0
  28. package/dist/collections/CollectionSaveWarning.js +28 -0
  29. package/dist/collections/CollectionSwitcher.d.ts +51 -0
  30. package/dist/collections/CollectionSwitcher.js +598 -0
  31. package/dist/collections/SetupReview.d.ts +9 -0
  32. package/dist/collections/SetupReview.js +216 -0
  33. package/dist/collections/copy.d.ts +100 -0
  34. package/dist/collections/copy.js +937 -0
  35. package/dist/collections/dialogs.d.ts +27 -0
  36. package/dist/collections/dialogs.js +169 -0
  37. package/dist/collections/model.d.ts +146 -0
  38. package/dist/collections/model.js +337 -0
  39. package/dist/collections/mount.d.ts +19 -0
  40. package/dist/collections/mount.js +56 -0
  41. package/dist/collections/parts.d.ts +86 -0
  42. package/dist/collections/parts.js +439 -0
  43. package/dist/collections/testing.d.ts +19 -0
  44. package/dist/collections/testing.js +39 -0
  45. package/dist/collections/use-collection-ui.d.ts +140 -0
  46. package/dist/collections/use-collection-ui.js +236 -0
  47. package/dist/collections.d.ts +19 -0
  48. package/dist/collections.js +13 -0
  49. package/dist/feedback-data.d.ts +13 -12
  50. package/dist/feedback-data.js +365 -168
  51. package/dist/flock.d.ts +63 -0
  52. package/dist/flock.js +140 -0
  53. package/dist/i18n.d.ts +6 -0
  54. package/dist/i18n.js +71 -0
  55. package/dist/locales/de/messages.json +1 -0
  56. package/dist/locales/en/messages.json +1 -0
  57. package/dist/locales/es/messages.json +1 -0
  58. package/dist/locales/fr/messages.json +1 -0
  59. package/dist/locales/it/messages.json +1 -0
  60. package/dist/locales/ja/messages.json +1 -0
  61. package/dist/locales/ko/messages.json +1 -0
  62. package/dist/locales/pt/messages.json +1 -0
  63. package/dist/locales/ru/messages.json +1 -0
  64. package/dist/locales/zh/messages.json +1 -0
  65. package/dist/mark-activity.js +82 -75
  66. package/dist/permission-selection.js +27 -17
  67. package/dist/popover.js +138 -130
  68. package/dist/screens.d.ts +20 -3
  69. package/dist/screens.js +275 -6
  70. package/dist/select-model.js +34 -28
  71. package/dist/text-diff.d.ts +1 -0
  72. package/dist/text-diff.js +106 -74
  73. package/dist/theme.js +34 -40
  74. package/package.json +56 -7
package/README.md CHANGED
@@ -36,6 +36,174 @@ 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
+ - Pass `open` and `onOpenChange` to control the switcher; `onOpenChange` is
106
+ called for every open and close it makes itself, controlled or not.
107
+ `variant="none"` renders no trigger, for an app that opens the switcher from
108
+ its own control, such as an item in an overflow menu. It requires
109
+ `anchorRef`, an element that stays mounted while the switcher is open (the
110
+ menu's button, say): the popover is placed against it, and focus returns to
111
+ it when the switcher or a row dialog opened from it closes. Close your menu
112
+ without moving focus back to that button; the switcher takes focus as it
113
+ opens.
114
+ - `rowDetail(row)` adds a second line to each collection row, such as where it
115
+ lives or which account it belongs to. `row.entry` is the SDK's entry.
116
+ - `sections` lists collections the app knows about and the SDK doesn't (local
117
+ or private ones). Each section is `{ id, title, items, onSelect, onClose?,
118
+ empty? }`, and each item is `{ id, name, detail?, current?, disabled? }`.
119
+ Sections appear after "Your collections" on the gate's choosing and
120
+ signed-out screens and in the switcher. Selecting an item asks
121
+ `onBeforeLeave("switch")` when something is open, closes any other open
122
+ item, then calls `onSelect` from the click. Mark the open item `current`.
123
+ The gate then renders `renderAppCollection(item, { section, chooseAnother })`
124
+ instead of its screens, and `chooseAnother()` (or "Choose a different
125
+ collection" in the switcher) calls `onClose` to return to the list. Choosing
126
+ an SDK collection also calls `onClose` first.
127
+ - A section item's `actions` fill its row menu, the same "…" menu SDK
128
+ collections have: `{ id, label, onSelect(item, context), danger?, disabled? }`.
129
+ `danger` actions show in the danger colour; confirm before acting.
130
+ `context.confirmDelete(onClose?)` opens `DeleteCollectionDialog` for the
131
+ item (the person types its name; the SDK deletes it by the item's `id`), and
132
+ `onClose(outcome)` reports how it ended:
133
+
134
+ ```tsx
135
+ actions: isOwner ? [{ id: "delete", label: "Delete collection…", danger: true,
136
+ onSelect: (_item, { confirmDelete }) => confirmDelete((outcome) => { if (outcome === "deleted") reload(); }) }] : []
137
+ ```
138
+ - `CollectionPanel` combines the gate screens with the switcher list, for
139
+ settings dialogs. `CollectionProblem` shows one problem with its fix, either
140
+ the current one or an error the app passes in.
141
+ - `onBeforeLeave(intent)` lets the app confirm before a switch, an add, choosing
142
+ another collection or signing out. Return `true` or a promise. The Connect
143
+ window opens straight after it, with no other await in between.
144
+ - `allowDelete` enables "Delete collection…" for owners. `copy` overrides
145
+ strings from `defaultCollectionCopy`. `DeleteCollectionDialog`'s
146
+ `onClose(outcome)` reports `"deleted"`, `"cancelled"` (closed without trying)
147
+ or `"failed"` (closed after a refused delete).
148
+ - `collectionView(snapshot)` is the headless model behind the components:
149
+ heading, rows and a notice with its control.
150
+ - Hosts that don't use React call
151
+ `mountCollectionUi(element, { part: "panel" | "switcher" | "problem", ...options })`,
152
+ which returns `{ update, unmount }`. React and react-dom must be installed.
153
+
154
+ ### Testing
155
+
156
+ The focus and popover code reads the global `window` and `document`, not the
157
+ rendered element's document. Test files that use a jsdom environment
158
+ (`// @vitest-environment jsdom`) already have them. A Node test that creates
159
+ its own window has to make it global before rendering:
160
+
161
+ ```ts
162
+ import { shareTestDocument } from "@mdbase-dev/ui/collections/testing";
163
+ import { JSDOM } from "jsdom";
164
+
165
+ const restore = shareTestDocument(new JSDOM("<!doctype html><body></body>").window);
166
+ afterAll(restore);
167
+ ```
168
+
169
+ ### Restyling
170
+
171
+ Map these properties anywhere up the tree (`:root` is fine) instead of
172
+ overriding internals. Each one falls back to the app-ui token, then to the
173
+ built-in value.
174
+
175
+ | Property (`--mdbase-collections-…`) | Used for | app-ui token | Built-in |
176
+ | --- | --- | --- | --- |
177
+ | `accent` | filled actions, focus, the current row | `--color-accent` | blue |
178
+ | `on-accent` | text on the accent | `--color-on-accent` | near white |
179
+ | `surface` | popovers, sheets, dialogs, rows | `--color-surface` | near white |
180
+ | `canvas` | the gate page background | `--color-canvas` | near white |
181
+ | `text` | primary text | `--color-text` | near black |
182
+ | `text-soft` | secondary text | `--color-text-soft` | grey |
183
+ | `border` | hairlines | `--color-border-strong` | light grey |
184
+ | `danger` | errors and destructive actions | `--color-danger` | red |
185
+ | `warning` | warning text | `--color-warning-text` | amber |
186
+ | `warning-edge` | the warning notice's edge | `--color-warning` | amber |
187
+ | `scrim` | behind dialogs and sheets | `--color-scrim` | `rgb(0 0 0 / 0.3)` |
188
+ | `current-bg` | the open collection's row | (none) | accent 9% into surface, mixed in oklab |
189
+ | `font` | font family | `--sans` | `system-ui, sans-serif` |
190
+ | `font-size` | body text | `--font-size-ui` | `0.8125rem` |
191
+ | `font-size-caption` | row details, chips, labels | `--font-size-caption` | `0.75rem` |
192
+ | `font-size-section` | leads, panel headings | `--font-size-section` | `0.9375rem` |
193
+ | `font-size-heading` | the gate heading | `--font-size-heading` | `1.5rem` |
194
+ | `font-weight-strong` | names, headings, buttons | `--font-weight-semibold` | `600` |
195
+ | `radius-sm` | rows, buttons, fields | `--radius-sm` | `4px` |
196
+ | `radius` | lists and cards | `--radius-md` | `8px` |
197
+ | `radius-lg` | popovers, dialogs, sheets | `--radius-lg` | `12px` |
198
+ | `elevation-low` | menus | `--elevation-low` | soft shadow |
199
+ | `elevation-high` | popovers and dialogs | `--elevation-high` | deeper shadow |
200
+ | `control-height` | button and row height | (none) | `36px`, `44px` on touch |
201
+
202
+ Motion reads `--ease-standard`, `--motion-quick` and `--motion-spin`
203
+ (`150ms` and `700ms` built in), and reduced motion slows the spinner. The
204
+ built-in colours are light-theme values: an app with a dark theme and no
205
+ `tokens.css` maps the colour properties.
206
+
39
207
  ## Shared feedback
40
208
 
41
209
  Import `@mdbase-dev/ui/feedback` and `@mdbase-dev/ui/feedback.css`, alongside