@stapel/workspaces-react 0.17.0 → 0.19.0

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 (123) hide show
  1. package/CHANGELOG.md +183 -0
  2. package/README.md +39 -8
  3. package/dist/api/generated/schema.d.ts +187 -60
  4. package/dist/api/generated/schema.d.ts.map +1 -1
  5. package/dist/default/ActiveWorkspace.d.ts +43 -0
  6. package/dist/default/ActiveWorkspace.d.ts.map +1 -0
  7. package/dist/default/ActiveWorkspace.js +33 -0
  8. package/dist/default/ActiveWorkspace.js.map +1 -0
  9. package/dist/default/AuditTrailPane.d.ts +12 -0
  10. package/dist/default/AuditTrailPane.d.ts.map +1 -0
  11. package/dist/default/AuditTrailPane.js +154 -0
  12. package/dist/default/AuditTrailPane.js.map +1 -0
  13. package/dist/default/InvitationsPane.d.ts +19 -0
  14. package/dist/default/InvitationsPane.d.ts.map +1 -0
  15. package/dist/default/InvitationsPane.js +217 -0
  16. package/dist/default/InvitationsPane.js.map +1 -0
  17. package/dist/default/InviteAcceptPage.d.ts +7 -0
  18. package/dist/default/InviteAcceptPage.d.ts.map +1 -1
  19. package/dist/default/InviteAcceptPage.js +74 -38
  20. package/dist/default/InviteAcceptPage.js.map +1 -1
  21. package/dist/default/MembersManager.d.ts +12 -4
  22. package/dist/default/MembersManager.d.ts.map +1 -1
  23. package/dist/default/MembersManager.js +320 -84
  24. package/dist/default/MembersManager.js.map +1 -1
  25. package/dist/default/RoleSelectField.d.ts +64 -0
  26. package/dist/default/RoleSelectField.d.ts.map +1 -0
  27. package/dist/default/RoleSelectField.js +78 -0
  28. package/dist/default/RoleSelectField.js.map +1 -0
  29. package/dist/default/WorkspaceSettings.d.ts +7 -1
  30. package/dist/default/WorkspaceSettings.d.ts.map +1 -1
  31. package/dist/default/WorkspaceSettings.js +203 -45
  32. package/dist/default/WorkspaceSettings.js.map +1 -1
  33. package/dist/default/WorkspacesPage.d.ts +13 -0
  34. package/dist/default/WorkspacesPage.d.ts.map +1 -0
  35. package/dist/default/WorkspacesPage.js +108 -0
  36. package/dist/default/WorkspacesPage.js.map +1 -0
  37. package/dist/default/index.d.ts +28 -7
  38. package/dist/default/index.d.ts.map +1 -1
  39. package/dist/default/index.js +24 -7
  40. package/dist/default/index.js.map +1 -1
  41. package/dist/default/parts.d.ts +104 -0
  42. package/dist/default/parts.d.ts.map +1 -0
  43. package/dist/default/parts.js +140 -0
  44. package/dist/default/parts.js.map +1 -0
  45. package/dist/headless/Members.d.ts +59 -14
  46. package/dist/headless/Members.d.ts.map +1 -1
  47. package/dist/headless/Members.js +35 -10
  48. package/dist/headless/Members.js.map +1 -1
  49. package/dist/headless/RoleSelect.d.ts +9 -3
  50. package/dist/headless/RoleSelect.d.ts.map +1 -1
  51. package/dist/headless/RoleSelect.js +3 -2
  52. package/dist/headless/RoleSelect.js.map +1 -1
  53. package/dist/i18n/es.d.ts +11 -12
  54. package/dist/i18n/es.d.ts.map +1 -1
  55. package/dist/i18n/es.js +267 -14
  56. package/dist/i18n/es.js.map +1 -1
  57. package/dist/i18n/generated/errors.es.gen.d.ts.map +1 -1
  58. package/dist/i18n/generated/errors.es.gen.js +5 -0
  59. package/dist/i18n/generated/errors.es.gen.js.map +1 -1
  60. package/dist/i18n/generated/errors.gen.d.ts +30 -0
  61. package/dist/i18n/generated/errors.gen.d.ts.map +1 -1
  62. package/dist/i18n/generated/errors.gen.js +15 -0
  63. package/dist/i18n/generated/errors.gen.js.map +1 -1
  64. package/dist/i18n/generated/errors.ru.gen.d.ts.map +1 -1
  65. package/dist/i18n/generated/errors.ru.gen.js +5 -0
  66. package/dist/i18n/generated/errors.ru.gen.js.map +1 -1
  67. package/dist/i18n/keys.d.ts +209 -1
  68. package/dist/i18n/keys.d.ts.map +1 -1
  69. package/dist/i18n/keys.js +410 -4
  70. package/dist/i18n/keys.js.map +1 -1
  71. package/dist/i18n/ru.d.ts +7 -2
  72. package/dist/i18n/ru.d.ts.map +1 -1
  73. package/dist/i18n/ru.js +209 -4
  74. package/dist/i18n/ru.js.map +1 -1
  75. package/dist/index.d.ts +1 -1
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +1 -1
  78. package/dist/index.js.map +1 -1
  79. package/dist/model/format.d.ts +56 -0
  80. package/dist/model/format.d.ts.map +1 -0
  81. package/dist/model/format.js +125 -0
  82. package/dist/model/format.js.map +1 -0
  83. package/dist/model/selection.d.ts +15 -0
  84. package/dist/model/selection.d.ts.map +1 -1
  85. package/dist/model/selection.js +18 -1
  86. package/dist/model/selection.js.map +1 -1
  87. package/dist/nav/manifest.d.ts +45 -0
  88. package/dist/nav/manifest.d.ts.map +1 -0
  89. package/dist/nav/manifest.js +77 -0
  90. package/dist/nav/manifest.js.map +1 -0
  91. package/llms.txt +11 -10
  92. package/manifest.json +281 -69
  93. package/package.json +18 -12
  94. package/src/analytics/generated/events.json +1 -1
  95. package/src/api/generated/schema.ts +187 -60
  96. package/src/default/ActiveWorkspace.tsx +97 -0
  97. package/src/default/AuditTrailPane.tsx +309 -0
  98. package/src/default/InvitationsPane.tsx +501 -0
  99. package/src/default/InviteAcceptPage.tsx +187 -90
  100. package/src/default/MembersManager.tsx +832 -222
  101. package/src/default/RoleSelectField.tsx +187 -0
  102. package/src/default/WorkspaceSettings.tsx +540 -125
  103. package/src/default/WorkspacesPage.tsx +387 -0
  104. package/src/default/index.ts +28 -7
  105. package/src/default/parts.tsx +308 -0
  106. package/src/headless/Members.tsx +84 -16
  107. package/src/headless/RoleSelect.tsx +12 -5
  108. package/src/i18n/es.ts +326 -14
  109. package/src/i18n/generated/errors.es.gen.ts +5 -0
  110. package/src/i18n/generated/errors.gen.ts +15 -0
  111. package/src/i18n/generated/errors.json +37 -0
  112. package/src/i18n/generated/errors.ru.gen.ts +5 -0
  113. package/src/i18n/keys.ts +462 -5
  114. package/src/i18n/ru.ts +259 -5
  115. package/src/index.ts +1 -0
  116. package/src/model/format.ts +158 -0
  117. package/src/model/selection.tsx +19 -1
  118. package/src/nav/manifest.ts +120 -0
  119. package/dist/default/ErrorAlert.d.ts +0 -8
  120. package/dist/default/ErrorAlert.d.ts.map +0 -1
  121. package/dist/default/ErrorAlert.js +0 -30
  122. package/dist/default/ErrorAlert.js.map +0 -1
  123. package/src/default/ErrorAlert.tsx +0 -47
@@ -0,0 +1,120 @@
1
+ /**
2
+ * This pair's contribution to the scripted-fullstack nav contract
3
+ * (`@stapel/core`'s `NavEntry`/`PackageNavManifest`). `scripts/gen-nav-
4
+ * manifest.mjs` reads `navEntries` below, stamps `package`/`version` from THIS
5
+ * package's own `package.json` (never hand-copied here — a version bump must
6
+ * not require touching this file), and emits
7
+ * `packages/workspaces-react/nav-manifest.json` plus this package's slice of
8
+ * the root aggregate.
9
+ *
10
+ * ## The six doors
11
+ *
12
+ * - `workspaces.list` — the workspace roster (`<WorkspacesPage/>`), under the
13
+ * container-synthesised `account.root` submenu, next to privacy and
14
+ * billing. Everything it shows is the caller's own.
15
+ * - `workspaces.settings` / `.members` / `.invitations` / `.audit` — the four
16
+ * workspace-scoped admin screens, siblings of the roster under the same
17
+ * account section, on paths RELATIVE to it (`workspaces/members`, …).
18
+ * - `workspaces.invite` — the public `/invite/:token` route
19
+ * (`<InviteAcceptPage/>`). `surface: "public"` and `requiresAuth: false`
20
+ * because the invitee usually has no account here at all — that is the
21
+ * entire reason `claim` exists — and the token in the URL is the bearer
22
+ * secret. `menuVisibleDefault: false`: it is an address a letter sends
23
+ * somebody to, never a menu item.
24
+ *
25
+ * ## Where the four scoped screens get their workspace (architecture verdict)
26
+ *
27
+ * They do NOT get it from the route. The active workspace is RUNTIME state —
28
+ * the same state the container writes when a person switches workspaces
29
+ * (`WorkspaceSelection.switchTo`) — not a path param of a settings URL, so
30
+ * these entries declare no `:workspaceId` segment and the screens read the
31
+ * selection themselves (`useOptionalWorkspaceSelection`, see
32
+ * `src/default/ActiveWorkspace.tsx`). A host that mounts the same components
33
+ * outside the shell keeps passing `workspaceId` explicitly; the prop stayed,
34
+ * it only became optional.
35
+ *
36
+ * The failure mode that made this a question at all — four doors opening on a
37
+ * screen with no workspace — is answered by the screens rather than by the
38
+ * contract: with no active workspace they render a designed "choose a
39
+ * workspace" state (and "you are not in a workspace yet" for a person who
40
+ * belongs to none), never a blank page and never a crash from a selection
41
+ * provider a shell forgot to wire.
42
+ */
43
+ import type { NavEntry } from "@stapel/core";
44
+
45
+ export const navEntries: readonly NavEntry[] = [
46
+ {
47
+ id: "workspaces.list",
48
+ labelKey: "workspaces.nav.workspaces",
49
+ icon: "AppstoreOutlined",
50
+ route: { path: "workspaces" },
51
+ component: { export: "WorkspacesPage", subpath: "default" },
52
+ placement: { level: "submenu", parentId: "account.root" },
53
+ menuVisibleDefault: true,
54
+ requiresAuth: true,
55
+ surface: "member",
56
+ order: 10,
57
+ },
58
+ {
59
+ id: "workspaces.settings",
60
+ labelKey: "workspaces.nav.settings",
61
+ icon: "ProfileOutlined",
62
+ route: { path: "workspaces/settings" },
63
+ component: { export: "WorkspaceSettings", subpath: "default" },
64
+ placement: { level: "submenu", parentId: "account.root" },
65
+ menuVisibleDefault: true,
66
+ requiresAuth: true,
67
+ surface: "member",
68
+ order: 11,
69
+ },
70
+ {
71
+ id: "workspaces.members",
72
+ labelKey: "workspaces.nav.members",
73
+ icon: "UserOutlined",
74
+ route: { path: "workspaces/members" },
75
+ component: { export: "MembersManager", subpath: "default" },
76
+ placement: { level: "submenu", parentId: "account.root" },
77
+ menuVisibleDefault: true,
78
+ requiresAuth: true,
79
+ surface: "member",
80
+ order: 12,
81
+ },
82
+ {
83
+ id: "workspaces.invitations",
84
+ labelKey: "workspaces.nav.invitations",
85
+ icon: "MessageOutlined",
86
+ route: { path: "workspaces/invitations" },
87
+ component: { export: "InvitationsPane", subpath: "default" },
88
+ placement: { level: "submenu", parentId: "account.root" },
89
+ menuVisibleDefault: true,
90
+ requiresAuth: true,
91
+ surface: "member",
92
+ order: 13,
93
+ },
94
+ {
95
+ id: "workspaces.audit",
96
+ labelKey: "workspaces.nav.audit",
97
+ icon: "AuditOutlined",
98
+ route: { path: "workspaces/audit" },
99
+ component: { export: "AuditTrailPane", subpath: "default" },
100
+ placement: { level: "submenu", parentId: "account.root" },
101
+ menuVisibleDefault: true,
102
+ requiresAuth: true,
103
+ surface: "member",
104
+ order: 14,
105
+ },
106
+ {
107
+ id: "workspaces.invite",
108
+ labelKey: "workspaces.nav.invite",
109
+ icon: "MessageOutlined",
110
+ route: { path: "/invite/:token" },
111
+ component: { export: "InviteAcceptPage", subpath: "default" },
112
+ placement: { level: "top" },
113
+ menuVisibleDefault: false,
114
+ // A session is NOT needed: the whole point of the claim path is that the
115
+ // invitee has no account yet, and decline went `AllowAny` in 0.27.0.
116
+ requiresAuth: false,
117
+ surface: "public",
118
+ order: 0,
119
+ },
120
+ ];
@@ -1,8 +0,0 @@
1
- import type { CSSProperties, ReactElement } from "react";
2
- import type { FlowErrorDisplay } from "@stapel/core";
3
- export declare function ErrorAlert(props: {
4
- error: FlowErrorDisplay | undefined;
5
- style?: CSSProperties | undefined;
6
- testId?: string | undefined;
7
- }): ReactElement | null;
8
- //# sourceMappingURL=ErrorAlert.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ErrorAlert.d.ts","sourceRoot":"","sources":["../../src/default/ErrorAlert.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpC,KAAK,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B,GAAG,YAAY,GAAG,IAAI,CAqBtB"}
@@ -1,30 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- /**
3
- * The one error surface this pair's default skins render, so the split copy
4
- * core produces reaches a screen the same way everywhere.
5
- *
6
- * Core's `describeFlowError` splits a failure into the sentence a person
7
- * reads and the technical detail a support agent quotes (owner report
8
- * 2026-08-09: the status used to be spliced into the sentence, which ended
9
- * in a bare `" (500)"` — and a product does not read a protocol number out to
10
- * a person). The split is only worth anything if a
11
- * skin actually renders both halves at their own weights: `message` at
12
- * normal weight, `detail` muted and small, where an eye skips it and a
13
- * support agent finds it.
14
- *
15
- * `undefined` in — including a `detail` that core left `undefined` because
16
- * there was nothing worth quoting — renders nothing rather than an empty
17
- * muted line.
18
- */
19
- import { Alert, Typography } from "antd";
20
- export function ErrorAlert(props) {
21
- const { error } = props;
22
- if (!error)
23
- return null;
24
- return (_jsx(Alert, { type: "error", showIcon: true, ...(props.style ? { style: props.style } : {}), ...(props.testId ? { "data-testid": props.testId } : {}), message: error.message, ...(error.detail
25
- ? {
26
- description: (_jsx(Typography.Text, { type: "secondary", style: { fontSize: 12 }, children: error.detail })),
27
- }
28
- : {}) }));
29
- }
30
- //# sourceMappingURL=ErrorAlert.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ErrorAlert.js","sourceRoot":"","sources":["../../src/default/ErrorAlert.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAIzC,MAAM,UAAU,UAAU,CAAC,KAI1B;IACC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IACxB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,CACL,KAAC,KAAK,IACJ,IAAI,EAAC,OAAO,EACZ,QAAQ,WACJ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAC3C,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EACzD,OAAO,EAAE,KAAK,CAAC,OAAO,KAClB,CAAC,KAAK,CAAC,MAAM;YACf,CAAC,CAAC;gBACE,WAAW,EAAE,CACX,KAAC,UAAU,CAAC,IAAI,IAAC,IAAI,EAAC,WAAW,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,YACtD,KAAK,CAAC,MAAM,GACG,CACnB;aACF;YACH,CAAC,CAAC,EAAE,CAAC,GACP,CACH,CAAC;AACJ,CAAC"}
@@ -1,47 +0,0 @@
1
- /**
2
- * The one error surface this pair's default skins render, so the split copy
3
- * core produces reaches a screen the same way everywhere.
4
- *
5
- * Core's `describeFlowError` splits a failure into the sentence a person
6
- * reads and the technical detail a support agent quotes (owner report
7
- * 2026-08-09: the status used to be spliced into the sentence, which ended
8
- * in a bare `" (500)"` — and a product does not read a protocol number out to
9
- * a person). The split is only worth anything if a
10
- * skin actually renders both halves at their own weights: `message` at
11
- * normal weight, `detail` muted and small, where an eye skips it and a
12
- * support agent finds it.
13
- *
14
- * `undefined` in — including a `detail` that core left `undefined` because
15
- * there was nothing worth quoting — renders nothing rather than an empty
16
- * muted line.
17
- */
18
- import { Alert, Typography } from "antd";
19
- import type { CSSProperties, ReactElement } from "react";
20
- import type { FlowErrorDisplay } from "@stapel/core";
21
-
22
- export function ErrorAlert(props: {
23
- error: FlowErrorDisplay | undefined;
24
- style?: CSSProperties | undefined;
25
- testId?: string | undefined;
26
- }): ReactElement | null {
27
- const { error } = props;
28
- if (!error) return null;
29
- return (
30
- <Alert
31
- type="error"
32
- showIcon
33
- {...(props.style ? { style: props.style } : {})}
34
- {...(props.testId ? { "data-testid": props.testId } : {})}
35
- message={error.message}
36
- {...(error.detail
37
- ? {
38
- description: (
39
- <Typography.Text type="secondary" style={{ fontSize: 12 }}>
40
- {error.detail}
41
- </Typography.Text>
42
- ),
43
- }
44
- : {})}
45
- />
46
- );
47
- }