@invopop/popui 0.1.14 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/BaseButton.svelte +25 -103
  2. package/dist/BaseCard.svelte +35 -30
  3. package/dist/BaseCounter.svelte +11 -8
  4. package/dist/BaseTable.svelte +6 -8
  5. package/dist/BaseTableActions.svelte +2 -2
  6. package/dist/BaseTableCellContent.svelte +2 -2
  7. package/dist/BaseTableHeaderContent.svelte +2 -2
  8. package/dist/Breadcrumb.svelte +40 -0
  9. package/dist/Breadcrumb.svelte.d.ts +4 -0
  10. package/dist/Breadcrumbs.svelte +5 -30
  11. package/dist/ButtonFile.svelte +35 -30
  12. package/dist/ButtonUuidCopy.svelte +2 -2
  13. package/dist/CardCheckbox.svelte +25 -21
  14. package/dist/CardRelation.svelte +12 -16
  15. package/dist/CompanySelector.svelte +35 -7
  16. package/dist/DataListItem.svelte +14 -10
  17. package/dist/DatePicker.svelte +9 -9
  18. package/dist/DrawerContext.svelte +112 -10
  19. package/dist/DrawerContextItem.svelte +19 -29
  20. package/dist/DrawerContextSeparator.svelte +1 -1
  21. package/dist/DrawerContextWorkspace.svelte +7 -7
  22. package/dist/DropdownSelect.svelte +40 -14
  23. package/dist/EmptyState.svelte +40 -0
  24. package/dist/EmptyState.svelte.d.ts +4 -0
  25. package/dist/EmptyStateIllustration.svelte.d.ts +0 -1
  26. package/dist/FeedEvents.svelte +9 -5
  27. package/dist/FeedIconEvent.svelte +1 -1
  28. package/dist/FeedItem.svelte +8 -8
  29. package/dist/FeedItemDetail.svelte +7 -5
  30. package/dist/GlobalSearch.svelte +13 -12
  31. package/dist/InputCheckbox.svelte +2 -5
  32. package/dist/InputError.svelte +4 -9
  33. package/dist/InputLabel.svelte +3 -1
  34. package/dist/InputRadio.svelte +26 -11
  35. package/dist/InputSearch.svelte +8 -8
  36. package/dist/InputSelect.svelte +32 -31
  37. package/dist/InputText.svelte +32 -24
  38. package/dist/InputTextarea.svelte +25 -19
  39. package/dist/InputToggle.svelte +24 -18
  40. package/dist/Notification.svelte +55 -24
  41. package/dist/ProfileAvatar.svelte +41 -14
  42. package/dist/SeparatorHorizontal.svelte +2 -2
  43. package/dist/ShortcutWrapper.svelte +14 -5
  44. package/dist/StatusLabel.svelte +4 -5
  45. package/dist/StepIconList.svelte +7 -9
  46. package/dist/TagBeta.svelte +26 -14
  47. package/dist/TagStatus.svelte +33 -48
  48. package/dist/TitleMain.svelte +1 -1
  49. package/dist/TitleSection.svelte +1 -1
  50. package/dist/UuidCopy.svelte +4 -4
  51. package/dist/alert-dialog/alert-dialog-action.svelte +5 -3
  52. package/dist/alert-dialog/alert-dialog-cancel.svelte +4 -2
  53. package/dist/alert-dialog/alert-dialog-content.svelte +1 -1
  54. package/dist/alert-dialog/alert-dialog-description.svelte +1 -1
  55. package/dist/alert-dialog/alert-dialog-footer.svelte +1 -1
  56. package/dist/alert-dialog/alert-dialog-header.svelte +1 -1
  57. package/dist/alert-dialog/alert-dialog-title.svelte +1 -1
  58. package/dist/button/button.svelte +183 -24
  59. package/dist/button/button.svelte.d.ts +48 -26
  60. package/dist/index.d.ts +2 -7
  61. package/dist/index.js +2 -12
  62. package/dist/range-calendar/range-calendar-cell.svelte +1 -1
  63. package/dist/range-calendar/range-calendar-day.svelte +10 -8
  64. package/dist/range-calendar/range-calendar-head-cell.svelte +1 -1
  65. package/dist/range-calendar/range-calendar-next-button.svelte +3 -3
  66. package/dist/range-calendar/range-calendar-prev-button.svelte +3 -3
  67. package/dist/range-calendar/range-calendar.svelte +1 -1
  68. package/dist/svg/CheckBadge.svelte +18 -0
  69. package/dist/svg/CheckBadge.svelte.d.ts +26 -0
  70. package/dist/svg/IconEmpty.svelte +78 -106
  71. package/dist/table/table-body.svelte +1 -1
  72. package/dist/table/table-cell.svelte +1 -1
  73. package/dist/table/table-footer.svelte +1 -1
  74. package/dist/table/table-head.svelte +1 -1
  75. package/dist/table/table-header.svelte +1 -1
  76. package/dist/table/table-row.svelte +1 -1
  77. package/dist/tabs/tabs-list.svelte +1 -1
  78. package/dist/tailwind.theme.css +969 -0
  79. package/dist/tooltip/tooltip-content.svelte +2 -2
  80. package/dist/types.d.ts +36 -42
  81. package/package.json +2 -2
  82. package/dist/CounterWorkflow.svelte +0 -19
  83. package/dist/CounterWorkflow.svelte.d.ts +0 -4
  84. package/dist/EmptyStateIcon.svelte +0 -52
  85. package/dist/EmptyStateIcon.svelte.d.ts +0 -4
  86. package/dist/FormLayoutModal.svelte +0 -14
  87. package/dist/FormLayoutModal.svelte.d.ts +0 -4
  88. package/dist/ProfileSelector.svelte +0 -41
  89. package/dist/ProfileSelector.svelte.d.ts +0 -4
  90. package/dist/SectionLayout.svelte +0 -13
  91. package/dist/SectionLayout.svelte.d.ts +0 -4
  92. package/dist/tw.theme.d.ts +0 -171
  93. package/dist/tw.theme.js +0 -188
@@ -2,31 +2,27 @@
2
2
  import { Icon } from '@steeze-ui/svelte-icon'
3
3
  import type { CardRelationProps } from './types.js'
4
4
  import { ChevronRight } from '@invopop/ui-icons'
5
- import SeparatorHorizontal from './SeparatorHorizontal.svelte'
6
5
 
7
6
  let { title = '', icon = undefined, items = [], onclick }: CardRelationProps = $props()
8
7
  </script>
9
8
 
10
- <div class="border border-neutral-100 rounded-lg">
11
- <button
12
- class="cursor-pointer pl-3 py-2 pr-2 flex items-center justify-between space-x-3 w-full"
13
- {onclick}
14
- >
15
- <div class="flex items-center space-x-1.5">
9
+ <div class="border border-border-default-secondary rounded-2xl overflow-hidden">
10
+ <button class="flex items-center gap-3 px-3 py-2 w-full cursor-pointer" {onclick}>
11
+ <div class="flex grow items-center gap-1.5 min-w-0">
16
12
  {#if icon}
17
- <Icon src={icon} class="h-4 w-4 text-neutral-500" />
13
+ <Icon src={icon} class="size-4 text-foreground shrink-0" />
18
14
  {/if}
19
- <span class="text-base font-medium text-neutral-800">{title}</span>
15
+ <span class="text-base font-medium text-foreground whitespace-nowrap">
16
+ {title}
17
+ </span>
20
18
  </div>
21
-
22
- <Icon src={ChevronRight} class="h-4 w-4 text-neutral-500" />
19
+ <Icon src={ChevronRight} class="size-3 text-foreground shrink-0" />
23
20
  </button>
24
- <SeparatorHorizontal />
25
- <div class="py-1.5 text-sm">
21
+ <div class="flex flex-col gap-2 px-3 pb-3 pt-2">
26
22
  {#each items as item}
27
- <div class="px-3 py-1 flex items-center space-x-3">
28
- <div class="min-w-[88px] text-neutral-500">{item.label}</div>
29
- <div class="text-neutral-800">{item.value}</div>
23
+ <div class="flex items-center gap-3 text-sm">
24
+ <div class="min-w-[88px] text-foreground-default-secondary shrink-0">{item.label}</div>
25
+ <div class="grow text-foreground min-w-0">{item.value}</div>
30
26
  </div>
31
27
  {/each}
32
28
  </div>
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">
2
2
  import ProfileAvatar from './ProfileAvatar.svelte'
3
- import type { AnyProp, CompanySelectorProps, DrawerOption } from './types.js'
3
+ import type { AnyProp, CompanySelectorProps, DrawerOption, DrawerGroup } from './types.js'
4
4
  import BaseDropdown from './BaseDropdown.svelte'
5
- import DrawerContextWorkspace from './DrawerContextWorkspace.svelte'
6
- import { DoubleArrow } from '@invopop/ui-icons'
5
+ import DrawerContext from './DrawerContext.svelte'
6
+ import { DoubleArrow, Workspace, AddCircle, ExternalLink } from '@invopop/ui-icons'
7
7
  import MenuItemCollapsible from './MenuItemCollapsible.svelte'
8
8
 
9
9
  let companyDropdown: BaseDropdown | undefined = $state()
@@ -21,6 +21,24 @@
21
21
  let country = $derived(selectedCompany?.country || '')
22
22
  let picture = $derived(selectedCompany?.logo_url || '')
23
23
  let isSandbox = $derived(selectedCompany?.sandbox)
24
+
25
+ let groups: DrawerGroup[] = [
26
+ {
27
+ label: 'Live',
28
+ slug: 'live',
29
+ emptyIcon: Workspace,
30
+ emptyTitle: 'No workspaces here',
31
+ emptyDescription: 'Create a workspace to start'
32
+ },
33
+ {
34
+ label: 'Sandbox',
35
+ slug: 'sandbox',
36
+ emptyIcon: Workspace,
37
+ emptyTitle: 'No workspaces here',
38
+ emptyDescription: 'Create a workspace to start'
39
+ }
40
+ ]
41
+
24
42
  let items = $derived([
25
43
  ...companies.map((c) => ({
26
44
  value: c.id,
@@ -28,8 +46,18 @@
28
46
  selected: c.slug === selectedCompany?.slug && !!c.sandbox === !!selectedCompany?.sandbox,
29
47
  country: c.country,
30
48
  picture: c.logo_url,
31
- sandbox: c.sandbox
32
- }))
49
+ sandbox: c.sandbox,
50
+ groupBy: c.sandbox ? 'sandbox' : 'live'
51
+ })),
52
+ {
53
+ separator: true
54
+ },
55
+ {
56
+ value: 'add',
57
+ label: 'Create workspace',
58
+ icon: AddCircle,
59
+ rightIcon: ExternalLink
60
+ }
33
61
  ] as DrawerOption[])
34
62
 
35
63
  function selectCompany(value: AnyProp) {
@@ -60,8 +88,8 @@
60
88
  active={isOpen}
61
89
  bold
62
90
  >
63
- <ProfileAvatar {name} {picture} {country} dark large />
91
+ <ProfileAvatar {name} {picture} {country} dark variant="lg" />
64
92
  </MenuItemCollapsible>
65
93
  {/snippet}
66
- <DrawerContextWorkspace {items} onclick={selectCompany} />
94
+ <DrawerContext {items} {groups} onclick={selectCompany} widthClass="w-[300px]" />
67
95
  </BaseDropdown>
@@ -11,8 +11,8 @@
11
11
  children
12
12
  }: DataListItemProps = $props()
13
13
 
14
- let styles = $derived(
15
- clsx({
14
+ let valueStyles = $derived(
15
+ clsx('text-foreground font-medium text-base', {
16
16
  'font-mono': monospaced,
17
17
  'slashed-zero tabular-nums lining-nums': monospacedNums,
18
18
  'w-full': fullWidth
@@ -20,13 +20,17 @@
20
20
  )
21
21
  </script>
22
22
 
23
- <div class="flex space-x-4 text-base items-center">
24
- <div class="text-neutral-500 min-w-[125px]">{label}</div>
25
- <div class="{styles} text-neutral-800 font-medium">
26
- {#if children}
27
- {@render children()}
28
- {:else}
29
- {value}
30
- {/if}
23
+ <div class="flex gap-6 items-center px-3 py-1.5 rounded-lg hover:bg-background-default-secondary">
24
+ <div class="text-foreground-default-secondary text-base min-w-[125px]">
25
+ {label}
26
+ </div>
27
+ <div class="flex gap-1 items-center">
28
+ <div class={valueStyles}>
29
+ {#if children}
30
+ {@render children()}
31
+ {:else}
32
+ {value}
33
+ {/if}
34
+ </div>
31
35
  </div>
32
36
  </div>
@@ -123,8 +123,8 @@
123
123
  let isOpen = $state(false)
124
124
  let styles = $derived(
125
125
  clsx({
126
- 'border-workspace-accent focus:border-workspace-accent shadow-active': isOpen,
127
- 'border-neutral-200 hover:border-neutral-300': !isOpen
126
+ 'border-border-selected-bold shadow-active': isOpen,
127
+ 'border-border hover:border-border-default-secondary-hover': !isOpen
128
128
  })
129
129
  )
130
130
  let selectedLabel = $state(label)
@@ -188,11 +188,11 @@
188
188
  onclick={() => {
189
189
  isOpen = !isOpen
190
190
  }}
191
- class="{styles} datepicker-trigger w-full py-1.25 pl-7 pr-8 border rounded-md text-neutral-800 placeholder-neutral-800 text-base cursor-pointer"
191
+ class="{styles} datepicker-trigger w-full py-1.25 pl-7 pr-8 border rounded-md text-foreground placeholder-foreground text-base cursor-pointer"
192
192
  >
193
193
  {selectedLabel}
194
194
  </button>
195
- <Icon src={Calendar} class="h-4 w-4 absolute top-2 left-2 text-neutral-500" />
195
+ <Icon src={Calendar} class="h-4 w-4 absolute top-2 left-2 text-foreground-default-secondary" />
196
196
  </div>
197
197
 
198
198
  <div class="relative">
@@ -209,21 +209,21 @@
209
209
  <div
210
210
  class:left-0={position === 'left'}
211
211
  class:right-0={position === 'right'}
212
- class="bg-white inline-flex flex-col shadow rounded-lg absolute right-0 top-2 z-40"
212
+ class="bg-white inline-flex flex-col shadow-md rounded-lg absolute right-0 top-2 z-40"
213
213
  use:clickOutside
214
214
  onclick_outside={() => {
215
215
  if (!isOpen) return
216
216
  cancel()
217
217
  }}
218
218
  >
219
- <div class="flex border-b border-neutral-100 min-h-[300px] rounded-lg shadow-calendar">
220
- <div class="flex flex-col space-y-2 items-start p-3 border-r border-neutral-100">
219
+ <div class="flex border-b border-border min-h-[300px] rounded-lg shadow-calendar">
220
+ <div class="flex flex-col space-y-2 items-start p-3 border-r border-border">
221
221
  {#each periods as period}
222
222
  <button
223
223
  onclick={period.action}
224
224
  class="{selectedPeriod === period.slug
225
- ? 'selected-period text-workspace-accent-600 bg-workspace-accent-100'
226
- : 'text-neutral-500'} whitespace-nowrap text-base px-2 py-1 tracking-normal rounded cursor-pointer"
225
+ ? 'selected-period text-foreground-accent bg-foreground-accent/10'
226
+ : 'text-foreground-default-secondary'} whitespace-nowrap text-base px-2 py-1 tracking-normal rounded cursor-pointer"
227
227
  >
228
228
  {period.label}
229
229
  </button>
@@ -2,6 +2,11 @@
2
2
  import type { DrawerContextProps, DrawerOption } from './types.ts'
3
3
  import DrawerContextItem from './DrawerContextItem.svelte'
4
4
  import DrawerContextSeparator from './DrawerContextSeparator.svelte'
5
+ import EmptyState from './EmptyState.svelte'
6
+ import BaseCounter from './BaseCounter.svelte'
7
+ import { Icon } from '@steeze-ui/svelte-icon'
8
+ import { ChevronRight } from '@steeze-ui/heroicons'
9
+ import { slide } from 'svelte/transition'
5
10
 
6
11
  let {
7
12
  items = $bindable([]),
@@ -9,10 +14,44 @@
9
14
  widthClass = 'w-60',
10
15
  onclick,
11
16
  onselect,
12
- children
17
+ children,
18
+ groups
13
19
  }: DrawerContextProps = $props()
14
20
 
15
21
  let selectedItems = $derived(items.filter((i) => i.selected))
22
+ let hasGroups = $derived(groups && groups.length > 0)
23
+ let { groupedItems, ungroupedItems } = $derived.by(() => {
24
+ if (!hasGroups) return { groupedItems: new Map(), ungroupedItems: items }
25
+
26
+ const grouped = new Map<string, DrawerOption[]>()
27
+ const ungrouped: DrawerOption[] = []
28
+
29
+ groups!.forEach((group) => {
30
+ grouped.set(group.slug, [])
31
+ })
32
+
33
+ items.forEach((item) => {
34
+ if (item.groupBy && grouped.has(item.groupBy)) {
35
+ grouped.get(item.groupBy)!.push(item)
36
+ } else {
37
+ ungrouped.push(item)
38
+ }
39
+ })
40
+
41
+ return { groupedItems: grouped, ungroupedItems: ungrouped }
42
+ })
43
+
44
+ let openGroups = $state<Record<string, boolean>>({})
45
+
46
+ $effect(() => {
47
+ if (hasGroups) {
48
+ const selectedItem = items.find((i) => i.selected)
49
+ if (selectedItem?.groupBy && Object.keys(openGroups).length === 0) {
50
+ openGroups = { [selectedItem.groupBy]: true }
51
+ }
52
+ }
53
+ })
54
+
16
55
  $effect(() => {
17
56
  onselect?.(selectedItems)
18
57
  })
@@ -23,19 +62,82 @@
23
62
  return i
24
63
  })
25
64
  }
65
+
66
+ function toggleGroup(groupSlug: string) {
67
+ openGroups = openGroups[groupSlug] ? {} : { [groupSlug]: true }
68
+ }
26
69
  </script>
27
70
 
28
71
  <div
29
- class="{widthClass} border border-neutral-200 py-0.5 rounded-2xl shadow-lg space-y-0.5 bg-white max-h-80 overflow-y-auto"
72
+ class="{widthClass} border border-border rounded-2xl shadow-lg bg-white overflow-hidden flex flex-col"
30
73
  >
31
74
  {@render children?.()}
32
- <ul class="space-y-0.5 max-h-80 overflow-y-auto">
33
- {#each items as item}
34
- {#if item.separator}
35
- <DrawerContextSeparator />
36
- {:else}
37
- <DrawerContextItem {item} {multiple} {onclick} onchange={updateItem} />
38
- {/if}
75
+
76
+ {#if hasGroups}
77
+ {#each groups as group, index}
78
+ {@const groupItems = groupedItems.get(group.slug) || []}
79
+ {@const isLastGroup = index === groups!.length - 1}
80
+ <div class="flex-shrink-0 {!isLastGroup ? 'border-b border-border' : ''}">
81
+ <button
82
+ class="cursor-pointer flex items-center justify-between h-9 pl-3 pr-2.5 py-2.5 text-sm font-medium text-foreground-default-secondary w-full hover:bg-background-default-secondary rounded-lg overflow-clip"
83
+ onclick={() => toggleGroup(group.slug)}
84
+ >
85
+ <div class="flex items-center gap-1.5">
86
+ <span>{group.label}</span>
87
+ <Icon
88
+ src={ChevronRight}
89
+ class="size-3 text-icon-default-secondary transition-all transform {openGroups[
90
+ group.slug
91
+ ]
92
+ ? 'rotate-90'
93
+ : ''}"
94
+ />
95
+ </div>
96
+ {#if groupItems.length}
97
+ <BaseCounter value={groupItems.length} />
98
+ {/if}
99
+ </button>
100
+
101
+ {#if openGroups[group.slug]}
102
+ <div transition:slide class="w-full">
103
+ {#if !groupItems.length}
104
+ <div class="px-1 pt-1 pb-5">
105
+ <EmptyState
106
+ iconSource={group.emptyIcon}
107
+ title={group.emptyTitle || 'No items here'}
108
+ description={group.emptyDescription || 'Add items to get started'}
109
+ />
110
+ </div>
111
+ {:else}
112
+ <div class="max-h-[400px] overflow-y-auto">
113
+ {#each groupItems as item}
114
+ {#if item.separator}
115
+ <DrawerContextSeparator />
116
+ {:else}
117
+ <div class="px-1">
118
+ <DrawerContextItem {item} {multiple} {onclick} onchange={updateItem} />
119
+ </div>
120
+ {/if}
121
+ {/each}
122
+ </div>
123
+ {/if}
124
+ </div>
125
+ {/if}
126
+ </div>
39
127
  {/each}
40
- </ul>
128
+ {/if}
129
+
130
+ {#if ungroupedItems.length}
131
+ <div class="flex-shrink-0 max-h-[400px] overflow-y-auto">
132
+ {#each ungroupedItems as item}
133
+ {#if item.separator}
134
+ <DrawerContextSeparator />
135
+ {:else}
136
+ <div class="px-1">
137
+ <DrawerContextItem {item} {multiple} {onclick} onchange={updateItem} />
138
+ </div>
139
+ {/if}
140
+ {/each}
141
+ </div>
142
+ {/if}
41
143
  </div>
@@ -3,8 +3,7 @@
3
3
  import InputCheckbox from './InputCheckbox.svelte'
4
4
  import { Icon } from '@steeze-ui/svelte-icon'
5
5
  import { onMount } from 'svelte'
6
- import { Success, Tick } from '@invopop/ui-icons'
7
- import ProfileAvatar from './ProfileAvatar.svelte'
6
+ import { Success } from '@invopop/ui-icons'
8
7
  import clsx from 'clsx'
9
8
  import BaseFlag from './BaseFlag.svelte'
10
9
  import { getCountryName } from './helpers.js'
@@ -14,32 +13,26 @@
14
13
  multiple = false,
15
14
  item = $bindable(),
16
15
  scrollIfSelected = false,
17
- workspace = false,
18
16
  onchange,
19
17
  onclick
20
18
  }: DrawerContextItemProps = $props()
21
19
 
22
20
  let el: HTMLElement | undefined = $state()
23
21
 
24
- let hasIcon = $derived(item.icon || workspace)
25
-
26
22
  let styles = $derived(
27
23
  clsx(
28
- { 'py-1 space-x-3': workspace },
29
- { 'py-1.5 space-x-1.5': !workspace },
30
- { 'pl-1.5': !hasIcon },
31
- { 'pl-2': hasIcon },
32
- { 'bg-workspace-accent-100': item.selected && !multiple },
33
- { 'group-hover:bg-neutral-100': (!item.selected && !item.disabled) || multiple }
24
+ 'py-1.5 space-x-1.5',
25
+ { 'pl-1.5': !item.icon },
26
+ { 'pl-2': item.icon },
27
+ { 'bg-background-selected': item.selected && !multiple },
28
+ {
29
+ 'group-hover:bg-background-default-secondary':
30
+ (!item.selected && !item.disabled) || multiple
31
+ }
34
32
  )
35
33
  )
36
34
  let labelStyles = $derived(
37
- clsx(
38
- { 'text-danger-500': item.destructive },
39
- { 'text-neutral-800': !item.destructive },
40
- { 'tracking-tight max-w-[200px]': workspace },
41
- { 'tracking-normal': !workspace }
42
- )
35
+ clsx({ 'text-danger-500': item.destructive }, { 'text-neutral-800': !item.destructive })
43
36
  )
44
37
  let title = $derived(item.label.length > 25 ? item.label : undefined)
45
38
 
@@ -64,19 +57,15 @@
64
57
 
65
58
  <button
66
59
  bind:this={el}
67
- class="cursor-pointer w-full px-1 py-0.5 disabled:opacity-30 group"
60
+ class="cursor-pointer w-full py-0.5 disabled:opacity-30 group"
68
61
  disabled={item.disabled}
69
62
  onclick={handleClick}
70
63
  >
71
64
  <div class="{styles} rounded pr-2 flex items-center justify-start w-full">
72
- {#if workspace}
73
- <ProfileAvatar name={item.label} picture={item.picture} large />
74
- {:else if item.icon}
65
+ {#if item.icon}
75
66
  <Icon
76
67
  src={item.icon}
77
- class="w-4 h-4 {item.destructive
78
- ? 'text-danger-500'
79
- : item.iconClass || 'text-neutral-500'}"
68
+ class="w-4 h-4 {item.destructive ? 'text-icon-critical' : item.iconClass || 'text-icon'}"
80
69
  />
81
70
  {/if}
82
71
  <div class="whitespace-nowrap flex-1 text-left flex flex-col truncate" {title}>
@@ -90,7 +79,7 @@
90
79
  {#if item.country}
91
80
  <span class="flex space-x-1 items-center">
92
81
  <BaseFlag country={item.country} width={10} />
93
- <span class="text-sm text-neutral-500 tracking-normal">
82
+ <span class="text-sm text-foreground-default-secondary">
94
83
  {getCountryName(item.country)}
95
84
  </span>
96
85
  </span>
@@ -98,15 +87,16 @@
98
87
  </div>
99
88
  {#if multiple}
100
89
  <InputCheckbox
101
- bind:checked={item.selected}
102
- onchange={() => {
90
+ checked={item.selected ?? false}
91
+ onchange={(value) => {
92
+ item.selected = value
103
93
  onchange?.(item)
104
94
  }}
105
95
  />
106
96
  {:else if item.selected}
107
- <Icon src={Success} class="w-4 h-4 text-workspace-accent" />
97
+ <Icon src={Success} class="size-4 text-icon-selected" />
108
98
  {:else if item.rightIcon}
109
- <Icon src={item.rightIcon} class="w-4 h-4 text-neutral-400" />
99
+ <Icon src={item.rightIcon} class="size-4 text-icon-default-secondary" />
110
100
  {/if}
111
101
  </div>
112
102
  </button>
@@ -1 +1 @@
1
- <li class="bg-neutral-100 h-px w-full"></li>
1
+ <li class="bg-border h-px w-full"></li>
@@ -4,7 +4,7 @@
4
4
  import { Icon } from '@steeze-ui/svelte-icon'
5
5
  import { AddCircle, ExternalLink, Workspace } from '@invopop/ui-icons'
6
6
  import BaseCounter from './BaseCounter.svelte'
7
- import EmptyStateIcon from './EmptyStateIcon.svelte'
7
+ import EmptyState from './EmptyState.svelte'
8
8
  import { slide } from 'svelte/transition'
9
9
  import { ChevronRight } from '@steeze-ui/heroicons'
10
10
 
@@ -44,15 +44,15 @@
44
44
  <span>Live</span>
45
45
  </div>
46
46
  {#if liveItems.length}
47
- <BaseCounter content={liveItems.length} />
47
+ <BaseCounter value={liveItems.length} />
48
48
  {/if}
49
49
  </button>
50
50
  {#if liveOpen}
51
51
  <div transition:slide class="max-h-[475px] overflow-auto">
52
52
  {#if !liveItems.length}
53
53
  <div class="h-[182px] overflow-x-hidden">
54
- <EmptyStateIcon
55
- icon={Workspace}
54
+ <EmptyState
55
+ iconSource={Workspace}
56
56
  title="No workspaces here"
57
57
  description="Create a workspace to start"
58
58
  />
@@ -82,15 +82,15 @@
82
82
  <span>Sandbox</span>
83
83
  </div>
84
84
  {#if sandboxItems.length}
85
- <BaseCounter content={sandboxItems.length} />
85
+ <BaseCounter value={sandboxItems.length} />
86
86
  {/if}
87
87
  </button>
88
88
  {#if sandboxOpen}
89
89
  <div transition:slide class="max-h-[475px] overflow-auto">
90
90
  {#if !sandboxItems.length}
91
91
  <div class="h-[182px] overflow-x-hidden">
92
- <EmptyStateIcon
93
- icon={Workspace}
92
+ <EmptyState
93
+ iconSource={Workspace}
94
94
  title="No workspaces here"
95
95
  description="Create a workspace to start"
96
96
  />
@@ -49,9 +49,9 @@
49
49
  )
50
50
 
51
51
  let styles = $derived(
52
- clsx({
53
- 'shadow-active border-workspace-accent hover:border-workspace-accent': isOpen,
54
- 'border-neutral-100': !isOpen
52
+ clsx('border backdrop-blur-sm backdrop-filter', {
53
+ 'border-border-selected-bold shadow-active': isOpen,
54
+ 'border-border hover:border-border-default-secondary-hover': !isOpen
55
55
  })
56
56
  )
57
57
 
@@ -78,19 +78,45 @@
78
78
  <BaseDropdown bind:isOpen placement="bottom-start" {fullWidth} bind:this={selectDropdown}>
79
79
  {#snippet trigger()}
80
80
  <div
81
- class="{styles} dropdown-select max-w-[420px] flex items-center border hover:border-neutral-300 rounded-md py-1.25 pl-2 gap-1 bg-white whitespace-nowrap"
81
+ class="{styles} dropdown-select flex items-center rounded-lg py-1.5 px-2 bg-background whitespace-nowrap {fullWidth
82
+ ? 'w-full'
83
+ : widthClass}"
82
84
  >
83
85
  {#if selectedColor}
84
- <TagStatus dot status={selectedColor} />
85
- {:else if selectedIcon}
86
- <Icon src={selectedIcon} {iconTheme} class="{selectedIconColor} h-4 w-4 flex-shrink-0" />
87
- {:else if resolvedIcon}
88
- <Icon src={resolvedIcon} {iconTheme} class="h-4 w-4 text-neutral-500 flex-shrink-0" />
86
+ <div class="flex items-center gap-1 flex-1 min-w-0">
87
+ <TagStatus dot status={selectedColor} />
88
+ <span
89
+ class="flex-1 text-sm truncate {selectedItems.length
90
+ ? 'text-foreground'
91
+ : 'text-foreground-default-secondary'}"
92
+ >
93
+ {selectedLabel}
94
+ </span>
95
+ </div>
96
+ {:else if selectedIcon || resolvedIcon}
97
+ <div class="flex items-center gap-1 flex-1 min-w-0">
98
+ {#if selectedIcon}
99
+ <Icon src={selectedIcon} {iconTheme} class="{selectedIconColor} size-4 flex-shrink-0" />
100
+ {:else if resolvedIcon}
101
+ <Icon src={resolvedIcon} {iconTheme} class="text-icon size-4 flex-shrink-0" />
102
+ {/if}
103
+ <span
104
+ class="flex-1 text-sm truncate {selectedItems.length
105
+ ? 'text-foreground'
106
+ : 'text-foreground-default-secondary'}"
107
+ >
108
+ {selectedLabel}
109
+ </span>
110
+ </div>
111
+ {:else}
112
+ <span
113
+ class="flex-1 text-sm truncate {selectedItems.length
114
+ ? 'text-foreground'
115
+ : 'text-foreground-default-secondary'}"
116
+ >
117
+ {selectedLabel}
118
+ </span>
89
119
  {/if}
90
-
91
- <span class="w-full pr-8 text-neutral-800 placeholder-neutral-800 text-base truncate">
92
- {selectedLabel}
93
- </span>
94
120
  </div>
95
121
  {/snippet}
96
122
  <DrawerContext {widthClass} {multiple} {items} onclick={handleClick} onselect={handleSelected} />
@@ -98,7 +124,7 @@
98
124
 
99
125
  <style>
100
126
  .dropdown-select {
101
- background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiByeD0iNCIgZmlsbD0iI0YzRjRGNiIvPgo8cGF0aCBkPSJNNi41IDguMjUwMDRMMTAgMTEuNzVMMTMuNSA4LjI1IiBzdHJva2U9IiMwMzA3MTIiIHN0cm9rZS13aWR0aD0iMS4xIi8+Cjwvc3ZnPg==');
127
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiByeD0iNCIgZmlsbD0icmdiYSg1LCA1LCAzNiwgMC4wNikiLz4KPHBhdGggZD0iTTQuNSA2LjVMOCAxMEwxMS41IDYuNSIgc3Ryb2tlPSIjMGIwYjEwIiBzdHJva2Utd2lkdGg9IjEuMSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjwvc3ZnPg==');
102
128
  background-repeat: no-repeat;
103
129
  background-position: center right 8px;
104
130
  }
@@ -0,0 +1,40 @@
1
+ <script lang="ts">
2
+ import IconEmpty from './svg/IconEmpty.svelte'
3
+ import CheckBadge from './svg/CheckBadge.svelte'
4
+ import { Icon } from '@steeze-ui/svelte-icon'
5
+ import type { EmptyStateProps } from './types'
6
+
7
+ let {
8
+ icon,
9
+ iconSource,
10
+ title = '',
11
+ description = '',
12
+ check = false,
13
+ children
14
+ }: EmptyStateProps = $props()
15
+ </script>
16
+
17
+ <div class="flex flex-col items-center justify-center gap-4">
18
+ {#if icon}
19
+ <div class="relative h-[120px] w-[352px] max-w-sm flex items-center justify-center">
20
+ {@render icon()}
21
+ </div>
22
+ {:else if iconSource}
23
+ <div class="relative h-[120px] w-[352px] max-w-sm">
24
+ <IconEmpty />
25
+ <div class="absolute left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2">
26
+ <Icon src={iconSource} class="h-12 w-12 text-foreground-accent" />
27
+ {#if check}
28
+ <CheckBadge />
29
+ {/if}
30
+ </div>
31
+ </div>
32
+ {/if}
33
+ <div class="flex flex-col items-center gap-0.5 text-center">
34
+ <h4 class="font-medium text-foreground text-base">{title}</h4>
35
+ <p class="text-foreground-default-secondary text-base">{description}</p>
36
+ </div>
37
+ {#if children}
38
+ {@render children()}
39
+ {/if}
40
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { EmptyStateProps } from './types';
2
+ declare const EmptyState: import("svelte").Component<EmptyStateProps, {}, "">;
3
+ type EmptyState = ReturnType<typeof EmptyState>;
4
+ export default EmptyState;
@@ -1,4 +1,3 @@
1
- import type { EmptyStateIllustrationProps } from './types.js';
2
1
  declare const EmptyStateIllustration: import("svelte").Component<EmptyStateIllustrationProps, {}, "">;
3
2
  type EmptyStateIllustration = ReturnType<typeof EmptyStateIllustration>;
4
3
  export default EmptyStateIllustration;