@poveste/app 0.13.0 → 0.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 (33) hide show
  1. package/dist/bundled/App.vue_vue_type_script_setup_true_lang.js +25 -33
  2. package/dist/bundled/app.css +3 -9
  3. package/dist/bundled/components/base/BaseListItemLink.js +6 -3
  4. package/dist/bundled/components/base/BaseListItemLink.vue_vue_type_script_lang.js +10 -4
  5. package/dist/bundled/components/base/BaseOverflowTab.js +6 -3
  6. package/dist/bundled/components/base/BaseOverflowTab.vue_vue_type_script_lang.js +4 -0
  7. package/dist/bundled/components/base/BaseTab.js +6 -3
  8. package/dist/bundled/components/base/BaseTab.vue_vue_type_script_lang.js +4 -0
  9. package/dist/bundled/components/panel/PaneTabs.vue_vue_type_script_setup_true_lang.js +4 -4
  10. package/dist/bundled/components/panel/StorySourceCode.js +1 -1
  11. package/dist/bundled/components/panel/StorySourceCode.vue_vue_type_script_setup_true_lang.js +3 -3
  12. package/dist/bundled/components/story/StoryVariantSingle.js +1 -1
  13. package/dist/bundled/components/story/StoryVariantSingle.vue_vue_type_script_setup_true_lang.js +21 -33
  14. package/dist/bundled/components/story/StoryVariantSingleView.vue_vue_type_script_setup_true_lang.js +1 -1
  15. package/dist/bundled/components/toolbar/ToolbarBackground.js +1 -3
  16. package/dist/bundled/components/toolbar/ToolbarBackground.vue_vue_type_script_setup_true_lang.js +1 -5
  17. package/dist/bundled/util/highlighter.js +1 -1
  18. package/dist/bundled/util/mapping.js +5 -1
  19. package/dist/style.css +14 -2
  20. package/package.json +7 -5
  21. package/src/app/App.vue +30 -26
  22. package/src/app/components/base/BaseListItemLink.vue +12 -1
  23. package/src/app/components/base/BaseOverflowTab.vue +12 -1
  24. package/src/app/components/base/BaseTab.vue +12 -1
  25. package/src/app/components/command/CommandPrompts.vue +9 -1
  26. package/src/app/components/panel/PaneTabs.vue +4 -4
  27. package/src/app/components/panel/StorySourceCode.vue +5 -5
  28. package/src/app/components/story/StoryVariantSingle.vue +44 -52
  29. package/src/app/components/story/StoryVariantSingleView.vue +1 -1
  30. package/src/app/components/toolbar/ToolbarBackground.vue +0 -7
  31. package/src/app/components/tree/StoryGroup.vue +1 -1
  32. package/src/app/util/highlighter.ts +9 -1
  33. package/src/app/util/mapping.ts +5 -1
@@ -18,7 +18,7 @@ import SearchModal_default from "./components/search/SearchModal.js";
18
18
  import GenericMountStory_default from "./components/story/GenericMountStory.js";
19
19
  import { mapFile } from "./util/mapping.js";
20
20
  import { useTitle } from "@poveste/vendors/vue-use";
21
- import { Fragment, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, normalizeStyle, onMounted, openBlock, ref, resolveComponent, toDisplayString, unref, watch, withCtx } from "@poveste/vendors/vue";
21
+ import { Fragment, Transition, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, onMounted, openBlock, ref, resolveComponent, toDisplayString, unref, watch, withCtx } from "@poveste/vendors/vue";
22
22
  import { files, onUpdate, tree } from "virtual:$poveste-stories";
23
23
  //#region src/app/App.vue?vue&type=script&setup=true&lang.ts
24
24
  var _hoisted_1 = { class: "poveste-app-root h-full" };
@@ -26,22 +26,17 @@ var _hoisted_2 = {
26
26
  key: 0,
27
27
  class: "poveste-app hidden"
28
28
  };
29
- var _hoisted_3 = {
30
- key: 0,
31
- class: "h-full flex flex-col divide-y divide-gray-100 dark:divide-gray-800"
32
- };
33
- var _hoisted_4 = { class: "flex items-center gap-2 pr-4" };
34
- var _hoisted_5 = { class: "grow flex flex-col min-h-0" };
35
- var _hoisted_6 = {
36
- key: 0,
29
+ var _hoisted_3 = { class: "flex items-center gap-2 pr-4" };
30
+ var _hoisted_4 = {
31
+ key: 1,
37
32
  class: "sr-only"
38
33
  };
39
- var _hoisted_7 = { class: "flex flex-col h-full bg-gray-100 dark:bg-gray-750 __poveste-pane-shadow-from-right" };
40
- var _hoisted_8 = {
34
+ var _hoisted_5 = { class: "flex flex-col h-full bg-gray-100 dark:bg-gray-750 __poveste-pane-shadow-from-right" };
35
+ var _hoisted_6 = {
41
36
  "aria-label": "Stories",
42
37
  class: "flex-1 flex flex-col min-h-0"
43
38
  };
44
- var _hoisted_9 = { class: "flex flex-col h-full" };
39
+ var _hoisted_7 = { class: "flex flex-col h-full" };
45
40
  var App_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
46
41
  name: "PovesteApp",
47
42
  setup(__props) {
@@ -114,48 +109,45 @@ var App_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompon
114
109
  class: "h-screen bg-gray-100 dark:bg-gray-750 dark:text-gray-100",
115
110
  style: normalizeStyle({ opacity: mounted.value ? 1 : 0 })
116
111
  }, [
117
- unref(isMobile) ? (openBlock(), createElementBlock("div", _hoisted_3, [
118
- createElementVNode("div", _hoisted_4, [createVNode(AppHeader_default, { class: "flex-1" }), createVNode(AppActions_default, {
119
- class: "flex-none",
120
- onLayout: _cache[0] || (_cache[0] = ($event) => isLayoutOpen.value = true),
121
- onSearch: _cache[1] || (_cache[1] = ($event) => isSearchOpen.value = true)
122
- })]),
123
- createVNode(Breadcrumb_default, {
124
- tree: tree$1.value,
125
- stories: stories.value
126
- }, null, 8, ["tree", "stories"]),
127
- createElementVNode("main", _hoisted_5, [createVNode(_component_RouterView, { class: "grow" })])
128
- ])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [!storyListVisible.value ? (openBlock(), createElementBlock("header", _hoisted_6, [createElementVNode("h1", null, toDisplayString(unref(povesteConfig).theme?.title ?? "Poveste"), 1)])) : createCommentVNode("", true), createVNode(BaseSplitPane_default, {
112
+ createElementVNode("div", { class: normalizeClass(["h-full flex flex-col", { "divide-y divide-gray-100 dark:divide-gray-800": unref(isMobile) }]) }, [unref(isMobile) ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("div", _hoisted_3, [createVNode(AppHeader_default, { class: "flex-1" }), createVNode(AppActions_default, {
113
+ class: "flex-none",
114
+ onLayout: _cache[0] || (_cache[0] = ($event) => isLayoutOpen.value = true),
115
+ onSearch: _cache[1] || (_cache[1] = ($event) => isSearchOpen.value = true)
116
+ })]), createVNode(Breadcrumb_default, {
117
+ tree: tree$1.value,
118
+ stories: stories.value
119
+ }, null, 8, ["tree", "stories"])], 64)) : !storyListVisible.value ? (openBlock(), createElementBlock("header", _hoisted_4, [createElementVNode("h1", null, toDisplayString(unref(povesteConfig).theme?.title ?? "Poveste"), 1)])) : createCommentVNode("", true), createVNode(BaseSplitPane_default, {
129
120
  "save-id": "main-horiz",
130
121
  min: 5,
131
122
  max: 50,
132
123
  "default-split": 15,
133
- "show-first": storyListVisible.value,
134
- class: "h-full"
124
+ "show-first": !unref(isMobile) && storyListVisible.value,
125
+ class: "flex-1 min-h-0"
135
126
  }, {
136
- first: withCtx(() => [createElementVNode("div", _hoisted_7, [createVNode(AppHeader_default, { class: "flex-none" }), createElementVNode("nav", _hoisted_8, [createVNode(StoryList_default, {
127
+ first: withCtx(() => [createElementVNode("div", _hoisted_5, [createVNode(AppHeader_default, { class: "flex-none" }), createElementVNode("nav", _hoisted_6, [createVNode(StoryList_default, {
137
128
  tree: tree$1.value,
138
129
  stories: stories.value,
139
130
  class: "flex-1"
140
131
  }, null, 8, ["tree", "stories"])])])]),
141
- last: withCtx(() => [createElementVNode("main", _hoisted_9, [createVNode(TopBar_default, {
132
+ last: withCtx(() => [createElementVNode("main", _hoisted_7, [!unref(isMobile) ? (openBlock(), createBlock(TopBar_default, {
133
+ key: 0,
142
134
  onLayout: _cache[2] || (_cache[2] = ($event) => isLayoutOpen.value = true),
143
135
  onSearch: _cache[3] || (_cache[3] = ($event) => isSearchOpen.value = true)
144
- }), createVNode(_component_RouterView, { class: "flex-1 min-h-0" })])]),
136
+ })) : createCommentVNode("", true), createVNode(_component_RouterView, { class: "flex-1 min-h-0" })])]),
145
137
  _: 1
146
- }, 8, ["show-first"])], 64)),
138
+ }, 8, ["show-first"])], 2),
147
139
  !unref(isMobile) ? (openBlock(), createBlock(LayoutModal_default, {
148
- key: 2,
140
+ key: 0,
149
141
  shown: isLayoutOpen.value,
150
142
  onClose: _cache[4] || (_cache[4] = ($event) => isLayoutOpen.value = false)
151
143
  }, null, 8, ["shown"])) : createCommentVNode("", true),
152
144
  loadSearch.value ? (openBlock(), createBlock(SearchModal_default, {
153
- key: 3,
145
+ key: 1,
154
146
  shown: isSearchOpen.value,
155
147
  onClose: _cache[5] || (_cache[5] = ($event) => isSearchOpen.value = false)
156
148
  }, null, 8, ["shown"])) : createCommentVNode("", true),
157
149
  _ctx.__POVESTE_DEV__ ? (openBlock(), createBlock(CommandPromptsModal_default, {
158
- key: 4,
150
+ key: 2,
159
151
  shown: unref(commandStore).showPromptsModal,
160
152
  onClose: _cache[6] || (_cache[6] = ($event) => unref(commandStore).showPromptsModal = false)
161
153
  }, null, 8, ["shown"])) : createCommentVNode("", true)
@@ -17,12 +17,6 @@
17
17
  }
18
18
  }
19
19
  @scope (:root) to (.__poveste-render-story:not(.__poveste-render-custom-controls)) {
20
- .bind-preview-bg[data-v-ed785ad4] {
21
- background-color: var(--ca113a48);
22
- color: var(--v0083f4ef);
23
- }
24
- }
25
- @scope (:root) to (.__poveste-render-story:not(.__poveste-render-custom-controls)) {
26
20
  .bind-icon-color[data-v-14aa93ef] {
27
21
  color: var(--b5fb8c94);
28
22
  }
@@ -93,7 +87,7 @@
93
87
  }
94
88
  }
95
89
  @scope (:root) to (.__poveste-render-story:not(.__poveste-render-custom-controls)) {
96
- .__poveste-code-placeholder[data-v-3d88bdb3] {
90
+ .__poveste-code-placeholder[data-v-6de9e107] {
97
91
  color: inherit;
98
92
  font-size: inherit;
99
93
  }
@@ -134,8 +128,8 @@
134
128
  }
135
129
  }
136
130
  @scope (:root) to (.__poveste-render-story:not(.__poveste-render-custom-controls)) {
137
- .bind-icon-color[data-v-6805a444] {
138
- color: var(--v72c6d646);
131
+ .bind-icon-color[data-v-6b31fb1b] {
132
+ color: var(--v0fc28fe3);
139
133
  }
140
134
  }
141
135
  @scope (:root) to (.__poveste-render-story:not(.__poveste-render-custom-controls)) {
@@ -10,16 +10,19 @@ var _hoisted_1 = [
10
10
  ];
11
11
  function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
12
12
  const _component_RouterLink = resolveComponent("RouterLink");
13
- return openBlock(), createBlock(_component_RouterLink, mergeProps({ class: "poveste-base-list-item-link" }, _ctx.$attrs, { custom: "" }), {
13
+ return openBlock(), createBlock(_component_RouterLink, mergeProps({
14
+ to: _ctx.to,
15
+ class: "poveste-base-list-item-link"
16
+ }, _ctx.$attrs, { custom: "" }), {
14
17
  default: withCtx(({ isActive: linkIsActive, href, navigate }) => [createElementVNode("a", {
15
18
  href,
16
19
  "aria-current": (_ctx.isActive != null ? _ctx.isActive : linkIsActive) ? "page" : void 0,
17
- class: normalizeClass(["flex items-center gap-2 text-gray-900 dark:text-gray-100", [_ctx.$attrs.class, (_ctx.isActive != null ? _ctx.isActive : linkIsActive) ? "active bg-primary-500 hover:bg-primary-600 text-white dark:text-black" : "hover:bg-primary-100 dark:hover:bg-primary-900"]]),
20
+ class: normalizeClass(["flex items-center gap-2 text-gray-900 dark:text-gray-100", [_ctx.$attrs.class, (_ctx.isActive != null ? _ctx.isActive : linkIsActive) ? "active bg-primary-700 hover:bg-primary-800 dark:bg-primary-500 dark:hover:bg-primary-600 text-white dark:text-black" : "hover:bg-primary-100 dark:hover:bg-primary-900"]]),
18
21
  onClick: ($event) => _ctx.handleNavigate($event, navigate),
19
22
  onKeyup: [withKeys(($event) => _ctx.handleNavigate($event, navigate), ["enter"]), withKeys(($event) => _ctx.handleNavigate($event, navigate), ["space"])]
20
23
  }, [renderSlot(_ctx.$slots, "default", { active: _ctx.isActive != null ? _ctx.isActive : linkIsActive })], 42, _hoisted_1)]),
21
24
  _: 3
22
- }, 16);
25
+ }, 16, ["to"]);
23
26
  }
24
27
  var BaseListItemLink_default = /*#__PURE__*/ _plugin_vue_export_helper_default(BaseListItemLink_vue_vue_type_script_lang_default, [["render", _sfc_render]]);
25
28
  //#endregion
@@ -2,10 +2,16 @@ import { defineComponent } from "@poveste/vendors/vue";
2
2
  //#region src/app/components/base/BaseListItemLink.vue?vue&type=script&lang.ts
3
3
  var BaseListItemLink_vue_vue_type_script_lang_default = defineComponent({
4
4
  inheritAttrs: false,
5
- props: { isActive: {
6
- type: Boolean,
7
- default: void 0
8
- } },
5
+ props: {
6
+ to: {
7
+ type: [String, Object],
8
+ required: true
9
+ },
10
+ isActive: {
11
+ type: Boolean,
12
+ default: void 0
13
+ }
14
+ },
9
15
  emits: { navigate: () => true },
10
16
  setup(props, { emit }) {
11
17
  function handleNavigate(event, navigate) {
@@ -9,17 +9,20 @@ var _hoisted_2 = {
9
9
  };
10
10
  function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
11
11
  const _component_router_link = resolveComponent("router-link");
12
- return openBlock(), createBlock(_component_router_link, mergeProps({ class: "poveste-base-overflow-tab" }, _ctx.$attrs, { custom: "" }), {
12
+ return openBlock(), createBlock(_component_router_link, mergeProps({
13
+ to: _ctx.to,
14
+ class: "poveste-base-overflow-tab"
15
+ }, _ctx.$attrs, { custom: "" }), {
13
16
  default: withCtx(({ isActive, isExactActive, href, navigate }) => [createElementVNode("a", mergeProps(_ctx.$attrs, {
14
17
  href,
15
- class: ["px-4 h-10 min-w-[150px] inline-flex items-center hover:bg-primary-50 dark:hover:bg-primary-900 relative text-gray-900 dark:text-gray-100", { "text-primary-500 dark:text-primary-400": _ctx.matched != null ? _ctx.matched : _ctx.exact && isExactActive || !_ctx.exact && isActive }],
18
+ class: ["px-4 h-10 min-w-[150px] inline-flex items-center hover:bg-primary-50 dark:hover:bg-primary-900 relative text-gray-900 dark:text-gray-100", { "text-primary-700 dark:text-primary-400": _ctx.matched != null ? _ctx.matched : _ctx.exact && isExactActive || !_ctx.exact && isActive }],
16
19
  onClick: navigate
17
20
  }), [renderSlot(_ctx.$slots, "default"), createVNode(Transition, { name: "__poveste-scale-y" }, {
18
21
  default: withCtx(() => [(_ctx.matched != null ? _ctx.matched : _ctx.exact && isExactActive || !_ctx.exact && isActive) ? (openBlock(), createElementBlock("div", _hoisted_2)) : createCommentVNode("", true)]),
19
22
  _: 2
20
23
  }, 1024)], 16, _hoisted_1)]),
21
24
  _: 3
22
- }, 16);
25
+ }, 16, ["to"]);
23
26
  }
24
27
  var BaseOverflowTab_default = /*#__PURE__*/ _plugin_vue_export_helper_default(BaseOverflowTab_vue_vue_type_script_lang_default, [["render", _sfc_render]]);
25
28
  //#endregion
@@ -3,6 +3,10 @@ import { defineComponent } from "@poveste/vendors/vue";
3
3
  var BaseOverflowTab_vue_vue_type_script_lang_default = defineComponent({
4
4
  inheritAttrs: false,
5
5
  props: {
6
+ to: {
7
+ type: [String, Object],
8
+ required: true
9
+ },
6
10
  exact: {
7
11
  type: Boolean,
8
12
  default: false
@@ -9,17 +9,20 @@ var _hoisted_2 = {
9
9
  };
10
10
  function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
11
11
  const _component_router_link = resolveComponent("router-link");
12
- return openBlock(), createBlock(_component_router_link, mergeProps({ class: "poveste-base-tab" }, _ctx.$attrs, { custom: "" }), {
12
+ return openBlock(), createBlock(_component_router_link, mergeProps({
13
+ to: _ctx.to,
14
+ class: "poveste-base-tab"
15
+ }, _ctx.$attrs, { custom: "" }), {
13
16
  default: withCtx(({ isActive, isExactActive, href, navigate }) => [createElementVNode("a", mergeProps(_ctx.$attrs, {
14
17
  href,
15
- class: ["px-4 h-full inline-flex items-center hover:bg-primary-50 dark:hover:bg-primary-900 relative text-gray-900 dark:text-gray-100", { "text-primary-500 dark:text-primary-400": _ctx.matched != null ? _ctx.matched : _ctx.exact && isExactActive || !_ctx.exact && isActive }],
18
+ class: ["px-4 h-full inline-flex items-center hover:bg-primary-50 dark:hover:bg-primary-900 relative text-gray-900 dark:text-gray-100", { "text-primary-700 dark:text-primary-400": _ctx.matched != null ? _ctx.matched : _ctx.exact && isExactActive || !_ctx.exact && isActive }],
16
19
  onClick: navigate
17
20
  }), [renderSlot(_ctx.$slots, "default"), createVNode(Transition, { name: "__poveste-scale-x" }, {
18
21
  default: withCtx(() => [(_ctx.matched != null ? _ctx.matched : _ctx.exact && isExactActive || !_ctx.exact && isActive) ? (openBlock(), createElementBlock("div", _hoisted_2)) : createCommentVNode("", true)]),
19
22
  _: 2
20
23
  }, 1024)], 16, _hoisted_1)]),
21
24
  _: 3
22
- }, 16);
25
+ }, 16, ["to"]);
23
26
  }
24
27
  var BaseTab_default = /*#__PURE__*/ _plugin_vue_export_helper_default(BaseTab_vue_vue_type_script_lang_default, [["render", _sfc_render]]);
25
28
  //#endregion
@@ -3,6 +3,10 @@ import { defineComponent } from "@poveste/vendors/vue";
3
3
  var BaseTab_vue_vue_type_script_lang_default = defineComponent({
4
4
  inheritAttrs: false,
5
5
  props: {
6
+ to: {
7
+ type: [String, Object],
8
+ required: true
9
+ },
6
10
  exact: {
7
11
  type: Boolean,
8
12
  default: false
@@ -43,7 +43,7 @@ var PaneTabs_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineC
43
43
  }
44
44
  },
45
45
  matched: _ctx.$route.query.tab === "docs",
46
- class: normalizeClass({ "opacity-50": !unref(renderedDoc) })
46
+ class: normalizeClass({ "opacity-70": !unref(renderedDoc) })
47
47
  }, {
48
48
  default: withCtx(() => [..._cache[4] || (_cache[4] = [createTextVNode(" Docs ", -1)])]),
49
49
  _: 1
@@ -61,7 +61,7 @@ var PaneTabs_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineC
61
61
  }
62
62
  },
63
63
  matched: _ctx.$route.query.tab === "events",
64
- class: normalizeClass({ "opacity-50": !hasEvents.value })
64
+ class: normalizeClass({ "opacity-70": !hasEvents.value })
65
65
  }, {
66
66
  default: withCtx(() => [_cache[5] || (_cache[5] = createTextVNode(" Events ", -1)), unref(eventsStore).unseen ? (openBlock(), createBlock(BaseTag_default, { key: 0 }, {
67
67
  default: withCtx(() => [createTextVNode(toDisplayString(unref(eventsStore).unseen <= 99 ? unref(eventsStore).unseen : "99+"), 1)]),
@@ -97,7 +97,7 @@ var PaneTabs_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineC
97
97
  }
98
98
  },
99
99
  matched: _ctx.$route.query.tab === "docs",
100
- class: normalizeClass({ "opacity-50": !unref(renderedDoc) })
100
+ class: normalizeClass({ "opacity-70": !unref(renderedDoc) })
101
101
  }, {
102
102
  default: withCtx(() => [..._cache[1] || (_cache[1] = [createTextVNode(" Docs ", -1)])]),
103
103
  _: 1
@@ -115,7 +115,7 @@ var PaneTabs_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineC
115
115
  }
116
116
  },
117
117
  matched: _ctx.$route.query.tab === "events",
118
- class: normalizeClass({ "opacity-50": !hasEvents.value })
118
+ class: normalizeClass({ "opacity-70": !hasEvents.value })
119
119
  }, {
120
120
  default: withCtx(() => [_cache[2] || (_cache[2] = createTextVNode(" Events ", -1)), unref(eventsStore).unseen ? (openBlock(), createBlock(BaseTag_default, { key: 0 }, {
121
121
  default: withCtx(() => [createTextVNode(toDisplayString(unref(eventsStore).unseen <= 99 ? unref(eventsStore).unseen : "99+"), 1)]),
@@ -2,6 +2,6 @@ import _plugin_vue_export_helper_default from "../../_virtual/_plugin-vue_export
2
2
  import StorySourceCode_vue_vue_type_script_setup_true_lang_default from "./StorySourceCode.vue_vue_type_script_setup_true_lang.js";
3
3
  /* empty css */
4
4
  //#region src/app/components/panel/StorySourceCode.vue
5
- var StorySourceCode_default = /*#__PURE__*/ _plugin_vue_export_helper_default(StorySourceCode_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-3d88bdb3"]]);
5
+ var StorySourceCode_default = /*#__PURE__*/ _plugin_vue_export_helper_default(StorySourceCode_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-6de9e107"]]);
6
6
  //#endregion
7
7
  export { StorySourceCode_default as default };
@@ -77,7 +77,7 @@ var StorySourceCode_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
77
77
  });
78
78
  const sourceHtml = computed(() => displayedSourceCode.value ? highlighter.value?.codeToHtml(displayedSourceCode.value, {
79
79
  lang: "html",
80
- theme: isDark.value ? "github-dark" : "github-light"
80
+ theme: isDark.value ? "github-dark" : "github-light-high-contrast"
81
81
  }) : "");
82
82
  let lastScroll = 0;
83
83
  watch(() => props.variant, () => {
@@ -97,13 +97,13 @@ var StorySourceCode_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
97
97
  _cache[2] || (_cache[2] = createElementVNode("div", { class: "text-gray-900 dark:text-gray-100" }, " Source ", -1)),
98
98
  _cache[3] || (_cache[3] = createElementVNode("div", { class: "flex-1" }, null, -1)),
99
99
  createElementVNode("div", _hoisted_3, [withDirectives((openBlock(), createElementBlock("button", {
100
- class: normalizeClass(["flex items-center gap-1 h-full px-1 bg-gray-500/10 rounded-l transition-all ease-[cubic-bezier(0,1,.6,1)] duration-300 overflow-hidden", [displayedSource.value !== "dynamic" ? "max-w-6 opacity-70" : "max-w-[82px] text-primary-600 dark:text-primary-400", dynamicSourceCode.value ? "cursor-pointer hover:bg-gray-500/30 active:bg-gray-600/50" : "opacity-50"]]),
100
+ class: normalizeClass(["flex items-center gap-1 h-full px-1 bg-gray-500/10 rounded-l transition-all ease-[cubic-bezier(0,1,.6,1)] duration-300 overflow-hidden", [displayedSource.value !== "dynamic" ? "max-w-6 opacity-70" : "max-w-[82px] text-primary-800 dark:text-primary-400", dynamicSourceCode.value ? "cursor-pointer hover:bg-gray-500/30 active:bg-gray-600/50" : "opacity-50"]]),
101
101
  onClick: _cache[0] || (_cache[0] = ($event) => dynamicSourceCode.value && (displayedSource.value = "dynamic"))
102
102
  }, [createVNode(unref(Icon), {
103
103
  icon: "carbon:flash",
104
104
  class: "w-4 h-4 flex-none"
105
105
  }), createElementVNode("span", { class: normalizeClass(["transition-opacity duration-300", { "opacity-0": displayedSource.value !== "dynamic" }]) }, " Dynamic ", 2)], 2)), [[_directive_tooltip, !dynamicSourceCode.value ? "Dynamic source code is not available" : displayedSource.value !== "dynamic" ? "Switch to dynamic source" : null]]), withDirectives((openBlock(), createElementBlock("button", {
106
- class: normalizeClass(["flex items-center gap-1 h-full px-1 bg-gray-500/10 rounded-r transition-all ease-[cubic-bezier(0,1,.6,1)] duration-300 overflow-hidden", [displayedSource.value !== "static" ? "max-w-6 opacity-70" : "max-w-[63px] text-primary-600 dark:text-primary-400", staticSourceCode.value ? "cursor-pointer hover:bg-gray-500/30 active:bg-gray-600/50" : "opacity-50"]]),
106
+ class: normalizeClass(["flex items-center gap-1 h-full px-1 bg-gray-500/10 rounded-r transition-all ease-[cubic-bezier(0,1,.6,1)] duration-300 overflow-hidden", [displayedSource.value !== "static" ? "max-w-6 opacity-70" : "max-w-[63px] text-primary-800 dark:text-primary-400", staticSourceCode.value ? "cursor-pointer hover:bg-gray-500/30 active:bg-gray-600/50" : "opacity-50"]]),
107
107
  onClick: _cache[1] || (_cache[1] = ($event) => staticSourceCode.value && (displayedSource.value = "static"))
108
108
  }, [createVNode(unref(Icon), {
109
109
  icon: "carbon:document",
@@ -2,6 +2,6 @@ import _plugin_vue_export_helper_default from "../../_virtual/_plugin-vue_export
2
2
  import StoryVariantSingle_vue_vue_type_script_setup_true_lang_default from "./StoryVariantSingle.vue_vue_type_script_setup_true_lang.js";
3
3
  /* empty css */
4
4
  //#region src/app/components/story/StoryVariantSingle.vue
5
- var StoryVariantSingle_default = /*#__PURE__*/ _plugin_vue_export_helper_default(StoryVariantSingle_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-6805a444"]]);
5
+ var StoryVariantSingle_default = /*#__PURE__*/ _plugin_vue_export_helper_default(StoryVariantSingle_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-6b31fb1b"]]);
6
6
  //#endregion
7
7
  export { StoryVariantSingle_default as default };
@@ -7,65 +7,53 @@ import StoryVariantSingleView_default from "./StoryVariantSingleView.js";
7
7
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, renderList, toDisplayString, unref, useCssVars, withCtx } from "@poveste/vendors/vue";
8
8
  import { Icon } from "@poveste/vendors/iconify";
9
9
  //#region src/app/components/story/StoryVariantSingle.vue?vue&type=script&setup=true&lang.ts
10
- var _hoisted_1 = {
11
- key: 0,
12
- class: "divide-y divide-gray-100 dark:divide-gray-800 h-full flex flex-col"
13
- };
10
+ var _hoisted_1 = { class: "h-full overflow-y-auto" };
14
11
  var _hoisted_2 = {
15
12
  key: 1,
16
13
  class: "poveste-story-variant-single p-2 h-full __poveste-pane-shadow-from-right"
17
14
  };
18
- var _hoisted_3 = { class: "h-full overflow-y-auto" };
19
- var _hoisted_4 = {
20
- key: 0,
21
- class: "poveste-story-variant-single p-2 h-full __poveste-pane-shadow-from-right"
22
- };
23
15
  var StoryVariantSingle_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
24
16
  __name: "StoryVariantSingle",
25
17
  emits: { openVariantMenu: () => true },
26
18
  setup(__props) {
27
- useCssVars((_ctx) => ({ "v72c6d646": variant.value?.iconColor }));
19
+ useCssVars((_ctx) => ({ "v0fc28fe3": variant.value?.iconColor }));
28
20
  const storyStore = useStoryStore();
29
21
  const hasSingleVariant = computed(() => storyStore.currentStory?.variants.length === 1);
30
22
  const variant = computed(() => storyStore.currentVariant ?? null);
31
23
  const showsPreview = computed(() => !!variant.value || autoSelectsVariant(storyStore.currentStory));
32
24
  return (_ctx, _cache) => {
33
- return unref(isMobile) ? (openBlock(), createElementBlock("div", _hoisted_1, [!hasSingleVariant.value || !variant.value ? (openBlock(), createElementBlock("a", {
34
- key: 0,
35
- class: "px-6 h-12 hover:text-primary-500 dark:hover:text-primary-400 cursor-pointer flex gap-2 flex-wrap w-full items-center flex-none",
36
- onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("openVariantMenu"))
37
- }, [variant.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createVNode(unref(Icon), {
38
- icon: variant.value.icon ?? "carbon:cube",
39
- class: normalizeClass(["w-5 h-5 flex-none", {
40
- "text-gray-500": !variant.value.iconColor,
41
- "bind-icon-color": variant.value.iconColor
42
- }])
43
- }, null, 8, ["icon", "class"]), createTextVNode(" " + toDisplayString(variant.value.title), 1)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createTextVNode(" Select a variant... ")], 64)), createVNode(unref(Icon), {
44
- icon: "carbon:chevron-sort",
45
- class: "w-5 h-5 shrink-0 ml-auto"
46
- })])) : createCommentVNode("", true), showsPreview.value ? (openBlock(), createElementBlock("div", _hoisted_2, [createVNode(StoryVariantSingleView_default, {
47
- variant: variant.value,
48
- story: unref(storyStore).currentStory
49
- }, null, 8, ["variant", "story"])])) : createCommentVNode("", true)])) : (openBlock(), createBlock(BaseSplitPane_default, {
50
- key: 1,
25
+ return openBlock(), createBlock(BaseSplitPane_default, {
51
26
  "save-id": "story-single-main-split",
52
27
  min: 5,
53
28
  max: 40,
54
29
  "default-split": 17,
55
- "show-first": !hasSingleVariant.value
30
+ "show-first": !unref(isMobile) && !hasSingleVariant.value
56
31
  }, {
57
- first: withCtx(() => [createElementVNode("div", _hoisted_3, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(storyStore).currentStory?.variants ?? [], (v, index) => {
32
+ first: withCtx(() => [createElementVNode("div", _hoisted_1, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(storyStore).currentStory?.variants ?? [], (v, index) => {
58
33
  return openBlock(), createBlock(StoryVariantListItem_default, {
59
34
  key: index,
60
35
  variant: v
61
36
  }, null, 8, ["variant"]);
62
37
  }), 128))])]),
63
- last: withCtx(() => [showsPreview.value ? (openBlock(), createElementBlock("div", _hoisted_4, [createVNode(StoryVariantSingleView_default, {
38
+ last: withCtx(() => [createElementVNode("div", { class: normalizeClass(["h-full flex flex-col", { "divide-y divide-gray-100 dark:divide-gray-800": unref(isMobile) }]) }, [unref(isMobile) && (!hasSingleVariant.value || !variant.value) ? (openBlock(), createElementBlock("a", {
39
+ key: 0,
40
+ class: "px-6 h-12 hover:text-primary-500 dark:hover:text-primary-400 cursor-pointer flex gap-2 flex-wrap w-full items-center flex-none",
41
+ onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("openVariantMenu"))
42
+ }, [variant.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createVNode(unref(Icon), {
43
+ icon: variant.value.icon ?? "carbon:cube",
44
+ class: normalizeClass(["w-5 h-5 flex-none", {
45
+ "text-gray-500": !variant.value.iconColor,
46
+ "bind-icon-color": variant.value.iconColor
47
+ }])
48
+ }, null, 8, ["icon", "class"]), createTextVNode(" " + toDisplayString(variant.value.title), 1)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createTextVNode(" Select a variant... ")], 64)), createVNode(unref(Icon), {
49
+ icon: "carbon:chevron-sort",
50
+ class: "w-5 h-5 shrink-0 ml-auto"
51
+ })])) : createCommentVNode("", true), showsPreview.value ? (openBlock(), createElementBlock("div", _hoisted_2, [createVNode(StoryVariantSingleView_default, {
64
52
  variant: variant.value,
65
53
  story: unref(storyStore).currentStory
66
- }, null, 8, ["variant", "story"])])) : createCommentVNode("", true)]),
54
+ }, null, 8, ["variant", "story"])])) : createCommentVNode("", true)], 2)]),
67
55
  _: 1
68
- }, 8, ["show-first"]));
56
+ }, 8, ["show-first"]);
69
57
  };
70
58
  }
71
59
  });
@@ -24,7 +24,7 @@ var StoryVariantSingleView_vue_vue_type_script_setup_true_lang_default = /*@__PU
24
24
  return openBlock(), createElementBlock("div", {
25
25
  class: normalizeClass(["poveste-story-variant-single-view h-full flex flex-col", { invisible: !__props.variant }]),
26
26
  "data-testid": "story-variant-single-view"
27
- }, [shown.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [shown.value.story.layout?.iframe === false ? (openBlock(), createBlock(StoryVariantSinglePreviewNative_default, {
27
+ }, [shown.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [shown.value.story.layout?.type === "single" && shown.value.story.layout.iframe === false ? (openBlock(), createBlock(StoryVariantSinglePreviewNative_default, {
28
28
  key: 0,
29
29
  story: shown.value.story,
30
30
  variant: shown.value.variant
@@ -1,7 +1,5 @@
1
- import _plugin_vue_export_helper_default from "../../_virtual/_plugin-vue_export-helper.js";
2
1
  import ToolbarBackground_vue_vue_type_script_setup_true_lang_default from "./ToolbarBackground.vue_vue_type_script_setup_true_lang.js";
3
- /* empty css */
4
2
  //#region src/app/components/toolbar/ToolbarBackground.vue
5
- var ToolbarBackground_default = /*#__PURE__*/ _plugin_vue_export_helper_default(ToolbarBackground_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-ed785ad4"]]);
3
+ var ToolbarBackground_default = ToolbarBackground_vue_vue_type_script_setup_true_lang_default;
6
4
  //#endregion
7
5
  export { ToolbarBackground_default as default };
@@ -1,7 +1,7 @@
1
1
  import { povesteConfig } from "../../util/config.js";
2
2
  import { usePreviewSettingsStore } from "../../stores/preview-settings.js";
3
3
  import BaseCheckbox_default from "../base/BaseCheckbox.js";
4
- import { Fragment, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, renderList, resolveComponent, resolveDirective, toDisplayString, unref, useCssVars, withCtx, withDirectives } from "@poveste/vendors/vue";
4
+ import { Fragment, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, renderList, resolveComponent, resolveDirective, toDisplayString, unref, withCtx, withDirectives } from "@poveste/vendors/vue";
5
5
  import { Icon } from "@poveste/vendors/iconify";
6
6
  //#region src/app/components/toolbar/ToolbarBackground.vue?vue&type=script&setup=true&lang.ts
7
7
  var _hoisted_1 = { class: "flex items-center gap-1 px-2.5 py-1.5 hover:bg-white/50 dark:hover:bg-white/10 hover:text-primary-500 dark:hover:text-primary-400 cursor-pointer text-gray-900 dark:text-gray-100 transition-colors group" };
@@ -22,10 +22,6 @@ var _hoisted_8 = { key: 0 };
22
22
  var ToolbarBackground_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
23
23
  __name: "ToolbarBackground",
24
24
  setup(__props) {
25
- useCssVars((_ctx) => ({
26
- "ca113a48": unref(settings).backgroundColor,
27
- "v0083f4ef": _ctx.contrastColor
28
- }));
29
25
  const previewSettings = usePreviewSettingsStore();
30
26
  const settings = previewSettings.currentSettings;
31
27
  const colorSchemeOptions = [
@@ -18,7 +18,7 @@ var highlighterPromise;
18
18
  function getHighlighter() {
19
19
  highlighterPromise ??= createHighlighterCore({
20
20
  langs: [import("shiki/langs/html.mjs"), import("shiki/langs/jsx.mjs")],
21
- themes: [import("shiki/themes/github-light.mjs"), import("shiki/themes/github-dark.mjs")],
21
+ themes: [import("shiki/themes/github-light-high-contrast.mjs"), import("shiki/themes/github-dark.mjs")],
22
22
  engine: createOnigurumaEngine(import("shiki/wasm"))
23
23
  }).catch((e) => {
24
24
  highlighterPromise = void 0;
@@ -46,7 +46,11 @@ function mapVariant(variant, existingVariant) {
46
46
  _hPropDefs: {}
47
47
  }),
48
48
  setupApp: null,
49
- slots: () => ({}),
49
+ slots: () => ({
50
+ default: void 0,
51
+ controls: void 0,
52
+ source: void 0
53
+ }),
50
54
  previewReady: false
51
55
  };
52
56
  return result;
package/dist/style.css CHANGED
@@ -1625,6 +1625,9 @@
1625
1625
  background-color: color-mix(in oklab, var(--color-primary-500) 25%, transparent);
1626
1626
  }
1627
1627
  }
1628
+ .bg-primary-700 {
1629
+ background-color: var(--color-primary-700);
1630
+ }
1628
1631
  .bg-transparent {
1629
1632
  background-color: transparent;
1630
1633
  }
@@ -1861,8 +1864,8 @@
1861
1864
  .text-primary-500 {
1862
1865
  color: var(--color-primary-500);
1863
1866
  }
1864
- .text-primary-600 {
1865
- color: var(--color-primary-600);
1867
+ .text-primary-700 {
1868
+ color: var(--color-primary-700);
1866
1869
  }
1867
1870
  .text-primary-800 {
1868
1871
  color: var(--color-primary-800);
@@ -2130,6 +2133,9 @@
2130
2133
  .hover\:bg-primary-600:hover {
2131
2134
  background-color: var(--color-primary-600);
2132
2135
  }
2136
+ .hover\:bg-primary-800:hover {
2137
+ background-color: var(--color-primary-800);
2138
+ }
2133
2139
  .hover\:bg-white\/50:hover {
2134
2140
  background-color: color-mix(in srgb, #fff 50%, transparent);
2135
2141
  }
@@ -2288,6 +2294,9 @@
2288
2294
  .dark\:bg-primary-400:where(.ptw-dark, .ptw-dark *) {
2289
2295
  background-color: var(--color-primary-400);
2290
2296
  }
2297
+ .dark\:bg-primary-500:where(.ptw-dark, .ptw-dark *) {
2298
+ background-color: var(--color-primary-500);
2299
+ }
2291
2300
  .dark\:bg-primary-600:where(.ptw-dark, .ptw-dark *) {
2292
2301
  background-color: var(--color-primary-600);
2293
2302
  }
@@ -2385,6 +2394,9 @@
2385
2394
  .dark\:hover\:bg-gray-800:where(.ptw-dark, .ptw-dark *):hover {
2386
2395
  background-color: var(--color-gray-800);
2387
2396
  }
2397
+ .dark\:hover\:bg-primary-600:where(.ptw-dark, .ptw-dark *):hover {
2398
+ background-color: var(--color-primary-600);
2399
+ }
2388
2400
  .dark\:hover\:bg-primary-700:where(.ptw-dark, .ptw-dark *):hover {
2389
2401
  background-color: var(--color-primary-700);
2390
2402
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@poveste/app",
3
3
  "type": "module",
4
- "version": "0.13.0",
4
+ "version": "0.13.1",
5
5
  "description": "Pre-bundled UI for Poveste",
6
6
  "author": {
7
7
  "name": "Sorin Gitlan",
@@ -38,9 +38,9 @@
38
38
  "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
39
39
  },
40
40
  "dependencies": {
41
- "@poveste/controls": "^0.13.0",
42
- "@poveste/shared": "^0.13.0",
43
- "@poveste/vendors": "^0.13.0",
41
+ "@poveste/controls": "^0.13.1",
42
+ "@poveste/shared": "^0.13.1",
43
+ "@poveste/vendors": "^0.13.1",
44
44
  "fuse.js": "^7.0.0",
45
45
  "shiki": "^3.0.0"
46
46
  },
@@ -67,10 +67,12 @@
67
67
  "typescript": "5.6.3",
68
68
  "vite": "^8.2.0",
69
69
  "vitest": "^4.1.10",
70
- "vue": "^3.5.26"
70
+ "vue": "^3.5.26",
71
+ "vue-tsc": "^2.1.10"
71
72
  },
72
73
  "scripts": {
73
74
  "build": "pnpm run icons && rimraf dist && vite build && pnpm run build:css && node ./scripts/copy.mjs",
75
+ "typecheck": "vue-tsc --noEmit",
74
76
  "build:css": "postcss src/app/style/main.pcss -o ./dist/style.css",
75
77
  "icons": "node ./scripts/icons.mjs",
76
78
  "test": "vitest run",
package/src/app/App.vue CHANGED
@@ -141,52 +141,55 @@ const storyListVisible = computed(() => !!layoutStore.settings.storyListVisible)
141
141
  }"
142
142
  >
143
143
  <div
144
- v-if="isMobile"
145
- class="h-full flex flex-col divide-y divide-gray-100 dark:divide-gray-800"
144
+ class="h-full flex flex-col"
145
+ :class="{ 'divide-y divide-gray-100 dark:divide-gray-800': isMobile }"
146
146
  >
147
- <div class="flex items-center gap-2 pr-4">
148
- <AppHeader class="flex-1" />
149
- <AppActions
150
- class="flex-none"
151
- @layout="isLayoutOpen = true"
152
- @search="isSearchOpen = true"
147
+ <!--
148
+ The mobile chrome is a sibling of `main`, not a child: `AppHeader`
149
+ carries the page's banner and its only `h1`, and a `header` inside
150
+ `main` is neither (#310).
151
+ -->
152
+ <template v-if="isMobile">
153
+ <div class="flex items-center gap-2 pr-4">
154
+ <AppHeader class="flex-1" />
155
+ <AppActions
156
+ class="flex-none"
157
+ @layout="isLayoutOpen = true"
158
+ @search="isSearchOpen = true"
159
+ />
160
+ </div>
161
+ <Breadcrumb
162
+ :tree="tree"
163
+ :stories="stories"
153
164
  />
154
- </div>
155
- <Breadcrumb
156
- :tree="tree"
157
- :stories="stories"
158
- />
159
- <main class="grow flex flex-col min-h-0">
160
- <RouterView class="grow" />
161
- </main>
162
- </div>
165
+ </template>
163
166
 
164
- <template v-else>
165
167
  <!--
166
168
  With the story list hidden `AppHeader` goes with it, taking the page's
167
169
  only `h1` and its banner. A heading has to exist in every layout, and
168
170
  it has to sit inside a landmark, so this stands in for it (#310).
169
171
  -->
170
172
  <header
171
- v-if="!storyListVisible"
173
+ v-else-if="!storyListVisible"
172
174
  class="sr-only"
173
175
  >
174
176
  <h1>{{ povesteConfig.theme?.title ?? 'Poveste' }}</h1>
175
177
  </header>
176
178
 
177
179
  <!--
178
- One split pane whether or not the story list is showing. Two branches
179
- each carrying their own `RouterView` moved the whole view in the tree
180
- when the list was toggled, cold-booting the sandbox under it — the same
181
- remount #328 removed from sidebar clicks (#596).
180
+ One split pane for every layout, mobile included. Each chrome used to
181
+ be a branch carrying its own `RouterView`, so switching between them
182
+ moved the routed view in the tree and cold-booted the sandbox under
183
+ it. The settings toggles were #596; `isMobile` is a live media query,
184
+ so this one fired on a window resize (#600).
182
185
  -->
183
186
  <BaseSplitPane
184
187
  save-id="main-horiz"
185
188
  :min="5"
186
189
  :max="50"
187
190
  :default-split="15"
188
- :show-first="storyListVisible"
189
- class="h-full"
191
+ :show-first="!isMobile && storyListVisible"
192
+ class="flex-1 min-h-0"
190
193
  >
191
194
  <template #first>
192
195
  <div class="flex flex-col h-full bg-gray-100 dark:bg-gray-750 __poveste-pane-shadow-from-right">
@@ -207,6 +210,7 @@ const storyListVisible = computed(() => !!layoutStore.settings.storyListVisible)
207
210
  <template #last>
208
211
  <main class="flex flex-col h-full">
209
212
  <TopBar
213
+ v-if="!isMobile"
210
214
  @layout="isLayoutOpen = true"
211
215
  @search="isSearchOpen = true"
212
216
  />
@@ -214,7 +218,7 @@ const storyListVisible = computed(() => !!layoutStore.settings.storyListVisible)
214
218
  </main>
215
219
  </template>
216
220
  </BaseSplitPane>
217
- </template>
221
+ </div>
218
222
 
219
223
  <LayoutModal
220
224
  v-if="!isMobile"
@@ -1,10 +1,20 @@
1
1
  <script lang="ts">
2
+ import type { PropType } from 'vue'
3
+ import type { RouteLocationRaw } from 'vue-router'
2
4
  import { defineComponent } from 'vue'
3
5
 
4
6
  export default defineComponent({
5
7
  inheritAttrs: false,
6
8
 
7
9
  props: {
10
+ // Declared rather than passed through `$attrs`: with
11
+ // `inheritAttrs: false` the checker cannot see it there, and
12
+ // router-link requires it.
13
+ to: {
14
+ type: [String, Object] as PropType<RouteLocationRaw>,
15
+ required: true,
16
+ },
17
+
8
18
  isActive: {
9
19
  type: Boolean,
10
20
  default: undefined,
@@ -31,6 +41,7 @@ export default defineComponent({
31
41
  <template>
32
42
  <RouterLink
33
43
  v-slot="{ isActive: linkIsActive, href, navigate }"
44
+ :to="to"
34
45
  class="poveste-base-list-item-link"
35
46
  v-bind="$attrs"
36
47
  custom
@@ -42,7 +53,7 @@ export default defineComponent({
42
53
  :class="[
43
54
  $attrs.class,
44
55
  (isActive != null ? isActive : linkIsActive)
45
- ? 'active bg-primary-500 hover:bg-primary-600 text-white dark:text-black'
56
+ ? 'active bg-primary-700 hover:bg-primary-800 dark:bg-primary-500 dark:hover:bg-primary-600 text-white dark:text-black'
46
57
  : 'hover:bg-primary-100 dark:hover:bg-primary-900',
47
58
  ]"
48
59
  @click="handleNavigate($event, navigate)"
@@ -1,10 +1,20 @@
1
1
  <script lang="ts">
2
+ import type { PropType } from 'vue'
3
+ import type { RouteLocationRaw } from 'vue-router'
2
4
  import { defineComponent } from 'vue'
3
5
 
4
6
  export default defineComponent({
5
7
  inheritAttrs: false,
6
8
 
7
9
  props: {
10
+ // Declared rather than passed through `$attrs`: with
11
+ // `inheritAttrs: false` the checker cannot see it there, and
12
+ // router-link requires it.
13
+ to: {
14
+ type: [String, Object] as PropType<RouteLocationRaw>,
15
+ required: true,
16
+ },
17
+
8
18
  exact: {
9
19
  type: Boolean,
10
20
  default: false,
@@ -21,6 +31,7 @@ export default defineComponent({
21
31
  <template>
22
32
  <router-link
23
33
  v-slot="{ isActive, isExactActive, href, navigate }"
34
+ :to="to"
24
35
  class="poveste-base-overflow-tab"
25
36
  v-bind="$attrs"
26
37
  custom
@@ -30,7 +41,7 @@ export default defineComponent({
30
41
  :href="href"
31
42
  class="px-4 h-10 min-w-[150px] inline-flex items-center hover:bg-primary-50 dark:hover:bg-primary-900 relative text-gray-900 dark:text-gray-100"
32
43
  :class="{
33
- 'text-primary-500 dark:text-primary-400': matched != null ? matched : (exact && isExactActive) || (!exact && isActive),
44
+ 'text-primary-700 dark:text-primary-400': matched != null ? matched : (exact && isExactActive) || (!exact && isActive),
34
45
  }"
35
46
  @click="navigate"
36
47
  >
@@ -1,10 +1,20 @@
1
1
  <script lang="ts">
2
+ import type { PropType } from 'vue'
3
+ import type { RouteLocationRaw } from 'vue-router'
2
4
  import { defineComponent } from 'vue'
3
5
 
4
6
  export default defineComponent({
5
7
  inheritAttrs: false,
6
8
 
7
9
  props: {
10
+ // Declared rather than passed through `$attrs`: with
11
+ // `inheritAttrs: false` the checker cannot see it there, and
12
+ // router-link requires it.
13
+ to: {
14
+ type: [String, Object] as PropType<RouteLocationRaw>,
15
+ required: true,
16
+ },
17
+
8
18
  exact: {
9
19
  type: Boolean,
10
20
  default: false,
@@ -21,6 +31,7 @@ export default defineComponent({
21
31
  <template>
22
32
  <router-link
23
33
  v-slot="{ isActive, isExactActive, href, navigate }"
34
+ :to="to"
24
35
  class="poveste-base-tab"
25
36
  v-bind="$attrs"
26
37
  custom
@@ -30,7 +41,7 @@ export default defineComponent({
30
41
  :href="href"
31
42
  class="px-4 h-full inline-flex items-center hover:bg-primary-50 dark:hover:bg-primary-900 relative text-gray-900 dark:text-gray-100"
32
43
  :class="{
33
- 'text-primary-500 dark:text-primary-400': matched != null ? matched : (exact && isExactActive) || (!exact && isActive),
44
+ 'text-primary-700 dark:text-primary-400': matched != null ? matched : (exact && isExactActive) || (!exact && isActive),
34
45
  }"
35
46
  @click="navigate"
36
47
  >
@@ -1,5 +1,6 @@
1
1
  <script lang="ts" setup>
2
2
  import type { ClientCommand } from '@poveste/shared'
3
+ import type { Component } from 'vue'
3
4
  import { nextTick, onMounted, reactive, ref } from 'vue'
4
5
  import { executeCommand, getCommandContext } from '../../util/commands.js'
5
6
  import BaseButton from '../base/BaseButton.vue'
@@ -67,8 +68,15 @@ onMounted(() => {
67
68
  {{ command.label }}
68
69
  </div>
69
70
 
71
+ <!--
72
+ `promptTypes[prompt.type]` resolves to the component whose `prompt` prop
73
+ is that member of the union, but nothing states the correlation and the
74
+ checker cannot infer it. Splitting this into `v-if` branches per type is
75
+ what makes it checkable; that is a refactor of untested UI, so it waits
76
+ for coverage rather than riding along with the type gate (#441).
77
+ -->
70
78
  <component
71
- :is="promptTypes[prompt.type]"
79
+ :is="promptTypes[prompt.type] as Component"
72
80
  v-for="(prompt, index) of command.prompts"
73
81
  :key="prompt.field"
74
82
  ref="promptComps"
@@ -33,7 +33,7 @@ const hasEvents = computed(() => eventsStore.events.length)
33
33
  :to="{ ...$route, query: { ...$route.query, tab: 'docs' } }"
34
34
  :matched="$route.query.tab === 'docs'"
35
35
  :class="{
36
- 'opacity-50': !renderedDoc,
36
+ 'opacity-70': !renderedDoc,
37
37
  }"
38
38
  >
39
39
  Docs
@@ -42,7 +42,7 @@ const hasEvents = computed(() => eventsStore.events.length)
42
42
  :to="{ ...$route, query: { ...$route.query, tab: 'events' } }"
43
43
  :matched="$route.query.tab === 'events'"
44
44
  :class="{
45
- 'opacity-50': !hasEvents,
45
+ 'opacity-70': !hasEvents,
46
46
  }"
47
47
  >
48
48
  Events
@@ -62,7 +62,7 @@ const hasEvents = computed(() => eventsStore.events.length)
62
62
  :to="{ ...$route, query: { ...$route.query, tab: 'docs' } }"
63
63
  :matched="$route.query.tab === 'docs'"
64
64
  :class="{
65
- 'opacity-50': !renderedDoc,
65
+ 'opacity-70': !renderedDoc,
66
66
  }"
67
67
  >
68
68
  Docs
@@ -71,7 +71,7 @@ const hasEvents = computed(() => eventsStore.events.length)
71
71
  :to="{ ...$route, query: { ...$route.query, tab: 'events' } }"
72
72
  :matched="$route.query.tab === 'events'"
73
73
  :class="{
74
- 'opacity-50': !hasEvents,
74
+ 'opacity-70': !hasEvents,
75
75
  }"
76
76
  >
77
77
  Events
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import type { Highlighter } from 'shiki'
2
+ import type { HighlighterCore } from 'shiki/core'
3
3
  import type { Story, Variant } from '../../types'
4
4
  import { Icon } from '@iconify/vue'
5
5
  import { HstCopyIcon } from '@poveste/controls'
@@ -25,7 +25,7 @@ watchEffect(async () => {
25
25
  }
26
26
  })
27
27
 
28
- const highlighter = shallowRef<Highlighter>()
28
+ const highlighter = shallowRef<HighlighterCore>()
29
29
 
30
30
  const dynamicSourceCode = ref('')
31
31
  const error = ref<string>(null)
@@ -103,7 +103,7 @@ onMounted(async () => {
103
103
  const sourceHtml = computed(() => displayedSourceCode.value
104
104
  ? highlighter.value?.codeToHtml(displayedSourceCode.value, {
105
105
  lang: 'html',
106
- theme: isDark.value ? 'github-dark' : 'github-light',
106
+ theme: isDark.value ? 'github-dark' : 'github-light-high-contrast',
107
107
  })
108
108
  : '')
109
109
 
@@ -152,7 +152,7 @@ watch(sourceHtml, async () => {
152
152
  v-tooltip="!dynamicSourceCode ? 'Dynamic source code is not available' : displayedSource !== 'dynamic' ? 'Switch to dynamic source' : null"
153
153
  class="flex items-center gap-1 h-full px-1 bg-gray-500/10 rounded-l transition-all ease-[cubic-bezier(0,1,.6,1)] duration-300 overflow-hidden"
154
154
  :class="[
155
- displayedSource !== 'dynamic' ? 'max-w-6 opacity-70' : 'max-w-[82px] text-primary-600 dark:text-primary-400',
155
+ displayedSource !== 'dynamic' ? 'max-w-6 opacity-70' : 'max-w-[82px] text-primary-800 dark:text-primary-400',
156
156
  dynamicSourceCode ? 'cursor-pointer hover:bg-gray-500/30 active:bg-gray-600/50' : 'opacity-50',
157
157
  ]"
158
158
  @click="dynamicSourceCode && (displayedSource = 'dynamic')"
@@ -174,7 +174,7 @@ watch(sourceHtml, async () => {
174
174
  v-tooltip="!staticSourceCode ? 'Static source code is not available' : displayedSource !== 'static' ? 'Switch to static source' : null"
175
175
  class="flex items-center gap-1 h-full px-1 bg-gray-500/10 rounded-r transition-all ease-[cubic-bezier(0,1,.6,1)] duration-300 overflow-hidden"
176
176
  :class="[
177
- displayedSource !== 'static' ? 'max-w-6 opacity-70' : 'max-w-[63px] text-primary-600 dark:text-primary-400',
177
+ displayedSource !== 'static' ? 'max-w-6 opacity-70' : 'max-w-[63px] text-primary-800 dark:text-primary-400',
178
178
  staticSourceCode ? 'cursor-pointer hover:bg-gray-500/30 active:bg-gray-600/50' : 'opacity-50',
179
179
  ]"
180
180
  @click="staticSourceCode && (displayedSource = 'static')"
@@ -27,59 +27,19 @@ const showsPreview = computed(() => !!variant.value || autoSelectsVariant(storyS
27
27
  </script>
28
28
 
29
29
  <template>
30
- <div
31
- v-if="isMobile"
32
- class="divide-y divide-gray-100 dark:divide-gray-800 h-full flex flex-col"
33
- >
34
- <a
35
- v-if="!hasSingleVariant || !variant"
36
- class="px-6 h-12 hover:text-primary-500 dark:hover:text-primary-400 cursor-pointer flex gap-2 flex-wrap w-full items-center flex-none"
37
- @click="$emit('openVariantMenu')"
38
- >
39
- <template v-if="variant">
40
- <Icon
41
- :icon="variant.icon ?? 'carbon:cube'"
42
- class="w-5 h-5 flex-none"
43
- :class="{
44
- 'text-gray-500': !variant.iconColor,
45
- 'bind-icon-color': variant.iconColor,
46
- }"
47
- />
48
- {{ variant.title }}
49
- </template>
50
- <template v-else>
51
- Select a variant...
52
- </template>
53
-
54
- <Icon
55
- icon="carbon:chevron-sort"
56
- class="w-5 h-5 shrink-0 ml-auto"
57
- />
58
- </a>
59
- <div
60
- v-if="showsPreview"
61
- class="poveste-story-variant-single p-2 h-full __poveste-pane-shadow-from-right"
62
- >
63
- <StoryVariantSingleView
64
- :variant="variant"
65
- :story="storyStore.currentStory"
66
- />
67
- </div>
68
- </div>
69
-
70
30
  <!--
71
- One split pane whether or not there is a list to put in it. A story with a
72
- single variant hides the first pane instead of taking a different branch, so
73
- the preview stays at one position in the tree and survives the move between
74
- a one-variant story and a many-variant one (#328).
31
+ One split pane for every layout. The variant list, the mobile picker row and
32
+ the bare single-variant view used to be three branches each carrying their
33
+ own `StoryVariantSingleView`, so moving between them rebuilt the preview and
34
+ cold-booted its sandbox. `isMobile` is a live media query, so that happened
35
+ on a window resize (#600); the single/many-variant half was #328.
75
36
  -->
76
37
  <BaseSplitPane
77
- v-else
78
38
  save-id="story-single-main-split"
79
39
  :min="5"
80
40
  :max="40"
81
41
  :default-split="17"
82
- :show-first="!hasSingleVariant"
42
+ :show-first="!isMobile && !hasSingleVariant"
83
43
  >
84
44
  <template #first>
85
45
  <div class="h-full overflow-y-auto">
@@ -92,13 +52,45 @@ const showsPreview = computed(() => !!variant.value || autoSelectsVariant(storyS
92
52
  </template>
93
53
  <template #last>
94
54
  <div
95
- v-if="showsPreview"
96
- class="poveste-story-variant-single p-2 h-full __poveste-pane-shadow-from-right"
55
+ class="h-full flex flex-col"
56
+ :class="{ 'divide-y divide-gray-100 dark:divide-gray-800': isMobile }"
97
57
  >
98
- <StoryVariantSingleView
99
- :variant="variant"
100
- :story="storyStore.currentStory"
101
- />
58
+ <!-- Mobile has no room for the list beside the preview, so the variant
59
+ it is showing opens a full-screen overlay instead. -->
60
+ <a
61
+ v-if="isMobile && (!hasSingleVariant || !variant)"
62
+ class="px-6 h-12 hover:text-primary-500 dark:hover:text-primary-400 cursor-pointer flex gap-2 flex-wrap w-full items-center flex-none"
63
+ @click="$emit('openVariantMenu')"
64
+ >
65
+ <template v-if="variant">
66
+ <Icon
67
+ :icon="variant.icon ?? 'carbon:cube'"
68
+ class="w-5 h-5 flex-none"
69
+ :class="{
70
+ 'text-gray-500': !variant.iconColor,
71
+ 'bind-icon-color': variant.iconColor,
72
+ }"
73
+ />
74
+ {{ variant.title }}
75
+ </template>
76
+ <template v-else>
77
+ Select a variant...
78
+ </template>
79
+
80
+ <Icon
81
+ icon="carbon:chevron-sort"
82
+ class="w-5 h-5 shrink-0 ml-auto"
83
+ />
84
+ </a>
85
+ <div
86
+ v-if="showsPreview"
87
+ class="poveste-story-variant-single p-2 h-full __poveste-pane-shadow-from-right"
88
+ >
89
+ <StoryVariantSingleView
90
+ :variant="variant"
91
+ :story="storyStore.currentStory"
92
+ />
93
+ </div>
102
94
  </div>
103
95
  </template>
104
96
  </BaseSplitPane>
@@ -60,7 +60,7 @@ watchEffect(() => {
60
60
  -->
61
61
  <template v-if="shown">
62
62
  <StoryVariantSinglePreviewNative
63
- v-if="shown.story.layout?.iframe === false"
63
+ v-if="shown.story.layout?.type === 'single' && shown.story.layout.iframe === false"
64
64
  :story="shown.story"
65
65
  :variant="shown.variant"
66
66
  />
@@ -109,10 +109,3 @@ const showDropdown = showColorScheme || !!povesteConfig.backgroundPresets.length
109
109
  </template>
110
110
  </VDropdown>
111
111
  </template>
112
-
113
- <style scoped>
114
- .bind-preview-bg {
115
- background-color: v-bind('settings.backgroundColor');
116
- color: v-bind('contrastColor');
117
- }
118
- </style>
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import type { Story, TreeGroup } from '../../types'
2
+ import type { Story, TreeFolder, TreeGroup, TreeLeaf } from '../../types'
3
3
  import { Icon } from '@iconify/vue'
4
4
  import { computed } from 'vue'
5
5
  import { useFolderStore } from '../../stores/folder'
@@ -23,8 +23,16 @@ export function getHighlighter(): Promise<HighlighterCore> {
23
23
  import('shiki/langs/html.mjs'),
24
24
  import('shiki/langs/jsx.mjs'),
25
25
  ],
26
+ /*
27
+ * `github-light-high-contrast`, not `github-light`. The plain one paints
28
+ * keywords at 4.38:1 on the pane background, variables at 3.34 and tag
29
+ * names at 4.43 — three of its twelve token colours miss AA (#533). This is
30
+ * GitHub's own accessible build of the same theme, so code keeps reading the
31
+ * way it did, and the colours are maintained upstream rather than darkened
32
+ * by hand here.
33
+ */
26
34
  themes: [
27
- import('shiki/themes/github-light.mjs'),
35
+ import('shiki/themes/github-light-high-contrast.mjs'),
28
36
  import('shiki/themes/github-dark.mjs'),
29
37
  ],
30
38
  engine: createOnigurumaEngine(import('shiki/wasm')),
@@ -71,7 +71,11 @@ export function mapVariant(variant: Variant, existingVariant?: Variant): Variant
71
71
  _hPropDefs: {},
72
72
  }),
73
73
  setupApp: null,
74
- slots: () => ({}),
74
+ // The three keys `Variant` declares, absent rather than missing: a
75
+ // variant created here defines no slots, and consumers read them
76
+ // with `||`. `Story.slots` is `() => any`, which is why the same
77
+ // literal above needs nothing.
78
+ slots: () => ({ default: undefined, controls: undefined, source: undefined }),
75
79
  previewReady: false,
76
80
  }
77
81
  }