@insymetri/styleguide 0.1.0
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/IIActionGroup/IIActionGroup.svelte +11 -0
- package/dist/IIActionGroup/IIActionGroup.svelte.d.ts +6 -0
- package/dist/IIActionGroup/index.d.ts +1 -0
- package/dist/IIActionGroup/index.js +1 -0
- package/dist/IIAsyncState/IIAsyncState.svelte +50 -0
- package/dist/IIAsyncState/IIAsyncState.svelte.d.ts +15 -0
- package/dist/IIAsyncState/index.d.ts +1 -0
- package/dist/IIAsyncState/index.js +1 -0
- package/dist/IIAuditTrail/IIAuditTrail.svelte +167 -0
- package/dist/IIAuditTrail/IIAuditTrail.svelte.d.ts +13 -0
- package/dist/IIAuditTrail/IIAuditTrail.types.d.ts +14 -0
- package/dist/IIAuditTrail/IIAuditTrail.types.js +1 -0
- package/dist/IIAuditTrail/index.d.ts +2 -0
- package/dist/IIAuditTrail/index.js +1 -0
- package/dist/IIBadge/IIBadge.svelte +46 -0
- package/dist/IIBadge/IIBadge.svelte.d.ts +11 -0
- package/dist/IIBadge/IIBadge.types.d.ts +1 -0
- package/dist/IIBadge/IIBadge.types.js +1 -0
- package/dist/IIBadge/index.d.ts +2 -0
- package/dist/IIBadge/index.js +1 -0
- package/dist/IIButton/IIButton.svelte +103 -0
- package/dist/IIButton/IIButton.svelte.d.ts +23 -0
- package/dist/IIButton/index.d.ts +1 -0
- package/dist/IIButton/index.js +1 -0
- package/dist/IICheckbox/IICheckbox.svelte +66 -0
- package/dist/IICheckbox/IICheckbox.svelte.d.ts +16 -0
- package/dist/IICheckbox/index.d.ts +1 -0
- package/dist/IICheckbox/index.js +1 -0
- package/dist/IICheckboxList/IICheckboxList.svelte +15 -0
- package/dist/IICheckboxList/IICheckboxList.svelte.d.ts +7 -0
- package/dist/IICheckboxList/index.d.ts +1 -0
- package/dist/IICheckboxList/index.js +1 -0
- package/dist/IICombobox/IICombobox.svelte +158 -0
- package/dist/IICombobox/IICombobox.svelte.d.ts +39 -0
- package/dist/IICombobox/index.d.ts +1 -0
- package/dist/IICombobox/index.js +1 -0
- package/dist/IIDatePicker/IIDatePicker.svelte +107 -0
- package/dist/IIDatePicker/IIDatePicker.svelte.d.ts +9 -0
- package/dist/IIDatePicker/index.d.ts +1 -0
- package/dist/IIDatePicker/index.js +1 -0
- package/dist/IIDropdownInput/IIDropdownInput.svelte +76 -0
- package/dist/IIDropdownInput/IIDropdownInput.svelte.d.ts +15 -0
- package/dist/IIDropdownInput/index.d.ts +1 -0
- package/dist/IIDropdownInput/index.js +1 -0
- package/dist/IIDropdownMenu/IIDropdownMenu.svelte +74 -0
- package/dist/IIDropdownMenu/IIDropdownMenu.svelte.d.ts +19 -0
- package/dist/IIDropdownMenu/index.d.ts +1 -0
- package/dist/IIDropdownMenu/index.js +1 -0
- package/dist/IIEditableBadges/IIEditableBadges.svelte +91 -0
- package/dist/IIEditableBadges/IIEditableBadges.svelte.d.ts +17 -0
- package/dist/IIEditableBadges/index.d.ts +1 -0
- package/dist/IIEditableBadges/index.js +1 -0
- package/dist/IIEditableText/IIEditableText.svelte +143 -0
- package/dist/IIEditableText/IIEditableText.svelte.d.ts +12 -0
- package/dist/IIEditableText/index.d.ts +1 -0
- package/dist/IIEditableText/index.js +1 -0
- package/dist/IIEmptyState/IIEmptyState.svelte +29 -0
- package/dist/IIEmptyState/IIEmptyState.svelte.d.ts +9 -0
- package/dist/IIEmptyState/index.d.ts +1 -0
- package/dist/IIEmptyState/index.js +1 -0
- package/dist/IIFilterChip/IIFilterChip.svelte +47 -0
- package/dist/IIFilterChip/IIFilterChip.svelte.d.ts +9 -0
- package/dist/IIFilterChip/index.d.ts +1 -0
- package/dist/IIFilterChip/index.js +1 -0
- package/dist/IIFormField/IIFormField.svelte +18 -0
- package/dist/IIFormField/IIFormField.svelte.d.ts +9 -0
- package/dist/IIFormField/index.d.ts +1 -0
- package/dist/IIFormField/index.js +1 -0
- package/dist/IIInput/IIInput.svelte +69 -0
- package/dist/IIInput/IIInput.svelte.d.ts +15 -0
- package/dist/IIInput/index.d.ts +1 -0
- package/dist/IIInput/index.js +1 -0
- package/dist/IIModal/IIModal.svelte +76 -0
- package/dist/IIModal/IIModal.svelte.d.ts +15 -0
- package/dist/IIModal/index.d.ts +1 -0
- package/dist/IIModal/index.js +1 -0
- package/dist/IIOverflowActions/IIOverflowActions.svelte +104 -0
- package/dist/IIOverflowActions/IIOverflowActions.svelte.d.ts +16 -0
- package/dist/IIOverflowActions/index.d.ts +1 -0
- package/dist/IIOverflowActions/index.js +1 -0
- package/dist/IIStatusBadge/IIStatusBadge.svelte +29 -0
- package/dist/IIStatusBadge/IIStatusBadge.svelte.d.ts +9 -0
- package/dist/IIStatusBadge/index.d.ts +1 -0
- package/dist/IIStatusBadge/index.js +1 -0
- package/dist/IISwitch/IISwitch.svelte +60 -0
- package/dist/IISwitch/IISwitch.svelte.d.ts +15 -0
- package/dist/IISwitch/index.d.ts +1 -0
- package/dist/IISwitch/index.js +1 -0
- package/dist/IITable/IITable.svelte +17 -0
- package/dist/IITable/IITable.svelte.d.ts +8 -0
- package/dist/IITable/index.d.ts +1 -0
- package/dist/IITable/index.js +1 -0
- package/dist/IITableSkeleton/IITableSkeleton.svelte +32 -0
- package/dist/IITableSkeleton/IITableSkeleton.svelte.d.ts +8 -0
- package/dist/IITableSkeleton/index.d.ts +1 -0
- package/dist/IITableSkeleton/index.js +1 -0
- package/dist/IITabs/IITabs.svelte +139 -0
- package/dist/IITabs/IITabs.svelte.d.ts +19 -0
- package/dist/IITabs/index.d.ts +1 -0
- package/dist/IITabs/index.js +1 -0
- package/dist/IITaskCardSkeleton/IITaskCardSkeleton.svelte +15 -0
- package/dist/IITaskCardSkeleton/IITaskCardSkeleton.svelte.d.ts +26 -0
- package/dist/IITaskCardSkeleton/index.d.ts +1 -0
- package/dist/IITaskCardSkeleton/index.js +1 -0
- package/dist/IITextarea/IITextarea.svelte +79 -0
- package/dist/IITextarea/IITextarea.svelte.d.ts +15 -0
- package/dist/IITextarea/index.d.ts +1 -0
- package/dist/IITextarea/index.js +1 -0
- package/dist/IIToaster/IIToaster.svelte +5 -0
- package/dist/IIToaster/IIToaster.svelte.d.ts +18 -0
- package/dist/IIToaster/index.d.ts +1 -0
- package/dist/IIToaster/index.js +1 -0
- package/dist/IIViewFilterChip/IIViewFilterChip.svelte +37 -0
- package/dist/IIViewFilterChip/IIViewFilterChip.svelte.d.ts +8 -0
- package/dist/IIViewFilterChip/index.d.ts +1 -0
- package/dist/IIViewFilterChip/index.js +1 -0
- package/dist/Typography/Typography.svelte +67 -0
- package/dist/Typography/Typography.svelte.d.ts +18 -0
- package/dist/Typography/index.d.ts +1 -0
- package/dist/Typography/index.js +1 -0
- package/dist/icons.d.ts +92 -0
- package/dist/icons.js +104 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +35 -0
- package/dist/style/base.css +71 -0
- package/dist/style/colors.css +183 -0
- package/dist/style/global.css +2 -0
- package/dist/style/index.d.ts +1 -0
- package/dist/style/index.js +1 -0
- package/dist/style/tailwind/animations.js +89 -0
- package/dist/style/tailwind/colors.d.ts +217 -0
- package/dist/style/tailwind/colors.js +239 -0
- package/dist/style/tailwind/preset.js +103 -0
- package/dist/style/tailwind/radius.d.ts +1 -0
- package/dist/style/tailwind/radius.js +5 -0
- package/dist/style/tailwind/shadows.d.ts +15 -0
- package/dist/style/tailwind/shadows.js +27 -0
- package/dist/style/tailwind/spacing.d.ts +1 -0
- package/dist/style/tailwind/spacing.js +37 -0
- package/dist/style/tailwind/typography.d.ts +100 -0
- package/dist/style/tailwind/typography.js +39 -0
- package/dist/style/tailwind/z-index.d.ts +1 -0
- package/dist/style/tailwind/z-index.js +7 -0
- package/dist/toast.d.ts +16 -0
- package/dist/toast.js +24 -0
- package/dist/utils/cn.d.ts +2 -0
- package/dist/utils/cn.js +4 -0
- package/package.json +79 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
<script lang="ts" generics="T">
|
|
2
|
+
import type {Snippet} from 'svelte'
|
|
3
|
+
import {Combobox} from 'bits-ui'
|
|
4
|
+
import {IconCheck} from '../icons'
|
|
5
|
+
import {cn} from '../utils/cn'
|
|
6
|
+
|
|
7
|
+
// Simple default item type for basic usage
|
|
8
|
+
type SimpleItem = {
|
|
9
|
+
label: string
|
|
10
|
+
value: string
|
|
11
|
+
disabled?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type Props<T> = {
|
|
15
|
+
items: T[]
|
|
16
|
+
value?: string
|
|
17
|
+
placeholder?: string
|
|
18
|
+
disabled?: boolean
|
|
19
|
+
onSelect?: (item: T) => void
|
|
20
|
+
// Function to extract value from item (required for custom types)
|
|
21
|
+
getItemValue: (item: T) => string
|
|
22
|
+
// Function to check if item is disabled (optional)
|
|
23
|
+
getItemDisabled?: (item: T) => boolean
|
|
24
|
+
// Custom filter function (optional)
|
|
25
|
+
filterFn?: (items: T[], inputValue: string) => T[]
|
|
26
|
+
// Custom render function for items (optional, uses default if not provided)
|
|
27
|
+
renderItem?: Snippet<[item: T, selected: boolean]>
|
|
28
|
+
// Content shown inside dropdown when there are no items (e.g. loading/no results)
|
|
29
|
+
emptyContent?: Snippet
|
|
30
|
+
// CSS classes
|
|
31
|
+
class?: string
|
|
32
|
+
contentClass?: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let {
|
|
36
|
+
items,
|
|
37
|
+
value = $bindable(''),
|
|
38
|
+
placeholder = 'Select...',
|
|
39
|
+
disabled = false,
|
|
40
|
+
onSelect,
|
|
41
|
+
getItemValue,
|
|
42
|
+
getItemDisabled,
|
|
43
|
+
filterFn,
|
|
44
|
+
renderItem,
|
|
45
|
+
emptyContent,
|
|
46
|
+
class: className,
|
|
47
|
+
contentClass,
|
|
48
|
+
}: Props<T> = $props()
|
|
49
|
+
|
|
50
|
+
let inputValue = $state('')
|
|
51
|
+
let open = $state(false)
|
|
52
|
+
|
|
53
|
+
// Default filter for simple items
|
|
54
|
+
function defaultFilter(items: T[], inputValue: string): T[] {
|
|
55
|
+
if (!inputValue) return items
|
|
56
|
+
return items.filter(item => {
|
|
57
|
+
const itemValue = getItemValue(item)
|
|
58
|
+
// If item is a SimpleItem, use label for filtering
|
|
59
|
+
if (typeof item === 'object' && item !== null && 'label' in item) {
|
|
60
|
+
return (item as unknown as SimpleItem).label.toLowerCase().includes(inputValue.toLowerCase())
|
|
61
|
+
}
|
|
62
|
+
// Otherwise filter by value
|
|
63
|
+
return itemValue.toLowerCase().includes(inputValue.toLowerCase())
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const filteredItems = $derived.by(() => {
|
|
68
|
+
if (filterFn) {
|
|
69
|
+
return filterFn(items, inputValue)
|
|
70
|
+
}
|
|
71
|
+
return defaultFilter(items, inputValue)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
function handleValueChange(newValue: string | undefined) {
|
|
75
|
+
value = newValue || ''
|
|
76
|
+
if (newValue && onSelect) {
|
|
77
|
+
const selectedItem = items.find(item => getItemValue(item) === newValue)
|
|
78
|
+
if (selectedItem) {
|
|
79
|
+
onSelect(selectedItem)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function handleOpenChange(newOpen: boolean) {
|
|
85
|
+
open = newOpen
|
|
86
|
+
if (!newOpen) {
|
|
87
|
+
inputValue = ''
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function handleInput(e: Event & {currentTarget: HTMLInputElement}) {
|
|
92
|
+
inputValue = e.currentTarget.value
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Check if item looks like a SimpleItem for default rendering
|
|
96
|
+
function isSimpleItem(item: T): item is T & SimpleItem {
|
|
97
|
+
return typeof item === 'object' && item !== null && 'label' in item && 'value' in item
|
|
98
|
+
}
|
|
99
|
+
</script>
|
|
100
|
+
|
|
101
|
+
<div class={cn('block w-full', className)}>
|
|
102
|
+
<Combobox.Root
|
|
103
|
+
type="single"
|
|
104
|
+
bind:value
|
|
105
|
+
onValueChange={handleValueChange}
|
|
106
|
+
{disabled}
|
|
107
|
+
{open}
|
|
108
|
+
onOpenChange={handleOpenChange}
|
|
109
|
+
>
|
|
110
|
+
<Combobox.Input
|
|
111
|
+
{placeholder}
|
|
112
|
+
{disabled}
|
|
113
|
+
oninput={handleInput}
|
|
114
|
+
class="w-full box-border py-6 px-12 text-small text-input-text bg-input-bg border border-input-border rounded-10 transition-all duration-fast outline-none placeholder:text-input-placeholder hover:border-input-border-hover focus:border-input-border-hover disabled:opacity-50 disabled:cursor-not-allowed disabled:bg-input-bg-disabled motion-reduce:transition-none"
|
|
115
|
+
/>
|
|
116
|
+
<Combobox.Portal>
|
|
117
|
+
{#if filteredItems.length > 0 || emptyContent}
|
|
118
|
+
<Combobox.Content
|
|
119
|
+
class={cn(
|
|
120
|
+
'bg-surface border border-primary rounded-b-6 border-t-0 shadow-dropdown p-4 max-h-300 overflow-y-auto z-12',
|
|
121
|
+
contentClass
|
|
122
|
+
)}
|
|
123
|
+
style="width: calc(var(--bits-floating-anchor-width) - 4px)"
|
|
124
|
+
sideOffset={2}
|
|
125
|
+
align="start"
|
|
126
|
+
>
|
|
127
|
+
{#each filteredItems as item, i (i + '-' + getItemValue(item))}
|
|
128
|
+
<Combobox.Item
|
|
129
|
+
value={getItemValue(item)}
|
|
130
|
+
label=""
|
|
131
|
+
disabled={getItemDisabled?.(item) ?? false}
|
|
132
|
+
class="flex items-center gap-8 py-6 px-12 text-small text-dropdown-item rounded-4 cursor-default transition-all duration-fast outline-none hover:bg-dropdown-item-hover data-[highlighted]:bg-dropdown-item-hover data-[selected]:bg-dropdown-item-selected data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed motion-reduce:transition-none"
|
|
133
|
+
>
|
|
134
|
+
{#snippet children({selected})}
|
|
135
|
+
{#if renderItem}
|
|
136
|
+
{@render renderItem(item, selected)}
|
|
137
|
+
{:else if isSimpleItem(item)}
|
|
138
|
+
<span class="flex-1">{item.label}</span>
|
|
139
|
+
{#if selected}
|
|
140
|
+
<IconCheck class="w-18 h-18 shrink-0 ml-auto" />
|
|
141
|
+
{/if}
|
|
142
|
+
{:else}
|
|
143
|
+
<span class="flex-1">{getItemValue(item)}</span>
|
|
144
|
+
{#if selected}
|
|
145
|
+
<IconCheck class="w-18 h-18 shrink-0 ml-auto" />
|
|
146
|
+
{/if}
|
|
147
|
+
{/if}
|
|
148
|
+
{/snippet}
|
|
149
|
+
</Combobox.Item>
|
|
150
|
+
{/each}
|
|
151
|
+
{#if filteredItems.length === 0 && emptyContent}
|
|
152
|
+
{@render emptyContent()}
|
|
153
|
+
{/if}
|
|
154
|
+
</Combobox.Content>
|
|
155
|
+
{/if}
|
|
156
|
+
</Combobox.Portal>
|
|
157
|
+
</Combobox.Root>
|
|
158
|
+
</div>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
type Props<T> = {
|
|
3
|
+
items: T[];
|
|
4
|
+
value?: string;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
onSelect?: (item: T) => void;
|
|
8
|
+
getItemValue: (item: T) => string;
|
|
9
|
+
getItemDisabled?: (item: T) => boolean;
|
|
10
|
+
filterFn?: (items: T[], inputValue: string) => T[];
|
|
11
|
+
renderItem?: Snippet<[item: T, selected: boolean]>;
|
|
12
|
+
emptyContent?: Snippet;
|
|
13
|
+
class?: string;
|
|
14
|
+
contentClass?: string;
|
|
15
|
+
};
|
|
16
|
+
declare function $$render<T>(): {
|
|
17
|
+
props: Props<T>;
|
|
18
|
+
exports: {};
|
|
19
|
+
bindings: "value";
|
|
20
|
+
slots: {};
|
|
21
|
+
events: {};
|
|
22
|
+
};
|
|
23
|
+
declare class __sveltets_Render<T> {
|
|
24
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
25
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
26
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
27
|
+
bindings(): "value";
|
|
28
|
+
exports(): {};
|
|
29
|
+
}
|
|
30
|
+
interface $$IsomorphicComponent {
|
|
31
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
32
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
33
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
34
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
35
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
36
|
+
}
|
|
37
|
+
declare const IICombobox: $$IsomorphicComponent;
|
|
38
|
+
type IICombobox<T> = InstanceType<typeof IICombobox<T>>;
|
|
39
|
+
export default IICombobox;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IICombobox } from './IICombobox.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IICombobox } from './IICombobox.svelte';
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {DatePicker} from 'bits-ui'
|
|
3
|
+
import type {DateValue} from '@internationalized/date'
|
|
4
|
+
import {IconCalendar} from '../icons'
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
value: DateValue | undefined
|
|
8
|
+
label?: string
|
|
9
|
+
onValueChange?: (value: DateValue | undefined) => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let {value = $bindable(), label, onValueChange}: Props = $props()
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<DatePicker.Root bind:value {onValueChange}>
|
|
16
|
+
{#if label}
|
|
17
|
+
<DatePicker.Label class="text-small-emphasis text-gray-700 mb-8 block">{label}</DatePicker.Label>
|
|
18
|
+
{/if}
|
|
19
|
+
<div class="relative">
|
|
20
|
+
<DatePicker.Input
|
|
21
|
+
class="flex items-center gap-4 py-6 px-12 border border-strong rounded-10 text-small text-gray-800 bg-surface transition-all duration-fast [&:has(:focus)]:border-primary [&:has(:focus)]:ring-3 [&:has(:focus)]:ring-primary"
|
|
22
|
+
>
|
|
23
|
+
{#snippet children({segments})}
|
|
24
|
+
{#each segments as { part, value: segValue }, i (`${part}-${i}`)}
|
|
25
|
+
<DatePicker.Segment
|
|
26
|
+
{part}
|
|
27
|
+
class="py-4 min-w-[2ch] text-center outline-none cursor-text rounded-4 transition-all duration-fast focus:bg-primary focus:text-inverse data-[placeholder]:text-tertiary motion-reduce:transition-none"
|
|
28
|
+
>
|
|
29
|
+
{segValue}
|
|
30
|
+
</DatePicker.Segment>
|
|
31
|
+
{/each}
|
|
32
|
+
<DatePicker.Trigger
|
|
33
|
+
class="[all:unset] flex items-center justify-center p-4 ml-auto rounded-4 cursor-default text-secondary transition-all duration-fast hover:bg-gray-100 hover:text-body [&_svg]:w-11 [&_svg]:h-11 motion-reduce:transition-none"
|
|
34
|
+
>
|
|
35
|
+
<IconCalendar />
|
|
36
|
+
</DatePicker.Trigger>
|
|
37
|
+
{/snippet}
|
|
38
|
+
</DatePicker.Input>
|
|
39
|
+
</div>
|
|
40
|
+
<DatePicker.Content class="bg-surface border border-primary rounded-10 shadow-dropdown p-12 z-12 min-w-280">
|
|
41
|
+
<DatePicker.Calendar>
|
|
42
|
+
{#snippet children({months, weekdays})}
|
|
43
|
+
<div class="flex items-center justify-between gap-16 mb-12">
|
|
44
|
+
<DatePicker.MonthSelect aria-label="Select month" monthFormat="long">
|
|
45
|
+
{#snippet child({props, monthItems, selectedMonthItem})}
|
|
46
|
+
<select
|
|
47
|
+
{...props}
|
|
48
|
+
class="appearance-none bg-transparent border-0 py-4 pr-16 pl-0 text-small-emphasis text-body cursor-pointer focus:outline-none flex-1"
|
|
49
|
+
style="background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right center"
|
|
50
|
+
>
|
|
51
|
+
{#each monthItems as month (month.value)}
|
|
52
|
+
<option value={month.value} selected={month.value === selectedMonthItem.value}>
|
|
53
|
+
{month.label}
|
|
54
|
+
</option>
|
|
55
|
+
{/each}
|
|
56
|
+
</select>
|
|
57
|
+
{/snippet}
|
|
58
|
+
</DatePicker.MonthSelect>
|
|
59
|
+
<DatePicker.YearSelect aria-label="Select year">
|
|
60
|
+
{#snippet child({props, yearItems, selectedYearItem})}
|
|
61
|
+
<select
|
|
62
|
+
{...props}
|
|
63
|
+
class="appearance-none bg-transparent border-0 py-4 pr-16 pl-0 text-small-emphasis text-body cursor-pointer focus:outline-none"
|
|
64
|
+
style="background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right center"
|
|
65
|
+
>
|
|
66
|
+
{#each yearItems as year (year.value)}
|
|
67
|
+
<option value={year.value} selected={year.value === selectedYearItem.value}>
|
|
68
|
+
{year.label}
|
|
69
|
+
</option>
|
|
70
|
+
{/each}
|
|
71
|
+
</select>
|
|
72
|
+
{/snippet}
|
|
73
|
+
</DatePicker.YearSelect>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
{#each months as month (month.value.toString())}
|
|
77
|
+
<DatePicker.Grid class="w-full border-collapse">
|
|
78
|
+
<DatePicker.GridHead>
|
|
79
|
+
<DatePicker.GridRow class="flex w-full">
|
|
80
|
+
{#each weekdays as day, i (`day-${i}`)}
|
|
81
|
+
<DatePicker.HeadCell class="flex-1 text-center text-tiny-emphasis text-secondary p-4 uppercase">
|
|
82
|
+
{day.slice(0, 2)}
|
|
83
|
+
</DatePicker.HeadCell>
|
|
84
|
+
{/each}
|
|
85
|
+
</DatePicker.GridRow>
|
|
86
|
+
</DatePicker.GridHead>
|
|
87
|
+
<DatePicker.GridBody>
|
|
88
|
+
{#each month.weeks as weekDates, weekIndex (weekIndex)}
|
|
89
|
+
<DatePicker.GridRow class="flex w-full">
|
|
90
|
+
{#each weekDates as date (date.toString())}
|
|
91
|
+
<DatePicker.Cell {date} month={month.value} class="flex-1 aspect-square p-2">
|
|
92
|
+
<DatePicker.Day
|
|
93
|
+
class="[all:unset] flex items-center justify-center w-full h-full rounded-4 text-small text-body cursor-default transition-all duration-fast hover:bg-gray-100 data-[selected]:bg-primary data-[selected]:text-inverse data-[selected]:font-semibold data-[today]:border data-[today]:border-primary data-[outside-month]:text-tertiary data-[outside-month]:opacity-50 data-[disabled]:text-tertiary data-[disabled]:cursor-not-allowed data-[disabled]:opacity-30 motion-reduce:transition-none"
|
|
94
|
+
>
|
|
95
|
+
{date.day}
|
|
96
|
+
</DatePicker.Day>
|
|
97
|
+
</DatePicker.Cell>
|
|
98
|
+
{/each}
|
|
99
|
+
</DatePicker.GridRow>
|
|
100
|
+
{/each}
|
|
101
|
+
</DatePicker.GridBody>
|
|
102
|
+
</DatePicker.Grid>
|
|
103
|
+
{/each}
|
|
104
|
+
{/snippet}
|
|
105
|
+
</DatePicker.Calendar>
|
|
106
|
+
</DatePicker.Content>
|
|
107
|
+
</DatePicker.Root>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DateValue } from '@internationalized/date';
|
|
2
|
+
type Props = {
|
|
3
|
+
value: DateValue | undefined;
|
|
4
|
+
label?: string;
|
|
5
|
+
onValueChange?: (value: DateValue | undefined) => void;
|
|
6
|
+
};
|
|
7
|
+
declare const IIDatePicker: import("svelte").Component<Props, {}, "value">;
|
|
8
|
+
type IIDatePicker = ReturnType<typeof IIDatePicker>;
|
|
9
|
+
export default IIDatePicker;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IIDatePicker } from './IIDatePicker.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IIDatePicker } from './IIDatePicker.svelte';
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {DropdownMenu} from 'bits-ui'
|
|
3
|
+
import {IconExpandMore, IconCheck} from '../icons'
|
|
4
|
+
import {cn} from '../utils/cn'
|
|
5
|
+
|
|
6
|
+
type Item = {
|
|
7
|
+
label: string
|
|
8
|
+
value: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
items: Item[]
|
|
13
|
+
value?: string | undefined
|
|
14
|
+
placeholder?: string
|
|
15
|
+
disabled?: boolean
|
|
16
|
+
onSelect?: (value: string) => void
|
|
17
|
+
class?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
items,
|
|
22
|
+
value = $bindable(),
|
|
23
|
+
placeholder = 'Select...',
|
|
24
|
+
disabled = false,
|
|
25
|
+
onSelect,
|
|
26
|
+
class: className,
|
|
27
|
+
}: Props = $props()
|
|
28
|
+
|
|
29
|
+
let open = $state(false)
|
|
30
|
+
|
|
31
|
+
const selectedLabel = $derived(items.find(i => i.value === value)?.label ?? placeholder)
|
|
32
|
+
|
|
33
|
+
function handleSelect(item: Item) {
|
|
34
|
+
value = item.value
|
|
35
|
+
open = false
|
|
36
|
+
onSelect?.(item.value)
|
|
37
|
+
}
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<DropdownMenu.Root bind:open>
|
|
41
|
+
<DropdownMenu.Trigger
|
|
42
|
+
{disabled}
|
|
43
|
+
class={cn(
|
|
44
|
+
'inline-flex items-center gap-4 py-6 pl-12 pr-8 border rounded-10 bg-input-bg cursor-default text-small text-input-text box-border appearance-none font-inherit outline-none focus:border-accent focus:ring-3 focus:ring-primary disabled:opacity-50 disabled:cursor-not-allowed',
|
|
45
|
+
open ? 'border-input-border-hover' : 'border-input-border hover:border-input-border-hover',
|
|
46
|
+
value === undefined && 'text-input-placeholder',
|
|
47
|
+
className
|
|
48
|
+
)}
|
|
49
|
+
>
|
|
50
|
+
<span class={cn('text-small', value !== undefined ? 'text-input-text' : 'text-input-placeholder')}
|
|
51
|
+
>{selectedLabel}</span
|
|
52
|
+
>
|
|
53
|
+
<IconExpandMore class="w-14 h-14 text-secondary shrink-0" />
|
|
54
|
+
</DropdownMenu.Trigger>
|
|
55
|
+
<DropdownMenu.Content
|
|
56
|
+
class="min-w-100 bg-dropdown-bg border border-dropdown-border rounded-10 shadow-dropdown p-4 z-12 outline-none"
|
|
57
|
+
sideOffset={2}
|
|
58
|
+
side="bottom"
|
|
59
|
+
align="start"
|
|
60
|
+
>
|
|
61
|
+
{#each items as item (item.value)}
|
|
62
|
+
<DropdownMenu.Item
|
|
63
|
+
class={cn(
|
|
64
|
+
'flex items-center justify-between gap-12 px-12 py-6 rounded-6 text-small text-dropdown-item cursor-default outline-none data-[highlighted]:bg-dropdown-item-hover',
|
|
65
|
+
value === item.value && 'text-dropdown-item-selected'
|
|
66
|
+
)}
|
|
67
|
+
onSelect={() => handleSelect(item)}
|
|
68
|
+
>
|
|
69
|
+
<span>{item.label}</span>
|
|
70
|
+
{#if value === item.value}
|
|
71
|
+
<IconCheck class="w-14 h-14 text-accent shrink-0" />
|
|
72
|
+
{/if}
|
|
73
|
+
</DropdownMenu.Item>
|
|
74
|
+
{/each}
|
|
75
|
+
</DropdownMenu.Content>
|
|
76
|
+
</DropdownMenu.Root>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type Item = {
|
|
2
|
+
label: string;
|
|
3
|
+
value: string;
|
|
4
|
+
};
|
|
5
|
+
type Props = {
|
|
6
|
+
items: Item[];
|
|
7
|
+
value?: string | undefined;
|
|
8
|
+
placeholder?: string;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
onSelect?: (value: string) => void;
|
|
11
|
+
class?: string;
|
|
12
|
+
};
|
|
13
|
+
declare const IIDropdownInput: import("svelte").Component<Props, {}, "value">;
|
|
14
|
+
type IIDropdownInput = ReturnType<typeof IIDropdownInput>;
|
|
15
|
+
export default IIDropdownInput;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IIDropdownInput } from './IIDropdownInput.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IIDropdownInput } from './IIDropdownInput.svelte';
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type {Snippet} from 'svelte'
|
|
3
|
+
import {DropdownMenu} from 'bits-ui'
|
|
4
|
+
import {cn} from '../utils/cn'
|
|
5
|
+
import {IconMoreVert} from '../icons'
|
|
6
|
+
|
|
7
|
+
type Item = {
|
|
8
|
+
label: string
|
|
9
|
+
value: string
|
|
10
|
+
icon?: Snippet
|
|
11
|
+
disabled?: boolean
|
|
12
|
+
variant?: 'default' | 'destructive'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type Props = {
|
|
16
|
+
items: Item[]
|
|
17
|
+
onSelect: (value: string) => void
|
|
18
|
+
children?: Snippet
|
|
19
|
+
side?: 'top' | 'right' | 'bottom' | 'left'
|
|
20
|
+
align?: 'start' | 'center' | 'end'
|
|
21
|
+
class?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let {items, onSelect, children, side = 'bottom', align = 'end', class: className}: Props = $props()
|
|
25
|
+
|
|
26
|
+
let open = $state(false)
|
|
27
|
+
|
|
28
|
+
function handleSelect(value: string) {
|
|
29
|
+
onSelect(value)
|
|
30
|
+
open = false
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<DropdownMenu.Root bind:open>
|
|
35
|
+
<DropdownMenu.Trigger
|
|
36
|
+
class="[all:unset] cursor-default inline-flex items-center justify-center p-4 rounded-4 text-secondary transition-all duration-fast hover:bg-background hover:text-body data-[state=open]:bg-background data-[state=open]:text-body motion-reduce:transition-none"
|
|
37
|
+
>
|
|
38
|
+
{#if children}
|
|
39
|
+
{@render children()}
|
|
40
|
+
{:else}
|
|
41
|
+
<IconMoreVert />
|
|
42
|
+
{/if}
|
|
43
|
+
</DropdownMenu.Trigger>
|
|
44
|
+
<DropdownMenu.Portal>
|
|
45
|
+
<DropdownMenu.Content
|
|
46
|
+
{side}
|
|
47
|
+
{align}
|
|
48
|
+
class={cn(
|
|
49
|
+
'min-w-48 bg-dropdown-bg border border-dropdown-border rounded-10 shadow-dropdown p-4 z-12 animate-slide-in motion-reduce:animate-none',
|
|
50
|
+
className
|
|
51
|
+
)}
|
|
52
|
+
>
|
|
53
|
+
{#each items as item (item.value)}
|
|
54
|
+
<DropdownMenu.Item
|
|
55
|
+
disabled={item.disabled}
|
|
56
|
+
class={cn(
|
|
57
|
+
'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',
|
|
58
|
+
item.variant === 'destructive'
|
|
59
|
+
? 'text-error hover:bg-error-bg data-[highlighted]:bg-error-bg data-[highlighted]:outline-none'
|
|
60
|
+
: 'text-dropdown-item hover:bg-dropdown-item-hover data-[highlighted]:bg-dropdown-item-hover data-[highlighted]:outline-none'
|
|
61
|
+
)}
|
|
62
|
+
onSelect={() => handleSelect(item.value)}
|
|
63
|
+
>
|
|
64
|
+
{#if item.icon}
|
|
65
|
+
<div class="w-11 h-11 flex items-center justify-center shrink-0">
|
|
66
|
+
{@render item.icon()}
|
|
67
|
+
</div>
|
|
68
|
+
{/if}
|
|
69
|
+
<span class="flex-1">{item.label}</span>
|
|
70
|
+
</DropdownMenu.Item>
|
|
71
|
+
{/each}
|
|
72
|
+
</DropdownMenu.Content>
|
|
73
|
+
</DropdownMenu.Portal>
|
|
74
|
+
</DropdownMenu.Root>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
type Item = {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string;
|
|
5
|
+
icon?: Snippet;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
variant?: 'default' | 'destructive';
|
|
8
|
+
};
|
|
9
|
+
type Props = {
|
|
10
|
+
items: Item[];
|
|
11
|
+
onSelect: (value: string) => void;
|
|
12
|
+
children?: Snippet;
|
|
13
|
+
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
14
|
+
align?: 'start' | 'center' | 'end';
|
|
15
|
+
class?: string;
|
|
16
|
+
};
|
|
17
|
+
declare const IIDropdownMenu: import("svelte").Component<Props, {}, "">;
|
|
18
|
+
type IIDropdownMenu = ReturnType<typeof IIDropdownMenu>;
|
|
19
|
+
export default IIDropdownMenu;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IIDropdownMenu } from './IIDropdownMenu.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IIDropdownMenu } from './IIDropdownMenu.svelte';
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {Popover} from 'bits-ui'
|
|
3
|
+
import {IconCheck} from '../icons'
|
|
4
|
+
import IIBadge from '../IIBadge/IIBadge.svelte'
|
|
5
|
+
import type {BadgeVariant} from '../IIBadge/IIBadge.types'
|
|
6
|
+
import {cn} from '../utils/cn'
|
|
7
|
+
|
|
8
|
+
type Item = {
|
|
9
|
+
value: string
|
|
10
|
+
label: string
|
|
11
|
+
description?: string
|
|
12
|
+
variant?: BadgeVariant
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type Props = {
|
|
16
|
+
items: Item[]
|
|
17
|
+
selectedValues: string[]
|
|
18
|
+
onToggle: (value: string, checked: boolean) => void
|
|
19
|
+
emptyText?: string
|
|
20
|
+
disabled?: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let {items, selectedValues, onToggle, emptyText = 'None', disabled = false}: Props = $props()
|
|
24
|
+
|
|
25
|
+
const optionVariantClasses: Record<string, string> = {
|
|
26
|
+
grey: 'bg-badge-grey border-badge-grey text-badge-grey',
|
|
27
|
+
blue: 'bg-badge-blue border-badge-blue text-badge-blue',
|
|
28
|
+
red: 'bg-badge-red border-badge-red text-badge-red',
|
|
29
|
+
purple: 'bg-badge-purple border-badge-purple text-badge-purple',
|
|
30
|
+
green: 'bg-badge-green border-badge-green text-badge-green',
|
|
31
|
+
orange: 'bg-badge-orange border-badge-orange text-badge-orange',
|
|
32
|
+
cyan: 'bg-badge-cyan border-badge-cyan text-badge-cyan',
|
|
33
|
+
pink: 'bg-badge-pink border-badge-pink text-badge-pink',
|
|
34
|
+
teal: 'bg-badge-teal border-badge-teal text-badge-teal',
|
|
35
|
+
amber: 'bg-badge-amber border-badge-amber text-badge-amber',
|
|
36
|
+
yellow: 'bg-badge-yellow border-badge-yellow text-badge-yellow',
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getVariantForItem(item: Item): BadgeVariant {
|
|
40
|
+
return item.variant ?? 'grey'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function handleItemClick(value: string) {
|
|
44
|
+
if (disabled) return
|
|
45
|
+
const isSelected = selectedValues.includes(value)
|
|
46
|
+
onToggle(value, !isSelected)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const selectedItems = $derived(items.filter(item => selectedValues.includes(item.value)))
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<Popover.Root>
|
|
53
|
+
<Popover.Trigger class="[all:unset] flex items-center gap-4 flex-wrap cursor-default">
|
|
54
|
+
{#if selectedItems.length === 0}
|
|
55
|
+
<IIBadge variant="grey">{emptyText}</IIBadge>
|
|
56
|
+
{:else}
|
|
57
|
+
{#each selectedItems as item (item.value)}
|
|
58
|
+
<IIBadge variant={getVariantForItem(item)}>{item.label}</IIBadge>
|
|
59
|
+
{/each}
|
|
60
|
+
{/if}
|
|
61
|
+
</Popover.Trigger>
|
|
62
|
+
<Popover.Portal>
|
|
63
|
+
<Popover.Content
|
|
64
|
+
class="bg-surface border border-primary rounded-10 shadow-dropdown p-8 z-12 min-w-200 max-w-300"
|
|
65
|
+
side="bottom"
|
|
66
|
+
align="start"
|
|
67
|
+
>
|
|
68
|
+
<div class="flex flex-col gap-4">
|
|
69
|
+
{#each items as item (item.value)}
|
|
70
|
+
{@const isSelected = selectedValues.includes(item.value)}
|
|
71
|
+
{@const variant = getVariantForItem(item)}
|
|
72
|
+
<button
|
|
73
|
+
type="button"
|
|
74
|
+
class={cn(
|
|
75
|
+
'[all:unset] flex items-center justify-between px-12 py-8 border rounded-4 bg-background cursor-default transition-all duration-fast text-small text-body hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed',
|
|
76
|
+
isSelected && 'border-2',
|
|
77
|
+
optionVariantClasses[variant]
|
|
78
|
+
)}
|
|
79
|
+
onclick={() => handleItemClick(item.value)}
|
|
80
|
+
{disabled}
|
|
81
|
+
>
|
|
82
|
+
<span class="flex-1 text-left">{item.label}</span>
|
|
83
|
+
{#if isSelected}
|
|
84
|
+
<IconCheck class="w-11 h-11 text-accent ml-8 shrink-0" />
|
|
85
|
+
{/if}
|
|
86
|
+
</button>
|
|
87
|
+
{/each}
|
|
88
|
+
</div>
|
|
89
|
+
</Popover.Content>
|
|
90
|
+
</Popover.Portal>
|
|
91
|
+
</Popover.Root>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { BadgeVariant } from '../IIBadge/IIBadge.types';
|
|
2
|
+
type Item = {
|
|
3
|
+
value: string;
|
|
4
|
+
label: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
variant?: BadgeVariant;
|
|
7
|
+
};
|
|
8
|
+
type Props = {
|
|
9
|
+
items: Item[];
|
|
10
|
+
selectedValues: string[];
|
|
11
|
+
onToggle: (value: string, checked: boolean) => void;
|
|
12
|
+
emptyText?: string;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
};
|
|
15
|
+
declare const IIEditableBadges: import("svelte").Component<Props, {}, "">;
|
|
16
|
+
type IIEditableBadges = ReturnType<typeof IIEditableBadges>;
|
|
17
|
+
export default IIEditableBadges;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IIEditableBadges } from './IIEditableBadges.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as IIEditableBadges } from './IIEditableBadges.svelte';
|