@insymetri/styleguide 0.1.34 → 0.1.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.
- package/dist/IIContextMenu/IIContextMenu.svelte +169 -0
- package/dist/IIContextMenu/IIContextMenuStories.svelte +162 -0
- package/dist/IIContextMenu/IIContextMenuStories.svelte.d.ts +18 -0
- package/dist/IIContextMenu/index.d.ts +1 -0
- package/dist/IIContextMenu/index.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type {Snippet} from 'svelte'
|
|
3
|
+
import {ContextMenu} from 'bits-ui'
|
|
4
|
+
import {cn} from '../utils/cn'
|
|
5
|
+
import {IIIcon} from '../IIIcon'
|
|
6
|
+
|
|
7
|
+
type Item = {
|
|
8
|
+
label: string
|
|
9
|
+
value: string
|
|
10
|
+
icon?: Snippet
|
|
11
|
+
disabled?: boolean
|
|
12
|
+
variant?: 'default' | 'destructive'
|
|
13
|
+
shortcut?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type SeparatorEntry = {
|
|
17
|
+
type: 'separator'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type GroupEntry = {
|
|
21
|
+
type: 'group'
|
|
22
|
+
heading?: string
|
|
23
|
+
items: (Item | SubEntry)[]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type SubEntry = {
|
|
27
|
+
type: 'sub'
|
|
28
|
+
label: string
|
|
29
|
+
icon?: Snippet
|
|
30
|
+
disabled?: boolean
|
|
31
|
+
shortcut?: string
|
|
32
|
+
items: MenuEntry[]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type MenuEntry = Item | SeparatorEntry | GroupEntry | SubEntry
|
|
36
|
+
|
|
37
|
+
type Props = {
|
|
38
|
+
items: MenuEntry[]
|
|
39
|
+
onSelect: (value: string) => void
|
|
40
|
+
open?: boolean
|
|
41
|
+
children: Snippet
|
|
42
|
+
renderItem?: Snippet<[Item]>
|
|
43
|
+
class?: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let {
|
|
47
|
+
items,
|
|
48
|
+
onSelect,
|
|
49
|
+
open = $bindable(false),
|
|
50
|
+
children,
|
|
51
|
+
renderItem,
|
|
52
|
+
class: className,
|
|
53
|
+
}: Props = $props()
|
|
54
|
+
|
|
55
|
+
function handleSelect(value: string) {
|
|
56
|
+
onSelect(value)
|
|
57
|
+
open = false
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function isSeparator(entry: MenuEntry): entry is SeparatorEntry {
|
|
61
|
+
return 'type' in entry && entry.type === 'separator'
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function isGroup(entry: MenuEntry): entry is GroupEntry {
|
|
65
|
+
return 'type' in entry && entry.type === 'group'
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function isSub(entry: MenuEntry): entry is SubEntry {
|
|
69
|
+
return 'type' in entry && entry.type === 'sub'
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function isItem(entry: MenuEntry): entry is Item {
|
|
73
|
+
return !('type' in entry)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const itemClass = 'flex items-center gap-8 px-12 py-8 rounded-4 text-small cursor-default select-none outline-none data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed data-[disabled]:pointer-events-none motion-reduce:transition-none'
|
|
77
|
+
const itemDefaultClass = 'text-dropdown-item hover:bg-dropdown-item-hover data-[highlighted]:bg-dropdown-item-hover data-[highlighted]:outline-none'
|
|
78
|
+
const itemDestructiveClass = 'text-error hover:bg-error-bg data-[highlighted]:bg-error-bg data-[highlighted]:outline-none'
|
|
79
|
+
const contentClass = 'min-w-48 max-h-300 overflow-y-auto bg-dropdown-bg border border-dropdown-border rounded-10 shadow-dropdown p-4 z-12 animate-slide-in motion-reduce:animate-none'
|
|
80
|
+
</script>
|
|
81
|
+
|
|
82
|
+
{#snippet itemContent(item: Item)}
|
|
83
|
+
{#if renderItem}
|
|
84
|
+
{@render renderItem(item)}
|
|
85
|
+
{:else}
|
|
86
|
+
{#if item.icon}
|
|
87
|
+
<div class="w-16 h-16 flex items-center justify-center shrink-0 [&_svg]:w-16 [&_svg]:h-16">
|
|
88
|
+
{@render item.icon()}
|
|
89
|
+
</div>
|
|
90
|
+
{/if}
|
|
91
|
+
<span class="flex-1">{item.label}</span>
|
|
92
|
+
{#if item.shortcut}
|
|
93
|
+
<span class="text-tiny text-tertiary ml-8">{item.shortcut}</span>
|
|
94
|
+
{/if}
|
|
95
|
+
{/if}
|
|
96
|
+
{/snippet}
|
|
97
|
+
|
|
98
|
+
{#snippet menuItem(item: Item)}
|
|
99
|
+
<ContextMenu.Item
|
|
100
|
+
disabled={item.disabled}
|
|
101
|
+
class={cn(itemClass, item.variant === 'destructive' ? itemDestructiveClass : itemDefaultClass)}
|
|
102
|
+
onSelect={() => handleSelect(item.value)}
|
|
103
|
+
>
|
|
104
|
+
{@render itemContent(item)}
|
|
105
|
+
</ContextMenu.Item>
|
|
106
|
+
{/snippet}
|
|
107
|
+
|
|
108
|
+
{#snippet subMenu(entry: SubEntry)}
|
|
109
|
+
<ContextMenu.Sub>
|
|
110
|
+
<ContextMenu.SubTrigger
|
|
111
|
+
disabled={entry.disabled}
|
|
112
|
+
class={cn(itemClass, itemDefaultClass)}
|
|
113
|
+
>
|
|
114
|
+
{#if entry.icon}
|
|
115
|
+
<div class="w-16 h-16 flex items-center justify-center shrink-0 [&_svg]:w-16 [&_svg]:h-16">
|
|
116
|
+
{@render entry.icon()}
|
|
117
|
+
</div>
|
|
118
|
+
{/if}
|
|
119
|
+
<span class="flex-1">{entry.label}</span>
|
|
120
|
+
{#if entry.shortcut}
|
|
121
|
+
<span class="text-tiny text-tertiary ml-8">{entry.shortcut}</span>
|
|
122
|
+
{/if}
|
|
123
|
+
<IIIcon iconName="caret-right" class="w-12 h-12 text-tertiary shrink-0" />
|
|
124
|
+
</ContextMenu.SubTrigger>
|
|
125
|
+
<ContextMenu.Portal>
|
|
126
|
+
<ContextMenu.SubContent class={contentClass}>
|
|
127
|
+
{@render menuEntries(entry.items)}
|
|
128
|
+
</ContextMenu.SubContent>
|
|
129
|
+
</ContextMenu.Portal>
|
|
130
|
+
</ContextMenu.Sub>
|
|
131
|
+
{/snippet}
|
|
132
|
+
|
|
133
|
+
{#snippet menuEntries(entries: MenuEntry[])}
|
|
134
|
+
{#each entries as entry, i (i)}
|
|
135
|
+
{#if isSeparator(entry)}
|
|
136
|
+
<ContextMenu.Separator class="h-1 bg-muted mx-4 my-4" />
|
|
137
|
+
{:else if isGroup(entry)}
|
|
138
|
+
<ContextMenu.Group>
|
|
139
|
+
{#if entry.heading}
|
|
140
|
+
<ContextMenu.GroupHeading class="text-tiny-emphasis text-secondary px-12 py-4 uppercase select-none">
|
|
141
|
+
{entry.heading}
|
|
142
|
+
</ContextMenu.GroupHeading>
|
|
143
|
+
{/if}
|
|
144
|
+
{#each entry.items as groupItem (isItem(groupItem) ? groupItem.value : groupItem.label)}
|
|
145
|
+
{#if isSub(groupItem)}
|
|
146
|
+
{@render subMenu(groupItem)}
|
|
147
|
+
{:else}
|
|
148
|
+
{@render menuItem(groupItem)}
|
|
149
|
+
{/if}
|
|
150
|
+
{/each}
|
|
151
|
+
</ContextMenu.Group>
|
|
152
|
+
{:else if isSub(entry)}
|
|
153
|
+
{@render subMenu(entry)}
|
|
154
|
+
{:else if isItem(entry)}
|
|
155
|
+
{@render menuItem(entry)}
|
|
156
|
+
{/if}
|
|
157
|
+
{/each}
|
|
158
|
+
{/snippet}
|
|
159
|
+
|
|
160
|
+
<ContextMenu.Root bind:open>
|
|
161
|
+
<ContextMenu.Trigger class="inline-block">
|
|
162
|
+
{@render children()}
|
|
163
|
+
</ContextMenu.Trigger>
|
|
164
|
+
<ContextMenu.Portal>
|
|
165
|
+
<ContextMenu.Content class={cn(contentClass, className)}>
|
|
166
|
+
{@render menuEntries(items)}
|
|
167
|
+
</ContextMenu.Content>
|
|
168
|
+
</ContextMenu.Portal>
|
|
169
|
+
</ContextMenu.Root>
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import IIContextMenu from './IIContextMenu.svelte'
|
|
3
|
+
import {IIIcon} from '../IIIcon'
|
|
4
|
+
|
|
5
|
+
function handleSelect(value: string) {
|
|
6
|
+
console.log('Selected:', value)
|
|
7
|
+
}
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
{#snippet statusIcon()}<IIIcon iconName="clock" />{/snippet}
|
|
11
|
+
{#snippet clockIcon()}<IIIcon iconName="clock-clockwise" />{/snippet}
|
|
12
|
+
{#snippet circleIcon()}<IIIcon iconName="circle" />{/snippet}
|
|
13
|
+
{#snippet checkCircleIcon()}<IIIcon iconName="check-circle" />{/snippet}
|
|
14
|
+
{#snippet userIcon()}<IIIcon iconName="user" />{/snippet}
|
|
15
|
+
{#snippet warningIcon()}<IIIcon iconName="warning-circle" />{/snippet}
|
|
16
|
+
{#snippet listIcon()}<IIIcon iconName="list" />{/snippet}
|
|
17
|
+
{#snippet pencilIcon()}<IIIcon iconName="pencil-simple" />{/snippet}
|
|
18
|
+
{#snippet trashIcon()}<IIIcon iconName="trash" />{/snippet}
|
|
19
|
+
|
|
20
|
+
<div class="flex flex-col gap-32">
|
|
21
|
+
<!-- Basic -->
|
|
22
|
+
<section>
|
|
23
|
+
<h2 class="text-default-emphasis text-primary mb-8">Basic</h2>
|
|
24
|
+
<p class="text-small text-secondary mb-12">Right-click the area below to open the context menu.</p>
|
|
25
|
+
<IIContextMenu
|
|
26
|
+
items={[
|
|
27
|
+
{label: 'Edit', value: 'edit'},
|
|
28
|
+
{label: 'Duplicate', value: 'duplicate'},
|
|
29
|
+
{label: 'Archive', value: 'archive'},
|
|
30
|
+
{label: 'Delete', value: 'delete', variant: 'destructive'},
|
|
31
|
+
]}
|
|
32
|
+
onSelect={handleSelect}
|
|
33
|
+
>
|
|
34
|
+
<div class="w-full h-100 border border-dashed border-muted rounded-8 flex items-center justify-center text-small text-secondary">
|
|
35
|
+
Right-click here
|
|
36
|
+
</div>
|
|
37
|
+
</IIContextMenu>
|
|
38
|
+
</section>
|
|
39
|
+
|
|
40
|
+
<!-- With Separators -->
|
|
41
|
+
<section>
|
|
42
|
+
<h2 class="text-default-emphasis text-primary mb-8">With Separators</h2>
|
|
43
|
+
<p class="text-small text-secondary mb-12">Menu entries can include separator dividers.</p>
|
|
44
|
+
<IIContextMenu
|
|
45
|
+
items={[
|
|
46
|
+
{label: 'Cut', value: 'cut', shortcut: '⌘X'},
|
|
47
|
+
{label: 'Copy', value: 'copy', shortcut: '⌘C'},
|
|
48
|
+
{label: 'Paste', value: 'paste', shortcut: '⌘V'},
|
|
49
|
+
{type: 'separator'},
|
|
50
|
+
{label: 'Delete', value: 'delete', variant: 'destructive'},
|
|
51
|
+
]}
|
|
52
|
+
onSelect={handleSelect}
|
|
53
|
+
>
|
|
54
|
+
<div class="w-full h-100 border border-dashed border-muted rounded-8 flex items-center justify-center text-small text-secondary">
|
|
55
|
+
Right-click here
|
|
56
|
+
</div>
|
|
57
|
+
</IIContextMenu>
|
|
58
|
+
</section>
|
|
59
|
+
|
|
60
|
+
<!-- With Submenus -->
|
|
61
|
+
<section>
|
|
62
|
+
<h2 class="text-default-emphasis text-primary mb-8">With Submenus</h2>
|
|
63
|
+
<p class="text-small text-secondary mb-12">Hover over an item with an arrow to reveal its submenu.</p>
|
|
64
|
+
<IIContextMenu
|
|
65
|
+
items={[
|
|
66
|
+
{
|
|
67
|
+
type: 'sub',
|
|
68
|
+
label: 'Status',
|
|
69
|
+
icon: statusIcon,
|
|
70
|
+
shortcut: 'S',
|
|
71
|
+
items: [
|
|
72
|
+
{label: 'To Do', value: 'status-todo', icon: circleIcon},
|
|
73
|
+
{label: 'In Progress', value: 'status-progress', icon: clockIcon},
|
|
74
|
+
{label: 'Done', value: 'status-done', icon: checkCircleIcon},
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
type: 'sub',
|
|
79
|
+
label: 'Assignee',
|
|
80
|
+
icon: userIcon,
|
|
81
|
+
shortcut: 'A',
|
|
82
|
+
items: [
|
|
83
|
+
{label: 'No assignee', value: 'assign-none', icon: userIcon},
|
|
84
|
+
{type: 'separator'},
|
|
85
|
+
{
|
|
86
|
+
type: 'group',
|
|
87
|
+
heading: 'Team members',
|
|
88
|
+
items: [
|
|
89
|
+
{label: 'Alice', value: 'assign-alice', icon: userIcon},
|
|
90
|
+
{label: 'Bob', value: 'assign-bob', icon: userIcon},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: 'sub',
|
|
97
|
+
label: 'Priority',
|
|
98
|
+
icon: warningIcon,
|
|
99
|
+
shortcut: 'P',
|
|
100
|
+
items: [
|
|
101
|
+
{label: 'Urgent', value: 'priority-urgent'},
|
|
102
|
+
{label: 'High', value: 'priority-high'},
|
|
103
|
+
{label: 'Medium', value: 'priority-medium'},
|
|
104
|
+
{label: 'Low', value: 'priority-low'},
|
|
105
|
+
{label: 'No priority', value: 'priority-none'},
|
|
106
|
+
],
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
type: 'sub',
|
|
110
|
+
label: 'Labels',
|
|
111
|
+
icon: listIcon,
|
|
112
|
+
shortcut: 'L',
|
|
113
|
+
items: [
|
|
114
|
+
{label: 'Bug', value: 'label-bug'},
|
|
115
|
+
{label: 'Feature', value: 'label-feature'},
|
|
116
|
+
{label: 'Improvement', value: 'label-improvement'},
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
{type: 'separator'},
|
|
120
|
+
{label: 'Rename...', value: 'rename', icon: pencilIcon, shortcut: 'R'},
|
|
121
|
+
{label: 'Delete', value: 'delete', icon: trashIcon, variant: 'destructive'},
|
|
122
|
+
]}
|
|
123
|
+
onSelect={handleSelect}
|
|
124
|
+
>
|
|
125
|
+
<div class="w-full h-100 border border-dashed border-muted rounded-8 flex items-center justify-center text-small text-secondary">
|
|
126
|
+
Right-click here
|
|
127
|
+
</div>
|
|
128
|
+
</IIContextMenu>
|
|
129
|
+
</section>
|
|
130
|
+
|
|
131
|
+
<!-- With Groups -->
|
|
132
|
+
<section>
|
|
133
|
+
<h2 class="text-default-emphasis text-primary mb-8">With Groups</h2>
|
|
134
|
+
<p class="text-small text-secondary mb-12">Items organized into labeled groups with headings.</p>
|
|
135
|
+
<IIContextMenu
|
|
136
|
+
items={[
|
|
137
|
+
{
|
|
138
|
+
type: 'group',
|
|
139
|
+
heading: 'Edit',
|
|
140
|
+
items: [
|
|
141
|
+
{label: 'Cut', value: 'cut'},
|
|
142
|
+
{label: 'Copy', value: 'copy'},
|
|
143
|
+
{label: 'Paste', value: 'paste'},
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
{type: 'separator'},
|
|
147
|
+
{
|
|
148
|
+
type: 'group',
|
|
149
|
+
heading: 'Danger Zone',
|
|
150
|
+
items: [
|
|
151
|
+
{label: 'Delete', value: 'delete', variant: 'destructive'},
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
]}
|
|
155
|
+
onSelect={handleSelect}
|
|
156
|
+
>
|
|
157
|
+
<div class="w-full h-100 border border-dashed border-muted rounded-8 flex items-center justify-center text-small text-secondary">
|
|
158
|
+
Right-click here
|
|
159
|
+
</div>
|
|
160
|
+
</IIContextMenu>
|
|
161
|
+
</section>
|
|
162
|
+
</div>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const IIContextMenuStories: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type IIContextMenuStories = InstanceType<typeof IIContextMenuStories>;
|
|
18
|
+
export default IIContextMenuStories;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IIContextMenu } from './IIContextMenu.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IIContextMenu } from './IIContextMenu.svelte';
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { IICard } from './IICard';
|
|
|
13
13
|
export { IICheckbox } from './IICheckbox';
|
|
14
14
|
export { IICheckboxList } from './IICheckboxList';
|
|
15
15
|
export { IICombobox } from './IICombobox';
|
|
16
|
+
export { IIContextMenu } from './IIContextMenu';
|
|
16
17
|
export { IIDateInput } from './IIDateInput';
|
|
17
18
|
export { IIDropdownInput } from './IIDropdownInput';
|
|
18
19
|
export { IIDropdownMenu } from './IIDropdownMenu';
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export { IICard } from './IICard';
|
|
|
17
17
|
export { IICheckbox } from './IICheckbox';
|
|
18
18
|
export { IICheckboxList } from './IICheckboxList';
|
|
19
19
|
export { IICombobox } from './IICombobox';
|
|
20
|
+
export { IIContextMenu } from './IIContextMenu';
|
|
20
21
|
export { IIDateInput } from './IIDateInput';
|
|
21
22
|
export { IIDropdownInput } from './IIDropdownInput';
|
|
22
23
|
export { IIDropdownMenu } from './IIDropdownMenu';
|