@cloudron/pankow 4.2.2 → 4.3.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.
package/index.js CHANGED
@@ -5,14 +5,16 @@ import "@fontsource/inter/500.css";
5
5
  import '@fortawesome/fontawesome-free/css/all.min.css';
6
6
  import './style.css';
7
7
 
8
+ import pankowPlugin from './plugin.js';
9
+
8
10
  // Order of import matters due to css rule matching!
9
11
  import BottomBar from './components/BottomBar.vue';
10
- import Breadcrumb from './components/Breadcrumb.vue';
12
+ import BreadCrumb from './components/BreadCrumb.vue';
11
13
  import Button from './components/Button.vue';
12
14
  import ButtonGroup from './components/ButtonGroup.vue';
13
15
  import ClipboardAction from './components/ClipboardAction.vue';
14
16
  import ClipboardButton from './components/ClipboardButton.vue';
15
- import Checkbox from './components/Checkbox.vue';
17
+ import CheckBox from './components/CheckBox.vue';
16
18
  import DateTimeInput from './components/DateTimeInput.vue';
17
19
  import Dialog from './components/Dialog.vue';
18
20
  import DirectoryView from './components/DirectoryView.vue';
@@ -21,6 +23,7 @@ import FileUploader from './components/FileUploader.vue';
21
23
  import FormGroup from './components/FormGroup.vue';
22
24
  import Icon from './components/Icon.vue';
23
25
  import InputDialog from './components/InputDialog.vue';
26
+ import ListItem from './components/ListItem.vue';
24
27
  import LoginView from './components/LoginView.vue';
25
28
  import MainLayout from './components/MainLayout.vue';
26
29
  import MaskedInput from './components/MaskedInput.vue';
@@ -34,7 +37,8 @@ import OfflineBanner from './components/OfflineBanner.vue';
34
37
  import PasswordInput from './components/PasswordInput.vue';
35
38
  import Popover from './components/Popover.vue';
36
39
  import ProgressBar from './components/ProgressBar.vue';
37
- import Radiobutton from './components/Radiobutton.vue';
40
+ import RadioButton from './components/RadioButton.vue';
41
+ import SectionItem from './components/SectionItem.vue';
38
42
  import SideBar from './components/SideBar.vue';
39
43
  import SplitLayout from './components/SplitLayout.vue';
40
44
  import Spinner from './components/Spinner.vue';
@@ -57,12 +61,12 @@ import fallbackImage from './fallbackImage.js';
57
61
 
58
62
  export {
59
63
  BottomBar,
60
- Breadcrumb,
64
+ BreadCrumb,
61
65
  Button,
62
66
  ButtonGroup,
63
67
  ClipboardAction,
64
68
  ClipboardButton,
65
- Checkbox,
69
+ CheckBox,
66
70
  DateTimeInput,
67
71
  Dialog,
68
72
  DirectoryView,
@@ -71,6 +75,7 @@ export {
71
75
  FormGroup,
72
76
  InputGroup,
73
77
  Icon,
78
+ ListItem,
74
79
  InputDialog,
75
80
  LoginView,
76
81
  MainLayout,
@@ -85,7 +90,8 @@ export {
85
90
  PasswordInput,
86
91
  Popover,
87
92
  ProgressBar,
88
- Radiobutton,
93
+ RadioButton,
94
+ SectionItem,
89
95
  SideBar,
90
96
  SplitLayout,
91
97
  Spinner,
@@ -105,3 +111,10 @@ export {
105
111
  fallbackImage,
106
112
  utils,
107
113
  };
114
+
115
+ export { CheckBox as Checkbox }; /* deprecated */
116
+ export { RadioButton as Radiobutton }; /* deprecated */
117
+ export { BreadCrumb as Breadcrumb }; /* deprecated */
118
+
119
+ export { useNotify } from './notifyState.js';
120
+ export default pankowPlugin;
package/notifyState.js ADDED
@@ -0,0 +1,48 @@
1
+ import { reactive, ref } from 'vue';
2
+ import { uuidv4 } from './utils.js';
3
+
4
+ const messages = reactive([]);
5
+ const position = ref('top-center');
6
+
7
+ function pushNotify(options) {
8
+ const id = uuidv4();
9
+ const text = typeof options === 'object' && 'text' in options ? options.text : options;
10
+ const persistent = typeof options === 'object' && 'persistent' in options ? options.persistent : false;
11
+ const timeout = typeof options === 'object' && 'timeout' in options ? options.timeout : 2000;
12
+ const type = typeof options === 'object' && 'type' in options ? options.type : null;
13
+
14
+ messages.push({ id, text, persistent, type });
15
+
16
+ if (!persistent) {
17
+ setTimeout(() => {
18
+ const index = messages.findIndex((value) => value.id === id);
19
+ if (index > -1) messages.splice(index, 1);
20
+ }, timeout);
21
+ }
22
+ }
23
+
24
+ function removeNotify(id) {
25
+ const index = messages.findIndex((value) => value.id === id);
26
+ if (index > -1) messages.splice(index, 1);
27
+ }
28
+
29
+ function useNotify() {
30
+ return { notify: pushNotify };
31
+ }
32
+
33
+ function setNotifyPosition(pos) {
34
+ position.value = pos;
35
+ }
36
+
37
+ if (typeof window !== 'undefined') {
38
+ if (!window.pankow) window.pankow = {};
39
+ if (window.pankow.notify) {
40
+ console.error('Pankow: Notification already registered! Only ever use a single one.');
41
+ } else {
42
+ window.pankow.notify = pushNotify;
43
+ }
44
+
45
+ window.pankow.setNotifyPosition = setNotifyPosition;
46
+ }
47
+
48
+ export { messages, position, pushNotify, removeNotify, setNotifyPosition, useNotify };
package/package.json CHANGED
@@ -1,10 +1,19 @@
1
1
  {
2
2
  "name": "@cloudron/pankow",
3
3
  "private": false,
4
- "version": "4.2.2",
5
- "description": "",
4
+ "version": "4.3.0",
5
+ "description": "Vue 3 UI component library for Cloudron apps",
6
6
  "main": "index.js",
7
7
  "types": "types/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./index.js",
11
+ "types": "./types/index.d.ts"
12
+ },
13
+ "./*": "./*",
14
+ "./vite-plugin": "./vite-plugin.js"
15
+ },
16
+ "keywords": ["vue", "vue3", "cloudron", "ui", "components"],
8
17
  "files": [
9
18
  "*.css",
10
19
  "*.js",
@@ -28,12 +37,15 @@
28
37
  "monaco-editor": "^0.55.1",
29
38
  "online-3d-viewer": "^0.18.0"
30
39
  },
40
+ "peerDependencies": {
41
+ "vue": "^3.5.0"
42
+ },
31
43
  "devDependencies": {
32
44
  "@highlightjs/vue-plugin": "^2.1.0",
33
45
  "@vitejs/plugin-vue": "^6.0.7",
34
46
  "highlight.js": "^11.11.1",
35
47
  "typescript": "^6.0.3",
36
- "vite": "^8.1.0",
48
+ "vite": "^8.1.3",
37
49
  "vue": "^3.5.39",
38
50
  "vue-router": "^5.1.0"
39
51
  }
package/plugin.js ADDED
@@ -0,0 +1,39 @@
1
+ import { createApp } from 'vue';
2
+ import tooltip from './tooltip.js';
3
+ import fallbackImage from './fallbackImage.js';
4
+ import fetcher from './fetcher.js';
5
+ import { setNotifyPosition } from './notifyState.js';
6
+ import Notification from './components/Notification.vue';
7
+
8
+ const CONTAINER_ID = 'pankow-notification-root';
9
+
10
+ export default {
11
+ install(app, options = {}) {
12
+ app.directive('tooltip', tooltip);
13
+ app.directive('fallback-image', fallbackImage);
14
+
15
+ if (options.fetcher) {
16
+ if (options.fetcher.credentials !== undefined) {
17
+ fetcher.globalOptions.credentials = options.fetcher.credentials;
18
+ }
19
+ if (options.fetcher.errorHook !== undefined) {
20
+ fetcher.globalOptions.errorHook = options.fetcher.errorHook;
21
+ }
22
+ }
23
+
24
+ if (options.notification?.position) {
25
+ setNotifyPosition(options.notification.position);
26
+ }
27
+
28
+ if (typeof document !== 'undefined') {
29
+ const existing = document.getElementById(CONTAINER_ID);
30
+ if (existing) existing.remove();
31
+
32
+ const container = document.createElement('div');
33
+ container.id = CONTAINER_ID;
34
+ document.body.appendChild(container);
35
+
36
+ createApp(Notification).mount(container);
37
+ }
38
+ }
39
+ };
package/tooltip.js CHANGED
@@ -1,19 +1,16 @@
1
- /*
1
+ /**
2
+ * Tooltip Directive
3
+ *
4
+ * Usage:
5
+ * ```
6
+ * import tooltip from 'pankow/tooltip';
7
+ * app.directive('tooltip', tooltip);
8
+ * // <div v-tooltip.top="'hello'"></div>
9
+ * ```
10
+ *
11
+ * Position modifiers: `.top`, `.left`, `.right` (default: bottom).
12
+ */
2
13
 
3
- Tooltip Directive
4
-
5
- ```
6
- import tooltip from 'pankow/tooltip';
7
-
8
- app.directive('tooltip', tooltip);
9
-
10
- ...
11
-
12
- <div v-tooltip.top="'hello'"></div>
13
-
14
- ```
15
-
16
- */
17
14
 
18
15
  const TOP = 1;
19
16
  const BOTTOM = 2;
@@ -73,6 +70,12 @@ function update(target, modifiers, key) {
73
70
  else tooltips[key].element.style.top = (targetRect.bottom + padding) + 'px';
74
71
  }
75
72
 
73
+ /**
74
+ * Vue directive `mounted` hook. Creates tooltip element on mouseenter.
75
+ * @param {HTMLElement} el
76
+ * @param {import('vue').DirectiveBinding} binding
77
+ * @param {import('vue').VNode} vnode
78
+ */
76
79
  function mounted(el, binding, vnode) {
77
80
  // generate running unique id
78
81
  el.__pankow_id = id++;
@@ -112,6 +115,12 @@ function mounted(el, binding, vnode) {
112
115
 
113
116
  }
114
117
 
118
+ /**
119
+ * Vue directive `updated` hook. Updates tooltip text and position.
120
+ * @param {HTMLElement} el
121
+ * @param {import('vue').DirectiveBinding} binding
122
+ * @param {import('vue').VNode} vnode
123
+ */
115
124
  function updated(el, binding, vnode) {
116
125
  if (!tooltips[el.__pankow_id]) return;
117
126
 
@@ -123,6 +132,12 @@ function updated(el, binding, vnode) {
123
132
  update(el, binding.modifiers, el.__pankow_id);
124
133
  }
125
134
 
135
+ /**
136
+ * Vue directive `beforeUnmount` hook. Removes tooltip element and cleans up.
137
+ * @param {HTMLElement} el
138
+ * @param {import('vue').DirectiveBinding} binding
139
+ * @param {import('vue').VNode} vnode
140
+ */
126
141
  function beforeUnmount(el, binding, vnode) {
127
142
  if (!tooltips[el.__pankow_id]) return;
128
143
 
@@ -130,6 +145,10 @@ function beforeUnmount(el, binding, vnode) {
130
145
  delete tooltips[el.__pankow_id];
131
146
  }
132
147
 
148
+ /**
149
+ * Vue directive for tooltips. Register via `app.directive('tooltip', tooltip)`.
150
+ * @type {import('vue').Directive}
151
+ */
133
152
  const tooltip = {
134
153
  mounted,
135
154
  updated,
@@ -1,5 +1,6 @@
1
1
  export default fallbackImage;
2
- declare namespace fallbackImage {
3
- export { mounted };
4
- }
5
- declare function mounted(el: any, binding: any, vnode: any): void;
2
+ /**
3
+ * Vue directive for image fallback. Register via `app.directive('fallback-image', fallbackImage)`.
4
+ * @type {import('vue').Directive}
5
+ */
6
+ declare const fallbackImage: import("vue").Directive;
@@ -8,33 +8,83 @@ declare namespace _default {
8
8
  export { del as delete };
9
9
  }
10
10
  export default _default;
11
+ /**
12
+ * Shared configuration for all HTTP requests.
13
+ */
14
+ export type FetcherGlobalOptions = {
15
+ /**
16
+ * - Fetch credentials mode
17
+ */
18
+ credentials: string;
19
+ /**
20
+ * - Fetch redirect mode
21
+ */
22
+ redirect: string;
23
+ /**
24
+ * - Called on non-2xx responses or network errors
25
+ */
26
+ errorHook: ((arg0: Response | Error) => void) | null;
27
+ };
11
28
  declare namespace globalOptions {
12
29
  let credentials: string;
13
30
  let redirect: string;
14
31
  let errorHook: null;
15
32
  }
16
- /** @param {RequestInit} [options] Merged into `fetch()`; use `{ signal }` to abort. */
17
- declare function head(uri: any, query?: {}, options?: RequestInit): Promise<{
33
+ /**
34
+ * Sends a HEAD request.
35
+ * @param {string} uri
36
+ * @param {Object} [query={}] - Query parameters serialized as URL query string
37
+ * @param {RequestInit} [options={}] - Merged into `fetch()`; use `{ signal }` to abort
38
+ * @returns {Promise<{ status: number, body: * }>}
39
+ */
40
+ declare function head(uri: string, query?: Object, options?: RequestInit): Promise<{
18
41
  status: number;
19
42
  body: any;
20
43
  }>;
21
- /** @param {RequestInit} [options] Merged into `fetch()`; use `{ signal }` to abort. */
22
- declare function get(uri: any, query?: {}, options?: RequestInit): Promise<{
44
+ /**
45
+ * Sends a GET request.
46
+ * @param {string} uri
47
+ * @param {Object} [query={}] - Query parameters serialized as URL query string
48
+ * @param {RequestInit} [options={}] - Merged into `fetch()`; use `{ signal }` to abort
49
+ * @returns {Promise<{ status: number, body: * }>}
50
+ */
51
+ declare function get(uri: string, query?: Object, options?: RequestInit): Promise<{
23
52
  status: number;
24
53
  body: any;
25
54
  }>;
26
- /** @param {RequestInit} [options] Merged into `fetch()`; use `{ signal }` to abort. */
27
- declare function post(uri: any, body: any, query?: {}, options?: RequestInit): Promise<{
55
+ /**
56
+ * Sends a POST request with a JSON or FormData body.
57
+ * @param {string} uri
58
+ * @param {Object|FormData} body - Request body; objects are JSON-stringified
59
+ * @param {Object} [query={}] - Query parameters serialized as URL query string
60
+ * @param {RequestInit} [options={}] - Merged into `fetch()`; use `{ signal }` to abort
61
+ * @returns {Promise<{ status: number, body: * }>}
62
+ */
63
+ declare function post(uri: string, body: Object | FormData, query?: Object, options?: RequestInit): Promise<{
28
64
  status: number;
29
65
  body: any;
30
66
  }>;
31
- /** @param {RequestInit} [options] Merged into `fetch()`; use `{ signal }` to abort. */
32
- declare function put(uri: any, body: any, query?: {}, options?: RequestInit): Promise<{
67
+ /**
68
+ * Sends a PUT request with a JSON or FormData body.
69
+ * @param {string} uri
70
+ * @param {Object|FormData} body - Request body; objects are JSON-stringified
71
+ * @param {Object} [query={}] - Query parameters serialized as URL query string
72
+ * @param {RequestInit} [options={}] - Merged into `fetch()`; use `{ signal }` to abort
73
+ * @returns {Promise<{ status: number, body: * }>}
74
+ */
75
+ declare function put(uri: string, body: Object | FormData, query?: Object, options?: RequestInit): Promise<{
33
76
  status: number;
34
77
  body: any;
35
78
  }>;
36
- /** @param {RequestInit} [options] Merged into `fetch()`; use `{ signal }` to abort. */
37
- declare function del(uri: any, body: any, query?: {}, options?: RequestInit): Promise<{
79
+ /**
80
+ * Sends a DELETE request with an optional body.
81
+ * @param {string} uri
82
+ * @param {Object|FormData} body - Request body; objects are JSON-stringified
83
+ * @param {Object} [query={}] - Query parameters serialized as URL query string
84
+ * @param {RequestInit} [options={}] - Merged into `fetch()`; use `{ signal }` to abort
85
+ * @returns {Promise<{ status: number, body: * }>}
86
+ */
87
+ declare function del(uri: string, body: Object | FormData, query?: Object, options?: RequestInit): Promise<{
38
88
  status: number;
39
89
  body: any;
40
90
  }>;
@@ -2,4 +2,19 @@ declare namespace _default {
2
2
  export { onSwipe };
3
3
  }
4
4
  export default _default;
5
- export function onSwipe(elem: any, callback: any, threshold?: number): void;
5
+ /**
6
+ * Swipe handler
7
+ *
8
+ * Usage:
9
+ * ```
10
+ * import { onSwipe } from 'pankow/gestures';
11
+ * onSwipe(element, (direction) => {});
12
+ * ```
13
+ */
14
+ /**
15
+ * Registers touch event listeners on an element and calls the callback on swipe.
16
+ * @param {HTMLElement} elem
17
+ * @param {function('left'|'right'|'up'|'down'): void} callback
18
+ * @param {number} [threshold=50] - Minimum pixel distance to trigger a swipe
19
+ */
20
+ export function onSwipe(elem: HTMLElement, callback: (arg0: "left" | "right" | "up" | "down") => void, threshold?: number): void;
package/types/index.d.ts CHANGED
@@ -1,6 +1,9 @@
1
+ export { useNotify } from "./notifyState.js";
2
+ export default pankowPlugin;
1
3
  import fetcher from './fetcher.js';
2
4
  import gestures from './gestures.js';
3
5
  import tooltip from './tooltip.js';
4
6
  import fallbackImage from './fallbackImage.js';
5
7
  import utils from './utils.js';
6
- export { BottomBar, Breadcrumb, Button, ButtonGroup, ClipboardAction, ClipboardButton, Checkbox, DateTimeInput, Dialog, DirectoryView, EmailInput, FileUploader, FormGroup, InputGroup, Icon, InputDialog, LoginView, MainLayout, MaskedInput, Menu, MenuItem, SingleSelect, MultiSelect, Notification, NumberInput, OfflineBanner, PasswordInput, Popover, ProgressBar, Radiobutton, SideBar, SplitLayout, Spinner, Switch, TableView, TableViewActionBar, TabView, TagInput, TextInput, TextInputRaw, TopBar, TreeView, fetcher, gestures, tooltip, fallbackImage, utils };
8
+ import pankowPlugin from './plugin.js';
9
+ export { BottomBar, BreadCrumb, Button, ButtonGroup, ClipboardAction, ClipboardButton, CheckBox, DateTimeInput, Dialog, DirectoryView, EmailInput, FileUploader, FormGroup, InputGroup, Icon, ListItem, InputDialog, LoginView, MainLayout, MaskedInput, Menu, MenuItem, SingleSelect, MultiSelect, Notification, NumberInput, OfflineBanner, PasswordInput, Popover, ProgressBar, RadioButton, SectionItem, SideBar, SplitLayout, Spinner, Switch, TableView, TableViewActionBar, TabView, TagInput, TextInput, TextInputRaw, TopBar, TreeView, fetcher, gestures, tooltip, fallbackImage, utils, CheckBox as Checkbox, RadioButton as Radiobutton, BreadCrumb as Breadcrumb };
@@ -0,0 +1,8 @@
1
+ export const messages: import("vue").Reactive<never[]>;
2
+ export const position: import("vue").Ref<string, string>;
3
+ export function pushNotify(options: any): void;
4
+ export function removeNotify(id: any): void;
5
+ export function setNotifyPosition(pos: any): void;
6
+ export function useNotify(): {
7
+ notify: typeof pushNotify;
8
+ };
@@ -0,0 +1,4 @@
1
+ declare namespace _default {
2
+ function install(app: any, options?: {}): void;
3
+ }
4
+ export default _default;
@@ -1,9 +1,6 @@
1
1
  export default tooltip;
2
- declare namespace tooltip {
3
- export { mounted };
4
- export { updated };
5
- export { beforeUnmount };
6
- }
7
- declare function mounted(el: any, binding: any, vnode: any): void;
8
- declare function updated(el: any, binding: any, vnode: any): void;
9
- declare function beforeUnmount(el: any, binding: any, vnode: any): void;
2
+ /**
3
+ * Vue directive for tooltips. Register via `app.directive('tooltip', tooltip)`.
4
+ * @type {import('vue').Directive}
5
+ */
6
+ declare const tooltip: import("vue").Directive;