@rimelight/ui 0.0.34 → 0.0.35

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 (185) hide show
  1. package/README.md +1 -0
  2. package/package.json +19 -24
  3. package/src/components/astro/RLAAccordion.astro +94 -18
  4. package/src/components/astro/RLAAvatar.astro +135 -68
  5. package/src/components/astro/RLABadge.astro +4 -2
  6. package/src/components/astro/RLABanner.astro +138 -23
  7. package/src/components/astro/RLABreadcrumb.astro +13 -0
  8. package/src/components/astro/RLAButton.astro +8 -4
  9. package/src/components/astro/RLACallout.astro +112 -0
  10. package/src/components/astro/RLACard.astro +6 -5
  11. package/src/components/astro/RLACarousel.astro +104 -75
  12. package/src/components/astro/RLAChart.astro +4 -1
  13. package/src/components/astro/RLAChip.astro +11 -5
  14. package/src/components/astro/RLACollapsible.astro +4 -1
  15. package/src/components/astro/RLAColorArea.astro +432 -0
  16. package/src/components/astro/RLAColorField.astro +300 -0
  17. package/src/components/astro/RLAColorSlider.astro +413 -0
  18. package/src/components/astro/RLAConfirm.astro +13 -11
  19. package/src/components/astro/RLACopyMarkdown.astro +78 -0
  20. package/src/components/astro/RLADate.astro +30 -0
  21. package/src/components/astro/RLADrawer.astro +50 -3
  22. package/src/components/astro/RLADropdownMenu.astro +78 -51
  23. package/src/components/astro/RLAFieldGroup.astro +4 -1
  24. package/src/components/astro/RLAFileUpload.astro +114 -100
  25. package/src/components/astro/RLAFooter.astro +2 -1
  26. package/src/components/astro/RLAFormField.astro +10 -6
  27. package/src/components/astro/RLAGrid.astro +31 -39
  28. package/src/components/astro/RLAHead.astro +139 -39
  29. package/src/components/astro/RLAHeader.astro +2 -1
  30. package/src/components/astro/RLAImage.astro +274 -251
  31. package/src/components/astro/RLAInput.astro +14 -9
  32. package/src/components/astro/RLAInputMenu.astro +119 -83
  33. package/src/components/astro/RLAKbd.astro +5 -5
  34. package/src/components/astro/RLALayoutGrid.astro +395 -0
  35. package/src/components/astro/RLALink.astro +23 -1
  36. package/src/components/astro/RLALinkGroup.astro +99 -99
  37. package/src/components/astro/RLALocaleSelector.astro +29 -35
  38. package/src/components/astro/RLALogo.astro +117 -90
  39. package/src/components/astro/RLAModal.astro +48 -18
  40. package/src/components/astro/RLANavigationMenu.astro +381 -326
  41. package/src/components/astro/{RLADocsPackageManagers.astro → RLAPackageManagers.astro} +81 -87
  42. package/src/components/astro/RLAPageSection.astro +4 -2
  43. package/src/components/astro/RLAPopover.astro +4 -3
  44. package/src/components/astro/RLAPost.astro +11 -2
  45. package/src/components/astro/RLAScrollArea.astro +4 -1
  46. package/src/components/astro/RLAScrollToTop.astro +200 -172
  47. package/src/components/astro/RLASearch.astro +282 -0
  48. package/src/components/astro/RLASelect.astro +78 -55
  49. package/src/components/astro/RLASeparator.astro +11 -6
  50. package/src/components/astro/RLAShare.astro +60 -0
  51. package/src/components/astro/RLAShortcuts.astro +429 -0
  52. package/src/components/astro/RLASidebar.astro +158 -212
  53. package/src/components/astro/RLASlideover.astro +47 -17
  54. package/src/components/astro/RLASplitter.astro +194 -141
  55. package/src/components/astro/RLASteps.astro +118 -71
  56. package/src/components/astro/RLASurround.astro +39 -0
  57. package/src/components/astro/RLATable.astro +4 -1
  58. package/src/components/astro/RLATableOfContents.astro +109 -23
  59. package/src/components/astro/RLATabs.astro +147 -133
  60. package/src/components/astro/RLATextarea.astro +4 -1
  61. package/src/components/astro/RLAThemeSelector.astro +105 -76
  62. package/src/components/astro/RLAToast.astro +35 -21
  63. package/src/components/vue/RLVBanner.vue +230 -0
  64. package/src/components/vue/RLVButton.vue +3 -2
  65. package/src/components/vue/RLVCheckbox.vue +4 -2
  66. package/src/components/vue/RLVFooter.vue +3 -2
  67. package/src/components/vue/RLVHeader.vue +3 -2
  68. package/src/components/vue/RLVIcon.vue +4 -2
  69. package/src/components/vue/RLVInput.vue +5 -4
  70. package/src/components/vue/RLVLogo.vue +25 -3
  71. package/src/components/vue/RLVPlaceholder.vue +3 -2
  72. package/src/components/vue/RLVPost.vue +8 -2
  73. package/src/components/vue/RLVProgress.vue +60 -0
  74. package/src/components/vue/RLVScrollToTop.vue +65 -52
  75. package/src/components/vue/RLVSection.vue +14 -13
  76. package/src/components/vue/RLVToast.vue +17 -4
  77. package/src/composables/index.ts +1 -0
  78. package/src/composables/useHeaderStore.ts +1 -0
  79. package/src/composables/useShortcuts.ts +11 -0
  80. package/src/config/security.ts +43 -36
  81. package/src/config/site.config.ts +1 -0
  82. package/src/docs/components/ApiChangelog.astro +147 -0
  83. package/src/{plugins/starlightDocsApi → docs}/components/ApiEmits.astro +4 -4
  84. package/src/{plugins/starlightDocsApi → docs}/components/ApiProps.astro +4 -4
  85. package/src/{plugins/starlightDocsApi → docs}/components/ApiSlots.astro +4 -4
  86. package/src/docs/components/ApiTheme.astro +100 -0
  87. package/src/docs/extractAll.ts +94 -0
  88. package/src/docs/extractors/extractAstro.ts +69 -0
  89. package/src/docs/extractors/extractTheme.ts +56 -0
  90. package/src/{plugins/starlightDocsApi/extract-vue.ts → docs/extractors/extractVue.ts} +164 -15
  91. package/src/{plugins/starlightDocsApi → docs}/utils.ts +1 -2
  92. package/src/env.d.ts +0 -12
  93. package/src/integrations/ui.ts +35 -19
  94. package/src/middleware/security.ts +75 -19
  95. package/src/presets/index.ts +118 -293
  96. package/src/styles/index.css +0 -2
  97. package/src/themes/accordion.theme.ts +29 -3
  98. package/src/themes/aspect-ratio.theme.ts +1 -1
  99. package/src/themes/avatar-group.theme.ts +1 -1
  100. package/src/themes/avatar.theme.ts +2 -2
  101. package/src/themes/badge.theme.ts +2 -3
  102. package/src/themes/banner.theme.ts +40 -4
  103. package/src/themes/breadcrumb.theme.ts +1 -1
  104. package/src/themes/button.theme.ts +21 -22
  105. package/src/themes/{alert.theme.ts → callout.theme.ts} +12 -39
  106. package/src/themes/card.theme.ts +17 -9
  107. package/src/themes/carousel.theme.ts +1 -1
  108. package/src/themes/checkbox.theme.ts +1 -2
  109. package/src/themes/chip.theme.ts +2 -3
  110. package/src/themes/color-area.theme.ts +33 -0
  111. package/src/themes/color-field.theme.ts +32 -0
  112. package/src/themes/color-slider.theme.ts +34 -0
  113. package/src/themes/confirm.theme.ts +1 -1
  114. package/src/themes/container.theme.ts +1 -1
  115. package/src/themes/drawer.theme.ts +1 -1
  116. package/src/themes/footer.theme.ts +2 -2
  117. package/src/themes/grid.theme.ts +38 -0
  118. package/src/themes/header.theme.ts +4 -3
  119. package/src/themes/hover-card.theme.ts +1 -1
  120. package/src/themes/image.theme.ts +11 -1
  121. package/src/themes/input.theme.ts +7 -1
  122. package/src/themes/kbd.theme.ts +2 -3
  123. package/src/themes/label.theme.ts +1 -1
  124. package/src/themes/layout-grid.theme.ts +16 -0
  125. package/src/themes/link-group.theme.ts +0 -4
  126. package/src/themes/marquee.theme.ts +1 -1
  127. package/src/themes/modal.theme.ts +1 -1
  128. package/src/themes/navigation-menu.theme.ts +2 -2
  129. package/src/themes/page-section.theme.ts +4 -2
  130. package/src/themes/pagination.theme.ts +1 -1
  131. package/src/themes/pin-input.theme.ts +1 -1
  132. package/src/themes/popover.theme.ts +1 -1
  133. package/src/themes/post.theme.ts +23 -3
  134. package/src/themes/progress.theme.ts +1 -2
  135. package/src/themes/scroll-to-top.theme.ts +2 -3
  136. package/src/themes/search.theme.ts +64 -0
  137. package/src/themes/separator.theme.ts +1 -1
  138. package/src/themes/slideover.theme.ts +1 -1
  139. package/src/themes/slider.theme.ts +1 -2
  140. package/src/themes/spinner.theme.ts +1 -2
  141. package/src/themes/{megamenu.theme.ts → steps.theme.ts} +3 -3
  142. package/src/themes/sticky-surface.theme.ts +1 -1
  143. package/src/themes/switch.theme.ts +1 -2
  144. package/src/themes/table-of-contents.theme.ts +21 -2
  145. package/src/themes/timeline.theme.ts +7 -2
  146. package/src/themes/toast.theme.ts +1 -1
  147. package/src/types/components/accordion.ts +35 -2
  148. package/src/types/components/avatar.ts +16 -0
  149. package/src/types/components/banner.ts +42 -0
  150. package/src/types/components/button.ts +3 -4
  151. package/src/types/components/{alert.ts → callout.ts} +6 -6
  152. package/src/types/components/color-area.ts +19 -0
  153. package/src/types/components/color-field.ts +21 -0
  154. package/src/types/components/color-slider.ts +20 -0
  155. package/src/types/components/grid.ts +23 -0
  156. package/src/types/components/input.ts +4 -0
  157. package/src/types/components/layout-grid.ts +145 -0
  158. package/src/types/components/link-group.ts +4 -2
  159. package/src/types/components/link.ts +15 -0
  160. package/src/types/components/logo.ts +3 -3
  161. package/src/types/components/post.ts +12 -0
  162. package/src/types/components/search.ts +29 -0
  163. package/src/types/components/sidebar.ts +2 -6
  164. package/src/types/components/{megamenu.ts → steps.ts} +7 -1
  165. package/src/types/components/table-of-contents.ts +22 -0
  166. package/src/types/components/toast.ts +4 -0
  167. package/src/types/docs.ts +40 -0
  168. package/src/types/index.ts +151 -1
  169. package/src/types/theme.ts +6 -6
  170. package/src/utils/color.ts +165 -0
  171. package/src/utils/docs.ts +260 -110
  172. package/src/utils/headerStack.ts +24 -4
  173. package/src/utils/index.ts +2 -0
  174. package/src/utils/shortcuts.ts +322 -0
  175. package/src/components/TableOfContents.astro +0 -107
  176. package/src/components/astro/RLAAlert.astro +0 -93
  177. package/src/components/astro/RLAChangelog.astro +0 -23
  178. package/src/components/astro/RLAMegamenu.astro +0 -23
  179. package/src/plugins/index.ts +0 -2
  180. package/src/plugins/starlightDocsApi/components/ApiTheme.astro +0 -27
  181. package/src/plugins/starlightDocsApi/index.ts +0 -272
  182. package/src/styles/prism.css +0 -42
  183. package/src/themes/changelog.theme.ts +0 -13
  184. package/src/types/components/index.ts +0 -134
  185. /package/src/{plugins/starlightDocsApi → docs}/types.ts +0 -0
@@ -1,87 +1,81 @@
1
- ---
2
- import RLATabs from "./RLATabs.astro";
3
- import Prism from "prismjs";
4
- import "prismjs/components/prism-bash.js";
5
-
6
- type Manager = "npm" | "pnpm" | "yarn" | "deno" | "bun" | "vp"
7
- type CommandType = "add" | "create" | "dlx" | "exec" | "install" | "remove" | "run"
8
-
9
- interface Props {
10
- pkg?: string
11
- type?: CommandType
12
- dev?: boolean
13
- args?: string
14
- comment?: string
15
- prefix?: string
16
- managers?: Manager[]
17
- }
18
-
19
- const {
20
- pkg,
21
- type = "add",
22
- dev = false,
23
- args,
24
- comment,
25
- prefix,
26
- managers = ["npm", "pnpm", "yarn", "deno", "bun", "vp"]
27
- } = Astro.props
28
-
29
- const commands: Record<Manager, Partial<Record<CommandType, string>> & { dev: string }> = {
30
- npm: { add: "npm i", create: "npm create", dlx: "npx", exec: "npx", install: "npm install", run: "npm run", remove: "npm uninstall", dev: "-D" },
31
- yarn: { add: "yarn add", create: "yarn create", dlx: "yarn dlx", exec: "yarn", install: "yarn install", run: "yarn run", remove: "yarn remove", dev: "-D" },
32
- pnpm: { add: "pnpm add", create: "pnpm create", dlx: "pnpx", exec: "pnpm", install: "pnpm install", run: "pnpm run", remove: "pnpm remove", dev: "-D" },
33
- deno: { add: "deno add", create: "deno run -A", dlx: "deno run", exec: "deno run", install: "deno install", run: "deno task", remove: "deno remove", dev: "--dev" },
34
- bun: { add: "bun add", create: "bun create", install: "bun install", run: "bun run", remove: "bun remove", dev: "-d" },
35
- vp: { add: "vp add", create: "vp create", dlx: "vp dlx", exec: "vp exec", install: "vp install", run: "vp run", remove: "vp remove", dev: "-D" },
36
- }
37
-
38
- function getCommand(mgr: Manager, cmdType: CommandType): string | undefined {
39
- let cmd = commands[mgr][cmdType]
40
- if (cmd === undefined) return undefined
41
-
42
- if (prefix) cmd = `${prefix} ${cmd}`
43
- if (comment) cmd = `# ${comment.replaceAll("{PKG}", mgr)}\n${cmd}`
44
- if (dev && cmdType === "add") cmd += ` ${commands[mgr].dev}`
45
-
46
- if (pkg) {
47
- // Logic to strip version tags for yarn create
48
- const processedPkg = (cmdType === "create" && mgr === "yarn")
49
- ? pkg.replace(/@(?![^@]*\/)[^\s]*$/, "")
50
- : pkg
51
- cmd += ` ${processedPkg}`
52
- }
53
-
54
- if (args) {
55
- const needsDoubleDash = mgr === "npm" && !["dlx", "exec", "run"].includes(cmdType)
56
- cmd += `${needsDoubleDash ? " --" : ""} ${args}`
57
- }
58
-
59
- return cmd
60
- }
61
-
62
- const tabs = managers
63
- .map((mgr) => ({
64
- mgr,
65
- cmd: getCommand(mgr, type),
66
- }))
67
- .filter((tab) => tab.cmd !== undefined)
68
-
69
- const tabItems = tabs.map((tab) => ({
70
- value: tab.mgr,
71
- label: tab.mgr,
72
- }))
73
-
74
- // Pre-render the highlighted bash command via pure static prismjs
75
- const highlightedTabs = tabs.map((tab) => ({
76
- mgr: tab.mgr,
77
- html: Prism.highlight(tab.cmd!, Prism.languages.bash || Prism.languages.shell, "bash")
78
- }))
79
- ---
80
-
81
- <RLATabs items={tabItems} color="primary" size="md" variant="solid">
82
- {highlightedTabs.map((tab, idx) => (
83
- <div role="tabpanel" data-value={tab.mgr} class:list={[{ "hidden": idx !== 0 }]}>
84
- <pre class="language-sh"><code class="language-sh" set:html={tab.html}></code></pre>
85
- </div>
86
- ))}
87
- </RLATabs>
1
+ ---
2
+ import RLATabs from "./RLATabs.astro";
3
+ import { Code } from "astro:components";
4
+
5
+ type Manager = "npm" | "pnpm" | "yarn" | "deno" | "bun" | "vp"
6
+ type CommandType = "add" | "create" | "dlx" | "exec" | "install" | "remove" | "run"
7
+
8
+ interface Props {
9
+ pkg?: string
10
+ type?: CommandType
11
+ dev?: boolean
12
+ args?: string
13
+ comment?: string
14
+ prefix?: string
15
+ managers?: Manager[]
16
+ }
17
+
18
+ const {
19
+ pkg,
20
+ type = "add",
21
+ dev = false,
22
+ args,
23
+ comment,
24
+ prefix,
25
+ managers = ["npm", "pnpm", "yarn", "deno", "bun", "vp"]
26
+ } = Astro.props
27
+
28
+ const commands: Record<Manager, Partial<Record<CommandType, string>> & { dev: string }> = {
29
+ npm: { add: "npm i", create: "npm create", dlx: "npx", exec: "npx", install: "npm install", run: "npm run", remove: "npm uninstall", dev: "-D" },
30
+ yarn: { add: "yarn add", create: "yarn create", dlx: "yarn dlx", exec: "yarn", install: "yarn install", run: "yarn run", remove: "yarn remove", dev: "-D" },
31
+ pnpm: { add: "pnpm add", create: "pnpm create", dlx: "pnpx", exec: "pnpm", install: "pnpm install", run: "pnpm run", remove: "pnpm remove", dev: "-D" },
32
+ deno: { add: "deno add", create: "deno run -A", dlx: "deno run", exec: "deno run", install: "deno install", run: "deno task", remove: "deno remove", dev: "--dev" },
33
+ bun: { add: "bun add", create: "bun create", install: "bun install", run: "bun run", remove: "bun remove", dev: "-d" },
34
+ vp: { add: "vp add", create: "vp create", dlx: "vp dlx", exec: "vp exec", install: "vp install", run: "vp run", remove: "vp remove", dev: "-D" },
35
+ }
36
+
37
+ function getCommand(mgr: Manager, cmdType: CommandType): string | undefined {
38
+ let cmd = commands[mgr][cmdType]
39
+ if (cmd === undefined) return undefined
40
+
41
+ if (prefix) cmd = `${prefix} ${cmd}`
42
+ if (comment) cmd = `# ${comment.replaceAll("{PKG}", mgr)}\n${cmd}`
43
+ if (dev && cmdType === "add") cmd += ` ${commands[mgr].dev}`
44
+
45
+ if (pkg) {
46
+ // Logic to strip version tags for yarn create
47
+ const processedPkg = (cmdType === "create" && mgr === "yarn")
48
+ ? pkg.replace(/@(?![^@]*\/)\S*$/, "")
49
+ : pkg
50
+ cmd += ` ${processedPkg}`
51
+ }
52
+
53
+ if (args) {
54
+ const needsDoubleDash = mgr === "npm" && !["dlx", "exec", "run"].includes(cmdType)
55
+ cmd += `${needsDoubleDash ? " --" : ""} ${args}`
56
+ }
57
+
58
+ return cmd
59
+ }
60
+
61
+ const tabs = managers
62
+ .map((mgr) => ({
63
+ mgr,
64
+ cmd: getCommand(mgr, type),
65
+ }))
66
+ .filter((tab) => tab.cmd !== undefined)
67
+
68
+ const tabItems = tabs.map((tab) => ({
69
+ value: tab.mgr,
70
+ label: tab.mgr,
71
+ }))
72
+
73
+ ---
74
+
75
+ <RLATabs items={tabItems} color="primary" size="md" variant="solid">
76
+ {tabs.map((tab, idx) => (
77
+ <div role="tabpanel" data-value={tab.mgr} class:list={[{ "hidden": idx !== 0 }]}>
78
+ <Code code={tab.cmd!} lang="bash" />
79
+ </div>
80
+ ))}
81
+ </RLATabs>
@@ -28,11 +28,13 @@ const {
28
28
  ...rest
29
29
  } = Astro.props as PageSectionProps;
30
30
 
31
+ const resolvedVariant = (variant === "default" || variant === "hero" || variant === "cta") ? variant : "default"
32
+
31
33
  const classes = resolveClasses(pageSection, {
32
- variant,
34
+ variant: resolvedVariant,
33
35
  orientation,
34
36
  reverse,
35
- ...(variant === "cta" && { ctaVariant }),
37
+ ...(resolvedVariant === "cta" && { ctaVariant }),
36
38
  headline: !!(Astro.slots.has("headline") || headline),
37
39
  title: !!(Astro.slots.has("title") || title),
38
40
  description: !!(Astro.slots.has("description") || description),
@@ -21,15 +21,16 @@ const {
21
21
  const classes = resolveClasses(popover, {
22
22
  placement
23
23
  }, useUi("popover", uiProp), className)
24
+ const popoverId = `rla-popover-${Math.random().toString(36).substring(2, 9)}`
24
25
  ---
25
26
  <div class={classes.root} data-slot="popover-container" {...rest}>
26
- <div class={classes.trigger} data-slot="trigger" tabindex="0">
27
+ <div class={classes.trigger} data-slot="trigger">
27
28
  <slot name="trigger">
28
- {triggerLabel && <button type="button" class="cursor-pointer">{triggerLabel}</button>}
29
+ {triggerLabel && <button type="button" class="cursor-pointer" popovertarget={popoverId}>{triggerLabel}</button>}
29
30
  </slot>
30
31
  </div>
31
32
 
32
- <div class={classes.content} data-slot="content">
33
+ <div id={popoverId} popover class={classes.content} data-slot="content">
33
34
  <slot />
34
35
  </div>
35
36
  </div>
@@ -4,7 +4,9 @@ import { useUi, resolveClasses } from "../../utils"
4
4
  import type { PostProps } from "../../types"
5
5
  import postThemeDefault, { createPostTheme } from "../../themes/post.theme"
6
6
  import { getUIConfig } from "virtual:rimelight-ui"
7
+ import type { ImageMetadata } from "astro"
7
8
  import Image from "astro/components/Image.astro"
9
+ import RLABadge from "./RLABadge.astro"
8
10
 
9
11
  const uiConfig = getUIConfig()
10
12
  const postTheme = uiConfig.colors ? createPostTheme() : postThemeDefault
@@ -17,13 +19,16 @@ const {
17
19
  date,
18
20
  image,
19
21
  to,
22
+ badge,
23
+ badgeColor = "primary",
20
24
  variant = "soft",
25
+ orientation = "vertical",
21
26
  ui: uiProp,
22
27
  class: className,
23
28
  ...rest
24
29
  } = Astro.props as PostProps
25
30
 
26
- const classes = resolveClasses(post, { variant }, useUi("post", uiProp), className);
31
+ const classes = resolveClasses(post, { variant, orientation }, useUi("post", uiProp), className);
27
32
 
28
33
  const Tag = to ? "a" : "div";
29
34
  const formattedDate = date ? (date instanceof Date ? date.toLocaleDateString() : date) : null;
@@ -35,7 +40,7 @@ const formattedDate = date ? (date instanceof Date ? date.toLocaleDateString() :
35
40
  {typeof image === 'string' ? (
36
41
  <img src={image} alt={title} class={classes.image} data-slot="image" />
37
42
  ) : (
38
- <Image src={image} alt={title || ""} class={classes.image} data-slot="image" />
43
+ <Image src={image as ImageMetadata} alt={title || ""} class={classes.image} data-slot="image" />
39
44
  )}
40
45
  </div>
41
46
  )}
@@ -50,6 +55,10 @@ const formattedDate = date ? (date instanceof Date ? date.toLocaleDateString() :
50
55
  {description && <p class={classes.description} data-slot="description">{description}</p>}
51
56
  </slot>
52
57
 
58
+ <slot name="badge" {...{ ui: classes }}>
59
+ {badge && <RLABadge color={badgeColor as any} size="sm" shape="pill" class={classes.badge} data-slot="badge">{badge}</RLABadge>}
60
+ </slot>
61
+
53
62
  <slot name="date" {...{ ui: classes }}>
54
63
  {formattedDate && <time class={classes.date} data-slot="date">{formattedDate}</time>}
55
64
  </slot>
@@ -4,7 +4,10 @@ import { useUi, resolveClasses } from "../../utils"
4
4
  import type { ScrollAreaProps } from "../../types"
5
5
  import scrollAreaThemeDefault, { createScrollAreaTheme } from "../../themes/scroll-area.theme"
6
6
 
7
- const scrollAreaTheme = scrollAreaThemeDefault
7
+ import { getUIConfig } from "virtual:rimelight-ui"
8
+
9
+ const uiConfig = getUIConfig()
10
+ const scrollAreaTheme = uiConfig.colors ? createScrollAreaTheme() : scrollAreaThemeDefault
8
11
  const scrollArea = scv(scrollAreaTheme)
9
12
 
10
13
  const {
@@ -1,172 +1,200 @@
1
- ---
2
- import { scv } from "css-variants"
3
- import { useUi, resolveClasses } from "../../utils"
4
- import type { ScrollToTopProps } from "../../types"
5
- import scrollToTopThemeDefault, { createScrollToTopTheme } from "../../themes/scroll-to-top.theme"
6
- import { getUIConfig } from "virtual:rimelight-ui"
7
-
8
- const uiConfig = getUIConfig()
9
- const scrollToTopTheme = uiConfig.colors ? createScrollToTopTheme(uiConfig.colors) : scrollToTopThemeDefault
10
-
11
- const scrollToTop = scv(scrollToTopTheme)
12
-
13
- const {
14
- color = "primary",
15
- progressWidth = 6,
16
- duration = 0.1,
17
- threshold = 200,
18
- showProgress = false,
19
- theme,
20
- ui: uiProp,
21
- class: className,
22
- ...rest
23
- } = Astro.props as ScrollToTopProps
24
-
25
- const classes = resolveClasses(scrollToTop, { color, theme }, useUi("scrollToTop", uiProp), className)
26
-
27
- const circumference = 2 * Math.PI * 45
28
- const percentPx = circumference / 100
29
-
30
-
31
- ---
32
-
33
- <div
34
- class:list={["rla-scroll-to-top", "fixed bottom-6 right-6 z-50", classes.root]}
35
- data-threshold={threshold}
36
- data-duration={duration}
37
- data-circle-stroke-width={progressWidth}
38
- {...rest}
39
- >
40
- <button
41
- type="button"
42
- class={classes.button}
43
- aria-label="Scroll to top"
44
- data-scroll-to-top-button
45
- >
46
- <div class={classes.progressBase}>
47
- <svg class={classes.svg} viewBox="0 0 100 100" shape-rendering="geometricPrecision">
48
- <circle
49
- cx="50"
50
- cy="50"
51
- r="45"
52
- stroke={`var(--color-${color}-900)`}
53
- fill={`var(--color-${color}-950)`}
54
- stroke-width={progressWidth}
55
- stroke-dashoffset="0"
56
- stroke-linecap="round"
57
- class="gauge-secondary-stroke opacity-100"
58
- />
59
- {showProgress && (
60
- <circle
61
- cx="50"
62
- cy="50"
63
- r="45"
64
- fill="transparent"
65
- stroke={`var(--color-${color}-500)`}
66
- stroke-width={progressWidth}
67
- stroke-dashoffset="0"
68
- stroke-linecap="round"
69
- class="gauge-primary-stroke opacity-100"
70
- data-progress-circle
71
- />
72
- )}
73
- </svg>
74
- <div class={classes.iconContainer}>
75
- <svg
76
- xmlns="http://www.w3.org/2000/svg"
77
- width="24"
78
- height="24"
79
- viewBox="0 0 24 24"
80
- fill="none"
81
- stroke="currentColor"
82
- stroke-width="2"
83
- stroke-linecap="round"
84
- stroke-linejoin="round"
85
- class={classes.icon}
86
- >
87
- <path d="m5 12 7-7 7 7" />
88
- <path d="M12 19V5" />
89
- </svg>
90
- </div>
91
- </div>
92
- </button>
93
- </div>
94
-
95
- <script>
96
- document.querySelectorAll('.rla-scroll-to-top').forEach((el) => {
97
- const element = el as HTMLElement
98
- const button = element.querySelector('[data-scroll-to-top-button]') as HTMLButtonElement | null
99
- const progressCircle = element.querySelector('[data-progress-circle]') as SVGCircleElement | null
100
-
101
- if (!button) return
102
-
103
- const threshold = Number(element.dataset.threshold) || 200
104
-
105
- function updateScrollState() {
106
- const scrollTop = window.scrollY || document.documentElement.scrollTop
107
- const scrollHeight = document.documentElement.scrollHeight - window.innerHeight
108
- const scrollPercentage = scrollHeight > 0 ? (scrollTop / scrollHeight) * 100 : 0
109
-
110
- if (scrollTop > threshold) {
111
- element.classList.add('visible')
112
- } else {
113
- element.classList.remove('visible')
114
- }
115
-
116
- if (progressCircle) {
117
- const circumference = 2 * Math.PI * 45
118
- const percentPx = circumference / 100
119
- const duration = element.dataset.duration || '0.1'
120
- progressCircle.style.setProperty('--stroke-percent', scrollPercentage.toString())
121
- progressCircle.style.setProperty('--percent-to-px', `${percentPx}px`)
122
- progressCircle.style.setProperty('--circumference', circumference.toString())
123
- progressCircle.style.setProperty('--duration', `${duration}s`)
124
- }
125
- }
126
-
127
- button.addEventListener('click', () => {
128
- window.scrollTo({ top: 0, behavior: 'smooth' })
129
- })
130
-
131
- window.addEventListener('scroll', updateScrollState, { passive: true })
132
- updateScrollState()
133
- })
134
- </script>
135
-
136
- <style>
137
- .rla-scroll-to-top {
138
- opacity: 0;
139
- pointer-events: none;
140
- transition: opacity 0.3s ease-in-out;
141
- }
142
-
143
- .rla-scroll-to-top.visible {
144
- opacity: 1;
145
- pointer-events: auto;
146
- }
147
-
148
- .progress-circle-base {
149
- transform: translateZ(0);
150
- }
151
-
152
- .gauge-primary-stroke {
153
- stroke-dasharray: calc(var(--stroke-percent, 0) * var(--percent-to-px, 2.826px)) var(--circumference, 282.6);
154
- transition: stroke-dasharray var(--duration, 0.1s) ease, stroke var(--duration, 0.1s) ease;
155
- transform: rotate(-90deg);
156
- transform-origin: center;
157
- shape-rendering: geometricPrecision;
158
- }
159
-
160
- .gauge-secondary-stroke {
161
- stroke-dasharray: 282.6;
162
- transform: rotate(-90deg);
163
- transform-origin: center;
164
- }
165
-
166
- [data-progress-circle] {
167
- --stroke-percent: 0;
168
- --percent-to-px: 2.826px;
169
- --circumference: 282.6;
170
- --duration: 0.1s;
171
- }
172
- </style>
1
+ ---
2
+ import { scv } from "css-variants"
3
+ import { useUi, resolveClasses } from "../../utils"
4
+ import type { ScrollToTopProps } from "../../types"
5
+ import scrollToTopThemeDefault, { createScrollToTopTheme } from "../../themes/scroll-to-top.theme"
6
+ import { getUIConfig } from "virtual:rimelight-ui"
7
+
8
+ const uiConfig = getUIConfig()
9
+ const scrollToTopTheme = uiConfig.colors ? createScrollToTopTheme(uiConfig.colors) : scrollToTopThemeDefault
10
+
11
+ const scrollToTop = scv(scrollToTopTheme)
12
+
13
+ const {
14
+ color = "primary",
15
+ progressWidth = 6,
16
+ duration = 0.1,
17
+ threshold = 200,
18
+ showProgress = false,
19
+ theme,
20
+ ui: uiProp,
21
+ class: className,
22
+ ...rest
23
+ } = Astro.props as ScrollToTopProps
24
+
25
+ const classes = resolveClasses(scrollToTop, { color, theme }, useUi("scrollToTop", uiProp), className)
26
+
27
+ ---
28
+
29
+ <rla-scroll-to-top data-threshold={threshold} data-duration={duration} data-color={color} data-progress-width={progressWidth} {...rest}>
30
+ <div
31
+ class:list={["rla-scroll-to-top-inner", "fixed bottom-6 right-6 z-50", classes.root]}
32
+ >
33
+ <button
34
+ type="button"
35
+ class={classes.button}
36
+ aria-label="Scroll to top"
37
+ data-scroll-to-top-button
38
+ >
39
+ <div class={classes.progressBase}>
40
+ <div class="gauge-track"></div>
41
+ {showProgress && (
42
+ <div class="gauge-progress" data-gauge-progress></div>
43
+ )}
44
+ <div class={classes.iconContainer}>
45
+ <svg
46
+ xmlns="http://www.w3.org/2000/svg"
47
+ width="24"
48
+ height="24"
49
+ viewBox="0 0 24 24"
50
+ fill="none"
51
+ stroke="currentColor"
52
+ stroke-width="2"
53
+ stroke-linecap="round"
54
+ stroke-linejoin="round"
55
+ class={classes.icon}
56
+ >
57
+ <path d="m5 12 7-7 7 7" />
58
+ <path d="M12 19V5" />
59
+ </svg>
60
+ </div>
61
+ </div>
62
+ </button>
63
+ </div>
64
+ </rla-scroll-to-top>
65
+
66
+ <script>
67
+ function onClick() {
68
+ window.scrollTo({ top: 0, behavior: 'smooth' });
69
+ }
70
+
71
+ class RLAScrollToTop extends HTMLElement {
72
+ private cleanupScroll: (() => void) | null = null;
73
+ private styleEl: HTMLStyleElement | null = null;
74
+
75
+ connectedCallback() {
76
+ this.style.display = 'contents';
77
+ const button = this.querySelector('[data-scroll-to-top-button]');
78
+ const innerElement = this.querySelector('.rla-scroll-to-top-inner') as HTMLElement | null;
79
+
80
+ if (!button || !innerElement) return;
81
+
82
+ const id = ++RLAScrollToTop.instanceCounter;
83
+ const threshold = Number(this.dataset.threshold) || 200;
84
+ const color = this.dataset.color || 'primary';
85
+ const progressWidth = Number(this.dataset.progressWidth) || 6;
86
+ const gaugeBorderWidth = progressWidth * 0.5;
87
+ const nonce = (document.querySelector('meta[name="csp-nonce"]')?.getAttribute('content') ?? '');
88
+
89
+ const getStyleEl = () => {
90
+ if (!this.styleEl) {
91
+ this.styleEl = document.createElement('style');
92
+ if (nonce) this.styleEl.setAttribute('nonce', nonce);
93
+ document.head.appendChild(this.styleEl);
94
+ }
95
+ return this.styleEl;
96
+ };
97
+
98
+ const updateStyles = () => {
99
+ const scrollTop = window.scrollY || document.documentElement.scrollTop;
100
+ const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
101
+ const scrollPercentage = scrollHeight > 0 ? (scrollTop / scrollHeight) * 100 : 0;
102
+
103
+ if (scrollTop > threshold) {
104
+ innerElement.classList.add('visible');
105
+ } else {
106
+ innerElement.classList.remove('visible');
107
+ }
108
+
109
+ getStyleEl().textContent = `
110
+ .rla-scroll-to-top-inner[data-rla-instance="${id}"] .gauge-track {
111
+ border-width: ${gaugeBorderWidth}px;
112
+ border-color: var(--color-${color}-900);
113
+ background-color: #000;
114
+ }
115
+ .rla-scroll-to-top-inner[data-rla-instance="${id}"] .gauge-progress {
116
+ --gauge-progress: ${scrollPercentage};
117
+ --gauge-stroke-width: ${gaugeBorderWidth}px;
118
+ --gauge-color: var(--color-${color}-500);
119
+ }
120
+ `;
121
+ };
122
+
123
+ innerElement.dataset.rlaInstance = String(id);
124
+
125
+ button.addEventListener('click', onClick);
126
+
127
+ window.addEventListener('scroll', updateStyles, { passive: true });
128
+ updateStyles();
129
+
130
+ this.cleanupScroll = () => {
131
+ button.removeEventListener('click', onClick);
132
+ window.removeEventListener('scroll', updateStyles);
133
+ if (this.styleEl) {
134
+ this.styleEl.remove();
135
+ this.styleEl = null;
136
+ }
137
+ };
138
+ }
139
+
140
+ disconnectedCallback() {
141
+ if (this.cleanupScroll) {
142
+ this.cleanupScroll();
143
+ this.cleanupScroll = null;
144
+ }
145
+ }
146
+
147
+ static instanceCounter = 0;
148
+ }
149
+
150
+ if (!customElements.get('rla-scroll-to-top')) {
151
+ customElements.define('rla-scroll-to-top', RLAScrollToTop);
152
+ }
153
+ </script>
154
+
155
+ <style>
156
+ .rla-scroll-to-top-inner {
157
+ opacity: 0;
158
+ pointer-events: none;
159
+ transition: opacity 0.3s ease-in-out;
160
+ }
161
+
162
+ .rla-scroll-to-top-inner.visible {
163
+ opacity: 1;
164
+ pointer-events: auto;
165
+ }
166
+
167
+ .progress-circle-base {
168
+ position: relative;
169
+ transform: translateZ(0);
170
+ }
171
+
172
+ .gauge-track {
173
+ position: absolute;
174
+ inset: 0;
175
+ border-radius: 50%;
176
+ border-style: solid;
177
+ }
178
+
179
+ .gauge-progress {
180
+ position: absolute;
181
+ inset: 0;
182
+ border-radius: 50%;
183
+ background: conic-gradient(
184
+ from 0deg,
185
+ var(--gauge-color, var(--color-primary-500)) 0deg,
186
+ var(--gauge-color, var(--color-primary-500)) calc(var(--gauge-progress, 0) * 3.6deg),
187
+ transparent calc(var(--gauge-progress, 0) * 3.6deg)
188
+ );
189
+ -webkit-mask: radial-gradient(
190
+ circle closest-side,
191
+ transparent calc(100% - var(--gauge-stroke-width, 6px)),
192
+ #000 calc(100% - var(--gauge-stroke-width, 6px))
193
+ );
194
+ mask: radial-gradient(
195
+ circle closest-side,
196
+ transparent calc(100% - var(--gauge-stroke-width, 6px)),
197
+ #000 calc(100% - var(--gauge-stroke-width, 6px))
198
+ );
199
+ }
200
+ </style>