@vezham/react 26.0.3 → 26.3.1

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 (143) hide show
  1. package/dist/index.css +2 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +2 -1
  5. package/dist/lib/components/command/command-dialog.js +1 -1
  6. package/dist/lib/components/command/command-provider.js +1 -1
  7. package/dist/lib/components/command/index.d.ts +0 -1
  8. package/dist/lib/components/command/index.d.ts.map +1 -1
  9. package/dist/lib/components/panel/footer/control-center/control-center.js +1 -1
  10. package/dist/lib/components/panel/footer/control-center/editor.d.ts.map +1 -1
  11. package/dist/lib/components/panel/footer/control-center/editor.js +19 -24
  12. package/dist/lib/components/panel/footer/control-center/theme.d.ts.map +1 -1
  13. package/dist/lib/components/panel/footer/control-center/theme.js +2 -15
  14. package/dist/lib/components/panel/footer/control-center/variant.d.ts +3 -3
  15. package/dist/lib/components/panel/footer/control-center/variant.js +1 -1
  16. package/dist/lib/components/panel/footer/data.d.ts +1 -1
  17. package/dist/lib/components/panel/footer/data.js +1 -1
  18. package/dist/lib/components/panel/footer/index.d.ts +1 -1
  19. package/dist/lib/components/panel/footer/index.d.ts.map +1 -1
  20. package/dist/lib/components/panel/footer/index.js +11 -9
  21. package/dist/lib/components/panel/footer/notification-center/index.js +1 -1
  22. package/dist/lib/components/panel/footer/tamizhi/index.d.ts +3 -0
  23. package/dist/lib/components/panel/footer/tamizhi/index.d.ts.map +1 -0
  24. package/dist/lib/components/panel/footer/tamizhi/index.js +20 -0
  25. package/dist/lib/components/panel/footer/types.d.ts +2 -3
  26. package/dist/lib/components/panel/footer/types.d.ts.map +1 -1
  27. package/dist/lib/components/panel/footer/user-menu.d.ts +2 -2
  28. package/dist/lib/components/panel/footer/user-menu.d.ts.map +1 -1
  29. package/dist/lib/components/panel/footer/user-menu.js +127 -59
  30. package/dist/lib/components/panel/header/bookmarks/favorites/variant.js +2 -2
  31. package/dist/lib/components/panel/header/bookmarks/folder-modal/index.js +6 -6
  32. package/dist/lib/components/panel/header/bookmarks/index.js +1 -1
  33. package/dist/lib/components/panel/header/bookmarks/quick-access/index.js +9 -9
  34. package/dist/lib/components/panel/header/bookmarks/variant.js +22 -22
  35. package/dist/lib/components/panel/header/index.js +3 -3
  36. package/dist/lib/components/panel/info-panel/provider.d.ts.map +1 -1
  37. package/dist/lib/components/panel/info-panel/provider.js +20 -34
  38. package/dist/lib/components/panel/info-panel/types.d.ts +1 -1
  39. package/dist/lib/components/panel/info-panel/types.d.ts.map +1 -1
  40. package/dist/lib/components/panel/menu/index.js +4 -4
  41. package/dist/lib/components/panel/menu/variant.js +4 -4
  42. package/dist/lib/components/workspace-navigation/index.d.ts.map +1 -1
  43. package/dist/lib/components/workspace-navigation/index.js +1 -1
  44. package/dist/lib/layouts/app/frame.d.ts +2 -1
  45. package/dist/lib/layouts/app/frame.d.ts.map +1 -1
  46. package/dist/lib/layouts/app/frame.js +2 -2
  47. package/dist/lib/layouts/app/index.d.ts +7 -4
  48. package/dist/lib/layouts/app/index.d.ts.map +1 -1
  49. package/dist/lib/layouts/app/index.js +37 -6
  50. package/dist/lib/layouts/menu-layout/home-navigation-bubble.js +3 -3
  51. package/dist/lib/layouts/menu-layout/index-md.d.ts.map +1 -1
  52. package/dist/lib/layouts/menu-layout/index-md.js +19 -28
  53. package/dist/lib/layouts/menu-layout/index-sm.d.ts.map +1 -1
  54. package/dist/lib/layouts/menu-layout/index-sm.js +8 -20
  55. package/dist/lib/layouts/section/toolbar.js +1 -1
  56. package/dist/lib/pages/settings/settings-content.d.ts.map +1 -1
  57. package/dist/lib/pages/settings/settings-content.js +14 -26
  58. package/dist/lib/workspace/action-dialog.d.ts +9 -0
  59. package/dist/lib/workspace/action-dialog.d.ts.map +1 -0
  60. package/dist/lib/workspace/action-dialog.js +86 -0
  61. package/dist/lib/workspace/actions-menu.d.ts +8 -0
  62. package/dist/lib/workspace/actions-menu.d.ts.map +1 -0
  63. package/dist/lib/workspace/actions-menu.js +47 -0
  64. package/dist/lib/workspace/create-dialog.d.ts +5 -0
  65. package/dist/lib/workspace/create-dialog.d.ts.map +1 -0
  66. package/dist/lib/workspace/create-dialog.js +108 -0
  67. package/dist/lib/workspace/index.d.ts +34 -0
  68. package/dist/lib/workspace/index.d.ts.map +1 -0
  69. package/dist/lib/workspace/index.js +128 -0
  70. package/dist/lib/workspace/menu.d.ts +18 -0
  71. package/dist/lib/workspace/menu.d.ts.map +1 -0
  72. package/dist/lib/workspace/menu.js +148 -0
  73. package/dist/lib/workspace/model.d.ts +17 -0
  74. package/dist/lib/workspace/model.d.ts.map +1 -0
  75. package/dist/lib/workspace/model.js +35 -0
  76. package/package.json +3 -2
  77. package/dist/lib/components/command/index.js +0 -3
  78. package/dist/lib/components/panel/footer/ai/chat-header.d.ts +0 -9
  79. package/dist/lib/components/panel/footer/ai/chat-header.d.ts.map +0 -1
  80. package/dist/lib/components/panel/footer/ai/chat-header.js +0 -63
  81. package/dist/lib/components/panel/footer/ai/composer.d.ts +0 -7
  82. package/dist/lib/components/panel/footer/ai/composer.d.ts.map +0 -1
  83. package/dist/lib/components/panel/footer/ai/composer.js +0 -77
  84. package/dist/lib/components/panel/footer/ai/content.d.ts +0 -13
  85. package/dist/lib/components/panel/footer/ai/content.d.ts.map +0 -1
  86. package/dist/lib/components/panel/footer/ai/content.js +0 -148
  87. package/dist/lib/components/panel/footer/ai/conversation.d.ts +0 -47
  88. package/dist/lib/components/panel/footer/ai/conversation.d.ts.map +0 -1
  89. package/dist/lib/components/panel/footer/ai/conversation.js +0 -222
  90. package/dist/lib/components/panel/footer/ai/index.d.ts +0 -3
  91. package/dist/lib/components/panel/footer/ai/index.d.ts.map +0 -1
  92. package/dist/lib/components/panel/footer/ai/index.js +0 -41
  93. package/dist/lib/components/panel/footer/ai/message-actions.d.ts +0 -8
  94. package/dist/lib/components/panel/footer/ai/message-actions.d.ts.map +0 -1
  95. package/dist/lib/components/panel/footer/ai/message-actions.js +0 -63
  96. package/dist/lib/components/panel/footer/ai/mock-result.d.ts +0 -6
  97. package/dist/lib/components/panel/footer/ai/mock-result.d.ts.map +0 -1
  98. package/dist/lib/components/panel/footer/ai/mock-result.js +0 -121
  99. package/dist/lib/components/panel/footer/ai/model-logo.d.ts +0 -5
  100. package/dist/lib/components/panel/footer/ai/model-logo.d.ts.map +0 -1
  101. package/dist/lib/components/panel/footer/ai/model-logo.js +0 -13
  102. package/dist/lib/components/panel/footer/ai/model-logos.d.ts +0 -2
  103. package/dist/lib/components/panel/footer/ai/model-logos.d.ts.map +0 -1
  104. package/dist/lib/components/panel/footer/ai/model-logos.js +0 -10
  105. package/dist/lib/components/panel/footer/ai/model-picker.d.ts +0 -8
  106. package/dist/lib/components/panel/footer/ai/model-picker.d.ts.map +0 -1
  107. package/dist/lib/components/panel/footer/ai/model-picker.js +0 -166
  108. package/dist/lib/components/panel/footer/ai/models.d.ts +0 -9
  109. package/dist/lib/components/panel/footer/ai/models.d.ts.map +0 -1
  110. package/dist/lib/components/panel/footer/ai/models.js +0 -72
  111. package/dist/lib/components/panel/footer/ai/permission-picker.d.ts +0 -5
  112. package/dist/lib/components/panel/footer/ai/permission-picker.d.ts.map +0 -1
  113. package/dist/lib/components/panel/footer/ai/permission-picker.js +0 -63
  114. package/dist/lib/components/panel/footer/ai/use-chat-scroll.d.ts +0 -9
  115. package/dist/lib/components/panel/footer/ai/use-chat-scroll.d.ts.map +0 -1
  116. package/dist/lib/components/panel/footer/ai/use-chat-scroll.js +0 -57
  117. package/dist/lib/components/panel/footer/preferences/data.d.ts +0 -14
  118. package/dist/lib/components/panel/footer/preferences/data.d.ts.map +0 -1
  119. package/dist/lib/components/panel/footer/preferences/data.js +0 -304
  120. package/dist/lib/components/panel/footer/preferences/modal.d.ts +0 -8
  121. package/dist/lib/components/panel/footer/preferences/modal.d.ts.map +0 -1
  122. package/dist/lib/components/panel/footer/preferences/modal.js +0 -75
  123. package/dist/lib/components/panel/footer/preferences/sidebar.d.ts +0 -9
  124. package/dist/lib/components/panel/footer/preferences/sidebar.d.ts.map +0 -1
  125. package/dist/lib/components/panel/footer/preferences/sidebar.js +0 -105
  126. package/dist/lib/components/panel/footer/preferences/user-settings/account/index.d.ts +0 -3
  127. package/dist/lib/components/panel/footer/preferences/user-settings/account/index.d.ts.map +0 -1
  128. package/dist/lib/components/panel/footer/preferences/user-settings/account/index.js +0 -16
  129. package/dist/lib/components/panel/footer/preferences/user-settings/content-social/index.d.ts +0 -3
  130. package/dist/lib/components/panel/footer/preferences/user-settings/content-social/index.d.ts.map +0 -1
  131. package/dist/lib/components/panel/footer/preferences/user-settings/content-social/index.js +0 -16
  132. package/dist/lib/components/panel/footer/preferences/user-settings/data-privacy/index.d.ts +0 -3
  133. package/dist/lib/components/panel/footer/preferences/user-settings/data-privacy/index.d.ts.map +0 -1
  134. package/dist/lib/components/panel/footer/preferences/user-settings/data-privacy/index.js +0 -101
  135. package/dist/lib/components/panel/footer/preferences/user-settings/family-center/index.d.ts +0 -3
  136. package/dist/lib/components/panel/footer/preferences/user-settings/family-center/index.d.ts.map +0 -1
  137. package/dist/lib/components/panel/footer/preferences/user-settings/family-center/index.js +0 -24
  138. package/dist/lib/components/panel/footer/preferences/user-settings/profiles/index.d.ts +0 -3
  139. package/dist/lib/components/panel/footer/preferences/user-settings/profiles/index.d.ts.map +0 -1
  140. package/dist/lib/components/panel/footer/preferences/user-settings/profiles/index.js +0 -103
  141. package/dist/lib/components/panel/footer/tabs.d.ts +0 -12
  142. package/dist/lib/components/panel/footer/tabs.d.ts.map +0 -1
  143. package/dist/lib/components/panel/footer/tabs.js +0 -23
@@ -1,20 +1,23 @@
1
1
  import { AppearanceProvider, useAppearance } from "../../components/panel/footer/control-center/appearance.js";
2
2
  import { useRootAttribute } from "../../components/panel/footer/control-center/document.js";
3
3
  import { useUser } from "../../store/users/useUserStore.js";
4
- import { useState, useSyncExternalStore } from "react";
4
+ import { useState } from "react";
5
+ import { useLocalStore } from "@vezham/hooks";
5
6
  import { Button, Input, Label, ListBox, Select, Surface, Switch, TextField } from "@vezham/react-v3";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
7
8
  //#region src/lib/pages/settings/settings-content.tsx
8
- var subscribeNotifications = (onChange) => {
9
- window.addEventListener("storage", onChange);
10
- window.addEventListener("vx:notification-settings", onChange);
11
- return () => {
12
- window.removeEventListener("storage", onChange);
13
- window.removeEventListener("vx:notification-settings", onChange);
14
- };
9
+ var INITIAL_NOTIFICATIONS = {
10
+ sounds: true,
11
+ badges: true
12
+ };
13
+ var parseNotifications = (data) => {
14
+ if (!data || typeof data !== "object") return INITIAL_NOTIFICATIONS;
15
+ const value = data;
16
+ return typeof value.sounds === "boolean" && typeof value.badges === "boolean" ? {
17
+ sounds: value.sounds,
18
+ badges: value.badges
19
+ } : INITIAL_NOTIFICATIONS;
15
20
  };
16
- var readNotifications = () => localStorage.getItem("demo:notification-settings") ?? "";
17
- var serverNotifications = () => "";
18
21
  var useSettingsPreferences = () => {
19
22
  const { user, updateUser } = useUser();
20
23
  const { value: language, onChange: setLanguage } = useRootAttribute("lang", "en");
@@ -23,22 +26,7 @@ var useSettingsPreferences = () => {
23
26
  const [lastName, setLastName] = useState(user?.lastName ?? "");
24
27
  const [email, setEmail] = useState(user?.email ?? "");
25
28
  const [saved, setSaved] = useState(false);
26
- const snapshot = useSyncExternalStore(subscribeNotifications, readNotifications, serverNotifications);
27
- let notifications = {
28
- sounds: true,
29
- badges: true
30
- };
31
- try {
32
- const value = JSON.parse(snapshot || "null");
33
- if (value && typeof value.sounds === "boolean" && typeof value.badges === "boolean") notifications = {
34
- sounds: value.sounds,
35
- badges: value.badges
36
- };
37
- } catch {}
38
- const setNotifications = (next) => {
39
- localStorage.setItem("demo:notification-settings", JSON.stringify(next));
40
- window.dispatchEvent(new Event("vx:notification-settings"));
41
- };
29
+ const { value: notifications, setValue: setNotifications } = useLocalStore("demo:notification-settings", INITIAL_NOTIFICATIONS, { parse: parseNotifications });
42
30
  return {
43
31
  updateUser,
44
32
  language,
@@ -0,0 +1,9 @@
1
+ export type WorkspaceAction = {
2
+ id: string;
3
+ type: 'rename' | 'delete';
4
+ };
5
+ export declare const WorkspaceActionDialog: ({ action, onClose }: {
6
+ action: WorkspaceAction;
7
+ onClose: () => void;
8
+ }) => import("react").JSX.Element;
9
+ //# sourceMappingURL=action-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-dialog.d.ts","sourceRoot":"","sources":["../../../src/lib/workspace/action-dialog.tsx"],"names":[],"mappings":"AAcA,MAAM,MAAM,eAAe,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAE,CAAA;AAEvE,eAAO,MAAM,qBAAqB,GAAI,qBAGnC;IACD,MAAM,EAAE,eAAe,CAAA;IACvB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,gCAwGA,CAAA"}
@@ -0,0 +1,86 @@
1
+ import { useWorkspace } from "./index.js";
2
+ import { useState } from "react";
3
+ import { Button, Form, Input, Label, Modal, TextField, useOverlayState } from "@vezham/react-v3";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/lib/workspace/action-dialog.tsx
6
+ var WorkspaceActionDialog = ({ action, onClose }) => {
7
+ const workspace = useWorkspace();
8
+ const target = workspace.workspaces.find((item) => item.id === action.id);
9
+ const [name, setName] = useState(target?.name ?? "");
10
+ const [pending, setPending] = useState(false);
11
+ const [error, setError] = useState("");
12
+ const deleting = action.type === "delete";
13
+ const state = useOverlayState({
14
+ isOpen: true,
15
+ onOpenChange: (open) => {
16
+ if (!open && !pending) onClose();
17
+ }
18
+ });
19
+ const submit = async () => {
20
+ if (pending || !target) return;
21
+ setPending(true);
22
+ setError("");
23
+ try {
24
+ if (deleting ? await workspace.remove(target.id) : await workspace.rename(target.id, name)) onClose();
25
+ else setError(deleting && workspace.workspaces.length <= 1 ? "Keep at least one workspace." : "Unable to save this change. Check browser storage permissions.");
26
+ } catch (cause) {
27
+ setError(cause instanceof Error ? cause.message : "Unable to update workspace.");
28
+ } finally {
29
+ setPending(false);
30
+ }
31
+ };
32
+ return /* @__PURE__ */ jsx(Modal, {
33
+ state,
34
+ children: /* @__PURE__ */ jsx(Modal.Backdrop, {
35
+ variant: "blur",
36
+ children: /* @__PURE__ */ jsx(Modal.Container, {
37
+ placement: "center",
38
+ size: "sm",
39
+ children: /* @__PURE__ */ jsxs(Modal.Dialog, { children: [
40
+ /* @__PURE__ */ jsx(Modal.CloseTrigger, {
41
+ "aria-label": "Close workspace action",
42
+ isDisabled: pending
43
+ }),
44
+ /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Heading, { children: deleting ? "Delete workspace" : "Rename workspace" }) }),
45
+ /* @__PURE__ */ jsxs(Form, {
46
+ onSubmit: (event) => {
47
+ event.preventDefault();
48
+ submit();
49
+ },
50
+ children: [/* @__PURE__ */ jsxs(Modal.Body, {
51
+ className: "flex flex-col gap-4",
52
+ children: [deleting ? /* @__PURE__ */ jsxs("p", { children: [
53
+ "Delete ",
54
+ /* @__PURE__ */ jsx("strong", { children: target?.name }),
55
+ "? Its local notes, chat history, and workspace data will be permanently removed from this browser."
56
+ ] }) : /* @__PURE__ */ jsxs(TextField, {
57
+ isRequired: true,
58
+ value: name,
59
+ onChange: setName,
60
+ isDisabled: pending,
61
+ children: [/* @__PURE__ */ jsx(Label, { children: "Workspace name" }), /* @__PURE__ */ jsx(Input, { maxLength: 64 })]
62
+ }), error && /* @__PURE__ */ jsx("p", {
63
+ role: "alert",
64
+ className: "text-danger text-sm",
65
+ children: error
66
+ })]
67
+ }), /* @__PURE__ */ jsxs(Modal.Footer, { children: [/* @__PURE__ */ jsx(Button, {
68
+ variant: "secondary",
69
+ onPress: onClose,
70
+ isDisabled: pending,
71
+ children: "Cancel"
72
+ }), /* @__PURE__ */ jsx(Button, {
73
+ type: "submit",
74
+ variant: deleting ? "danger" : "primary",
75
+ isPending: pending,
76
+ isDisabled: !target || !workspace.isReady || Boolean(workspace.error) || (deleting ? workspace.workspaces.length <= 1 : !name.trim()),
77
+ children: deleting ? "Delete workspace" : "Save name"
78
+ })] })]
79
+ })
80
+ ] })
81
+ })
82
+ })
83
+ });
84
+ };
85
+ //#endregion
86
+ export { WorkspaceActionDialog };
@@ -0,0 +1,8 @@
1
+ import type { WorkspaceAction } from './action-dialog';
2
+ import type { LocalWorkspace } from './model';
3
+ export declare const WorkspaceActionsMenu: ({ workspace, canDelete, onAction }: {
4
+ workspace: LocalWorkspace;
5
+ canDelete: boolean;
6
+ onAction: (action: WorkspaceAction) => void;
7
+ }) => import("react").JSX.Element;
8
+ //# sourceMappingURL=actions-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions-menu.d.ts","sourceRoot":"","sources":["../../../src/lib/workspace/actions-menu.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,eAAO,MAAM,oBAAoB,GAAI,oCAIlC;IACD,SAAS,EAAE,cAAc,CAAA;IACzB,SAAS,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAA;CAC5C,gCA+BA,CAAA"}
@@ -0,0 +1,47 @@
1
+ import { Button, Dropdown } from "@vezham/react-v3";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { MenuDots, Pen, TrashBinTrash } from "@vezham/icons-react";
4
+ //#region src/lib/workspace/actions-menu.tsx
5
+ var WorkspaceActionsMenu = ({ workspace, canDelete, onAction }) => /* @__PURE__ */ jsxs(Dropdown, { children: [/* @__PURE__ */ jsx(Button, {
6
+ variant: "ghost",
7
+ size: "sm",
8
+ isIconOnly: true,
9
+ "aria-label": `Options for ${workspace.name}`,
10
+ className: "size-8 min-w-8 shrink-0",
11
+ children: /* @__PURE__ */ jsx(MenuDots, {
12
+ size: 18,
13
+ "aria-hidden": "true"
14
+ })
15
+ }), /* @__PURE__ */ jsx(Dropdown.Popover, {
16
+ className: "z-90 w-44",
17
+ children: /* @__PURE__ */ jsxs(Dropdown.Menu, {
18
+ "aria-label": `Workspace actions for ${workspace.name}`,
19
+ children: [/* @__PURE__ */ jsxs(Dropdown.Item, {
20
+ id: "rename",
21
+ textValue: "Rename",
22
+ onAction: () => onAction({
23
+ id: workspace.id,
24
+ type: "rename"
25
+ }),
26
+ children: [/* @__PURE__ */ jsx(Pen, {
27
+ size: 18,
28
+ "aria-hidden": "true"
29
+ }), "Rename"]
30
+ }), /* @__PURE__ */ jsxs(Dropdown.Item, {
31
+ id: "delete",
32
+ textValue: "Delete",
33
+ variant: "danger",
34
+ isDisabled: !canDelete,
35
+ onAction: () => onAction({
36
+ id: workspace.id,
37
+ type: "delete"
38
+ }),
39
+ children: [/* @__PURE__ */ jsx(TrashBinTrash, {
40
+ size: 18,
41
+ "aria-hidden": "true"
42
+ }), "Delete"]
43
+ })]
44
+ })
45
+ })] });
46
+ //#endregion
47
+ export { WorkspaceActionsMenu };
@@ -0,0 +1,5 @@
1
+ export declare const CreateWorkspaceDialog: ({ isOpen, onOpenChange }: {
2
+ isOpen: boolean;
3
+ onOpenChange: (open: boolean) => void;
4
+ }) => import("react").JSX.Element;
5
+ //# sourceMappingURL=create-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-dialog.d.ts","sourceRoot":"","sources":["../../../src/lib/workspace/create-dialog.tsx"],"names":[],"mappings":"AAgBA,eAAO,MAAM,qBAAqB,GAAI,0BAGnC;IACD,MAAM,EAAE,OAAO,CAAA;IACf,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;CACtC,gCAiBA,CAAA"}
@@ -0,0 +1,108 @@
1
+ import { useWorkspace } from "./index.js";
2
+ import { useState } from "react";
3
+ import { Button, Description, Form, Input, Label, Modal, TextField, useOverlayState } from "@vezham/react-v3";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { Laptop } from "@vezham/icons-react";
6
+ //#region src/lib/workspace/create-dialog.tsx
7
+ var CreateWorkspaceDialog = ({ isOpen, onOpenChange }) => {
8
+ return /* @__PURE__ */ jsx(Modal, {
9
+ state: useOverlayState({
10
+ isOpen,
11
+ onOpenChange
12
+ }),
13
+ children: /* @__PURE__ */ jsx(Modal.Backdrop, {
14
+ variant: "blur",
15
+ children: /* @__PURE__ */ jsx(Modal.Container, {
16
+ placement: "center",
17
+ size: "sm",
18
+ children: /* @__PURE__ */ jsxs(Modal.Dialog, { children: [
19
+ /* @__PURE__ */ jsx(Modal.CloseTrigger, { "aria-label": "Close create workspace" }),
20
+ /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Heading, { children: "Name your workspace" }) }),
21
+ /* @__PURE__ */ jsx(CreateWorkspaceForm, { onClose: () => onOpenChange(false) })
22
+ ] })
23
+ })
24
+ })
25
+ });
26
+ };
27
+ var CreateWorkspaceForm = ({ onClose }) => {
28
+ const workspace = useWorkspace();
29
+ const [name, setName] = useState("");
30
+ const [error, setError] = useState("");
31
+ const [isPending, setIsPending] = useState(false);
32
+ const submit = async () => {
33
+ if (isPending) return;
34
+ setIsPending(true);
35
+ setError("");
36
+ try {
37
+ if (await workspace.create(name)) onClose();
38
+ else setError("Unable to save this workspace. Check browser storage permissions.");
39
+ } catch (cause) {
40
+ setError(cause instanceof Error ? cause.message : "Unable to create workspace.");
41
+ } finally {
42
+ setIsPending(false);
43
+ }
44
+ };
45
+ return /* @__PURE__ */ jsxs(Form, {
46
+ onSubmit: (event) => {
47
+ event.preventDefault();
48
+ submit();
49
+ },
50
+ children: [/* @__PURE__ */ jsxs(Modal.Body, {
51
+ className: "flex flex-col gap-5",
52
+ children: [
53
+ /* @__PURE__ */ jsx("p", {
54
+ className: "text-muted text-sm",
55
+ children: "A workspace keeps your app data together. Create one for yourself, a project, or a team."
56
+ }),
57
+ /* @__PURE__ */ jsxs(TextField, {
58
+ isRequired: true,
59
+ value: name,
60
+ onChange: setName,
61
+ isInvalid: Boolean(error),
62
+ isDisabled: isPending,
63
+ children: [/* @__PURE__ */ jsx(Label, { children: "Workspace name" }), /* @__PURE__ */ jsx(Input, {
64
+ placeholder: "Set a workspace name",
65
+ maxLength: 64
66
+ })]
67
+ }),
68
+ /* @__PURE__ */ jsxs("div", {
69
+ className: "flex flex-col gap-2",
70
+ children: [
71
+ /* @__PURE__ */ jsx("span", {
72
+ className: "text-sm font-medium",
73
+ children: "Workspace type"
74
+ }),
75
+ /* @__PURE__ */ jsxs("div", {
76
+ className: "bg-surface-secondary flex items-center gap-3 rounded-lg p-3",
77
+ children: [/* @__PURE__ */ jsx(Laptop, {
78
+ size: 20,
79
+ "aria-hidden": "true"
80
+ }), /* @__PURE__ */ jsx("span", {
81
+ className: "text-sm",
82
+ children: "Local storage"
83
+ })]
84
+ }),
85
+ /* @__PURE__ */ jsx(Description, { children: "Saved in this browser. No sign-in needed." })
86
+ ]
87
+ }),
88
+ error && /* @__PURE__ */ jsx("p", {
89
+ role: "alert",
90
+ className: "text-danger text-sm",
91
+ children: error
92
+ })
93
+ ]
94
+ }), /* @__PURE__ */ jsxs(Modal.Footer, { children: [/* @__PURE__ */ jsx(Button, {
95
+ variant: "secondary",
96
+ onPress: onClose,
97
+ isDisabled: isPending,
98
+ children: "Cancel"
99
+ }), /* @__PURE__ */ jsx(Button, {
100
+ type: "submit",
101
+ isPending,
102
+ isDisabled: !name.trim() || !workspace.isReady || Boolean(workspace.error),
103
+ children: "Create workspace"
104
+ })] })]
105
+ });
106
+ };
107
+ //#endregion
108
+ export { CreateWorkspaceDialog };
@@ -0,0 +1,34 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { IndexedDBStoreOptions } from '@vezham/hooks';
3
+ import type { LocalWorkspace } from './model';
4
+ interface WorkspaceContextValue {
5
+ appId: string;
6
+ active: LocalWorkspace;
7
+ workspaces: readonly LocalWorkspace[];
8
+ isReady: boolean;
9
+ isSaved: boolean;
10
+ error: unknown;
11
+ create: (name: string) => Promise<string | null>;
12
+ select: (id: string) => void;
13
+ rename: (id: string, name: string) => Promise<boolean>;
14
+ remove: (id: string) => Promise<boolean>;
15
+ }
16
+ export interface WorkspaceProviderProps {
17
+ children: ReactNode;
18
+ appId?: string;
19
+ defaultName?: string;
20
+ }
21
+ export declare const WorkspaceProvider: ({ children, appId: explicitAppId, defaultName }: WorkspaceProviderProps) => import("react").JSX.Element;
22
+ export declare const useOptionalWorkspace: () => WorkspaceContextValue | null;
23
+ export declare const useWorkspace: () => WorkspaceContextValue;
24
+ export declare const useWorkspaceStore: <T>(key: string, initialValue: T, options?: IndexedDBStoreOptions<T>) => {
25
+ setValue: (update: T | ((current: T) => T), options?: import("@vezham/hooks").IndexedDBMutationOptions) => Promise<boolean>;
26
+ flush: () => Promise<undefined>;
27
+ refresh: () => Promise<undefined>;
28
+ value: T;
29
+ isReady: boolean;
30
+ isSaved: boolean;
31
+ error: unknown;
32
+ };
33
+ export type { LocalWorkspace } from './model';
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/workspace/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAW1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,UAAU,qBAAqB;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,cAAc,CAAA;IACtB,UAAU,EAAE,SAAS,cAAc,EAAE,CAAA;IACrC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAChD,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACtD,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACzC;AASD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,SAAS,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,eAAO,MAAM,iBAAiB,GAAI,iDAI/B,sBAAsB,gCAYxB,CAAA;AAqID,eAAO,MAAM,oBAAoB,oCAAqC,CAAA;AAEtE,eAAO,MAAM,YAAY,6BAIxB,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,CAAC,EACjC,KAAK,MAAM,EACX,cAAc,CAAC,EACf,UAAS,qBAAqB,CAAC,CAAC,CAAM;;;;;;;;CAQvC,CAAA;AAED,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,128 @@
1
+ import { createInitialWorkspaceCatalog, createLocalWorkspace, normalizeWorkspaceName, parseWorkspaceCatalog, workspaceCatalogKey, workspaceDataKey, workspaceSelectionKey } from "./model.js";
2
+ import { createContext, useCallback, useContext, useMemo } from "react";
3
+ import { useApp, useIndexedDBStore, useLocalStore } from "@vezham/hooks";
4
+ import { jsx } from "react/jsx-runtime";
5
+ //#region src/lib/workspace/index.tsx
6
+ var parseWorkspaceSelection = (value) => typeof value === "string" && value.length > 0 && value.length <= 128 ? value : "default";
7
+ var WorkspaceContext = createContext(null);
8
+ var WorkspaceProvider = ({ children, appId: explicitAppId, defaultName = "My Workspace" }) => {
9
+ const app = useApp();
10
+ const appId = explicitAppId ?? app?.id;
11
+ if (!appId) throw new Error("WorkspaceProvider requires an app ID or an app identity provider.");
12
+ return /* @__PURE__ */ jsx(WorkspaceScope, {
13
+ appId,
14
+ defaultName,
15
+ children
16
+ }, appId);
17
+ };
18
+ var WorkspaceScope = ({ children, appId, defaultName }) => {
19
+ const initial = useMemo(() => createInitialWorkspaceCatalog(defaultName), [defaultName]);
20
+ const { value: catalog, setValue, isReady, isSaved, error } = useIndexedDBStore(workspaceCatalogKey(appId), initial, { parse: parseWorkspaceCatalog });
21
+ const { value: selectedId, setValue: setSelection, isReady: selectionReady, isSaved: selectionSaved, error: selectionError } = useLocalStore(workspaceSelectionKey(appId), "default", { parse: parseWorkspaceSelection });
22
+ const active = catalog.workspaces.find((item) => item.id === selectedId) ?? catalog.workspaces[0];
23
+ const create = useCallback(async (name) => {
24
+ if (!isReady || !selectionReady || error) return null;
25
+ const workspace = createLocalWorkspace(name);
26
+ if (!await setValue((current) => ({ workspaces: [...current.workspaces, workspace] }))) return null;
27
+ setSelection(workspace.id);
28
+ return workspace.id;
29
+ }, [
30
+ isReady,
31
+ selectionReady,
32
+ error,
33
+ setValue,
34
+ setSelection
35
+ ]);
36
+ const select = useCallback((id) => {
37
+ if (!isReady || !selectionReady || error || !catalog.workspaces.some((item) => item.id === id)) return;
38
+ setSelection(id);
39
+ }, [
40
+ isReady,
41
+ selectionReady,
42
+ error,
43
+ catalog.workspaces,
44
+ setSelection
45
+ ]);
46
+ const rename = useCallback(async (id, name) => {
47
+ if (!isReady || error) return false;
48
+ const normalized = normalizeWorkspaceName(name);
49
+ if (!catalog.workspaces.some((item) => item.id === id)) return false;
50
+ return setValue((current) => ({ workspaces: current.workspaces.map((item) => item.id === id ? {
51
+ ...item,
52
+ name: normalized
53
+ } : item) }));
54
+ }, [
55
+ isReady,
56
+ error,
57
+ catalog.workspaces,
58
+ setValue
59
+ ]);
60
+ const remove = useCallback(async (id) => {
61
+ if (!isReady || error || catalog.workspaces.length <= 1 || !catalog.workspaces.some((item) => item.id === id)) return false;
62
+ const saved = await setValue((current) => {
63
+ const remaining = current.workspaces.filter((item) => item.id !== id);
64
+ if (!remaining.length) throw new Error("Keep at least one workspace.");
65
+ return { workspaces: remaining };
66
+ }, {
67
+ deletePrefixes: [workspaceDataKey(appId, id, "")],
68
+ optimistic: false
69
+ });
70
+ if (saved) {
71
+ const next = catalog.workspaces.find((item) => item.id !== id);
72
+ if (next) setSelection((current) => current === id ? next.id : current);
73
+ }
74
+ return saved;
75
+ }, [
76
+ isReady,
77
+ error,
78
+ catalog.workspaces,
79
+ setValue,
80
+ appId,
81
+ setSelection
82
+ ]);
83
+ const ready = isReady && selectionReady;
84
+ const storageError = error ?? selectionError;
85
+ const saved = isSaved && selectionSaved;
86
+ const value = useMemo(() => ({
87
+ appId,
88
+ active,
89
+ workspaces: catalog.workspaces,
90
+ isReady: ready,
91
+ isSaved: saved,
92
+ error: storageError,
93
+ create,
94
+ rename,
95
+ remove,
96
+ select
97
+ }), [
98
+ appId,
99
+ active,
100
+ catalog.workspaces,
101
+ ready,
102
+ saved,
103
+ storageError,
104
+ create,
105
+ rename,
106
+ remove,
107
+ select
108
+ ]);
109
+ return /* @__PURE__ */ jsx(WorkspaceContext.Provider, {
110
+ value,
111
+ children
112
+ });
113
+ };
114
+ var useOptionalWorkspace = () => useContext(WorkspaceContext);
115
+ var useWorkspace = () => {
116
+ const workspace = useOptionalWorkspace();
117
+ if (!workspace) throw new Error("useWorkspace requires WorkspaceProvider.");
118
+ return workspace;
119
+ };
120
+ var useWorkspaceStore = (key, initialValue, options = {}) => {
121
+ const { appId, active, isReady } = useWorkspace();
122
+ return useIndexedDBStore(workspaceDataKey(appId, active.id, key), initialValue, {
123
+ ...options,
124
+ enabled: isReady && options.enabled !== false
125
+ });
126
+ };
127
+ //#endregion
128
+ export { WorkspaceProvider, useOptionalWorkspace, useWorkspace, useWorkspaceStore };
@@ -0,0 +1,18 @@
1
+ import type { WorkspaceAction } from './action-dialog';
2
+ import type { useWorkspace } from './index';
3
+ type Props = {
4
+ workspace: ReturnType<typeof useWorkspace>;
5
+ select: (id: string) => void;
6
+ create: () => void;
7
+ onAction: (action: WorkspaceAction) => void;
8
+ };
9
+ export declare const renderWorkspaceMenuSection: (props: Props) => import("react").JSX.Element;
10
+ export declare const WorkspaceSheetTrigger: ({ name, onPress }: {
11
+ name: string;
12
+ onPress: () => void;
13
+ }) => import("react").JSX.Element;
14
+ export declare const WorkspaceSheetItems: ({ workspace, select, create, onAction, onBack }: Props & {
15
+ onBack: () => void;
16
+ }) => import("react").JSX.Element;
17
+ export {};
18
+ //# sourceMappingURL=menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../../src/lib/workspace/menu.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C,KAAK,KAAK,GAAG;IACX,SAAS,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAA;IAC1C,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAA;CAC5C,CAAA;AA4CD,eAAO,MAAM,0BAA0B,GAAI,OAAO,KAAK,gCAqBtD,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,mBAGnC;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,gCAUA,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,iDAMjC,KAAK,GAAG;IAAE,MAAM,EAAE,MAAM,IAAI,CAAA;CAAE,gCA6ChC,CAAA"}