@nextcloud/vue 9.12.0 → 9.13.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 (100) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/assets/NcAppContent.css +20 -20
  3. package/dist/assets/NcAppNavigation.css +13 -13
  4. package/dist/assets/NcAppNavigationSettings.css +6 -6
  5. package/dist/assets/NcAppSettingsDialog.css +3 -3
  6. package/dist/assets/NcAppSettingsShortcutsSection.css +1 -1
  7. package/dist/assets/NcAppSidebar.css +28 -28
  8. package/dist/assets/NcAssistantButton.css +9 -9
  9. package/dist/assets/NcAssistantContent.css +3 -3
  10. package/dist/assets/NcAssistantIcon.css +4 -4
  11. package/dist/assets/NcAvatar.css +26 -26
  12. package/dist/assets/NcBlurHash.css +2 -2
  13. package/dist/assets/NcDateTimePicker.css +234 -234
  14. package/dist/assets/NcDialog.css +16 -16
  15. package/dist/assets/NcFilePicker.css +1 -1
  16. package/dist/assets/NcFormBox.css +11 -11
  17. package/dist/assets/NcFormBoxButton.css +2 -2
  18. package/dist/assets/NcFormBoxItem.css +15 -15
  19. package/dist/assets/NcFormBoxSwitch.css +2 -2
  20. package/dist/assets/NcFormGroup.css +7 -7
  21. package/dist/assets/NcHotkey.css +8 -8
  22. package/dist/assets/NcHotkeyList.css +2 -2
  23. package/dist/assets/NcIconToggleSwitch.css +4 -4
  24. package/dist/assets/NcKbd.css +3 -3
  25. package/dist/assets/NcModal.css +71 -64
  26. package/dist/assets/NcPopover.css +16 -16
  27. package/dist/assets/NcRadioGroup.css +2 -2
  28. package/dist/assets/NcRadioGroupButton.css +14 -14
  29. package/dist/assets/NcReferenceWidget.css +24 -23
  30. package/dist/assets/NcRichContenteditable.css +17 -17
  31. package/dist/assets/NcSelect.css +8 -13
  32. package/dist/assets/NcUploadPicker.css +7 -7
  33. package/dist/assets/autolink.css +3 -3
  34. package/dist/chunks/NcAppContent.mjs +170 -297
  35. package/dist/chunks/NcAppContent.mjs.map +1 -1
  36. package/dist/chunks/NcAppContentList.vue_vue_type_script_setup_true_lang.mjs +21 -0
  37. package/dist/chunks/NcAppContentList.vue_vue_type_script_setup_true_lang.mjs.map +1 -0
  38. package/dist/chunks/NcAppNavigation.mjs +7 -4
  39. package/dist/chunks/NcAppNavigation.mjs.map +1 -1
  40. package/dist/chunks/NcAppNavigationSettings.mjs +6 -6
  41. package/dist/chunks/NcAppSettingsDialog.mjs +4 -4
  42. package/dist/chunks/NcAppSettingsShortcutsSection.mjs +1 -1
  43. package/dist/chunks/NcAppSidebar.mjs +12 -12
  44. package/dist/chunks/NcAssistantButton.mjs +7 -7
  45. package/dist/chunks/NcAssistantContent.mjs +3 -3
  46. package/dist/chunks/NcAssistantIcon.mjs +4 -4
  47. package/dist/chunks/NcAvatar.mjs +14 -7
  48. package/dist/chunks/NcAvatar.mjs.map +1 -1
  49. package/dist/chunks/NcBlurHash.mjs +2 -2
  50. package/dist/chunks/NcContent.mjs +1 -1
  51. package/dist/chunks/NcDateTimePicker.mjs +39 -1
  52. package/dist/chunks/NcDateTimePicker.mjs.map +1 -1
  53. package/dist/chunks/NcDialog.mjs +1 -1
  54. package/dist/chunks/NcDialog.mjs.map +1 -1
  55. package/dist/chunks/NcFilePicker.mjs +1 -1
  56. package/dist/chunks/NcFormBox.mjs +5 -5
  57. package/dist/chunks/NcFormBoxButton.mjs +2 -2
  58. package/dist/chunks/NcFormBoxItem.mjs +8 -8
  59. package/dist/chunks/NcFormBoxSwitch.mjs +2 -2
  60. package/dist/chunks/NcFormGroup.mjs +7 -7
  61. package/dist/chunks/NcHotkey.mjs +4 -4
  62. package/dist/chunks/NcHotkeyList.mjs +2 -2
  63. package/dist/chunks/NcIconToggleSwitch.mjs +2 -2
  64. package/dist/chunks/NcKbd.mjs +2 -2
  65. package/dist/chunks/NcMentionBubble.vue_vue_type_style_index_0_scoped_3c4a673d_lang.mjs +7 -7
  66. package/dist/chunks/NcMentionBubble.vue_vue_type_style_index_0_scoped_3c4a673d_lang.mjs.map +1 -1
  67. package/dist/chunks/NcModal.mjs +11 -12
  68. package/dist/chunks/NcModal.mjs.map +1 -1
  69. package/dist/chunks/NcPopover.mjs +2 -2
  70. package/dist/chunks/NcPopover.mjs.map +1 -1
  71. package/dist/chunks/NcRadioGroup.mjs +2 -2
  72. package/dist/chunks/NcRadioGroupButton.mjs +6 -6
  73. package/dist/chunks/NcReferenceWidget.mjs +2 -2
  74. package/dist/chunks/NcReferenceWidget.mjs.map +1 -1
  75. package/dist/chunks/NcRichContenteditable.mjs +10 -10
  76. package/dist/chunks/NcSelect.mjs.map +1 -1
  77. package/dist/chunks/NcUploadPicker.mjs +6 -6
  78. package/dist/chunks/NcUploadPicker.mjs.map +1 -1
  79. package/dist/chunks/_l10n.mjs +24 -24
  80. package/dist/chunks/autolink.mjs +3 -3
  81. package/dist/components/NcAppContent/NcAppContent.vue.d.ts +77 -149
  82. package/dist/components/NcAppContent/index.d.ts +5 -0
  83. package/dist/components/NcAppContentList/NcAppContentList.vue.d.ts +28 -27
  84. package/dist/components/NcAppContentList/index.d.ts +4 -0
  85. package/dist/components/NcAppContentList/index.mjs +2 -2
  86. package/dist/components/NcAvatar/NcAvatar.vue.d.ts +17 -0
  87. package/dist/components/NcCollectionList/NcCollectionList.vue.d.ts +18 -0
  88. package/dist/components/NcCollectionList/NcCollectionListItem.vue.d.ts +9 -0
  89. package/dist/components/NcDashboardWidget/NcDashboardWidget.vue.d.ts +18 -0
  90. package/dist/components/NcDashboardWidgetItem/NcDashboardWidgetItem.vue.d.ts +9 -0
  91. package/dist/components/NcDateTimePicker/formatValidation.d.ts +10 -0
  92. package/dist/components/NcListItemIcon/NcListItemIcon.vue.d.ts +9 -0
  93. package/dist/components/NcModal/NcModal.vue.d.ts +3 -0
  94. package/dist/components/NcRichText/NcReferencePicker/NcReferencePickerModal.vue.d.ts +8 -0
  95. package/dist/components/index.d.ts +2 -2
  96. package/dist/index.mjs +169 -169
  97. package/dist/utils/getAvatarUrl.d.ts +4 -0
  98. package/package.json +11 -11
  99. package/dist/chunks/NcAppContentList.mjs +0 -33
  100. package/dist/chunks/NcAppContentList.mjs.map +0 -1
@@ -1,20 +1,20 @@
1
1
  import '../assets/NcAppContent.css';
2
- import { getBuilder } from "@nextcloud/browser-storage";
3
- import { getCapabilities } from "@nextcloud/capabilities";
2
+ import { defineComponent, watch, onMounted, onBeforeUnmount, openBlock, createBlock, unref, normalizeClass, withCtx, createVNode, useModel, ref, computed, createElementBlock, toDisplayString, createCommentVNode, Fragment, withModifiers, withDirectives, createElementVNode, renderSlot, vShow, mergeModels } from "vue";
4
3
  import { emit } from "@nextcloud/event-bus";
5
- import { useSwipe } from "@vueuse/core";
4
+ import { useCurrentElement, useSwipe } from "@vueuse/core";
6
5
  import { Splitpanes, Pane } from "splitpanes";
7
- import { defineComponent, watch, onMounted, onBeforeUnmount, openBlock, createBlock, unref, normalizeClass, withCtx, createVNode, resolveComponent, createElementBlock, toDisplayString, createCommentVNode, Fragment, withModifiers, withDirectives, createElementVNode, renderSlot, vShow } from "vue";
8
6
  import { m as mdiArrowRight } from "./mdi.mjs";
9
7
  import { useIsMobile } from "../composables/useIsMobile/index.mjs";
10
- import { r as register, H as t29, a as t } from "./_l10n.mjs";
8
+ import { r as register, J as t29, a as t } from "./_l10n.mjs";
11
9
  import { N as NcButton } from "./NcButton.mjs";
12
10
  import { N as NcIconSvgWrapper } from "./NcIconSvgWrapper.mjs";
13
11
  import { _ as _export_sfc } from "./_plugin-vue_export-helper.mjs";
14
- import { u as useLocalizedAppName, a as useAppName } from "./appName.mjs";
12
+ import { a as useAppName, u as useLocalizedAppName } from "./appName.mjs";
15
13
  import { l as logger } from "./logger.mjs";
16
14
  import { i as isRtl } from "./rtl.mjs";
17
15
  import "splitpanes/dist/splitpanes.css";
16
+ import { getBuilder } from "@nextcloud/browser-storage";
17
+ import { getCapabilities } from "@nextcloud/capabilities";
18
18
  register(t29);
19
19
  const _sfc_main$1 = /* @__PURE__ */ defineComponent({
20
20
  __name: "NcAppContentDetailsToggle",
@@ -57,324 +57,197 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
57
57
  }
58
58
  });
59
59
  const NcAppContentDetailsToggle = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-a28923a1"]]);
60
+ const _hoisted_1 = {
61
+ key: 0,
62
+ class: "hidden-visually"
63
+ };
64
+ const _hoisted_2 = { class: "app-content-wrapper__list" };
65
+ const _hoisted_3 = {
66
+ key: 1,
67
+ class: "app-content-wrapper"
68
+ };
60
69
  const browserStorage = getBuilder("nextcloud").persist().build();
61
70
  const instanceName = getCapabilities().theming?.name ?? "Nextcloud";
62
- const _sfc_main = {
63
- name: "NcAppContent",
64
- components: {
65
- NcAppContentDetailsToggle,
66
- Pane,
67
- Splitpanes
68
- },
69
- props: {
70
- /**
71
- * Allows to disable the control by swipe of the app navigation open state.
72
- */
73
- disableSwipe: {
74
- type: Boolean,
75
- default: false
76
- },
77
- /**
78
- * Allows you to set the default width of the resizable list in % on vertical-split
79
- * or respectively the default height on horizontal-split.
80
- *
81
- * Must be between `listMinWidth` and `listMaxWidth`.
82
- */
83
- listSize: {
84
- type: Number,
85
- default: 20
86
- },
87
- /**
88
- * Allows you to set the minimum width of the list column in % on vertical-split
89
- * or respectively the minimum height on horizontal-split.
90
- */
91
- listMinWidth: {
92
- type: Number,
93
- default: 15
94
- },
95
- /**
96
- * Allows you to set the maximum width of the list column in % on vertical-split
97
- * or respectively the maximum height on horizontal-split.
98
- */
99
- listMaxWidth: {
100
- type: Number,
101
- default: 40
102
- },
103
- /**
104
- * Specify the config key for the pane config sizes
105
- * Default is the global var appName if you use the webpack-vue-config
106
- */
107
- paneConfigKey: {
108
- type: String,
109
- default: ""
110
- },
111
- /**
112
- * When in mobile view, only the list or the details are shown.
113
- *
114
- * If you provide a list, you need to provide a variable
115
- * that will be set to true by the user when an element of
116
- * the list gets selected. The details will then show a back
117
- * arrow to return to the list that will update this prop to false.
118
- */
119
- showDetails: {
120
- type: Boolean,
121
- default: true
122
- },
123
- /**
124
- * Content layout used when there is a list together with content:
125
- * - `vertical-split` - a 2-column layout with list and default content separated vertically
126
- * - `no-split` - a single column layout; List is shown when `showDetails` is `false`, otherwise the default slot content is shown with a back button to return to the list.
127
- * - 'horizontal-split' - a 2-column layout with list and default content separated horizontally
128
- * On mobile screen `no-split` layout is forced.
129
- */
130
- layout: {
131
- type: String,
132
- default: "vertical-split",
133
- validator(value) {
134
- return ["no-split", "vertical-split", "horizontal-split"].includes(value);
71
+ const _sfc_main = /* @__PURE__ */ defineComponent({
72
+ __name: "NcAppContent",
73
+ props: /* @__PURE__ */ mergeModels({
74
+ disableSwipe: { type: Boolean, default: false },
75
+ listSize: { default: 20 },
76
+ listMinWidth: { default: 15 },
77
+ listMaxWidth: { default: 40 },
78
+ paneConfigKey: { default: "" },
79
+ layout: { default: "vertical-split" },
80
+ pageHeading: { default: () => void 0 },
81
+ pageTitle: { default: () => void 0 }
82
+ }, {
83
+ "showDetails": { type: Boolean, ...{ default: true } },
84
+ "showDetailsModifiers": {}
85
+ }),
86
+ emits: /* @__PURE__ */ mergeModels(["resizeList", "update:showDetails"], ["update:showDetails"]),
87
+ setup(__props, { emit: __emit }) {
88
+ const showDetails = useModel(__props, "showDetails");
89
+ const emit$1 = __emit;
90
+ const appName = useAppName();
91
+ const localizedAppName = useLocalizedAppName();
92
+ const isMobile = useIsMobile();
93
+ const element = useCurrentElement();
94
+ const swipe = useSwipe(
95
+ // Swiping can be disabled by not providing a target to listen on
96
+ () => __props.disableSwipe ? void 0 : element.value,
97
+ {
98
+ onSwipeEnd(_event, direction) {
99
+ const minSwipeX = 70;
100
+ const touchZone = 300;
101
+ if (Math.abs(swipe.lengthX.value) > minSwipeX) {
102
+ if (swipe.coordsStart.x < touchZone / 2 && direction === "right") {
103
+ emit("toggle-navigation", {
104
+ open: true
105
+ });
106
+ } else if (swipe.coordsStart.x < touchZone * 1.5 && direction === "left") {
107
+ emit("toggle-navigation", {
108
+ open: false
109
+ });
110
+ }
111
+ }
112
+ }
135
113
  }
136
- },
137
- /**
138
- * Specify the `<h1>` page heading
139
- */
140
- pageHeading: {
141
- type: String,
142
- default: null
143
- },
144
- /**
145
- * Allow setting the page's `<title>`
146
- *
147
- * If a page heading is set it defaults to `{pageHeading} - {appName} - {instanceName}` e.g. `Favorites - Files - MyPersonalCloud`.
148
- * When the page heading and the app name is the same only one is used, e.g. `Files - Files - MyPersonalCloud` is shown as `Files - MyPersonalCloud`.
149
- * When setting the prop then the following format will be used: `{pageTitle} - {instanceName}`
150
- */
151
- pageTitle: {
152
- type: String,
153
- default: null
154
- }
155
- },
156
- emits: [
157
- "update:showDetails",
158
- "resizeList"
159
- ],
160
- setup() {
161
- return {
162
- appName: useAppName(),
163
- localizedAppName: useLocalizedAppName(),
164
- isMobile: useIsMobile(),
165
- isRtl
166
- };
167
- },
168
- data() {
169
- return {
170
- contentHeight: 0,
171
- swiping: {},
172
- listPaneSize: this.restorePaneConfig()
173
- };
174
- },
175
- computed: {
176
- paneConfigID() {
177
- if (this.paneConfigKey !== "") {
178
- return `pane-list-size-${this.paneConfigKey}`;
114
+ );
115
+ const listPaneSize = ref();
116
+ const paneConfigID = computed(() => {
117
+ if (__props.paneConfigKey !== "") {
118
+ return `pane-list-size-${__props.paneConfigKey}`;
179
119
  }
180
- try {
181
- return `pane-list-size-${this.appName}`;
182
- } catch {
183
- logger.info("[NcAppContent]: falling back to global nextcloud pane config");
184
- return "pane-list-size-nextcloud";
120
+ return `pane-list-size-${appName}`;
121
+ });
122
+ const paneDefaults = computed(() => ({
123
+ list: {
124
+ size: __props.listSize,
125
+ min: __props.listMinWidth,
126
+ max: __props.listMaxWidth
127
+ },
128
+ // set the inverse values of the details column
129
+ // based on the provided (or default) values of the list column
130
+ details: {
131
+ size: 100 - __props.listSize,
132
+ min: 100 - __props.listMaxWidth,
133
+ max: 100 - __props.listMinWidth
185
134
  }
186
- },
187
- detailsPaneSize() {
188
- if (this.listPaneSize) {
189
- return 100 - this.listPaneSize;
135
+ }));
136
+ const detailsPaneSize = computed(() => {
137
+ if (listPaneSize.value) {
138
+ return 100 - listPaneSize.value;
190
139
  }
191
- return this.paneDefaults.details.size;
192
- },
193
- paneDefaults() {
194
- return {
195
- list: {
196
- size: this.listSize,
197
- min: this.listMinWidth,
198
- max: this.listMaxWidth
199
- },
200
- // set the inverse values of the details column
201
- // based on the provided (or default) values of the list column
202
- details: {
203
- size: 100 - this.listSize,
204
- min: 100 - this.listMaxWidth,
205
- max: 100 - this.listMinWidth
206
- }
207
- };
208
- },
209
- realPageTitle() {
140
+ return paneDefaults.value.details.size;
141
+ });
142
+ const realPageTitle = computed(() => {
210
143
  const entries = /* @__PURE__ */ new Set();
211
- if (this.pageTitle) {
212
- for (const part of this.pageTitle.split(" - ")) {
144
+ if (__props.pageTitle) {
145
+ for (const part of __props.pageTitle.split(" - ")) {
213
146
  entries.add(part);
214
147
  }
215
- } else if (this.pageHeading) {
216
- for (const part of this.pageHeading.split(" - ")) {
148
+ } else if (__props.pageHeading) {
149
+ for (const part of __props.pageHeading.split(" - ")) {
217
150
  entries.add(part);
218
151
  }
219
152
  if (entries.size > 0) {
220
- entries.add(this.localizedAppName);
153
+ entries.add(localizedAppName);
221
154
  }
222
155
  } else {
223
156
  return null;
224
157
  }
225
158
  entries.add(instanceName);
226
159
  return [...entries.values()].join(" - ");
227
- }
228
- },
229
- watch: {
230
- realPageTitle: {
231
- immediate: true,
232
- handler() {
233
- if (this.realPageTitle !== null) {
234
- document.title = this.realPageTitle;
235
- }
236
- }
237
- },
238
- paneConfigKey: {
239
- immediate: true,
240
- handler() {
241
- this.restorePaneConfig();
160
+ });
161
+ watch(realPageTitle, () => {
162
+ if (realPageTitle.value !== null) {
163
+ document.title = realPageTitle.value;
242
164
  }
165
+ }, { immediate: true });
166
+ watch(() => __props.paneConfigKey, restorePaneConfig, { immediate: true });
167
+ onMounted(restorePaneConfig);
168
+ function handlePaneResize(event) {
169
+ const size = Math.trunc(event.panes[0].size);
170
+ browserStorage.setItem(paneConfigID.value, JSON.stringify(size));
171
+ listPaneSize.value = size;
172
+ emit$1("resizeList", { size });
173
+ logger.debug("[NcAppContent] pane config", { listPaneSize: size });
243
174
  }
244
- },
245
- mounted() {
246
- if (!this.disableSwipe) {
247
- this.swiping = useSwipe(this.$el, {
248
- onSwipeEnd: this.handleSwipe
249
- });
250
- }
251
- this.restorePaneConfig();
252
- },
253
- methods: {
254
- /**
255
- * handle the swipe event
256
- *
257
- * @param {TouchEvent} e The touch event
258
- * @param {import('@vueuse/core').SwipeDirection} direction The swipe direction of the event
259
- */
260
- handleSwipe(e, direction) {
261
- const minSwipeX = 70;
262
- const touchZone = 300;
263
- if (Math.abs(this.swiping.lengthX) > minSwipeX) {
264
- if (this.swiping.coordsStart.x < touchZone / 2 && direction === "right") {
265
- emit("toggle-navigation", {
266
- open: true
267
- });
268
- } else if (this.swiping.coordsStart.x < touchZone * 1.5 && direction === "left") {
269
- emit("toggle-navigation", {
270
- open: false
271
- });
272
- }
175
+ function restorePaneConfig() {
176
+ const size = parseInt(browserStorage.getItem(paneConfigID.value) ?? "", 10);
177
+ if (!isNaN(size) && size !== listPaneSize.value) {
178
+ logger.debug("[NcAppContent] pane config", { listPaneSize: size });
179
+ listPaneSize.value = size;
273
180
  }
274
- },
275
- handlePaneResize(event) {
276
- const listPaneSize = parseInt(event.panes[0].size, 10);
277
- browserStorage.setItem(this.paneConfigID, JSON.stringify(listPaneSize));
278
- this.listPaneSize = listPaneSize;
279
- this.$emit("resizeList", { size: listPaneSize });
280
- logger.debug("[NcAppContent] pane config", { listPaneSize });
281
- },
282
- // browserStorage is not reactive, we need to update this manually
283
- restorePaneConfig() {
284
- const listPaneSize = parseInt(browserStorage.getItem(this.paneConfigID), 10);
285
- if (!isNaN(listPaneSize) && listPaneSize !== this.listPaneSize) {
286
- logger.debug("[NcAppContent] pane config", { listPaneSize });
287
- this.listPaneSize = listPaneSize;
288
- return listPaneSize;
289
- }
290
- },
291
- /**
292
- * The user clicked the back arrow from the details view
293
- */
294
- hideDetails() {
295
- this.$emit("update:showDetails", false);
296
181
  }
297
- }
298
- };
299
- const _hoisted_1 = {
300
- key: 0,
301
- class: "hidden-visually"
302
- };
303
- const _hoisted_2 = { class: "app-content-wrapper__list" };
304
- const _hoisted_3 = {
305
- key: 1,
306
- class: "app-content-wrapper"
307
- };
308
- function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
309
- const _component_NcAppContentDetailsToggle = resolveComponent("NcAppContentDetailsToggle");
310
- const _component_Pane = resolveComponent("Pane");
311
- const _component_Splitpanes = resolveComponent("Splitpanes");
312
- return openBlock(), createElementBlock("main", {
313
- id: "app-content-vue",
314
- class: normalizeClass(["app-content no-snapper", { "app-content--has-list": !!_ctx.$slots.list }])
315
- }, [
316
- $props.pageHeading ? (openBlock(), createElementBlock("h1", _hoisted_1, toDisplayString($props.pageHeading), 1)) : createCommentVNode("", true),
317
- !!_ctx.$slots.list ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
318
- $setup.isMobile || $props.layout === "no-split" ? (openBlock(), createElementBlock("div", {
319
- key: 0,
320
- class: normalizeClass(["app-content-wrapper app-content-wrapper--no-split", {
321
- "app-content-wrapper--show-details": $props.showDetails,
322
- "app-content-wrapper--show-list": !$props.showDetails,
323
- "app-content-wrapper--mobile": $setup.isMobile
324
- }])
182
+ return (_ctx, _cache) => {
183
+ return openBlock(), createElementBlock("main", {
184
+ id: "app-content-vue",
185
+ class: normalizeClass(["app-content no-snapper", { "app-content--has-list": !!_ctx.$slots.list }])
325
186
  }, [
326
- $props.showDetails ? (openBlock(), createBlock(_component_NcAppContentDetailsToggle, {
327
- key: 0,
328
- onClick: withModifiers($options.hideDetails, ["stop", "prevent"])
329
- }, null, 8, ["onClick"])) : createCommentVNode("", true),
330
- withDirectives(createElementVNode("div", _hoisted_2, [
331
- renderSlot(_ctx.$slots, "list", {}, void 0, true)
332
- ], 512), [
333
- [vShow, !$props.showDetails]
334
- ]),
335
- $props.showDetails ? renderSlot(_ctx.$slots, "default", {}, void 0, true, 1) : createCommentVNode("", true)
336
- ], 2)) : $props.layout === "vertical-split" || $props.layout === "horizontal-split" ? (openBlock(), createElementBlock("div", _hoisted_3, [
337
- createVNode(_component_Splitpanes, {
338
- horizontal: $props.layout === "horizontal-split",
339
- class: normalizeClass(["default-theme", {
340
- "splitpanes--horizontal": $props.layout === "horizontal-split",
341
- "splitpanes--vertical": $props.layout === "vertical-split"
342
- }]),
343
- rtl: $setup.isRtl,
344
- onResized: $options.handlePaneResize
345
- }, {
346
- default: withCtx(() => [
347
- createVNode(_component_Pane, {
348
- class: "splitpanes__pane-list",
349
- size: $data.listPaneSize || $options.paneDefaults.list.size,
350
- minSize: $options.paneDefaults.list.min,
351
- maxSize: $options.paneDefaults.list.max
352
- }, {
353
- default: withCtx(() => [
354
- renderSlot(_ctx.$slots, "list", {}, void 0, true)
355
- ]),
356
- _: 3
357
- }, 8, ["size", "minSize", "maxSize"]),
358
- createVNode(_component_Pane, {
359
- class: "splitpanes__pane-details",
360
- size: $options.detailsPaneSize,
361
- minSize: $options.paneDefaults.details.min,
362
- maxSize: $options.paneDefaults.details.max
187
+ __props.pageHeading ? (openBlock(), createElementBlock("h1", _hoisted_1, toDisplayString(__props.pageHeading), 1)) : createCommentVNode("", true),
188
+ !!_ctx.$slots.list ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
189
+ unref(isMobile) || __props.layout === "no-split" ? (openBlock(), createElementBlock("div", {
190
+ key: 0,
191
+ class: normalizeClass(["app-content-wrapper app-content-wrapper--no-split", {
192
+ "app-content-wrapper--show-details": showDetails.value,
193
+ "app-content-wrapper--show-list": !showDetails.value,
194
+ "app-content-wrapper--mobile": unref(isMobile)
195
+ }])
196
+ }, [
197
+ showDetails.value ? (openBlock(), createBlock(NcAppContentDetailsToggle, {
198
+ key: 0,
199
+ onClick: _cache[0] || (_cache[0] = withModifiers(($event) => showDetails.value = false, ["stop", "prevent"]))
200
+ })) : createCommentVNode("", true),
201
+ withDirectives(createElementVNode("div", _hoisted_2, [
202
+ renderSlot(_ctx.$slots, "list", {}, void 0, true)
203
+ ], 512), [
204
+ [vShow, !showDetails.value]
205
+ ]),
206
+ showDetails.value ? renderSlot(_ctx.$slots, "default", {}, void 0, true, 1) : createCommentVNode("", true)
207
+ ], 2)) : __props.layout === "vertical-split" || __props.layout === "horizontal-split" ? (openBlock(), createElementBlock("div", _hoisted_3, [
208
+ createVNode(unref(Splitpanes), {
209
+ horizontal: __props.layout === "horizontal-split",
210
+ class: normalizeClass(["default-theme", {
211
+ "splitpanes--horizontal": __props.layout === "horizontal-split",
212
+ "splitpanes--vertical": __props.layout === "vertical-split"
213
+ }]),
214
+ rtl: unref(isRtl),
215
+ onResized: handlePaneResize
363
216
  }, {
364
217
  default: withCtx(() => [
365
- renderSlot(_ctx.$slots, "default", {}, void 0, true)
218
+ createVNode(unref(Pane), {
219
+ class: "splitpanes__pane-list",
220
+ size: listPaneSize.value || paneDefaults.value.list.size,
221
+ minSize: paneDefaults.value.list.min,
222
+ maxSize: paneDefaults.value.list.max
223
+ }, {
224
+ default: withCtx(() => [
225
+ renderSlot(_ctx.$slots, "list", {}, void 0, true)
226
+ ]),
227
+ _: 3
228
+ }, 8, ["size", "minSize", "maxSize"]),
229
+ createVNode(unref(Pane), {
230
+ class: "splitpanes__pane-details",
231
+ size: detailsPaneSize.value,
232
+ minSize: paneDefaults.value.details.min,
233
+ maxSize: paneDefaults.value.details.max
234
+ }, {
235
+ default: withCtx(() => [
236
+ renderSlot(_ctx.$slots, "default", {}, void 0, true)
237
+ ]),
238
+ _: 3
239
+ }, 8, ["size", "minSize", "maxSize"])
366
240
  ]),
367
241
  _: 3
368
- }, 8, ["size", "minSize", "maxSize"])
369
- ]),
370
- _: 3
371
- }, 8, ["horizontal", "class", "rtl", "onResized"])
372
- ])) : createCommentVNode("", true)
373
- ], 64)) : createCommentVNode("", true),
374
- !_ctx.$slots.list ? renderSlot(_ctx.$slots, "default", {}, void 0, true, 2) : createCommentVNode("", true)
375
- ], 2);
376
- }
377
- const NcAppContent = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-51427d61"]]);
242
+ }, 8, ["horizontal", "class", "rtl"])
243
+ ])) : createCommentVNode("", true)
244
+ ], 64)) : createCommentVNode("", true),
245
+ !_ctx.$slots.list ? renderSlot(_ctx.$slots, "default", {}, void 0, true, 2) : createCommentVNode("", true)
246
+ ], 2);
247
+ };
248
+ }
249
+ });
250
+ const NcAppContent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-5de09463"]]);
378
251
  export {
379
252
  NcAppContent as N
380
253
  };
@@ -1 +1 @@
1
- {"version":3,"file":"NcAppContent.mjs","sources":["../../src/components/NcAppContent/NcAppContentDetailsToggle.vue","../../src/components/NcAppContent/NcAppContent.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n\n<script setup lang=\"ts\">\nimport { mdiArrowRight } from '@mdi/js'\nimport { emit } from '@nextcloud/event-bus'\nimport { onBeforeUnmount, onMounted, watch } from 'vue'\nimport { useIsMobile } from '../../composables/useIsMobile/index.js'\nimport { t } from '../../l10n.ts'\nimport NcButton from '../NcButton/index.ts'\nimport NcIconSvgWrapper from '../NcIconSvgWrapper/index.ts'\n\nconst isMobile = useIsMobile()\nwatch(isMobile, toggleAppNavigationButton)\n\nonMounted(() => {\n\ttoggleAppNavigationButton(isMobile.value)\n})\n\nonBeforeUnmount(() => {\n\tif (isMobile.value) {\n\t\ttoggleAppNavigationButton(false)\n\t}\n})\n\n/**\n * Toggle the app navigation button and hide it if needed.\n *\n * @param hide - if true the navigation toggle is visually hidden\n */\nfunction toggleAppNavigationButton(hide: boolean = true) {\n\tconst appNavigationToggle = document.querySelector<HTMLElement>('.app-navigation .app-navigation-toggle')\n\tif (appNavigationToggle) {\n\t\tappNavigationToggle.style.display = hide ? 'none' : ''\n\n\t\t// If we hide the NavigationToggle, we need to make sure the Navigation is also closed\n\t\tif (hide === true) {\n\t\t\temit('toggle-navigation', { open: false })\n\t\t}\n\t}\n}\n</script>\n\n<template>\n\t<NcButton\n\t\t:aria-label=\"t('Go back to the list')\"\n\t\tclass=\"app-details-toggle\"\n\t\t:class=\"{ 'app-details-toggle--mobile': isMobile }\"\n\t\t:title=\"t('Go back to the list')\"\n\t\tvariant=\"tertiary\">\n\t\t<template #icon>\n\t\t\t<NcIconSvgWrapper directional :path=\"mdiArrowRight\" />\n\t\t</template>\n\t</NcButton>\n</template>\n\n<style lang=\"scss\" scoped>\n.app-details-toggle {\n\tposition: sticky;\n\twidth: var(--default-clickable-area);\n\theight: var(--default-clickable-area);\n\tpadding: $icon-margin;\n\tcursor: pointer;\n\topacity: .6;\n\ttransform: rotate(180deg);\n\tbackground-color: var(--color-main-background);\n\tz-index: 2000;\n\n\ttop: var(--app-navigation-padding);\n\t// Navigation Toggle button width + 2 paddings around\n\tinset-inline-start: calc(var(--default-clickable-area) + var(--app-navigation-padding) * 2);\n\t&--mobile {\n\t\t// There is no NavigationToggle button\n\t\tinset-inline-start: var(--app-navigation-padding);\n\t}\n\n\t&:active,\n\t&:hover,\n\t&:focus {\n\t\topacity: 1;\n\t}\n}\n\n</style>\n","<!--\n - SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n\n<docs>\n### General description\n\nThis components provides a wrapper around the main app's content.\n\nSingle-column layouts can just use the default slot. A resizable column\ncan be added by providing content to the named slot `list`.\n\n### CSS variables\nIn the css section some css variables are declared and will be available for\nall the children of the NcAppContent component\n\n### Examples\n\n#### Usage: Single-column content\n```vue\n<template>\n\t<NcAppContent>\n\t\t<h2>Single-column main content</h2>\n\t</NcAppContent>\n</template>\n```\n\n#### Usage: Two resizable columns\n```vue\n<template>\n\t<NcAppContent>\n\t\t<template #list>\n\t\t\t<div>Resizable list content</div>\n\t\t</template>\n\n\t\t<div>Main content</div>\n\t</NcAppContent>\n</template>\n```\n\n#### Overriding Defaults\nThe default, min and max sizes (in percent) of the resizable list column can be overridden.\nThe list size must be between the min and the max width value.\n\n```\n<NcAppContent\n\t:list-size=\"35\"\n\t:list-min-width=\"20\"\n\t:list-max-width=\"45\"\n>...</NcAppContent>\n```\n\n#### Usage: Custom document title\nFor accessibility reasons every document should have a `h1` heading,\nthis is visually hidden, but required for a semantically correct document.\nYou can use your app name or current view for the heading.\n\nAdditionally you can set a custom document title, e.g. to show the current status.\n\n```vue\n<template>\n\t<NcAppContent :pageHeading=\"heading ? 'Heading' : undefined\" :pageTitle=\"title ? 'Title' : undefined\" >\n\t\t<NcCheckboxRadioSwitch type=\"switch\" :checked.sync=\"title\">\n\t\t\tToggle title\n\t\t</NcCheckboxRadioSwitch>\n\t\t<NcCheckboxRadioSwitch type=\"switch\" :checked.sync=\"heading\">\n\t\t\tToggle Heading\n\t\t</NcCheckboxRadioSwitch>\n\t\t<NcButton @click=\"reset\">Reset</NcButton>\n\t</NcAppContent>\n</template>\n\n<script>\nexport default {\n\tdata() {\n\t\treturn {\n\t\t\theading: false,\n\t\t\ttitle: false,\n\t\t}\n\t},\n\tmethods: {\n\t\treset() {\n\t\t\tthis.heading = false\n\t\t\tthis.title = false\n\t\t\tdocument.title = ''\n\t\t},\n\t},\n}\n</script>\n```\n</docs>\n\n<template>\n\t<main id=\"app-content-vue\" class=\"app-content no-snapper\" :class=\"{ 'app-content--has-list': !!$slots.list }\">\n\t\t<h1 v-if=\"pageHeading\" class=\"hidden-visually\">\n\t\t\t{{ pageHeading }}\n\t\t</h1>\n\n\t\t<template v-if=\"!!$slots.list\">\n\t\t\t<!-- Mobile view does not allow resizeable panes -->\n\t\t\t<div\n\t\t\t\tv-if=\"isMobile || layout === 'no-split'\"\n\t\t\t\tclass=\"app-content-wrapper app-content-wrapper--no-split\"\n\t\t\t\t:class=\"{\n\t\t\t\t\t'app-content-wrapper--show-details': showDetails,\n\t\t\t\t\t'app-content-wrapper--show-list': !showDetails,\n\t\t\t\t\t'app-content-wrapper--mobile': isMobile,\n\t\t\t\t}\">\n\t\t\t\t<NcAppContentDetailsToggle v-if=\"showDetails\" @click.stop.prevent=\"hideDetails\" />\n\n\t\t\t\t<div v-show=\"!showDetails\" class=\"app-content-wrapper__list\">\n\t\t\t\t\t<slot name=\"list\" />\n\t\t\t\t</div>\n\t\t\t\t<slot v-if=\"showDetails\" />\n\t\t\t</div>\n\t\t\t<div v-else-if=\"layout === 'vertical-split' || layout === 'horizontal-split'\" class=\"app-content-wrapper\">\n\t\t\t\t<Splitpanes\n\t\t\t\t\t:horizontal=\"layout === 'horizontal-split'\"\n\t\t\t\t\tclass=\"default-theme\"\n\t\t\t\t\t:class=\"{\n\t\t\t\t\t\t'splitpanes--horizontal': layout === 'horizontal-split',\n\t\t\t\t\t\t'splitpanes--vertical': layout === 'vertical-split',\n\t\t\t\t\t}\"\n\t\t\t\t\t:rtl=\"isRtl\"\n\t\t\t\t\t@resized=\"handlePaneResize\">\n\t\t\t\t\t<Pane\n\t\t\t\t\t\tclass=\"splitpanes__pane-list\"\n\t\t\t\t\t\t:size=\"listPaneSize || paneDefaults.list.size\"\n\t\t\t\t\t\t:minSize=\"paneDefaults.list.min\"\n\t\t\t\t\t\t:maxSize=\"paneDefaults.list.max\">\n\t\t\t\t\t\t<!-- @slot Provide a list to the app content -->\n\t\t\t\t\t\t<slot name=\"list\" />\n\t\t\t\t\t</Pane>\n\n\t\t\t\t\t<Pane\n\t\t\t\t\t\tclass=\"splitpanes__pane-details\"\n\t\t\t\t\t\t:size=\"detailsPaneSize\"\n\t\t\t\t\t\t:minSize=\"paneDefaults.details.min\"\n\t\t\t\t\t\t:maxSize=\"paneDefaults.details.max\">\n\t\t\t\t\t\t<!-- @slot Provide the main content to the app content -->\n\t\t\t\t\t\t<slot />\n\t\t\t\t\t</Pane>\n\t\t\t\t</Splitpanes>\n\t\t\t</div>\n\t\t</template>\n\t\t<!-- @slot Provide the main content to the app content -->\n\t\t<slot v-if=\"!$slots.list\" />\n\t</main>\n</template>\n\n<script>\nimport { getBuilder } from '@nextcloud/browser-storage'\nimport { getCapabilities } from '@nextcloud/capabilities'\nimport { emit } from '@nextcloud/event-bus'\nimport { useSwipe } from '@vueuse/core'\nimport { Pane, Splitpanes } from 'splitpanes'\nimport NcAppContentDetailsToggle from './NcAppContentDetailsToggle.vue'\nimport { useIsMobile } from '../../composables/useIsMobile/index.js'\nimport { useAppName, useLocalizedAppName } from '../../utils/appName.ts'\nimport { logger } from '../../utils/logger.ts'\nimport { isRtl } from '../../utils/rtl.ts'\n\nimport 'splitpanes/dist/splitpanes.css'\n\nconst browserStorage = getBuilder('nextcloud').persist().build()\nconst instanceName = getCapabilities().theming?.name ?? 'Nextcloud'\n\n/**\n * App content container to be used for the main content of your app\n *\n */\nexport default {\n\tname: 'NcAppContent',\n\n\tcomponents: {\n\t\tNcAppContentDetailsToggle,\n\t\tPane,\n\t\tSplitpanes,\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * Allows to disable the control by swipe of the app navigation open state.\n\t\t */\n\t\tdisableSwipe: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Allows you to set the default width of the resizable list in % on vertical-split\n\t\t * or respectively the default height on horizontal-split.\n\t\t *\n\t\t * Must be between `listMinWidth` and `listMaxWidth`.\n\t\t */\n\t\tlistSize: {\n\t\t\ttype: Number,\n\t\t\tdefault: 20,\n\t\t},\n\n\t\t/**\n\t\t * Allows you to set the minimum width of the list column in % on vertical-split\n\t\t * or respectively the minimum height on horizontal-split.\n\t\t */\n\t\tlistMinWidth: {\n\t\t\ttype: Number,\n\t\t\tdefault: 15,\n\t\t},\n\n\t\t/**\n\t\t * Allows you to set the maximum width of the list column in % on vertical-split\n\t\t * or respectively the maximum height on horizontal-split.\n\t\t */\n\t\tlistMaxWidth: {\n\t\t\ttype: Number,\n\t\t\tdefault: 40,\n\t\t},\n\n\t\t/**\n\t\t * Specify the config key for the pane config sizes\n\t\t * Default is the global var appName if you use the webpack-vue-config\n\t\t */\n\t\tpaneConfigKey: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * When in mobile view, only the list or the details are shown.\n\t\t *\n\t\t * If you provide a list, you need to provide a variable\n\t\t * that will be set to true by the user when an element of\n\t\t * the list gets selected. The details will then show a back\n\t\t * arrow to return to the list that will update this prop to false.\n\t\t */\n\t\tshowDetails: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Content layout used when there is a list together with content:\n\t\t * - `vertical-split` - a 2-column layout with list and default content separated vertically\n\t\t * - `no-split` - a single column layout; List is shown when `showDetails` is `false`, otherwise the default slot content is shown with a back button to return to the list.\n\t\t * - 'horizontal-split' - a 2-column layout with list and default content separated horizontally\n\t\t * On mobile screen `no-split` layout is forced.\n\t\t */\n\t\tlayout: {\n\t\t\ttype: String,\n\t\t\tdefault: 'vertical-split',\n\t\t\tvalidator(value) {\n\t\t\t\treturn ['no-split', 'vertical-split', 'horizontal-split'].includes(value)\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Specify the `<h1>` page heading\n\t\t */\n\t\tpageHeading: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Allow setting the page's `<title>`\n\t\t *\n\t\t * If a page heading is set it defaults to `{pageHeading} - {appName} - {instanceName}` e.g. `Favorites - Files - MyPersonalCloud`.\n\t\t * When the page heading and the app name is the same only one is used, e.g. `Files - Files - MyPersonalCloud` is shown as `Files - MyPersonalCloud`.\n\t\t * When setting the prop then the following format will be used: `{pageTitle} - {instanceName}`\n\t\t */\n\t\tpageTitle: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: [\n\t\t'update:showDetails',\n\t\t'resizeList',\n\t],\n\n\tsetup() {\n\t\treturn {\n\t\t\tappName: useAppName(),\n\t\t\tlocalizedAppName: useLocalizedAppName(),\n\t\t\tisMobile: useIsMobile(),\n\t\t\tisRtl,\n\t\t}\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tcontentHeight: 0,\n\t\t\tswiping: {},\n\t\t\tlistPaneSize: this.restorePaneConfig(),\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tpaneConfigID() {\n\t\t\t// If provided, let's use it\n\t\t\tif (this.paneConfigKey !== '') {\n\t\t\t\treturn `pane-list-size-${this.paneConfigKey}`\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\t// Using the webpack-vue-config, appName is a global variable\n\t\t\t\t// This will throw a ReferenceError when the global variable is missing\n\t\t\t\t// In that case either you provide paneConfigKey or else it fallback\n\t\t\t\t// to a global storage key\n\t\t\t\treturn `pane-list-size-${this.appName}`\n\t\t\t} catch {\n\t\t\t\tlogger.info('[NcAppContent]: falling back to global nextcloud pane config')\n\t\t\t\treturn 'pane-list-size-nextcloud'\n\t\t\t}\n\t\t},\n\n\t\tdetailsPaneSize() {\n\t\t\tif (this.listPaneSize) {\n\t\t\t\treturn 100 - this.listPaneSize\n\t\t\t}\n\t\t\treturn this.paneDefaults.details.size\n\t\t},\n\n\t\tpaneDefaults() {\n\t\t\treturn {\n\t\t\t\tlist: {\n\t\t\t\t\tsize: this.listSize,\n\t\t\t\t\tmin: this.listMinWidth,\n\t\t\t\t\tmax: this.listMaxWidth,\n\t\t\t\t},\n\n\t\t\t\t// set the inverse values of the details column\n\t\t\t\t// based on the provided (or default) values of the list column\n\t\t\t\tdetails: {\n\t\t\t\t\tsize: 100 - this.listSize,\n\t\t\t\t\tmin: 100 - this.listMaxWidth,\n\t\t\t\t\tmax: 100 - this.listMinWidth,\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\n\t\trealPageTitle() {\n\t\t\tconst entries = new Set()\n\t\t\tif (this.pageTitle) {\n\t\t\t\t// when page title is set we only use that\n\t\t\t\t// we still split to remove duplicated instanceName\n\t\t\t\tfor (const part of this.pageTitle.split(' - ')) {\n\t\t\t\t\tentries.add(part)\n\t\t\t\t}\n\t\t\t} else if (this.pageHeading) {\n\t\t\t\t// when the page heading is provided but not the title\n\t\t\t\t// then we split to remove duplicates\n\t\t\t\t// but also add the localized app name\n\t\t\t\tfor (const part of this.pageHeading.split(' - ')) {\n\t\t\t\t\tentries.add(part)\n\t\t\t\t}\n\n\t\t\t\tif (entries.size > 0) {\n\t\t\t\t\tentries.add(this.localizedAppName)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tentries.add(instanceName)\n\t\t\treturn [...entries.values()].join(' - ')\n\t\t},\n\t},\n\n\twatch: {\n\t\trealPageTitle: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tif (this.realPageTitle !== null) {\n\t\t\t\t\tdocument.title = this.realPageTitle\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\n\t\tpaneConfigKey: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tthis.restorePaneConfig()\n\t\t\t},\n\t\t},\n\t},\n\n\tmounted() {\n\t\tif (!this.disableSwipe) {\n\t\t\tthis.swiping = useSwipe(this.$el, {\n\t\t\t\tonSwipeEnd: this.handleSwipe,\n\t\t\t})\n\t\t}\n\n\t\tthis.restorePaneConfig()\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * handle the swipe event\n\t\t *\n\t\t * @param {TouchEvent} e The touch event\n\t\t * @param {import('@vueuse/core').SwipeDirection} direction The swipe direction of the event\n\t\t */\n\t\thandleSwipe(e, direction) {\n\t\t\tconst minSwipeX = 70\n\t\t\tconst touchZone = 300\n\t\t\tif (Math.abs(this.swiping.lengthX) > minSwipeX) {\n\t\t\t\tif (this.swiping.coordsStart.x < (touchZone / 2) && direction === 'right') {\n\t\t\t\t\temit('toggle-navigation', {\n\t\t\t\t\t\topen: true,\n\t\t\t\t\t})\n\t\t\t\t} else if (this.swiping.coordsStart.x < touchZone * 1.5 && direction === 'left') {\n\t\t\t\t\temit('toggle-navigation', {\n\t\t\t\t\t\topen: false,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\thandlePaneResize(event) {\n\t\t\tconst listPaneSize = parseInt(event.panes[0].size, 10)\n\t\t\tbrowserStorage.setItem(this.paneConfigID, JSON.stringify(listPaneSize))\n\t\t\tthis.listPaneSize = listPaneSize\n\t\t\t/**\n\t\t\t * Emitted when the list pane is resized by the user\n\t\t\t */\n\t\t\tthis.$emit('resizeList', { size: listPaneSize })\n\t\t\tlogger.debug('[NcAppContent] pane config', { listPaneSize })\n\t\t},\n\n\t\t// browserStorage is not reactive, we need to update this manually\n\t\trestorePaneConfig() {\n\t\t\tconst listPaneSize = parseInt(browserStorage.getItem(this.paneConfigID), 10)\n\t\t\tif (!isNaN(listPaneSize) && listPaneSize !== this.listPaneSize) {\n\t\t\t\tlogger.debug('[NcAppContent] pane config', { listPaneSize })\n\t\t\t\tthis.listPaneSize = listPaneSize\n\t\t\t\treturn listPaneSize\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The user clicked the back arrow from the details view\n\t\t */\n\t\thideDetails() {\n\t\t\tthis.$emit('update:showDetails', false)\n\t\t},\n\t},\n}\n</script>\n\n<style lang=\"scss\" scoped>\n\n.app-content {\n\tposition: initial;\n\tz-index: 1000;\n\tflex-basis: 100vw;\n\theight: 100%;\n\t// Overriding server styles TODO: cleanup!\n\tmargin: 0 !important;\n\tbackground-color: var(--color-main-background);\n\tmin-width: 0;\n\n\t&:not(.app-content--has-list) {\n\t\toverflow: auto;\n\t}\n}\n\n.app-content-wrapper {\n\tposition: relative;\n\twidth: 100%;\n\theight: 100%;\n}\n\n// Mobile list/details handling\n.app-content-wrapper--no-split {\n\t&.app-content-wrapper--show-list :deep() {\n\t\t.app-content-list {\n\t\t\tdisplay: flex;\n\t\t}\n\t\t.app-content-details {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n\t&.app-content-wrapper--show-details :deep() {\n\t\t.app-content-list {\n\t\t\tdisplay: none;\n\t\t}\n\t\t.app-content-details {\n\t\t\tdisplay: block;\n\t\t}\n\t}\n}\n\n:deep(.splitpanes.default-theme) {\n\t.app-content-list {\n\t\tmax-width: none;\n\t\t/* Thin scrollbar is hard to catch on resizable columns */\n\t\tscrollbar-width: auto;\n\t}\n\n\t.splitpanes__pane {\n\t\tbackground-color: transparent;\n\t\ttransition: none;\n\n\t\t&-list {\n\t\t\tmin-width: 300px;\n\t\t\tposition: sticky;\n\n\t\t\t@media only screen and (width < $breakpoint-mobile) {\n\t\t\t\tdisplay: none;\n\t\t\t}\n\t\t}\n\n\t\t&-details {\n\t\t\toverflow-y: auto;\n\n\t\t\t@media only screen and (width < $breakpoint-mobile) {\n\t\t\t\tmin-width: 100%;\n\t\t\t}\n\t\t}\n\t}\n\n\t.splitpanes__splitter {\n\t\tbackground-color: var(--color-main-background);\n\t\t&::before, &::after {\n\t\t\tbackground-color: var(--color-border);\n\t\t}\n\t}\n\n\t&.splitpanes--vertical .splitpanes__splitter {\n\t\tborder-inline-start: 1px solid var(--color-border);\n\t}\n\n\t&.splitpanes--horizontal .splitpanes__splitter {\n\t\tborder-top: 1px solid var(--color-border);\n\t}\n}\n\n.app-content-wrapper--show-list {\n\t:deep(.app-content-list) {\n\t\tmax-width: none;\n\t}\n}\n\n.app-content-wrapper__list {\n\theight: 100%;\n}\n</style>\n"],"names":["_createBlock","_unref","_normalizeClass","_createVNode","_createElementBlock","_toDisplayString","_Fragment","_withDirectives","_createElementVNode","_renderSlot","_openBlock"],"mappings":";;;;;;;;;;;;;;;;;;;;AAcA,UAAM,WAAW,YAAA;AACjB,UAAM,UAAU,yBAAyB;AAEzC,cAAU,MAAM;AACf,gCAA0B,SAAS,KAAK;AAAA,IACzC,CAAC;AAED,oBAAgB,MAAM;AACrB,UAAI,SAAS,OAAO;AACnB,kCAA0B,KAAK;AAAA,MAChC;AAAA,IACD,CAAC;AAOD,aAAS,0BAA0B,OAAgB,MAAM;AACxD,YAAM,sBAAsB,SAAS,cAA2B,wCAAwC;AACxG,UAAI,qBAAqB;AACxB,4BAAoB,MAAM,UAAU,OAAO,SAAS;AAGpD,YAAI,SAAS,MAAM;AAClB,eAAK,qBAAqB,EAAE,MAAM,MAAA,CAAO;AAAA,QAC1C;AAAA,MACD;AAAA,IACD;;0BAICA,YASWC,MAAA,QAAA,GAAA;AAAA,QART,cAAYA,MAAA,CAAA,EAAC,qBAAA;AAAA,QACd,OAAKC,eAAA,CAAC,sBAAoB,EAAA,8BACcD,MAAA,QAAA,EAAA,CAAQ,CAAA;AAAA,QAC/C,OAAOA,MAAA,CAAA,EAAC,qBAAA;AAAA,QACT,SAAQ;AAAA,MAAA;QACG,cACV,MAAsD;AAAA,UAAtDE,YAAsDF,MAAA,gBAAA,GAAA;AAAA,YAApC,aAAA;AAAA,YAAa,MAAMA,MAAA,aAAA;AAAA,UAAA;;;;;;;;ACgHxC,MAAM,iBAAiB,WAAW,WAAW,EAAE,QAAO,EAAG,MAAK;AAC9D,MAAM,eAAe,gBAAe,EAAG,SAAS,QAAQ;AAMxD,MAAK,YAAU;AAAA,EACd,MAAM;AAAA,EAEN,YAAY;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA;EAGD,OAAO;AAAA;AAAA;AAAA;AAAA,IAIN,cAAc;AAAA,MACb,MAAM;AAAA,MACN,SAAS;AAAA;;;;;;;IASV,UAAU;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA;;;;;IAOV,cAAc;AAAA,MACb,MAAM;AAAA,MACN,SAAS;AAAA;;;;;IAOV,cAAc;AAAA,MACb,MAAM;AAAA,MACN,SAAS;AAAA;;;;;IAOV,eAAe;AAAA,MACd,MAAM;AAAA,MACN,SAAS;AAAA;;;;;;;;;IAWV,aAAa;AAAA,MACZ,MAAM;AAAA,MACN,SAAS;AAAA;;;;;;;;IAUV,QAAQ;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU,OAAO;AAChB,eAAO,CAAC,YAAY,kBAAkB,kBAAkB,EAAE,SAAS,KAAK;AAAA,MACzE;AAAA;;;;IAMD,aAAa;AAAA,MACZ,MAAM;AAAA,MACN,SAAS;AAAA;;;;;;;;IAUV,WAAW;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA;;EAIX,OAAO;AAAA,IACN;AAAA,IACA;AAAA;EAGD,QAAQ;AACP,WAAO;AAAA,MACN,SAAS,WAAU;AAAA,MACnB,kBAAkB,oBAAmB;AAAA,MACrC,UAAU,YAAW;AAAA,MACrB;AAAA,IACD;AAAA,EACD;AAAA,EAEA,OAAO;AACN,WAAO;AAAA,MACN,eAAe;AAAA,MACf,SAAS,CAAA;AAAA,MACT,cAAc,KAAK,kBAAiB;AAAA,IACrC;AAAA,EACD;AAAA,EAEA,UAAU;AAAA,IACT,eAAe;AAEd,UAAI,KAAK,kBAAkB,IAAI;AAC9B,eAAO,kBAAkB,KAAK,aAAa;AAAA,MAC5C;AAEA,UAAI;AAKH,eAAO,kBAAkB,KAAK,OAAO;AAAA,MACtC,QAAQ;AACP,eAAO,KAAK,8DAA8D;AAC1E,eAAO;AAAA,MACR;AAAA,IACD;AAAA,IAEA,kBAAkB;AACjB,UAAI,KAAK,cAAc;AACtB,eAAO,MAAM,KAAK;AAAA,MACnB;AACA,aAAO,KAAK,aAAa,QAAQ;AAAA,IAClC;AAAA,IAEA,eAAe;AACd,aAAO;AAAA,QACN,MAAM;AAAA,UACL,MAAM,KAAK;AAAA,UACX,KAAK,KAAK;AAAA,UACV,KAAK,KAAK;AAAA;;;QAKX,SAAS;AAAA,UACR,MAAM,MAAM,KAAK;AAAA,UACjB,KAAK,MAAM,KAAK;AAAA,UAChB,KAAK,MAAM,KAAK;AAAA;MAElB;AAAA,IACD;AAAA,IAEA,gBAAgB;AACf,YAAM,UAAU,oBAAI,IAAG;AACvB,UAAI,KAAK,WAAW;AAGnB,mBAAW,QAAQ,KAAK,UAAU,MAAM,KAAK,GAAG;AAC/C,kBAAQ,IAAI,IAAI;AAAA,QACjB;AAAA,MACD,WAAW,KAAK,aAAa;AAI5B,mBAAW,QAAQ,KAAK,YAAY,MAAM,KAAK,GAAG;AACjD,kBAAQ,IAAI,IAAI;AAAA,QACjB;AAEA,YAAI,QAAQ,OAAO,GAAG;AACrB,kBAAQ,IAAI,KAAK,gBAAgB;AAAA,QAClC;AAAA,MACD,OAAO;AACN,eAAO;AAAA,MACR;AAEA,cAAQ,IAAI,YAAY;AACxB,aAAO,CAAC,GAAG,QAAQ,OAAM,CAAE,EAAE,KAAK,KAAK;AAAA,IACxC;AAAA;EAGD,OAAO;AAAA,IACN,eAAe;AAAA,MACd,WAAW;AAAA,MACX,UAAU;AACT,YAAI,KAAK,kBAAkB,MAAM;AAChC,mBAAS,QAAQ,KAAK;AAAA,QACvB;AAAA,MACD;AAAA;IAGD,eAAe;AAAA,MACd,WAAW;AAAA,MACX,UAAU;AACT,aAAK,kBAAiB;AAAA,MACvB;AAAA;;EAIF,UAAU;AACT,QAAI,CAAC,KAAK,cAAc;AACvB,WAAK,UAAU,SAAS,KAAK,KAAK;AAAA,QACjC,YAAY,KAAK;AAAA,OACjB;AAAA,IACF;AAEA,SAAK,kBAAiB;AAAA,EACvB;AAAA,EAEA,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOR,YAAY,GAAG,WAAW;AACzB,YAAM,YAAY;AAClB,YAAM,YAAY;AAClB,UAAI,KAAK,IAAI,KAAK,QAAQ,OAAO,IAAI,WAAW;AAC/C,YAAI,KAAK,QAAQ,YAAY,IAAK,YAAY,KAAM,cAAc,SAAS;AAC1E,eAAK,qBAAqB;AAAA,YACzB,MAAM;AAAA,WACN;AAAA,QACF,WAAW,KAAK,QAAQ,YAAY,IAAI,YAAY,OAAO,cAAc,QAAQ;AAChF,eAAK,qBAAqB;AAAA,YACzB,MAAM;AAAA,WACN;AAAA,QACF;AAAA,MACD;AAAA,IACD;AAAA,IAEA,iBAAiB,OAAO;AACvB,YAAM,eAAe,SAAS,MAAM,MAAM,CAAC,EAAE,MAAM,EAAE;AACrD,qBAAe,QAAQ,KAAK,cAAc,KAAK,UAAU,YAAY,CAAC;AACtE,WAAK,eAAe;AAIpB,WAAK,MAAM,cAAc,EAAE,MAAM,cAAc;AAC/C,aAAO,MAAM,8BAA8B,EAAE,aAAW,CAAG;AAAA,IAC5D;AAAA;AAAA,IAGA,oBAAoB;AACnB,YAAM,eAAe,SAAS,eAAe,QAAQ,KAAK,YAAY,GAAG,EAAE;AAC3E,UAAI,CAAC,MAAM,YAAY,KAAK,iBAAiB,KAAK,cAAc;AAC/D,eAAO,MAAM,8BAA8B,EAAE,aAAW,CAAG;AAC3D,aAAK,eAAe;AACpB,eAAO;AAAA,MACR;AAAA,IACD;AAAA;AAAA;AAAA;AAAA,IAKA,cAAc;AACb,WAAK,MAAM,sBAAsB,KAAK;AAAA,IACvC;AAAA;AAEF;;;EAnWyB,OAAM;;AAgBA,MAAA,aAAA,EAAA,OAAM,4BAA2B;;;EAKiB,OAAM;;;;;;sBAtBtFG,mBAsDO,QAAA;AAAA,IAtDD,IAAG;AAAA,IAAkB,OAAKF,eAAA,CAAC,0BAAwB,EAAA,yBAAA,CAAA,CAAsC,KAAA,OAAO,MAAI,CAAA;AAAA;IAC/F,OAAA,4BAAVE,mBAEK,MAFL,YAEKC,gBADD,OAAA,WAAW,GAAA,CAAA;IAGG,CAAA,CAAA,KAAA,OAAO,qBAAzBD,mBA8CWE,UAAA,EAAA,KAAA,EAAA,GAAA;AAAA,MA3CH,OAAA,YAAY,OAAA,WAAM,2BADzBF,mBAcM,OAAA;AAAA;QAZL,uBAAM,qDAAmD;AAAA,+CACL,OAAA;AAAA,6CAAqD,OAAA;AAAA,yCAAiD,OAAA;AAAA;;QAKzH,OAAA,4BAAjCJ,YAAkF,sCAAA;AAAA;UAAnC,uBAAoB,SAAA,aAAW,CAAA,QAAA,SAAA,CAAA;AAAA;QAE9EO,eAAAC,mBAEM,OAFN,YAEM;AAAA,UADLC,WAAoB,KAAA,QAAA,QAAA,CAAA,GAAA,QAAA,IAAA;AAAA;mBADP,OAAA,WAAW;AAAA;QAGb,OAAA,cAAZA,WAA2B,KAAA,QAAA,WAAA,CAAA,GAAA,QAAA,MAAA,CAAA;eAEZ,OAAA,+BAA+B,OAAA,WAAM,sBAArDC,aAAAN,mBA4BM,OA5BN,YA4BM;AAAA,QA3BLD,YA0Ba,uBAAA;AAAA,UAzBX,YAAY,OAAA,WAAM;AAAA,UACnB,uBAAM,iBAAe;AAAA,sCACqB,OAAA,WAAM;AAAA,oCAAuD,OAAA,WAAM;AAAA;UAI5G,KAAK,OAAA;AAAA,UACL,WAAS,SAAA;AAAA;2BACV,MAOO;AAAA,YAPPA,YAOO,iBAAA;AAAA,cANN,OAAM;AAAA,cACL,MAAM,MAAA,gBAAgB,sBAAa,KAAK;AAAA,cACxC,SAAS,SAAA,aAAa,KAAK;AAAA,cAC3B,SAAS,SAAA,aAAa,KAAK;AAAA;+BAE5B,MAAoB;AAAA,gBAApBM,WAAoB,KAAA,QAAA,QAAA,CAAA,GAAA,QAAA,IAAA;AAAA;;;YAGrBN,YAOO,iBAAA;AAAA,cANN,OAAM;AAAA,cACL,MAAM,SAAA;AAAA,cACN,SAAS,SAAA,aAAa,QAAQ;AAAA,cAC9B,SAAS,SAAA,aAAa,QAAQ;AAAA;+BAE/B,MAAQ;AAAA,gBAARM,WAAQ,KAAA,QAAA,WAAA,CAAA,GAAA,QAAA,IAAA;AAAA;;;;;;;;IAMC,CAAA,KAAA,OAAO,OAApBA,WAA4B,KAAA,QAAA,WAAA,CAAA,GAAA,QAAA,MAAA,CAAA;;;;"}
1
+ {"version":3,"file":"NcAppContent.mjs","sources":["../../src/components/NcAppContent/NcAppContentDetailsToggle.vue","../../src/components/NcAppContent/NcAppContent.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n\n<script setup lang=\"ts\">\nimport { mdiArrowRight } from '@mdi/js'\nimport { emit } from '@nextcloud/event-bus'\nimport { onBeforeUnmount, onMounted, watch } from 'vue'\nimport { useIsMobile } from '../../composables/useIsMobile/index.js'\nimport { t } from '../../l10n.ts'\nimport NcButton from '../NcButton/index.ts'\nimport NcIconSvgWrapper from '../NcIconSvgWrapper/index.ts'\n\nconst isMobile = useIsMobile()\nwatch(isMobile, toggleAppNavigationButton)\n\nonMounted(() => {\n\ttoggleAppNavigationButton(isMobile.value)\n})\n\nonBeforeUnmount(() => {\n\tif (isMobile.value) {\n\t\ttoggleAppNavigationButton(false)\n\t}\n})\n\n/**\n * Toggle the app navigation button and hide it if needed.\n *\n * @param hide - if true the navigation toggle is visually hidden\n */\nfunction toggleAppNavigationButton(hide: boolean = true) {\n\tconst appNavigationToggle = document.querySelector<HTMLElement>('.app-navigation .app-navigation-toggle')\n\tif (appNavigationToggle) {\n\t\tappNavigationToggle.style.display = hide ? 'none' : ''\n\n\t\t// If we hide the NavigationToggle, we need to make sure the Navigation is also closed\n\t\tif (hide === true) {\n\t\t\temit('toggle-navigation', { open: false })\n\t\t}\n\t}\n}\n</script>\n\n<template>\n\t<NcButton\n\t\t:aria-label=\"t('Go back to the list')\"\n\t\tclass=\"app-details-toggle\"\n\t\t:class=\"{ 'app-details-toggle--mobile': isMobile }\"\n\t\t:title=\"t('Go back to the list')\"\n\t\tvariant=\"tertiary\">\n\t\t<template #icon>\n\t\t\t<NcIconSvgWrapper directional :path=\"mdiArrowRight\" />\n\t\t</template>\n\t</NcButton>\n</template>\n\n<style lang=\"scss\" scoped>\n.app-details-toggle {\n\tposition: sticky;\n\twidth: var(--default-clickable-area);\n\theight: var(--default-clickable-area);\n\tpadding: $icon-margin;\n\tcursor: pointer;\n\topacity: .6;\n\ttransform: rotate(180deg);\n\tbackground-color: var(--color-main-background);\n\tz-index: 2000;\n\n\ttop: var(--app-navigation-padding);\n\t// Navigation Toggle button width + 2 paddings around\n\tinset-inline-start: calc(var(--default-clickable-area) + var(--app-navigation-padding) * 2);\n\t&--mobile {\n\t\t// There is no NavigationToggle button\n\t\tinset-inline-start: var(--app-navigation-padding);\n\t}\n\n\t&:active,\n\t&:hover,\n\t&:focus {\n\t\topacity: 1;\n\t}\n}\n\n</style>\n","<!--\n - SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n\n<script lang=\"ts\">\nimport { getBuilder } from '@nextcloud/browser-storage'\nimport { getCapabilities } from '@nextcloud/capabilities'\n\n/**\n * Content layout used when a list is provided together with the main content.\n */\nexport type AppContentLayout = 'no-split' | 'vertical-split' | 'horizontal-split'\n\n/**\n * Payload of the `resized` event of the splitpanes component.\n */\ninterface SplitpanesResizedEvent {\n\tpanes: { min: number, max: number, size: number }[]\n}\n\nconst browserStorage = getBuilder('nextcloud').persist().build()\nconst instanceName = (getCapabilities() as { theming?: { name?: string } }).theming?.name ?? 'Nextcloud'\n</script>\n\n<script setup lang=\"ts\">\nimport type { Slot } from 'vue'\n\nimport { emit as emitBusEvent } from '@nextcloud/event-bus'\nimport { useCurrentElement, useSwipe } from '@vueuse/core'\nimport { Pane, Splitpanes } from 'splitpanes'\nimport { computed, onMounted, ref, watch } from 'vue'\nimport NcAppContentDetailsToggle from './NcAppContentDetailsToggle.vue'\nimport { useIsMobile } from '../../composables/useIsMobile/index.ts'\nimport { useAppName, useLocalizedAppName } from '../../utils/appName.ts'\nimport { logger } from '../../utils/logger.ts'\nimport { isRtl } from '../../utils/rtl.ts'\n\nimport 'splitpanes/dist/splitpanes.css'\n\n/**\n * When in mobile view, only the list or the details are shown.\n *\n * If you provide a list, you need to provide a variable\n * that will be set to true by the user when an element of\n * the list gets selected. The details will then show a back\n * arrow to return to the list that will update this model to false.\n */\nconst showDetails = defineModel<boolean>('showDetails', { default: true })\n\nconst {\n\tdisableSwipe = false,\n\tlayout = 'vertical-split',\n\tlistMaxWidth = 40,\n\tlistMinWidth = 15,\n\tlistSize = 20,\n\tpageHeading = undefined,\n\tpageTitle = undefined,\n\tpaneConfigKey = '',\n} = defineProps<{\n\t/**\n\t * Allows to disable the control by swipe of the app navigation open state.\n\t */\n\tdisableSwipe?: boolean\n\n\t/**\n\t * Allows you to set the default width of the resizable list in % on vertical-split\n\t * or respectively the default height on horizontal-split.\n\t *\n\t * Must be between `listMinWidth` and `listMaxWidth`.\n\t *\n\t * @default 20\n\t */\n\tlistSize?: number\n\n\t/**\n\t * Allows you to set the minimum width of the list column in % on vertical-split\n\t * or respectively the minimum height on horizontal-split.\n\t *\n\t * @default 15\n\t */\n\tlistMinWidth?: number\n\n\t/**\n\t * Allows you to set the maximum width of the list column in % on vertical-split\n\t * or respectively the maximum height on horizontal-split.\n\t *\n\t * @default 40\n\t */\n\tlistMaxWidth?: number\n\n\t/**\n\t * Specify the config key for the pane config sizes\n\t * Default is the global var appName if you use the webpack-vue-config\n\t */\n\tpaneConfigKey?: string\n\n\t/**\n\t * Content layout used when there is a list together with content:\n\t * - `vertical-split` - a 2-column layout with list and default content separated vertically\n\t * - `no-split` - a single column layout; List is shown when `showDetails` is `false`, otherwise the default slot content is shown with a back button to return to the list.\n\t * - 'horizontal-split' - a 2-column layout with list and default content separated horizontally\n\t * On mobile screen `no-split` layout is forced.\n\t *\n\t * @default 'vertical-split'\n\t */\n\tlayout?: AppContentLayout\n\n\t/**\n\t * Specify the `<h1>` page heading\n\t */\n\tpageHeading?: string | null\n\n\t/**\n\t * Allow setting the page's `<title>`\n\t *\n\t * If a page heading is set it defaults to `{pageHeading} - {appName} - {instanceName}` e.g. `Favorites - Files - MyPersonalCloud`.\n\t * When the page heading and the app name is the same only one is used, e.g. `Files - Files - MyPersonalCloud` is shown as `Files - MyPersonalCloud`.\n\t * When setting the prop then the following format will be used: `{pageTitle} - {instanceName}`\n\t */\n\tpageTitle?: string | null\n}>()\n\nconst emit = defineEmits<{\n\t/**\n\t * Emitted when the list pane is resized by the user\n\t */\n\tresizeList: [payload: { size: number }]\n\n\t/**\n\t * Emitted when the user clicked the back arrow from the details view\n\t *\n\t * @param showDetails - The new details state\n\t */\n\t'update:showDetails': [showDetails: boolean]\n}>()\n\ndefineSlots<{\n\t/**\n\t * Provide the main content to the app content\n\t */\n\tdefault?: Slot\n\n\t/**\n\t * Provide a list to the app content\n\t */\n\tlist?: Slot\n}>()\n\nconst appName = useAppName()\nconst localizedAppName = useLocalizedAppName()\nconst isMobile = useIsMobile()\n\nconst element = useCurrentElement<HTMLElement>()\nconst swipe = useSwipe(\n\t// Swiping can be disabled by not providing a target to listen on\n\t() => disableSwipe ? undefined : element.value,\n\t{\n\t\tonSwipeEnd(_event, direction) {\n\t\t\tconst minSwipeX = 70\n\t\t\tconst touchZone = 300\n\t\t\tif (Math.abs(swipe.lengthX.value) > minSwipeX) {\n\t\t\t\tif (swipe.coordsStart.x < (touchZone / 2) && direction === 'right') {\n\t\t\t\t\temitBusEvent('toggle-navigation', {\n\t\t\t\t\t\topen: true,\n\t\t\t\t\t})\n\t\t\t\t} else if (swipe.coordsStart.x < touchZone * 1.5 && direction === 'left') {\n\t\t\t\t\temitBusEvent('toggle-navigation', {\n\t\t\t\t\t\topen: false,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t},\n)\n\n/**\n * Size of the list pane as restored from the browser storage\n */\nconst listPaneSize = ref<number>()\n\nconst paneConfigID = computed(() => {\n\t// If provided, let's use it\n\tif (paneConfigKey !== '') {\n\t\treturn `pane-list-size-${paneConfigKey}`\n\t}\n\n\treturn `pane-list-size-${appName}`\n})\n\nconst paneDefaults = computed(() => ({\n\tlist: {\n\t\tsize: listSize,\n\t\tmin: listMinWidth,\n\t\tmax: listMaxWidth,\n\t},\n\n\t// set the inverse values of the details column\n\t// based on the provided (or default) values of the list column\n\tdetails: {\n\t\tsize: 100 - listSize,\n\t\tmin: 100 - listMaxWidth,\n\t\tmax: 100 - listMinWidth,\n\t},\n}))\n\nconst detailsPaneSize = computed(() => {\n\tif (listPaneSize.value) {\n\t\treturn 100 - listPaneSize.value\n\t}\n\treturn paneDefaults.value.details.size\n})\n\nconst realPageTitle = computed<string | null>(() => {\n\tconst entries = new Set<string>()\n\tif (pageTitle) {\n\t\t// when page title is set we only use that\n\t\t// we still split to remove duplicated instanceName\n\t\tfor (const part of pageTitle.split(' - ')) {\n\t\t\tentries.add(part)\n\t\t}\n\t} else if (pageHeading) {\n\t\t// when the page heading is provided but not the title\n\t\t// then we split to remove duplicates\n\t\t// but also add the localized app name\n\t\tfor (const part of pageHeading.split(' - ')) {\n\t\t\tentries.add(part)\n\t\t}\n\n\t\tif (entries.size > 0) {\n\t\t\tentries.add(localizedAppName)\n\t\t}\n\t} else {\n\t\treturn null\n\t}\n\n\tentries.add(instanceName)\n\treturn [...entries.values()].join(' - ')\n})\n\nwatch(realPageTitle, () => {\n\tif (realPageTitle.value !== null) {\n\t\tdocument.title = realPageTitle.value\n\t}\n}, { immediate: true })\n\nwatch(() => paneConfigKey, restorePaneConfig, { immediate: true })\n\nonMounted(restorePaneConfig)\n\n/**\n * Handle the resize of the list pane by the user.\n *\n * @param event - The `resized` event of the splitpanes component\n */\nfunction handlePaneResize(event: SplitpanesResizedEvent): void {\n\tconst size = Math.trunc(event.panes[0].size)\n\tbrowserStorage.setItem(paneConfigID.value, JSON.stringify(size))\n\tlistPaneSize.value = size\n\temit('resizeList', { size })\n\tlogger.debug('[NcAppContent] pane config', { listPaneSize: size })\n}\n\n/**\n * Restore the size of the list pane from the browser storage.\n *\n * browserStorage is not reactive, we need to update this manually.\n */\nfunction restorePaneConfig(): void {\n\tconst size = parseInt(browserStorage.getItem(paneConfigID.value) ?? '', 10)\n\tif (!isNaN(size) && size !== listPaneSize.value) {\n\t\tlogger.debug('[NcAppContent] pane config', { listPaneSize: size })\n\t\tlistPaneSize.value = size\n\t}\n}\n</script>\n\n<template>\n\t<main id=\"app-content-vue\" class=\"app-content no-snapper\" :class=\"{ 'app-content--has-list': !!$slots.list }\">\n\t\t<h1 v-if=\"pageHeading\" class=\"hidden-visually\">\n\t\t\t{{ pageHeading }}\n\t\t</h1>\n\n\t\t<template v-if=\"!!$slots.list\">\n\t\t\t<!-- Mobile view does not allow resizeable panes -->\n\t\t\t<div\n\t\t\t\tv-if=\"isMobile || layout === 'no-split'\"\n\t\t\t\tclass=\"app-content-wrapper app-content-wrapper--no-split\"\n\t\t\t\t:class=\"{\n\t\t\t\t\t'app-content-wrapper--show-details': showDetails,\n\t\t\t\t\t'app-content-wrapper--show-list': !showDetails,\n\t\t\t\t\t'app-content-wrapper--mobile': isMobile,\n\t\t\t\t}\">\n\t\t\t\t<NcAppContentDetailsToggle v-if=\"showDetails\" @click.stop.prevent=\"showDetails = false\" />\n\n\t\t\t\t<div v-show=\"!showDetails\" class=\"app-content-wrapper__list\">\n\t\t\t\t\t<slot name=\"list\" />\n\t\t\t\t</div>\n\t\t\t\t<slot v-if=\"showDetails\" />\n\t\t\t</div>\n\t\t\t<div v-else-if=\"layout === 'vertical-split' || layout === 'horizontal-split'\" class=\"app-content-wrapper\">\n\t\t\t\t<Splitpanes\n\t\t\t\t\t:horizontal=\"layout === 'horizontal-split'\"\n\t\t\t\t\tclass=\"default-theme\"\n\t\t\t\t\t:class=\"{\n\t\t\t\t\t\t'splitpanes--horizontal': layout === 'horizontal-split',\n\t\t\t\t\t\t'splitpanes--vertical': layout === 'vertical-split',\n\t\t\t\t\t}\"\n\t\t\t\t\t:rtl=\"isRtl\"\n\t\t\t\t\t@resized=\"handlePaneResize\">\n\t\t\t\t\t<Pane\n\t\t\t\t\t\tclass=\"splitpanes__pane-list\"\n\t\t\t\t\t\t:size=\"listPaneSize || paneDefaults.list.size\"\n\t\t\t\t\t\t:minSize=\"paneDefaults.list.min\"\n\t\t\t\t\t\t:maxSize=\"paneDefaults.list.max\">\n\t\t\t\t\t\t<slot name=\"list\" />\n\t\t\t\t\t</Pane>\n\n\t\t\t\t\t<Pane\n\t\t\t\t\t\tclass=\"splitpanes__pane-details\"\n\t\t\t\t\t\t:size=\"detailsPaneSize\"\n\t\t\t\t\t\t:minSize=\"paneDefaults.details.min\"\n\t\t\t\t\t\t:maxSize=\"paneDefaults.details.max\">\n\t\t\t\t\t\t<slot />\n\t\t\t\t\t</Pane>\n\t\t\t\t</Splitpanes>\n\t\t\t</div>\n\t\t</template>\n\t\t<slot v-if=\"!$slots.list\" />\n\t</main>\n</template>\n\n<style lang=\"scss\" scoped>\n\n.app-content {\n\tposition: initial;\n\tz-index: 1000;\n\tflex-basis: 100vw;\n\theight: 100%;\n\t// Overriding server styles TODO: cleanup!\n\tmargin: 0 !important;\n\tbackground-color: var(--color-main-background);\n\tmin-width: 0;\n\n\t&:not(.app-content--has-list) {\n\t\toverflow: auto;\n\t}\n}\n\n.app-content-wrapper {\n\tposition: relative;\n\twidth: 100%;\n\theight: 100%;\n}\n\n// Mobile list/details handling\n.app-content-wrapper--no-split {\n\t&.app-content-wrapper--show-list :deep() {\n\t\t.app-content-list {\n\t\t\tdisplay: flex;\n\t\t}\n\t\t.app-content-details {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n\t&.app-content-wrapper--show-details :deep() {\n\t\t.app-content-list {\n\t\t\tdisplay: none;\n\t\t}\n\t\t.app-content-details {\n\t\t\tdisplay: block;\n\t\t}\n\t}\n}\n\n:deep(.splitpanes.default-theme) {\n\t.app-content-list {\n\t\tmax-width: none;\n\t\t/* Thin scrollbar is hard to catch on resizable columns */\n\t\tscrollbar-width: auto;\n\t}\n\n\t.splitpanes__pane {\n\t\tbackground-color: transparent;\n\t\ttransition: none;\n\n\t\t&-list {\n\t\t\tmin-width: 300px;\n\t\t\tposition: sticky;\n\n\t\t\t@media only screen and (width < $breakpoint-mobile) {\n\t\t\t\tdisplay: none;\n\t\t\t}\n\t\t}\n\n\t\t&-details {\n\t\t\toverflow-y: auto;\n\n\t\t\t@media only screen and (width < $breakpoint-mobile) {\n\t\t\t\tmin-width: 100%;\n\t\t\t}\n\t\t}\n\t}\n\n\t.splitpanes__splitter {\n\t\tbackground-color: var(--color-main-background);\n\t\t&::before, &::after {\n\t\t\tbackground-color: var(--color-border);\n\t\t}\n\t}\n\n\t&.splitpanes--vertical .splitpanes__splitter {\n\t\tborder-inline-start: 1px solid var(--color-border);\n\t}\n\n\t&.splitpanes--horizontal .splitpanes__splitter {\n\t\tborder-top: 1px solid var(--color-border);\n\t}\n}\n\n.app-content-wrapper--show-list {\n\t:deep(.app-content-list) {\n\t\tmax-width: none;\n\t}\n}\n\n.app-content-wrapper__list {\n\theight: 100%;\n}\n</style>\n\n<docs>\n### General description\n\nThis components provides a wrapper around the main app's content.\n\nSingle-column layouts can just use the default slot. A resizable column\ncan be added by providing content to the named slot `list`.\n\n### CSS variables\nIn the css section some css variables are declared and will be available for\nall the children of the NcAppContent component\n\n### Examples\n\n#### Usage: Single-column content\n```vue\n<template>\n\t<NcAppContent>\n\t\t<h2>Single-column main content</h2>\n\t</NcAppContent>\n</template>\n```\n\n#### Usage: Two resizable columns\n```vue\n<template>\n\t<NcAppContent>\n\t\t<template #list>\n\t\t\t<div>Resizable list content</div>\n\t\t</template>\n\n\t\t<div>Main content</div>\n\t</NcAppContent>\n</template>\n```\n\n#### Overriding Defaults\nThe default, min and max sizes (in percent) of the resizable list column can be overridden.\nThe list size must be between the min and the max width value.\n\n```\n<NcAppContent\n\t:list-size=\"35\"\n\t:list-min-width=\"20\"\n\t:list-max-width=\"45\"\n>...</NcAppContent>\n```\n\n#### Usage: Custom document title\nFor accessibility reasons every document should have a `h1` heading,\nthis is visually hidden, but required for a semantically correct document.\nYou can use your app name or current view for the heading.\n\nAdditionally you can set a custom document title, e.g. to show the current status.\n\n```vue\n<template>\n\t<NcAppContent :pageHeading=\"heading ? 'Heading' : undefined\" :pageTitle=\"title ? 'Title' : undefined\" >\n\t\t<NcCheckboxRadioSwitch type=\"switch\" :checked.sync=\"title\">\n\t\t\tToggle title\n\t\t</NcCheckboxRadioSwitch>\n\t\t<NcCheckboxRadioSwitch type=\"switch\" :checked.sync=\"heading\">\n\t\t\tToggle Heading\n\t\t</NcCheckboxRadioSwitch>\n\t\t<NcButton @click=\"reset\">Reset</NcButton>\n\t</NcAppContent>\n</template>\n\n<script>\nexport default {\n\tdata() {\n\t\treturn {\n\t\t\theading: false,\n\t\t\ttitle: false,\n\t\t}\n\t},\n\tmethods: {\n\t\treset() {\n\t\t\tthis.heading = false\n\t\t\tthis.title = false\n\t\t\tdocument.title = ''\n\t\t},\n\t},\n}\n</script>\n```\n</docs>\n"],"names":["_createBlock","_unref","_normalizeClass","_createVNode","_useModel","emit","emitBusEvent","_createElementBlock","$slots","_toDisplayString","_Fragment","_withDirectives","_createElementVNode","_renderSlot","_openBlock"],"mappings":";;;;;;;;;;;;;;;;;;;;AAcA,UAAM,WAAW,YAAA;AACjB,UAAM,UAAU,yBAAyB;AAEzC,cAAU,MAAM;AACf,gCAA0B,SAAS,KAAK;AAAA,IACzC,CAAC;AAED,oBAAgB,MAAM;AACrB,UAAI,SAAS,OAAO;AACnB,kCAA0B,KAAK;AAAA,MAChC;AAAA,IACD,CAAC;AAOD,aAAS,0BAA0B,OAAgB,MAAM;AACxD,YAAM,sBAAsB,SAAS,cAA2B,wCAAwC;AACxG,UAAI,qBAAqB;AACxB,4BAAoB,MAAM,UAAU,OAAO,SAAS;AAGpD,YAAI,SAAS,MAAM;AAClB,eAAK,qBAAqB,EAAE,MAAM,MAAA,CAAO;AAAA,QAC1C;AAAA,MACD;AAAA,IACD;;0BAICA,YASWC,MAAA,QAAA,GAAA;AAAA,QART,cAAYA,MAAA,CAAA,EAAC,qBAAA;AAAA,QACd,OAAKC,eAAA,CAAC,sBAAoB,EAAA,8BACcD,MAAA,QAAA,EAAA,CAAQ,CAAA;AAAA,QAC/C,OAAOA,MAAA,CAAA,EAAC,qBAAA;AAAA,QACT,SAAQ;AAAA,MAAA;QACG,cACV,MAAsD;AAAA,UAAtDE,YAAsDF,MAAA,gBAAA,GAAA;AAAA,YAApC,aAAA;AAAA,YAAa,MAAMA,MAAA,aAAA;AAAA,UAAA;;;;;;;;;;;;;;;;;AChCxC,MAAM,iBAAiB,WAAW,WAAW,EAAE,QAAA,EAAU,MAAA;AACzD,MAAM,eAAgB,gBAAA,EAAsD,SAAS,QAAQ;;;;;;;;;;;;;;;;;;AA0B7F,UAAM,cAAcG,kBAAqB,aAAgC;AA2EzE,UAAMC,SAAO;AA0Bb,UAAM,UAAU,WAAA;AAChB,UAAM,mBAAmB,oBAAA;AACzB,UAAM,WAAW,YAAA;AAEjB,UAAM,UAAU,kBAAA;AAChB,UAAM,QAAQ;AAAA;AAAA,MAEb,MAAM,QAAA,eAAe,SAAY,QAAQ;AAAA,MACzC;AAAA,QACC,WAAW,QAAQ,WAAW;AAC7B,gBAAM,YAAY;AAClB,gBAAM,YAAY;AAClB,cAAI,KAAK,IAAI,MAAM,QAAQ,KAAK,IAAI,WAAW;AAC9C,gBAAI,MAAM,YAAY,IAAK,YAAY,KAAM,cAAc,SAAS;AACnEC,mBAAa,qBAAqB;AAAA,gBACjC,MAAM;AAAA,cAAA,CACN;AAAA,YACF,WAAW,MAAM,YAAY,IAAI,YAAY,OAAO,cAAc,QAAQ;AACzEA,mBAAa,qBAAqB;AAAA,gBACjC,MAAM;AAAA,cAAA,CACN;AAAA,YACF;AAAA,UACD;AAAA,QACD;AAAA,MAAA;AAAA,IACD;AAMD,UAAM,eAAe,IAAA;AAErB,UAAM,eAAe,SAAS,MAAM;AAEnC,UAAI,QAAA,kBAAkB,IAAI;AACzB,eAAO,kBAAkB,QAAA,aAAa;AAAA,MACvC;AAEA,aAAO,kBAAkB,OAAO;AAAA,IACjC,CAAC;AAED,UAAM,eAAe,SAAS,OAAO;AAAA,MACpC,MAAM;AAAA,QACL,MAAM,QAAA;AAAA,QACN,KAAK,QAAA;AAAA,QACL,KAAK,QAAA;AAAA,MAAA;AAAA;AAAA;AAAA,MAKN,SAAS;AAAA,QACR,MAAM,MAAM,QAAA;AAAA,QACZ,KAAK,MAAM,QAAA;AAAA,QACX,KAAK,MAAM,QAAA;AAAA,MAAA;AAAA,IACZ,EACC;AAEF,UAAM,kBAAkB,SAAS,MAAM;AACtC,UAAI,aAAa,OAAO;AACvB,eAAO,MAAM,aAAa;AAAA,MAC3B;AACA,aAAO,aAAa,MAAM,QAAQ;AAAA,IACnC,CAAC;AAED,UAAM,gBAAgB,SAAwB,MAAM;AACnD,YAAM,8BAAc,IAAA;AACpB,UAAI,QAAA,WAAW;AAGd,mBAAW,QAAQ,QAAA,UAAU,MAAM,KAAK,GAAG;AAC1C,kBAAQ,IAAI,IAAI;AAAA,QACjB;AAAA,MACD,WAAW,QAAA,aAAa;AAIvB,mBAAW,QAAQ,QAAA,YAAY,MAAM,KAAK,GAAG;AAC5C,kBAAQ,IAAI,IAAI;AAAA,QACjB;AAEA,YAAI,QAAQ,OAAO,GAAG;AACrB,kBAAQ,IAAI,gBAAgB;AAAA,QAC7B;AAAA,MACD,OAAO;AACN,eAAO;AAAA,MACR;AAEA,cAAQ,IAAI,YAAY;AACxB,aAAO,CAAC,GAAG,QAAQ,QAAQ,EAAE,KAAK,KAAK;AAAA,IACxC,CAAC;AAED,UAAM,eAAe,MAAM;AAC1B,UAAI,cAAc,UAAU,MAAM;AACjC,iBAAS,QAAQ,cAAc;AAAA,MAChC;AAAA,IACD,GAAG,EAAE,WAAW,MAAM;AAEtB,UAAM,MAAM,uBAAe,mBAAmB,EAAE,WAAW,MAAM;AAEjE,cAAU,iBAAiB;AAO3B,aAAS,iBAAiB,OAAqC;AAC9D,YAAM,OAAO,KAAK,MAAM,MAAM,MAAM,CAAC,EAAE,IAAI;AAC3C,qBAAe,QAAQ,aAAa,OAAO,KAAK,UAAU,IAAI,CAAC;AAC/D,mBAAa,QAAQ;AACrBD,aAAK,cAAc,EAAE,MAAM;AAC3B,aAAO,MAAM,8BAA8B,EAAE,cAAc,MAAM;AAAA,IAClE;AAOA,aAAS,oBAA0B;AAClC,YAAM,OAAO,SAAS,eAAe,QAAQ,aAAa,KAAK,KAAK,IAAI,EAAE;AAC1E,UAAI,CAAC,MAAM,IAAI,KAAK,SAAS,aAAa,OAAO;AAChD,eAAO,MAAM,8BAA8B,EAAE,cAAc,MAAM;AACjE,qBAAa,QAAQ;AAAA,MACtB;AAAA,IACD;;0BAICE,mBAmDO,QAAA;AAAA,QAnDD,IAAG;AAAA,QAAkB,OAAKL,eAAA,CAAC,0BAAwB,EAAA,yBAAA,CAAA,CAAsCM,KAAAA,OAAO,MAAI,CAAA;AAAA,MAAA;QAC/F,QAAA,4BAAVD,mBAEK,MAFL,YAEKE,gBADD,QAAA,WAAW,GAAA,CAAA;QAGGD,CAAAA,CAAAA,KAAAA,OAAO,qBAAzBD,mBA4CWG,UAAA,EAAA,KAAA,KAAA;AAAA,UAzCHT,MAAA,QAAA,KAAY,QAAA,WAAM,2BADzBM,mBAcM,OAAA;AAAA;YAZL,uBAAM,qDAAmD;AAAA,mDACL,YAAA;AAAA,iDAAqD,YAAA;AAAA,6CAAiDN,MAAA,QAAA;AAAA,YAAA;;YAKzH,YAAA,sBAAjCD,YAA0F,2BAAA;AAAA;cAA3C,6DAAoB,YAAA,QAAW,OAAA,CAAA,QAAA,SAAA,CAAA;AAAA,YAAA;YAE9EW,eAAAC,mBAEM,OAFN,YAEM;AAAA,cADLC,WAAoB,KAAA,QAAA,QAAA,CAAA,GAAA,QAAA,IAAA;AAAA,YAAA;uBADP,YAAA,KAAW;AAAA,YAAA;YAGb,YAAA,QAAZA,WAA2B,KAAA,QAAA,WAAA,IAAA,QAAA,MAAA,CAAA;mBAEZ,QAAA,+BAA+B,QAAA,WAAM,sBAArDC,UAAA,GAAAP,mBA0BM,OA1BN,YA0BM;AAAA,YAzBLJ,YAwBaF,MAAA,UAAA,GAAA;AAAA,cAvBX,YAAY,QAAA,WAAM;AAAA,cACnB,uBAAM,iBAAe;AAAA,0CACqB,QAAA,WAAM;AAAA,wCAAuD,QAAA,WAAM;AAAA,cAAA;cAI5G,KAAKA,MAAA,KAAA;AAAA,cACL,WAAS;AAAA,YAAA;+BACV,MAMO;AAAA,gBANPE,YAMOF,MAAA,IAAA,GAAA;AAAA,kBALN,OAAM;AAAA,kBACL,MAAM,aAAA,SAAgB,mBAAa,KAAK;AAAA,kBACxC,SAAS,aAAA,MAAa,KAAK;AAAA,kBAC3B,SAAS,aAAA,MAAa,KAAK;AAAA,gBAAA;mCAC5B,MAAoB;AAAA,oBAApBY,WAAoB,KAAA,QAAA,QAAA,CAAA,GAAA,QAAA,IAAA;AAAA,kBAAA;;;gBAGrBV,YAMOF,MAAA,IAAA,GAAA;AAAA,kBALN,OAAM;AAAA,kBACL,MAAM,gBAAA;AAAA,kBACN,SAAS,aAAA,MAAa,QAAQ;AAAA,kBAC9B,SAAS,aAAA,MAAa,QAAQ;AAAA,gBAAA;mCAC/B,MAAQ;AAAA,oBAARY,WAAQ,KAAA,QAAA,WAAA,CAAA,GAAA,QAAA,IAAA;AAAA,kBAAA;;;;;;;;QAKCL,CAAAA,KAAAA,OAAO,OAApBK,WAA4B,KAAA,QAAA,WAAA,CAAA,GAAA,QAAA,MAAA,CAAA;;;;;;"}