@cloudron/pankow 4.3.4 → 4.3.6

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.
@@ -77,6 +77,7 @@ function onClick(event) {
77
77
  align-items: center;
78
78
  justify-content: center;
79
79
  display: inline-flex;
80
+ line-height: 1.2;
80
81
  cursor: pointer;
81
82
  border: 1px solid transparent;
82
83
  transition: background 250ms, border-color 250ms;
@@ -101,6 +102,12 @@ a.pankow-button:visited {
101
102
  margin-right: 7px;
102
103
  }
103
104
 
105
+ .pankow-button [class^="fa-"],
106
+ .pankow-button [class*=" fa-"],
107
+ .pankow-button .fa {
108
+ line-height: inherit;
109
+ }
110
+
104
111
  .pankow-button-icon-right-with-text {
105
112
  padding-left: 7px;
106
113
  }
@@ -1,6 +1,7 @@
1
1
  <script setup>
2
2
 
3
3
  import { uuidv4 } from '../utils.js';
4
+ import textOverflow from '../text-overflow.js';
4
5
 
5
6
  const props = defineProps({
6
7
  label: String,
@@ -13,13 +14,15 @@ const model = defineModel({ type: Boolean });
13
14
 
14
15
  const internalId = uuidv4();
15
16
 
17
+ const vTextOverflow = textOverflow;
18
+
16
19
  </script>
17
20
 
18
21
  <template>
19
22
  <span class="pankow-checkbox">
20
23
  <input :id="id || internalId" class="pankow-checkbox-input" type="checkbox" v-model="model" :disabled="disabled" :required="$attrs['required']" @input="$emit('update:modelValue', $event.target.checked)"/>
21
24
  <slot>
22
- <label :for="id || internalId" class="pankow-checkbox-input-label">
25
+ <label :for="id || internalId" class="pankow-checkbox-input-label" v-text-overflow>
23
26
  {{ label }}
24
27
  <sup v-if="helpUrl"><a :href="helpUrl" target="_blank" tabindex="-1"><i class="fa fa-question-circle"></i></a></sup>
25
28
  </label>
@@ -58,6 +58,7 @@
58
58
  :show-modified="showModified"
59
59
  :rename-handler="renameHandler"
60
60
  :share-indicator-property="shareIndicatorProperty"
61
+ :file-drop-indicator-property="fileDropIndicatorProperty"
61
62
  :select-handler="onSelectAndFocus"
62
63
  :drop-handler="onDrop"
63
64
  :can-drop-handler="onCanDropHandler"
@@ -77,6 +78,7 @@
77
78
  :show-star="showStar"
78
79
  :rename-handler="renameHandler"
79
80
  :share-indicator-property="shareIndicatorProperty"
81
+ :file-drop-indicator-property="fileDropIndicatorProperty"
80
82
  :select-handler="onSelectAndFocus"
81
83
  :drop-handler="onDrop"
82
84
  :can-drop-handler="onCanDropHandler"
@@ -198,6 +200,10 @@ const props = defineProps({
198
200
  type: String,
199
201
  default: '',
200
202
  },
203
+ fileDropIndicatorProperty: {
204
+ type: String,
205
+ default: '',
206
+ },
201
207
  editable: {
202
208
  type: Boolean,
203
209
  default: true,
@@ -694,8 +700,9 @@ function onSelectAndFocus(item, event, keepSelected = false) {
694
700
  invalidateSelected();
695
701
  }
696
702
 
697
- const contextMenuBodyModel = [
703
+ const contextMenuBodyModel = ref([
698
704
  {
705
+ id: 'paste-body',
699
706
  label: props.tr('filemanager.list.menu.paste'),
700
707
  icon: 'fa-regular fa-paste',
701
708
  disabled: () => !clipboard.files || !clipboard.files.length,
@@ -704,56 +711,66 @@ const contextMenuBodyModel = [
704
711
  },
705
712
  },
706
713
  {
714
+ id: 'select-all-body',
707
715
  label: props.tr('filemanager.list.menu.selectAll'),
708
716
  icon: 'fa-solid fa-check-double',
709
717
  action: onSelectAll,
710
718
  },
711
719
  {
720
+ id: 'sep-body1',
712
721
  separator: true,
713
722
  visible: () => typeof props.refreshHandler === 'function',
714
723
  },
715
724
  {
725
+ id: 'refresh-body',
716
726
  label: props.tr('filemanager.toolbar.refresh'),
717
727
  icon: 'fa-solid fa-arrow-rotate-right',
718
728
  visible: () => typeof props.refreshHandler === 'function',
719
729
  action: props.refreshHandler,
720
730
  },
721
731
  {
732
+ id: 'sep-body2',
722
733
  separator: true,
723
734
  visible: () => props.showNewFile || props.showNewFolder,
724
735
  },
725
736
  {
737
+ id: 'new-file-body',
726
738
  label: props.tr('filemanager.toolbar.newFile'),
727
739
  icon: 'fa-solid fa-file-circle-plus',
728
740
  action: props.newFileHandler,
729
741
  visible: () => props.showNewFile,
730
742
  },
731
743
  {
744
+ id: 'new-folder-body',
732
745
  label: props.tr('filemanager.toolbar.newFolder'),
733
746
  icon: 'fa-solid fa-folder-plus',
734
747
  action: props.newFolderHandler,
735
748
  visible: () => props.showNewFolder,
736
749
  },
737
750
  {
751
+ id: 'sep-body3',
738
752
  separator: true,
739
753
  visible: () => props.showUploadFile || props.showUploadFolder,
740
754
  },
741
755
  {
756
+ id: 'upload-file-body',
742
757
  label: props.tr('filemanager.toolbar.uploadFile'),
743
758
  icon: 'fa-solid fa-file-arrow-up',
744
759
  action: props.uploadFileHandler,
745
760
  visible: () => props.showUploadFile,
746
761
  },
747
762
  {
763
+ id: 'upload-folder-body',
748
764
  label: props.tr('filemanager.toolbar.uploadFolder'),
749
765
  icon: 'fa-regular fa-folder-open',
750
766
  action: props.uploadFolderHandler,
751
767
  visible: () => props.showUploadFolder,
752
768
  },
753
- ];
769
+ ]);
754
770
 
755
- const contextMenuModel = [
771
+ const contextMenuModel = ref([
756
772
  {
773
+ id: 'open',
757
774
  label: props.tr('filemanager.list.menu.open'),
758
775
  icon: 'fa-regular fa-folder-open',
759
776
  disabled: () => selectedCount.value > 1,
@@ -762,6 +779,7 @@ const contextMenuModel = [
762
779
  },
763
780
  },
764
781
  {
782
+ id: 'sep-actions-top',
765
783
  separator: true,
766
784
  visible: () =>
767
785
  props.showDownload ||
@@ -772,6 +790,7 @@ const contextMenuModel = [
772
790
  props.showSelectAll,
773
791
  },
774
792
  {
793
+ id: 'download',
775
794
  label: props.tr('filemanager.list.menu.download'),
776
795
  icon: 'fa-solid fa-download',
777
796
  action: onItemDownload,
@@ -779,6 +798,7 @@ const contextMenuModel = [
779
798
  disabled: () => (props.multiDownload ? selectedCount.value === 0 : selectedCount.value !== 1),
780
799
  },
781
800
  {
801
+ id: 'share',
782
802
  label: props.tr('filemanager.list.menu.share'),
783
803
  icon: 'fa-solid fa-share-nodes',
784
804
  action: onItemShare,
@@ -786,18 +806,21 @@ const contextMenuModel = [
786
806
  visible: () => props.showShare,
787
807
  },
788
808
  {
809
+ id: 'copy',
789
810
  label: props.tr('filemanager.list.menu.copy'),
790
811
  icon: 'fa-regular fa-copy',
791
812
  action: onItemsCopy,
792
813
  visible: () => props.showCopy,
793
814
  },
794
815
  {
816
+ id: 'cut',
795
817
  label: props.tr('filemanager.list.menu.cut'),
796
818
  icon: 'fa-solid fa-scissors',
797
819
  action: onItemsCut,
798
820
  visible: () => props.showCut,
799
821
  },
800
822
  {
823
+ id: 'paste',
801
824
  label: props.tr('filemanager.list.menu.paste'),
802
825
  icon: 'fa-regular fa-paste',
803
826
  visible: () => props.showPaste,
@@ -811,12 +834,14 @@ const contextMenuModel = [
811
834
  },
812
835
  },
813
836
  {
837
+ id: 'select-all',
814
838
  label: props.tr('filemanager.list.menu.selectAll'),
815
839
  icon: 'fa-solid fa-check-double',
816
840
  visible: () => props.showSelectAll,
817
841
  action: onSelectAll,
818
842
  },
819
843
  {
844
+ id: 'rename',
820
845
  label: props.tr('filemanager.list.menu.rename'),
821
846
  icon: 'fa-regular fa-pen-to-square',
822
847
  action: onItemRenameBegin,
@@ -824,12 +849,14 @@ const contextMenuModel = [
824
849
  disabled: () => !props.editable || selectedCount.value > 1,
825
850
  },
826
851
  {
852
+ id: 'chown',
827
853
  label: props.tr('filemanager.list.menu.chown'),
828
854
  icon: 'fa-solid fa-user-pen',
829
855
  action: onItemsChangeOwner,
830
856
  visible: () => props.showOwner,
831
857
  },
832
858
  {
859
+ id: 'extract',
833
860
  label: props.tr('filemanager.list.menu.extract'),
834
861
  action: onItemExtract,
835
862
  visible: () => {
@@ -852,10 +879,12 @@ const contextMenuModel = [
852
879
  },
853
880
  },
854
881
  {
882
+ id: 'sep-actions-bottom',
855
883
  separator: true,
856
884
  visible: () => props.showDelete,
857
885
  },
858
886
  {
887
+ id: 'delete',
859
888
  label: props.tr('filemanager.list.menu.delete'),
860
889
  icon: 'fa-regular fa-trash-can',
861
890
  action: () => {
@@ -863,7 +892,7 @@ const contextMenuModel = [
863
892
  },
864
893
  visible: () => props.showDelete,
865
894
  },
866
- ];
895
+ ]);
867
896
 
868
897
  const filteredSortedItems = computed(() => {
869
898
  invalidateSelected();
@@ -902,6 +931,9 @@ const filteredSortedItems = computed(() => {
902
931
  });
903
932
 
904
933
  defineExpose({
934
+ contextMenuModel,
935
+ contextMenuBodyModel,
936
+ focusItem,
905
937
  highlight,
906
938
  highlightByName,
907
939
  });
@@ -19,6 +19,7 @@
19
19
  <template v-if="visible">
20
20
  <img :src="item.previewUrl || item.icon" ref="iconImage" @error="iconError($event)"/>
21
21
  <i v-show="shareIndicatorProperty !== '' && !!item[shareIndicatorProperty]" class="fa-solid fa-share-nodes is-shared"></i>
22
+ <i v-show="fileDropIndicatorProperty !== '' && !!item[fileDropIndicatorProperty]" class="fa-solid fa-cloud-arrow-up is-filedrop"></i>
22
23
  </template>
23
24
  </div>
24
25
 
@@ -62,6 +63,10 @@ const props = defineProps({
62
63
  type: String,
63
64
  default: '',
64
65
  },
66
+ fileDropIndicatorProperty: {
67
+ type: String,
68
+ default: '',
69
+ },
65
70
  fallbackIcon: String,
66
71
  renameHandler: {
67
72
  type: Function,
@@ -323,6 +328,13 @@ defineExpose({
323
328
  font-size: 1rem;
324
329
  }
325
330
 
331
+ .is-filedrop {
332
+ position: absolute;
333
+ left: 2px;
334
+ bottom: 2px;
335
+ font-size: 1rem;
336
+ }
337
+
326
338
  .grid-item-label {
327
339
  width: 100%;
328
340
  text-align: center;
@@ -14,6 +14,7 @@
14
14
  <div v-if="visible" class="col icon">
15
15
  <img :src="item.previewUrl || item.icon" ref="iconImage" @error="iconError($event)"/>
16
16
  <i v-show="shareIndicatorProperty !== '' && !!item[shareIndicatorProperty]" class="fa-solid fa-share-nodes is-shared"></i>
17
+ <i v-show="fileDropIndicatorProperty !== '' && !!item[fileDropIndicatorProperty]" class="fa-solid fa-cloud-arrow-up is-filedrop"></i>
17
18
  </div>
18
19
 
19
20
  <!-- this is just a placeholder label to allow the native browser search to work -->
@@ -81,6 +82,10 @@ const props = defineProps({
81
82
  type: String,
82
83
  default: '',
83
84
  },
85
+ fileDropIndicatorProperty: {
86
+ type: String,
87
+ default: '',
88
+ },
84
89
  fallbackIcon: String,
85
90
  renameHandler: {
86
91
  type: Function,
@@ -305,6 +310,7 @@ defineExpose({
305
310
  height: 45px;
306
311
  width: 45px;
307
312
  padding: 5px;
313
+ position: relative;
308
314
  }
309
315
 
310
316
  .icon > img {
@@ -341,6 +347,13 @@ defineExpose({
341
347
  font-size: 1.2rem
342
348
  }
343
349
 
350
+ .is-filedrop {
351
+ position: absolute;
352
+ left: 2px;
353
+ bottom: 0;
354
+ font-size: 1.2rem
355
+ }
356
+
344
357
  .label {
345
358
  padding-left: 5px;
346
359
  flex-grow: 1;
package/index.js CHANGED
@@ -59,6 +59,7 @@ import gestures from './gestures.js';
59
59
  import utils from './utils.js';
60
60
  import tooltip from './tooltip.js';
61
61
  import fallbackImage from './fallbackImage.js';
62
+ import textOverflow from './text-overflow.js';
62
63
 
63
64
  export {
64
65
  BottomBar,
@@ -111,6 +112,7 @@ export {
111
112
  gestures,
112
113
  tooltip,
113
114
  fallbackImage,
115
+ textOverflow,
114
116
  utils,
115
117
  };
116
118
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudron/pankow",
3
3
  "private": false,
4
- "version": "4.3.4",
4
+ "version": "4.3.6",
5
5
  "description": "Vue 3 UI component library for Cloudron apps",
6
6
  "main": "index.js",
7
7
  "types": "types/index.d.ts",
@@ -37,10 +37,10 @@
37
37
  "author": "",
38
38
  "license": "ISC",
39
39
  "dependencies": {
40
- "@fontsource/inter": "^5.2.8",
41
- "@fortawesome/fontawesome-free": "^7.3.0",
40
+ "@fontsource/inter": "^5.3.0",
41
+ "@fortawesome/fontawesome-free": "^7.3.1",
42
42
  "filesize": "^11.0.22",
43
- "monaco-editor": "^0.55.1",
43
+ "monaco-editor": "^0.56.0",
44
44
  "online-3d-viewer": "^0.18.0"
45
45
  },
46
46
  "peerDependencies": {
@@ -48,13 +48,16 @@
48
48
  },
49
49
  "devDependencies": {
50
50
  "@highlightjs/vue-plugin": "^2.1.0",
51
- "@unhead/vue": "^2.1.15",
51
+ "@unhead/vue": "^3.2.1",
52
52
  "@vitejs/plugin-vue": "^6.0.8",
53
53
  "highlight.js": "^11.11.1",
54
54
  "typescript": "^7.0.2",
55
- "vite": "^8.1.4",
55
+ "vite": "^8.1.5",
56
56
  "vite-ssg": "^28.3.0",
57
- "vue": "^3.5.39",
58
- "vue-router": "^5.1.0"
57
+ "vue": "^3.5.40",
58
+ "vue-router": "^5.2.0"
59
+ },
60
+ "allowScripts": {
61
+ "core-js": false
59
62
  }
60
63
  }
package/plugin.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createApp } from 'vue';
2
2
  import tooltip from './tooltip.js';
3
3
  import fallbackImage from './fallbackImage.js';
4
+ import textOverflow from './text-overflow.js';
4
5
  import fetcher from './fetcher.js';
5
6
  import { setNotifyPosition } from './notifyState.js';
6
7
  import Notification from './components/Notification.vue';
@@ -11,6 +12,7 @@ export default {
11
12
  install(app, options = {}) {
12
13
  app.directive('tooltip', tooltip);
13
14
  app.directive('fallback-image', fallbackImage);
15
+ app.directive('text-overflow', textOverflow);
14
16
 
15
17
  if (options.fetcher) {
16
18
  if (options.fetcher.credentials !== undefined) {
package/style.css CHANGED
@@ -34,6 +34,8 @@
34
34
  --pankow-tooltip-background-color: #333;
35
35
  --pankow-tooltip-text-color: white;
36
36
 
37
+ --pankow-color-border: #ddd;
38
+
37
39
  --pankow-color-primary: #1a76bf;
38
40
  --pankow-color-primary-hover: #0d89ec;
39
41
  --pankow-color-primary-active: #0b7ad1;
@@ -111,6 +113,8 @@ input {
111
113
  --pankow-color-background: #1b1e21;
112
114
  --pankow-color-background-hover: #1f2326;
113
115
 
116
+ --pankow-color-border: #495057;
117
+
114
118
  --pankow-dialog-background-color: #32383e;
115
119
  --pankow-dialog-backdrop-color: rgba(0,0,0,.7);
116
120
  }
@@ -211,6 +215,33 @@ textarea[disabled]:hover {
211
215
  text-align: center;
212
216
  }
213
217
 
218
+ .pankow-text-overflow-tooltip {
219
+ position: fixed;
220
+ background: var(--pankow-color-background);
221
+ border: 1px solid var(--pankow-color-border);
222
+ border-radius: var(--pankow-border-radius);
223
+ padding: 8px 12px;
224
+ font-size: 13px;
225
+ z-index: 10000;
226
+ max-width: 400px;
227
+ white-space: normal;
228
+ word-break: break-word;
229
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
230
+ pointer-events: none;
231
+ }
232
+
233
+ @media (prefers-color-scheme: dark) {
234
+ .pankow-text-overflow-tooltip {
235
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
236
+ }
237
+ }
238
+
239
+ @media (hover: none) and (pointer: coarse) {
240
+ .pankow-text-overflow-tooltip {
241
+ display: none !important;
242
+ }
243
+ }
244
+
214
245
  .has-error {
215
246
  color: var(--pankow-color-danger);
216
247
  }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * TextOverflow Directive
3
+ *
4
+ * Shows a cursor-following tooltip overlay only when the element's text content
5
+ * is actually clipped (scrollWidth > clientWidth).
6
+ *
7
+ * Usage:
8
+ * ```
9
+ * import textOverflow from 'pankow/text-overflow';
10
+ * app.directive('text-overflow', textOverflow);
11
+ * // <div v-text-overflow>{{ longText }}</div>
12
+ * ```
13
+ */
14
+
15
+ const tooltips = {};
16
+ let id = 0;
17
+
18
+ function createOverlay() {
19
+ const el = document.createElement('div');
20
+ el.classList.add('pankow-text-overflow-tooltip');
21
+ el.style.display = 'none';
22
+ document.body.appendChild(el);
23
+ return el;
24
+ }
25
+
26
+ function isOverflowing(el) {
27
+ return el.scrollWidth > el.clientWidth;
28
+ }
29
+
30
+ /**
31
+ * Vue directive `mounted` hook.
32
+ * @param {HTMLElement} el
33
+ * @param {import('vue').DirectiveBinding} binding
34
+ * @param {import('vue').VNode} vnode
35
+ */
36
+ function mounted(el, binding, vnode) {
37
+ el.__pankow_to_id = id++;
38
+
39
+ tooltips[el.__pankow_to_id] = {
40
+ overlay: null,
41
+ text: el.textContent || '',
42
+ };
43
+
44
+ el.addEventListener('mouseenter', onMouseEnter);
45
+ el.addEventListener('mouseleave', onMouseLeave);
46
+ el.addEventListener('mousemove', onMouseMove);
47
+ }
48
+
49
+ /**
50
+ * Vue directive `updated` hook.
51
+ * @param {HTMLElement} el
52
+ * @param {import('vue').DirectiveBinding} binding
53
+ * @param {import('vue').VNode} vnode
54
+ */
55
+ function updated(el, binding, vnode) {
56
+ const state = tooltips[el.__pankow_to_id];
57
+ if (state) state.text = el.textContent || '';
58
+ }
59
+
60
+ /**
61
+ * Vue directive `beforeUnmount` hook.
62
+ * @param {HTMLElement} el
63
+ * @param {import('vue').DirectiveBinding} binding
64
+ * @param {import('vue').VNode} vnode
65
+ */
66
+ function beforeUnmount(el, binding, vnode) {
67
+ el.removeEventListener('mouseenter', onMouseEnter);
68
+ el.removeEventListener('mouseleave', onMouseLeave);
69
+ el.removeEventListener('mousemove', onMouseMove);
70
+
71
+ const state = tooltips[el.__pankow_to_id];
72
+ if (state) {
73
+ if (state.overlay) state.overlay.remove();
74
+ delete tooltips[el.__pankow_to_id];
75
+ }
76
+ }
77
+
78
+ function onMouseEnter(event) {
79
+ const el = event.currentTarget;
80
+ if (!isOverflowing(el)) return;
81
+
82
+ const state = tooltips[el.__pankow_to_id];
83
+ if (!state) return;
84
+
85
+ if (!state.overlay) state.overlay = createOverlay();
86
+ state.overlay.textContent = state.text;
87
+ state.overlay.style.display = 'block';
88
+ updatePosition(event, state);
89
+ }
90
+
91
+ function onMouseLeave(event) {
92
+ const el = event.currentTarget;
93
+ const state = tooltips[el.__pankow_to_id];
94
+ if (!state || !state.overlay) return;
95
+ state.overlay.style.display = 'none';
96
+ }
97
+
98
+ function onMouseMove(event) {
99
+ const el = event.currentTarget;
100
+ const state = tooltips[el.__pankow_to_id];
101
+ updatePosition(event, state);
102
+ }
103
+
104
+ function updatePosition(event, state) {
105
+ if (!state || !state.overlay) return;
106
+ state.overlay.style.left = (event.clientX + 10) + 'px';
107
+ state.overlay.style.top = (event.clientY + 20) + 'px';
108
+ }
109
+
110
+ /**
111
+ * Vue directive for text-overflow tooltips. Register via `app.directive('text-overflow', textOverflow)`.
112
+ * @type {import('vue').Directive}
113
+ */
114
+ const textOverflow = {
115
+ mounted,
116
+ updated,
117
+ beforeUnmount
118
+ };
119
+
120
+ export default textOverflow;
package/types/index.d.ts CHANGED
@@ -53,7 +53,8 @@ import gestures from './gestures.js';
53
53
  import utils from './utils.js';
54
54
  import tooltip from './tooltip.js';
55
55
  import fallbackImage from './fallbackImage.js';
56
- 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, SaveIndicator, SectionItem, SideBar, SplitLayout, Spinner, Switch, TableView, TableViewActionBar, TabView, TagInput, TextInput, TextInputRaw, TopBar, TreeView, fetcher, gestures, tooltip, fallbackImage, utils, };
56
+ import textOverflow from './text-overflow.js';
57
+ 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, SaveIndicator, SectionItem, SideBar, SplitLayout, Spinner, Switch, TableView, TableViewActionBar, TabView, TagInput, TextInput, TextInputRaw, TopBar, TreeView, fetcher, gestures, tooltip, fallbackImage, textOverflow, utils, };
57
58
  export { CheckBox as Checkbox };
58
59
  export { RadioButton as Radiobutton };
59
60
  export { BreadCrumb as Breadcrumb };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * TextOverflow Directive
3
+ *
4
+ * Shows a cursor-following tooltip overlay only when the element's text content
5
+ * is actually clipped (scrollWidth > clientWidth).
6
+ *
7
+ * Usage:
8
+ * ```
9
+ * import textOverflow from 'pankow/text-overflow';
10
+ * app.directive('text-overflow', textOverflow);
11
+ * // <div v-text-overflow>{{ longText }}</div>
12
+ * ```
13
+ */
14
+ /**
15
+ * Vue directive for text-overflow tooltips. Register via `app.directive('text-overflow', textOverflow)`.
16
+ * @type {import('vue').Directive}
17
+ */
18
+ declare const textOverflow: import('vue').Directive;
19
+ export default textOverflow;