@jskit-ai/users-web 0.1.31 → 0.1.33

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.
@@ -23,10 +23,6 @@ import { useAddEdit } from "./useAddEdit.js";
23
23
  import { useCommand } from "./useCommand.js";
24
24
  import { useView } from "./useView.js";
25
25
  import { usePaths } from "./usePaths.js";
26
- import {
27
- ACCOUNT_SETTINGS_CHANGED_EVENT,
28
- WORKSPACE_PENDING_INVITATIONS_CHANGED_EVENT
29
- } from "@jskit-ai/users-core/shared/events/usersEvents";
30
26
  import { resolveAccountSettingsPathFromPlacementContext } from "../lib/workspaceSurfacePaths.js";
31
27
  import {
32
28
  ACCOUNT_SETTINGS_DEFAULTS,
@@ -206,22 +202,22 @@ function useAccountSettingsRuntime() {
206
202
 
207
203
  const settingsView = useView({
208
204
  ownershipFilter: OWNERSHIP_PUBLIC,
209
- apiSuffix: "/settings",
210
- queryKeyFactory: () => accountSettingsQueryKey,
211
- realtime: {
212
- event: ACCOUNT_SETTINGS_CHANGED_EVENT
213
- },
205
+ apiSuffix: "/settings",
206
+ queryKeyFactory: () => accountSettingsQueryKey,
207
+ realtime: {
208
+ event: "account.settings.changed"
209
+ },
214
210
  fallbackLoadError: "Unable to load settings.",
215
211
  mapLoadedToModel: mapAccountSettingsPayload
216
212
  });
217
213
 
218
214
  const pendingInvitesView = useView({
219
215
  ownershipFilter: OWNERSHIP_PUBLIC,
220
- apiSuffix: "/bootstrap",
221
- queryKeyFactory: () => pendingInvitesQueryKey,
222
- realtime: {
223
- event: WORKSPACE_PENDING_INVITATIONS_CHANGED_EVENT
224
- },
216
+ apiSuffix: "/bootstrap",
217
+ queryKeyFactory: () => pendingInvitesQueryKey,
218
+ realtime: {
219
+ event: "workspace.invitations.pending.changed"
220
+ },
225
221
  fallbackLoadError: "Unable to load invitations.",
226
222
  model: pendingInvitesModel,
227
223
  mapLoadedToModel: (model, payload = {}) => {
@@ -1,8 +1,10 @@
1
1
  import { computed, proxyRefs } from "vue";
2
+ import { useRoute } from "vue-router";
2
3
  import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
3
4
  import { useAddEditCore } from "./useAddEditCore.js";
4
5
  import { useEndpointResource } from "./useEndpointResource.js";
5
- import { useOperationScope } from "./internal/useOperationScope.js";
6
+ import { resolveOperationAdapter } from "./operationAdapters.js";
7
+ import { createAddEditUiRuntime } from "./addEditUiRuntime.js";
6
8
  import { useUiFeedback } from "./useUiFeedback.js";
7
9
  import { useFieldErrorBag } from "./useFieldErrorBag.js";
8
10
  import {
@@ -36,15 +38,39 @@ function useAddEdit({
36
38
  buildRawPayload,
37
39
  buildSavePayload,
38
40
  onSaveSuccess,
41
+ recordIdParam = "recordId",
42
+ routeParams = null,
43
+ routeRecordId = null,
44
+ apiUrlTemplate = "",
45
+ viewUrlTemplate = "",
46
+ listUrlTemplate = "",
47
+ saveRecordIdSelector = null,
39
48
  messages = {},
40
- realtime = null
49
+ realtime = null,
50
+ adapter = null
41
51
  } = {}) {
42
- const operationScope = useOperationScope({
52
+ const route = useRoute();
53
+ const addEditUiRuntime = createAddEditUiRuntime({
54
+ recordIdParam,
55
+ routeParams: routeParams ?? computed(() => route?.params || {}),
56
+ routePath: computed(() => route?.path || ""),
57
+ routeRecordId,
58
+ apiUrlTemplate,
59
+ viewUrlTemplate,
60
+ listUrlTemplate,
61
+ saveRecordIdSelector
62
+ });
63
+ const normalizedApiUrlTemplate = String(apiUrlTemplate || "").trim();
64
+ const effectiveApiSuffix = normalizedApiUrlTemplate ? addEditUiRuntime.apiSuffix : apiSuffix;
65
+ const operationAdapter = resolveOperationAdapter(adapter, {
66
+ context: "useAddEdit adapter"
67
+ });
68
+ const operationScope = operationAdapter.useOperationScope({
43
69
  ownershipFilter,
44
70
  surfaceId,
45
71
  access,
46
72
  placementSource,
47
- apiSuffix,
73
+ apiSuffix: effectiveApiSuffix,
48
74
  model,
49
75
  readEnabled,
50
76
  queryKeyFactory,
@@ -128,7 +154,13 @@ function useAddEdit({
128
154
  messageType: addEdit.messageType,
129
155
  submit: addEdit.submit,
130
156
  refresh: endpointResource.reload,
131
- resource: endpointResource
157
+ resource: endpointResource,
158
+ recordId: addEditUiRuntime.recordId,
159
+ listUrl: addEditUiRuntime.listUrl,
160
+ cancelUrl: addEditUiRuntime.cancelUrl,
161
+ resolveParams: addEditUiRuntime.resolveParams,
162
+ resolveViewUrl: addEditUiRuntime.resolveViewUrl,
163
+ resolveSavedViewUrl: addEditUiRuntime.resolveSavedViewUrl
132
164
  });
133
165
  }
134
166
 
@@ -0,0 +1,177 @@
1
+ import { computed, reactive } from "vue";
2
+ import { useRouter } from "vue-router";
3
+ import { asPlainObject } from "./scopeHelpers.js";
4
+ import { useAddEdit } from "./useAddEdit.js";
5
+ import {
6
+ normalizeCrudFormFields,
7
+ createCrudFormModel,
8
+ buildCrudFormPayload,
9
+ applyCrudPayloadToForm,
10
+ resolveCrudFieldErrors,
11
+ parseCrudResourceOperationInput
12
+ } from "./crudSchemaFormHelpers.js";
13
+
14
+ function normalizeFieldErrorKeys(keys = []) {
15
+ return Array.isArray(keys)
16
+ ? keys.map((entry) => String(entry || "").trim()).filter(Boolean)
17
+ : [];
18
+ }
19
+
20
+ function normalizeSaveSuccessOptions(options = {}) {
21
+ const source = asPlainObject(options);
22
+ const invalidateQueryKey = Array.isArray(source.invalidateQueryKey)
23
+ ? source.invalidateQueryKey
24
+ : null;
25
+ const listUrlTemplate = String(source.listUrlTemplate || "").trim();
26
+ const navigateToView = source.navigateToView !== false;
27
+ const navigateToList = source.navigateToList !== false;
28
+
29
+ return Object.freeze({
30
+ invalidateQueryKey,
31
+ listUrlTemplate,
32
+ navigateToView,
33
+ navigateToList
34
+ });
35
+ }
36
+
37
+ function useCrudSchemaForm({
38
+ resource = null,
39
+ operationName = "",
40
+ formFields = [],
41
+ addEditOptions = {},
42
+ saveSuccess = {},
43
+ createModel = null,
44
+ buildPayload = null,
45
+ mapPayloadToModel = null,
46
+ parseInput = null
47
+ } = {}) {
48
+ const router = useRouter();
49
+ const normalizedFields = normalizeCrudFormFields(formFields);
50
+ const normalizedAddEditOptions = asPlainObject(addEditOptions);
51
+ const saveSuccessOptions = normalizeSaveSuccessOptions(saveSuccess);
52
+ const defaultFieldErrorKeys = normalizedFields.map((field) => field.key);
53
+ const providedFieldErrorKeys = normalizeFieldErrorKeys(normalizedAddEditOptions.fieldErrorKeys);
54
+ const fieldErrorKeys = providedFieldErrorKeys.length > 0 ? providedFieldErrorKeys : defaultFieldErrorKeys;
55
+ const providedModel = normalizedAddEditOptions.model;
56
+ const hasProvidedModel = Boolean(providedModel && typeof providedModel === "object" && !Array.isArray(providedModel));
57
+ const defaultModel = typeof createModel === "function"
58
+ ? asPlainObject(createModel(normalizedFields))
59
+ : createCrudFormModel(normalizedFields);
60
+ const form = hasProvidedModel ? providedModel : reactive(defaultModel);
61
+ const parseInputOverride = typeof parseInput === "function"
62
+ ? parseInput
63
+ : (typeof normalizedAddEditOptions.parseInput === "function" ? normalizedAddEditOptions.parseInput : null);
64
+ const buildPayloadOverride = typeof buildPayload === "function"
65
+ ? buildPayload
66
+ : (typeof normalizedAddEditOptions.buildRawPayload === "function" ? normalizedAddEditOptions.buildRawPayload : null);
67
+ const mapPayloadToModelOverride = typeof mapPayloadToModel === "function"
68
+ ? mapPayloadToModel
69
+ : (typeof normalizedAddEditOptions.mapLoadedToModel === "function" ? normalizedAddEditOptions.mapLoadedToModel : null);
70
+ const onSaveSuccessOverride = typeof normalizedAddEditOptions.onSaveSuccess === "function"
71
+ ? normalizedAddEditOptions.onSaveSuccess
72
+ : null;
73
+ const shouldApplyDefaultMapPayload = normalizedAddEditOptions.readEnabled !== false;
74
+ const resolvedResource = normalizedAddEditOptions.resource || resource;
75
+
76
+ function resolveParseInput(rawPayload = {}, context = {}) {
77
+ if (parseInputOverride) {
78
+ return parseInputOverride(rawPayload, context);
79
+ }
80
+
81
+ return parseCrudResourceOperationInput({
82
+ resource: resolvedResource,
83
+ operationName,
84
+ rawPayload,
85
+ context
86
+ });
87
+ }
88
+
89
+ function resolveBuildRawPayload(model = {}, context = {}) {
90
+ if (buildPayloadOverride) {
91
+ return buildPayloadOverride(model, {
92
+ ...context,
93
+ fields: normalizedFields
94
+ });
95
+ }
96
+
97
+ return buildCrudFormPayload(normalizedFields, model);
98
+ }
99
+
100
+ const effectiveMapLoadedToModel = mapPayloadToModelOverride
101
+ ? (model = {}, payload = {}, context = {}) => {
102
+ mapPayloadToModelOverride(model, payload, {
103
+ ...context,
104
+ fields: normalizedFields
105
+ });
106
+ }
107
+ : (shouldApplyDefaultMapPayload
108
+ ? (model = {}, payload = {}) => {
109
+ applyCrudPayloadToForm(normalizedFields, model, payload);
110
+ }
111
+ : undefined);
112
+
113
+ let addEditRuntime = null;
114
+
115
+ async function handleSaveSuccess(payload, context = {}) {
116
+ if (onSaveSuccessOverride) {
117
+ await onSaveSuccessOverride(payload, context);
118
+ return;
119
+ }
120
+
121
+ const queryClient = context?.queryClient;
122
+ if (queryClient && saveSuccessOptions.invalidateQueryKey?.length > 0) {
123
+ await queryClient.invalidateQueries({
124
+ queryKey: saveSuccessOptions.invalidateQueryKey
125
+ });
126
+ }
127
+
128
+ if (saveSuccessOptions.navigateToView) {
129
+ const viewUrl = addEditRuntime?.resolveSavedViewUrl(payload) ||
130
+ addEditRuntime?.resolveViewUrl(addEditRuntime?.recordId);
131
+ if (viewUrl) {
132
+ await router.push(viewUrl);
133
+ return;
134
+ }
135
+ }
136
+
137
+ if (!saveSuccessOptions.navigateToList) {
138
+ return;
139
+ }
140
+
141
+ const listUrlTemplate = saveSuccessOptions.listUrlTemplate ||
142
+ String(normalizedAddEditOptions.listUrlTemplate || "").trim();
143
+ const listUrl = addEditRuntime?.resolveParams(listUrlTemplate);
144
+ if (listUrl) {
145
+ await router.push(listUrl);
146
+ }
147
+ }
148
+
149
+ const addEdit = useAddEdit({
150
+ ...normalizedAddEditOptions,
151
+ resource: resolvedResource,
152
+ model: form,
153
+ fieldErrorKeys,
154
+ parseInput: resolveParseInput,
155
+ buildRawPayload: resolveBuildRawPayload,
156
+ mapLoadedToModel: effectiveMapLoadedToModel,
157
+ onSaveSuccess: handleSaveSuccess
158
+ });
159
+ addEditRuntime = addEdit;
160
+
161
+ function resolveFieldErrors(fieldKey = "") {
162
+ return resolveCrudFieldErrors(addEdit.fieldErrors, fieldKey);
163
+ }
164
+
165
+ const showFormSkeleton = computed(() => Boolean(addEdit.isInitialLoading));
166
+
167
+ return Object.freeze({
168
+ formFields: normalizedFields,
169
+ fieldErrorKeys,
170
+ form,
171
+ addEdit,
172
+ showFormSkeleton,
173
+ resolveFieldErrors
174
+ });
175
+ }
176
+
177
+ export { useCrudSchemaForm };
@@ -1,8 +1,9 @@
1
1
  import { computed } from "vue";
2
2
  import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
3
3
  import { useListCore } from "./useListCore.js";
4
- import { useOperationScope } from "./internal/useOperationScope.js";
4
+ import { resolveOperationAdapter } from "./operationAdapters.js";
5
5
  import { setupOperationErrorReporting } from "./operationUiHelpers.js";
6
+ import { createListUiRuntime } from "./listUiRuntime.js";
6
7
 
7
8
  function useList({
8
9
  ownershipFilter = USERS_ROUTE_VISIBILITY_WORKSPACE,
@@ -19,9 +20,17 @@ function useList({
19
20
  selectItems,
20
21
  requestOptions,
21
22
  queryOptions,
22
- realtime = null
23
+ realtime = null,
24
+ adapter = null,
25
+ recordIdParam = "recordId",
26
+ recordIdSelector = null,
27
+ viewUrlTemplate = "",
28
+ editUrlTemplate = ""
23
29
  } = {}) {
24
- const operationScope = useOperationScope({
30
+ const operationAdapter = resolveOperationAdapter(adapter, {
31
+ context: "useList adapter"
32
+ });
33
+ const operationScope = operationAdapter.useOperationScope({
25
34
  ownershipFilter,
26
35
  surfaceId,
27
36
  access,
@@ -53,6 +62,16 @@ function useList({
53
62
  const isRefetching = computed(() => Boolean(isFetching.value && !isInitialLoading.value));
54
63
  const loadError = operationScope.loadError(list.loadError);
55
64
  const isLoading = operationScope.isLoading(list.isLoading);
65
+ const listUiRuntime = createListUiRuntime({
66
+ items: list.items,
67
+ isInitialLoading,
68
+ recordIdParam,
69
+ recordIdSelector,
70
+ routeParams: computed(() => operationScope.routeContext.route?.params || {}),
71
+ routePath: computed(() => operationScope.routeContext.route?.path || ""),
72
+ viewUrlTemplate,
73
+ editUrlTemplate
74
+ });
56
75
  setupOperationErrorReporting({
57
76
  source: `${placementSource}.load`,
58
77
  loadError,
@@ -78,7 +97,15 @@ function useList({
78
97
  pages: list.pages,
79
98
  items: list.items,
80
99
  reload: list.reload,
81
- loadMore: list.loadMore
100
+ loadMore: list.loadMore,
101
+ hasViewUrl: listUiRuntime.hasViewUrl,
102
+ hasEditUrl: listUiRuntime.hasEditUrl,
103
+ actionColumnCount: listUiRuntime.actionColumnCount,
104
+ showListSkeleton: listUiRuntime.showListSkeleton,
105
+ resolveRowKey: listUiRuntime.resolveRowKey,
106
+ resolveParams: listUiRuntime.resolveParams,
107
+ resolveViewUrl: listUiRuntime.resolveViewUrl,
108
+ resolveEditUrl: listUiRuntime.resolveEditUrl
82
109
  });
83
110
  }
84
111
 
@@ -1,9 +1,11 @@
1
1
  import { computed } from "vue";
2
+ import { useRoute } from "vue-router";
2
3
  import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
3
4
  import { useViewCore } from "./useViewCore.js";
4
5
  import { useEndpointResource } from "./useEndpointResource.js";
5
- import { useOperationScope } from "./internal/useOperationScope.js";
6
+ import { resolveOperationAdapter } from "./operationAdapters.js";
6
7
  import { setupOperationErrorReporting } from "./operationUiHelpers.js";
8
+ import { createViewUiRuntime } from "./viewUiRuntime.js";
7
9
 
8
10
  function useView({
9
11
  ownershipFilter = USERS_ROUTE_VISIBILITY_WORKSPACE,
@@ -20,14 +22,37 @@ function useView({
20
22
  notFoundMessage = "Record not found.",
21
23
  model,
22
24
  mapLoadedToModel,
23
- realtime = null
25
+ recordIdParam = "recordId",
26
+ routeParams = null,
27
+ routeRecordId = null,
28
+ apiUrlTemplate = "",
29
+ listUrlTemplate = "",
30
+ editUrlTemplate = "",
31
+ includeRecordIdInQueryKey = false,
32
+ realtime = null,
33
+ adapter = null
24
34
  } = {}) {
25
- const operationScope = useOperationScope({
35
+ const route = useRoute();
36
+ const viewUiRuntime = createViewUiRuntime({
37
+ recordIdParam,
38
+ routeParams: routeParams ?? computed(() => route?.params || {}),
39
+ routePath: computed(() => route?.path || ""),
40
+ routeRecordId,
41
+ apiUrlTemplate,
42
+ listUrlTemplate,
43
+ editUrlTemplate
44
+ });
45
+ const normalizedApiUrlTemplate = String(apiUrlTemplate || "").trim();
46
+ const effectiveApiSuffix = normalizedApiUrlTemplate ? viewUiRuntime.apiSuffix : apiSuffix;
47
+ const operationAdapter = resolveOperationAdapter(adapter, {
48
+ context: "useView adapter"
49
+ });
50
+ const operationScope = operationAdapter.useOperationScope({
26
51
  ownershipFilter,
27
52
  surfaceId,
28
53
  access,
29
54
  placementSource,
30
- apiSuffix,
55
+ apiSuffix: effectiveApiSuffix,
31
56
  readEnabled,
32
57
  queryKeyFactory,
33
58
  permissionSets: {
@@ -35,10 +60,19 @@ function useView({
35
60
  },
36
61
  realtime
37
62
  });
63
+ const queryKey = computed(() => {
64
+ const source = Array.isArray(operationScope.queryKey.value) ? operationScope.queryKey.value : [];
65
+ if (!includeRecordIdInQueryKey) {
66
+ return source;
67
+ }
68
+
69
+ const recordIdToken = String(viewUiRuntime.recordId.value || "").trim();
70
+ return [...source, recordIdToken];
71
+ });
38
72
  const canView = operationScope.permissionGate("view");
39
73
 
40
74
  const resource = useEndpointResource({
41
- queryKey: operationScope.queryKey,
75
+ queryKey,
42
76
  path: operationScope.apiPath,
43
77
  enabled: operationScope.queryCanRun(canView),
44
78
  readMethod,
@@ -74,6 +108,10 @@ function useView({
74
108
 
75
109
  return Object.freeze({
76
110
  record: view.record,
111
+ recordId: viewUiRuntime.recordId,
112
+ listUrl: viewUiRuntime.listUrl,
113
+ editUrl: viewUiRuntime.editUrl,
114
+ resolveParams: viewUiRuntime.resolveParams,
77
115
  canView,
78
116
  isLoading,
79
117
  isFetching,
@@ -0,0 +1,87 @@
1
+ import { computed, unref } from "vue";
2
+ import { asPlainObject } from "./scopeHelpers.js";
3
+ import {
4
+ normalizeRouteParamName,
5
+ resolveRouteParamsSource,
6
+ resolveRoutePathnameSource,
7
+ resolveRouteTemplateLocation,
8
+ toRouteParamValue
9
+ } from "./routeTemplateHelpers.js";
10
+
11
+ function resolveRecordId({ routeParams, recordIdParam, routeRecordId }) {
12
+ const explicitRecordId = toRouteParamValue(
13
+ typeof routeRecordId === "function" ? routeRecordId() : unref(routeRecordId)
14
+ );
15
+ if (explicitRecordId) {
16
+ return explicitRecordId;
17
+ }
18
+
19
+ return toRouteParamValue(routeParams[recordIdParam]);
20
+ }
21
+
22
+ function createViewUiRuntime({
23
+ recordIdParam = "recordId",
24
+ routeParams = null,
25
+ routePath = "",
26
+ routeRecordId = null,
27
+ apiUrlTemplate = "",
28
+ listUrlTemplate = "",
29
+ editUrlTemplate = ""
30
+ } = {}) {
31
+ const normalizedRecordIdParam = normalizeRouteParamName(recordIdParam, {
32
+ context: "useView recordIdParam"
33
+ });
34
+ const normalizedApiUrlTemplate = String(apiUrlTemplate || "").trim();
35
+ const normalizedListUrlTemplate = String(listUrlTemplate || "").trim();
36
+ const normalizedEditUrlTemplate = String(editUrlTemplate || "").trim();
37
+
38
+ function resolveTemplatePath(urlTemplate = "", extraParams = {}) {
39
+ const normalizedTemplate = String(urlTemplate || "").trim();
40
+ if (!normalizedTemplate) {
41
+ return "";
42
+ }
43
+
44
+ const currentRouteParams = resolveRouteParamsSource(routeParams);
45
+ const sourceParams = {
46
+ ...currentRouteParams,
47
+ ...asPlainObject(extraParams)
48
+ };
49
+ const resolvedRecordId = toRouteParamValue(sourceParams[normalizedRecordIdParam]) ||
50
+ resolveRecordId({
51
+ routeParams: currentRouteParams,
52
+ recordIdParam: normalizedRecordIdParam,
53
+ routeRecordId
54
+ });
55
+ sourceParams[normalizedRecordIdParam] = resolvedRecordId;
56
+
57
+ return resolveRouteTemplateLocation(normalizedTemplate, {
58
+ params: sourceParams,
59
+ currentPathname: resolveRoutePathnameSource(routePath)
60
+ });
61
+ }
62
+
63
+ const recordId = computed(() =>
64
+ resolveRecordId({
65
+ routeParams: resolveRouteParamsSource(routeParams),
66
+ recordIdParam: normalizedRecordIdParam,
67
+ routeRecordId
68
+ })
69
+ );
70
+ const apiSuffix = computed(() => resolveTemplatePath(normalizedApiUrlTemplate));
71
+ const listUrl = computed(() => resolveTemplatePath(normalizedListUrlTemplate));
72
+ const editUrl = computed(() => resolveTemplatePath(normalizedEditUrlTemplate));
73
+
74
+ function resolveParams(urlTemplate = "", extraParams = {}) {
75
+ return resolveTemplatePath(urlTemplate, extraParams);
76
+ }
77
+
78
+ return Object.freeze({
79
+ recordId,
80
+ apiSuffix,
81
+ listUrl,
82
+ editUrl,
83
+ resolveParams
84
+ });
85
+ }
86
+
87
+ export { createViewUiRuntime };
@@ -4,7 +4,6 @@ import { resolveWorkspaceThemePalette } from "@jskit-ai/users-core/shared/settin
4
4
  const THEME_PREFERENCE_LIGHT = "light";
5
5
  const THEME_PREFERENCE_DARK = "dark";
6
6
  const THEME_PREFERENCE_SYSTEM = "system";
7
- const THEME_PREFERENCE_STORAGE_KEY = "jskit.themePreference";
8
7
  const HEX_COLOR_PATTERN = /^#[0-9A-Fa-f]{6}$/;
9
8
  const WORKSPACE_THEME_NAME_LIGHT = "workspace-light";
10
9
  const WORKSPACE_THEME_NAME_DARK = "workspace-dark";
@@ -71,7 +70,7 @@ function readPersistedThemePreference(options = {}) {
71
70
  }
72
71
 
73
72
  try {
74
- const value = storage.getItem(THEME_PREFERENCE_STORAGE_KEY);
73
+ const value = storage.getItem("jskit.themePreference");
75
74
  return normalizeThemePreference(value);
76
75
  } catch {
77
76
  return THEME_PREFERENCE_SYSTEM;
@@ -86,7 +85,7 @@ function persistThemePreference(themePreference, options = {}) {
86
85
 
87
86
  const normalizedPreference = normalizeThemePreference(themePreference);
88
87
  try {
89
- storage.setItem(THEME_PREFERENCE_STORAGE_KEY, normalizedPreference);
88
+ storage.setItem("jskit.themePreference", normalizedPreference);
90
89
  return true;
91
90
  } catch {
92
91
  return false;
@@ -9,21 +9,9 @@ import ProfileClientElement from "../components/ProfileClientElement.vue";
9
9
  import MembersAdminClientElement from "../components/MembersAdminClientElement.vue";
10
10
  import WorkspaceSettingsClientElement from "../components/WorkspaceSettingsClientElement.vue";
11
11
  import {
12
- USERS_WEB_BOOTSTRAP_PLACEMENT_RUNTIME_TOKEN,
13
12
  createBootstrapPlacementRuntime
14
13
  } from "../runtime/bootstrapPlacementRuntime.js";
15
14
 
16
- const USERS_WEB_WORKSPACE_SELECTOR_TOKEN = "users.web.workspace.selector";
17
- const USERS_WEB_WORKSPACE_TOOLS_WIDGET_TOKEN = "users.web.workspace.tools.widget";
18
- const USERS_WEB_SHELL_MENU_LINK_ITEM_TOKEN = "users.web.shell.menu-link-item";
19
- const USERS_WEB_SURFACE_AWARE_MENU_LINK_ITEM_TOKEN = "users.web.shell.surface-aware-menu-link-item";
20
- const USERS_WEB_PROFILE_SURFACE_SWITCH_MENU_ITEM_TOKEN = "users.web.profile.menu.surface-switch-item";
21
- const USERS_WEB_WORKSPACE_SETTINGS_MENU_ITEM_TOKEN = "users.web.workspace-settings.menu-item";
22
- const USERS_WEB_WORKSPACE_MEMBERS_MENU_ITEM_TOKEN = "users.web.workspace-members.menu-item";
23
- const USERS_WEB_PROFILE_ELEMENT_TOKEN = "users.web.profile.element";
24
- const USERS_WEB_MEMBERS_ADMIN_ELEMENT_TOKEN = "users.web.members-admin.element";
25
- const USERS_WEB_WORKSPACE_SETTINGS_ELEMENT_TOKEN = "users.web.workspace-settings.element";
26
-
27
15
  class UsersWebClientProvider {
28
16
  static id = "users.web.client";
29
17
  static dependsOn = ["shell.web.client"];
@@ -33,17 +21,17 @@ class UsersWebClientProvider {
33
21
  throw new Error("UsersWebClientProvider requires application singleton().");
34
22
  }
35
23
 
36
- app.singleton(USERS_WEB_WORKSPACE_SELECTOR_TOKEN, () => UsersWorkspaceSelector);
37
- app.singleton(USERS_WEB_WORKSPACE_TOOLS_WIDGET_TOKEN, () => UsersWorkspaceToolsWidget);
38
- app.singleton(USERS_WEB_SHELL_MENU_LINK_ITEM_TOKEN, () => UsersShellMenuLinkItem);
39
- app.singleton(USERS_WEB_SURFACE_AWARE_MENU_LINK_ITEM_TOKEN, () => UsersSurfaceAwareMenuLinkItem);
40
- app.singleton(USERS_WEB_PROFILE_SURFACE_SWITCH_MENU_ITEM_TOKEN, () => UsersProfileSurfaceSwitchMenuItem);
41
- app.singleton(USERS_WEB_WORKSPACE_SETTINGS_MENU_ITEM_TOKEN, () => UsersWorkspaceSettingsMenuItem);
42
- app.singleton(USERS_WEB_WORKSPACE_MEMBERS_MENU_ITEM_TOKEN, () => UsersWorkspaceMembersMenuItem);
43
- app.singleton(USERS_WEB_PROFILE_ELEMENT_TOKEN, () => ProfileClientElement);
44
- app.singleton(USERS_WEB_MEMBERS_ADMIN_ELEMENT_TOKEN, () => MembersAdminClientElement);
45
- app.singleton(USERS_WEB_WORKSPACE_SETTINGS_ELEMENT_TOKEN, () => WorkspaceSettingsClientElement);
46
- app.singleton(USERS_WEB_BOOTSTRAP_PLACEMENT_RUNTIME_TOKEN, (scope) => createBootstrapPlacementRuntime({ app: scope }));
24
+ app.singleton("users.web.workspace.selector", () => UsersWorkspaceSelector);
25
+ app.singleton("users.web.workspace.tools.widget", () => UsersWorkspaceToolsWidget);
26
+ app.singleton("users.web.shell.menu-link-item", () => UsersShellMenuLinkItem);
27
+ app.singleton("users.web.shell.surface-aware-menu-link-item", () => UsersSurfaceAwareMenuLinkItem);
28
+ app.singleton("users.web.profile.menu.surface-switch-item", () => UsersProfileSurfaceSwitchMenuItem);
29
+ app.singleton("users.web.workspace-settings.menu-item", () => UsersWorkspaceSettingsMenuItem);
30
+ app.singleton("users.web.workspace-members.menu-item", () => UsersWorkspaceMembersMenuItem);
31
+ app.singleton("users.web.profile.element", () => ProfileClientElement);
32
+ app.singleton("users.web.members-admin.element", () => MembersAdminClientElement);
33
+ app.singleton("users.web.workspace-settings.element", () => WorkspaceSettingsClientElement);
34
+ app.singleton("users.web.bootstrap-placement.runtime", (scope) => createBootstrapPlacementRuntime({ app: scope }));
47
35
  }
48
36
 
49
37
  async boot(app) {
@@ -51,7 +39,7 @@ class UsersWebClientProvider {
51
39
  throw new Error("UsersWebClientProvider requires application make().");
52
40
  }
53
41
 
54
- const runtime = app.make(USERS_WEB_BOOTSTRAP_PLACEMENT_RUNTIME_TOKEN);
42
+ const runtime = app.make("users.web.bootstrap-placement.runtime");
55
43
  if (runtime && typeof runtime.initialize === "function") {
56
44
  await runtime.initialize();
57
45
  }
@@ -62,24 +50,11 @@ class UsersWebClientProvider {
62
50
  return;
63
51
  }
64
52
 
65
- const runtime = app.make(USERS_WEB_BOOTSTRAP_PLACEMENT_RUNTIME_TOKEN);
53
+ const runtime = app.make("users.web.bootstrap-placement.runtime");
66
54
  if (runtime && typeof runtime.shutdown === "function") {
67
55
  runtime.shutdown();
68
56
  }
69
57
  }
70
58
  }
71
59
 
72
- export {
73
- UsersWebClientProvider,
74
- USERS_WEB_WORKSPACE_SELECTOR_TOKEN,
75
- USERS_WEB_WORKSPACE_TOOLS_WIDGET_TOKEN,
76
- USERS_WEB_SHELL_MENU_LINK_ITEM_TOKEN,
77
- USERS_WEB_SURFACE_AWARE_MENU_LINK_ITEM_TOKEN,
78
- USERS_WEB_PROFILE_SURFACE_SWITCH_MENU_ITEM_TOKEN,
79
- USERS_WEB_WORKSPACE_SETTINGS_MENU_ITEM_TOKEN,
80
- USERS_WEB_WORKSPACE_MEMBERS_MENU_ITEM_TOKEN,
81
- USERS_WEB_PROFILE_ELEMENT_TOKEN,
82
- USERS_WEB_MEMBERS_ADMIN_ELEMENT_TOKEN,
83
- USERS_WEB_WORKSPACE_SETTINGS_ELEMENT_TOKEN,
84
- USERS_WEB_BOOTSTRAP_PLACEMENT_RUNTIME_TOKEN
85
- };
60
+ export { UsersWebClientProvider };