@jskit-ai/users-web 0.1.53 → 0.1.54

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 (70) hide show
  1. package/package.descriptor.mjs +15 -53
  2. package/package.json +16 -11
  3. package/src/client/account-settings/sections.js +74 -0
  4. package/src/client/composables/account-settings/accountSettingsRuntimeHelpers.js +2 -38
  5. package/src/client/composables/crud/crudLookupFieldRuntime.js +2 -2
  6. package/src/client/composables/internal/crudListParentTitleSupport.js +1 -1
  7. package/src/client/composables/internal/useOperationScope.js +12 -12
  8. package/src/client/composables/records/useAddEdit.js +2 -2
  9. package/src/client/composables/records/useList.js +3 -3
  10. package/src/client/composables/records/useView.js +2 -2
  11. package/src/client/composables/support/scopeHelpers.js +19 -19
  12. package/src/client/composables/useAccess.js +3 -3
  13. package/src/client/composables/useAccountSettingsRuntime.js +8 -156
  14. package/src/client/composables/useCommand.js +2 -2
  15. package/src/client/composables/useCrudListParentTitle.js +2 -2
  16. package/src/client/composables/usePaths.js +50 -38
  17. package/src/client/composables/useScopeRuntime.js +55 -27
  18. package/src/client/composables/useSurfaceRouteContext.js +1 -7
  19. package/src/client/index.js +0 -1
  20. package/src/client/lib/bootstrap.js +0 -63
  21. package/src/client/lib/httpClient.js +2 -59
  22. package/src/client/lib/theme.js +12 -189
  23. package/src/client/providers/UsersWebClientProvider.js +2 -25
  24. package/src/client/providers/bootUsersWebClientProvider.js +28 -0
  25. package/src/shared/toolsOutletContracts.js +1 -8
  26. package/templates/src/components/account/settings/AccountSettingsClientElement.vue +33 -21
  27. package/test/accountSettingsSections.test.js +79 -0
  28. package/test/exportsContract.test.js +2 -2
  29. package/test/scopeHelpers.test.js +6 -6
  30. package/test/settingsPlacementContract.test.js +4 -11
  31. package/test/theme.test.js +0 -56
  32. package/src/client/components/MembersAdminClientElement.vue +0 -400
  33. package/src/client/components/UsersProfileSurfaceSwitchMenuItem.vue +0 -39
  34. package/src/client/components/UsersWorkspaceMembersMenuItem.vue +0 -36
  35. package/src/client/components/UsersWorkspacePermissionMenuItem.vue +0 -90
  36. package/src/client/components/UsersWorkspaceSelector.vue +0 -248
  37. package/src/client/components/UsersWorkspaceSettingsMenuItem.vue +0 -39
  38. package/src/client/components/UsersWorkspaceToolsWidget.vue +0 -12
  39. package/src/client/components/WorkspaceMembersClientElement.vue +0 -655
  40. package/src/client/components/WorkspaceProfileClientElement.vue +0 -116
  41. package/src/client/components/WorkspaceSettingsClientElement.vue +0 -102
  42. package/src/client/components/WorkspaceSettingsFieldsClientElement.vue +0 -265
  43. package/src/client/components/WorkspacesClientElement.vue +0 -509
  44. package/src/client/composables/account-settings/accountSettingsInvitesRuntime.js +0 -88
  45. package/src/client/composables/useBootstrapQuery.js +0 -52
  46. package/src/client/composables/useWorkspaceRouteContext.js +0 -28
  47. package/src/client/composables/useWorkspaceSurfaceId.js +0 -43
  48. package/src/client/lib/menuIcons.js +0 -201
  49. package/src/client/lib/profileSurfaceMenuLinks.js +0 -142
  50. package/src/client/lib/surfaceAccessPolicy.js +0 -350
  51. package/src/client/lib/workspaceLinkResolver.js +0 -207
  52. package/src/client/lib/workspaceSurfaceContext.js +0 -82
  53. package/src/client/lib/workspaceSurfacePaths.js +0 -163
  54. package/src/client/providers/UsersWorkspacesClientProvider.js +0 -24
  55. package/src/client/runtime/bootstrapPlacementRouteGuards.js +0 -371
  56. package/src/client/runtime/bootstrapPlacementRuntime.js +0 -463
  57. package/src/client/runtime/bootstrapPlacementRuntimeConstants.js +0 -28
  58. package/src/client/runtime/bootstrapPlacementRuntimeHelpers.js +0 -147
  59. package/src/client/support/menuLinkTarget.js +0 -93
  60. package/src/client/support/realtimeWorkspace.js +0 -21
  61. package/src/client/support/runtimeNormalization.js +0 -27
  62. package/src/client/support/workspaceQueryKeys.js +0 -15
  63. package/templates/src/components/account/settings/AccountSettingsInvitesSection.vue +0 -77
  64. package/test/bootstrapPlacementRuntime.test.js +0 -1095
  65. package/test/menuIcons.test.js +0 -34
  66. package/test/menuLinkTarget.test.js +0 -116
  67. package/test/profileSurfaceMenuLinks.test.js +0 -208
  68. package/test/surfaceAccessPolicy.test.js +0 -129
  69. package/test/workspaceLinkResolver.test.js +0 -61
  70. package/test/workspaceSurfacePaths.test.js +0 -39
@@ -1,43 +0,0 @@
1
- import { computed, unref } from "vue";
2
- import { resolveSurfaceIdFromPlacementPathname } from "@jskit-ai/shell-web/client/placement";
3
- import {
4
- resolveSurfaceSwitchTargetsFromPlacementContext,
5
- surfaceRequiresWorkspaceFromPlacementContext
6
- } from "../lib/workspaceSurfaceContext.js";
7
-
8
- function resolveCurrentPathname(route = null) {
9
- const routePath = String(route?.path || "").trim();
10
- if (routePath) {
11
- return routePath;
12
- }
13
-
14
- if (typeof window === "object" && window?.location?.pathname) {
15
- return String(window.location.pathname);
16
- }
17
-
18
- return "/";
19
- }
20
-
21
- function useWorkspaceSurfaceId({ route = null, placementContext = null } = {}) {
22
- const currentSurfaceId = computed(() =>
23
- resolveSurfaceIdFromPlacementPathname(unref(placementContext), resolveCurrentPathname(route))
24
- );
25
-
26
- const workspaceSurfaceId = computed(() => {
27
- const contextValue = unref(placementContext);
28
- const surfaceId = String(currentSurfaceId.value || "").trim().toLowerCase();
29
- if (surfaceId && surfaceRequiresWorkspaceFromPlacementContext(contextValue, surfaceId)) {
30
- return surfaceId;
31
- }
32
-
33
- const targets = resolveSurfaceSwitchTargetsFromPlacementContext(contextValue, surfaceId);
34
- return String(targets.workspaceSurfaceId || "").trim().toLowerCase();
35
- });
36
-
37
- return Object.freeze({
38
- currentSurfaceId,
39
- workspaceSurfaceId
40
- });
41
- }
42
-
43
- export { useWorkspaceSurfaceId };
@@ -1,201 +0,0 @@
1
- import * as mdiIcons from "@mdi/js";
2
- import {
3
- mdiAccountCircleOutline,
4
- mdiAccountCogOutline,
5
- mdiAccountGroupOutline,
6
- mdiArrowRightCircleOutline,
7
- mdiClipboardListOutline,
8
- mdiCogOutline,
9
- mdiFolderOutline,
10
- mdiHomeVariantOutline,
11
- mdiLogin,
12
- mdiLogout,
13
- mdiRobotOutline,
14
- mdiShieldCrownOutline,
15
- mdiViewDashboardOutline,
16
- mdiViewListOutline
17
- } from "@mdi/js";
18
- import { isExternalLinkTarget, splitPathQueryHash } from "@jskit-ai/kernel/shared/support/linkPath";
19
- import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
20
- import { normalizePathname as normalizeKernelPathname } from "@jskit-ai/kernel/shared/surface/paths";
21
-
22
- const SURFACE_SWITCH_ICON_BY_ID = Object.freeze({
23
- home: mdiHomeVariantOutline,
24
- app: mdiViewDashboardOutline,
25
- admin: mdiShieldCrownOutline
26
- });
27
-
28
- function resolveExplicitIconValue(explicitIcon = "") {
29
- const normalizedExplicitIcon = normalizeText(explicitIcon);
30
- if (!normalizedExplicitIcon) {
31
- return "";
32
- }
33
-
34
- if (!normalizedExplicitIcon.startsWith("mdi-")) {
35
- return normalizedExplicitIcon;
36
- }
37
-
38
- const iconKey = normalizedExplicitIcon
39
- .slice("mdi-".length)
40
- .split("-")
41
- .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
42
- .join("");
43
- const exportName = `mdi${iconKey}`;
44
- const resolvedIcon = mdiIcons[exportName];
45
- return typeof resolvedIcon === "string" && resolvedIcon ? resolvedIcon : normalizedExplicitIcon;
46
- }
47
-
48
- function normalizePathname(value) {
49
- const normalizedValue = normalizeText(value);
50
- if (!normalizedValue) {
51
- return "";
52
- }
53
-
54
- if (isExternalLinkTarget(normalizedValue)) {
55
- const isHttpTarget = normalizedValue.startsWith("http://") || normalizedValue.startsWith("https://");
56
- if (!isHttpTarget) {
57
- return "";
58
- }
59
-
60
- let parsedPathname = "";
61
- try {
62
- parsedPathname = String(new URL(normalizedValue).pathname || "");
63
- } catch {
64
- return "";
65
- }
66
-
67
- const normalizedPathname = normalizeText(parsedPathname);
68
- if (!normalizedPathname) {
69
- return "";
70
- }
71
- return normalizeKernelPathname(normalizedPathname).toLowerCase();
72
- }
73
-
74
- const { pathname } = splitPathQueryHash(normalizedValue);
75
- const normalizedPathname = normalizeText(pathname);
76
- if (!normalizedPathname) {
77
- return "";
78
- }
79
-
80
- return normalizeKernelPathname(normalizedPathname).toLowerCase();
81
- }
82
-
83
- function resolveSurfaceSwitchIdFromLabel(label = "") {
84
- const normalizedLabel = normalizeText(label).toLowerCase();
85
- if (!normalizedLabel.startsWith("go to ")) {
86
- return "";
87
- }
88
- return normalizeText(normalizedLabel.slice("go to ".length));
89
- }
90
-
91
- function resolveSurfaceSwitchIcon(surfaceId = "", explicitIcon = "") {
92
- const resolvedExplicitIcon = resolveExplicitIconValue(explicitIcon);
93
- if (resolvedExplicitIcon) {
94
- return resolvedExplicitIcon;
95
- }
96
-
97
- const normalizedSurfaceId = normalizeText(surfaceId).toLowerCase();
98
- return SURFACE_SWITCH_ICON_BY_ID[normalizedSurfaceId] || mdiArrowRightCircleOutline;
99
- }
100
-
101
- function resolveMenuLinkIcon({ icon = "", label = "", to = "" } = {}) {
102
- const resolvedExplicitIcon = resolveExplicitIconValue(icon);
103
- if (resolvedExplicitIcon) {
104
- return resolvedExplicitIcon;
105
- }
106
-
107
- const normalizedLabel = normalizeText(label).toLowerCase();
108
- const normalizedPathname = normalizePathname(to);
109
- if (!normalizedLabel && !normalizedPathname) {
110
- return "";
111
- }
112
-
113
- const surfaceSwitchSurfaceId = resolveSurfaceSwitchIdFromLabel(normalizedLabel);
114
- if (surfaceSwitchSurfaceId) {
115
- return resolveSurfaceSwitchIcon(surfaceSwitchSurfaceId);
116
- }
117
-
118
- if (
119
- normalizedLabel.includes("sign in") ||
120
- normalizedPathname.includes("/auth/login")
121
- ) {
122
- return mdiLogin;
123
- }
124
-
125
- if (
126
- normalizedLabel.includes("sign out") ||
127
- normalizedPathname.includes("/auth/signout")
128
- ) {
129
- return mdiLogout;
130
- }
131
-
132
- if (
133
- normalizedLabel.includes("account") ||
134
- normalizedPathname.includes("/account")
135
- ) {
136
- if (
137
- normalizedLabel.includes("settings") ||
138
- normalizedPathname.includes("/settings") ||
139
- normalizedPathname === "/account"
140
- ) {
141
- return mdiAccountCogOutline;
142
- }
143
- return mdiAccountCircleOutline;
144
- }
145
-
146
- if (
147
- normalizedLabel.includes("members") ||
148
- normalizedLabel.includes("team") ||
149
- normalizedPathname.includes("/members")
150
- ) {
151
- return mdiAccountGroupOutline;
152
- }
153
-
154
- if (normalizedLabel.includes("assistant") || normalizedPathname.includes("/assistant")) {
155
- return mdiRobotOutline;
156
- }
157
-
158
- if (
159
- normalizedLabel.includes("admin") ||
160
- normalizedPathname.includes("/admin")
161
- ) {
162
- return mdiShieldCrownOutline;
163
- }
164
-
165
- if (normalizedLabel.includes("settings") || normalizedPathname.includes("/settings")) {
166
- return mdiCogOutline;
167
- }
168
-
169
- if (
170
- normalizedLabel.includes("home") ||
171
- normalizedPathname === "/"
172
- ) {
173
- return mdiHomeVariantOutline;
174
- }
175
-
176
- if (
177
- normalizedLabel.includes("workspace") ||
178
- normalizedLabel.includes("dashboard") ||
179
- normalizedPathname.includes("/w/")
180
- ) {
181
- return mdiViewDashboardOutline;
182
- }
183
-
184
- if (normalizedPathname) {
185
- const segments = normalizedPathname.split("/").filter(Boolean);
186
- if (segments.length === 1) {
187
- return mdiFolderOutline;
188
- }
189
- }
190
-
191
- if (normalizedLabel.includes("list")) {
192
- return mdiClipboardListOutline;
193
- }
194
-
195
- return mdiViewListOutline;
196
- }
197
-
198
- export {
199
- resolveMenuLinkIcon,
200
- resolveSurfaceSwitchIcon
201
- };
@@ -1,142 +0,0 @@
1
- import {
2
- resolveSurfaceIdFromPlacementPathname
3
- } from "@jskit-ai/shell-web/client/placement";
4
- import { resolveWorkspaceShellLinkPath } from "./workspaceLinkResolver.js";
5
- import { resolveSurfaceSwitchTargetsFromPlacementContext } from "./workspaceSurfaceContext.js";
6
- import { evaluateSurfaceAccess, hasWorkspaceMembership } from "./surfaceAccessPolicy.js";
7
- import {
8
- resolveWorkspaceSurfaceIdFromPlacementPathname,
9
- extractWorkspaceSlugFromSurfacePathname
10
- } from "./workspaceSurfacePaths.js";
11
- import { resolveSurfaceSwitchIcon } from "./menuIcons.js";
12
-
13
- function resolveCurrentWorkspaceSlug(contextValue, surfaceId) {
14
- const context = contextValue && typeof contextValue === "object" ? contextValue : {};
15
- const workspaceSlugFromContext = String(context?.workspace?.slug || "").trim();
16
- if (workspaceSlugFromContext) {
17
- return workspaceSlugFromContext;
18
- }
19
-
20
- if (typeof window !== "object" || !window?.location?.pathname) {
21
- return "";
22
- }
23
-
24
- const pathname = String(window.location.pathname || "").trim();
25
- const currentSurfaceId =
26
- resolveWorkspaceSurfaceIdFromPlacementPathname(context, pathname) ||
27
- resolveSurfaceIdFromPlacementPathname(context, pathname) ||
28
- surfaceId;
29
- return String(extractWorkspaceSlugFromSurfacePathname(context, currentSurfaceId, pathname) || "").trim();
30
- }
31
-
32
- function shouldIncludeSurfaceSwitchTarget(surfaceDefinition = null) {
33
- if (!surfaceDefinition || typeof surfaceDefinition !== "object") {
34
- return false;
35
- }
36
-
37
- if (surfaceDefinition.enabled === false) {
38
- return false;
39
- }
40
-
41
- if (surfaceDefinition.showInSurfaceSwitchMenu === true) {
42
- return true;
43
- }
44
- if (surfaceDefinition.showInSurfaceSwitchMenu === false) {
45
- return false;
46
- }
47
-
48
- return surfaceDefinition.requiresWorkspace === true || surfaceDefinition.requiresAuth === true;
49
- }
50
-
51
- function resolveSurfaceSwitchLinkLabel(surfaceDefinition = null, surfaceId = "") {
52
- const normalizedSurfaceId = String(surfaceId || "").trim();
53
- const configuredLabel = String(surfaceDefinition?.label || "").trim();
54
- const label = configuredLabel || normalizedSurfaceId;
55
- if (!label) {
56
- return "Go to surface";
57
- }
58
- return `Go to ${label.toLowerCase()}`;
59
- }
60
-
61
- function resolveSurfaceSwitchLinks({ context, surface } = {}) {
62
- const source = context && typeof context === "object" ? context : {};
63
- const targets = resolveSurfaceSwitchTargetsFromPlacementContext(source, surface);
64
- const currentSurfaceId = String(targets.currentSurfaceId || "").trim().toLowerCase();
65
- const resolvedWorkspaceSlug = resolveCurrentWorkspaceSlug(source, currentSurfaceId || surface);
66
- const workspaceSlug = hasWorkspaceMembership(source, resolvedWorkspaceSlug) ? resolvedWorkspaceSlug : "";
67
- const enabledSurfaceIds = Array.isArray(targets?.surfaceConfig?.enabledSurfaceIds)
68
- ? targets.surfaceConfig.enabledSurfaceIds
69
- : [];
70
- const links = [];
71
-
72
- for (const targetSurfaceIdCandidate of enabledSurfaceIds) {
73
- const targetSurfaceId = String(targetSurfaceIdCandidate || "").trim().toLowerCase();
74
- if (!targetSurfaceId) {
75
- continue;
76
- }
77
- if (targetSurfaceId === currentSurfaceId) {
78
- continue;
79
- }
80
-
81
- const targetSurface = targets.surfaceConfig.surfacesById[targetSurfaceId] || null;
82
- if (!shouldIncludeSurfaceSwitchTarget(targetSurface)) {
83
- continue;
84
- }
85
-
86
- const targetWorkspaceSlug = targetSurface?.requiresWorkspace === true ? workspaceSlug : "";
87
- if (targetSurface?.requiresWorkspace === true && !targetWorkspaceSlug) {
88
- continue;
89
- }
90
-
91
- const accessDecision = evaluateSurfaceAccess({
92
- context: source,
93
- surfaceId: targetSurfaceId,
94
- workspaceSlug: targetWorkspaceSlug
95
- });
96
- if (!accessDecision.allowed) {
97
- continue;
98
- }
99
-
100
- links.push({
101
- id: `surface-switch.${targetSurfaceId}`,
102
- label: resolveSurfaceSwitchLinkLabel(targetSurface, targetSurfaceId),
103
- icon: resolveSurfaceSwitchIcon(targetSurfaceId, targetSurface?.icon),
104
- to: resolveWorkspaceShellLinkPath({
105
- context: source,
106
- surface: targetSurfaceId,
107
- workspaceSlug: targetWorkspaceSlug,
108
- mode: targetSurface?.requiresWorkspace === true ? "workspace" : "surface",
109
- relativePath: "/"
110
- })
111
- });
112
- }
113
-
114
- return links;
115
- }
116
-
117
- function resolvePrimarySurfaceSwitchLink({ context, surface } = {}) {
118
- const links = resolveSurfaceSwitchLinks({
119
- context,
120
- surface
121
- });
122
- return links[0] || null;
123
- }
124
-
125
- function resolveProfileSurfaceMenuLinks({ context, surface } = {}) {
126
- const source = context && typeof context === "object" ? context : {};
127
- const authenticated = Boolean(source?.auth?.authenticated);
128
- if (!authenticated) {
129
- return [];
130
- }
131
- return resolveSurfaceSwitchLinks({
132
- context: source,
133
- surface
134
- });
135
- }
136
-
137
- export {
138
- resolveProfileSurfaceMenuLinks,
139
- resolvePrimarySurfaceSwitchLink,
140
- resolveSurfaceSwitchLinks,
141
- hasWorkspaceMembership
142
- };