@poveste/app 0.19.1 → 0.21.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 +208 -7
- package/dist/bundled/components/HomeView.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/bundled/components/app/AppLogo.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/bundled/components/app/TopBarChipItem.js +10 -6
- package/dist/bundled/components/layout/LayoutItem.js +1 -0
- package/dist/bundled/components/layout/LayoutItem.vue_vue_type_script_setup_true_lang.js +20 -23
- package/dist/bundled/components/layout/LayoutModal.vue_vue_type_script_setup_true_lang.js +44 -5
- package/dist/bundled/components/panel/ComponentDocs.js +7 -0
- package/dist/bundled/components/panel/ComponentDocs.vue_vue_type_script_setup_true_lang.js +164 -0
- package/dist/bundled/components/panel/StoryDocs.vue_vue_type_script_setup_true_lang.js +57 -22
- package/dist/bundled/components/panel/StorySourceCode.js +1 -1
- package/dist/bundled/components/panel/StorySourceCode.vue_vue_type_script_setup_true_lang.js +22 -6
- package/dist/bundled/components/story/GenericMountStory.vue_vue_type_script_setup_true_lang.js +3 -7
- package/dist/bundled/components/story/GenericRenderStory.vue_vue_type_script_setup_true_lang.js +3 -10
- package/dist/bundled/components/story/StoryResponsivePreview.js +1 -1
- package/dist/bundled/components/story/StoryResponsivePreview.vue_vue_type_script_setup_true_lang.js +5 -3
- package/dist/bundled/components/story/StoryVariantGridItem.js +1 -1
- package/dist/bundled/components/story/StoryVariantGridItem.vue_vue_type_script_setup_true_lang.js +5 -3
- package/dist/bundled/components/story/StoryVariantSinglePreviewRemote.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/bundled/components/toolbar/DevOnlyToolbarOpenInEditor.vue_vue_type_script_setup_true_lang.js +0 -1
- package/dist/bundled/index.js +5 -1
- package/dist/bundled/sandbox.js +2 -0
- package/dist/bundled/util/client-plugin.js +22 -0
- package/dist/bundled/util/component-docs-data.js +5 -0
- package/dist/bundled/util/component-docs.js +133 -0
- package/dist/bundled/util/dark.js +3 -1
- package/dist/bundled/util/docs.js +13 -3
- package/dist/bundled/util/highlighter.js +1 -1
- package/dist/bundled/util/icons.generated.js +3 -2
- package/dist/bundled/util/keyboard.js +5 -4
- package/dist/bundled/util/mapping.js +1 -5
- package/dist/style.css +321 -195
- package/package.json +17 -17
- package/src/app/components/HomeView.vue +2 -2
- package/src/app/components/app/AppLogo.vue +4 -6
- package/src/app/components/app/TopBarChipItem.vue +55 -6
- package/src/app/components/layout/LayoutItem.vue +56 -6
- package/src/app/components/layout/LayoutModal.vue +55 -2
- package/src/app/components/panel/ComponentDocs.vue +323 -0
- package/src/app/components/panel/StoryDocs.vue +38 -2
- package/src/app/components/panel/StorySourceCode.vue +29 -5
- package/src/app/components/story/GenericMountStory.vue +3 -5
- package/src/app/components/story/GenericRenderStory.vue +4 -12
- package/src/app/components/story/StoryResponsivePreview.vue +4 -1
- package/src/app/components/story/StoryVariantGridItem.vue +4 -1
- package/src/app/components/story/StoryVariantSinglePreviewRemote.vue +6 -4
- package/src/app/components/toolbar/DevOnlyToolbarOpenInEditor.vue +0 -1
- package/src/app/index.ts +12 -3
- package/src/app/sandbox.ts +5 -0
- package/src/app/util/client-plugin.ts +33 -0
- package/src/app/util/component-docs-data.ts +6 -0
- package/src/app/util/component-docs.ts +169 -0
- package/src/app/util/dark.ts +6 -0
- package/src/app/util/docs.ts +18 -2
- package/src/app/util/highlighter.ts +2 -1
- package/src/app/util/icons.generated.ts +2 -2
- package/src/app/util/keyboard.ts +8 -4
- package/src/app/util/mapping.ts +1 -5
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poveste/app",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.21.0",
|
|
5
5
|
"description": "Pre-bundled UI for Poveste",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Sorin Gitlan",
|
|
@@ -36,16 +36,16 @@
|
|
|
36
36
|
"node": ">=22.22.2"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@poveste/controls": "^0.
|
|
40
|
-
"@poveste/shared": "^0.
|
|
41
|
-
"@poveste/vendors": "^0.
|
|
39
|
+
"@poveste/controls": "^0.21.0",
|
|
40
|
+
"@poveste/shared": "^0.21.0",
|
|
41
|
+
"@poveste/vendors": "^0.21.0",
|
|
42
42
|
"fuse.js": "^7.0.0",
|
|
43
|
-
"shiki": "^4.
|
|
43
|
+
"shiki": "^4.5.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@fontsource/noto-sans-display": "^5.3.0",
|
|
47
|
-
"@iconify-json/carbon": "^1.2.
|
|
48
|
-
"@iconify-json/fluent": "1.2.
|
|
47
|
+
"@iconify-json/carbon": "^1.2.28",
|
|
48
|
+
"@iconify-json/fluent": "1.2.60",
|
|
49
49
|
"@iconify-json/mdi": "^1.2.3",
|
|
50
50
|
"@iconify-json/ri": "^1.2.10",
|
|
51
51
|
"@iconify/utils": "^3.1.7",
|
|
@@ -53,24 +53,24 @@
|
|
|
53
53
|
"@tailwindcss/postcss": "^4.3.3",
|
|
54
54
|
"@tailwindcss/typography": "^0.5.20",
|
|
55
55
|
"@types/fs-extra": "^11.0.4",
|
|
56
|
-
"@types/node": "^26.6.
|
|
57
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
56
|
+
"@types/node": "^26.6.5",
|
|
57
|
+
"@vitejs/plugin-vue": "^6.0.10",
|
|
58
58
|
"@vueuse/core": "^15.0.0",
|
|
59
59
|
"chokidar": "^5.0.0",
|
|
60
|
-
"concurrently": "^10.0.
|
|
60
|
+
"concurrently": "^10.0.6",
|
|
61
61
|
"fs-extra": "^11.4.1",
|
|
62
62
|
"globby": "^16.2.4",
|
|
63
63
|
"pathe": "^2.0.3",
|
|
64
|
-
"pinia": "^4.0
|
|
65
|
-
"postcss": "^8.5.
|
|
64
|
+
"pinia": "^4.1.0",
|
|
65
|
+
"postcss": "^8.5.31",
|
|
66
66
|
"postcss-cli": "^12.0.0",
|
|
67
67
|
"tailwindcss": "^4.3.3",
|
|
68
68
|
"typescript": "6.0.3",
|
|
69
|
-
"vite": "^8.3.
|
|
70
|
-
"vitest": "^5.0.
|
|
71
|
-
"vue": "^3.5.
|
|
72
|
-
"vue-router": "^5.
|
|
73
|
-
"vue-tsc": "^3.3.
|
|
69
|
+
"vite": "^8.3.4",
|
|
70
|
+
"vitest": "^5.0.5",
|
|
71
|
+
"vue": "^3.5.44",
|
|
72
|
+
"vue-router": "^5.4.0",
|
|
73
|
+
"vue-tsc": "^3.3.13"
|
|
74
74
|
},
|
|
75
75
|
"scripts": {
|
|
76
76
|
"build": "pnpm run icons && rimraf dist && vite build && pnpm run build:css && node ./scripts/copy.mjs",
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import PovesteLogo from '../assets/poveste.svg'
|
|
4
4
|
import { useStoryStore } from '../stores/story'
|
|
5
|
-
import { customLogos
|
|
5
|
+
import { customLogos } from '../util/config'
|
|
6
6
|
import HomeCounter from './app/HomeCounter.vue'
|
|
7
7
|
|
|
8
|
-
const logoUrl = computed(() =>
|
|
8
|
+
const logoUrl = computed(() => customLogos?.square ?? PovesteLogo)
|
|
9
9
|
const storyStore = useStoryStore()
|
|
10
10
|
|
|
11
11
|
const stats = computed(() => {
|
|
@@ -6,15 +6,13 @@ import PovesteLogoLight from '../../assets/poveste-text.svg'
|
|
|
6
6
|
import { customLogos, povesteConfig } from '../../util/config'
|
|
7
7
|
import { isDark } from '../../util/dark'
|
|
8
8
|
|
|
9
|
-
// `
|
|
10
|
-
//
|
|
11
|
-
// about the other — and falling back to the bundled logo beats rendering an
|
|
12
|
-
// `<img>` with no `src` if they ever disagree.
|
|
9
|
+
// `customLogos` holds a served URL for each logo the config names. The config's
|
|
10
|
+
// own entries are paths on the machine that built the book, and are not sent (#1383).
|
|
13
11
|
const logoUrl = computed(() => {
|
|
14
12
|
if (isDark.value) {
|
|
15
|
-
return
|
|
13
|
+
return customLogos?.dark ?? PovesteLogoDark
|
|
16
14
|
}
|
|
17
|
-
return
|
|
15
|
+
return customLogos?.light ?? PovesteLogoLight
|
|
18
16
|
})
|
|
19
17
|
|
|
20
18
|
const altText = computed(() => `${povesteConfig.theme.title} logo`)
|
|
@@ -1,10 +1,59 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<!--
|
|
3
|
-
|
|
4
|
-
<
|
|
5
|
-
:
|
|
6
|
-
|
|
2
|
+
<!-- A link where it navigates, a button everywhere else. An `<a>` without an
|
|
3
|
+
href is not focusable, so a keyboard could not reach the chip (#1351). -->
|
|
4
|
+
<component
|
|
5
|
+
:is="$attrs['href'] ? 'a' : 'button'"
|
|
6
|
+
:type="$attrs['href'] ? undefined : 'button'"
|
|
7
|
+
class="poveste-top-bar-chip-item"
|
|
8
|
+
data-slot="top-bar-chip-item"
|
|
7
9
|
>
|
|
8
10
|
<slot />
|
|
9
|
-
</
|
|
11
|
+
</component>
|
|
10
12
|
</template>
|
|
13
|
+
|
|
14
|
+
<style lang="postcss">
|
|
15
|
+
.poveste-top-bar-chip-item {
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
gap: .25rem;
|
|
19
|
+
padding: .375rem .625rem;
|
|
20
|
+
border: 0;
|
|
21
|
+
font: inherit;
|
|
22
|
+
color: var(--color-gray-900);
|
|
23
|
+
cursor: pointer;
|
|
24
|
+
|
|
25
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
26
|
+
transition: color .15s ease-out, background-color .15s ease-out;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&:hover {
|
|
30
|
+
background-color: rgb(255 255 255 / .5);
|
|
31
|
+
color: var(--color-primary-500);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&:active {
|
|
35
|
+
background-color: rgb(255 255 255 / .7);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Inset: the chip clips its items to its rounded border. */
|
|
39
|
+
&:focus-visible {
|
|
40
|
+
outline: 2px solid var(--color-primary-500);
|
|
41
|
+
outline-offset: -2px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* Spelled out on the subject: `.ptw-dark` sits above the `@scope` root, so a
|
|
45
|
+
descendant rule keyed on it never matches from in here (#101). */
|
|
46
|
+
&:where(.ptw-dark, .ptw-dark *) {
|
|
47
|
+
color: var(--color-gray-100);
|
|
48
|
+
|
|
49
|
+
&:hover {
|
|
50
|
+
background-color: rgb(255 255 255 / .1);
|
|
51
|
+
color: var(--color-primary-400);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&:active {
|
|
55
|
+
background-color: rgb(255 255 255 / .15);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
</style>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { Icon } from '@iconify/vue'
|
|
3
|
-
import BaseListItem from '../base/BaseListItem.vue'
|
|
4
3
|
|
|
5
4
|
defineProps<{
|
|
6
5
|
title: string
|
|
@@ -15,10 +14,14 @@ defineEmits<{
|
|
|
15
14
|
</script>
|
|
16
15
|
|
|
17
16
|
<template>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
<!-- A button: `BaseListItem` is an `<a>` with no href, which a keyboard cannot
|
|
18
|
+
reach (#1351). -->
|
|
19
|
+
<button
|
|
20
|
+
type="button"
|
|
21
|
+
class="poveste-layout-item"
|
|
22
|
+
:class="{ active: isActive }"
|
|
23
|
+
data-slot="layout-item"
|
|
24
|
+
@click="$emit('click')"
|
|
22
25
|
>
|
|
23
26
|
<Icon
|
|
24
27
|
class="w-4 h-4 flex-none"
|
|
@@ -32,5 +35,52 @@ defineEmits<{
|
|
|
32
35
|
:icon="stateIcon"
|
|
33
36
|
aria-hidden="true"
|
|
34
37
|
/>
|
|
35
|
-
</
|
|
38
|
+
</button>
|
|
36
39
|
</template>
|
|
40
|
+
|
|
41
|
+
<style lang="postcss">
|
|
42
|
+
.poveste-layout-item {
|
|
43
|
+
display: flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
gap: 1rem;
|
|
46
|
+
width: 100%;
|
|
47
|
+
padding: 1rem 1.5rem;
|
|
48
|
+
border: 0;
|
|
49
|
+
font: inherit;
|
|
50
|
+
text-align: start;
|
|
51
|
+
color: var(--color-gray-900);
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
|
|
54
|
+
&:hover {
|
|
55
|
+
background-color: var(--color-primary-100);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&:focus-visible {
|
|
59
|
+
outline: 2px solid var(--color-primary-500);
|
|
60
|
+
outline-offset: -2px;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&.active {
|
|
64
|
+
background-color: var(--color-primary-500);
|
|
65
|
+
color: var(--color-white);
|
|
66
|
+
|
|
67
|
+
&:hover {
|
|
68
|
+
background-color: var(--color-primary-600);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* Spelled out on the subject: `.ptw-dark` sits above the `@scope` root, so a
|
|
73
|
+
descendant rule keyed on it never matches from in here (#101). */
|
|
74
|
+
&:where(.ptw-dark, .ptw-dark *) {
|
|
75
|
+
color: var(--color-gray-100);
|
|
76
|
+
|
|
77
|
+
&:hover {
|
|
78
|
+
background-color: var(--color-primary-900);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
&.active {
|
|
82
|
+
color: var(--color-black);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
</style>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { Icon } from '@iconify/vue'
|
|
3
|
+
import { nextTick, ref, watch } from 'vue'
|
|
3
4
|
import { onKeyboardShortcut } from '../../util/keyboard'
|
|
4
5
|
import LayoutPane from './LayoutPane.vue'
|
|
5
6
|
|
|
@@ -23,6 +24,48 @@ onKeyboardShortcut(['escape'], () => {
|
|
|
23
24
|
close()
|
|
24
25
|
}
|
|
25
26
|
})
|
|
27
|
+
|
|
28
|
+
// A dialog to the keyboard as well: focus moves in when it opens, Tab stays inside,
|
|
29
|
+
// and closing hands focus back to whatever opened it, the layout chip or the page
|
|
30
|
+
// behind a shortcut. Focus used to stay on the chip, behind the pane (#1372).
|
|
31
|
+
const panel = ref<HTMLElement>()
|
|
32
|
+
let opener: HTMLElement | null = null
|
|
33
|
+
|
|
34
|
+
const FOCUSABLE = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
35
|
+
|
|
36
|
+
function focusables() {
|
|
37
|
+
return [...panel.value?.querySelectorAll<HTMLElement>(FOCUSABLE) ?? []]
|
|
38
|
+
.filter(element => !element.hasAttribute('disabled') && element.getClientRects().length > 0)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
watch(() => props.shown, async (shown) => {
|
|
42
|
+
if (shown) {
|
|
43
|
+
opener = document.activeElement instanceof HTMLElement ? document.activeElement : null
|
|
44
|
+
await nextTick()
|
|
45
|
+
focusables()[0]?.focus()
|
|
46
|
+
}
|
|
47
|
+
else if (opener?.isConnected) {
|
|
48
|
+
opener.focus()
|
|
49
|
+
opener = null
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
function keepFocusInside(event: KeyboardEvent) {
|
|
54
|
+
const elements = focusables()
|
|
55
|
+
const first = elements[0]
|
|
56
|
+
const last = elements.at(-1)
|
|
57
|
+
if (!first || !last) {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
if (event.shiftKey && document.activeElement === first) {
|
|
61
|
+
event.preventDefault()
|
|
62
|
+
last.focus()
|
|
63
|
+
}
|
|
64
|
+
else if (!event.shiftKey && document.activeElement === last) {
|
|
65
|
+
event.preventDefault()
|
|
66
|
+
first.focus()
|
|
67
|
+
}
|
|
68
|
+
}
|
|
26
69
|
</script>
|
|
27
70
|
|
|
28
71
|
<template>
|
|
@@ -35,9 +78,19 @@ onKeyboardShortcut(['escape'], () => {
|
|
|
35
78
|
class="absolute inset-0"
|
|
36
79
|
@click="close()"
|
|
37
80
|
/>
|
|
38
|
-
<div
|
|
81
|
+
<div
|
|
82
|
+
ref="panel"
|
|
83
|
+
role="dialog"
|
|
84
|
+
aria-modal="true"
|
|
85
|
+
aria-labelledby="poveste-layout-modal-title"
|
|
86
|
+
class="bg-white dark:bg-gray-900 md:mt-16 md:mx-auto w-screen max-w-[512px] shadow-xl border border-gray-200 dark:border-gray-750 rounded-lg relative divide-y divide-gray-200 dark:divide-gray-850"
|
|
87
|
+
@keydown.tab="keepFocusInside"
|
|
88
|
+
>
|
|
39
89
|
<div class="flex items-center px-6 py-3 text-gray-900 dark:text-gray-100">
|
|
40
|
-
<h2
|
|
90
|
+
<h2
|
|
91
|
+
id="poveste-layout-modal-title"
|
|
92
|
+
class="flex-1 text-sm font-medium m-0"
|
|
93
|
+
>
|
|
41
94
|
Customize Layout
|
|
42
95
|
</h2>
|
|
43
96
|
<button
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import type { DocProp } from '@poveste/shared'
|
|
3
|
+
import type { ComponentDocsEntry } from '../../util/component-docs'
|
|
4
|
+
import { computed } from 'vue'
|
|
5
|
+
import { modelLabel, OPEN_PARTS, rootFirst, tagHref, tagText } from '../../util/component-docs'
|
|
6
|
+
|
|
7
|
+
const props = defineProps<{
|
|
8
|
+
components: ComponentDocsEntry[]
|
|
9
|
+
/** The story's file, which names the family whose root opens first. */
|
|
10
|
+
storyFile?: string | undefined
|
|
11
|
+
}>()
|
|
12
|
+
|
|
13
|
+
const ordered = computed(() => rootFirst(props.components, props.storyFile))
|
|
14
|
+
|
|
15
|
+
function shownDefault(prop: DocProp) {
|
|
16
|
+
return prop.default ?? prop.defaultTag
|
|
17
|
+
}
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<template>
|
|
21
|
+
<div
|
|
22
|
+
class="poveste-component-docs"
|
|
23
|
+
data-testid="component-docs"
|
|
24
|
+
>
|
|
25
|
+
<details
|
|
26
|
+
v-for="(component, index) of ordered"
|
|
27
|
+
:key="component.file"
|
|
28
|
+
:open="ordered.length <= OPEN_PARTS || index === 0"
|
|
29
|
+
data-slot="component"
|
|
30
|
+
:data-component="component.name"
|
|
31
|
+
>
|
|
32
|
+
<summary>
|
|
33
|
+
<h3 data-slot="component-name">
|
|
34
|
+
{{ component.name }}<code
|
|
35
|
+
v-if="component.doc?.generic"
|
|
36
|
+
title="The component's type parameters, as its script declares them"
|
|
37
|
+
data-slot="generic"
|
|
38
|
+
><{{ component.doc.generic }}></code>
|
|
39
|
+
</h3>
|
|
40
|
+
</summary>
|
|
41
|
+
|
|
42
|
+
<p
|
|
43
|
+
v-if="component.error"
|
|
44
|
+
data-slot="error"
|
|
45
|
+
>
|
|
46
|
+
Could not read this component's types: {{ component.error }}
|
|
47
|
+
</p>
|
|
48
|
+
|
|
49
|
+
<template v-else-if="component.doc">
|
|
50
|
+
<table
|
|
51
|
+
v-if="component.doc.props.length"
|
|
52
|
+
data-slot="props"
|
|
53
|
+
>
|
|
54
|
+
<thead>
|
|
55
|
+
<tr>
|
|
56
|
+
<th>Prop</th>
|
|
57
|
+
<th>Type</th>
|
|
58
|
+
<th>Default</th>
|
|
59
|
+
<th>Description</th>
|
|
60
|
+
</tr>
|
|
61
|
+
</thead>
|
|
62
|
+
<tbody>
|
|
63
|
+
<tr
|
|
64
|
+
v-for="prop of component.doc.props"
|
|
65
|
+
:key="prop.name"
|
|
66
|
+
:data-prop="prop.name"
|
|
67
|
+
>
|
|
68
|
+
<td>
|
|
69
|
+
<code
|
|
70
|
+
:class="{ deprecated: tagText(prop.tags, 'deprecated') !== undefined }"
|
|
71
|
+
>{{ prop.name }}</code><span
|
|
72
|
+
v-if="prop.required"
|
|
73
|
+
title="Required"
|
|
74
|
+
data-slot="required"
|
|
75
|
+
>*</span>
|
|
76
|
+
<code
|
|
77
|
+
v-if="modelLabel(component.doc, prop.name)"
|
|
78
|
+
:title="`Bound two ways with ${modelLabel(component.doc, prop.name)}, through the update:${prop.name} event`"
|
|
79
|
+
data-slot="model"
|
|
80
|
+
>{{ modelLabel(component.doc, prop.name) }}</code>
|
|
81
|
+
</td>
|
|
82
|
+
<td><code>{{ prop.type }}</code></td>
|
|
83
|
+
<td>
|
|
84
|
+
<code v-if="shownDefault(prop) !== undefined">{{ shownDefault(prop) }}</code>
|
|
85
|
+
<span
|
|
86
|
+
v-if="__POVESTE_DEV__ && prop.defaultConflict"
|
|
87
|
+
:title="`The code's default is shown; the @default tag says ${prop.defaultTag}`"
|
|
88
|
+
data-slot="default-conflict"
|
|
89
|
+
>≠</span>
|
|
90
|
+
</td>
|
|
91
|
+
<td>
|
|
92
|
+
<span
|
|
93
|
+
v-if="tagText(prop.tags, 'deprecated') !== undefined"
|
|
94
|
+
data-slot="deprecated"
|
|
95
|
+
>Deprecated<template v-if="tagText(prop.tags, 'deprecated')">: {{ tagText(prop.tags, 'deprecated') }}</template></span>
|
|
96
|
+
{{ prop.description }}
|
|
97
|
+
<template
|
|
98
|
+
v-for="tag of prop.tags.filter(tag => tag.name === 'see' || tag.name === 'link')"
|
|
99
|
+
:key="tag.text"
|
|
100
|
+
>
|
|
101
|
+
<a
|
|
102
|
+
v-if="tagHref(tag.text ?? '')"
|
|
103
|
+
:href="tagHref(tag.text ?? '')"
|
|
104
|
+
target="_blank"
|
|
105
|
+
rel="noopener"
|
|
106
|
+
data-slot="see"
|
|
107
|
+
>{{ tag.text }}</a>
|
|
108
|
+
<span
|
|
109
|
+
v-else
|
|
110
|
+
data-slot="see"
|
|
111
|
+
>{{ tag.text }}</span>
|
|
112
|
+
</template>
|
|
113
|
+
<pre
|
|
114
|
+
v-if="tagText(prop.tags, 'example')"
|
|
115
|
+
data-slot="example"
|
|
116
|
+
><code>{{ tagText(prop.tags, 'example') }}</code></pre>
|
|
117
|
+
</td>
|
|
118
|
+
</tr>
|
|
119
|
+
</tbody>
|
|
120
|
+
</table>
|
|
121
|
+
|
|
122
|
+
<table
|
|
123
|
+
v-if="component.doc.slots.length"
|
|
124
|
+
data-slot="slots"
|
|
125
|
+
>
|
|
126
|
+
<thead>
|
|
127
|
+
<tr>
|
|
128
|
+
<th>Slot</th>
|
|
129
|
+
<th>Type</th>
|
|
130
|
+
<th>Description</th>
|
|
131
|
+
</tr>
|
|
132
|
+
</thead>
|
|
133
|
+
<tbody>
|
|
134
|
+
<template
|
|
135
|
+
v-for="slot of component.doc.slots"
|
|
136
|
+
:key="slot.name"
|
|
137
|
+
>
|
|
138
|
+
<tr :data-slot-name="slot.name">
|
|
139
|
+
<td><code>{{ slot.name }}</code></td>
|
|
140
|
+
<!-- Its props are listed below, one row each; the type string would only repeat them. -->
|
|
141
|
+
<td><code v-if="slot.type && !slot.props?.length">{{ slot.type }}</code></td>
|
|
142
|
+
<td>{{ slot.description }}</td>
|
|
143
|
+
</tr>
|
|
144
|
+
<tr
|
|
145
|
+
v-for="slotProp of slot.props ?? []"
|
|
146
|
+
:key="`${slot.name}.${slotProp.name}`"
|
|
147
|
+
:data-slot-prop="slotProp.name"
|
|
148
|
+
>
|
|
149
|
+
<td><code>{{ slotProp.name }}</code></td>
|
|
150
|
+
<td><code>{{ slotProp.type }}</code></td>
|
|
151
|
+
<td>{{ slotProp.description }}</td>
|
|
152
|
+
</tr>
|
|
153
|
+
</template>
|
|
154
|
+
</tbody>
|
|
155
|
+
</table>
|
|
156
|
+
|
|
157
|
+
<table
|
|
158
|
+
v-if="component.doc.events.length"
|
|
159
|
+
data-slot="events"
|
|
160
|
+
>
|
|
161
|
+
<thead>
|
|
162
|
+
<tr>
|
|
163
|
+
<th>Event</th>
|
|
164
|
+
<th>Payload</th>
|
|
165
|
+
<th>Description</th>
|
|
166
|
+
</tr>
|
|
167
|
+
</thead>
|
|
168
|
+
<tbody>
|
|
169
|
+
<tr
|
|
170
|
+
v-for="event of component.doc.events"
|
|
171
|
+
:key="event.name"
|
|
172
|
+
:data-event="event.name"
|
|
173
|
+
>
|
|
174
|
+
<td>
|
|
175
|
+
<code>{{ event.name }}</code>
|
|
176
|
+
<code
|
|
177
|
+
v-if="modelLabel(component.doc, event.name)"
|
|
178
|
+
:title="`Bound two ways with ${modelLabel(component.doc, event.name)}, with the ${event.name.slice('update:'.length)} prop`"
|
|
179
|
+
data-slot="model"
|
|
180
|
+
>{{ modelLabel(component.doc, event.name) }}</code>
|
|
181
|
+
</td>
|
|
182
|
+
<td><code v-if="event.type">{{ event.type }}</code></td>
|
|
183
|
+
<td>{{ event.description }}</td>
|
|
184
|
+
</tr>
|
|
185
|
+
</tbody>
|
|
186
|
+
</table>
|
|
187
|
+
</template>
|
|
188
|
+
</details>
|
|
189
|
+
</div>
|
|
190
|
+
</template>
|
|
191
|
+
|
|
192
|
+
<style scoped>
|
|
193
|
+
.poveste-component-docs {
|
|
194
|
+
padding: 1rem;
|
|
195
|
+
font-size: .875rem;
|
|
196
|
+
color: var(--color-gray-800);
|
|
197
|
+
|
|
198
|
+
/* On the subject, not `.ptw-dark &`: `.ptw-dark` sits above the `@scope` root (#101). */
|
|
199
|
+
&:where(.ptw-dark, .ptw-dark *) {
|
|
200
|
+
color: var(--color-gray-200);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
details + details {
|
|
205
|
+
margin-top: 1.5rem;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
summary {
|
|
209
|
+
cursor: pointer;
|
|
210
|
+
margin-bottom: .5rem;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
h3 {
|
|
214
|
+
display: inline;
|
|
215
|
+
font-weight: 600;
|
|
216
|
+
font-size: 1rem;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
table {
|
|
220
|
+
width: 100%;
|
|
221
|
+
border-collapse: collapse;
|
|
222
|
+
margin-bottom: 1rem;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
th {
|
|
226
|
+
text-align: start;
|
|
227
|
+
font-weight: 500;
|
|
228
|
+
color: var(--color-gray-500);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
th,
|
|
232
|
+
td {
|
|
233
|
+
padding: .375rem .5rem;
|
|
234
|
+
border-bottom: 1px solid var(--color-gray-200);
|
|
235
|
+
vertical-align: top;
|
|
236
|
+
|
|
237
|
+
&:where(.ptw-dark, .ptw-dark *) {
|
|
238
|
+
border-color: var(--color-gray-750);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
code {
|
|
243
|
+
font-size: .8125rem;
|
|
244
|
+
background-color: var(--color-gray-100);
|
|
245
|
+
border-radius: .25rem;
|
|
246
|
+
padding: 0 .25rem;
|
|
247
|
+
|
|
248
|
+
&:where(.ptw-dark, .ptw-dark *) {
|
|
249
|
+
background-color: var(--color-gray-750);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
pre code {
|
|
254
|
+
display: block;
|
|
255
|
+
padding: .5rem;
|
|
256
|
+
margin-top: .25rem;
|
|
257
|
+
white-space: pre-wrap;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.deprecated {
|
|
261
|
+
text-decoration: line-through;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* Its own line: a constraint wrapped beside the name broke mid-phrase in the narrow panel. */
|
|
265
|
+
/* A prop a slot passes its content, under the slot it belongs to. */
|
|
266
|
+
[data-slot-prop] td:first-child {
|
|
267
|
+
padding-inline-start: 1rem;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
[data-slot='generic'] {
|
|
271
|
+
display: block;
|
|
272
|
+
width: fit-content;
|
|
273
|
+
margin-top: .25rem;
|
|
274
|
+
font-size: .75rem;
|
|
275
|
+
font-weight: 400;
|
|
276
|
+
cursor: help;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
[data-slot='required'] {
|
|
280
|
+
color: var(--color-red-500);
|
|
281
|
+
margin-inline-start: .125rem;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
[data-slot='model'] {
|
|
285
|
+
display: inline-block;
|
|
286
|
+
margin-inline-start: .375rem;
|
|
287
|
+
color: var(--color-primary-600);
|
|
288
|
+
cursor: help;
|
|
289
|
+
|
|
290
|
+
&:where(.ptw-dark, .ptw-dark *) {
|
|
291
|
+
color: var(--color-primary-400);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
[data-slot='deprecated'],
|
|
296
|
+
[data-slot='default-conflict'] {
|
|
297
|
+
color: var(--color-amber-600);
|
|
298
|
+
font-weight: 500;
|
|
299
|
+
|
|
300
|
+
&:where(.ptw-dark, .ptw-dark *) {
|
|
301
|
+
color: var(--color-amber-400);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
[data-slot='default-conflict'] {
|
|
306
|
+
margin-inline-start: .25rem;
|
|
307
|
+
cursor: help;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
[data-slot='see'] {
|
|
311
|
+
display: block;
|
|
312
|
+
margin-top: .25rem;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
a[data-slot='see'] {
|
|
316
|
+
color: var(--color-primary-500);
|
|
317
|
+
text-decoration: underline;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
[data-slot='error'] {
|
|
321
|
+
color: var(--color-gray-500);
|
|
322
|
+
}
|
|
323
|
+
</style>
|