@poveste/app 0.14.0 → 0.15.0
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.
- package/dist/bundled/app.css +26 -26
- package/dist/bundled/components/app/TopBarChipItem.js +1 -1
- package/dist/bundled/components/base/BaseEmpty.js +2 -2
- package/dist/bundled/components/base/BaseOverflowMenu.vue_vue_type_script_setup_true_lang.js +14 -14
- package/dist/bundled/components/base/BaseSelect.vue_vue_type_script_setup_true_lang.js +158 -26
- package/dist/bundled/components/base/BaseSplitPane.js +1 -1
- package/dist/bundled/components/command/PromptSelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/bundled/components/panel/ControlsComponentPropItem.vue_vue_type_script_setup_true_lang.js +20 -14
- package/dist/bundled/components/panel/PaneTabs.vue_vue_type_script_setup_true_lang.js +6 -6
- package/dist/bundled/components/panel/StatePresets.vue_vue_type_script_setup_true_lang.js +78 -49
- package/dist/bundled/components/panel/StorySidePanel.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/bundled/components/panel/StorySourceCode.js +1 -1
- package/dist/bundled/components/panel/StorySourceCode.vue_vue_type_script_setup_true_lang.js +5 -4
- package/dist/bundled/components/search/SearchItemContent.vue_vue_type_script_setup_true_lang.js +2 -1
- package/dist/bundled/components/search/SearchPane.vue_vue_type_script_setup_true_lang.js +1 -2
- package/dist/bundled/components/story/StoryResponsivePreview.js +1 -1
- package/dist/bundled/components/story/StoryResponsivePreview.vue_vue_type_script_setup_true_lang.js +8 -4
- package/dist/bundled/components/story/StoryVariantGridItem.js +1 -1
- package/dist/bundled/components/story/StoryVariantGridItem.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/bundled/components/story/StoryVariantSinglePreviewRemote.vue_vue_type_script_setup_true_lang.js +9 -6
- package/dist/bundled/components/story/StoryView.vue_vue_type_script_setup_true_lang.js +4 -1
- package/dist/bundled/components/toolbar/ToolbarTitle.js +1 -1
- package/dist/bundled/components/toolbar/ToolbarTitle.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/bundled/components/tree/StoryGroup.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/bundled/components/tree/StoryList.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/bundled/components/tree/StoryListFolder.js +1 -1
- package/dist/bundled/components/tree/StoryListFolder.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/bundled/components/tree/StoryListItem.js +1 -1
- package/dist/bundled/components/tree/StoryListItem.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/bundled/sandbox.js +3 -2
- package/dist/bundled/stores/story.js +2 -2
- package/dist/bundled/util/commands.js +1 -1
- package/dist/bundled/util/dark.js +1 -1
- package/dist/bundled/util/events.js +1 -1
- package/dist/bundled/util/grid-slots.js +1 -1
- package/dist/bundled/util/keyboard.js +8 -14
- package/dist/bundled/util/mapping.js +2 -2
- package/dist/bundled/util/render-tracker.js +33 -0
- package/dist/bundled/util/variant.js +12 -2
- package/dist/style.css +23 -1
- package/package.json +13 -17
- package/src/__tests__/render-tracker.spec.ts +38 -0
- package/src/app/App.vue +1 -1
- package/src/app/components/app/TopBarChipItem.vue +1 -1
- package/src/app/components/base/BaseEmpty.vue +1 -1
- package/src/app/components/base/BaseListItemLink.vue +4 -2
- package/src/app/components/base/BaseOverflowMenu.vue +17 -16
- package/src/app/components/base/BaseSelect.vue +171 -15
- package/src/app/components/base/BaseSplitPane.vue +2 -2
- package/src/app/components/command/PromptSelect.vue +1 -1
- package/src/app/components/panel/ControlsComponentPropItem.vue +26 -15
- package/src/app/components/panel/PaneTabs.vue +6 -6
- package/src/app/components/panel/StatePresets.vue +100 -64
- package/src/app/components/panel/StorySidePanel.vue +1 -1
- package/src/app/components/panel/StorySourceCode.vue +6 -5
- package/src/app/components/search/SearchItemContent.vue +2 -1
- package/src/app/components/search/SearchPane.vue +2 -3
- package/src/app/components/story/StoryResponsivePreview.vue +6 -2
- package/src/app/components/story/StoryVariantGridItem.vue +1 -1
- package/src/app/components/story/StoryVariantSinglePreviewRemote.vue +14 -8
- package/src/app/components/story/StoryView.vue +3 -1
- package/src/app/components/toolbar/ToolbarTitle.vue +2 -2
- package/src/app/components/tree/StoryGroup.vue +2 -2
- package/src/app/components/tree/StoryList.vue +2 -2
- package/src/app/components/tree/StoryListFolder.vue +2 -2
- package/src/app/components/tree/StoryListItem.vue +1 -1
- package/src/app/sandbox.ts +8 -2
- package/src/app/stores/story.ts +2 -2
- package/src/app/types.ts +4 -4
- package/src/app/util/commands.ts +1 -1
- package/src/app/util/dark.ts +1 -1
- package/src/app/util/env.ts +0 -1
- package/src/app/util/events.ts +6 -5
- package/src/app/util/grid-slots.ts +1 -1
- package/src/app/util/keyboard.ts +7 -11
- package/src/app/util/mapping.ts +2 -2
- package/src/app/util/render-tracker.ts +31 -0
- package/src/app/util/state.ts +3 -3
- package/src/app/util/variant.ts +12 -2
package/src/app/stores/story.ts
CHANGED
|
@@ -9,9 +9,9 @@ export const useStoryStore = defineStore('story', () => {
|
|
|
9
9
|
stories.value = value
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
const currentStory = computed(() => stories.value.find(s => s.id === router.currentRoute.value.params
|
|
12
|
+
const currentStory = computed(() => stories.value.find(s => s.id === router.currentRoute.value.params['storyId']))
|
|
13
13
|
|
|
14
|
-
const currentVariant = computed(() => currentStory.value?.variants.find(v => v.id === router.currentRoute.value.query
|
|
14
|
+
const currentVariant = computed(() => currentStory.value?.variants.find(v => v.id === router.currentRoute.value.query['variantId']))
|
|
15
15
|
|
|
16
16
|
const maps = computed(() => {
|
|
17
17
|
const storyMap = new Map<string, Story>()
|
package/src/app/types.ts
CHANGED
|
@@ -33,10 +33,10 @@ export interface SearchResultBase {
|
|
|
33
33
|
rank: number
|
|
34
34
|
id: string
|
|
35
35
|
title: string
|
|
36
|
-
path?: string[]
|
|
37
|
-
icon?: string
|
|
38
|
-
iconColor?: string
|
|
39
|
-
type?: SearchResultType
|
|
36
|
+
path?: string[] | undefined
|
|
37
|
+
icon?: string | undefined
|
|
38
|
+
iconColor?: string | undefined
|
|
39
|
+
type?: SearchResultType | undefined
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export type SearchResult = SearchResultBase & ({
|
package/src/app/util/commands.ts
CHANGED
|
@@ -41,7 +41,7 @@ export const builtinCommands: ClientCommand[] = [
|
|
|
41
41
|
label: 'Open Poveste Documentation',
|
|
42
42
|
icon: 'carbon:help',
|
|
43
43
|
clientAction: () => {
|
|
44
|
-
window.open('https://poveste.dev/guide/getting-started
|
|
44
|
+
window.open('https://poveste.dev/guide/getting-started', '_blank')
|
|
45
45
|
},
|
|
46
46
|
},
|
|
47
47
|
]
|
package/src/app/util/dark.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { povesteConfig } from './config.js'
|
|
|
4
4
|
|
|
5
5
|
export const isDark = useDark({
|
|
6
6
|
valueDark: 'ptw-dark',
|
|
7
|
-
initialValue: povesteConfig.theme.defaultColorScheme,
|
|
7
|
+
...povesteConfig.theme.defaultColorScheme ? { initialValue: povesteConfig.theme.defaultColorScheme } : {},
|
|
8
8
|
storageKey: 'poveste-color-scheme',
|
|
9
9
|
storage: povesteConfig.theme.storeColorScheme ? localStorage : sessionStorage,
|
|
10
10
|
})
|
package/src/app/util/env.ts
CHANGED
|
@@ -2,5 +2,4 @@
|
|
|
2
2
|
// `navigator.userAgentData` is Chromium-only, so reading it here would simply
|
|
3
3
|
// stop detecting macOS in Safari and Firefox — the two places where getting the
|
|
4
4
|
// ⌘ shortcuts right matters most.
|
|
5
|
-
// eslint-disable-next-line ts/no-deprecated
|
|
6
5
|
export const isMac = navigator.platform.toLowerCase().includes('mac')
|
package/src/app/util/events.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EVENT_SEND } from './const'
|
|
2
2
|
import { occupant } from './occupant'
|
|
3
3
|
|
|
4
|
-
export async function logEvent(name: string, argument) {
|
|
4
|
+
export async function logEvent(name: string, argument: unknown) {
|
|
5
5
|
const event = {
|
|
6
6
|
name,
|
|
7
7
|
argument: JSON.parse(stringifyEvent(argument)), // Needed for HTMLEvent that can't be cloned
|
|
@@ -20,10 +20,11 @@ export async function logEvent(name: string, argument) {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function stringifyEvent(e) {
|
|
24
|
-
const obj = {}
|
|
25
|
-
for
|
|
26
|
-
|
|
23
|
+
function stringifyEvent(e: unknown) {
|
|
24
|
+
const obj: Record<string, unknown> = {}
|
|
25
|
+
// `for...in` rather than `Object.entries`: an event's fields are inherited.
|
|
26
|
+
for (const k in e as object) {
|
|
27
|
+
obj[k] = Reflect.get(e as object, k)
|
|
27
28
|
}
|
|
28
29
|
return JSON.stringify(obj, (k, v) => {
|
|
29
30
|
if (v instanceof Node) return 'Node'
|
package/src/app/util/keyboard.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface KeyboardShortcutOptions {
|
|
|
11
11
|
event?: 'keyup' | 'keydown' | 'keypress'
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const modifiers
|
|
14
|
+
const modifiers = {
|
|
15
15
|
ctrl: { key: 'Control', pressed: false },
|
|
16
16
|
alt: { key: 'Alt', pressed: false },
|
|
17
17
|
shift: { key: 'Shift', pressed: false },
|
|
@@ -24,8 +24,7 @@ const trackedWindows = shallowRef<Window[]>([])
|
|
|
24
24
|
|
|
25
25
|
function bindTracking(target: Window) {
|
|
26
26
|
const onKeydown = (event: KeyboardEvent) => {
|
|
27
|
-
for (const
|
|
28
|
-
const mod = modifiers[i]
|
|
27
|
+
for (const mod of Object.values(modifiers)) {
|
|
29
28
|
if (mod.key === event.key) {
|
|
30
29
|
mod.pressed = true
|
|
31
30
|
return
|
|
@@ -36,8 +35,7 @@ function bindTracking(target: Window) {
|
|
|
36
35
|
const onKeyup = (event: KeyboardEvent) => {
|
|
37
36
|
requestAnimationFrame(() => {
|
|
38
37
|
pressedKeys.clear()
|
|
39
|
-
for (const
|
|
40
|
-
const mod = modifiers[i]
|
|
38
|
+
for (const mod of Object.values(modifiers)) {
|
|
41
39
|
if (mod.key === event.key) {
|
|
42
40
|
mod.pressed = false
|
|
43
41
|
break
|
|
@@ -47,8 +45,8 @@ function bindTracking(target: Window) {
|
|
|
47
45
|
}
|
|
48
46
|
const onBlur = () => {
|
|
49
47
|
pressedKeys.clear()
|
|
50
|
-
for (const
|
|
51
|
-
|
|
48
|
+
for (const mod of Object.values(modifiers)) {
|
|
49
|
+
mod.pressed = false
|
|
52
50
|
}
|
|
53
51
|
}
|
|
54
52
|
target.addEventListener('keydown', onKeydown)
|
|
@@ -108,10 +106,8 @@ function isMatchingCombination(combination: string): boolean {
|
|
|
108
106
|
// `split` always yields at least one element, so this is unreachable for any
|
|
109
107
|
// real combination — an empty or blank one matches nothing, which is right.
|
|
110
108
|
if (!targetKey) return false
|
|
111
|
-
for (const mod
|
|
112
|
-
|
|
113
|
-
const isPressed = modifiers[mod].pressed
|
|
114
|
-
if (containsMod !== isPressed) {
|
|
109
|
+
for (const [name, mod] of Object.entries(modifiers)) {
|
|
110
|
+
if (splitted.includes(name) !== mod.pressed) {
|
|
115
111
|
return false
|
|
116
112
|
}
|
|
117
113
|
}
|
package/src/app/util/mapping.ts
CHANGED
|
@@ -28,7 +28,7 @@ export function mapFile(file: StoryFile, existingFile?: StoryFile): StoryFile {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
else if (key !== 'component') {
|
|
31
|
-
result
|
|
31
|
+
Reflect.set(result, key, Reflect.get(file, key))
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -58,7 +58,7 @@ export function mapVariant(variant: Variant, existingVariant?: Variant): Variant
|
|
|
58
58
|
result = existingVariant
|
|
59
59
|
for (const key in variant) {
|
|
60
60
|
if (!copiedFromExistingVariant.includes(key)) {
|
|
61
|
-
result
|
|
61
|
+
Reflect.set(result, key, Reflect.get(variant, key))
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether the render now under way inside a realm reported a throw.
|
|
3
|
+
*
|
|
4
|
+
* The host cannot see inside the realm, so "did this render succeed" has to be
|
|
5
|
+
* read off the two named messages it does see. A throw reaches
|
|
6
|
+
* `app.config.errorHandler` during mount and `SANDBOX_READY` is emitted after
|
|
7
|
+
* `await host.mount()` returns, so the order is always error-then-ready — which
|
|
8
|
+
* makes a ready with nothing recorded since the render began a clean render.
|
|
9
|
+
*
|
|
10
|
+
* Clearing on the story and variant ids changing instead cleared the pair being
|
|
11
|
+
* navigated *to*, so arriving at a broken story wiped its marker, and the fixed
|
|
12
|
+
* story the comment was about was never reached at all: a file edited in place
|
|
13
|
+
* keeps its ids, so that watcher did not fire on the one path it named (#597).
|
|
14
|
+
*/
|
|
15
|
+
export function createRenderTracker() {
|
|
16
|
+
let threw = false
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
/** A new render is starting: what the previous one reported no longer holds. */
|
|
20
|
+
begin(): void {
|
|
21
|
+
threw = false
|
|
22
|
+
},
|
|
23
|
+
threw(): void {
|
|
24
|
+
threw = true
|
|
25
|
+
},
|
|
26
|
+
/** True when the render that has just reported ready said nothing before it. */
|
|
27
|
+
wasClean(): boolean {
|
|
28
|
+
return !threw
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/app/util/state.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { clone, omit } from '@poveste/shared'
|
|
2
2
|
import { isRef, unref } from 'vue'
|
|
3
3
|
|
|
4
|
-
const isObject = val => val !== null && typeof val === 'object'
|
|
4
|
+
const isObject = (val: unknown): val is object => val !== null && typeof val === 'object'
|
|
5
5
|
|
|
6
|
-
export function toRawDeep(val, clean = false, seen = new WeakMap()) {
|
|
6
|
+
export function toRawDeep(val: unknown, clean = false, seen = new WeakMap()): any {
|
|
7
7
|
const unwrappedValue = isRef(val) ? unref(val) : val
|
|
8
8
|
|
|
9
9
|
if (typeof unwrappedValue === 'symbol') {
|
|
@@ -31,7 +31,7 @@ export function toRawDeep(val, clean = false, seen = new WeakMap()) {
|
|
|
31
31
|
else {
|
|
32
32
|
const result = {}
|
|
33
33
|
seen.set(unwrappedValue, result)
|
|
34
|
-
toRawObject(unwrappedValue, result, clean, seen)
|
|
34
|
+
toRawObject(unwrappedValue as Record<any, any>, result, clean, seen)
|
|
35
35
|
return result
|
|
36
36
|
}
|
|
37
37
|
}
|
package/src/app/util/variant.ts
CHANGED
|
@@ -10,17 +10,27 @@ import { useRoute } from 'vue-router'
|
|
|
10
10
|
* has to tell "a variant is on its way" from "this story is waiting for the
|
|
11
11
|
* reader to pick one" needs the same answer it will give — hence one predicate
|
|
12
12
|
* rather than two copies of the condition (#328).
|
|
13
|
+
*
|
|
14
|
+
* Any story with variants, deliberately. It used to require a remembered choice
|
|
15
|
+
* or exactly one variant, which made `StoryView`'s `variants[0]` fallback
|
|
16
|
+
* unreachable: a story with several variants and no history satisfied neither
|
|
17
|
+
* clause, so the first visit of a session showed an empty panel and every visit
|
|
18
|
+
* after it worked, because the first one recorded the history (#724).
|
|
19
|
+
*
|
|
20
|
+
* No layout clause. Grid stories already auto-selected on revisit through the
|
|
21
|
+
* remembered choice, so excluding them here would auto-open them on the second
|
|
22
|
+
* visit and never the first — this defect, made permanent for one layout.
|
|
13
23
|
*/
|
|
14
24
|
// A type predicate rather than `boolean`: the body already establishes that the
|
|
15
25
|
// story is there, and returning `boolean` threw that away at every call site —
|
|
16
26
|
// `StoryView` reads the story twice immediately after this returns true.
|
|
17
27
|
export function autoSelectsVariant(story: Story | null | undefined): story is Story {
|
|
18
|
-
return !!story &&
|
|
28
|
+
return !!story && story.variants.length > 0
|
|
19
29
|
}
|
|
20
30
|
|
|
21
31
|
export function useCurrentVariantRoute(variant: Ref<Variant>) {
|
|
22
32
|
const route = useRoute()
|
|
23
|
-
const isActive = computed(() => route.query
|
|
33
|
+
const isActive = computed(() => route.query['variantId'] === variant.value.id)
|
|
24
34
|
const targetRoute = computed(() => ({
|
|
25
35
|
...route,
|
|
26
36
|
query: {
|