@shwfed/nuxt 0.7.8 → 0.7.10

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 (174) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/app.d.vue.ts +7 -58
  3. package/dist/runtime/components/app.vue +18 -411
  4. package/dist/runtime/components/app.vue.d.ts +7 -58
  5. package/dist/runtime/components/fields.d.vue.ts +177 -0
  6. package/dist/runtime/components/fields.vue +47 -0
  7. package/dist/runtime/components/fields.vue.d.ts +177 -0
  8. package/dist/runtime/components/table.d.vue.ts +63 -59
  9. package/dist/runtime/components/table.vue +52 -617
  10. package/dist/runtime/components/table.vue.d.ts +63 -59
  11. package/dist/runtime/components/ui/app/App.d.vue.ts +86 -0
  12. package/dist/runtime/components/ui/app/App.vue +414 -0
  13. package/dist/runtime/components/ui/app/App.vue.d.ts +86 -0
  14. package/dist/runtime/components/ui/button-group/ButtonGroupSeparator.vue +1 -1
  15. package/dist/runtime/components/ui/button-group/ButtonGroupText.vue +1 -1
  16. package/dist/runtime/components/ui/calendar/Calendar.d.vue.ts +5 -12
  17. package/dist/runtime/components/ui/calendar/Calendar.vue +77 -92
  18. package/dist/runtime/components/ui/calendar/Calendar.vue.d.ts +5 -12
  19. package/dist/runtime/components/ui/calendar/CalendarCellTrigger.vue +1 -1
  20. package/dist/runtime/components/ui/calendar/index.d.ts +1 -1
  21. package/dist/runtime/components/ui/checkbox/Checkbox.vue +6 -2
  22. package/dist/runtime/components/ui/command/CommandGroup.vue +4 -0
  23. package/dist/runtime/components/ui/dialog/DialogOverlay.vue +1 -1
  24. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +1 -1
  25. package/dist/runtime/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +1 -1
  26. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.d.vue.ts +30 -0
  27. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue +87 -0
  28. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue.d.ts +30 -0
  29. package/dist/runtime/components/ui/expression-editor/index.d.ts +1 -0
  30. package/dist/runtime/components/ui/expression-editor/index.js +1 -0
  31. package/dist/runtime/components/ui/field/FieldContent.vue +1 -1
  32. package/dist/runtime/components/ui/field/FieldDescription.vue +1 -1
  33. package/dist/runtime/components/ui/field/FieldError.vue +2 -2
  34. package/dist/runtime/components/ui/field/FieldLabel.vue +1 -1
  35. package/dist/runtime/components/ui/field/FieldSeparator.vue +1 -1
  36. package/dist/runtime/components/ui/field/index.js +7 -5
  37. package/dist/runtime/components/ui/fields/Fields.d.vue.ts +376 -0
  38. package/dist/runtime/components/ui/fields/Fields.vue +441 -0
  39. package/dist/runtime/components/ui/fields/Fields.vue.d.ts +376 -0
  40. package/dist/runtime/components/ui/fields-configurator/FieldsConfiguratorDialog.d.vue.ts +163 -0
  41. package/dist/runtime/components/ui/fields-configurator/FieldsConfiguratorDialog.vue +363 -0
  42. package/dist/runtime/components/ui/fields-configurator/FieldsConfiguratorDialog.vue.d.ts +163 -0
  43. package/dist/runtime/components/ui/input/Input.d.vue.ts +1 -0
  44. package/dist/runtime/components/ui/input/Input.vue +3 -1
  45. package/dist/runtime/components/ui/input/Input.vue.d.ts +1 -0
  46. package/dist/runtime/components/ui/input-group/InputGroup.vue +3 -0
  47. package/dist/runtime/components/ui/input-group/InputGroupAddon.vue +4 -1
  48. package/dist/runtime/components/ui/input-group/InputGroupCombobox.d.vue.ts +11 -3
  49. package/dist/runtime/components/ui/input-group/InputGroupCombobox.vue +16 -5
  50. package/dist/runtime/components/ui/input-group/InputGroupCombobox.vue.d.ts +11 -3
  51. package/dist/runtime/components/ui/input-group/InputGroupComboboxInput.d.vue.ts +8 -1
  52. package/dist/runtime/components/ui/input-group/InputGroupComboboxInput.vue +12 -1
  53. package/dist/runtime/components/ui/input-group/InputGroupComboboxInput.vue.d.ts +8 -1
  54. package/dist/runtime/components/ui/input-group/InputGroupInput.vue +1 -1
  55. package/dist/runtime/components/ui/input-group/InputGroupNumberField.d.vue.ts +5 -2
  56. package/dist/runtime/components/ui/input-group/InputGroupNumberField.vue +10 -4
  57. package/dist/runtime/components/ui/input-group/InputGroupNumberField.vue.d.ts +5 -2
  58. package/dist/runtime/components/ui/input-group/InputGroupText.vue +1 -1
  59. package/dist/runtime/components/ui/input-group/InputGroupTextarea.vue +1 -1
  60. package/dist/runtime/components/ui/input-group/index.js +2 -2
  61. package/dist/runtime/components/ui/label/Label.vue +1 -1
  62. package/dist/runtime/components/ui/locale/Locale.d.vue.ts +20 -0
  63. package/dist/runtime/components/ui/locale/Locale.vue +291 -0
  64. package/dist/runtime/components/ui/locale/Locale.vue.d.ts +20 -0
  65. package/dist/runtime/components/ui/locale/index.d.ts +1 -0
  66. package/dist/runtime/components/ui/locale/index.js +1 -0
  67. package/dist/runtime/components/ui/native-select/NativeSelect.vue +3 -3
  68. package/dist/runtime/components/ui/native-select/NativeSelectOption.d.vue.ts +1 -0
  69. package/dist/runtime/components/ui/native-select/NativeSelectOption.vue +4 -1
  70. package/dist/runtime/components/ui/native-select/NativeSelectOption.vue.d.ts +1 -0
  71. package/dist/runtime/components/ui/navigation-menu/NavigationMenuLink.vue +1 -1
  72. package/dist/runtime/components/ui/navigation-menu/NavigationMenuViewport.vue +1 -1
  73. package/dist/runtime/components/ui/number-field/NumberFieldInput.vue +1 -1
  74. package/dist/runtime/components/ui/range-calendar/RangeCalendarCell.vue +1 -1
  75. package/dist/runtime/components/ui/range-calendar/RangeCalendarCellTrigger.vue +1 -1
  76. package/dist/runtime/components/ui/sheet/SheetOverlay.vue +1 -1
  77. package/dist/runtime/components/ui/switch/Switch.d.vue.ts +24 -0
  78. package/dist/runtime/components/ui/switch/Switch.vue +46 -0
  79. package/dist/runtime/components/ui/switch/Switch.vue.d.ts +24 -0
  80. package/dist/runtime/components/ui/switch/index.d.ts +1 -0
  81. package/dist/runtime/components/ui/switch/index.js +1 -0
  82. package/dist/runtime/components/ui/table/Table.d.vue.ts +81 -0
  83. package/dist/runtime/components/ui/table/Table.vue +792 -0
  84. package/dist/runtime/components/ui/table/Table.vue.d.ts +81 -0
  85. package/dist/runtime/components/ui/table/schema.d.ts +48 -0
  86. package/dist/runtime/components/ui/table/schema.js +126 -0
  87. package/dist/runtime/components/ui/table-configurator/TableConfiguratorDialog.d.vue.ts +62 -0
  88. package/dist/runtime/components/ui/table-configurator/TableConfiguratorDialog.vue +2233 -0
  89. package/dist/runtime/components/ui/table-configurator/TableConfiguratorDialog.vue.d.ts +62 -0
  90. package/dist/runtime/components/ui/table-configurator/menu.d.ts +37 -0
  91. package/dist/runtime/components/ui/table-configurator/menu.js +227 -0
  92. package/dist/runtime/components/ui/tabs/Tabs.d.vue.ts +24 -0
  93. package/dist/runtime/components/ui/tabs/Tabs.vue +30 -0
  94. package/dist/runtime/components/ui/tabs/Tabs.vue.d.ts +24 -0
  95. package/dist/runtime/components/ui/tabs/TabsContent.d.vue.ts +18 -0
  96. package/dist/runtime/components/ui/tabs/TabsContent.vue +23 -0
  97. package/dist/runtime/components/ui/tabs/TabsContent.vue.d.ts +18 -0
  98. package/dist/runtime/components/ui/tabs/TabsList.d.vue.ts +18 -0
  99. package/dist/runtime/components/ui/tabs/TabsList.vue +25 -0
  100. package/dist/runtime/components/ui/tabs/TabsList.vue.d.ts +18 -0
  101. package/dist/runtime/components/ui/tabs/TabsTrigger.d.vue.ts +18 -0
  102. package/dist/runtime/components/ui/tabs/TabsTrigger.vue +27 -0
  103. package/dist/runtime/components/ui/tabs/TabsTrigger.vue.d.ts +18 -0
  104. package/dist/runtime/components/ui/tabs/index.d.ts +4 -0
  105. package/dist/runtime/components/ui/tabs/index.js +4 -0
  106. package/dist/runtime/components/ui/textarea/Textarea.d.vue.ts +1 -0
  107. package/dist/runtime/components/ui/textarea/Textarea.vue +4 -2
  108. package/dist/runtime/components/ui/textarea/Textarea.vue.d.ts +1 -0
  109. package/dist/runtime/components/ui/toggle/Toggle.d.vue.ts +34 -0
  110. package/dist/runtime/components/ui/toggle/Toggle.vue +32 -0
  111. package/dist/runtime/components/ui/toggle/Toggle.vue.d.ts +34 -0
  112. package/dist/runtime/components/ui/toggle/index.d.ts +7 -0
  113. package/dist/runtime/components/ui/toggle/index.js +22 -0
  114. package/dist/runtime/composables/useTableRenderers.d.ts +2 -1
  115. package/dist/runtime/composables/useTableRenderers.js +2 -1
  116. package/dist/runtime/plugins/cel/env.d.ts +2 -2
  117. package/dist/runtime/plugins/cel/env.js +5 -4
  118. package/dist/runtime/plugins/cel/index.d.ts +3 -3
  119. package/dist/runtime/plugins/cel/index.js +7 -3
  120. package/dist/runtime/plugins/markdown/index.d.ts +1 -1
  121. package/dist/runtime/style.css +1 -1
  122. package/dist/runtime/table-renderers/builtins.js +213 -98
  123. package/dist/runtime/table-renderers/registry.d.ts +1 -0
  124. package/dist/runtime/table-renderers/registry.js +3 -0
  125. package/dist/runtime/utils/coders.d.ts +32 -0
  126. package/dist/runtime/utils/coders.js +64 -0
  127. package/dist/runtime/vendor/cel/index.d.ts +17 -0
  128. package/dist/runtime/vendor/cel/index.js +10 -0
  129. package/dist/runtime/vendor/cel-js/LICENSE +21 -0
  130. package/dist/runtime/vendor/cel-js/UPSTREAM.md +17 -0
  131. package/dist/runtime/vendor/cel-js/lib/errors.d.ts +21 -0
  132. package/dist/runtime/vendor/cel-js/lib/errors.js +97 -0
  133. package/dist/runtime/vendor/cel-js/lib/evaluator.d.ts +4 -0
  134. package/dist/runtime/vendor/cel-js/lib/evaluator.js +192 -0
  135. package/dist/runtime/vendor/cel-js/lib/functions.d.ts +53 -0
  136. package/dist/runtime/vendor/cel-js/lib/functions.js +513 -0
  137. package/dist/runtime/vendor/cel-js/lib/globals.d.ts +27 -0
  138. package/dist/runtime/vendor/cel-js/lib/globals.js +33 -0
  139. package/dist/runtime/vendor/cel-js/lib/index.d.ts +469 -0
  140. package/dist/runtime/vendor/cel-js/lib/index.js +18 -0
  141. package/dist/runtime/vendor/cel-js/lib/macros.d.ts +1 -0
  142. package/dist/runtime/vendor/cel-js/lib/macros.js +230 -0
  143. package/dist/runtime/vendor/cel-js/lib/operators.d.ts +117 -0
  144. package/dist/runtime/vendor/cel-js/lib/operators.js +739 -0
  145. package/dist/runtime/vendor/cel-js/lib/optional.d.ts +14 -0
  146. package/dist/runtime/vendor/cel-js/lib/optional.js +161 -0
  147. package/dist/runtime/vendor/cel-js/lib/options.d.ts +23 -0
  148. package/dist/runtime/vendor/cel-js/lib/options.js +47 -0
  149. package/dist/runtime/vendor/cel-js/lib/overloads.d.ts +1 -0
  150. package/dist/runtime/vendor/cel-js/lib/overloads.js +214 -0
  151. package/dist/runtime/vendor/cel-js/lib/parser.d.ts +56 -0
  152. package/dist/runtime/vendor/cel-js/lib/parser.js +827 -0
  153. package/dist/runtime/vendor/cel-js/lib/registry.d.ts +279 -0
  154. package/dist/runtime/vendor/cel-js/lib/registry.js +1596 -0
  155. package/dist/runtime/vendor/cel-js/lib/serialize.d.ts +1 -0
  156. package/dist/runtime/vendor/cel-js/lib/serialize.js +259 -0
  157. package/dist/runtime/vendor/cel-js/lib/type-checker.d.ts +26 -0
  158. package/dist/runtime/vendor/cel-js/lib/type-checker.js +81 -0
  159. package/package.json +9 -4
  160. package/dist/runtime/components/locale.d.vue.ts +0 -14
  161. package/dist/runtime/components/locale.vue +0 -89
  162. package/dist/runtime/components/locale.vue.d.ts +0 -14
  163. package/dist/runtime/components/query.d.vue.ts +0 -30
  164. package/dist/runtime/components/query.vue +0 -266
  165. package/dist/runtime/components/query.vue.d.ts +0 -30
  166. package/dist/runtime/utilities/query-config/global.d.ts +0 -4
  167. package/dist/runtime/utilities/query-config/global.js +0 -18
  168. package/dist/runtime/utilities/query-config/index.d.ts +0 -3
  169. package/dist/runtime/utilities/query-config/index.js +0 -14
  170. package/dist/runtime/utilities/query-config/schema.d.ts +0 -96
  171. package/dist/runtime/utilities/query-config/schema.js +0 -51
  172. /package/dist/runtime/components/{logo.d.vue.ts → ui/logo/Logo.d.vue.ts} +0 -0
  173. /package/dist/runtime/components/{logo.vue → ui/logo/Logo.vue} +0 -0
  174. /package/dist/runtime/components/{logo.vue.d.ts → ui/logo/Logo.vue.d.ts} +0 -0
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shwfed/nuxt",
3
3
  "configKey": "shwfed",
4
- "version": "0.7.8",
4
+ "version": "0.7.10",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -1,13 +1,14 @@
1
1
  import type { Scope } from 'effect';
2
- import { Effect } from 'effect';
3
- import { type Sidebar as SidebarType } from '../composables/useNavigationTabs.js';
2
+ import type { Sidebar as SidebarType } from '../composables/useNavigationTabs.js';
3
+ type CommandEffect = import('effect').Effect.Effect<void>;
4
+ type DslEffect = import('effect').Effect.Effect<Record<string, unknown>, never, Scope.Scope>;
4
5
  type ProfileCommandInputItem = Readonly<{
5
6
  id: string | number;
6
7
  title: string;
7
8
  icon?: string;
8
9
  hidden?: boolean;
9
10
  disabled?: boolean;
10
- effect?: Effect.Effect<void>;
11
+ effect?: CommandEffect;
11
12
  keywords?: Array<string>;
12
13
  }>;
13
14
  type ProfileCommandInputGroup = Readonly<{
@@ -17,65 +18,13 @@ type ProfileCommandInputGroup = Readonly<{
17
18
  children: Array<ProfileCommandInputItem>;
18
19
  }>;
19
20
  type __VLS_Props = {
20
- /**
21
- * 应用的全局 DSL(CEL)执行上下文。传入一个 Effect,在应用启动时运行一次;
22
- * 其解析结果(一个 record)会被永久设为全局上下文,供后续所有 CEL 求值(如 `$dsl.evaluate`)使用。
23
- *
24
- * 应用会等待该 effect 解析完成后才渲染;在整个应用生命周期内只会执行一次。
25
- * 若未传入 `dsl`,全局上下文将被设为 `{}`。
26
- *
27
- * 适用于需要在首屏前就确定的、会话级稳定数据,例如:当前用户信息、用户所属组、
28
- * 用户菜单列表、用户权限(或权限模块)等。此处加载的数据在整个应用内可通过 CEL 访问
29
- *(如 `user`、`menu`、`permissions`)。强调「会话级」稳定即可,不必永久不变。
30
- *
31
- * 重要约束:
32
- * - 加载时间至关重要:在该 effect 解析前,整应用不会加载,用户会看到白屏,因此必须保持非常快
33
- * (如减少请求、缓存或并行拉取)。
34
- * - 这是有意为之的权衡:菜单、用户等关键数据必须在此加载,否则可能出现空菜单、无用户等异常表现。
35
- * - 该 effect 不得抛错(类型为 `never`):任何失败(如网络)应在 effect 内部处理,
36
- * 返回空对象或安全默认值,保证应用仍能正常启动并得到一致的全局上下文。
37
- *
38
- * 返回的 `Record<string, unknown>` 会在通过 `$dsl.evaluate` 求值 CEL 表达式时,
39
- * 与运行时上下文(如 `now`、`today` 及调用处传入的 context)合并使用。
40
- *
41
- * @example 最小示例:返回静态对象,键可在 CEL 中直接使用
42
- * dsl: Effect.succeed({ hello: 'world' })
43
- * // 之后在模板或逻辑中:$dsl.evaluate`hello`() 得到 'world'
44
- *
45
- * @example 实际场景:拉取会话数据(用户、菜单、权限)并返回,供 CEL 使用
46
- * dsl: Effect.gen(function* () {
47
- * const [user, menu, permissions] = yield* Effect.all([
48
- * fetchUser().pipe(Effect.catchAll(() => Effect.succeed({ name: '', id: '' }))),
49
- * fetchMenu().pipe(Effect.catchAll(() => Effect.succeed([]))),
50
- * fetchPermissions().pipe(Effect.catchAll(() => Effect.succeed({ canEdit: false }))),
51
- * ])
52
- * return { user, menu, permissions }
53
- * })
54
- * // CEL 中可访问 user.name、permissions.canEdit 等;失败时在 effect 内兜底,不抛错
55
- */
56
- dsl?: Effect.Effect<Record<string, unknown>, never, Scope.Scope>;
57
- /**
58
- * Sidebar config.
59
- *
60
- * `menus` is structured navigation data.
61
- */
21
+ dsl?: DslEffect;
62
22
  sidebar?: SidebarType;
63
- /**
64
- * Profile command config.
65
- *
66
- * Structured command entries for profile menu and command palette.
67
- */
68
23
  commands?: Array<ProfileCommandInputItem | ProfileCommandInputGroup>;
69
- read?: <T>(identity: string) => Effect.Effect<T>;
70
- write?: <T>(identity: string, value: T) => Effect.Effect<void>;
71
24
  };
72
- declare var __VLS_108: {}, __VLS_124: {}, __VLS_347: {};
25
+ declare var __VLS_10: string, __VLS_11: any;
73
26
  type __VLS_Slots = {} & {
74
- menu?: (props: typeof __VLS_108) => any;
75
- } & {
76
- profile?: (props: typeof __VLS_124) => any;
77
- } & {
78
- default?: (props: typeof __VLS_347) => any;
27
+ [K in NonNullable<typeof __VLS_10>]?: (props: typeof __VLS_11) => any;
79
28
  };
80
29
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
81
30
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1,420 +1,27 @@
1
1
  <script setup>
2
- import { useHead, useNuxtApp, useRuntimeConfig } from "#app";
3
- import { reactive } from "vue";
4
- import { CommandDialog, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from "./ui/command";
5
- import { TooltipProvider } from "./ui/tooltip";
6
- import { Toaster } from "vue-sonner";
7
- import { useMagicKeys, useTimeoutFn, whenever } from "@vueuse/core";
8
- import { useI18n } from "vue-i18n";
9
- import { Icon } from "@iconify/vue";
10
- import { Effect } from "effect";
11
- import { setGlobalDslContext } from "../plugins/cel/context";
12
- import { setQueryConfigAccessors } from "../utilities/query-config/global";
13
- import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarMenu, SidebarMenuAction, SidebarMenuButton, SidebarMenuItem, SidebarProvider } from "./ui/sidebar";
14
- import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./ui/collapsible";
15
- import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "./ui/dropdown-menu";
16
- import Logo from "./logo.vue";
17
- import { useFavorite } from "../composables/useFavorite";
18
- import { useNavigationTabs } from "../composables/useNavigationTabs";
19
- const {
20
- public: {
21
- shwfed
22
- }
23
- } = useRuntimeConfig();
24
- const { $dsl } = useNuxtApp();
25
- const { t } = useI18n();
2
+ import UiApp from "./ui/app/App.vue";
3
+ defineOptions({
4
+ inheritAttrs: false
5
+ });
26
6
  const props = defineProps({
27
7
  dsl: { type: null, required: false },
28
8
  sidebar: { type: Array, required: false },
29
- commands: { type: Array, required: false },
30
- read: { type: Function, required: false },
31
- write: { type: Function, required: false }
32
- });
33
- const { active, tabs, nameOf, close } = useNavigationTabs(() => props.sidebar ?? []);
34
- const ui = reactive({
35
- isCommandPaletteOpen: false,
36
- isProfileDropdownOpen: false
9
+ commands: { type: Array, required: false }
37
10
  });
38
- useHead({
39
- title: () => active.value && nameOf(active.value),
40
- bodyAttrs: {
41
- style: {
42
- "--primary": "#2DA8BC",
43
- "--workspace": "#FFFFFF"
44
- }
45
- }
46
- });
47
- const { start: startProfileCloseTimer, stop: stopProfileCloseTimer } = useTimeoutFn(() => {
48
- ui.isProfileDropdownOpen = false;
49
- }, 150, { immediate: false });
50
- const { meta_k } = useMagicKeys();
51
- whenever(() => meta_k?.value, () => ui.isCommandPaletteOpen = !ui.isCommandPaletteOpen);
52
- setGlobalDslContext(await props.dsl?.pipe(Effect.scoped).pipe(Effect.runPromise) ?? {});
53
- if (props.read !== void 0 && props.write !== void 0) {
54
- setQueryConfigAccessors(props.read, props.write);
55
- }
56
- const {
57
- isFavorited: isNavigationFavorited,
58
- canBeFavorited: canBeNavigationFavorited,
59
- toggle: toggleNavigationFavorite,
60
- withFavorites: navigations
61
- } = useFavorite("navigation", () => props.sidebar ?? []);
62
- const logout = () => {
63
- if (shwfed.api.logout) {
64
- window.location.href = shwfed.api.logout;
65
- }
66
- return Effect.void;
67
- };
68
11
  </script>
69
12
 
70
13
  <template>
71
- <TooltipProvider>
72
- <ClientOnly>
73
- <Toaster />
74
- <CommandDialog
75
- v-model:open="ui.isCommandPaletteOpen"
76
- >
77
- <CommandInput :placeholder="t('search')" />
78
- <CommandList>
79
- <CommandEmpty as-child>
80
- <section class="h-32 flex flex-col text-lg items-center justify-center gap-2 select-none">
81
- <Icon
82
- icon="fluent:app-recent-20-regular"
83
- class="text-zinc-400 text-2xl!"
84
- />
85
- <p class="text-zinc-500">
86
- {{ t("command-palette-empty") }}
87
- </p>
88
- </section>
89
- </CommandEmpty>
90
-
91
- <template
92
- v-for="command in props.commands"
93
- :key="command.id"
94
- >
95
- <CommandGroup
96
- v-if="'children' in command"
97
- :heading="command.title"
98
- >
99
- <CommandItem
100
- v-for="child in command.children.filter((child2) => !child2.hidden)"
101
- :key="child.id"
102
- :value="child.id"
103
- :disabled="child.disabled"
104
- @select="child.effect?.pipe(Effect.tap(() => {
105
- ui.isCommandPaletteOpen = false;
106
- })).pipe(Effect.runPromise)"
107
- >
108
- <span>{{ child.title }}</span>
109
- <span class="sr-only">
110
- {{ child.keywords?.join(" ") }}
111
- </span>
112
- </CommandItem>
113
- </CommandGroup>
114
- <CommandGroup v-else>
115
- <CommandItem
116
- :value="command.id"
117
- :disabled="command.disabled"
118
- @select="command.effect?.pipe(Effect.tap(() => {
119
- ui.isCommandPaletteOpen = false;
120
- })).pipe(Effect.runPromise)"
121
- >
122
- <span>{{ command.title }}</span>
123
- <span class="sr-only">
124
- {{ command.keywords?.join(" ") }}
125
- </span>
126
- </CommandItem>
127
- </CommandGroup>
128
- </template>
129
-
130
- <template
131
- v-for="navigation in props.sidebar"
132
- :key="navigation.id"
133
- >
134
- <CommandGroup
135
- v-if="'children' in navigation"
136
- :heading="navigation.title"
137
- >
138
- <CommandItem
139
- v-for="menu in navigation.children"
140
- :key="menu.id"
141
- :value="menu.id"
142
- @select="$router.replace(menu.route)"
143
- >
144
- <span>{{ menu.title }}</span>
145
- </CommandItem>
146
- </CommandGroup>
147
- <CommandGroup v-else>
148
- <CommandItem
149
- :value="navigation.id"
150
- @select="$router.replace(navigation.route)"
151
- >
152
- <span>{{ navigation.title }}</span>
153
- </CommandItem>
154
- </CommandGroup>
155
- </template>
156
- </CommandList>
157
- </CommandDialog>
158
- </ClientOnly>
159
-
160
- <main class="h-screen w-screen flex flex-col overflow-hidden">
161
- <header class="bg-(--primary) h-12 w-full flex items-center justify-between px-4 gap-4">
162
- <Logo />
163
- <slot name="menu" />
164
- <span class="flex-1" />
165
- <DropdownMenu
166
- v-model:open="ui.isProfileDropdownOpen"
167
- :modal="false"
168
- @update:open="ui.isProfileDropdownOpen = $event"
169
- >
170
- <DropdownMenuTrigger as-child>
171
- <button
172
- type="button"
173
- class="text-white text-sm cursor-pointer appearance-none outline-none py-2 px-3 rounded hover:bg-white/10"
174
- @pointerenter="stopProfileCloseTimer();
175
- ui.isProfileDropdownOpen = true"
176
- @pointerleave="stopProfileCloseTimer();
177
- startProfileCloseTimer()"
178
- @click.prevent="stopProfileCloseTimer();
179
- ui.isProfileDropdownOpen = true"
180
- >
181
- <slot name="profile" />
182
- </button>
183
- </DropdownMenuTrigger>
184
- <DropdownMenuContent
185
- class="min-w-56"
186
- align="end"
187
- @pointerenter="stopProfileCloseTimer()"
188
- @pointerleave="stopProfileCloseTimer();
189
- startProfileCloseTimer()"
190
- >
191
- <template
192
- v-for="command in props.commands"
193
- :key="command.id"
194
- >
195
- <template v-if="'children' in command && command.children.some((child2) => !child2.hidden)">
196
- <DropdownMenuLabel>
197
- {{ command.title }}
198
- </DropdownMenuLabel>
199
- <DropdownMenuGroup>
200
- <template
201
- v-for="child in command.children"
202
- :key="child.id"
203
- >
204
- <DropdownMenuItem
205
- v-if="!child.hidden"
206
- :disabled="child.disabled"
207
- @select="child.effect?.pipe(Effect.runPromise)"
208
- >
209
- <Icon
210
- v-if="child.icon"
211
- :icon="child.icon"
212
- />
213
- {{ child.title }}
214
- </DropdownMenuItem>
215
- </template>
216
- </DropdownMenuGroup>
217
- <DropdownMenuSeparator />
218
- </template>
219
- <DropdownMenuItem
220
- v-else-if="!('children' in command) && !command.hidden"
221
- :disabled="command.disabled"
222
- @select="command.effect?.pipe(Effect.runPromise)"
223
- >
224
- <Icon
225
- v-if="command.icon"
226
- :icon="command.icon"
227
- />
228
- {{ command.title }}
229
- </DropdownMenuItem>
230
- </template>
231
- <DropdownMenuItem
232
- @select="logout"
233
- >
234
- <Icon
235
- icon="fluent:sign-out-20-regular"
236
- />
237
- {{ t("logout") }}
238
- </DropdownMenuItem>
239
- <DropdownMenuSeparator v-if="props.commands?.some((command2) => 'children' in command2 ? command2.children.some((child2) => !child2.hidden) : !command2.hidden)" />
240
- <DropdownMenuItem disabled>
241
- <Icon icon="fluent:history-20-regular" />
242
- {{ t("build") }}
243
- <code class="uppercase">{{ $dsl.evaluate`has(git.commit) && git.commit.size() > 0 ? git.commit.slice(0, 7) : 'development'`() }}</code>
244
- </DropdownMenuItem>
245
- </DropdownMenuContent>
246
- </DropdownMenu>
247
- </header>
248
- <main class="flex-1 flex w-full overflow-hidden">
249
- <SidebarProvider
250
- default-open
251
- class="w-fit"
252
- :style="{
253
- '--sidebar-width': '13rem'
254
- }"
255
- >
256
- <Sidebar
257
- collapsible="icon"
258
- class="sticky h-full"
259
- >
260
- <SidebarContent class="gap-2 py-1">
261
- <template
262
- v-for="group in navigations"
263
- :key="group.id"
264
- >
265
- <Collapsible
266
- v-if="'children' in group"
267
- class="group/collapsible"
268
- >
269
- <SidebarGroup>
270
- <SidebarGroupLabel
271
- as-child
272
- class="group/label text-sm text-zinc-700 hover:bg-zinc-100 hover:text-zinc-900"
273
- >
274
- <CollapsibleTrigger>
275
- <Icon
276
- v-if="group.icon"
277
- :icon="group.icon"
278
- />
279
- {{ group.title }}
280
- <Icon
281
- icon="fluent:chevron-right-20-regular"
282
- class="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90"
283
- />
284
- </CollapsibleTrigger>
285
- </SidebarGroupLabel>
286
- <CollapsibleContent class="overflow-hidden data-[state=open]:overflow-visible data-[state=open]:h-auto">
287
- <SidebarGroupContent>
288
- <SidebarMenu class="pl-4">
289
- <SidebarMenuItem
290
- v-for="menu in group.children"
291
- :key="menu.id"
292
- >
293
- <SidebarMenuButton
294
- v-if="'route' in menu"
295
- as-child
296
- :is-active="active === menu.route"
297
- >
298
- <button
299
- type="button"
300
- @click="active = menu.route"
301
- >
302
- <Icon
303
- v-if="menu.icon"
304
- :icon="menu.icon"
305
- />
306
- {{ menu.title }}
307
- </button>
308
- </SidebarMenuButton>
309
- <SidebarMenuAction
310
- v-if="canBeNavigationFavorited(menu, group.id)"
311
- :show-on-hover="!isNavigationFavorited(menu, group.id)"
312
- class="text-yellow-500!"
313
- @click.stop="toggleNavigationFavorite(menu, group.id)"
314
- >
315
- <Icon
316
- :icon="isNavigationFavorited(menu, group.id) ? 'fluent:star-20-filled' : 'fluent:star-20-regular'"
317
- />
318
- </SidebarMenuAction>
319
- </SidebarMenuItem>
320
- </SidebarMenu>
321
- </SidebarGroupContent>
322
- </CollapsibleContent>
323
- </SidebarGroup>
324
- </Collapsible>
325
- <template v-else-if="'route' in group">
326
- <SidebarGroup>
327
- <SidebarGroupContent>
328
- <SidebarMenu>
329
- <SidebarMenuItem>
330
- <SidebarMenuButton
331
- as-child
332
- :is-active="active === group.route"
333
- >
334
- <button
335
- type="button"
336
- @click="active = group.route"
337
- >
338
- <Icon
339
- v-if="group.icon"
340
- :icon="group.icon"
341
- />
342
- {{ group.title }}
343
- </button>
344
- </SidebarMenuButton>
345
- </SidebarMenuItem>
346
- </SidebarMenu>
347
- </SidebarGroupContent>
348
- </SidebarGroup>
349
- </template>
350
- </template>
351
- </SidebarContent>
352
- </Sidebar>
353
- </SidebarProvider>
354
- <main class="flex-1 flex flex-col bg-zinc-100 overflow-hidden">
355
- <nav class="bg-white p-1 border-b border-zinc-100 h-10 flex items-center justify-start gap-1 overflow-x-auto min-w-0">
356
- <div
357
- v-for="tab in tabs"
358
- :key="tab"
359
- :class="[
360
- 'h-8 max-w-60 border rounded px-2 text-sm flex items-center gap-2 shrink-0 min-w-0 transition-colors',
361
- active === tab ? 'text-(--primary) border-(--primary) bg-cyan-50' : 'text-zinc-600 border-zinc-200 hover:text-zinc-900 hover:border-zinc-300'
362
- ]"
363
- >
364
- <button
365
- type="button"
366
- class="truncate cursor-pointer"
367
- @click="active = tab"
368
- >
369
- {{ nameOf(tab) }}
370
- </button>
371
- <button
372
- v-if="tabs.size !== 1"
373
- type="button"
374
- class="cursor-pointer text-zinc-500 hover:text-zinc-900"
375
- @click.stop="close(tab)"
376
- >
377
- <Icon icon="fluent:dismiss-20-regular" />
378
- </button>
379
- </div>
380
- </nav>
381
- <main class="m-2 flex-1 p-1 bg-(--workspace) border border-zinc-100 rounded overflow-hidden">
382
- <slot />
383
- </main>
384
- </main>
385
- </main>
386
- </main>
387
- </TooltipProvider>
14
+ <UiApp
15
+ v-bind="{ ...props, ...$attrs }"
16
+ >
17
+ <template
18
+ v-for="(_, slotName) in $slots"
19
+ #[slotName]="slotProps"
20
+ >
21
+ <slot
22
+ :name="slotName"
23
+ v-bind="slotProps ?? {}"
24
+ />
25
+ </template>
26
+ </UiApp>
388
27
  </template>
389
-
390
- <i18n lang="json">
391
- {
392
- "zh": {
393
- "command-palette-empty": "无搜索结果",
394
- "search": "搜索",
395
- "logout": "退出登录",
396
- "build": "构建",
397
- "navigation": "导航",
398
- "profile": "个人信息",
399
- "favorites": "收藏"
400
- },
401
- "ja": {
402
- "command-palette-empty": "結果はありません",
403
- "search": "検索",
404
- "logout": "ログアウト",
405
- "build": "ビルド",
406
- "navigation": "ナビゲーション",
407
- "profile": "プロフィール",
408
- "favorites": "お気に入り"
409
- },
410
- "en": {
411
- "command-palette-empty": "No results",
412
- "search": "Search",
413
- "logout": "Logout",
414
- "build": "Build",
415
- "navigation": "Navigation",
416
- "profile": "Profile",
417
- "favorites": "Favorites"
418
- }
419
- }
420
- </i18n>
@@ -1,13 +1,14 @@
1
1
  import type { Scope } from 'effect';
2
- import { Effect } from 'effect';
3
- import { type Sidebar as SidebarType } from '../composables/useNavigationTabs.js';
2
+ import type { Sidebar as SidebarType } from '../composables/useNavigationTabs.js';
3
+ type CommandEffect = import('effect').Effect.Effect<void>;
4
+ type DslEffect = import('effect').Effect.Effect<Record<string, unknown>, never, Scope.Scope>;
4
5
  type ProfileCommandInputItem = Readonly<{
5
6
  id: string | number;
6
7
  title: string;
7
8
  icon?: string;
8
9
  hidden?: boolean;
9
10
  disabled?: boolean;
10
- effect?: Effect.Effect<void>;
11
+ effect?: CommandEffect;
11
12
  keywords?: Array<string>;
12
13
  }>;
13
14
  type ProfileCommandInputGroup = Readonly<{
@@ -17,65 +18,13 @@ type ProfileCommandInputGroup = Readonly<{
17
18
  children: Array<ProfileCommandInputItem>;
18
19
  }>;
19
20
  type __VLS_Props = {
20
- /**
21
- * 应用的全局 DSL(CEL)执行上下文。传入一个 Effect,在应用启动时运行一次;
22
- * 其解析结果(一个 record)会被永久设为全局上下文,供后续所有 CEL 求值(如 `$dsl.evaluate`)使用。
23
- *
24
- * 应用会等待该 effect 解析完成后才渲染;在整个应用生命周期内只会执行一次。
25
- * 若未传入 `dsl`,全局上下文将被设为 `{}`。
26
- *
27
- * 适用于需要在首屏前就确定的、会话级稳定数据,例如:当前用户信息、用户所属组、
28
- * 用户菜单列表、用户权限(或权限模块)等。此处加载的数据在整个应用内可通过 CEL 访问
29
- *(如 `user`、`menu`、`permissions`)。强调「会话级」稳定即可,不必永久不变。
30
- *
31
- * 重要约束:
32
- * - 加载时间至关重要:在该 effect 解析前,整应用不会加载,用户会看到白屏,因此必须保持非常快
33
- * (如减少请求、缓存或并行拉取)。
34
- * - 这是有意为之的权衡:菜单、用户等关键数据必须在此加载,否则可能出现空菜单、无用户等异常表现。
35
- * - 该 effect 不得抛错(类型为 `never`):任何失败(如网络)应在 effect 内部处理,
36
- * 返回空对象或安全默认值,保证应用仍能正常启动并得到一致的全局上下文。
37
- *
38
- * 返回的 `Record<string, unknown>` 会在通过 `$dsl.evaluate` 求值 CEL 表达式时,
39
- * 与运行时上下文(如 `now`、`today` 及调用处传入的 context)合并使用。
40
- *
41
- * @example 最小示例:返回静态对象,键可在 CEL 中直接使用
42
- * dsl: Effect.succeed({ hello: 'world' })
43
- * // 之后在模板或逻辑中:$dsl.evaluate`hello`() 得到 'world'
44
- *
45
- * @example 实际场景:拉取会话数据(用户、菜单、权限)并返回,供 CEL 使用
46
- * dsl: Effect.gen(function* () {
47
- * const [user, menu, permissions] = yield* Effect.all([
48
- * fetchUser().pipe(Effect.catchAll(() => Effect.succeed({ name: '', id: '' }))),
49
- * fetchMenu().pipe(Effect.catchAll(() => Effect.succeed([]))),
50
- * fetchPermissions().pipe(Effect.catchAll(() => Effect.succeed({ canEdit: false }))),
51
- * ])
52
- * return { user, menu, permissions }
53
- * })
54
- * // CEL 中可访问 user.name、permissions.canEdit 等;失败时在 effect 内兜底,不抛错
55
- */
56
- dsl?: Effect.Effect<Record<string, unknown>, never, Scope.Scope>;
57
- /**
58
- * Sidebar config.
59
- *
60
- * `menus` is structured navigation data.
61
- */
21
+ dsl?: DslEffect;
62
22
  sidebar?: SidebarType;
63
- /**
64
- * Profile command config.
65
- *
66
- * Structured command entries for profile menu and command palette.
67
- */
68
23
  commands?: Array<ProfileCommandInputItem | ProfileCommandInputGroup>;
69
- read?: <T>(identity: string) => Effect.Effect<T>;
70
- write?: <T>(identity: string, value: T) => Effect.Effect<void>;
71
24
  };
72
- declare var __VLS_108: {}, __VLS_124: {}, __VLS_347: {};
25
+ declare var __VLS_10: string, __VLS_11: any;
73
26
  type __VLS_Slots = {} & {
74
- menu?: (props: typeof __VLS_108) => any;
75
- } & {
76
- profile?: (props: typeof __VLS_124) => any;
77
- } & {
78
- default?: (props: typeof __VLS_347) => any;
27
+ [K in NonNullable<typeof __VLS_10>]?: (props: typeof __VLS_11) => any;
79
28
  };
80
29
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
81
30
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;