@protobase/ui 0.25.2 → 0.25.3

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 (255) hide show
  1. package/dist/account/account-pages.js +3 -2
  2. package/dist/account/account-security-page.js +9 -4
  3. package/dist/account/backup-codes.js +7 -6
  4. package/dist/account/messages.js +214 -0
  5. package/dist/account/passkeys-section.js +23 -22
  6. package/dist/account/password-dialog.js +3 -2
  7. package/dist/account/sign-in-policy-form.js +11 -10
  8. package/dist/account/sign-in-policy-labels.js +30 -29
  9. package/dist/account/sign-in-policy-page.js +11 -6
  10. package/dist/account/sign-in-providers-section.js +6 -5
  11. package/dist/account/staff-sign-in-log.js +11 -10
  12. package/dist/account/totp-qr.js +2 -1
  13. package/dist/account/two-factor-section.js +24 -23
  14. package/dist/account/two-factor-setup.js +18 -17
  15. package/dist/action-card/action-card.js +2 -1
  16. package/dist/action-card/messages.js +8 -0
  17. package/dist/activity-chart/activity-chart.js +3 -2
  18. package/dist/activity-chart/messages.js +14 -0
  19. package/dist/app/app.d.ts +1 -1
  20. package/dist/app/app.js +20 -21
  21. package/dist/app/assistant-shell.js +2 -1
  22. package/dist/app/batch-failure.js +2 -1
  23. package/dist/app/breadcrumb-for.js +4 -3
  24. package/dist/app/charts/chart-groups.js +3 -2
  25. package/dist/app/charts/chart-view.js +3 -2
  26. package/dist/app/charts/group-bars.js +2 -1
  27. package/dist/app/charts/messages.js +26 -0
  28. package/dist/app/charts/period-chart.js +3 -2
  29. package/dist/app/charts/split-points.js +2 -1
  30. package/dist/app/comments/comment-composer.js +19 -18
  31. package/dist/app/comments/comments-section.js +4 -3
  32. package/dist/app/comments/messages.js +26 -0
  33. package/dist/app/create/create-page.js +11 -18
  34. package/dist/app/custom-section.js +4 -6
  35. package/dist/app/displays/board-column.js +6 -5
  36. package/dist/app/displays/board-columns.js +3 -2
  37. package/dist/app/displays/board-display.js +13 -15
  38. package/dist/app/displays/calendar-controls.js +3 -2
  39. package/dist/app/displays/calendar-display.js +12 -17
  40. package/dist/app/displays/card-carousel.js +4 -3
  41. package/dist/app/displays/cards-display.js +2 -1
  42. package/dist/app/displays/custom-display.js +4 -6
  43. package/dist/app/displays/display-frame.js +3 -2
  44. package/dist/app/displays/list-cards.js +5 -8
  45. package/dist/app/displays/list-displays.js +3 -3
  46. package/dist/app/displays/map-display.js +15 -14
  47. package/dist/app/displays/messages.js +128 -2
  48. package/dist/app/displays/period-controls.js +4 -3
  49. package/dist/app/displays/record-card.js +7 -6
  50. package/dist/app/displays/timeline-display.js +17 -26
  51. package/dist/app/displays/timeline-range.js +2 -1
  52. package/dist/app/displays/use-board-move.js +2 -2
  53. package/dist/app/displays/use-calendar-move.js +2 -1
  54. package/dist/app/document-title.js +2 -1
  55. package/dist/app/export/builder-port.js +2 -1
  56. package/dist/app/export/export-dialog.js +36 -40
  57. package/dist/app/export/export-worker.js +2 -0
  58. package/dist/app/export/messages.js +78 -0
  59. package/dist/app/export/run-export.js +5 -2
  60. package/dist/app/export/sink.js +4 -3
  61. package/dist/app/export/use-export-flow.js +4 -3
  62. package/dist/app/field-editor.js +4 -3
  63. package/dist/app/field-types/messages.js +8 -0
  64. package/dist/app/field-types/widget-part.js +2 -1
  65. package/dist/app/file-field.js +11 -14
  66. package/dist/app/gallery/gallery-section.js +4 -3
  67. package/dist/app/gallery/lightbox.js +5 -4
  68. package/dist/app/gallery/messages.js +30 -0
  69. package/dist/app/gallery/photo-details.js +3 -2
  70. package/dist/app/hand-order/hand-sorted-list.js +3 -6
  71. package/dist/app/hand-order/messages.js +4 -2
  72. package/dist/app/history/describe-change.js +3 -8
  73. package/dist/app/history/messages.js +32 -0
  74. package/dist/app/import/convert.js +20 -19
  75. package/dist/app/import/failed-rows.js +3 -2
  76. package/dist/app/import/import-button.js +2 -1
  77. package/dist/app/import/import-check-step.js +19 -35
  78. package/dist/app/import/import-dialog.js +13 -17
  79. package/dist/app/import/import-file-step.js +5 -9
  80. package/dist/app/import/import-mapping-step.js +32 -35
  81. package/dist/app/import/import-result-step.js +13 -12
  82. package/dist/app/import/messages.js +200 -0
  83. package/dist/app/import/parse-worker.js +2 -0
  84. package/dist/app/import/prepare-rows.js +5 -4
  85. package/dist/app/import/sheet-cell.js +2 -1
  86. package/dist/app/import/sheet-file.js +3 -2
  87. package/dist/app/import/sheet-source.js +7 -3
  88. package/dist/app/import/xlsx-reader.js +4 -3
  89. package/dist/app/import/xlsx-xml.js +2 -1
  90. package/dist/app/import/zip-reader.js +4 -3
  91. package/dist/app/list-edit/use-list-edits.js +1 -1
  92. package/dist/app/list-group-chart.js +2 -1
  93. package/dist/app/list-page.js +1 -1
  94. package/dist/app/map/map-layer-switch.js +3 -2
  95. package/dist/app/map/messages.js +14 -0
  96. package/dist/app/messages.js +116 -2
  97. package/dist/app/meta-gate.js +1 -1
  98. package/dist/app/nav-from-meta.js +11 -10
  99. package/dist/app/pages/action-inputs/action-inputs-dialog.js +3 -2
  100. package/dist/app/pages/action-inputs/input-answers.js +6 -5
  101. package/dist/app/pages/blocks/card-row.js +3 -2
  102. package/dist/app/pages/blocks/modal-form.js +5 -4
  103. package/dist/app/pages/blocks/record-card.js +3 -2
  104. package/dist/app/pages/blocks/stat.js +2 -1
  105. package/dist/app/pages/composed-page.js +6 -8
  106. package/dist/app/pages/confirm-action.js +2 -1
  107. package/dist/app/pages/custom-boundary.js +4 -2
  108. package/dist/app/pages/messages.js +64 -0
  109. package/dist/app/pages/render-node.js +5 -7
  110. package/dist/app/pages/use-run-action.js +11 -10
  111. package/dist/app/record-page.js +1 -1
  112. package/dist/app/record-row/messages.js +26 -0
  113. package/dist/app/record-row/record-row-body.js +12 -7
  114. package/dist/app/record-row/record-row.js +4 -3
  115. package/dist/app/record-row/saved-record-row.js +3 -2
  116. package/dist/app/related-dots/dots-summary.js +2 -1
  117. package/dist/app/related-dots/messages.js +8 -0
  118. package/dist/app/relation-picker.js +9 -8
  119. package/dist/app/router.js +5 -4
  120. package/dist/app/runtime/messages.js +58 -0
  121. package/dist/app/runtime/runtime-status.js +10 -23
  122. package/dist/app/runtime/runtime-update-dialog.js +7 -6
  123. package/dist/app/runtime/runtime-update.js +4 -3
  124. package/dist/app/saved/favorite-button.js +2 -1
  125. package/dist/app/saved/messages.js +22 -0
  126. package/dist/app/saved/saved-list.js +4 -7
  127. package/dist/app/saved/use-favorite.js +3 -2
  128. package/dist/app/search/messages.js +6 -2
  129. package/dist/app/search/navigation-hits.js +9 -7
  130. package/dist/app/searches/filter-chip-list.js +2 -1
  131. package/dist/app/searches/messages.js +96 -0
  132. package/dist/app/searches/save-search-button.js +5 -4
  133. package/dist/app/searches/saved-search-rows.js +3 -2
  134. package/dist/app/searches/saved-search-section.js +6 -5
  135. package/dist/app/searches/saved-search.js +4 -3
  136. package/dist/app/searches/saved-searches.js +15 -25
  137. package/dist/app/searches/search-controls.js +5 -4
  138. package/dist/app/searches/search-diff.js +4 -2
  139. package/dist/app/searches/search-name-dialog.js +4 -3
  140. package/dist/app/searches/update-search-dialog.js +15 -30
  141. package/dist/app/searches/use-save-search.js +8 -7
  142. package/dist/app/searches/use-search-row.js +4 -3
  143. package/dist/app/sensitive-field.js +5 -4
  144. package/dist/app/source-notice.js +13 -8
  145. package/dist/app/staff-banner.js +12 -19
  146. package/dist/app-shell/global-search.js +2 -2
  147. package/dist/app-shell/messages.js +4 -2
  148. package/dist/assistant-dock/assistant-dock.js +5 -5
  149. package/dist/assistant-dock/messages.js +26 -0
  150. package/dist/assistant-dock/use-assistant.js +2 -1
  151. package/dist/assistant-dock/use-backend-data.js +2 -1
  152. package/dist/assistant-dock/widget-view.js +3 -2
  153. package/dist/auth/auth-gate.js +10 -5
  154. package/dist/auth/auth-locale.js +14 -0
  155. package/dist/auth/auth-messages.js +122 -43
  156. package/dist/auth/auth-provider.js +6 -1
  157. package/dist/auth/code-form.js +2 -1
  158. package/dist/auth/email-code-form.js +11 -13
  159. package/dist/auth/email-code-page.js +2 -1
  160. package/dist/auth/first-run-page.js +6 -5
  161. package/dist/auth/forgot-password-form.js +14 -16
  162. package/dist/auth/forgot-password-page.js +2 -1
  163. package/dist/auth/messages.js +200 -0
  164. package/dist/auth/provider-sign-in-page.js +5 -5
  165. package/dist/auth/resend-code-button.js +2 -1
  166. package/dist/auth/reset-password-form.js +11 -10
  167. package/dist/auth/reset-password-page.js +4 -3
  168. package/dist/auth/setup-required-form.js +7 -9
  169. package/dist/auth/setup-required-page.js +7 -2
  170. package/dist/auth/sign-in-form.js +15 -18
  171. package/dist/auth/sign-in-prompt.js +4 -3
  172. package/dist/auth/sign-up-code-form.js +11 -13
  173. package/dist/auth/sign-up-details-form.js +14 -21
  174. package/dist/auth/sign-up-email-form.js +8 -7
  175. package/dist/auth/sign-up-page.js +2 -1
  176. package/dist/auth/staff-sign-in-form.js +14 -17
  177. package/dist/auth/two-factor-form.js +17 -16
  178. package/dist/auth/user-to-shell.js +2 -1
  179. package/dist/chat/composer.js +8 -7
  180. package/dist/chat/messages.js +14 -0
  181. package/dist/compact-table/compact-table.js +4 -8
  182. package/dist/compact-table/messages.js +18 -0
  183. package/dist/data/meta-data.d.ts +1 -1
  184. package/dist/data/use-update-record.js +1 -1
  185. package/dist/inline-child-table/inline-child-table.js +12 -12
  186. package/dist/inline-child-table/line-row.js +10 -9
  187. package/dist/inline-child-table/messages.js +52 -0
  188. package/dist/inline-child-table/totals-footer.js +5 -8
  189. package/dist/invitations/invite-form.js +3 -2
  190. package/dist/invitations/link-notice.js +6 -4
  191. package/dist/invitations/messages.js +24 -0
  192. package/dist/invitations/pending-invitation-row.js +4 -3
  193. package/dist/lists/messages.js +8 -0
  194. package/dist/lists/paged-search-list.js +2 -1
  195. package/dist/locale/slotted.js +14 -0
  196. package/dist/markdown/markdown-editor.js +6 -5
  197. package/dist/markdown/messages.js +16 -0
  198. package/dist/organizations/all-organizations.js +6 -5
  199. package/dist/organizations/app-roles-picker.js +2 -1
  200. package/dist/organizations/invitation-page.js +39 -49
  201. package/dist/organizations/invitations-page.js +11 -10
  202. package/dist/organizations/members-page.js +15 -10
  203. package/dist/organizations/messages.js +180 -0
  204. package/dist/organizations/organization-page.js +27 -26
  205. package/dist/organizations/organization-paths.js +16 -13
  206. package/dist/organizations/organization-row.js +3 -2
  207. package/dist/organizations/organizations-page.js +17 -16
  208. package/dist/organizations/use-organizations.js +2 -1
  209. package/dist/package.js +1 -1
  210. package/dist/plugins/before-sign-in.js +6 -1
  211. package/dist/plugins/load-plugin.d.ts +1 -1
  212. package/dist/plugins/load-plugin.js +3 -2
  213. package/dist/plugins/messages.js +36 -0
  214. package/dist/plugins/plugin-gate.js +6 -1
  215. package/dist/plugins/plugin-manifest.js +8 -7
  216. package/dist/plugins/plugin-notice.js +8 -12
  217. package/dist/primitives/messages.js +16 -0
  218. package/dist/primitives/sheet.js +2 -1
  219. package/dist/primitives/spinner.js +2 -1
  220. package/dist/primitives/token.js +2 -1
  221. package/dist/record-view/messages.js +4 -2
  222. package/dist/record-view/record-tabs.js +2 -1
  223. package/dist/roles/messages.js +14 -0
  224. package/dist/roles/use-active-role.js +3 -2
  225. package/dist/shell/assets/app-CW3U56yM.js +69 -0
  226. package/dist/shell/assets/cn-Bi0ZEjD9.js +1 -0
  227. package/dist/shell/assets/export-worker-ClACk00b.js +2 -0
  228. package/dist/shell/assets/{index-xY0Mvv6V.js → index-B7cIjCuz.js} +2 -2
  229. package/dist/shell/assets/maplibre-CVG5L9FD.js +814 -0
  230. package/dist/shell/assets/{markdown-content-ukDTCu6u.js → markdown-content-CtGUP4W6.js} +1 -1
  231. package/dist/shell/assets/parse-worker-UhbwEjS0.js +5 -0
  232. package/dist/shell/assets/preload-helper-BX9CcZkY.js +1 -0
  233. package/dist/shell/assets/{record-map-BJmYZ7kQ.js → record-map-Cw3_NcUl.js} +1 -1
  234. package/dist/shell/assets/records-map-D4f3ZeDL.js +1 -0
  235. package/dist/shell/assets/shared-protobase-ui-CB_i50NP.js +1 -0
  236. package/dist/shell/index.html +5 -3
  237. package/dist/shell/protobase.shell.json +1 -1
  238. package/dist/shell/protobase.sw.js +2 -2
  239. package/dist/side-panel/messages.js +8 -0
  240. package/dist/side-panel/side-panel.js +2 -1
  241. package/dist/toasts/messages.js +8 -0
  242. package/dist/toasts/toast.js +2 -1
  243. package/dist/users/app-invitations.js +5 -4
  244. package/dist/users/create-user-form.js +9 -8
  245. package/dist/users/messages.js +52 -0
  246. package/dist/users/use-user-roles.js +2 -1
  247. package/dist/users/user-list.js +6 -5
  248. package/dist/users/user-row.js +5 -4
  249. package/package.json +4 -4
  250. package/dist/shell/assets/app-C-OLrsRR.js +0 -69
  251. package/dist/shell/assets/export-worker-Bz57Pf5g.js +0 -2
  252. package/dist/shell/assets/maplibre-Dov6nhPX.js +0 -814
  253. package/dist/shell/assets/parse-worker-BtcY0dQw.js +0 -5
  254. package/dist/shell/assets/records-map-C1_gDKHR.js +0 -1
  255. package/dist/shell/assets/shared-protobase-ui-CFYJAbMR.js +0 -1
@@ -1,5 +1,6 @@
1
1
  import { RouteLink } from "../primitives/route-link.js";
2
2
  import { Input } from "../primitives/input.js";
3
+ import { text } from "./messages.js";
3
4
  import { Button } from "../primitives/button.js";
4
5
  import { AuthLayout } from "./auth-layout.js";
5
6
  import { ProviderIcon } from "./provider-icon.js";
@@ -11,7 +12,7 @@ const Divider = () => /* @__PURE__ */ jsxs("div", {
11
12
  className: "my-4 flex items-center gap-3 text-xs text-muted-foreground",
12
13
  children: [
13
14
  /* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" }),
14
- "or",
15
+ text("or"),
15
16
  /* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" })
16
17
  ]
17
18
  });
@@ -28,7 +29,7 @@ const SignInForm = ({ onSubmit, busy, error, workspace, notice, methods = ["pass
28
29
  onSendCode?.(email.trim());
29
30
  };
30
31
  return /* @__PURE__ */ jsxs(AuthLayout, {
31
- title: "Sign in to Protobase",
32
+ title: text("signInTitle"),
32
33
  description: workspace,
33
34
  children: [
34
35
  notice && /* @__PURE__ */ jsx("p", {
@@ -43,25 +44,21 @@ const SignInForm = ({ onSubmit, busy, error, workspace, notice, methods = ["pass
43
44
  onClick: () => onContinueWith?.(provider.id),
44
45
  disabled: busy,
45
46
  className: "min-h-10 w-full",
46
- children: [
47
- /* @__PURE__ */ jsx(ProviderIcon, { id: provider.id }),
48
- "Continue with ",
49
- provider.name
50
- ]
47
+ children: [/* @__PURE__ */ jsx(ProviderIcon, { id: provider.id }), text("continueWith", provider.name)]
51
48
  }, provider.id)),
52
49
  withPasskey && /* @__PURE__ */ jsxs(Button, {
53
50
  onClick: () => onPasskey?.(),
54
51
  disabled: busy,
55
52
  className: "min-h-10 w-full",
56
- children: [/* @__PURE__ */ jsx(KeyRound, { className: "size-4" }), "Sign in with a passkey"]
53
+ children: [/* @__PURE__ */ jsx(KeyRound, { className: "size-4" }), text("signInWithPasskey")]
57
54
  }),
58
- withPasskey && passkeyDomains.slice(1).map((domain) => /* @__PURE__ */ jsxs(Button, {
55
+ withPasskey && passkeyDomains.slice(1).map((domain) => /* @__PURE__ */ jsx(Button, {
59
56
  variant: "ghost",
60
57
  size: "sm",
61
58
  onClick: () => onPasskey?.(domain),
62
59
  disabled: busy,
63
60
  className: "w-full",
64
- children: ["Use a passkey made for ", domain]
61
+ children: text("passkeyFor", domain)
65
62
  }, domain))
66
63
  ]
67
64
  }), withPassword || withCode ? /* @__PURE__ */ jsx(Divider, {}) : error && /* @__PURE__ */ jsx("p", {
@@ -79,7 +76,7 @@ const SignInForm = ({ onSubmit, busy, error, workspace, notice, methods = ["pass
79
76
  children: [
80
77
  /* @__PURE__ */ jsxs("label", {
81
78
  className: "flex flex-col gap-1.5 font-medium",
82
- children: ["Email", /* @__PURE__ */ jsx(Input, {
79
+ children: [text("email"), /* @__PURE__ */ jsx(Input, {
83
80
  ref: emailInput,
84
81
  type: "email",
85
82
  name: "email",
@@ -94,7 +91,7 @@ const SignInForm = ({ onSubmit, busy, error, workspace, notice, methods = ["pass
94
91
  }),
95
92
  withPassword && /* @__PURE__ */ jsxs("label", {
96
93
  className: "flex flex-col gap-1.5 font-medium",
97
- children: ["Password", /* @__PURE__ */ jsx(Input, {
94
+ children: [text("password"), /* @__PURE__ */ jsx(Input, {
98
95
  type: "password",
99
96
  name: "password",
100
97
  autoComplete: "current-password",
@@ -115,7 +112,7 @@ const SignInForm = ({ onSubmit, busy, error, workspace, notice, methods = ["pass
115
112
  type: "submit",
116
113
  loading: busy,
117
114
  className: "min-h-10",
118
- children: "Sign in"
115
+ children: text("signIn")
119
116
  }),
120
117
  withCode && /* @__PURE__ */ jsxs(Button, {
121
118
  variant: withPassword ? "secondary" : "primary",
@@ -124,24 +121,24 @@ const SignInForm = ({ onSubmit, busy, error, workspace, notice, methods = ["pass
124
121
  loading: busy && !withPassword,
125
122
  disabled: busy,
126
123
  className: "min-h-10",
127
- children: [/* @__PURE__ */ jsx(Mail, { className: "size-4" }), "Email me a sign-in code"]
124
+ children: [/* @__PURE__ */ jsx(Mail, { className: "size-4" }), text("emailSignInCode")]
128
125
  }),
129
126
  withPassword && forgotPassword && /* @__PURE__ */ jsx(RouteLink, {
130
127
  to: forgotPassword,
131
128
  className: "self-center font-medium text-primary-text hover:underline",
132
- children: "Forgot password?"
129
+ children: text("forgotPassword")
133
130
  })
134
131
  ]
135
132
  }),
136
133
  signUp && /* @__PURE__ */ jsxs("p", {
137
134
  className: "mt-4 text-center text-muted-foreground",
138
135
  children: [
139
- "New here?",
136
+ text("newHere"),
140
137
  " ",
141
138
  /* @__PURE__ */ jsx(RouteLink, {
142
139
  to: signUp,
143
140
  className: "font-medium text-primary-text hover:underline",
144
- children: "Create an account"
141
+ children: text("createAnAccount")
145
142
  })
146
143
  ]
147
144
  }),
@@ -149,7 +146,7 @@ const SignInForm = ({ onSubmit, busy, error, workspace, notice, methods = ["pass
149
146
  type: "button",
150
147
  onClick: onBrowse,
151
148
  className: "mt-4 w-full text-center font-medium text-muted-foreground hover:text-foreground hover:underline",
152
- children: "Continue without signing in"
149
+ children: text("browse")
153
150
  })
154
151
  ]
155
152
  });
@@ -1,4 +1,5 @@
1
1
  import { RouteLink } from "../primitives/route-link.js";
2
+ import { text } from "./messages.js";
2
3
  import { useAuth } from "./auth-provider.js";
3
4
  import { Button, buttonClass } from "../primitives/button.js";
4
5
  import { useSignInAddress } from "./use-sign-in-address.js";
@@ -31,12 +32,12 @@ const Actions = ({ prompt }) => {
31
32
  }) : canSignUp && /* @__PURE__ */ jsx(RouteLink, {
32
33
  to: link("sign-up"),
33
34
  className: primary,
34
- children: "Create an account"
35
+ children: text("createAnAccount")
35
36
  });
36
37
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(RouteLink, {
37
38
  to: link(),
38
39
  className: signUp ? buttonClass() : primary,
39
- children: "Sign in"
40
+ children: text("signIn")
40
41
  }), signUp] });
41
42
  };
42
43
  /**
@@ -55,7 +56,7 @@ const SignInPrompt = (props) => {
55
56
  onClose: props.onClose,
56
57
  actions: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Button, {
57
58
  onClick: props.onClose,
58
- children: "Not now"
59
+ children: text("notNow")
59
60
  }), /* @__PURE__ */ jsx(Actions, { prompt })] }),
60
61
  children: /* @__PURE__ */ jsx(Benefits, { benefits: prompt.benefits })
61
62
  });
@@ -1,21 +1,19 @@
1
+ import { text } from "./messages.js";
1
2
  import { CodeForm } from "./code-form.js";
2
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { slotted } from "../locale/slotted.js";
4
+ import { Fragment, jsx } from "react/jsx-runtime";
3
5
  //#region src/auth/sign-up-code-form.tsx
4
6
  /** The second step of making an account: the emailed code on its own, before the name and password. */
5
7
  const SignUpCodeForm = ({ email, onBack, ...rest }) => /* @__PURE__ */ jsx(CodeForm, {
6
- title: "Check your email",
7
- description: "Enter the code we sent to create your account.",
8
- explanation: /* @__PURE__ */ jsxs(Fragment, { children: [
9
- "A 6-digit code is on its way to ",
10
- /* @__PURE__ */ jsx("span", {
11
- className: "font-medium text-foreground",
12
- children: email
13
- }),
14
- ". It works for 5 minutes, once. If the address has an account already, the email says so instead."
15
- ] }),
16
- submitLabel: "Continue",
8
+ title: text("checkEmail"),
9
+ description: text("signUpCodeDescription"),
10
+ explanation: /* @__PURE__ */ jsx(Fragment, { children: slotted(text("signUpCodeSent"), /* @__PURE__ */ jsx("span", {
11
+ className: "font-medium text-foreground",
12
+ children: email
13
+ })) }),
14
+ submitLabel: text("continue"),
17
15
  onChangeAddress: onBack,
18
- changeAddressLabel: "Use another address",
16
+ changeAddressLabel: text("useAnotherAddress"),
19
17
  ...rest
20
18
  });
21
19
  //#endregion
@@ -1,6 +1,8 @@
1
1
  import { Input } from "../primitives/input.js";
2
+ import { text } from "./messages.js";
2
3
  import { Button } from "../primitives/button.js";
3
4
  import { AuthLayout } from "./auth-layout.js";
5
+ import { slotted } from "../locale/slotted.js";
4
6
  import { useId, useState } from "react";
5
7
  import { jsx, jsxs } from "react/jsx-runtime";
6
8
  //#region src/auth/sign-up-details-form.tsx
@@ -12,18 +14,14 @@ const SignUpDetailsForm = ({ email, onSubmit, onBack, methods, busy, error }) =>
12
14
  const withPassword = methods.includes("password");
13
15
  const passwordOptional = methods.includes("emailCode");
14
16
  return /* @__PURE__ */ jsxs(AuthLayout, {
15
- title: "Your details",
16
- description: "One last step to create your account.",
17
- children: [/* @__PURE__ */ jsxs("p", {
17
+ title: text("detailsTitle"),
18
+ description: text("detailsDescription"),
19
+ children: [/* @__PURE__ */ jsx("p", {
18
20
  className: "mb-4 text-muted-foreground",
19
- children: [
20
- "The code was right: the account is for ",
21
- /* @__PURE__ */ jsx("span", {
22
- className: "font-medium text-foreground",
23
- children: email
24
- }),
25
- "."
26
- ]
21
+ children: slotted(text("codeWasRight"), /* @__PURE__ */ jsx("span", {
22
+ className: "font-medium text-foreground",
23
+ children: email
24
+ }))
27
25
  }), /* @__PURE__ */ jsxs("form", {
28
26
  className: "flex flex-col gap-4",
29
27
  onSubmit: (event) => {
@@ -36,7 +34,7 @@ const SignUpDetailsForm = ({ email, onSubmit, onBack, methods, busy, error }) =>
36
34
  children: [
37
35
  /* @__PURE__ */ jsxs("label", {
38
36
  className: "flex flex-col gap-1.5 font-medium",
39
- children: ["Your name", /* @__PURE__ */ jsx(Input, {
37
+ children: [text("yourName"), /* @__PURE__ */ jsx(Input, {
40
38
  name: "name",
41
39
  autoComplete: "name",
42
40
  required: true,
@@ -51,7 +49,7 @@ const SignUpDetailsForm = ({ email, onSubmit, onBack, methods, busy, error }) =>
51
49
  className: "flex flex-col gap-1.5",
52
50
  children: [/* @__PURE__ */ jsxs("label", {
53
51
  className: "flex flex-col gap-1.5 font-medium",
54
- children: [passwordOptional ? "Password (optional)" : "Password", /* @__PURE__ */ jsx(Input, {
52
+ children: [passwordOptional ? text("passwordOptional") : text("password"), /* @__PURE__ */ jsx(Input, {
55
53
  type: "password",
56
54
  name: "password",
57
55
  autoComplete: "new-password",
@@ -66,12 +64,7 @@ const SignUpDetailsForm = ({ email, onSubmit, onBack, methods, busy, error }) =>
66
64
  }), /* @__PURE__ */ jsxs("p", {
67
65
  id: passwordHint,
68
66
  className: "text-xs text-muted-foreground",
69
- children: [
70
- "At least ",
71
- 12,
72
- " characters.",
73
- passwordOptional && " Without one, you sign in with a code we email you."
74
- ]
67
+ children: [text("atLeast", 12), passwordOptional && text("withoutPassword")]
75
68
  })]
76
69
  }),
77
70
  error && /* @__PURE__ */ jsx("p", {
@@ -84,13 +77,13 @@ const SignUpDetailsForm = ({ email, onSubmit, onBack, methods, busy, error }) =>
84
77
  type: "submit",
85
78
  loading: busy,
86
79
  className: "min-h-10",
87
- children: "Create account"
80
+ children: text("createAccount")
88
81
  }),
89
82
  /* @__PURE__ */ jsx(Button, {
90
83
  variant: "ghost",
91
84
  onClick: onBack,
92
85
  className: "min-h-10",
93
- children: "Use another address"
86
+ children: text("useAnotherAddress")
94
87
  })
95
88
  ]
96
89
  })]
@@ -1,4 +1,5 @@
1
1
  import { Input } from "../primitives/input.js";
2
+ import { text } from "./messages.js";
2
3
  import { Button } from "../primitives/button.js";
3
4
  import { AuthLayout } from "./auth-layout.js";
4
5
  import { useState } from "react";
@@ -9,7 +10,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
9
10
  const SignUpEmailForm = ({ onSubmit, onSignIn, onBrowse, busy, error, workspace }) => {
10
11
  const [email, setEmail] = useState("");
11
12
  return /* @__PURE__ */ jsxs(AuthLayout, {
12
- title: "Create an account",
13
+ title: text("createAnAccount"),
13
14
  description: workspace,
14
15
  children: [/* @__PURE__ */ jsxs("form", {
15
16
  className: "flex flex-col gap-4",
@@ -20,7 +21,7 @@ const SignUpEmailForm = ({ onSubmit, onSignIn, onBrowse, busy, error, workspace
20
21
  children: [
21
22
  /* @__PURE__ */ jsxs("label", {
22
23
  className: "flex flex-col gap-1.5 font-medium",
23
- children: ["Email", /* @__PURE__ */ jsx(Input, {
24
+ children: [text("email"), /* @__PURE__ */ jsx(Input, {
24
25
  type: "email",
25
26
  name: "email",
26
27
  autoComplete: "email",
@@ -34,7 +35,7 @@ const SignUpEmailForm = ({ onSubmit, onSignIn, onBrowse, busy, error, workspace
34
35
  }),
35
36
  /* @__PURE__ */ jsx("p", {
36
37
  className: "text-muted-foreground",
37
- children: "We email you a code to make sure the address is yours."
38
+ children: text("codeToConfirm")
38
39
  }),
39
40
  error && /* @__PURE__ */ jsx("p", {
40
41
  role: "alert",
@@ -46,18 +47,18 @@ const SignUpEmailForm = ({ onSubmit, onSignIn, onBrowse, busy, error, workspace
46
47
  type: "submit",
47
48
  loading: busy,
48
49
  className: "min-h-10",
49
- children: [/* @__PURE__ */ jsx(Mail, { className: "size-4" }), "Email me a code"]
50
+ children: [/* @__PURE__ */ jsx(Mail, { className: "size-4" }), text("emailCode")]
50
51
  }),
51
52
  /* @__PURE__ */ jsxs("p", {
52
53
  className: "text-center text-muted-foreground",
53
54
  children: [
54
- "Have an account?",
55
+ text("haveAccount"),
55
56
  " ",
56
57
  /* @__PURE__ */ jsx("button", {
57
58
  type: "button",
58
59
  onClick: onSignIn,
59
60
  className: "font-medium text-primary-text hover:underline",
60
- children: "Sign in"
61
+ children: text("signIn")
61
62
  })
62
63
  ]
63
64
  })
@@ -66,7 +67,7 @@ const SignUpEmailForm = ({ onSubmit, onSignIn, onBrowse, busy, error, workspace
66
67
  type: "button",
67
68
  onClick: onBrowse,
68
69
  className: "mt-4 w-full text-center font-medium text-muted-foreground hover:text-foreground hover:underline",
69
- children: "Continue without an account"
70
+ children: text("browseWithoutAccount")
70
71
  })]
71
72
  });
72
73
  };
@@ -1,4 +1,5 @@
1
1
  import { authMessage } from "./auth-messages.js";
2
+ import { text } from "./messages.js";
2
3
  import { useAuth } from "./auth-provider.js";
3
4
  import { SignUpCodeForm } from "./sign-up-code-form.js";
4
5
  import { SignUpDetailsForm } from "./sign-up-details-form.js";
@@ -49,7 +50,7 @@ const SignUpPage = ({ workspace, email, ticket, onCodeSent, onVerified, onBack,
49
50
  onSubmit: (code) => void attempt(async () => onVerified(await verifySignUpCode(email, code))),
50
51
  onResend: () => void attempt(async () => {
51
52
  await sendSignUpCode(email);
52
- setNotice("A new code is on its way. Only the newest one works.");
53
+ setNotice(text("newCodeSent"));
53
54
  })
54
55
  });
55
56
  return /* @__PURE__ */ jsx(SignUpDetailsForm, {
@@ -1,5 +1,6 @@
1
1
  import { cn } from "../lib/cn.js";
2
2
  import { Input } from "../primitives/input.js";
3
+ import { text } from "./messages.js";
3
4
  import { Button } from "../primitives/button.js";
4
5
  import { AuthLayout } from "./auth-layout.js";
5
6
  import { useState } from "react";
@@ -11,8 +12,8 @@ const StaffSignInForm = ({ operator, email: givenEmail = "", reason: givenReason
11
12
  const [email, setEmail] = useState(givenEmail);
12
13
  const [reason, setReason] = useState(givenReason);
13
14
  if (!operator) return /* @__PURE__ */ jsxs(AuthLayout, {
14
- title: "Staff sign-in",
15
- description: "Staff of the team that runs this app cannot sign in as people here.",
15
+ title: text("staffTitle"),
16
+ description: text("staffUnavailable"),
16
17
  children: [error && /* @__PURE__ */ jsx("p", {
17
18
  role: "alert",
18
19
  className: "mb-4 text-xs font-medium text-danger-text",
@@ -21,12 +22,12 @@ const StaffSignInForm = ({ operator, email: givenEmail = "", reason: givenReason
21
22
  variant: "primary",
22
23
  className: "min-h-10 w-full",
23
24
  onClick: onBack,
24
- children: "Back to sign in"
25
+ children: text("backToSignIn")
25
26
  })]
26
27
  });
27
28
  return /* @__PURE__ */ jsx(AuthLayout, {
28
- title: "Sign in as a person",
29
- description: `For staff of ${operator}, to help someone with this app.`,
29
+ title: text("signInAsPerson"),
30
+ description: text("forStaffOf", operator),
30
31
  children: /* @__PURE__ */ jsxs("form", {
31
32
  className: "flex flex-col gap-4",
32
33
  onSubmit: (event) => {
@@ -36,7 +37,7 @@ const StaffSignInForm = ({ operator, email: givenEmail = "", reason: givenReason
36
37
  children: [
37
38
  /* @__PURE__ */ jsxs("label", {
38
39
  className: "flex flex-col gap-1.5 font-medium",
39
- children: ["Their email", /* @__PURE__ */ jsx(Input, {
40
+ children: [text("theirEmail"), /* @__PURE__ */ jsx(Input, {
40
41
  type: "email",
41
42
  name: "email",
42
43
  required: true,
@@ -48,42 +49,38 @@ const StaffSignInForm = ({ operator, email: givenEmail = "", reason: givenReason
48
49
  }),
49
50
  /* @__PURE__ */ jsxs("label", {
50
51
  className: "flex flex-col gap-1.5 font-medium",
51
- children: ["Reason", /* @__PURE__ */ jsx("textarea", {
52
+ children: [text("reason"), /* @__PURE__ */ jsx("textarea", {
52
53
  name: "reason",
53
54
  required: true,
54
55
  minLength: minimumReason,
55
56
  rows: 3,
56
57
  value: reason,
57
- placeholder: "Ticket 4211: the invoice totals look wrong",
58
+ placeholder: text("reasonExample"),
58
59
  onChange: (event) => setReason(event.target.value),
59
60
  className: cn("resize-y rounded-md border bg-background px-2.5 py-1.5 font-normal shadow-sm outline-none placeholder:text-faint-foreground focus:border-primary focus:ring-2 focus:ring-primary/20", error ? "border-danger" : "border-border-strong")
60
61
  })]
61
62
  }),
62
- /* @__PURE__ */ jsxs("p", {
63
+ /* @__PURE__ */ jsx("p", {
63
64
  className: "text-xs text-muted-foreground",
64
- children: [
65
- "You sign in at ",
66
- operator,
67
- " with a passkey or a second step. The session is short, shows a banner, and cannot change their sign-in. The app's admins see who signed in as whom, and why."
68
- ]
65
+ children: text("staffExplanation", operator)
69
66
  }),
70
67
  error && /* @__PURE__ */ jsx("p", {
71
68
  role: "alert",
72
69
  className: "text-xs font-medium text-danger-text",
73
70
  children: error
74
71
  }),
75
- /* @__PURE__ */ jsxs(Button, {
72
+ /* @__PURE__ */ jsx(Button, {
76
73
  variant: "primary",
77
74
  type: "submit",
78
75
  loading: busy,
79
76
  className: "min-h-10",
80
- children: ["Continue with ", operator]
77
+ children: text("continueWith", operator)
81
78
  }),
82
79
  /* @__PURE__ */ jsx(Button, {
83
80
  variant: "ghost",
84
81
  onClick: onBack,
85
82
  className: "min-h-10",
86
- children: "Back to sign in"
83
+ children: text("backToSignIn")
87
84
  })
88
85
  ]
89
86
  })
@@ -1,4 +1,5 @@
1
1
  import { Input } from "../primitives/input.js";
2
+ import { text } from "./messages.js";
2
3
  import { Button } from "../primitives/button.js";
3
4
  import { OtpInput } from "../primitives/otp-input.js";
4
5
  import { AuthLayout } from "./auth-layout.js";
@@ -7,9 +8,9 @@ import { useState } from "react";
7
8
  import { jsx, jsxs } from "react/jsx-runtime";
8
9
  //#region src/auth/two-factor-form.tsx
9
10
  const instructions = {
10
- totp: "Enter the 6-digit code from your authenticator app.",
11
- otp: "Enter the 6-digit code we emailed you. It works for 5 minutes.",
12
- backup: "Enter one of the backup codes you saved when you set up the authenticator app. Each works once."
11
+ totp: "totpInstruction",
12
+ otp: "otpInstruction",
13
+ backup: "backupInstruction"
13
14
  };
14
15
  /** The second step of a sign-in, for an account with two-factor authentication. */
15
16
  const TwoFactorForm = ({ methods, onVerify, onSendCode, onBack, busy, error, codeSent, initialStep }) => {
@@ -23,14 +24,14 @@ const TwoFactorForm = ({ methods, onVerify, onSendCode, onBack, busy, error, cod
23
24
  if (next === "otp" && !codeSent) onSendCode();
24
25
  };
25
26
  return /* @__PURE__ */ jsxs(AuthLayout, {
26
- title: "Two-factor authentication",
27
- description: "One more step to sign in.",
27
+ title: text("twoFactorTitle"),
28
+ description: text("twoFactorDescription"),
28
29
  children: [waitingForEmail ? /* @__PURE__ */ jsxs("div", {
29
30
  className: "flex flex-col gap-4",
30
31
  children: [
31
32
  /* @__PURE__ */ jsx("p", {
32
33
  className: "text-muted-foreground",
33
- children: "We email you a code to finish signing in."
34
+ children: text("codeToFinish")
34
35
  }),
35
36
  error && /* @__PURE__ */ jsx("p", {
36
37
  role: "alert",
@@ -42,7 +43,7 @@ const TwoFactorForm = ({ methods, onVerify, onSendCode, onBack, busy, error, cod
42
43
  loading: busy,
43
44
  onClick: onSendCode,
44
45
  className: "min-h-10",
45
- children: "Email me a code"
46
+ children: text("emailCode")
46
47
  })
47
48
  ]
48
49
  }) : /* @__PURE__ */ jsxs("form", {
@@ -58,11 +59,11 @@ const TwoFactorForm = ({ methods, onVerify, onSendCode, onBack, busy, error, cod
58
59
  children: [
59
60
  /* @__PURE__ */ jsx("p", {
60
61
  className: "text-muted-foreground",
61
- children: instructions[step]
62
+ children: text(instructions[step])
62
63
  }),
63
64
  /* @__PURE__ */ jsxs("label", {
64
65
  className: "flex flex-col gap-1.5 font-medium",
65
- children: [step === "backup" ? "Backup code" : "Code", step === "backup" ? /* @__PURE__ */ jsx(Input, {
66
+ children: [step === "backup" ? text("backupCode") : text("code"), step === "backup" ? /* @__PURE__ */ jsx(Input, {
66
67
  name: "code",
67
68
  autoComplete: "off",
68
69
  spellCheck: false,
@@ -86,8 +87,8 @@ const TwoFactorForm = ({ methods, onVerify, onSendCode, onBack, busy, error, cod
86
87
  children: [/* @__PURE__ */ jsx(Checkbox, {
87
88
  checked: trustDevice,
88
89
  onChange: setTrustDevice,
89
- label: "Trust this browser"
90
- }), "Don't ask again in this browser for 30 days"]
90
+ label: text("trustBrowser")
91
+ }), text("trustBrowserFor")]
91
92
  }),
92
93
  error && /* @__PURE__ */ jsx("p", {
93
94
  role: "alert",
@@ -99,7 +100,7 @@ const TwoFactorForm = ({ methods, onVerify, onSendCode, onBack, busy, error, cod
99
100
  type: "submit",
100
101
  loading: busy,
101
102
  className: "min-h-10",
102
- children: "Verify"
103
+ children: text("verify")
103
104
  })
104
105
  ]
105
106
  }), /* @__PURE__ */ jsxs("div", {
@@ -109,25 +110,25 @@ const TwoFactorForm = ({ methods, onVerify, onSendCode, onBack, busy, error, cod
109
110
  type: "button",
110
111
  onClick: () => switchTo("totp"),
111
112
  className: "font-medium text-primary-text hover:underline",
112
- children: "Use the authenticator app"
113
+ children: text("useAuthenticator")
113
114
  }),
114
115
  step !== "otp" && methods.includes("otp") && /* @__PURE__ */ jsx("button", {
115
116
  type: "button",
116
117
  onClick: () => switchTo("otp"),
117
118
  className: "font-medium text-primary-text hover:underline",
118
- children: "Email me a code instead"
119
+ children: text("emailCodeInstead")
119
120
  }),
120
121
  step !== "backup" && methods.includes("totp") && /* @__PURE__ */ jsx("button", {
121
122
  type: "button",
122
123
  onClick: () => switchTo("backup"),
123
124
  className: "font-medium text-primary-text hover:underline",
124
- children: "Use a backup code"
125
+ children: text("useBackupCode")
125
126
  }),
126
127
  /* @__PURE__ */ jsx("button", {
127
128
  type: "button",
128
129
  onClick: onBack,
129
130
  className: "font-medium text-muted-foreground hover:underline",
130
- children: "Back to sign in"
131
+ children: text("backToSignIn")
131
132
  })
132
133
  ]
133
134
  })]
@@ -1,3 +1,4 @@
1
+ import { text } from "./messages.js";
1
2
  //#region src/auth/user-to-shell.ts
2
3
  /** The hue of someone's avatar, the same for the same id. */
3
4
  const hueOf = (text) => [...text].reduce((sum, char) => (sum * 31 + char.charCodeAt(0)) % 360, 7);
@@ -15,7 +16,7 @@ const userToShell = (user) => {
15
16
  email: user.email,
16
17
  initials: initialsOf(user.name || user.email) || "?",
17
18
  hue: hueOf(user.id || user.email),
18
- role: admin ? "Admin" : (roles[0] ?? "user").replace(/^./, (char) => char.toUpperCase()),
19
+ role: admin ? text("admin") : (roles[0] ?? "user").replace(/^./, (char) => char.toUpperCase()),
19
20
  roleTone: admin ? "violet" : "blue"
20
21
  };
21
22
  };
@@ -1,17 +1,18 @@
1
1
  import { Input } from "../primitives/input.js";
2
2
  import { Button } from "../primitives/button.js";
3
+ import { text } from "./messages.js";
3
4
  import { useState } from "react";
4
5
  import { SendHorizontal } from "lucide-react";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
6
7
  //#region src/chat/composer.tsx
7
8
  /** The text box under a chat. Enter or the button sends the trimmed text and clears the box. */
8
9
  const Composer = ({ onSend, busy, placeholder, inputRef }) => {
9
- const [text, setText] = useState("");
10
- const message = text.trim();
10
+ const [draft, setDraft] = useState("");
11
+ const message = draft.trim();
11
12
  const send = () => {
12
13
  if (!message || busy) return;
13
14
  onSend?.(message);
14
- setText("");
15
+ setDraft("");
15
16
  };
16
17
  return /* @__PURE__ */ jsxs("form", {
17
18
  className: "flex gap-2",
@@ -21,16 +22,16 @@ const Composer = ({ onSend, busy, placeholder, inputRef }) => {
21
22
  },
22
23
  children: [/* @__PURE__ */ jsx(Input, {
23
24
  ref: inputRef,
24
- "aria-label": "Message",
25
+ "aria-label": text("message"),
25
26
  placeholder,
26
- value: text,
27
- onChange: (event) => setText(event.target.value),
27
+ value: draft,
28
+ onChange: (event) => setDraft(event.target.value),
28
29
  wrapperClassName: "flex-1"
29
30
  }), /* @__PURE__ */ jsx(Button, {
30
31
  type: "submit",
31
32
  variant: "primary",
32
33
  className: "w-8 px-0",
33
- "aria-label": "Send",
34
+ "aria-label": text("send"),
34
35
  disabled: !message || busy,
35
36
  children: /* @__PURE__ */ jsx(SendHorizontal, { className: "size-4" })
36
37
  })]
@@ -0,0 +1,14 @@
1
+ import { defineMessages } from "../locale/messages.js";
2
+ //#region src/chat/messages.ts
3
+ const text = defineMessages({
4
+ en: {
5
+ message: "Message",
6
+ send: "Send"
7
+ },
8
+ nl: {
9
+ message: "Bericht",
10
+ send: "Versturen"
11
+ }
12
+ });
13
+ //#endregion
14
+ export { text };
@@ -1,10 +1,11 @@
1
1
  import { cn } from "../lib/cn.js";
2
2
  import { formatCell } from "./format-cell.js";
3
+ import { text } from "./messages.js";
3
4
  import { jsx, jsxs } from "react/jsx-runtime";
4
5
  //#region src/compact-table/compact-table.tsx
5
6
  /** A small read-only table of raw values with a row count, for narrow places such as a side panel. */
6
7
  const CompactTable = ({ columns, rows, caption, truncated, className }) => /* @__PURE__ */ jsxs("section", {
7
- "aria-label": caption ?? "Table",
8
+ "aria-label": caption ?? text("table"),
8
9
  className: cn("shrink-0 overflow-hidden rounded-lg border border-border-strong bg-background shadow-sm", className),
9
10
  children: [
10
11
  caption && /* @__PURE__ */ jsx("code", {
@@ -13,7 +14,7 @@ const CompactTable = ({ columns, rows, caption, truncated, className }) => /* @_
13
14
  }),
14
15
  rows.length === 0 ? /* @__PURE__ */ jsx("p", {
15
16
  className: "px-3 py-2 text-xs text-muted-foreground",
16
- children: "No rows."
17
+ children: text("noRows")
17
18
  }) : /* @__PURE__ */ jsx("div", {
18
19
  className: "max-h-64 overflow-auto",
19
20
  children: /* @__PURE__ */ jsxs("table", {
@@ -36,12 +37,7 @@ const CompactTable = ({ columns, rows, caption, truncated, className }) => /* @_
36
37
  }),
37
38
  /* @__PURE__ */ jsxs("footer", {
38
39
  className: "border-t border-border px-3 py-1.5 text-[11px] text-muted-foreground",
39
- children: [
40
- rows.length,
41
- " ",
42
- rows.length === 1 ? "row" : "rows",
43
- truncated && ", cut off at the limit"
44
- ]
40
+ children: [text("rows", rows.length), truncated && text("cutOff")]
45
41
  })
46
42
  ]
47
43
  });