@rokkit/ui 1.0.0-next.99 → 1.0.2

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 (83) hide show
  1. package/README.md +159 -1
  2. package/package.json +52 -53
  3. package/src/MarkdownRenderer.svelte +106 -0
  4. package/src/components/AlertList.svelte +59 -0
  5. package/src/components/Avatar.svelte +68 -0
  6. package/src/components/Badge.svelte +57 -0
  7. package/src/components/BreadCrumbs.svelte +94 -0
  8. package/src/components/Button.svelte +91 -0
  9. package/src/components/ButtonGroup.svelte +9 -0
  10. package/src/components/Card.svelte +71 -0
  11. package/src/components/Carousel.svelte +169 -0
  12. package/src/components/Code.svelte +189 -0
  13. package/src/components/Connector.svelte +46 -0
  14. package/src/components/Divider.svelte +24 -0
  15. package/src/components/Dropdown.svelte +202 -0
  16. package/src/components/FloatingAction.svelte +367 -0
  17. package/src/components/FloatingNavigation.svelte +256 -0
  18. package/src/components/Grid.svelte +128 -0
  19. package/src/components/ItemContent.svelte +25 -0
  20. package/src/components/LazyTree.svelte +171 -0
  21. package/src/components/List.svelte +224 -0
  22. package/src/components/Menu.svelte +270 -0
  23. package/src/components/Message.svelte +75 -0
  24. package/src/components/MultiSelect.svelte +367 -0
  25. package/src/components/NavContent.svelte +42 -0
  26. package/src/components/PaletteManager.svelte +360 -0
  27. package/src/components/Pill.svelte +83 -0
  28. package/src/components/ProgressBar.svelte +31 -0
  29. package/src/components/Range.svelte +346 -0
  30. package/src/components/Rating.svelte +115 -0
  31. package/src/components/ResponsiveGrid.svelte +34 -0
  32. package/src/components/Reveal.svelte +46 -0
  33. package/src/components/SearchFilter.svelte +88 -0
  34. package/src/components/Select.svelte +424 -0
  35. package/src/components/Shine.svelte +87 -0
  36. package/src/components/Stack.svelte +38 -0
  37. package/src/components/StatusList.svelte +18 -0
  38. package/src/components/Stepper.svelte +174 -0
  39. package/src/components/Swatch.svelte +102 -0
  40. package/src/components/Switch.svelte +71 -0
  41. package/src/components/Table.svelte +245 -0
  42. package/src/components/Tabs.svelte +202 -0
  43. package/src/components/Tilt.svelte +68 -0
  44. package/src/components/Timeline.svelte +61 -0
  45. package/src/components/Toggle.svelte +93 -0
  46. package/src/components/Toolbar.svelte +306 -0
  47. package/src/components/ToolbarGroup.svelte +17 -0
  48. package/src/components/Tooltip.svelte +121 -0
  49. package/src/components/Tree.svelte +143 -0
  50. package/src/components/UploadFileStatus.svelte +102 -0
  51. package/src/components/UploadProgress.svelte +127 -0
  52. package/src/components/UploadTarget.svelte +126 -0
  53. package/src/components/index.ts +50 -0
  54. package/src/index.ts +61 -0
  55. package/src/markdown-plugin.ts +12 -0
  56. package/src/types/button.ts +86 -0
  57. package/src/types/code.ts +46 -0
  58. package/src/types/floating-action.ts +123 -0
  59. package/src/types/floating-navigation.ts +80 -0
  60. package/src/types/index.ts +58 -0
  61. package/src/types/list.ts +200 -0
  62. package/src/types/menu.ts +95 -0
  63. package/src/types/palette.ts +160 -0
  64. package/src/types/range.ts +51 -0
  65. package/src/types/search-filter.ts +67 -0
  66. package/src/types/select.ts +176 -0
  67. package/src/types/switch.ts +68 -0
  68. package/src/types/table.ts +219 -0
  69. package/src/types/tabs.ts +103 -0
  70. package/src/types/timeline.ts +53 -0
  71. package/src/types/toggle.ts +68 -0
  72. package/src/types/toolbar.ts +167 -0
  73. package/src/types/tooltip.ts +21 -0
  74. package/src/types/tree.ts +250 -0
  75. package/src/types/upload-file-status.ts +45 -0
  76. package/src/types/upload-progress.ts +111 -0
  77. package/src/types/upload-target.ts +71 -0
  78. package/src/utils/palette.ts +618 -0
  79. package/src/utils/shiki.ts +114 -0
  80. package/src/utils/upload.js +145 -0
  81. package/LICENSE +0 -21
  82. package/src/index.js +0 -8
  83. package/src/wrappers.js +0 -2
@@ -0,0 +1,127 @@
1
+ <script lang="ts">
2
+ /**
3
+ * UploadProgress — File upload status orchestrator.
4
+ *
5
+ * Thin composition layer: header + List or Grid layout.
6
+ * Default itemContent snippet renders UploadFileStatus for each file.
7
+ * Consumer can override with custom itemContent snippet.
8
+ *
9
+ * Data attributes:
10
+ * data-upload-progress — root container
11
+ * data-upload-view — current view mode (list, grid)
12
+ * data-upload-header — header bar
13
+ * data-upload-clear — clear all button
14
+ */
15
+ import type { ProxyItem } from '@rokkit/states'
16
+ import type { UploadProgressProps, UploadItem } from '../types/upload-progress.js'
17
+ import { messages } from '@rokkit/states'
18
+ import { ITEM_SNIPPET } from '@rokkit/core'
19
+ import List from './List.svelte'
20
+ import Grid from './Grid.svelte'
21
+ import UploadFileStatus from './UploadFileStatus.svelte'
22
+
23
+ let {
24
+ files = [] as UploadItem[],
25
+ fields: userFields = {} as Record<string, string>,
26
+ view = 'list' as 'list' | 'grid',
27
+ cancelWhen = [] as string[],
28
+ retryWhen = [] as string[],
29
+ removeWhen = [] as string[],
30
+ oncancel,
31
+ onretry,
32
+ onremove,
33
+ onclear,
34
+ labels: userLabels = {} as Record<string, string>,
35
+ class: className = '',
36
+ ...snippets
37
+ }: UploadProgressProps & { [key: string]: unknown } = $props()
38
+
39
+ // ─── Labels ──────────────────────────────────────────────────────────────
40
+
41
+ const labels = $derived({ ...messages.uploadProgress, ...userLabels })
42
+
43
+ // ─── Field resolution ────────────────────────────────────────────────────
44
+ // Pass upload-specific field mappings through to List/Grid so ProxyItem
45
+ // can resolve them via proxy.get(). BASE_FIELDS handles label/value/icon;
46
+ // we add status, progress, size, type, error for UploadFileStatus.
47
+
48
+ const fieldMap = $derived({
49
+ ...userFields,
50
+ status: userFields.status ?? 'status',
51
+ progress: userFields.progress ?? 'progress',
52
+ size: userFields.size ?? 'size',
53
+ type: userFields.type ?? 'type',
54
+ error: userFields.error ?? 'error'
55
+ })
56
+
57
+ // ─── Status summary ──────────────────────────────────────────────────────
58
+
59
+ const statusField = $derived(userFields.status ?? 'status')
60
+
61
+ const statusSummary = $derived.by(() => {
62
+ const counts: Record<string, number> = {}
63
+ for (const file of files) {
64
+ const s = String(file[statusField] || 'unknown')
65
+ counts[s] = (counts[s] || 0) + 1
66
+ }
67
+ return Object.entries(counts)
68
+ .map(([s, n]) => `${n} ${labels[s] ?? s}`)
69
+ .join(', ')
70
+ })
71
+
72
+ // ─── Snippet resolution ──────────────────────────────────────────────────
73
+
74
+ let itemSnippet = $derived(snippets[ITEM_SNIPPET] as typeof defaultItemContent | undefined)
75
+
76
+ // ─── Action callbacks (unwrap proxy → raw item) ──────────────────────────
77
+
78
+ function handleCancel(proxy: ProxyItem) {
79
+ oncancel?.(proxy.original as UploadItem)
80
+ }
81
+
82
+ function handleRetry(proxy: ProxyItem) {
83
+ onretry?.(proxy.original as UploadItem)
84
+ }
85
+
86
+ function handleRemove(proxy: ProxyItem) {
87
+ onremove?.(proxy.original as UploadItem)
88
+ }
89
+ </script>
90
+
91
+ {#snippet defaultItemContent(proxy: ProxyItem)}
92
+ <UploadFileStatus
93
+ {proxy}
94
+ {cancelWhen}
95
+ {retryWhen}
96
+ {removeWhen}
97
+ oncancel={handleCancel}
98
+ onretry={handleRetry}
99
+ onremove={handleRemove}
100
+ labels={userLabels}
101
+ />
102
+ {/snippet}
103
+
104
+ <div data-upload-progress data-upload-view={view} class={className || undefined}>
105
+ <!-- Header -->
106
+ <div data-upload-header>
107
+ <span>{files.length} files — {statusSummary}</span>
108
+ {#if onclear}
109
+ <button type="button" data-upload-clear onclick={onclear}>{labels.clear}</button>
110
+ {/if}
111
+ </div>
112
+
113
+ <!-- Layout delegation -->
114
+ {#if view === 'grid'}
115
+ <Grid items={files} fields={fieldMap}>
116
+ {#snippet itemContent(proxy: ProxyItem)}
117
+ {@render (itemSnippet ?? defaultItemContent)(proxy)}
118
+ {/snippet}
119
+ </Grid>
120
+ {:else}
121
+ <List items={files} fields={fieldMap}>
122
+ {#snippet itemContent(proxy: ProxyItem)}
123
+ {@render (itemSnippet ?? defaultItemContent)(proxy)}
124
+ {/snippet}
125
+ </List>
126
+ {/if}
127
+ </div>
@@ -0,0 +1,126 @@
1
+ <script lang="ts">
2
+ /**
3
+ * UploadTarget — Drop zone with file validation.
4
+ *
5
+ * Accepts drag-and-drop or click-to-browse. Validates files against
6
+ * accept (MIME/extension) and maxSize constraints via upload-utils.
7
+ *
8
+ * Data attributes:
9
+ * data-upload-target — root container / drop zone
10
+ * data-upload-icon — upload icon
11
+ * data-upload-button — browse button
12
+ * data-dragging — present when files dragged over
13
+ * data-disabled — when disabled
14
+ */
15
+ import type { UploadTargetProps } from '../types/upload-target.js'
16
+ import { messages } from '@rokkit/states'
17
+ import { matchesAccept } from '../utils/upload.js'
18
+
19
+ let {
20
+ accept = '',
21
+ maxSize = Infinity,
22
+ multiple = false,
23
+ disabled = false,
24
+ size = 'full',
25
+ labels = {} as Record<string, string>,
26
+ onfiles,
27
+ onerror,
28
+ class: className = '',
29
+ ...snippets
30
+ }: UploadTargetProps & { [key: string]: unknown } = $props()
31
+
32
+ const content = $derived(snippets.content as ((dragging: boolean) => unknown) | undefined)
33
+
34
+ const resolvedLabels = $derived({
35
+ ...messages.uploadTarget,
36
+ ...labels
37
+ })
38
+
39
+ let inputRef = $state<HTMLInputElement | null>(null)
40
+ let dragging = $state(false)
41
+
42
+ function validateFile(file: File): 'type' | 'size' | null {
43
+ if (accept && !matchesAccept(file, accept)) return 'type'
44
+ if (file.size > maxSize) return 'size'
45
+ return null
46
+ }
47
+
48
+ function processFile(file: File, valid: File[]) {
49
+ const reason = validateFile(file)
50
+ if (reason) onerror?.({ file, reason })
51
+ else valid.push(file)
52
+ }
53
+
54
+ function handleFiles(fileList: FileList | File[]) {
55
+ const valid: File[] = []
56
+ for (const file of Array.from(fileList)) processFile(file, valid)
57
+ if (valid.length > 0) onfiles?.(valid)
58
+ }
59
+
60
+ function handleInputChange() {
61
+ if (inputRef?.files) handleFiles(inputRef.files)
62
+ if (inputRef) inputRef.value = ''
63
+ }
64
+
65
+ function handleDrop(event: DragEvent) {
66
+ event.preventDefault()
67
+ dragging = false
68
+ if (disabled || !event.dataTransfer?.files.length) return
69
+ handleFiles(event.dataTransfer.files)
70
+ }
71
+
72
+ function handleDragOver(event: DragEvent) {
73
+ event.preventDefault()
74
+ if (!disabled) dragging = true
75
+ }
76
+
77
+ function handleDragLeave() {
78
+ dragging = false
79
+ }
80
+
81
+ function handleKeydown(event: KeyboardEvent) {
82
+ if (event.key === 'Enter' || event.key === ' ') {
83
+ event.preventDefault()
84
+ if (!disabled) inputRef?.click()
85
+ }
86
+ }
87
+ </script>
88
+
89
+ <div
90
+ data-upload-target
91
+ data-size={size}
92
+ data-disabled={disabled || undefined}
93
+ data-dragging={dragging || undefined}
94
+ role="button"
95
+ tabindex="0"
96
+ aria-label={resolvedLabels.dropzone ?? 'File upload drop zone'}
97
+ aria-disabled={disabled}
98
+ class={className || undefined}
99
+ ondragover={handleDragOver}
100
+ ondragleave={handleDragLeave}
101
+ ondrop={handleDrop}
102
+ onclick={() => {
103
+ if (!disabled) inputRef?.click()
104
+ }}
105
+ onkeydown={handleKeydown}
106
+ >
107
+ {#if content}
108
+ {@render content(dragging)}
109
+ {:else}
110
+ <span data-upload-icon class="i-lucide:upload" aria-hidden="true"></span>
111
+ {#if size !== 'small'}
112
+ <p>Drop files here or click to browse</p>
113
+ <button type="button" data-upload-button {disabled}>Browse</button>
114
+ {/if}
115
+ {/if}
116
+
117
+ <input
118
+ bind:this={inputRef}
119
+ type="file"
120
+ {accept}
121
+ {multiple}
122
+ {disabled}
123
+ hidden
124
+ onchange={handleInputChange}
125
+ />
126
+ </div>
@@ -0,0 +1,50 @@
1
+ // UI Components
2
+ export { default as Button } from './Button.svelte'
3
+ export { default as ButtonGroup } from './ButtonGroup.svelte'
4
+ export { default as Code } from './Code.svelte'
5
+ export { default as Menu } from './Menu.svelte'
6
+ export { default as Dropdown } from './Dropdown.svelte'
7
+ export { default as Select } from './Select.svelte'
8
+ export { default as MultiSelect } from './MultiSelect.svelte'
9
+ export { default as Toolbar } from './Toolbar.svelte'
10
+ export { default as ToolbarGroup } from './ToolbarGroup.svelte'
11
+ export { default as Tabs } from './Tabs.svelte'
12
+ export { default as Toggle } from './Toggle.svelte'
13
+ export { default as Swatch } from './Swatch.svelte'
14
+ export { default as List } from './List.svelte'
15
+ export { default as Tree } from './Tree.svelte'
16
+ export { default as LazyTree } from './LazyTree.svelte'
17
+ export { default as Connector } from './Connector.svelte'
18
+ export { default as ItemContent } from './ItemContent.svelte'
19
+ export { default as FloatingAction } from './FloatingAction.svelte'
20
+ export { default as PaletteManager } from './PaletteManager.svelte'
21
+ export { default as Tilt } from './Tilt.svelte'
22
+ export { default as Shine } from './Shine.svelte'
23
+ export { default as BreadCrumbs } from './BreadCrumbs.svelte'
24
+ export { default as Card } from './Card.svelte'
25
+ export { default as ProgressBar } from './ProgressBar.svelte'
26
+ export { default as Carousel } from './Carousel.svelte'
27
+ export { default as Pill } from './Pill.svelte'
28
+ export { default as Rating } from './Rating.svelte'
29
+ export { default as Stepper } from './Stepper.svelte'
30
+ export { default as Switch } from './Switch.svelte'
31
+ export { default as Table } from './Table.svelte'
32
+ export { default as SearchFilter } from './SearchFilter.svelte'
33
+ export { default as Range } from './Range.svelte'
34
+ export { default as Timeline } from './Timeline.svelte'
35
+ export { default as Reveal } from './Reveal.svelte'
36
+ export { default as Grid } from './Grid.svelte'
37
+ export { default as UploadTarget } from './UploadTarget.svelte'
38
+ export { default as UploadFileStatus } from './UploadFileStatus.svelte'
39
+ export { default as UploadProgress } from './UploadProgress.svelte'
40
+ export { default as FloatingNavigation } from './FloatingNavigation.svelte'
41
+ export { default as StatusList } from './StatusList.svelte'
42
+ export { default as Message } from './Message.svelte'
43
+ export { default as AlertList } from './AlertList.svelte'
44
+ export { default as Divider } from './Divider.svelte'
45
+ export { default as Stack } from './Stack.svelte'
46
+ export { default as Badge } from './Badge.svelte'
47
+ export { default as Avatar } from './Avatar.svelte'
48
+ export { default as Tooltip } from './Tooltip.svelte'
49
+ export { default as NavContent } from './NavContent.svelte'
50
+ export { default as ResponsiveGrid } from './ResponsiveGrid.svelte'
package/src/index.ts ADDED
@@ -0,0 +1,61 @@
1
+ // Components
2
+ export {
3
+ Button,
4
+ ButtonGroup,
5
+ Code,
6
+ Menu,
7
+ Dropdown,
8
+ Select,
9
+ MultiSelect,
10
+ Toolbar,
11
+ ToolbarGroup,
12
+ Tabs,
13
+ Toggle,
14
+ Swatch,
15
+ List,
16
+ Tree,
17
+ LazyTree,
18
+ FloatingAction,
19
+ FloatingNavigation,
20
+ PaletteManager,
21
+ Tilt,
22
+ Shine,
23
+ BreadCrumbs,
24
+ Card,
25
+ ProgressBar,
26
+ Carousel,
27
+ Pill,
28
+ Rating,
29
+ Connector,
30
+ Stepper,
31
+ Switch,
32
+ Table,
33
+ SearchFilter,
34
+ Range,
35
+ Timeline,
36
+ Reveal,
37
+ Grid,
38
+ UploadTarget,
39
+ UploadFileStatus,
40
+ UploadProgress,
41
+ StatusList,
42
+ Message,
43
+ AlertList,
44
+ Divider,
45
+ Stack,
46
+ Badge,
47
+ Avatar,
48
+ Tooltip,
49
+ NavContent,
50
+ ResponsiveGrid
51
+ } from './components/index.js'
52
+
53
+ export { default as MarkdownRenderer } from './MarkdownRenderer.svelte'
54
+ export type { MarkdownPlugin } from './markdown-plugin.js'
55
+
56
+ // Utilities
57
+ export { highlightCode, preloadHighlighter, getSupportedLanguages } from './utils/shiki.js'
58
+ export * from './utils/palette.js'
59
+
60
+ // Types
61
+ export * from './types/index.js'
@@ -0,0 +1,12 @@
1
+ import type { Component } from 'svelte'
2
+
3
+ /**
4
+ * A plugin that renders a fenced code block as a Svelte component.
5
+ * The component receives { code: string } as props.
6
+ */
7
+ export interface MarkdownPlugin {
8
+ /** Fenced code block language to match (e.g. 'plot', 'table', 'sparkline') */
9
+ language: string
10
+ /** Svelte component to render the block. Receives { code: string } */
11
+ component: Component<{ code: string }>
12
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Button Component Types
3
+ *
4
+ * Provides types for the Button and ButtonGroup components.
5
+ * Supports variants, styles, sizes, loading state, link buttons, and custom content.
6
+ */
7
+
8
+ import type { Snippet } from 'svelte'
9
+
10
+ // =============================================================================
11
+ // Variant & Style Types
12
+ // =============================================================================
13
+
14
+ /** Semantic color variant */
15
+ export type ButtonVariant = 'default' | 'primary' | 'secondary' | 'accent' | 'danger'
16
+
17
+ /** Visual style treatment */
18
+ export type ButtonStyle = 'default' | 'outline' | 'ghost' | 'gradient' | 'link'
19
+
20
+ // =============================================================================
21
+ // Component Props Types
22
+ // =============================================================================
23
+
24
+ /**
25
+ * Props for the Button component
26
+ */
27
+ export interface ButtonProps {
28
+ /** Semantic color variant */
29
+ variant?: ButtonVariant
30
+
31
+ /** Visual style treatment */
32
+ style?: ButtonStyle
33
+
34
+ /** Size variant */
35
+ size?: 'sm' | 'md' | 'lg'
36
+
37
+ /** HTML button type */
38
+ type?: 'button' | 'submit' | 'reset'
39
+
40
+ /** Button label text */
41
+ label?: string
42
+
43
+ /** Leading icon class */
44
+ icon?: string
45
+
46
+ /** Trailing icon class */
47
+ iconRight?: string
48
+
49
+ /** Navigates as link instead of button */
50
+ href?: string
51
+
52
+ /** Link target (when href is set) */
53
+ target?: string
54
+
55
+ /** Native tooltip shown on hover */
56
+ title?: string
57
+
58
+ /** Disabled state */
59
+ disabled?: boolean
60
+
61
+ /** Loading state — shows spinner, disables interaction */
62
+ loading?: boolean
63
+
64
+ /** Additional CSS classes */
65
+ class?: string
66
+
67
+ /** Click handler */
68
+ onclick?: (event: MouseEvent) => void
69
+
70
+ /** Custom content snippet */
71
+ children?: Snippet
72
+ }
73
+
74
+ /**
75
+ * Props for the ButtonGroup component
76
+ */
77
+ export interface ButtonGroupProps {
78
+ /** Size applied to all buttons in the group */
79
+ size?: 'sm' | 'md' | 'lg'
80
+
81
+ /** Additional CSS classes */
82
+ class?: string
83
+
84
+ /** Content snippet (buttons) */
85
+ children?: Snippet
86
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Code component types
3
+ */
4
+
5
+ import { DEFAULT_STATE_ICONS } from '@rokkit/core'
6
+
7
+ /** Supported themes for code highlighting */
8
+ export type CodeTheme = 'light' | 'dark'
9
+
10
+ /**
11
+ * Icons configuration for code action states.
12
+ * Keys match the naming convention in @rokkit/core DEFAULT_STATE_ICONS.
13
+ */
14
+ export interface CodeStateIcons {
15
+ /** Icon class for copy button */
16
+ copy?: string
17
+ /** Icon class for copy success state */
18
+ copysuccess?: string
19
+ }
20
+
21
+ /**
22
+ * Default state icons — uses semantic names from @rokkit/core
23
+ * that get resolved to actual icon classes via UnoCSS shortcuts.
24
+ */
25
+ export const defaultCodeStateIcons: CodeStateIcons = {
26
+ copy: DEFAULT_STATE_ICONS.action.copy,
27
+ copysuccess: DEFAULT_STATE_ICONS.action.copysuccess
28
+ }
29
+
30
+ /** Props for the Code component */
31
+ export interface CodeProps {
32
+ /** The code string to display and highlight */
33
+ code: string
34
+ /** Programming language for syntax highlighting */
35
+ language?: string
36
+ /** Color theme for the code block */
37
+ theme?: CodeTheme
38
+ /** Whether to show line numbers */
39
+ showLineNumbers?: boolean
40
+ /** Whether to show the copy button */
41
+ showCopyButton?: boolean
42
+ /** Icons for copy action states */
43
+ icons?: CodeStateIcons
44
+ /** Additional CSS class */
45
+ class?: string
46
+ }
@@ -0,0 +1,123 @@
1
+ import type { Snippet } from 'svelte'
2
+
3
+ /**
4
+ * Field mapping for FloatingAction items
5
+ */
6
+ export type FloatingActionFields = Record<string, string>
7
+
8
+ /**
9
+ * Default field mappings
10
+ */
11
+ export const defaultFloatingActionFields: Required<
12
+ Pick<FloatingActionFields, 'text' | 'value' | 'icon' | 'label' | 'disabled'>
13
+ > = {
14
+ text: 'text',
15
+ value: 'value',
16
+ icon: 'icon',
17
+ label: 'label',
18
+ disabled: 'disabled'
19
+ }
20
+
21
+ /**
22
+ * A single action item
23
+ */
24
+ export type FloatingActionItem = Record<string, unknown>
25
+
26
+ /**
27
+ * Event handlers passed to custom snippets
28
+ */
29
+ export interface FloatingActionItemHandlers {
30
+ onclick: () => void
31
+ onkeydown: (event: KeyboardEvent) => void
32
+ }
33
+
34
+ /**
35
+ * Custom snippet for rendering an action item
36
+ */
37
+ export type FloatingActionItemSnippet = Snippet<
38
+ [item: FloatingActionItem, fields: FloatingActionFields, handlers: FloatingActionItemHandlers]
39
+ >
40
+
41
+ /**
42
+ * Position options for the FAB
43
+ */
44
+ export type FloatingActionPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
45
+
46
+ /**
47
+ * Expansion direction for action items
48
+ */
49
+ export type FloatingActionExpand = 'radial' | 'vertical' | 'horizontal'
50
+
51
+ /**
52
+ * Alignment for action items in the menu
53
+ */
54
+ export type FloatingActionItemAlign = 'start' | 'center' | 'end'
55
+
56
+ /**
57
+ * Icons for the FloatingAction trigger button
58
+ */
59
+ export interface FloatingActionIcons {
60
+ /** Icon for the main trigger (add action) */
61
+ add?: string
62
+ /** Icon shown when menu is open (close action) */
63
+ close?: string
64
+ }
65
+
66
+ /**
67
+ * Props for the FloatingAction component
68
+ */
69
+ export interface FloatingActionProps {
70
+ /** Array of action items */
71
+ items?: FloatingActionItem[]
72
+
73
+ /** Field mapping configuration */
74
+ fields?: FloatingActionFields
75
+
76
+ /** Custom icons for the trigger button */
77
+ icons?: FloatingActionIcons
78
+
79
+ /** Accessible label for the trigger */
80
+ label?: string
81
+
82
+ /** Size variant */
83
+ size?: 'sm' | 'md' | 'lg'
84
+
85
+ /** Position on screen */
86
+ position?: FloatingActionPosition
87
+
88
+ /** How items expand when opened */
89
+ expand?: FloatingActionExpand
90
+
91
+ /** Alignment of items in the menu (start/center/end) */
92
+ itemAlign?: FloatingActionItemAlign
93
+
94
+ /** Disable the FAB */
95
+ disabled?: boolean
96
+
97
+ /** Whether the menu is open (bindable) */
98
+ open?: boolean
99
+
100
+ /** Show backdrop overlay when open */
101
+ backdrop?: boolean
102
+
103
+ /** Position relative to nearest positioned ancestor instead of viewport */
104
+ contained?: boolean
105
+
106
+ /** Called when an action is selected */
107
+ onselect?: (value: unknown, item: FloatingActionItem) => void
108
+
109
+ /** Called when menu opens */
110
+ onopen?: () => void
111
+
112
+ /** Called when menu closes */
113
+ onclose?: () => void
114
+
115
+ /** Additional CSS classes */
116
+ class?: string
117
+
118
+ /** Custom snippet for rendering action items */
119
+ item?: FloatingActionItemSnippet
120
+ }
121
+
122
+ // Re-export getSnippet for convenience
123
+ export { getSnippet } from './menu.js'