@rimelight/ui 0.0.34 → 0.0.36
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/README.md +1 -0
- package/package.json +19 -24
- package/src/components/astro/RLAAccordion.astro +94 -18
- package/src/components/astro/RLAAvatar.astro +135 -68
- package/src/components/astro/RLABadge.astro +4 -2
- package/src/components/astro/RLABanner.astro +138 -23
- package/src/components/astro/RLABreadcrumb.astro +13 -0
- package/src/components/astro/RLAButton.astro +8 -4
- package/src/components/astro/RLACallout.astro +112 -0
- package/src/components/astro/RLACard.astro +6 -5
- package/src/components/astro/RLACarousel.astro +104 -75
- package/src/components/astro/RLAChart.astro +4 -1
- package/src/components/astro/RLAChip.astro +11 -5
- package/src/components/astro/RLACollapsible.astro +4 -1
- package/src/components/astro/RLAColorArea.astro +432 -0
- package/src/components/astro/RLAColorField.astro +300 -0
- package/src/components/astro/RLAColorSlider.astro +413 -0
- package/src/components/astro/RLAConfirm.astro +13 -11
- package/src/components/astro/RLACopyMarkdown.astro +78 -0
- package/src/components/astro/RLADate.astro +30 -0
- package/src/components/astro/RLADrawer.astro +50 -3
- package/src/components/astro/RLADropdownMenu.astro +78 -51
- package/src/components/astro/RLAFieldGroup.astro +4 -1
- package/src/components/astro/RLAFileUpload.astro +114 -100
- package/src/components/astro/RLAFooter.astro +2 -1
- package/src/components/astro/RLAFormField.astro +10 -6
- package/src/components/astro/RLAGrid.astro +31 -39
- package/src/components/astro/RLAHead.astro +139 -39
- package/src/components/astro/RLAHeader.astro +2 -1
- package/src/components/astro/RLAImage.astro +274 -251
- package/src/components/astro/RLAInput.astro +14 -9
- package/src/components/astro/RLAInputMenu.astro +119 -83
- package/src/components/astro/RLAKbd.astro +5 -5
- package/src/components/astro/RLALayoutGrid.astro +395 -0
- package/src/components/astro/RLALink.astro +23 -1
- package/src/components/astro/RLALinkGroup.astro +99 -99
- package/src/components/astro/RLALocaleSelector.astro +34 -41
- package/src/components/astro/RLALogo.astro +117 -90
- package/src/components/astro/RLAModal.astro +48 -18
- package/src/components/astro/RLANavigationMenu.astro +381 -326
- package/src/components/astro/{RLADocsPackageManagers.astro → RLAPackageManagers.astro} +81 -87
- package/src/components/astro/RLAPageSection.astro +4 -2
- package/src/components/astro/RLAPopover.astro +4 -3
- package/src/components/astro/RLAPost.astro +11 -2
- package/src/components/astro/RLAScrollArea.astro +4 -1
- package/src/components/astro/RLAScrollToTop.astro +200 -172
- package/src/components/astro/RLASearch.astro +282 -0
- package/src/components/astro/RLASelect.astro +78 -55
- package/src/components/astro/RLASeparator.astro +11 -6
- package/src/components/astro/RLAShare.astro +60 -0
- package/src/components/astro/RLAShortcuts.astro +429 -0
- package/src/components/astro/RLASidebar.astro +158 -212
- package/src/components/astro/RLASlideover.astro +47 -17
- package/src/components/astro/RLASplitter.astro +194 -141
- package/src/components/astro/RLASteps.astro +118 -71
- package/src/components/astro/RLASurround.astro +39 -0
- package/src/components/astro/RLATable.astro +4 -1
- package/src/components/astro/RLATableOfContents.astro +109 -23
- package/src/components/astro/RLATabs.astro +147 -133
- package/src/components/astro/RLATextarea.astro +4 -1
- package/src/components/astro/RLAThemeSelector.astro +105 -76
- package/src/components/astro/RLAToast.astro +35 -21
- package/src/components/vue/RLVBanner.vue +230 -0
- package/src/components/vue/RLVButton.vue +3 -2
- package/src/components/vue/RLVCheckbox.vue +4 -2
- package/src/components/vue/RLVFooter.vue +3 -2
- package/src/components/vue/RLVHeader.vue +3 -2
- package/src/components/vue/RLVIcon.vue +4 -2
- package/src/components/vue/RLVInput.vue +5 -4
- package/src/components/vue/RLVLogo.vue +25 -3
- package/src/components/vue/RLVPlaceholder.vue +3 -2
- package/src/components/vue/RLVPost.vue +8 -2
- package/src/components/vue/RLVProgress.vue +60 -0
- package/src/components/vue/RLVScrollToTop.vue +65 -52
- package/src/components/vue/RLVSection.vue +14 -13
- package/src/components/vue/RLVToast.vue +17 -4
- package/src/composables/index.ts +1 -0
- package/src/composables/useHeaderStore.ts +1 -0
- package/src/composables/useShortcuts.ts +11 -0
- package/src/config/security.ts +43 -36
- package/src/config/site.config.ts +1 -0
- package/src/docs/components/ApiChangelog.astro +147 -0
- package/src/{plugins/starlightDocsApi → docs}/components/ApiEmits.astro +4 -4
- package/src/{plugins/starlightDocsApi → docs}/components/ApiProps.astro +4 -4
- package/src/{plugins/starlightDocsApi → docs}/components/ApiSlots.astro +4 -4
- package/src/docs/components/ApiTheme.astro +100 -0
- package/src/docs/extractAll.ts +94 -0
- package/src/docs/extractors/extractAstro.ts +69 -0
- package/src/docs/extractors/extractTheme.ts +56 -0
- package/src/{plugins/starlightDocsApi/extract-vue.ts → docs/extractors/extractVue.ts} +164 -15
- package/src/{plugins/starlightDocsApi → docs}/utils.ts +1 -2
- package/src/env.d.ts +0 -12
- package/src/integrations/ui.ts +35 -19
- package/src/middleware/security.ts +75 -19
- package/src/presets/index.ts +118 -293
- package/src/styles/index.css +0 -2
- package/src/themes/accordion.theme.ts +29 -3
- package/src/themes/aspect-ratio.theme.ts +1 -1
- package/src/themes/avatar-group.theme.ts +1 -1
- package/src/themes/avatar.theme.ts +2 -2
- package/src/themes/badge.theme.ts +2 -3
- package/src/themes/banner.theme.ts +40 -4
- package/src/themes/breadcrumb.theme.ts +1 -1
- package/src/themes/button.theme.ts +21 -22
- package/src/themes/{alert.theme.ts → callout.theme.ts} +12 -39
- package/src/themes/card.theme.ts +17 -9
- package/src/themes/carousel.theme.ts +1 -1
- package/src/themes/checkbox.theme.ts +1 -2
- package/src/themes/chip.theme.ts +2 -3
- package/src/themes/color-area.theme.ts +33 -0
- package/src/themes/color-field.theme.ts +32 -0
- package/src/themes/color-slider.theme.ts +34 -0
- package/src/themes/confirm.theme.ts +1 -1
- package/src/themes/container.theme.ts +1 -1
- package/src/themes/drawer.theme.ts +1 -1
- package/src/themes/footer.theme.ts +2 -2
- package/src/themes/grid.theme.ts +38 -0
- package/src/themes/header.theme.ts +4 -3
- package/src/themes/hover-card.theme.ts +1 -1
- package/src/themes/image.theme.ts +11 -1
- package/src/themes/input.theme.ts +7 -1
- package/src/themes/kbd.theme.ts +2 -3
- package/src/themes/label.theme.ts +1 -1
- package/src/themes/layout-grid.theme.ts +16 -0
- package/src/themes/link-group.theme.ts +0 -4
- package/src/themes/marquee.theme.ts +1 -1
- package/src/themes/modal.theme.ts +1 -1
- package/src/themes/navigation-menu.theme.ts +2 -2
- package/src/themes/page-section.theme.ts +4 -2
- package/src/themes/pagination.theme.ts +1 -1
- package/src/themes/pin-input.theme.ts +1 -1
- package/src/themes/popover.theme.ts +1 -1
- package/src/themes/post.theme.ts +23 -3
- package/src/themes/progress.theme.ts +1 -2
- package/src/themes/scroll-to-top.theme.ts +2 -3
- package/src/themes/search.theme.ts +64 -0
- package/src/themes/separator.theme.ts +1 -1
- package/src/themes/slideover.theme.ts +1 -1
- package/src/themes/slider.theme.ts +1 -2
- package/src/themes/spinner.theme.ts +1 -2
- package/src/themes/{megamenu.theme.ts → steps.theme.ts} +3 -3
- package/src/themes/sticky-surface.theme.ts +1 -1
- package/src/themes/switch.theme.ts +1 -2
- package/src/themes/table-of-contents.theme.ts +21 -2
- package/src/themes/timeline.theme.ts +7 -2
- package/src/themes/toast.theme.ts +1 -1
- package/src/types/components/accordion.ts +35 -2
- package/src/types/components/avatar.ts +16 -0
- package/src/types/components/banner.ts +42 -0
- package/src/types/components/button.ts +3 -4
- package/src/types/components/{alert.ts → callout.ts} +6 -6
- package/src/types/components/color-area.ts +19 -0
- package/src/types/components/color-field.ts +21 -0
- package/src/types/components/color-slider.ts +20 -0
- package/src/types/components/grid.ts +23 -0
- package/src/types/components/input.ts +4 -0
- package/src/types/components/layout-grid.ts +145 -0
- package/src/types/components/link-group.ts +4 -2
- package/src/types/components/link.ts +15 -0
- package/src/types/components/logo.ts +3 -3
- package/src/types/components/post.ts +12 -0
- package/src/types/components/search.ts +29 -0
- package/src/types/components/sidebar.ts +2 -6
- package/src/types/components/{megamenu.ts → steps.ts} +7 -1
- package/src/types/components/table-of-contents.ts +22 -0
- package/src/types/components/toast.ts +4 -0
- package/src/types/docs.ts +40 -0
- package/src/types/index.ts +151 -1
- package/src/types/theme.ts +6 -6
- package/src/utils/color.ts +165 -0
- package/src/utils/docs.ts +260 -110
- package/src/utils/headerStack.ts +24 -4
- package/src/utils/index.ts +2 -0
- package/src/utils/shortcuts.ts +322 -0
- package/src/components/TableOfContents.astro +0 -107
- package/src/components/astro/RLAAlert.astro +0 -93
- package/src/components/astro/RLAChangelog.astro +0 -23
- package/src/components/astro/RLAMegamenu.astro +0 -23
- package/src/plugins/index.ts +0 -2
- package/src/plugins/starlightDocsApi/components/ApiTheme.astro +0 -27
- package/src/plugins/starlightDocsApi/index.ts +0 -272
- package/src/styles/prism.css +0 -42
- package/src/themes/changelog.theme.ts +0 -13
- package/src/types/components/index.ts +0 -134
- /package/src/{plugins/starlightDocsApi → docs}/types.ts +0 -0
|
@@ -4,8 +4,9 @@ import { useUi, resolveClasses } from "../../utils"
|
|
|
4
4
|
import type { ScrollToTopProps } from "../../types/components/scroll-to-top"
|
|
5
5
|
import scrollToTopTheme from "../../themes/scroll-to-top.theme"
|
|
6
6
|
import { useScrollToTop } from "../../composables/useScrollToTop"
|
|
7
|
-
import { computed } from "vue"
|
|
7
|
+
import { computed, onMounted, onUnmounted, watch, useAttrs } from "vue"
|
|
8
8
|
|
|
9
|
+
const attrs = useAttrs()
|
|
9
10
|
const scrollToTop = scv(scrollToTopTheme)
|
|
10
11
|
|
|
11
12
|
const {
|
|
@@ -28,49 +29,49 @@ const {
|
|
|
28
29
|
threshold
|
|
29
30
|
})
|
|
30
31
|
|
|
31
|
-
const
|
|
32
|
-
const
|
|
32
|
+
const instanceId = `rla-vue-${Math.random().toString(36).slice(2, 8)}`
|
|
33
|
+
const gaugeBorderWidth = progressWidth * 0.5
|
|
33
34
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
let styleEl: HTMLStyleElement | null = null
|
|
36
|
+
|
|
37
|
+
function updateCssVars() {
|
|
38
|
+
if (!styleEl) return
|
|
39
|
+
styleEl.textContent = `
|
|
40
|
+
[data-rla-instance="${instanceId}"] {
|
|
41
|
+
--gauge-track-border-color: var(--color-${color}-900);
|
|
42
|
+
--gauge-track-bg: var(--color-${color}-950);
|
|
43
|
+
--gauge-stroke-width: ${gaugeBorderWidth}px;
|
|
44
|
+
--gauge-color: var(--color-${color}-500);
|
|
45
|
+
--gauge-progress: ${scrollPercentage.value};
|
|
46
|
+
}
|
|
47
|
+
`
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
watch(scrollPercentage, updateCssVars)
|
|
51
|
+
|
|
52
|
+
onMounted(() => {
|
|
53
|
+
const nonce = document.querySelector('meta[name="csp-nonce"]')?.getAttribute("content") ?? ""
|
|
54
|
+
styleEl = document.createElement("style")
|
|
55
|
+
if (nonce) styleEl.setAttribute("nonce", nonce)
|
|
56
|
+
document.head.appendChild(styleEl)
|
|
57
|
+
updateCssVars()
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
onUnmounted(() => {
|
|
61
|
+
if (styleEl) styleEl.remove()
|
|
62
|
+
})
|
|
37
63
|
</script>
|
|
38
64
|
|
|
39
65
|
<template>
|
|
40
66
|
<div
|
|
67
|
+
:data-rla-instance="instanceId"
|
|
41
68
|
:class="['rla-scroll-to-top fixed bottom-6 right-6 z-50', { visible: isVisible }, classes.root]"
|
|
42
|
-
v-bind="
|
|
69
|
+
v-bind="attrs"
|
|
43
70
|
>
|
|
44
71
|
<button type="button" :class="classes.button" aria-label="Scroll to top" @click="scrollToTopFn">
|
|
45
72
|
<div :class="classes.progressBase">
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
cx="50"
|
|
49
|
-
cy="50"
|
|
50
|
-
r="45"
|
|
51
|
-
fill="var(--color-primary-950)"
|
|
52
|
-
:stroke-width="progressWidth"
|
|
53
|
-
stroke-dashoffset="0"
|
|
54
|
-
stroke-linecap="round"
|
|
55
|
-
class="gauge-secondary-stroke opacity-100"
|
|
56
|
-
/>
|
|
57
|
-
<circle
|
|
58
|
-
v-if="showProgress"
|
|
59
|
-
cx="50"
|
|
60
|
-
cy="50"
|
|
61
|
-
r="45"
|
|
62
|
-
fill="transparent"
|
|
63
|
-
:stroke-width="progressWidth"
|
|
64
|
-
stroke-linecap="round"
|
|
65
|
-
class="gauge-primary-stroke opacity-100"
|
|
66
|
-
:style="{
|
|
67
|
-
'--stroke-percent': currentPercent,
|
|
68
|
-
'--percent-to-px': percentageInPx,
|
|
69
|
-
'--circumference': circumference,
|
|
70
|
-
'--duration': durationInSeconds
|
|
71
|
-
}"
|
|
72
|
-
/>
|
|
73
|
-
</svg>
|
|
73
|
+
<div class="gauge-track"></div>
|
|
74
|
+
<div v-if="showProgress" class="gauge-progress"></div>
|
|
74
75
|
<div :class="classes.iconContainer">
|
|
75
76
|
<svg
|
|
76
77
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -106,27 +107,39 @@ const durationInSeconds = computed(() => `${duration}s`)
|
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
.progress-circle-base {
|
|
110
|
+
position: relative;
|
|
109
111
|
transform: translateZ(0);
|
|
110
112
|
}
|
|
111
113
|
|
|
112
|
-
.gauge-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
stroke v-bind(durationInSeconds) ease;
|
|
121
|
-
transform: rotate(-90deg);
|
|
122
|
-
transform-origin: center;
|
|
123
|
-
shape-rendering: geometricPrecision;
|
|
114
|
+
.gauge-track {
|
|
115
|
+
position: absolute;
|
|
116
|
+
inset: 0;
|
|
117
|
+
border-radius: 50%;
|
|
118
|
+
border-style: solid;
|
|
119
|
+
border-width: var(--gauge-stroke-width, 3px);
|
|
120
|
+
border-color: var(--gauge-track-border-color, var(--color-primary-900));
|
|
121
|
+
background-color: var(--gauge-track-bg, var(--color-primary-950));
|
|
124
122
|
}
|
|
125
123
|
|
|
126
|
-
.gauge-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
124
|
+
.gauge-progress {
|
|
125
|
+
position: absolute;
|
|
126
|
+
inset: 0;
|
|
127
|
+
border-radius: 50%;
|
|
128
|
+
background: conic-gradient(
|
|
129
|
+
from 0deg,
|
|
130
|
+
var(--gauge-color, var(--color-primary-500)) 0deg,
|
|
131
|
+
var(--gauge-color, var(--color-primary-500)) calc(var(--gauge-progress, 0) * 3.6deg),
|
|
132
|
+
transparent calc(var(--gauge-progress, 0) * 3.6deg)
|
|
133
|
+
);
|
|
134
|
+
-webkit-mask: radial-gradient(
|
|
135
|
+
circle closest-side,
|
|
136
|
+
transparent calc(100% - var(--gauge-stroke-width, 3px)),
|
|
137
|
+
#000 calc(100% - var(--gauge-stroke-width, 3px))
|
|
138
|
+
);
|
|
139
|
+
mask: radial-gradient(
|
|
140
|
+
circle closest-side,
|
|
141
|
+
transparent calc(100% - var(--gauge-stroke-width, 3px)),
|
|
142
|
+
#000 calc(100% - var(--gauge-stroke-width, 3px))
|
|
143
|
+
);
|
|
131
144
|
}
|
|
132
145
|
</style>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed, useSlots } from "vue"
|
|
2
|
+
import { computed, useSlots, useAttrs } from "vue"
|
|
3
3
|
import { scv } from "css-variants"
|
|
4
4
|
import { useUi, resolveClasses } from "../../utils"
|
|
5
5
|
import type { PageSectionProps } from "../../types/components/page-section"
|
|
@@ -24,6 +24,7 @@ const {
|
|
|
24
24
|
links
|
|
25
25
|
} = defineProps<PageSectionProps>()
|
|
26
26
|
|
|
27
|
+
const attrs = useAttrs()
|
|
27
28
|
const slots = useSlots()
|
|
28
29
|
|
|
29
30
|
const resolvedClasses = computed(() =>
|
|
@@ -51,9 +52,9 @@ const resolvedClasses = computed(() =>
|
|
|
51
52
|
data-slot="root"
|
|
52
53
|
:data-orientation="orientation"
|
|
53
54
|
:class="[resolvedClasses.root]"
|
|
54
|
-
v-bind="
|
|
55
|
+
v-bind="attrs"
|
|
55
56
|
>
|
|
56
|
-
<slot v-if="
|
|
57
|
+
<slot v-if="slots.background" name="background">
|
|
57
58
|
<div :class="resolvedClasses.background" data-slot="background">
|
|
58
59
|
<slot name="background" />
|
|
59
60
|
</div>
|
|
@@ -64,26 +65,26 @@ const resolvedClasses = computed(() =>
|
|
|
64
65
|
<div data-slot="container" :class="resolvedClasses.container">
|
|
65
66
|
<div
|
|
66
67
|
v-if="
|
|
67
|
-
|
|
68
|
+
slots.header ||
|
|
68
69
|
icon ||
|
|
69
70
|
headline ||
|
|
70
71
|
title ||
|
|
71
72
|
description ||
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
slots.body ||
|
|
74
|
+
slots.footer ||
|
|
75
|
+
slots.links ||
|
|
75
76
|
links?.length
|
|
76
77
|
"
|
|
77
78
|
data-slot="wrapper"
|
|
78
79
|
:class="resolvedClasses.wrapper"
|
|
79
80
|
>
|
|
80
81
|
<div
|
|
81
|
-
v-if="
|
|
82
|
+
v-if="slots.header || icon || headline || title || description"
|
|
82
83
|
data-slot="header"
|
|
83
84
|
:class="resolvedClasses.header"
|
|
84
85
|
>
|
|
85
86
|
<slot name="header">
|
|
86
|
-
<div v-if="icon ||
|
|
87
|
+
<div v-if="icon || slots.leading" data-slot="leading" :class="resolvedClasses.leading">
|
|
87
88
|
<slot name="leading" :ui="resolvedClasses">
|
|
88
89
|
<RLVIcon
|
|
89
90
|
v-if="icon"
|
|
@@ -119,18 +120,18 @@ const resolvedClasses = computed(() =>
|
|
|
119
120
|
</slot>
|
|
120
121
|
</div>
|
|
121
122
|
|
|
122
|
-
<div v-if="
|
|
123
|
+
<div v-if="slots.body" data-slot="body" :class="resolvedClasses.body">
|
|
123
124
|
<slot name="body" />
|
|
124
125
|
</div>
|
|
125
126
|
|
|
126
127
|
<div
|
|
127
|
-
v-if="
|
|
128
|
+
v-if="slots.footer || slots.links || links?.length"
|
|
128
129
|
data-slot="footer"
|
|
129
130
|
:class="resolvedClasses.footer"
|
|
130
131
|
>
|
|
131
132
|
<slot name="footer">
|
|
132
133
|
<div
|
|
133
|
-
v-if="links?.length ||
|
|
134
|
+
v-if="links?.length || slots.links"
|
|
134
135
|
data-slot="links"
|
|
135
136
|
:class="resolvedClasses.links"
|
|
136
137
|
>
|
|
@@ -141,7 +142,7 @@ const resolvedClasses = computed(() =>
|
|
|
141
142
|
</div>
|
|
142
143
|
</div>
|
|
143
144
|
|
|
144
|
-
<slot v-if="
|
|
145
|
+
<slot v-if="slots.default" />
|
|
145
146
|
<div v-else-if="orientation === 'horizontal'" class="hidden lg:block" />
|
|
146
147
|
</div>
|
|
147
148
|
|
|
@@ -49,11 +49,24 @@ const icon = computed(() => variantIcons[props.variant] ?? variantIcons.default!
|
|
|
49
49
|
{{ description }}
|
|
50
50
|
</div>
|
|
51
51
|
<slot />
|
|
52
|
-
</div>
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
<div
|
|
54
|
+
v-if="$slots.actions || actionLabel"
|
|
55
|
+
class="flex items-center justify-end gap-2 mt-3"
|
|
56
|
+
data-slot="actions"
|
|
57
|
+
>
|
|
58
|
+
<slot name="actions">
|
|
59
|
+
<button
|
|
60
|
+
v-if="actionLabel"
|
|
61
|
+
type="button"
|
|
62
|
+
:class="resolvedClasses.action"
|
|
63
|
+
data-slot="action"
|
|
64
|
+
>
|
|
65
|
+
{{ actionLabel }}
|
|
66
|
+
</button>
|
|
67
|
+
</slot>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
57
70
|
|
|
58
71
|
<button
|
|
59
72
|
type="button"
|
package/src/composables/index.ts
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { onUnmounted } from "vue"
|
|
2
|
+
import { defineShortcuts } from "../utils/shortcuts"
|
|
3
|
+
import type { ShortcutsConfig, ShortcutsOptions } from "../utils/shortcuts"
|
|
4
|
+
|
|
5
|
+
export function useShortcuts(config: ShortcutsConfig, options?: ShortcutsOptions) {
|
|
6
|
+
const cleanup = defineShortcuts(config, options)
|
|
7
|
+
onUnmounted(() => {
|
|
8
|
+
cleanup()
|
|
9
|
+
})
|
|
10
|
+
return cleanup
|
|
11
|
+
}
|
package/src/config/security.ts
CHANGED
|
@@ -33,6 +33,10 @@ export interface SecurityConfigOptions {
|
|
|
33
33
|
* Additional style resources
|
|
34
34
|
*/
|
|
35
35
|
styleResources?: string[]
|
|
36
|
+
/**
|
|
37
|
+
* Enables the 'require-trusted-types-for' directive
|
|
38
|
+
*/
|
|
39
|
+
trustedTypes?: boolean
|
|
36
40
|
/**
|
|
37
41
|
* Direct overrides for any security config fields
|
|
38
42
|
*/
|
|
@@ -46,46 +50,46 @@ export interface SecurityConfigOptions {
|
|
|
46
50
|
* support for easy customization and additions per project.
|
|
47
51
|
*
|
|
48
52
|
* @example
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
53
|
+
* ;```ts
|
|
54
|
+
* // Default returned shape:
|
|
55
|
+
* {
|
|
52
56
|
* checkOrigin: true,
|
|
53
57
|
* allowedDomains: [
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
+
* {
|
|
59
|
+
* hostname: "**.domain.com",
|
|
60
|
+
* protocol: "https"
|
|
61
|
+
* }
|
|
58
62
|
* ],
|
|
59
63
|
* csp: {
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
64
|
+
* algorithm: "SHA-384",
|
|
65
|
+
* directives: [
|
|
66
|
+
* "default-src 'none'",
|
|
67
|
+
* "img-src 'self' data: https://cdn.domain.com https://i3.ytimg.com https://www.youtube.com https://www.youtube-nocookie.com",
|
|
68
|
+
* "font-src 'self'",
|
|
69
|
+
* "connect-src 'self' https://cloudflareinsights.com",
|
|
70
|
+
* "frame-ancestors 'none'",
|
|
71
|
+
* "frame-src https://www.youtube.com https://www.youtube-nocookie.com",
|
|
72
|
+
* "upgrade-insecure-requests",
|
|
73
|
+
* "base-uri 'self'",
|
|
74
|
+
* "form-action 'self'"
|
|
75
|
+
* ],
|
|
76
|
+
* scriptDirective: {
|
|
77
|
+
* resources: [
|
|
78
|
+
* "'self'",
|
|
79
|
+
* "https://static.cloudflareinsights.com",
|
|
80
|
+
* "https://betterlytics.io/analytics.js",
|
|
81
|
+
* "'inline-speculation-rules'"
|
|
82
|
+
* ]
|
|
83
|
+
* },
|
|
84
|
+
* styleDirective: {
|
|
85
|
+
* resources: [
|
|
86
|
+
* "'self'",
|
|
87
|
+
* "'sha256-SKuaOGnks7NAUq37nvw1PfGEE0lOAs5ERbiYRbGFIbw='"
|
|
88
|
+
* ]
|
|
89
|
+
* }
|
|
90
|
+
* }
|
|
86
91
|
* }
|
|
87
|
-
*
|
|
88
|
-
* ```
|
|
92
|
+
* ```
|
|
89
93
|
*/
|
|
90
94
|
export function defineSecurity(options: SecurityConfigOptions): AstroSecurityConfig {
|
|
91
95
|
const { domain, overrides } = options
|
|
@@ -134,7 +138,10 @@ export function defineSecurity(options: SecurityConfigOptions): AstroSecurityCon
|
|
|
134
138
|
`frame-src ${frameSources.join(" ")}`,
|
|
135
139
|
"upgrade-insecure-requests",
|
|
136
140
|
"base-uri 'self'",
|
|
137
|
-
"form-action 'self'"
|
|
141
|
+
"form-action 'self'",
|
|
142
|
+
"object-src 'none'",
|
|
143
|
+
"manifest-src 'self'",
|
|
144
|
+
...(options.trustedTypes ? ["require-trusted-types-for 'script'" as const] : [])
|
|
138
145
|
]
|
|
139
146
|
|
|
140
147
|
// 3. Build script & style directives
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
import RLATimeline from "../../components/astro/RLATimeline.astro"
|
|
3
|
+
import { scv } from "css-variants"
|
|
4
|
+
import { useUi, resolveClasses } from "../../utils"
|
|
5
|
+
import timelineThemeDefault, { createTimelineTheme } from "../../themes/timeline.theme"
|
|
6
|
+
import { getUIConfig } from "virtual:rimelight-ui"
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
component: string
|
|
10
|
+
ui?: any
|
|
11
|
+
class?: any
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { component, ui: uiProp, class: className } = Astro.props
|
|
15
|
+
|
|
16
|
+
const uiConfig = getUIConfig()
|
|
17
|
+
const timelineTheme = uiConfig.colors ? createTimelineTheme() : timelineThemeDefault
|
|
18
|
+
const timeline = scv(timelineTheme)
|
|
19
|
+
const classes = resolveClasses(timeline, {}, useUi("timeline", uiProp), className);
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
<div class="api-changelog-container group" data-component={component} data-theme-classes={JSON.stringify(classes)}>
|
|
23
|
+
<!-- Loading skeleton -->
|
|
24
|
+
<div class="api-changelog-loading py-6 flex flex-col gap-4">
|
|
25
|
+
<div class="animate-pulse h-4 bg-gray-800 rounded w-1/4"></div>
|
|
26
|
+
<div class="animate-pulse h-3 bg-gray-850 rounded w-full"></div>
|
|
27
|
+
<div class="animate-pulse h-3 bg-gray-850 rounded w-5/6"></div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<!-- Timeline Content -->
|
|
31
|
+
<div class="api-changelog-content hidden">
|
|
32
|
+
<RLATimeline ui={uiProp} class={className}>
|
|
33
|
+
<!-- Dynamic timeline items insert here -->
|
|
34
|
+
<div class="api-changelog-list flex flex-col space-y-8"></div>
|
|
35
|
+
</RLATimeline>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="api-changelog-empty hidden text-sm italic text-gray-500 py-2">
|
|
39
|
+
No recent changes found.
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<script>
|
|
44
|
+
function escapeHtml(str: string): string {
|
|
45
|
+
return str
|
|
46
|
+
.replace(/&/g, "&")
|
|
47
|
+
.replace(/</g, "<")
|
|
48
|
+
.replace(/>/g, ">")
|
|
49
|
+
.replace(/"/g, """)
|
|
50
|
+
.replace(/'/g, "'");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function loadChangelog() {
|
|
54
|
+
if (typeof document === "undefined") return;
|
|
55
|
+
const containers = document.querySelectorAll('.api-changelog-container');
|
|
56
|
+
|
|
57
|
+
await Promise.all(
|
|
58
|
+
Array.from(containers).map(async (container) => {
|
|
59
|
+
if (container.getAttribute('data-changelog-ready') === 'true') return;
|
|
60
|
+
container.setAttribute('data-changelog-ready', 'true');
|
|
61
|
+
|
|
62
|
+
const component = container.getAttribute('data-component');
|
|
63
|
+
const themeClassesJson = container.getAttribute('data-theme-classes');
|
|
64
|
+
const themeClasses = themeClassesJson ? JSON.parse(themeClassesJson) : {};
|
|
65
|
+
|
|
66
|
+
const loadingEl = container.querySelector('.api-changelog-loading') as HTMLElement;
|
|
67
|
+
const contentEl = container.querySelector('.api-changelog-content') as HTMLElement;
|
|
68
|
+
const listEl = container.querySelector('.api-changelog-list') as HTMLElement;
|
|
69
|
+
const emptyEl = container.querySelector('.api-changelog-empty') as HTMLElement;
|
|
70
|
+
|
|
71
|
+
if (!component || !loadingEl || !contentEl || !listEl || !emptyEl) return;
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
const res = await fetch(`/api/github/changelog?component=${component}`);
|
|
75
|
+
if (!res.ok) throw new Error();
|
|
76
|
+
const data = await res.json();
|
|
77
|
+
|
|
78
|
+
loadingEl.classList.add('hidden');
|
|
79
|
+
|
|
80
|
+
if (!data || data.length === 0) {
|
|
81
|
+
emptyEl.classList.remove('hidden');
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let html = '';
|
|
86
|
+
for (const item of data) {
|
|
87
|
+
const dateStr = item.published_at
|
|
88
|
+
? new Date(item.published_at).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' })
|
|
89
|
+
: 'Unreleased';
|
|
90
|
+
|
|
91
|
+
html += `
|
|
92
|
+
<div class="${themeClasses.node || 'relative timeline-node'}">
|
|
93
|
+
<!-- Dot Indicator -->
|
|
94
|
+
<span class="${themeClasses.dot || 'absolute -left-[33px] top-[2px] flex h-4 w-4 items-center justify-center rounded-full bg-gray-950 ring-2 ring-gray-800'}">
|
|
95
|
+
<span class="${themeClasses.dotInner || 'h-2 w-2 rounded-full bg-primary-500'}"></span>
|
|
96
|
+
</span>
|
|
97
|
+
|
|
98
|
+
<div class="${themeClasses.header || 'flex items-center justify-between gap-4 mb-3'}">
|
|
99
|
+
<div class="flex items-center gap-2">
|
|
100
|
+
<span class="inline-flex items-center px-2 py-0.5 rounded text-xs font-semibold bg-primary-500/10 text-primary-400 border border-primary-500/20">
|
|
101
|
+
${escapeHtml(item.tag === 'unreleased' ? 'Soon' : item.tag)}
|
|
102
|
+
</span>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<time class="text-xs text-gray-500 font-normal">
|
|
106
|
+
${escapeHtml(dateStr)}
|
|
107
|
+
</time>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<ul class="${themeClasses.content || 'space-y-2 text-sm text-gray-400'}">
|
|
111
|
+
${item.commits.map((commit: any) => {
|
|
112
|
+
const cleanedMessage = commit.message
|
|
113
|
+
.replace(/#(\d+)/g, '<a href="https://github.com/Rimelight-Entertainment/rimelight/issues/$1" target="_blank" class="text-primary-400 hover:underline">#$1</a>')
|
|
114
|
+
.replace(/`(.*?)`/g, '<code class="text-xs px-1 bg-gray-900 border border-gray-800 rounded font-mono text-gray-300">$1</code>');
|
|
115
|
+
|
|
116
|
+
return `
|
|
117
|
+
<li class="flex items-start gap-2">
|
|
118
|
+
<a href="https://github.com/Rimelight-Entertainment/rimelight/commit/${commit.sha}" target="_blank" class="font-mono text-xs text-gray-500 hover:text-gray-300 hover:underline shrink-0 pt-0.5">
|
|
119
|
+
${commit.sha.slice(0, 7)}
|
|
120
|
+
</a>
|
|
121
|
+
<span class="text-gray-300">
|
|
122
|
+
${cleanedMessage}
|
|
123
|
+
</span>
|
|
124
|
+
</li>
|
|
125
|
+
`;
|
|
126
|
+
}).join('')}
|
|
127
|
+
</ul>
|
|
128
|
+
</div>
|
|
129
|
+
`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
listEl.innerHTML = html;
|
|
133
|
+
contentEl.classList.remove('hidden');
|
|
134
|
+
} catch (err) {
|
|
135
|
+
loadingEl.classList.add('hidden');
|
|
136
|
+
emptyEl.textContent = 'Failed to load changelog.';
|
|
137
|
+
emptyEl.classList.remove('hidden');
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (typeof document !== 'undefined') {
|
|
144
|
+
loadChangelog();
|
|
145
|
+
document.addEventListener('astro:after-swap', loadChangelog);
|
|
146
|
+
}
|
|
147
|
+
</script>
|
|
@@ -29,14 +29,14 @@ const emits = compMeta?.emits ?? []
|
|
|
29
29
|
{emits.map((emit: EmitMeta) => (
|
|
30
30
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
31
31
|
<td class="py-2 px-3">
|
|
32
|
-
<
|
|
32
|
+
<span class="font-mono text-sm">
|
|
33
33
|
{emit.name}
|
|
34
|
-
</
|
|
34
|
+
</span>
|
|
35
35
|
</td>
|
|
36
36
|
<td class="py-2 px-3">
|
|
37
|
-
<
|
|
37
|
+
<span class="font-mono text-xs text-gray-600 dark:text-gray-400">
|
|
38
38
|
{emit.type}
|
|
39
|
-
</
|
|
39
|
+
</span>
|
|
40
40
|
</td>
|
|
41
41
|
</tr>
|
|
42
42
|
))}
|
|
@@ -33,15 +33,15 @@ const props = filterProps(compMeta?.props ?? [], filterOpts)
|
|
|
33
33
|
<tbody>
|
|
34
34
|
{props.map((prop: PropMeta) => (
|
|
35
35
|
<tr>
|
|
36
|
-
<td><
|
|
37
|
-
<td><
|
|
36
|
+
<td><span class="font-mono text-sm">{prop.name}</span></td>
|
|
37
|
+
<td><span class="font-mono text-xs text-gray-600 dark:text-gray-400">{prop.type}</span></td>
|
|
38
38
|
<td>{prop.required ? "Yes" : "No"}</td>
|
|
39
|
-
<td>{prop.default !== undefined ? <
|
|
39
|
+
<td>{prop.default !== undefined ? <span class="font-mono text-xs text-gray-600 dark:text-gray-400">{prop.default}</span> : "—"}</td>
|
|
40
40
|
<td>{prop.description || "—"}</td>
|
|
41
41
|
</tr>
|
|
42
42
|
))}
|
|
43
43
|
</tbody>
|
|
44
44
|
</table>
|
|
45
45
|
) : (
|
|
46
|
-
<p>No props to display.</p>
|
|
46
|
+
<p class="text-sm italic text-gray-500">No props to display.</p>
|
|
47
47
|
)}
|
|
@@ -29,15 +29,15 @@ const slots = compMeta?.slots ?? []
|
|
|
29
29
|
{slots.map((slot: SlotMeta) => (
|
|
30
30
|
<tr class="border-b border-gray-100 dark:border-gray-800">
|
|
31
31
|
<td class="py-2 px-3">
|
|
32
|
-
<
|
|
32
|
+
<span class="font-mono text-sm">
|
|
33
33
|
{slot.name}
|
|
34
|
-
</
|
|
34
|
+
</span>
|
|
35
35
|
</td>
|
|
36
36
|
<td class="py-2 px-3">
|
|
37
37
|
{Object.keys(slot.bindings).length > 0 ? (
|
|
38
|
-
<
|
|
38
|
+
<span class="font-mono text-xs text-gray-600 dark:text-gray-400">
|
|
39
39
|
{Object.values(slot.bindings)[0]}
|
|
40
|
-
</
|
|
40
|
+
</span>
|
|
41
41
|
) : (
|
|
42
42
|
<span class="text-gray-400">-</span>
|
|
43
43
|
)}
|