@htlkg/components 0.0.13 → 0.0.15

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.
@@ -1,4 +1,4 @@
1
- import { defineComponent, computed, createElementBlock, openBlock, createElementVNode, Fragment, renderList, normalizeClass, createTextVNode, createCommentVNode, toDisplayString, renderSlot, createBlock, unref, createVNode, ref, withCtx } from "vue";
1
+ import { defineComponent, computed, ref, createElementBlock, openBlock, createElementVNode, Fragment, renderList, normalizeClass, createTextVNode, createCommentVNode, toDisplayString, withDirectives, renderSlot, vShow, createBlock, unref, createVNode, onMounted, onUnmounted, withCtx } from "vue";
2
2
  import { _ as _export_sfc } from "./_plugin-vue_export-helper-1tPrXgE0.js";
3
3
  import { uiStepsV4, uiBreadcrumbs, uiWrapper } from "@hotelinking/ui";
4
4
  import { $user } from "./stores/index.js";
@@ -16,9 +16,10 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
16
16
  __name: "Tabs",
17
17
  props: {
18
18
  tabs: {},
19
- modelValue: { default: "" }
19
+ modelValue: { default: "" },
20
+ lazy: { type: Boolean, default: false }
20
21
  },
21
- emits: ["update:modelValue", "tab-change"],
22
+ emits: ["update:modelValue", "tab-change", "lazy-load"],
22
23
  setup(__props, { expose: __expose, emit: __emit }) {
23
24
  const props = __props;
24
25
  const emit = __emit;
@@ -29,21 +30,37 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
29
30
  emit("tab-change", value);
30
31
  }
31
32
  });
33
+ const visitedTabs = ref(/* @__PURE__ */ new Set([currentTab.value]));
34
+ function selectTab(tabId) {
35
+ const isFirstVisit = !visitedTabs.value.has(tabId);
36
+ visitedTabs.value.add(tabId);
37
+ currentTab.value = tabId;
38
+ if (isFirstVisit && props.lazy) {
39
+ emit("lazy-load", tabId);
40
+ }
41
+ }
42
+ function shouldRender(tabId) {
43
+ if (!props.lazy) {
44
+ return currentTab.value === tabId;
45
+ }
46
+ return visitedTabs.value.has(tabId);
47
+ }
32
48
  __expose({
33
49
  setActiveTab: (tabId) => {
34
- currentTab.value = tabId;
50
+ selectTab(tabId);
35
51
  },
36
52
  getActiveTab: () => currentTab.value,
53
+ isTabLoaded: (tabId) => visitedTabs.value.has(tabId),
37
54
  nextTab: () => {
38
55
  const currentIndex = props.tabs.findIndex((t) => t.id === currentTab.value);
39
56
  if (currentIndex < props.tabs.length - 1) {
40
- currentTab.value = props.tabs[currentIndex + 1].id;
57
+ selectTab(props.tabs[currentIndex + 1].id);
41
58
  }
42
59
  },
43
60
  previousTab: () => {
44
61
  const currentIndex = props.tabs.findIndex((t) => t.id === currentTab.value);
45
62
  if (currentIndex > 0) {
46
- currentTab.value = props.tabs[currentIndex - 1].id;
63
+ selectTab(props.tabs[currentIndex - 1].id);
47
64
  }
48
65
  }
49
66
  });
@@ -54,7 +71,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
54
71
  (openBlock(true), createElementBlock(Fragment, null, renderList(__props.tabs, (tab) => {
55
72
  return openBlock(), createElementBlock("button", {
56
73
  key: tab.id,
57
- onClick: ($event) => currentTab.value = tab.id,
74
+ onClick: ($event) => selectTab(tab.id),
58
75
  class: normalizeClass([
59
76
  currentTab.value === tab.id ? "border-blue-500 text-blue-600" : "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700",
60
77
  "whitespace-nowrap border-b-2 py-4 px-1 text-sm font-medium transition-colors"
@@ -78,9 +95,11 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
78
95
  return openBlock(), createElementBlock(Fragment, {
79
96
  key: tab.id
80
97
  }, [
81
- currentTab.value === tab.id ? (openBlock(), createElementBlock("div", _hoisted_6, [
98
+ shouldRender(tab.id) ? withDirectives((openBlock(), createElementBlock("div", _hoisted_6, [
82
99
  renderSlot(_ctx.$slots, tab.id, { activeTab: currentTab.value }, void 0, true)
83
- ])) : createCommentVNode("", true)
100
+ ], 512)), [
101
+ [vShow, currentTab.value === tab.id]
102
+ ]) : createCommentVNode("", true)
84
103
  ], 64);
85
104
  }), 128))
86
105
  ])
@@ -88,7 +107,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
88
107
  };
89
108
  }
90
109
  });
91
- const Tabs = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-ece16231"]]);
110
+ const Tabs = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-50d39e08"]]);
92
111
  const _sfc_main$2 = /* @__PURE__ */ defineComponent({
93
112
  __name: "Stepper",
94
113
  props: {
@@ -250,7 +269,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
250
269
  const defaultProfileMenu = [
251
270
  { name: "Profile", id: "profile", href: "/admin/user" },
252
271
  { name: "Settings", id: "settings", href: "/admin/settings" },
253
- { name: "Logout", id: "logout", href: "#" }
272
+ // Direct link to server-side logout - no JavaScript needed
273
+ { name: "Logout", id: "logout", href: "/logout" }
254
274
  ];
255
275
  const topbarConfig = computed(() => {
256
276
  var _a, _b, _c;
@@ -300,14 +320,14 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
300
320
  handleLogout();
301
321
  return;
302
322
  }
303
- if (menuItemHref && menuItemHref !== "#") {
304
- window.location.href = menuItemHref;
305
- return;
306
- }
307
323
  const profileMenu = topbarConfig.value.profileMenu;
308
324
  const menuItem = profileMenu.find((item) => item.id === menuItemId || item.name === menuItemId);
309
325
  if ((menuItem == null ? void 0 : menuItem.href) && menuItem.href !== "#") {
310
326
  window.location.href = menuItem.href;
327
+ return;
328
+ }
329
+ if (menuItemHref && menuItemHref !== "#") {
330
+ window.location.href = menuItemHref;
311
331
  }
312
332
  };
313
333
  const handleSideBarClick = (itemId) => {
@@ -325,16 +345,47 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
325
345
  const handleInputChanged = (event) => {
326
346
  console.log("Input changed:", event);
327
347
  };
328
- const handleLogout = async () => {
329
- try {
330
- const { signOut } = await import("@htlkg/core/auth");
331
- await signOut();
332
- window.location.href = "/login";
333
- } catch (error) {
334
- console.error("Logout error:", error);
335
- window.location.href = "/login";
348
+ const handleLogout = () => {
349
+ window.location.href = "/logout";
350
+ };
351
+ const handleProfileLinkClick = (event) => {
352
+ var _a;
353
+ const target = event.target;
354
+ const link = target.closest("a[href]");
355
+ if (!link) return;
356
+ const href = link.getAttribute("href");
357
+ if (!href) return;
358
+ const profileMenu = topbarConfig.value.profileMenu;
359
+ const linkText = (_a = link.textContent) == null ? void 0 : _a.trim().toLowerCase();
360
+ if (href === "#" && linkText === "logout") {
361
+ event.preventDefault();
362
+ event.stopPropagation();
363
+ handleLogout();
364
+ return;
365
+ }
366
+ const pathMappings = {};
367
+ for (const item of profileMenu) {
368
+ if (item.id === "settings" || item.name === "Settings") {
369
+ pathMappings["/settings"] = item.href;
370
+ }
371
+ if (item.id === "profile" || item.name === "Profile") {
372
+ pathMappings["/profile"] = item.href;
373
+ pathMappings["/user"] = item.href;
374
+ }
375
+ }
376
+ const redirectTo = pathMappings[href];
377
+ if (redirectTo && redirectTo !== "#" && redirectTo !== href) {
378
+ event.preventDefault();
379
+ event.stopPropagation();
380
+ window.location.href = redirectTo;
336
381
  }
337
382
  };
383
+ onMounted(() => {
384
+ document.addEventListener("click", handleProfileLinkClick, true);
385
+ });
386
+ onUnmounted(() => {
387
+ document.removeEventListener("click", handleProfileLinkClick, true);
388
+ });
338
389
  return (_ctx, _cache) => {
339
390
  return openBlock(), createBlock(unref(uiWrapper), {
340
391
  sidebar: sidebarConfig.value,
@@ -361,4 +412,4 @@ export {
361
412
  _sfc_main$2 as _,
362
413
  _sfc_main as a
363
414
  };
364
- //# sourceMappingURL=AdminWrapper.vue_vue_type_script_setup_true_lang-BhnWQ-b0.js.map
415
+ //# sourceMappingURL=AdminWrapper.vue_vue_type_script_setup_true_lang-DgzX2LI3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminWrapper.vue_vue_type_script_setup_true_lang-DgzX2LI3.js","sources":["../src/navigation/Tabs/Tabs.vue","../src/navigation/Stepper/Stepper.vue","../src/navigation/Breadcrumbs/Breadcrumbs.vue","../src/navigation/AdminWrapper/AdminWrapper.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed } from 'vue';\n\nexport interface Tab {\n id: string;\n label: string;\n count?: number;\n}\n\ninterface Props {\n tabs: Tab[];\n modelValue?: string;\n /** When true, tab content is only rendered after first activation but stays alive once loaded */\n lazy?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n modelValue: '',\n lazy: false,\n});\n\nconst emit = defineEmits<{\n 'update:modelValue': [tabId: string];\n 'tab-change': [tabId: string];\n 'lazy-load': [tabId: string];\n}>();\n\n// Internal state synced with v-model\nconst currentTab = computed({\n get: () => props.modelValue || (props.tabs.length > 0 ? props.tabs[0].id : ''),\n set: (value: string) => {\n emit('update:modelValue', value);\n emit('tab-change', value);\n }\n});\n\n// Track visited tabs for lazy rendering\nconst visitedTabs = ref<Set<string>>(new Set([currentTab.value]));\n\nfunction selectTab(tabId: string) {\n const isFirstVisit = !visitedTabs.value.has(tabId);\n visitedTabs.value.add(tabId);\n currentTab.value = tabId;\n\n if (isFirstVisit && props.lazy) {\n emit('lazy-load', tabId);\n }\n}\n\nfunction shouldRender(tabId: string): boolean {\n if (!props.lazy) {\n // Non-lazy: standard v-if, only render active tab\n return currentTab.value === tabId;\n }\n // Lazy: render if ever visited\n return visitedTabs.value.has(tabId);\n}\n\n// Expose methods for parent components\ndefineExpose({\n setActiveTab: (tabId: string) => { selectTab(tabId); },\n getActiveTab: () => currentTab.value,\n isTabLoaded: (tabId: string) => visitedTabs.value.has(tabId),\n nextTab: () => {\n const currentIndex = props.tabs.findIndex(t => t.id === currentTab.value);\n if (currentIndex < props.tabs.length - 1) {\n selectTab(props.tabs[currentIndex + 1].id);\n }\n },\n previousTab: () => {\n const currentIndex = props.tabs.findIndex(t => t.id === currentTab.value);\n if (currentIndex > 0) {\n selectTab(props.tabs[currentIndex - 1].id);\n }\n }\n});\n</script>\n\n<template>\n <div class=\"tabs-wrapper\">\n <div class=\"border-b border-gray-200\">\n <nav class=\"-mb-px flex space-x-8\" aria-label=\"Tabs\">\n <button\n v-for=\"tab in tabs\"\n :key=\"tab.id\"\n @click=\"selectTab(tab.id)\"\n :class=\"[\n currentTab === tab.id\n ? 'border-blue-500 text-blue-600'\n : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700',\n 'whitespace-nowrap border-b-2 py-4 px-1 text-sm font-medium transition-colors'\n ]\"\n :aria-current=\"currentTab === tab.id ? 'page' : undefined\"\n >\n {{ tab.label }}\n <span\n v-if=\"tab.count !== undefined && tab.count > 0\"\n :class=\"[\n currentTab === tab.id\n ? 'bg-blue-100 text-blue-600'\n : 'bg-gray-100 text-gray-900',\n 'ml-3 hidden rounded-full py-0.5 px-2.5 text-xs font-medium md:inline-block'\n ]\"\n >\n {{ tab.count }}\n </span>\n </button>\n </nav>\n </div>\n\n <div class=\"tabs-content mt-4\">\n <template v-for=\"tab in tabs\" :key=\"tab.id\">\n <div v-if=\"shouldRender(tab.id)\" v-show=\"currentTab === tab.id\">\n <slot :name=\"tab.id\" :active-tab=\"currentTab\" />\n </div>\n </template>\n </div>\n </div>\n</template>\n\n<style scoped>\n.tabs-wrapper {\n width: 100%;\n}\n\n.tabs-content {\n margin-top: 1rem;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { uiStepsV4 } from '@hotelinking/ui';\n\nexport interface Step {\n id?: string | number;\n label: string;\n status?: 'complete' | 'current' | 'upcoming';\n valid?: boolean; // Validation state for the step\n}\n\ninterface Props {\n steps: Step[];\n currentStep?: number;\n validateOnNext?: boolean; // Enable validation when moving forward\n allowSkip?: boolean; // Allow skipping to any step regardless of validation\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n currentStep: 0,\n validateOnNext: false,\n allowSkip: false\n});\n\nconst emit = defineEmits<{\n 'step-click': [step: Step, index: number];\n 'step-completed': [step: Step];\n 'step-current': [step: Step];\n 'step-upcoming': [step: Step];\n 'validation-failed': [step: Step, index: number];\n 'update:currentStep': [index: number]; // v-model support\n}>();\n\n// Transform steps to uiStepsV4 format\nconst uiSteps = computed(() =>\n props.steps.map((step, index) => ({\n id: step.id || String(index + 1).padStart(2, '0'),\n name: step.label,\n status: step.status || (\n index < props.currentStep ? 'complete' :\n index === props.currentStep ? 'current' :\n 'upcoming'\n )\n }))\n);\n\n// Check if navigation to a step is allowed\nfunction canNavigateToStep(targetIndex: number): boolean {\n if (props.allowSkip) return true;\n if (!props.validateOnNext) return true;\n if (targetIndex < props.currentStep) return true;\n\n const currentStepData = props.steps[props.currentStep];\n if (targetIndex > props.currentStep && currentStepData.valid === false) {\n return false;\n }\n\n for (let i = props.currentStep; i < targetIndex; i++) {\n if (props.steps[i].valid === false) {\n return false;\n }\n }\n\n return true;\n}\n\n// Handle uiStepsV4 events\nfunction handleStepClick(step: any, index: number) {\n const originalStep = props.steps[index];\n \n if (!canNavigateToStep(index)) {\n const currentStepData = props.steps[props.currentStep];\n emit('validation-failed', currentStepData, props.currentStep);\n return;\n }\n\n emit('step-click', originalStep, index);\n emit('update:currentStep', index);\n}\n\nfunction handleStepCompleted(step: any) {\n const index = uiSteps.value.findIndex(s => s.id === step.id);\n if (index !== -1) {\n emit('step-completed', props.steps[index]);\n }\n}\n\nfunction handleStepCurrent(step: any) {\n const index = uiSteps.value.findIndex(s => s.id === step.id);\n if (index !== -1) {\n emit('step-current', props.steps[index]);\n }\n}\n\nfunction handleStepUpcoming(step: any) {\n const index = uiSteps.value.findIndex(s => s.id === step.id);\n if (index !== -1) {\n emit('step-upcoming', props.steps[index]);\n }\n}\n\n// Public methods for programmatic navigation\nfunction goToStep(index: number): boolean {\n if (index < 0 || index >= props.steps.length) return false;\n if (!canNavigateToStep(index)) {\n const currentStepData = props.steps[props.currentStep];\n emit('validation-failed', currentStepData, props.currentStep);\n return false;\n }\n emit('update:currentStep', index);\n return true;\n}\n\nfunction goToNext(): boolean {\n return goToStep(props.currentStep + 1);\n}\n\nfunction goToPrevious(): boolean {\n return goToStep(props.currentStep - 1);\n}\n\nfunction validateCurrentStep(): boolean {\n const currentStepData = props.steps[props.currentStep];\n return currentStepData.valid !== false;\n}\n\ndefineExpose({\n getCurrentStep: () => props.currentStep,\n getSteps: () => props.steps,\n goToStep,\n goToNext,\n goToPrevious,\n validateCurrentStep,\n canNavigateToStep\n});\n</script>\n\n<template>\n <uiStepsV4\n :steps=\"uiSteps\"\n @stepClick=\"handleStepClick\"\n @stepCompleted=\"handleStepCompleted\"\n @stepCurrent=\"handleStepCurrent\"\n @stepUpcoming=\"handleStepUpcoming\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { uiBreadcrumbs } from '@hotelinking/ui';\n\nexport interface BreadcrumbItem {\n label: string;\n routeName: string;\n current?: boolean;\n}\n\ninterface Props {\n items: BreadcrumbItem[];\n loading?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n loading: false\n});\n\nconst emit = defineEmits<{\n 'breadcrumb-click': [routeName: string];\n}>();\n\n// Convert items to uiBreadcrumbs format\nconst pagesConfig = computed(() =>\n props.items.map((item, index) => ({\n name: item.label,\n routeName: item.routeName,\n current: item.current ?? (index === props.items.length - 1)\n }))\n);\n\n// Handle breadcrumb click\nfunction handleBreadcrumbClick(routeName: string) {\n emit('breadcrumb-click', routeName);\n}\n\n// Expose methods for parent components\ndefineExpose({\n getItems: () => props.items\n});\n</script>\n\n<template>\n <div class=\"breadcrumbs-wrapper\">\n <uiBreadcrumbs\n :pages=\"pagesConfig\"\n :loading=\"loading\"\n @bread-crumb-clicked=\"handleBreadcrumbClick\"\n />\n </div>\n</template>\n\n<style scoped>\n.breadcrumbs-wrapper {\n width: 100%;\n}\n</style>\n","/**\n * Admin Wrapper Component\n * \n * Wraps uiWrapper from @hotelinking/ui with sidebar, topbar, and content area.\n */\n\n<template>\n <uiWrapper \n :sidebar=\"sidebarConfig as any\" \n :topbar=\"topbarConfig as any\"\n :sidebarOpen=\"sidebarOpen\"\n @selectChanged=\"handleSelectChanged\"\n @topBarClick=\"handleTopBarClick\"\n @sideBarClick=\"handleSideBarClick\"\n @productBarClick=\"handleProductBarClick\"\n @inputChanged=\"handleInputChanged\"\n @sidebarToggle=\"(isOpen: boolean) => sidebarOpen = isOpen\"\n >\n <slot></slot>\n </uiWrapper>\n</template>\n\n<script setup lang=\"ts\">\nimport type { SelectItemType } from \"@hotelinking/ui\";\nimport { uiWrapper } from \"@hotelinking/ui\";\nimport { useStore } from \"@nanostores/vue\";\nimport { computed, ref, onMounted, onUnmounted } from \"vue\";\nimport { $user } from \"../../stores/user\";\n\n// Profile menu item interface\ninterface ProfileMenuItem {\n\tname: string;\n\tid: string;\n\thref: string;\n}\n\n// Props interface (user is now from nanostore)\ninterface Props {\n\tsidebarLogo: string;\n\tcurrentPage?: string;\n\tsidebarTitle?: string;\n\tsidebarItems?: Array<{\n\t\tname: string;\n\t\ticon?: string;\n\t\tid: string;\n\t\trouteName: string;\n\t}>;\n\ttopbarActions?: Array<{\n\t\tname: string;\n\t\tevent: string;\n\t\ticon: string;\n\t}>;\n\tselectItems?: Array<{\n\t\tname: string;\n\t\tid: string;\n\t}>;\n\tselectedItem?: {\n\t\tname: string;\n\t\tid: string;\n\t};\n\tproductsSidebar?: Array<{\n\t\tname: string;\n\t\ticon: string;\n\t\tactive?: boolean;\n\t}>;\n\tprofileMenuItems?: ProfileMenuItem[];\n\tsidebarOpenByDefault?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n\tcurrentPage: \"dashboard\",\n\tsidebarItems: () => [],\n\ttopbarActions: () => [],\n\tselectItems: () => [],\n\tselectedItem: () => ({ name: \"\", id: \"\" }),\n\tproductsSidebar: () => [],\n\tprofileMenuItems: () => [],\n\tsidebarOpenByDefault: true,\n});\n\n// Emit events\nconst emit = defineEmits<{\n\tselectChanged: [item: { name: string; id: string }];\n}>();\n\n// Reactive state\nconst sidebarOpen = ref(props.sidebarOpenByDefault);\n\n// Get user from nanostore (no props needed!)\nconst user = useStore($user);\n\n// Default profile menu items (used when none provided via props)\nconst defaultProfileMenu: ProfileMenuItem[] = [\n\t{ name: \"Profile\", id: \"profile\", href: \"/admin/user\" },\n\t{ name: \"Settings\", id: \"settings\", href: \"/admin/settings\" },\n\t// Direct link to server-side logout - no JavaScript needed\n\t{ name: \"Logout\", id: \"logout\", href: \"/logout\" },\n];\n\n// Computed properties for UI configuration\nconst topbarConfig = computed(() => {\n\treturn {\n\t\tlogo: props.sidebarLogo,\n\t\taccountLogo: user.value?.avatar || \"\",\n\t\talerted: false,\n\t\tprofileMenu: props.profileMenuItems.length > 0\n\t\t\t? props.profileMenuItems\n\t\t\t: defaultProfileMenu,\n\t\tbrand: {\n\t\t\tname: user.value?.username || \"User\",\n\t\t\tdescription: user.value?.email || \"\",\n\t\t},\n\t\tselectItems: props.selectItems,\n\t\tselectedItem: props.selectedItem,\n\t};\n});\n\nconst sidebarConfig = computed(() => {\n\t// Add current attribute dynamically based on currentPage\n\tconst navigationItems = props.sidebarItems.map((item) => ({\n\t\tname: item.name,\n\t\ticon: item.icon,\n\t\tid: item.id,\n\t\tcurrent: item.id === props.currentPage,\n\t}));\n\n\treturn {\n\t\tnavigation: navigationItems,\n\t\tproductsSidebar: props.productsSidebar,\n\t\tlogo: props.sidebarLogo,\n\t};\n});\n\n// Event handlers\nconst handleSelectChanged = (item: SelectItemType | SelectItemType[]) => {\n\tconsole.log(\"Select changed:\", item);\n\t// Emit to parent component\n\tif (!Array.isArray(item) && item.id) {\n\t\temit(\"selectChanged\", { name: item.name, id: item.id });\n\t}\n};\n\nconst handleTopBarClick = (event: unknown) => {\n\t// Handle different possible event formats\n\tlet menuItemId: string | undefined;\n\tlet menuItemHref: string | undefined;\n\n\tif (typeof event === \"string\") {\n\t\tmenuItemId = event;\n\t} else if (event && typeof event === \"object\") {\n\t\tconst eventObj = event as Record<string, unknown>;\n\t\tmenuItemId = (eventObj.id as string) || (eventObj.name as string);\n\t\tmenuItemHref = eventObj.href as string;\n\t}\n\n\t// Handle logout separately\n\tif (menuItemId === \"logout\") {\n\t\thandleLogout();\n\t\treturn;\n\t}\n\n\t// First, look up href from our profileMenu configuration (takes priority)\n\tconst profileMenu = topbarConfig.value.profileMenu;\n\tconst menuItem = profileMenu.find((item) => item.id === menuItemId || item.name === menuItemId);\n\tif (menuItem?.href && menuItem.href !== \"#\") {\n\t\twindow.location.href = menuItem.href;\n\t\treturn;\n\t}\n\n\t// Fallback: use href from event object if not found in our config\n\tif (menuItemHref && menuItemHref !== \"#\") {\n\t\twindow.location.href = menuItemHref;\n\t}\n};\n\nconst handleSideBarClick = (itemId: string) => {\n\tconsole.log(\"Sidebar click:\", itemId);\n\n\t// Find the item by id to get the routeName\n\tconst item = props.sidebarItems.find(\n\t\t(i) => (i.id || i.name.toLowerCase()) === itemId,\n\t);\n\n\tif (item?.routeName) {\n\t\twindow.location.href = item.routeName;\n\t}\n};\n\nconst handleProductBarClick = (event: unknown) => {\n\tconsole.log(\"Product bar click:\", event);\n};\n\nconst handleInputChanged = (event: unknown) => {\n\tconsole.log(\"Input changed:\", event);\n};\n\nconst handleLogout = () => {\n\t// Navigate to server-side logout page\n\t// This is the most reliable approach because:\n\t// 1. Server can properly clear HttpOnly cookies via Set-Cookie headers\n\t// 2. Browser applies Set-Cookie headers from navigation responses (not fetch)\n\t// 3. Redirect happens server-side after cookies are cleared\n\twindow.location.href = \"/logout\";\n};\n\n// Intercept profile menu link clicks to use our configured hrefs\n// The uiWrapper may render links with default hrefs that don't include /admin prefix\nconst handleProfileLinkClick = (event: MouseEvent) => {\n\tconst target = event.target as HTMLElement;\n\tconst link = target.closest('a[href]') as HTMLAnchorElement | null;\n\n\tif (!link) return;\n\n\tconst href = link.getAttribute('href');\n\tif (!href) return;\n\n\t// Check if this is a profile menu link that needs redirection\n\tconst profileMenu = topbarConfig.value.profileMenu;\n\n\t// Handle logout link specifically (href=\"#\" with text \"Logout\")\n\tconst linkText = link.textContent?.trim().toLowerCase();\n\tif (href === '#' && linkText === 'logout') {\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\thandleLogout();\n\t\treturn;\n\t}\n\n\t// Map of default paths to our configured paths\n\tconst pathMappings: Record<string, string | undefined> = {};\n\tfor (const item of profileMenu) {\n\t\t// Map common default paths to our configured hrefs\n\t\tif (item.id === 'settings' || item.name === 'Settings') {\n\t\t\tpathMappings['/settings'] = item.href;\n\t\t}\n\t\tif (item.id === 'profile' || item.name === 'Profile') {\n\t\t\tpathMappings['/profile'] = item.href;\n\t\t\tpathMappings['/user'] = item.href;\n\t\t}\n\t}\n\n\tconst redirectTo = pathMappings[href];\n\tif (redirectTo && redirectTo !== '#' && redirectTo !== href) {\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\t\twindow.location.href = redirectTo;\n\t}\n};\n\nonMounted(() => {\n\tdocument.addEventListener('click', handleProfileLinkClick, true);\n});\n\nonUnmounted(() => {\n\tdocument.removeEventListener('click', handleProfileLinkClick, true);\n});\n</script>\n"],"names":["_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_Fragment","_renderList","_normalizeClass","_toDisplayString","_renderSlot","_createBlock","_unref","_createVNode"],"mappings":"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"}
@@ -3,10 +3,10 @@
3
3
  width: 100%;
4
4
  }
5
5
 
6
- .tabs-wrapper[data-v-ece16231] {
6
+ .tabs-wrapper[data-v-50d39e08] {
7
7
  width: 100%;
8
8
  }
9
- .tabs-content[data-v-ece16231] {
9
+ .tabs-content[data-v-50d39e08] {
10
10
  margin-top: 1rem;
11
11
  }
12
12
 
@@ -1,35 +1,36 @@
1
1
  import { u } from "../useTable-DutR1gkg.js";
2
- import { l, $, P, q, o, r, w, k, s, p, x, t, z, b, A, c, v, h, g, j, d, y, u as u2, e, f, n, a, i, m } from "../useAdminPage-AgWRvw6o.js";
2
+ import { m, $, P, r, p, t, x, l, s, q, y, v, A, c, B, d, w, i, h, k, b, e, z, u as u2, f, g, o, a, j, n } from "../useAdminPage-DjONnrbe.js";
3
3
  export {
4
- l as $currentBrand,
4
+ m as $currentBrand,
5
5
  $ as $user,
6
6
  P as PAGE_CONTEXT_KEY,
7
- q as averageStat,
8
- o as countStat,
9
- r as percentageStat,
10
- w as resetGlobalConfirmation,
11
- k as setCurrentBrand,
7
+ r as averageStat,
8
+ p as countStat,
9
+ t as percentageStat,
10
+ x as resetGlobalConfirmation,
11
+ l as setCurrentBrand,
12
12
  s as setUser,
13
- p as sumStat,
14
- x as useAdminPage,
15
- t as useConfirmation,
16
- z as useDetailPage,
17
- b as useForm,
18
- A as useFormPage,
19
- c as useFormValidation,
20
- v as useGlobalConfirmation,
21
- h as useHasAccessToAccount,
22
- g as useHasAccessToBrand,
23
- j as useHasRole,
24
- d as useJsonForm,
25
- y as useListPage,
13
+ q as sumStat,
14
+ y as useAdminPage,
15
+ v as useConfirmation,
16
+ A as useDetailPage,
17
+ c as useForm,
18
+ B as useFormPage,
19
+ d as useFormValidation,
20
+ w as useGlobalConfirmation,
21
+ i as useHasAccessToAccount,
22
+ h as useHasAccessToBrand,
23
+ k as useHasRole,
24
+ b as useIntersectionObserver,
25
+ e as useJsonForm,
26
+ z as useListPage,
26
27
  u2 as useModal,
27
- e as useNotifications,
28
- f as usePageContext,
29
- n as useStats,
28
+ f as useNotifications,
29
+ g as usePageContext,
30
+ o as useStats,
30
31
  u as useTable,
31
32
  a as useTabs,
32
- i as useUserRoles,
33
- m as useWizard
33
+ j as useUserRoles,
34
+ n as useWizard
34
35
  };
35
36
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-QK97OdqQ.js","sources":["../../../node_modules/.pnpm/@nanostores+vue@1.0.1_@nanostores+logger@1.0.0_nanostores@1.1.0__@vue+devtools-api@8.0.5_nano_djkilzzyulm3hnuci7uvhv5cmu/node_modules/@nanostores/vue/use-store/index.js"],"sourcesContent":["import {\n getCurrentInstance,\n getCurrentScope,\n onScopeDispose,\n readonly,\n shallowRef\n} from 'vue'\n\nexport function registerStore(store) {\n let instance = getCurrentInstance()\n if (instance && instance.proxy) {\n let vm = instance.proxy\n let cache = '_nanostores' in vm ? vm._nanostores : (vm._nanostores = [])\n cache.push(store)\n }\n}\n\nexport function useStore(store) {\n let state = shallowRef()\n\n let unsubscribe = store.subscribe(value => {\n state.value = value\n })\n\n getCurrentScope() && onScopeDispose(unsubscribe)\n\n if (process.env.NODE_ENV !== 'production') {\n registerStore(store)\n return readonly(state)\n }\n return state\n}\n"],"names":[],"mappings":";AAQO,SAAS,cAAc,OAAO;AACnC,MAAI,WAAW,mBAAkB;AACjC,MAAI,YAAY,SAAS,OAAO;AAC9B,QAAI,KAAK,SAAS;AAClB,QAAI,QAAQ,iBAAiB,KAAK,GAAG,cAAe,GAAG,cAAc,CAAA;AACrE,UAAM,KAAK,KAAK;AAAA,EAClB;AACF;AAEO,SAAS,SAAS,OAAO;AAC9B,MAAI,QAAQ,WAAU;AAEtB,MAAI,cAAc,MAAM,UAAU,WAAS;AACzC,UAAM,QAAQ;AAAA,EAChB,CAAC;AAED,kBAAe,KAAM,eAAe,WAAW;AAE/C,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,kBAAc,KAAK;AACnB,WAAO,SAAS,KAAK;AAAA,EACvB;AACA,SAAO;AACT;","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"index-QK97OdqQ.js","sources":["../../../node_modules/.pnpm/@nanostores+vue@1.0.1_@nanostores+logger@1.0.0_nanostores@1.1.0__@vue+devtools-api@8.0._c092e7f7f0c6a3dca73b1ea880aefdb3/node_modules/@nanostores/vue/use-store/index.js"],"sourcesContent":["import {\n getCurrentInstance,\n getCurrentScope,\n onScopeDispose,\n readonly,\n shallowRef\n} from 'vue'\n\nexport function registerStore(store) {\n let instance = getCurrentInstance()\n if (instance && instance.proxy) {\n let vm = instance.proxy\n let cache = '_nanostores' in vm ? vm._nanostores : (vm._nanostores = [])\n cache.push(store)\n }\n}\n\nexport function useStore(store) {\n let state = shallowRef()\n\n let unsubscribe = store.subscribe(value => {\n state.value = value\n })\n\n getCurrentScope() && onScopeDispose(unsubscribe)\n\n if (process.env.NODE_ENV !== 'production') {\n registerStore(store)\n return readonly(state)\n }\n return state\n}\n"],"names":[],"mappings":";AAQO,SAAS,cAAc,OAAO;AACnC,MAAI,WAAW,mBAAkB;AACjC,MAAI,YAAY,SAAS,OAAO;AAC9B,QAAI,KAAK,SAAS;AAClB,QAAI,QAAQ,iBAAiB,KAAK,GAAG,cAAe,GAAG,cAAc,CAAA;AACrE,UAAM,KAAK,KAAK;AAAA,EAClB;AACF;AAEO,SAAS,SAAS,OAAO;AAC9B,MAAI,QAAQ,WAAU;AAEtB,MAAI,cAAc,MAAM,UAAU,WAAS;AACzC,UAAM,QAAQ;AAAA,EAChB,CAAC;AAED,kBAAe,KAAM,eAAe,WAAW;AAE/C,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,kBAAc,KAAK;AACnB,WAAO,SAAS,KAAK;AAAA,EACvB;AACA,SAAO;AACT;","x_google_ignoreList":[0]}
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { j, _, k, i, T, h, c, d, a, b, f, g, s, e } from "./filterHelpers-DpHSlTuh.js";
2
2
  import { a as a2, _ as _2 } from "./DateRange.vue_vue_type_script_setup_true_lang-BLVg1Hah.js";
3
- import { a as a3, B, _ as _3, T as T2 } from "./AdminWrapper.vue_vue_type_script_setup_true_lang-BhnWQ-b0.js";
3
+ import { a as a3, B, _ as _3, T as T2 } from "./AdminWrapper.vue_vue_type_script_setup_true_lang-DgzX2LI3.js";
4
4
  import { c as c2, a as a4, _ as _4, b as b2 } from "./Alert.vue_vue_type_script_setup_true_lang-DxPCS-Hx.js";
5
5
  import { a as a5, _ as _5, c as c3, b as b3 } from "./ProductBadge.vue_vue_type_script_setup_true_lang-Cmr2f4Cy.js";
6
6
  import { u } from "./useTable-DutR1gkg.js";
7
- import { l, $, P, q, o, r, w, k as k2, s as s2, p, x, t, z, b as b4, A, c as c4, v, h as h2, g as g2, j as j2, d as d2, y, u as u2, e as e2, f as f2, n, a as a6, i as i2, m } from "./useAdminPage-AgWRvw6o.js";
7
+ import { m, $, P, r, p, t, x, l, s as s2, q, y, v, A, c as c4, B as B2, d as d2, w, i as i2, h as h2, k as k2, b as b4, e as e2, z, u as u2, f as f2, g as g2, o, a as a6, j as j2, n } from "./useAdminPage-DjONnrbe.js";
8
8
  export {
9
- l as $currentBrand,
9
+ m as $currentBrand,
10
10
  $ as $user,
11
11
  a3 as AdminWrapper,
12
12
  c2 as Alert,
@@ -28,41 +28,42 @@ export {
28
28
  T as Table,
29
29
  T2 as Tabs,
30
30
  b3 as UserAvatar,
31
- q as averageStat,
31
+ r as averageStat,
32
32
  h as booleanOptions,
33
33
  c as columns,
34
- o as countStat,
34
+ p as countStat,
35
35
  d as createFilterGroup,
36
36
  a as createStatusColorFn,
37
37
  b as filterPresets,
38
38
  f as filters,
39
39
  g as getStatusColor,
40
- r as percentageStat,
41
- w as resetGlobalConfirmation,
42
- k2 as setCurrentBrand,
40
+ t as percentageStat,
41
+ x as resetGlobalConfirmation,
42
+ l as setCurrentBrand,
43
43
  s2 as setUser,
44
44
  s as statusColors,
45
45
  e as statusOptions,
46
- p as sumStat,
47
- x as useAdminPage,
48
- t as useConfirmation,
49
- z as useDetailPage,
50
- b4 as useForm,
51
- A as useFormPage,
52
- c4 as useFormValidation,
53
- v as useGlobalConfirmation,
54
- h2 as useHasAccessToAccount,
55
- g2 as useHasAccessToBrand,
56
- j2 as useHasRole,
57
- d2 as useJsonForm,
58
- y as useListPage,
46
+ q as sumStat,
47
+ y as useAdminPage,
48
+ v as useConfirmation,
49
+ A as useDetailPage,
50
+ c4 as useForm,
51
+ B2 as useFormPage,
52
+ d2 as useFormValidation,
53
+ w as useGlobalConfirmation,
54
+ i2 as useHasAccessToAccount,
55
+ h2 as useHasAccessToBrand,
56
+ k2 as useHasRole,
57
+ b4 as useIntersectionObserver,
58
+ e2 as useJsonForm,
59
+ z as useListPage,
59
60
  u2 as useModal,
60
- e2 as useNotifications,
61
- f2 as usePageContext,
62
- n as useStats,
61
+ f2 as useNotifications,
62
+ g2 as usePageContext,
63
+ o as useStats,
63
64
  u as useTable,
64
65
  a6 as useTabs,
65
- i2 as useUserRoles,
66
- m as useWizard
66
+ j2 as useUserRoles,
67
+ n as useWizard
67
68
  };
68
69
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,4 @@
1
- import { a, B, _, T } from "../AdminWrapper.vue_vue_type_script_setup_true_lang-BhnWQ-b0.js";
1
+ import { a, B, _, T } from "../AdminWrapper.vue_vue_type_script_setup_true_lang-DgzX2LI3.js";
2
2
  export {
3
3
  a as AdminWrapper,
4
4
  B as Breadcrumbs,
@@ -1,4 +1,4 @@
1
- import { ref, computed, watch, onMounted, onUnmounted, inject } from "vue";
1
+ import { ref, computed, watch, onUnmounted, onMounted, inject } from "vue";
2
2
  import { routes } from "@htlkg/core";
3
3
  import { a as atom } from "./index-DGO_pNgG.js";
4
4
  import { u as useStore } from "./index-QK97OdqQ.js";
@@ -40,9 +40,9 @@ function useModal(options = {}) {
40
40
  }
41
41
  function useTabs(options) {
42
42
  const tabs = ref(options.tabs);
43
- const activeTab = ref(
44
- options.initialTab || (tabs.value.length > 0 ? tabs.value[0].id : "")
45
- );
43
+ const initialTabId = options.initialTab || (tabs.value.length > 0 ? tabs.value[0].id : "");
44
+ const activeTab = ref(initialTabId);
45
+ const visitedTabs = ref(/* @__PURE__ */ new Set([initialTabId]));
46
46
  const currentTabIndex = computed(
47
47
  () => tabs.value.findIndex((tab) => tab.id === activeTab.value)
48
48
  );
@@ -51,22 +51,28 @@ function useTabs(options) {
51
51
  () => currentTabIndex.value === tabs.value.length - 1
52
52
  );
53
53
  function setActiveTab(tabId) {
54
- var _a;
54
+ var _a, _b;
55
55
  const tab = tabs.value.find((t) => t.id === tabId);
56
56
  if (tab && !tab.disabled) {
57
+ const isFirstVisit = !visitedTabs.value.has(tabId);
57
58
  activeTab.value = tabId;
59
+ visitedTabs.value.add(tabId);
58
60
  (_a = options.onChange) == null ? void 0 : _a.call(options, tabId);
61
+ if (isFirstVisit && tab.lazy) {
62
+ (_b = options.onLazyLoad) == null ? void 0 : _b.call(options, tabId);
63
+ }
59
64
  }
60
65
  }
61
66
  function nextTab() {
62
67
  if (!isLastTab.value) {
63
68
  const nextIndex = currentTabIndex.value + 1;
64
- const nextTab2 = tabs.value[nextIndex];
65
- if (nextTab2 && !nextTab2.disabled) {
66
- setActiveTab(nextTab2.id);
69
+ const nextTabItem = tabs.value[nextIndex];
70
+ if (nextTabItem && !nextTabItem.disabled) {
71
+ setActiveTab(nextTabItem.id);
67
72
  } else if (nextIndex < tabs.value.length - 1) {
68
- activeTab.value = nextTab2.id;
69
- nextTab2();
73
+ activeTab.value = nextTabItem.id;
74
+ visitedTabs.value.add(nextTabItem.id);
75
+ nextTab();
70
76
  }
71
77
  }
72
78
  }
@@ -78,6 +84,7 @@ function useTabs(options) {
78
84
  setActiveTab(prevTab.id);
79
85
  } else if (prevIndex > 0) {
80
86
  activeTab.value = prevTab.id;
87
+ visitedTabs.value.add(prevTab.id);
81
88
  previousTab();
82
89
  }
83
90
  }
@@ -89,6 +96,16 @@ function useTabs(options) {
89
96
  const tab = tabs.value.find((t) => t.id === tabId);
90
97
  return (tab == null ? void 0 : tab.disabled) ?? false;
91
98
  }
99
+ function isTabLoaded(tabId) {
100
+ const tab = tabs.value.find((t) => t.id === tabId);
101
+ if (!(tab == null ? void 0 : tab.lazy)) return true;
102
+ return visitedTabs.value.has(tabId);
103
+ }
104
+ function shouldRenderTab(tabId) {
105
+ const tab = tabs.value.find((t) => t.id === tabId);
106
+ if (!(tab == null ? void 0 : tab.lazy)) return activeTab.value === tabId;
107
+ return visitedTabs.value.has(tabId);
108
+ }
92
109
  return {
93
110
  activeTab,
94
111
  tabs,
@@ -99,7 +116,49 @@ function useTabs(options) {
99
116
  nextTab,
100
117
  previousTab,
101
118
  isTabActive,
102
- isTabDisabled
119
+ isTabDisabled,
120
+ isTabLoaded,
121
+ shouldRenderTab,
122
+ visitedTabs
123
+ };
124
+ }
125
+ function useIntersectionObserver(target, options = {}) {
126
+ const { root = null, rootMargin = "0px", threshold = 0, once = true } = options;
127
+ const isVisible = ref(false);
128
+ let observer = null;
129
+ function cleanup() {
130
+ if (observer) {
131
+ observer.disconnect();
132
+ observer = null;
133
+ }
134
+ }
135
+ function observe(el) {
136
+ cleanup();
137
+ if (!el || typeof IntersectionObserver === "undefined") {
138
+ return;
139
+ }
140
+ observer = new IntersectionObserver(
141
+ (entries) => {
142
+ const entry = entries[0];
143
+ if (entry) {
144
+ isVisible.value = entry.isIntersecting;
145
+ if (entry.isIntersecting && once) {
146
+ cleanup();
147
+ }
148
+ }
149
+ },
150
+ { root, rootMargin, threshold }
151
+ );
152
+ observer.observe(el);
153
+ }
154
+ const stopWatch = watch(target, (el) => observe(el), { immediate: true });
155
+ onUnmounted(() => {
156
+ stopWatch();
157
+ cleanup();
158
+ });
159
+ return {
160
+ isVisible,
161
+ stop: cleanup
103
162
  };
104
163
  }
105
164
  function useForm(options) {
@@ -1162,33 +1221,34 @@ function useFormPage(options) {
1162
1221
  }
1163
1222
  export {
1164
1223
  $user as $,
1165
- useFormPage as A,
1224
+ useDetailPage as A,
1225
+ useFormPage as B,
1166
1226
  PAGE_CONTEXT_KEY as P,
1167
1227
  useTabs as a,
1168
- useForm as b,
1169
- useFormValidation as c,
1170
- useJsonForm as d,
1171
- useNotifications as e,
1172
- usePageContext as f,
1173
- useHasAccessToBrand as g,
1174
- useHasAccessToAccount as h,
1175
- useUserRoles as i,
1176
- useHasRole as j,
1177
- setCurrentBrand as k,
1178
- $currentBrand as l,
1179
- useWizard as m,
1180
- useStats as n,
1181
- countStat as o,
1182
- sumStat as p,
1183
- averageStat as q,
1184
- percentageStat as r,
1228
+ useIntersectionObserver as b,
1229
+ useForm as c,
1230
+ useFormValidation as d,
1231
+ useJsonForm as e,
1232
+ useNotifications as f,
1233
+ usePageContext as g,
1234
+ useHasAccessToBrand as h,
1235
+ useHasAccessToAccount as i,
1236
+ useUserRoles as j,
1237
+ useHasRole as k,
1238
+ setCurrentBrand as l,
1239
+ $currentBrand as m,
1240
+ useWizard as n,
1241
+ useStats as o,
1242
+ countStat as p,
1243
+ sumStat as q,
1244
+ averageStat as r,
1185
1245
  setUser as s,
1186
- useConfirmation as t,
1246
+ percentageStat as t,
1187
1247
  useModal as u,
1188
- useGlobalConfirmation as v,
1189
- resetGlobalConfirmation as w,
1190
- useAdminPage as x,
1191
- useListPage as y,
1192
- useDetailPage as z
1248
+ useConfirmation as v,
1249
+ useGlobalConfirmation as w,
1250
+ resetGlobalConfirmation as x,
1251
+ useAdminPage as y,
1252
+ useListPage as z
1193
1253
  };
1194
- //# sourceMappingURL=useAdminPage-AgWRvw6o.js.map
1254
+ //# sourceMappingURL=useAdminPage-DjONnrbe.js.map