@protobase/ui 0.25.2 → 0.25.4

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 (271) hide show
  1. package/dist/account/account-pages.js +3 -2
  2. package/dist/account/account-section.js +1 -1
  3. package/dist/account/account-security-page.js +9 -4
  4. package/dist/account/backup-codes.js +7 -6
  5. package/dist/account/messages.js +214 -0
  6. package/dist/account/passkeys-section.js +23 -22
  7. package/dist/account/password-dialog.js +4 -3
  8. package/dist/account/sign-in-policy-form.js +14 -13
  9. package/dist/account/sign-in-policy-labels.js +30 -29
  10. package/dist/account/sign-in-policy-page.js +11 -6
  11. package/dist/account/sign-in-providers-section.js +6 -5
  12. package/dist/account/staff-sign-in-log.js +11 -10
  13. package/dist/account/totp-qr.js +2 -1
  14. package/dist/account/two-factor-section.js +24 -23
  15. package/dist/account/two-factor-setup.js +19 -18
  16. package/dist/action-card/action-card.js +2 -1
  17. package/dist/action-card/field-list.js +1 -1
  18. package/dist/action-card/messages.js +8 -0
  19. package/dist/activity-chart/activity-chart.js +3 -2
  20. package/dist/activity-chart/messages.js +14 -0
  21. package/dist/app/app.d.ts +1 -1
  22. package/dist/app/app.js +20 -21
  23. package/dist/app/assistant-shell.js +2 -1
  24. package/dist/app/batch-failure.js +2 -1
  25. package/dist/app/breadcrumb-for.js +4 -3
  26. package/dist/app/charts/chart-groups.js +3 -2
  27. package/dist/app/charts/chart-view.js +3 -2
  28. package/dist/app/charts/group-bars.js +2 -1
  29. package/dist/app/charts/messages.js +26 -0
  30. package/dist/app/charts/period-chart.js +3 -2
  31. package/dist/app/charts/split-points.js +2 -1
  32. package/dist/app/comments/comment-composer.js +19 -18
  33. package/dist/app/comments/comments-section.js +4 -3
  34. package/dist/app/comments/messages.js +26 -0
  35. package/dist/app/create/create-page.js +11 -18
  36. package/dist/app/custom-section.js +4 -6
  37. package/dist/app/displays/board-column.js +7 -6
  38. package/dist/app/displays/board-columns.js +3 -2
  39. package/dist/app/displays/board-display.js +13 -15
  40. package/dist/app/displays/calendar-controls.js +3 -2
  41. package/dist/app/displays/calendar-display.js +12 -17
  42. package/dist/app/displays/card-carousel.js +4 -3
  43. package/dist/app/displays/cards-display.js +2 -1
  44. package/dist/app/displays/custom-display.js +4 -6
  45. package/dist/app/displays/display-frame.js +3 -2
  46. package/dist/app/displays/list-cards.js +5 -8
  47. package/dist/app/displays/list-displays.js +3 -3
  48. package/dist/app/displays/map-display.js +15 -14
  49. package/dist/app/displays/messages.js +128 -2
  50. package/dist/app/displays/period-controls.js +4 -3
  51. package/dist/app/displays/record-card.js +7 -6
  52. package/dist/app/displays/timeline-display.js +17 -26
  53. package/dist/app/displays/timeline-range.js +2 -1
  54. package/dist/app/displays/timeline-row.js +1 -1
  55. package/dist/app/displays/use-board-move.js +2 -2
  56. package/dist/app/displays/use-calendar-move.js +2 -1
  57. package/dist/app/document-title.js +2 -1
  58. package/dist/app/error-banner.js +1 -1
  59. package/dist/app/export/builder-port.js +2 -1
  60. package/dist/app/export/export-dialog.js +39 -43
  61. package/dist/app/export/export-worker.js +2 -0
  62. package/dist/app/export/messages.js +78 -0
  63. package/dist/app/export/run-export.js +5 -2
  64. package/dist/app/export/sink.js +4 -3
  65. package/dist/app/export/use-export-flow.js +4 -3
  66. package/dist/app/field-editor.js +4 -3
  67. package/dist/app/field-types/messages.js +8 -0
  68. package/dist/app/field-types/widget-part.js +2 -1
  69. package/dist/app/file-field.js +11 -14
  70. package/dist/app/gallery/gallery-section.js +4 -3
  71. package/dist/app/gallery/lightbox.js +5 -4
  72. package/dist/app/gallery/messages.js +30 -0
  73. package/dist/app/gallery/photo-details.js +3 -2
  74. package/dist/app/hand-order/hand-sorted-list.js +3 -6
  75. package/dist/app/hand-order/messages.js +4 -2
  76. package/dist/app/history/describe-change.js +3 -8
  77. package/dist/app/history/messages.js +32 -0
  78. package/dist/app/import/convert.js +20 -19
  79. package/dist/app/import/failed-rows.js +3 -2
  80. package/dist/app/import/import-button.js +2 -1
  81. package/dist/app/import/import-check-step.js +21 -37
  82. package/dist/app/import/import-dialog.js +13 -17
  83. package/dist/app/import/import-file-step.js +5 -9
  84. package/dist/app/import/import-mapping-step.js +32 -35
  85. package/dist/app/import/import-result-step.js +13 -12
  86. package/dist/app/import/messages.js +200 -0
  87. package/dist/app/import/parse-worker.js +2 -0
  88. package/dist/app/import/prepare-rows.js +5 -4
  89. package/dist/app/import/sheet-cell.js +2 -1
  90. package/dist/app/import/sheet-file.js +3 -2
  91. package/dist/app/import/sheet-source.js +7 -3
  92. package/dist/app/import/xlsx-reader.js +4 -3
  93. package/dist/app/import/xlsx-xml.js +2 -1
  94. package/dist/app/import/zip-reader.js +4 -3
  95. package/dist/app/list-edit/use-list-edits.js +1 -1
  96. package/dist/app/list-group-chart.js +2 -1
  97. package/dist/app/list-page.js +1 -1
  98. package/dist/app/map/map-layer-switch.js +3 -2
  99. package/dist/app/map/messages.js +14 -0
  100. package/dist/app/messages.js +116 -2
  101. package/dist/app/meta-gate.js +1 -1
  102. package/dist/app/nav-from-meta.js +11 -10
  103. package/dist/app/pages/action-inputs/action-inputs-dialog.js +3 -2
  104. package/dist/app/pages/action-inputs/input-answers.js +6 -5
  105. package/dist/app/pages/blocks/card-row.js +3 -2
  106. package/dist/app/pages/blocks/field.js +1 -1
  107. package/dist/app/pages/blocks/modal-form.js +5 -4
  108. package/dist/app/pages/blocks/progress.js +1 -1
  109. package/dist/app/pages/blocks/record-card.js +3 -2
  110. package/dist/app/pages/blocks/stat.js +2 -1
  111. package/dist/app/pages/composed-page.js +6 -8
  112. package/dist/app/pages/confirm-action.js +2 -1
  113. package/dist/app/pages/custom-boundary.js +4 -2
  114. package/dist/app/pages/messages.js +64 -0
  115. package/dist/app/pages/render-node.js +5 -7
  116. package/dist/app/pages/use-run-action.js +11 -10
  117. package/dist/app/record-page.js +1 -1
  118. package/dist/app/record-row/messages.js +26 -0
  119. package/dist/app/record-row/record-row-body.js +12 -7
  120. package/dist/app/record-row/record-row.js +4 -3
  121. package/dist/app/record-row/saved-record-row.js +3 -2
  122. package/dist/app/related-dots/dots-summary.js +2 -1
  123. package/dist/app/related-dots/messages.js +8 -0
  124. package/dist/app/relation-picker.js +9 -8
  125. package/dist/app/router.js +5 -4
  126. package/dist/app/runtime/messages.js +58 -0
  127. package/dist/app/runtime/runtime-status.js +10 -23
  128. package/dist/app/runtime/runtime-update-dialog.js +7 -6
  129. package/dist/app/runtime/runtime-update.js +4 -3
  130. package/dist/app/saved/favorite-button.js +2 -1
  131. package/dist/app/saved/messages.js +22 -0
  132. package/dist/app/saved/saved-list.js +4 -7
  133. package/dist/app/saved/use-favorite.js +3 -2
  134. package/dist/app/search/messages.js +6 -2
  135. package/dist/app/search/navigation-hits.js +9 -7
  136. package/dist/app/searches/filter-chip-list.js +2 -1
  137. package/dist/app/searches/messages.js +96 -0
  138. package/dist/app/searches/save-search-button.js +5 -4
  139. package/dist/app/searches/saved-search-rows.js +3 -2
  140. package/dist/app/searches/saved-search-section.js +6 -5
  141. package/dist/app/searches/saved-search.js +4 -3
  142. package/dist/app/searches/saved-searches.js +15 -25
  143. package/dist/app/searches/search-controls.js +5 -4
  144. package/dist/app/searches/search-diff.js +4 -2
  145. package/dist/app/searches/search-name-dialog.js +4 -3
  146. package/dist/app/searches/update-search-dialog.js +15 -30
  147. package/dist/app/searches/use-save-search.js +8 -7
  148. package/dist/app/searches/use-search-row.js +4 -3
  149. package/dist/app/sensitive-field.js +5 -4
  150. package/dist/app/source-notice.js +13 -8
  151. package/dist/app/staff-banner.js +13 -20
  152. package/dist/app-shell/global-search.js +2 -2
  153. package/dist/app-shell/messages.js +4 -2
  154. package/dist/app-shell/sidebar-group.js +1 -1
  155. package/dist/app-shell/sidebar-item.js +1 -1
  156. package/dist/app-shell/sidebar.js +1 -1
  157. package/dist/assistant-dock/assistant-dock.js +6 -6
  158. package/dist/assistant-dock/messages.js +26 -0
  159. package/dist/assistant-dock/use-assistant.js +2 -1
  160. package/dist/assistant-dock/use-backend-data.js +2 -1
  161. package/dist/assistant-dock/widget-view.js +3 -2
  162. package/dist/auth/auth-gate.js +10 -5
  163. package/dist/auth/auth-locale.js +14 -0
  164. package/dist/auth/auth-messages.js +122 -43
  165. package/dist/auth/auth-provider.js +6 -1
  166. package/dist/auth/code-form.js +4 -3
  167. package/dist/auth/email-code-form.js +11 -13
  168. package/dist/auth/email-code-page.js +2 -1
  169. package/dist/auth/first-run-page.js +6 -5
  170. package/dist/auth/forgot-password-form.js +15 -17
  171. package/dist/auth/forgot-password-page.js +2 -1
  172. package/dist/auth/messages.js +200 -0
  173. package/dist/auth/provider-sign-in-page.js +5 -5
  174. package/dist/auth/resend-code-button.js +2 -1
  175. package/dist/auth/reset-password-form.js +12 -11
  176. package/dist/auth/reset-password-page.js +4 -3
  177. package/dist/auth/setup-required-form.js +8 -10
  178. package/dist/auth/setup-required-page.js +7 -2
  179. package/dist/auth/sign-in-form.js +18 -21
  180. package/dist/auth/sign-in-prompt.js +4 -3
  181. package/dist/auth/sign-up-code-form.js +11 -13
  182. package/dist/auth/sign-up-details-form.js +15 -22
  183. package/dist/auth/sign-up-email-form.js +9 -8
  184. package/dist/auth/sign-up-page.js +2 -1
  185. package/dist/auth/staff-sign-in-form.js +16 -19
  186. package/dist/auth/two-factor-form.js +19 -18
  187. package/dist/auth/user-to-shell.js +2 -1
  188. package/dist/chat/composer.js +8 -7
  189. package/dist/chat/messages.js +14 -0
  190. package/dist/compact-table/compact-table.js +4 -8
  191. package/dist/compact-table/messages.js +18 -0
  192. package/dist/data/meta-data.d.ts +1 -1
  193. package/dist/data/use-update-record.js +1 -1
  194. package/dist/data-grid/grid-header.js +1 -1
  195. package/dist/filter-panel/date-presets.js +1 -1
  196. package/dist/forms/public-form-page.js +1 -1
  197. package/dist/inline-child-table/inline-child-table.js +12 -12
  198. package/dist/inline-child-table/line-row.js +10 -9
  199. package/dist/inline-child-table/messages.js +52 -0
  200. package/dist/inline-child-table/totals-footer.js +5 -8
  201. package/dist/invitations/invite-form.js +3 -2
  202. package/dist/invitations/link-notice.js +6 -4
  203. package/dist/invitations/messages.js +24 -0
  204. package/dist/invitations/pending-invitation-row.js +4 -3
  205. package/dist/lists/messages.js +8 -0
  206. package/dist/lists/paged-search-list.js +2 -1
  207. package/dist/locale/slotted.js +14 -0
  208. package/dist/markdown/markdown-editor.js +6 -5
  209. package/dist/markdown/messages.js +16 -0
  210. package/dist/organizations/all-organizations.js +6 -5
  211. package/dist/organizations/app-roles-picker.js +2 -1
  212. package/dist/organizations/invitation-page.js +41 -51
  213. package/dist/organizations/invitations-page.js +11 -10
  214. package/dist/organizations/members-page.js +16 -11
  215. package/dist/organizations/messages.js +180 -0
  216. package/dist/organizations/organization-page.js +27 -26
  217. package/dist/organizations/organization-paths.js +16 -13
  218. package/dist/organizations/organization-row.js +3 -2
  219. package/dist/organizations/organizations-page.js +17 -16
  220. package/dist/organizations/use-organizations.js +2 -1
  221. package/dist/package.js +1 -1
  222. package/dist/plugins/before-sign-in.js +6 -1
  223. package/dist/plugins/load-plugin.d.ts +1 -1
  224. package/dist/plugins/load-plugin.js +3 -2
  225. package/dist/plugins/messages.js +36 -0
  226. package/dist/plugins/plugin-gate.js +6 -1
  227. package/dist/plugins/plugin-manifest.js +8 -7
  228. package/dist/plugins/plugin-notice.js +8 -12
  229. package/dist/primitives/button.js +1 -1
  230. package/dist/primitives/messages.js +16 -0
  231. package/dist/primitives/segmented.js +1 -1
  232. package/dist/primitives/sheet.js +2 -1
  233. package/dist/primitives/spinner.js +2 -1
  234. package/dist/primitives/token.js +2 -1
  235. package/dist/record-view/field.js +2 -2
  236. package/dist/record-view/messages.js +4 -2
  237. package/dist/record-view/record-tabs.js +2 -1
  238. package/dist/roles/messages.js +14 -0
  239. package/dist/roles/use-active-role.js +3 -2
  240. package/dist/shell/assets/app-yCMYvqMX.js +69 -0
  241. package/dist/shell/assets/cn-Bi0ZEjD9.js +1 -0
  242. package/dist/shell/assets/export-worker-ClACk00b.js +2 -0
  243. package/dist/shell/assets/{index-BRkDA5KD.css → index-Bkc7w8I4.css} +1 -1
  244. package/dist/shell/assets/{index-xY0Mvv6V.js → index-HkjqX_O-.js} +2 -2
  245. package/dist/shell/assets/maplibre-DUTS_eJM.js +814 -0
  246. package/dist/shell/assets/{markdown-content-ukDTCu6u.js → markdown-content-CtGUP4W6.js} +1 -1
  247. package/dist/shell/assets/parse-worker-UhbwEjS0.js +5 -0
  248. package/dist/shell/assets/preload-helper-BZ3hrQDD.js +1 -0
  249. package/dist/shell/assets/{record-map-BJmYZ7kQ.js → record-map-DFy7sJEU.js} +1 -1
  250. package/dist/shell/assets/records-map-MfQEuiFB.js +1 -0
  251. package/dist/shell/assets/shared-protobase-ui-Bfa59vx6.js +1 -0
  252. package/dist/shell/index.html +6 -4
  253. package/dist/shell/protobase.shell.json +1 -1
  254. package/dist/shell/protobase.sw.js +2 -2
  255. package/dist/side-panel/messages.js +8 -0
  256. package/dist/side-panel/side-panel.js +2 -1
  257. package/dist/toasts/messages.js +8 -0
  258. package/dist/toasts/toast.js +2 -1
  259. package/dist/users/app-invitations.js +5 -4
  260. package/dist/users/create-user-form.js +9 -8
  261. package/dist/users/messages.js +52 -0
  262. package/dist/users/use-user-roles.js +2 -1
  263. package/dist/users/user-list.js +6 -5
  264. package/dist/users/user-row.js +5 -4
  265. package/package.json +4 -4
  266. package/dist/shell/assets/app-C-OLrsRR.js +0 -69
  267. package/dist/shell/assets/export-worker-Bz57Pf5g.js +0 -2
  268. package/dist/shell/assets/maplibre-Dov6nhPX.js +0 -814
  269. package/dist/shell/assets/parse-worker-BtcY0dQw.js +0 -5
  270. package/dist/shell/assets/records-map-C1_gDKHR.js +0 -1
  271. package/dist/shell/assets/shared-protobase-ui-CFYJAbMR.js +0 -1
@@ -5,6 +5,7 @@ import { humanize } from "../../live/naming.js";
5
5
  import { defaultOrderBy } from "../list-order.js";
6
6
  import { ResponsiveDialog } from "../../primitives/responsive-dialog.js";
7
7
  import { countQuery } from "../pages/use-layout-data.js";
8
+ import { text } from "./messages.js";
8
9
  import { useFilterChips } from "./use-filter-chips.js";
9
10
  import { EmbeddedList } from "../embedded-list/embedded-list.js";
10
11
  import { addedFilter, filterChanges, netChange, removedFilter } from "./search-diff.js";
@@ -17,26 +18,26 @@ import { useQuery } from "@tanstack/react-query";
17
18
  const shownLimit = 12;
18
19
  const changeStyle = {
19
20
  added: {
20
- word: "Added",
21
+ word: "added",
21
22
  className: "text-success-text"
22
23
  },
23
24
  removed: {
24
- word: "Removed",
25
+ word: "removed",
25
26
  className: "text-danger-text"
26
27
  },
27
28
  changed: {
28
- word: "Changed",
29
+ word: "changed",
29
30
  className: "text-primary-text"
30
31
  }
31
32
  };
32
33
  const FilterChanges = ({ changes }) => /* @__PURE__ */ jsx("ul", {
33
- "aria-label": "Filter changes",
34
+ "aria-label": text("filterChanges"),
34
35
  className: "divide-y rounded-md border",
35
36
  children: changes.map((change) => /* @__PURE__ */ jsxs("li", {
36
37
  className: "grid grid-cols-[72px_1fr] gap-3 px-3 py-2",
37
38
  children: [/* @__PURE__ */ jsx("span", {
38
39
  className: `font-medium ${changeStyle[change.kind].className}`,
39
- children: changeStyle[change.kind].word
40
+ children: text(changeStyle[change.kind].word)
40
41
  }), change.kind === "changed" ? /* @__PURE__ */ jsxs("span", { children: [
41
42
  /* @__PURE__ */ jsx("span", {
42
43
  className: "text-muted-foreground line-through",
@@ -84,23 +85,13 @@ const RecordsSide = ({ model, view, title, filter, total, plural }) => {
84
85
  })
85
86
  ]
86
87
  }),
87
- total !== void 0 && total > shownLimit && /* @__PURE__ */ jsxs("p", {
88
+ total !== void 0 && total > shownLimit && /* @__PURE__ */ jsx("p", {
88
89
  className: "text-xs text-muted-foreground",
89
- children: [
90
- "The first ",
91
- shownLimit,
92
- " of ",
93
- total,
94
- "."
95
- ]
90
+ children: text("firstOf", shownLimit, total)
96
91
  }),
97
- filter === null || total === 0 ? /* @__PURE__ */ jsxs("p", {
92
+ filter === null || total === 0 ? /* @__PURE__ */ jsx("p", {
98
93
  className: "text-muted-foreground",
99
- children: [
100
- "No ",
101
- plural,
102
- "."
103
- ]
94
+ children: text("noPlural", plural)
104
95
  }) : /* @__PURE__ */ jsx(EmbeddedList, {
105
96
  model,
106
97
  view,
@@ -136,7 +127,7 @@ const UpdateSearchDialog = ({ model, view, title, before, after, saveNewLabel, u
136
127
  actions: /* @__PURE__ */ jsxs(Fragment$1, { children: [
137
128
  /* @__PURE__ */ jsx(Button, {
138
129
  onClick: onCancel,
139
- children: "Cancel"
130
+ children: text("cancel")
140
131
  }),
141
132
  /* @__PURE__ */ jsx(Button, {
142
133
  loading: creating,
@@ -149,7 +140,7 @@ const UpdateSearchDialog = ({ model, view, title, before, after, saveNewLabel, u
149
140
  loading: updating,
150
141
  disabled: creating,
151
142
  onClick: onUpdate,
152
- children: "Update"
143
+ children: text("update")
153
144
  })
154
145
  ] }),
155
146
  children: /* @__PURE__ */ jsxs("div", {
@@ -161,18 +152,12 @@ const UpdateSearchDialog = ({ model, view, title, before, after, saveNewLabel, u
161
152
  children: netChange(addedCount, removedCount, singular, plural)
162
153
  }), /* @__PURE__ */ jsxs("span", {
163
154
  className: "text-muted-foreground",
164
- children: [
165
- ": ",
166
- count(addedCount, singular, plural),
167
- " added, ",
168
- removedCount,
169
- " removed"
170
- ]
155
+ children: [": ", text("addedRemoved", count(addedCount, singular, plural), removedCount)]
171
156
  })] }) : /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-48" }),
172
157
  /* @__PURE__ */ jsx(RecordsSide, {
173
158
  model,
174
159
  view,
175
- title: "Added",
160
+ title: text("added"),
176
161
  filter: added,
177
162
  total: addedCount,
178
163
  plural
@@ -180,7 +165,7 @@ const UpdateSearchDialog = ({ model, view, title, before, after, saveNewLabel, u
180
165
  /* @__PURE__ */ jsx(RecordsSide, {
181
166
  model,
182
167
  view,
183
- title: "Removed",
168
+ title: text("removed"),
184
169
  filter: removed,
185
170
  total: removedCount,
186
171
  plural
@@ -6,12 +6,13 @@ import { useAdminMeta } from "../meta-gate.js";
6
6
  import { useAppAddress } from "../use-app-address.js";
7
7
  import { can } from "../permissions.js";
8
8
  import { useRefreshResource } from "../pages/use-layout-data.js";
9
+ import { text } from "./messages.js";
9
10
  import { useSavedSearches } from "./use-saved-searches.js";
10
11
  import { useOpenedSearch } from "./use-opened-search.js";
11
12
  import { encodeKey } from "@protobase/schema/internal";
12
13
  import { useMutation } from "@tanstack/react-query";
13
14
  //#region src/app/searches/use-save-search.ts
14
- const message = (error) => error instanceof Error ? error.message : "Something went wrong";
15
+ const message = (error) => error instanceof Error ? error.message : text("somethingWrong");
15
16
  /**
16
17
  * A list page's "Save search" button for its `filter`: `save` for someone who can list, create and delete the saved
17
18
  * searches, `sign-in` for a visitor their resource asks to sign in (`prompt`), nothing otherwise. `saved` while a search
@@ -48,9 +49,9 @@ const useSaveSearch = (search, filter) => {
48
49
  opened.open(keyOf(created.record));
49
50
  toast.show({
50
51
  state: "success",
51
- title: "Search saved",
52
+ title: text("searchSaved"),
52
53
  action: {
53
- label: `Open ${plural.toLowerCase()}`,
54
+ label: text("openPlural", plural),
54
55
  href: href({
55
56
  kind: "list",
56
57
  resource
@@ -61,7 +62,7 @@ const useSaveSearch = (search, filter) => {
61
62
  },
62
63
  onError: (error) => toast.show({
63
64
  state: "error",
64
- title: "Could not save the search",
65
+ title: text("couldNotSave"),
65
66
  description: message(error)
66
67
  }),
67
68
  onSettled: () => refresh(resource)
@@ -70,7 +71,7 @@ const useSaveSearch = (search, filter) => {
70
71
  mutationFn: (row) => client.remove(resource, keyOf(row)),
71
72
  onError: (error) => toast.show({
72
73
  state: "error",
73
- title: "Could not take the search off",
74
+ title: text("couldNotTakeOff"),
74
75
  description: message(error)
75
76
  }),
76
77
  onSettled: () => refresh(resource)
@@ -79,11 +80,11 @@ const useSaveSearch = (search, filter) => {
79
80
  mutationFn: (row) => client.update(resource, keyOf(row), { [of.filter]: filter }, row.etag ?? "*"),
80
81
  onSuccess: () => toast.show({
81
82
  state: "success",
82
- title: "Search updated"
83
+ title: text("searchUpdated")
83
84
  }),
84
85
  onError: (error) => toast.show({
85
86
  state: "error",
86
- title: "Could not update the search",
87
+ title: text("couldNotUpdate"),
87
88
  description: message(error)
88
89
  }),
89
90
  onSettled: () => refresh(resource)
@@ -1,6 +1,7 @@
1
1
  import { useClient } from "../../data/api-provider.js";
2
2
  import { humanize } from "../../live/naming.js";
3
3
  import { countQuery, useRefreshResource } from "../pages/use-layout-data.js";
4
+ import { text } from "./messages.js";
4
5
  import { chipsText } from "./filter-chip-list.js";
5
6
  import { isUnseen, unseenFilter } from "./saved-search.js";
6
7
  import { useFilterChips } from "./use-filter-chips.js";
@@ -36,11 +37,11 @@ const useSearchRow = ({ model, of, target, targetView, row, recordKey }) => {
36
37
  sort: unseen ? `${unseen.field} desc` : void 0,
37
38
  limit: of.limit,
38
39
  chips: name !== void 0,
39
- empty: `No ${plural} match.`,
40
- note: unseen && newCount.data === 0 && `No new ${plural} since you last looked.`,
40
+ empty: text("noneMatch", plural),
41
+ note: unseen && newCount.data === 0 && text("noNew", plural),
41
42
  isNew: unseen && ((record) => isUnseen(record.record[unseen.field], row[unseen.seenAt])),
42
43
  viewAll: {
43
- label: "View all results",
44
+ label: text("viewAll"),
44
45
  savedSearch: recordKey,
45
46
  ...unseen && { onOpen: () => markSeen.mutate((/* @__PURE__ */ new Date()).toISOString()) }
46
47
  }
@@ -1,6 +1,7 @@
1
1
  import { cn } from "../lib/cn.js";
2
2
  import { Input } from "../primitives/input.js";
3
3
  import { Button } from "../primitives/button.js";
4
+ import { text } from "./messages.js";
4
5
  import { humanize } from "../live/naming.js";
5
6
  import { displayValue } from "../live/display-value.js";
6
7
  import { toDraft } from "../live/field-values.js";
@@ -28,7 +29,7 @@ const SensitiveField = ({ field, hints, value, reveal, locked, invalid, placehol
28
29
  variant: "ghost",
29
30
  size: "sm",
30
31
  className: "-mr-1.5 px-1.5",
31
- "aria-label": `${shown ? "Hide" : "Show"} ${label}`,
32
+ "aria-label": shown ? text("hide", label) : text("show", label),
32
33
  "aria-pressed": shown,
33
34
  loading: stored.isPending,
34
35
  onClick: toggle,
@@ -37,7 +38,7 @@ const SensitiveField = ({ field, hints, value, reveal, locked, invalid, placehol
37
38
  const error = stored.error && /* @__PURE__ */ jsx("div", {
38
39
  className: "mt-2",
39
40
  children: /* @__PURE__ */ jsx(ErrorBanner, {
40
- title: `Could not show the ${label}`,
41
+ title: text("couldNotShow", label),
41
42
  error: stored.error
42
43
  })
43
44
  });
@@ -48,7 +49,7 @@ const SensitiveField = ({ field, hints, value, reveal, locked, invalid, placehol
48
49
  children: shown ? displayValue(field, stored.data, hints) : mask
49
50
  }), reveal && eye]
50
51
  }), error] });
51
- const text = typed ? toDraft(value) : shown && stored.isSuccess ? toDraft(stored.data) : "";
52
+ const text$1 = typed ? toDraft(value) : shown && stored.isSuccess ? toDraft(stored.data) : "";
52
53
  return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input, {
53
54
  type: shown ? "text" : "password",
54
55
  autoComplete: "off",
@@ -56,7 +57,7 @@ const SensitiveField = ({ field, hints, value, reveal, locked, invalid, placehol
56
57
  "aria-label": label,
57
58
  className: cn(hints?.format === "code" && "font-mono text-xs"),
58
59
  placeholder: typed || !reveal ? placeholder : mask,
59
- value: text,
60
+ value: text$1,
60
61
  trailing: eye,
61
62
  onChange: (event) => onChange(event.target.value)
62
63
  }), error] });
@@ -1,13 +1,14 @@
1
1
  import { Spinner } from "../primitives/spinner.js";
2
2
  import { Button } from "../primitives/button.js";
3
3
  import { keys } from "../data/query-keys.js";
4
+ import { text } from "./messages.js";
4
5
  import { isApiError } from "@protobase/client";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
7
  import { useQueryClient } from "@tanstack/react-query";
7
8
  //#region src/app/source-notice.tsx
8
9
  const reason = (error) => {
9
- if (!isApiError(error)) return "It did not answer.";
10
- if (error.status === 401 || error.status === 403) return `It did not accept your sign-in: ${error.message}`;
10
+ if (!isApiError(error)) return text("noAnswer");
11
+ if (error.status === 401 || error.status === 403) return text("signInRefused", error.message);
11
12
  return error.message;
12
13
  };
13
14
  /** Where a resource drawn from another API would be while that API's `/meta` loads, or when it cannot be read. */
@@ -17,8 +18,8 @@ const SourceNotice = ({ status }) => {
17
18
  className: "flex h-full min-h-48 flex-1 items-center justify-center gap-2 text-muted-foreground",
18
19
  children: [
19
20
  /* @__PURE__ */ jsx(Spinner, {}),
20
- " Loading from ",
21
- status.source.label
21
+ " ",
22
+ text("loadingFrom", status.source.label)
22
23
  ]
23
24
  });
24
25
  return /* @__PURE__ */ jsx("div", {
@@ -26,18 +27,22 @@ const SourceNotice = ({ status }) => {
26
27
  children: /* @__PURE__ */ jsxs("div", {
27
28
  className: "max-w-md text-center",
28
29
  children: [
29
- /* @__PURE__ */ jsxs("h1", {
30
+ /* @__PURE__ */ jsx("h1", {
30
31
  className: "text-[16px] font-semibold",
31
- children: ["Cannot reach ", status.source.label]
32
+ children: text("cannotReach", status.source.label)
32
33
  }),
33
34
  /* @__PURE__ */ jsxs("p", {
34
35
  className: "mt-1 text-muted-foreground",
35
- children: [reason(status.error), " The rest of the app works as before."]
36
+ children: [
37
+ reason(status.error),
38
+ " ",
39
+ text("restWorks")
40
+ ]
36
41
  }),
37
42
  /* @__PURE__ */ jsx(Button, {
38
43
  className: "mt-3",
39
44
  onClick: () => void queryClient.refetchQueries({ queryKey: keys.sourceMetas(status.source.url) }),
40
- children: "Try again"
45
+ children: text("tryAgain")
41
46
  })
42
47
  ]
43
48
  })
@@ -1,6 +1,8 @@
1
1
  import { authMessage } from "../auth/auth-messages.js";
2
2
  import { formatDateTime } from "../format/date.js";
3
3
  import { Button } from "../primitives/button.js";
4
+ import { text } from "./messages.js";
5
+ import { slotted } from "../locale/slotted.js";
4
6
  import { useState } from "react";
5
7
  import { UserRoundCog } from "lucide-react";
6
8
  import { AuthError } from "@protobase/client";
@@ -23,42 +25,33 @@ const StaffBanner = ({ signIn, onStop }) => {
23
25
  };
24
26
  return /* @__PURE__ */ jsxs("div", {
25
27
  role: "region",
26
- "aria-label": "Staff session",
28
+ "aria-label": text("staffSession"),
27
29
  className: "flex flex-wrap items-center gap-x-3 gap-y-2 border-b border-warning/40 bg-warning-soft px-4 py-2 text-warning-text",
28
30
  children: [
29
31
  /* @__PURE__ */ jsx(UserRoundCog, {
30
32
  "aria-hidden": true,
31
33
  className: "size-4 shrink-0"
32
34
  }),
33
- /* @__PURE__ */ jsxs("p", {
35
+ /* @__PURE__ */ jsx("p", {
34
36
  className: "min-w-64 flex-1 break-words",
35
- children: [
36
- /* @__PURE__ */ jsx("span", {
37
- className: "font-semibold",
38
- children: signIn.staffName ?? signIn.staff
39
- }),
40
- " is signed in as ",
41
- /* @__PURE__ */ jsx("span", {
42
- className: "font-semibold",
43
- children: signIn.user
44
- }),
45
- " until",
46
- " ",
47
- formatDateTime(Date.parse(signIn.expiresAt)),
48
- ". Reason: ",
49
- signIn.reason
50
- ]
37
+ children: slotted(text("staffSignedIn"), /* @__PURE__ */ jsx("span", {
38
+ className: "font-semibold",
39
+ children: signIn.staffName ?? signIn.staff
40
+ }), /* @__PURE__ */ jsx("span", {
41
+ className: "font-semibold",
42
+ children: signIn.user
43
+ }), formatDateTime(Date.parse(signIn.expiresAt)), signIn.reason)
51
44
  }),
52
45
  error && /* @__PURE__ */ jsx("p", {
53
46
  role: "alert",
54
- className: "text-xs font-medium text-danger-text",
47
+ className: "text-body font-medium text-danger-text",
55
48
  children: error
56
49
  }),
57
50
  /* @__PURE__ */ jsx(Button, {
58
51
  size: "sm",
59
52
  loading: stopping,
60
53
  onClick: () => void stop(),
61
- children: "Stop staff session"
54
+ children: text("stopStaffSession")
62
55
  })
63
56
  ]
64
57
  });
@@ -107,9 +107,9 @@ const GlobalSearch = ({ search, className = "w-96", autoFocus, showShortcut = tr
107
107
  className: "px-3 pb-1 pt-2 text-[11px] font-medium uppercase tracking-wide text-faint-foreground",
108
108
  children: group.label
109
109
  }),
110
- group.failed && /* @__PURE__ */ jsxs("p", {
110
+ group.failed && /* @__PURE__ */ jsx("p", {
111
111
  className: "px-3 py-1.5 text-danger-text",
112
- children: ["Could not search ", group.label.toLowerCase()]
112
+ children: text("couldNotSearch", group.label)
113
113
  }),
114
114
  group.hits.map((hit) => {
115
115
  position += 1;
@@ -28,7 +28,8 @@ const text = defineMessages({
28
28
  recent: (plural) => `Recent ${plural}`,
29
29
  loading: "Loading...",
30
30
  couldNotLoad: "Could not load",
31
- viewAll: "View all"
31
+ viewAll: "View all",
32
+ couldNotSearch: (label) => `Could not search ${label.toLowerCase()}`
32
33
  },
33
34
  nl: {
34
35
  navigation: "Navigatie",
@@ -57,7 +58,8 @@ const text = defineMessages({
57
58
  recent: (plural) => `Recente ${plural}`,
58
59
  loading: "Laden...",
59
60
  couldNotLoad: "Kon niet laden",
60
- viewAll: "Alles bekijken"
61
+ viewAll: "Alles bekijken",
62
+ couldNotSearch: (label) => `Kon niet zoeken in ${label.toLowerCase()}`
61
63
  }
62
64
  });
63
65
  //#endregion
@@ -9,7 +9,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
9
9
  //#region src/app-shell/sidebar-group.tsx
10
10
  const row = {
11
11
  "text-large": "h-8 gap-2.5 px-2.5",
12
- "text-small": "h-7 gap-2 px-2 text-xs"
12
+ "text-small": "h-7 gap-2 px-2 text-body"
13
13
  };
14
14
  /** Lines the records up under the entry's icon. */
15
15
  const indent = {
@@ -6,7 +6,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region src/app-shell/sidebar-item.tsx
7
7
  const layout = {
8
8
  "text-large": "h-9 gap-3 px-3 text-sm",
9
- "text-small": "h-7 gap-2.5 px-2.5 text-xs",
9
+ "text-small": "h-7 gap-2.5 px-2.5 text-body",
10
10
  icon: "size-9 justify-center",
11
11
  "icon-label": "w-full flex-col gap-0.5 py-1.5 text-[10px]",
12
12
  "icon-tooltip": "size-9 justify-center",
@@ -34,7 +34,7 @@ const Sidebar = ({ mode, activeItem, user, workspace, appName, forceExpanded, pr
34
34
  children: groups.map((group, index) => /* @__PURE__ */ jsxs("div", {
35
35
  className: cn("flex flex-col gap-0.5", index > 0 && "mt-3"),
36
36
  children: [inline ? /* @__PURE__ */ jsx("div", {
37
- className: cn("px-3 pb-1 pt-1 text-[11px] font-medium uppercase tracking-wide text-faint-foreground", expanding && "h-4 whitespace-nowrap py-0 opacity-0 transition-opacity group-hover/side:opacity-100 group-focus-within/side:opacity-100", expanded && "opacity-100"),
37
+ className: cn("px-3 pb-1 pt-1 text-xs font-medium uppercase tracking-wide text-faint-foreground", expanding && "h-4 whitespace-nowrap py-0 opacity-0 transition-opacity group-hover/side:opacity-100 group-focus-within/side:opacity-100", expanded && "opacity-100"),
38
38
  children: group.label
39
39
  }) : index > 0 && /* @__PURE__ */ jsx("div", { className: "mx-auto mb-1 h-px w-6 bg-border" }), group.items.map((item) => item.recent && isTextMode(mode) ? /* @__PURE__ */ jsx(SidebarGroup, {
40
40
  item,
@@ -2,13 +2,13 @@ import { ChatMessage } from "../chat/chat-message.js";
2
2
  import { ChatThread } from "../chat/chat-thread.js";
3
3
  import { Composer } from "../chat/composer.js";
4
4
  import { SidePanel } from "../side-panel/side-panel.js";
5
+ import { text } from "./messages.js";
5
6
  import { PartView } from "./part-view.js";
6
7
  import { AssistantBackendContext } from "./use-backend-data.js";
7
8
  import { useEffect, useRef } from "react";
8
9
  import { Sparkles } from "lucide-react";
9
10
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
11
  //#region src/assistant-dock/assistant-dock.tsx
11
- const defaultPlaceholder = "Ask a question...";
12
12
  /**
13
13
  * The assistant beside the app: renders a backend's chat, its cards, the app's widgets and status line, and sends
14
14
  * messages and clicks back.
@@ -19,25 +19,25 @@ const AssistantDock = ({ state, offline, error, onSend, onAction, onClose, clien
19
19
  if (state.placeholder) input.current?.focus();
20
20
  }, [state.placeholder]);
21
21
  return /* @__PURE__ */ jsx(SidePanel, {
22
- title: "Assistant",
22
+ title: text("assistant"),
23
23
  icon: /* @__PURE__ */ jsx(Sparkles, { className: "size-4 text-primary" }),
24
- status: offline ? "Reconnecting..." : state.status,
24
+ status: offline ? text("reconnecting") : state.status,
25
25
  onClose,
26
26
  footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [error && /* @__PURE__ */ jsx("p", {
27
27
  role: "alert",
28
- className: "text-xs text-danger-text",
28
+ className: "text-body text-danger-text",
29
29
  children: error
30
30
  }), /* @__PURE__ */ jsx(Composer, {
31
31
  inputRef: input,
32
32
  onSend,
33
33
  busy: state.replying,
34
- placeholder: state.placeholder ?? defaultPlaceholder
34
+ placeholder: state.placeholder ?? text("askQuestion")
35
35
  })] }),
36
36
  children: /* @__PURE__ */ jsx(AssistantBackendContext.Provider, {
37
37
  value: client,
38
38
  children: /* @__PURE__ */ jsx(ChatThread, {
39
39
  length: state.messages.reduce((sum, message) => sum + message.parts.length, 0),
40
- empty: "Ask a question about this app or its data.",
40
+ empty: text("empty"),
41
41
  children: state.messages.map((message) => /* @__PURE__ */ jsx(ChatMessage, {
42
42
  from: message.from,
43
43
  children: message.parts.map((part) => /* @__PURE__ */ jsx(PartView, {
@@ -0,0 +1,26 @@
1
+ import { defineMessages } from "../locale/messages.js";
2
+ //#region src/assistant-dock/messages.ts
3
+ const text = defineMessages({
4
+ en: {
5
+ askQuestion: "Ask a question...",
6
+ assistant: "Assistant",
7
+ reconnecting: "Reconnecting...",
8
+ empty: "Ask a question about this app or its data.",
9
+ noAnswer: "The assistant did not answer",
10
+ backendNoAnswer: "The assistant backend did not answer",
11
+ couldNotDraw: "It could not be drawn.",
12
+ cannotShowLive: "This version of the app cannot show it live."
13
+ },
14
+ nl: {
15
+ askQuestion: "Stel een vraag...",
16
+ assistant: "Assistent",
17
+ reconnecting: "Opnieuw verbinden...",
18
+ empty: "Stel een vraag over deze app of de gegevens ervan.",
19
+ noAnswer: "De assistent antwoordde niet",
20
+ backendNoAnswer: "De backend van de assistent antwoordde niet",
21
+ couldNotDraw: "Dit kon niet worden getekend.",
22
+ cannotShowLive: "Deze versie van de app kan dit niet live tonen."
23
+ }
24
+ });
25
+ //#endregion
26
+ export { text };
@@ -1,7 +1,8 @@
1
+ import { text } from "./messages.js";
1
2
  import { useEffect, useState } from "react";
2
3
  import { applyAssistantEvent, emptyAssistantState } from "@protobase/schema/internal";
3
4
  //#region src/assistant-dock/use-assistant.ts
4
- const messageOf = (error) => error instanceof Error ? error.message : "The assistant did not answer";
5
+ const messageOf = (error) => error instanceof Error ? error.message : text("noAnswer");
5
6
  /** Follows an assistant backend's event stream into state, with its two requests; `undefined` client means not yet. */
6
7
  const useAssistant = (client) => {
7
8
  const [state, setState] = useState(emptyAssistantState);
@@ -1,8 +1,9 @@
1
+ import { text } from "./messages.js";
1
2
  import { createContext, useContext, useEffect, useRef, useState } from "react";
2
3
  //#region src/assistant-dock/use-backend-data.ts
3
4
  /** The assistant backend the dock talks to, for the widgets it draws; `AssistantDock` provides it from its `client`. */
4
5
  const AssistantBackendContext = createContext(void 0);
5
- const asError = (reason) => reason instanceof Error ? reason : /* @__PURE__ */ new Error("The assistant backend did not answer");
6
+ const asError = (reason) => reason instanceof Error ? reason : new Error(text("backendNoAnswer"));
6
7
  const refreshOf = (refresh, data) => typeof refresh === "function" ? refresh(data) : refresh;
7
8
  /**
8
9
  * JSON from the assistant backend at `path` (see `AssistantClient.fetch`), read as the signed-in user each time the
@@ -1,6 +1,7 @@
1
1
  import { reportRenderError } from "../app/error-reporting.js";
2
2
  import { useProjectUi } from "../app/pages/project-ui.js";
3
3
  import { ActionCard } from "../action-card/action-card.js";
4
+ import { text } from "./messages.js";
4
5
  import { Component } from "react";
5
6
  import { jsx } from "react/jsx-runtime";
6
7
  //#region src/assistant-dock/widget-view.tsx
@@ -24,7 +25,7 @@ var WidgetBoundary = class extends Component {
24
25
  render() {
25
26
  return this.state.failed ? /* @__PURE__ */ jsx(Fallback, {
26
27
  part: this.props.part,
27
- note: "It could not be drawn."
28
+ note: text("couldNotDraw")
28
29
  }) : this.props.children;
29
30
  }
30
31
  };
@@ -34,7 +35,7 @@ const WidgetView = ({ part }) => {
34
35
  const Widget = Object.hasOwn(components, part.name) ? components[part.name] : void 0;
35
36
  if (!Widget) return /* @__PURE__ */ jsx(Fallback, {
36
37
  part,
37
- note: "This version of the app cannot show it live."
38
+ note: text("cannotShowLive")
38
39
  });
39
40
  return /* @__PURE__ */ jsx(WidgetBoundary, {
40
41
  part,
@@ -1,6 +1,7 @@
1
1
  import { Spinner } from "../primitives/spinner.js";
2
2
  import { providerMessage } from "./auth-messages.js";
3
3
  import { readProviderError, readSignInLink, withoutSignInLink } from "./provider-link.js";
4
+ import { text } from "./messages.js";
4
5
  import { useAuth } from "./auth-provider.js";
5
6
  import { Button } from "../primitives/button.js";
6
7
  import { useRouter } from "../app/router.js";
@@ -121,7 +122,7 @@ const useAuthPage = (workspace, children) => {
121
122
  if (state.kind === "signed-in") await signOut();
122
123
  leaveResetPage({
123
124
  kind: "sign-in",
124
- notice: "Your password is changed. Sign in with the new one."
125
+ notice: text("passwordChanged")
125
126
  });
126
127
  };
127
128
  const backToSignIn = () => {
@@ -131,16 +132,20 @@ const useAuthPage = (workspace, children) => {
131
132
  switch (state.kind) {
132
133
  case "loading": return /* @__PURE__ */ jsxs("div", {
133
134
  className: "flex h-full min-h-48 items-center justify-center gap-2 text-muted-foreground",
134
- children: [/* @__PURE__ */ jsx(Spinner, {}), " Loading"]
135
+ children: [
136
+ /* @__PURE__ */ jsx(Spinner, {}),
137
+ " ",
138
+ text("loading")
139
+ ]
135
140
  });
136
141
  case "error": return /* @__PURE__ */ jsxs("div", {
137
142
  className: "flex h-full min-h-48 flex-col items-center justify-center gap-3 p-8 text-center",
138
- children: [/* @__PURE__ */ jsxs("p", {
143
+ children: [/* @__PURE__ */ jsx("p", {
139
144
  className: "text-muted-foreground",
140
- children: ["Cannot reach the server: ", state.message]
145
+ children: text("cannotReach", state.message)
141
146
  }), /* @__PURE__ */ jsx(Button, {
142
147
  onClick: recheck,
143
- children: "Try again"
148
+ children: text("tryAgain")
144
149
  })]
145
150
  });
146
151
  case "needs-admin": return /* @__PURE__ */ jsx(FirstRunPage, { onCheckAgain: recheck });
@@ -0,0 +1,14 @@
1
+ import { useAuth } from "./auth-provider.js";
2
+ import { AppLocale } from "../locale/app-locale.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/auth/auth-locale.tsx
5
+ /**
6
+ * Puts the screens below in the language the setup status names: the sign-in screens and public forms come before
7
+ * `/meta`, and are in the app's language all the same.
8
+ */
9
+ const AuthLocale = ({ children }) => /* @__PURE__ */ jsx(AppLocale, {
10
+ locale: useAuth().locale,
11
+ children
12
+ });
13
+ //#endregion
14
+ export { AuthLocale };