@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.
- package/README.md +159 -1
- package/package.json +52 -53
- package/src/MarkdownRenderer.svelte +106 -0
- package/src/components/AlertList.svelte +59 -0
- package/src/components/Avatar.svelte +68 -0
- package/src/components/Badge.svelte +57 -0
- package/src/components/BreadCrumbs.svelte +94 -0
- package/src/components/Button.svelte +91 -0
- package/src/components/ButtonGroup.svelte +9 -0
- package/src/components/Card.svelte +71 -0
- package/src/components/Carousel.svelte +169 -0
- package/src/components/Code.svelte +189 -0
- package/src/components/Connector.svelte +46 -0
- package/src/components/Divider.svelte +24 -0
- package/src/components/Dropdown.svelte +202 -0
- package/src/components/FloatingAction.svelte +367 -0
- package/src/components/FloatingNavigation.svelte +256 -0
- package/src/components/Grid.svelte +128 -0
- package/src/components/ItemContent.svelte +25 -0
- package/src/components/LazyTree.svelte +171 -0
- package/src/components/List.svelte +224 -0
- package/src/components/Menu.svelte +270 -0
- package/src/components/Message.svelte +75 -0
- package/src/components/MultiSelect.svelte +367 -0
- package/src/components/NavContent.svelte +42 -0
- package/src/components/PaletteManager.svelte +360 -0
- package/src/components/Pill.svelte +83 -0
- package/src/components/ProgressBar.svelte +31 -0
- package/src/components/Range.svelte +346 -0
- package/src/components/Rating.svelte +115 -0
- package/src/components/ResponsiveGrid.svelte +34 -0
- package/src/components/Reveal.svelte +46 -0
- package/src/components/SearchFilter.svelte +88 -0
- package/src/components/Select.svelte +424 -0
- package/src/components/Shine.svelte +87 -0
- package/src/components/Stack.svelte +38 -0
- package/src/components/StatusList.svelte +18 -0
- package/src/components/Stepper.svelte +174 -0
- package/src/components/Swatch.svelte +102 -0
- package/src/components/Switch.svelte +71 -0
- package/src/components/Table.svelte +245 -0
- package/src/components/Tabs.svelte +202 -0
- package/src/components/Tilt.svelte +68 -0
- package/src/components/Timeline.svelte +61 -0
- package/src/components/Toggle.svelte +93 -0
- package/src/components/Toolbar.svelte +306 -0
- package/src/components/ToolbarGroup.svelte +17 -0
- package/src/components/Tooltip.svelte +121 -0
- package/src/components/Tree.svelte +143 -0
- package/src/components/UploadFileStatus.svelte +102 -0
- package/src/components/UploadProgress.svelte +127 -0
- package/src/components/UploadTarget.svelte +126 -0
- package/src/components/index.ts +50 -0
- package/src/index.ts +61 -0
- package/src/markdown-plugin.ts +12 -0
- package/src/types/button.ts +86 -0
- package/src/types/code.ts +46 -0
- package/src/types/floating-action.ts +123 -0
- package/src/types/floating-navigation.ts +80 -0
- package/src/types/index.ts +58 -0
- package/src/types/list.ts +200 -0
- package/src/types/menu.ts +95 -0
- package/src/types/palette.ts +160 -0
- package/src/types/range.ts +51 -0
- package/src/types/search-filter.ts +67 -0
- package/src/types/select.ts +176 -0
- package/src/types/switch.ts +68 -0
- package/src/types/table.ts +219 -0
- package/src/types/tabs.ts +103 -0
- package/src/types/timeline.ts +53 -0
- package/src/types/toggle.ts +68 -0
- package/src/types/toolbar.ts +167 -0
- package/src/types/tooltip.ts +21 -0
- package/src/types/tree.ts +250 -0
- package/src/types/upload-file-status.ts +45 -0
- package/src/types/upload-progress.ts +111 -0
- package/src/types/upload-target.ts +71 -0
- package/src/utils/palette.ts +618 -0
- package/src/utils/shiki.ts +114 -0
- package/src/utils/upload.js +145 -0
- package/LICENSE +0 -21
- package/src/index.js +0 -8
- 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'
|