@rokkit/app 1.1.13 → 1.1.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rokkit/app",
3
- "version": "1.1.13",
3
+ "version": "1.1.15",
4
4
  "description": "App-level controls for Rokkit applications - theme management and UI chrome",
5
5
  "repository": {
6
6
  "type": "git",
@@ -37,10 +37,10 @@
37
37
  "build": "echo 'No build step needed for source-only package'"
38
38
  },
39
39
  "dependencies": {
40
- "@rokkit/actions": "1.1.13",
41
- "@rokkit/core": "1.1.13",
42
- "@rokkit/states": "1.1.13",
43
- "@rokkit/ui": "1.1.13"
40
+ "@rokkit/actions": "1.1.15",
41
+ "@rokkit/core": "1.1.15",
42
+ "@rokkit/states": "1.1.15",
43
+ "@rokkit/ui": "1.1.15"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "svelte": "^5.0.0"
@@ -0,0 +1,42 @@
1
+ <script lang="ts">
2
+ import { vibe } from '@rokkit/states'
3
+ import { Toggle } from '@rokkit/ui'
4
+ import { buildSkinSwitcherOptions } from '../types/skin-switcher.js'
5
+
6
+ let {
7
+ skins = undefined,
8
+ labels = {},
9
+ showLabels = false,
10
+ size = 'sm',
11
+ disabled = false,
12
+ class: className = '',
13
+ onchange
14
+ }: {
15
+ skins?: Array<string | { name: string; label?: string; icon?: string }>
16
+ labels?: Record<string, string>
17
+ showLabels?: boolean
18
+ size?: 'sm' | 'md' | 'lg'
19
+ disabled?: boolean
20
+ class?: string
21
+ onchange?: (skin: string) => void
22
+ } = $props()
23
+
24
+ const options = $derived(buildSkinSwitcherOptions(skins ?? vibe.allowedSkins, labels))
25
+ let value = $derived(vibe.skin)
26
+
27
+ function handleChange(newValue: unknown) {
28
+ vibe.skin = newValue as string
29
+ onchange?.(newValue as string)
30
+ }
31
+ </script>
32
+
33
+ <Toggle
34
+ variant="group"
35
+ {options}
36
+ {value}
37
+ onchange={handleChange}
38
+ {showLabels}
39
+ {size}
40
+ {disabled}
41
+ class={className}
42
+ />
@@ -1,7 +1,7 @@
1
1
  <script>
2
2
  // @ts-nocheck
3
- import { navigable } from '@rokkit/actions'
4
3
  import { onMount } from 'svelte'
4
+ import { keyboard } from '@rokkit/actions'
5
5
 
6
6
  let { container = 'main-content' } = $props()
7
7
 
@@ -97,6 +97,13 @@
97
97
  scrollToHeading(id)
98
98
  }
99
99
 
100
+ // Arrow/Enter keys → previous/next/select events, dispatched by the `keyboard` action.
101
+ const navKeys = {
102
+ previous: ['ArrowUp', 'ArrowLeft'],
103
+ next: ['ArrowDown', 'ArrowRight'],
104
+ select: ['Enter', ' ']
105
+ }
106
+
100
107
  onMount(() => {
101
108
  scan()
102
109
  observe()
@@ -112,7 +119,7 @@
112
119
  bind:this={navEl}
113
120
  data-toc
114
121
  aria-label="On this page"
115
- use:navigable
122
+ use:keyboard={navKeys}
116
123
  onprevious={handlePrevious}
117
124
  onnext={handleNext}
118
125
  onselect={handleSelect}
@@ -1,2 +1,3 @@
1
1
  export { default as ThemeSwitcherToggle } from './ThemeSwitcherToggle.svelte'
2
2
  export { default as TableOfContents } from './TableOfContents.svelte'
3
+ export { default as SkinSwitcherToggle } from './SkinSwitcherToggle.svelte'
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  // Components
2
- export { ThemeSwitcherToggle, TableOfContents } from './components/index.js'
2
+ export { ThemeSwitcherToggle, SkinSwitcherToggle, TableOfContents } from './components/index.js'
3
3
 
4
4
  // Types
5
5
  export * from './types/index.js'
@@ -1 +1,2 @@
1
1
  export * from './theme-switcher.js'
2
+ export * from './skin-switcher.js'
@@ -0,0 +1,17 @@
1
+ export interface SkinSwitcherOption {
2
+ value: string
3
+ label: string
4
+ icon?: string
5
+ }
6
+
7
+ export function buildSkinSwitcherOptions(
8
+ skins: Array<string | { name: string; label?: string; icon?: string }>,
9
+ labels: Record<string, string> = {}
10
+ ): SkinSwitcherOption[] {
11
+ return skins.map((s) => {
12
+ const name = typeof s === 'string' ? s : s.name
13
+ const label = typeof s === 'string' ? (labels[s] ?? s) : (s.label ?? labels[s.name] ?? s.name)
14
+ const icon = typeof s === 'string' ? undefined : s.icon
15
+ return { value: name, label, icon }
16
+ })
17
+ }
@@ -31,7 +31,7 @@ export const defaultThemeSwitcherIcons: Required<ThemeSwitcherIcons> = {
31
31
 
32
32
  export interface ThemeSwitcherOption {
33
33
  value: ColorMode
34
- text: string
34
+ label: string
35
35
  icon: string
36
36
  [key: string]: unknown
37
37
  }
@@ -52,9 +52,9 @@ export function buildThemeSwitcherOptions(
52
52
  ): ThemeSwitcherOption[] {
53
53
  const mergedLabels = { ...messages.mode, ...labels }
54
54
  const all: ThemeSwitcherOption[] = [
55
- { value: 'system', text: mergedLabels.system, icon: icons.system },
56
- { value: 'light', text: mergedLabels.light, icon: icons.light },
57
- { value: 'dark', text: mergedLabels.dark, icon: icons.dark }
55
+ { value: 'system', label: mergedLabels.system, icon: icons.system },
56
+ { value: 'light', label: mergedLabels.light, icon: icons.light },
57
+ { value: 'dark', label: mergedLabels.dark, icon: icons.dark }
58
58
  ]
59
59
  return all.filter((o) => modes.includes(o.value))
60
60
  }