@casinogate/ui 1.7.0 → 1.8.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.
Files changed (119) hide show
  1. package/dist/assets/css/root.css +43 -4
  2. package/dist/components/breadcrumb/breadcrumb.svelte +2 -2
  3. package/dist/components/breadcrumb/types.d.ts +2 -2
  4. package/dist/components/button/styles.d.ts +15 -0
  5. package/dist/components/button/styles.js +9 -4
  6. package/dist/components/button-group/components/button-group.root.svelte +1 -3
  7. package/dist/components/collapsible/components/collapsaible.svelte.js +3 -3
  8. package/dist/components/data-table/data-table.svelte +1 -1
  9. package/dist/components/data-table/utils/pagination-state.svelte.js +3 -3
  10. package/dist/components/data-table/utils/resize-state.svelte.js +3 -3
  11. package/dist/components/data-table/utils/row-selection-state.svelte.js +3 -3
  12. package/dist/components/dialog/components/dialog.overlay.svelte +1 -7
  13. package/dist/components/dropdown/components/dropdown.content.svelte +0 -2
  14. package/dist/components/dropdown/dropdown.svelte +127 -67
  15. package/dist/components/dropdown/dropdown.svelte.d.ts +3 -2
  16. package/dist/components/dropdown/exports.d.ts +1 -1
  17. package/dist/components/dropdown/exports.js +1 -1
  18. package/dist/components/dropdown/index.d.ts +1 -1
  19. package/dist/components/dropdown/styles.js +5 -3
  20. package/dist/components/dropdown/types.d.ts +47 -23
  21. package/dist/components/field/field.svelte +0 -1
  22. package/dist/components/segment/components/segment.root.svelte +2 -1
  23. package/dist/components/segment/components/segmet.svelte.d.ts +0 -1
  24. package/dist/components/segment/components/segmet.svelte.js +0 -1
  25. package/dist/components/segment/styles.d.ts +18 -0
  26. package/dist/components/segment/styles.js +7 -1
  27. package/dist/components/select/components/select.content.svelte +2 -4
  28. package/dist/components/select/components/select.group-heading.svelte +2 -4
  29. package/dist/components/select/components/select.group-heading.svelte.d.ts +2 -2
  30. package/dist/components/select/components/select.group.svelte.d.ts +2 -2
  31. package/dist/components/select/components/select.item.svelte +5 -13
  32. package/dist/components/select/components/select.item.svelte.d.ts +2 -2
  33. package/dist/components/select/components/select.root.svelte +1 -17
  34. package/dist/components/select/components/select.root.svelte.d.ts +1 -2
  35. package/dist/components/select/components/select.trigger.svelte +17 -5
  36. package/dist/components/select/components/select.viewport.svelte +2 -4
  37. package/dist/components/select/components/select.viewport.svelte.d.ts +2 -2
  38. package/dist/components/select/exports.d.ts +1 -1
  39. package/dist/components/select/exports.js +1 -1
  40. package/dist/components/select/select.async.svelte +146 -83
  41. package/dist/components/select/select.async.svelte.d.ts +1 -1
  42. package/dist/components/select/select.svelte +107 -62
  43. package/dist/components/select/select.svelte.d.ts +4 -2
  44. package/dist/components/select/styles.d.ts +48 -139
  45. package/dist/components/select/styles.js +74 -101
  46. package/dist/components/select/types.d.ts +69 -29
  47. package/dist/components/select/types.js +0 -1
  48. package/dist/components/select/utils/get-item-key.d.ts +1 -1
  49. package/dist/internal/index.d.ts +1 -0
  50. package/dist/internal/index.js +1 -0
  51. package/dist/internal/lib/collection/grid-collection.d.ts +3 -0
  52. package/dist/internal/lib/collection/grid-collection.js +2 -0
  53. package/dist/internal/lib/collection/index.d.ts +5 -0
  54. package/dist/internal/lib/collection/index.js +5 -0
  55. package/dist/internal/lib/collection/list-collection.d.ts +3 -0
  56. package/dist/internal/lib/collection/list-collection.js +2 -0
  57. package/dist/internal/lib/collection/tree-collection.d.ts +4 -0
  58. package/dist/internal/lib/collection/tree-collection.js +3 -0
  59. package/dist/internal/lib/collection/use-list-collection.svelte.d.ts +88 -0
  60. package/dist/internal/lib/collection/use-list-collection.svelte.js +94 -0
  61. package/dist/internal/lib/collection/use-list-selection.svelte.d.ts +92 -0
  62. package/dist/internal/lib/collection/use-list-selection.svelte.js +80 -0
  63. package/dist/internal/lib/index.d.ts +1 -0
  64. package/dist/internal/lib/index.js +1 -0
  65. package/dist/internal/utils/equal.d.ts +3 -0
  66. package/dist/internal/utils/equal.js +56 -0
  67. package/dist/internal/utils/functions.d.ts +2 -0
  68. package/dist/internal/utils/functions.js +4 -0
  69. package/dist/internal/utils/guard.d.ts +5 -0
  70. package/dist/internal/utils/guard.js +5 -0
  71. package/package.json +5 -3
  72. package/dist/components/app-shell/app-shell.stories.svelte +0 -107
  73. package/dist/components/app-shell/app-shell.stories.svelte.d.ts +0 -18
  74. package/dist/components/badge/badge.stories.svelte +0 -81
  75. package/dist/components/badge/badge.stories.svelte.d.ts +0 -19
  76. package/dist/components/breadcrumb/breadcrumb.stories.svelte +0 -67
  77. package/dist/components/breadcrumb/breadcrumb.stories.svelte.d.ts +0 -4
  78. package/dist/components/button/button.stories.svelte +0 -106
  79. package/dist/components/button/button.stories.svelte.d.ts +0 -19
  80. package/dist/components/button-group/button-group.stories.svelte +0 -59
  81. package/dist/components/button-group/button-group.stories.svelte.d.ts +0 -18
  82. package/dist/components/checkbox/checkbox.stories.svelte +0 -52
  83. package/dist/components/checkbox/checkbox.stories.svelte.d.ts +0 -18
  84. package/dist/components/collapsible/collapsible.stories.svelte +0 -69
  85. package/dist/components/collapsible/collapsible.stories.svelte.d.ts +0 -18
  86. package/dist/components/data-table/data-table.stories.svelte +0 -327
  87. package/dist/components/data-table/data-table.stories.svelte.d.ts +0 -4
  88. package/dist/components/dialog/dialog.stories.svelte +0 -116
  89. package/dist/components/dialog/dialog.stories.svelte.d.ts +0 -3
  90. package/dist/components/dropdown/dropdown.stories.svelte +0 -151
  91. package/dist/components/dropdown/dropdown.stories.svelte.d.ts +0 -19
  92. package/dist/components/field/field.stories.svelte +0 -56
  93. package/dist/components/field/field.stories.svelte.d.ts +0 -19
  94. package/dist/components/input/input.stories.svelte +0 -41
  95. package/dist/components/input/input.stories.svelte.d.ts +0 -19
  96. package/dist/components/navigation/navigation.stories.svelte +0 -99
  97. package/dist/components/navigation/navigation.stories.svelte.d.ts +0 -19
  98. package/dist/components/pagination/pagination.stories.svelte +0 -69
  99. package/dist/components/pagination/pagination.stories.svelte.d.ts +0 -19
  100. package/dist/components/popover/popover.stories.svelte +0 -195
  101. package/dist/components/popover/popover.stories.svelte.d.ts +0 -3
  102. package/dist/components/segment/segment.stories.svelte +0 -57
  103. package/dist/components/segment/segment.stories.svelte.d.ts +0 -19
  104. package/dist/components/select/select.stories.svelte +0 -263
  105. package/dist/components/select/select.stories.svelte.d.ts +0 -4
  106. package/dist/components/separator/separator.stories.svelte +0 -44
  107. package/dist/components/separator/separator.stories.svelte.d.ts +0 -19
  108. package/dist/components/skeleton/skeleton.stories.svelte +0 -129
  109. package/dist/components/skeleton/skeleton.stories.svelte.d.ts +0 -19
  110. package/dist/components/spinner/spinner.stories.svelte +0 -29
  111. package/dist/components/spinner/spinner.stories.svelte.d.ts +0 -19
  112. package/dist/components/switch/switch.stories.svelte +0 -55
  113. package/dist/components/switch/switch.stories.svelte.d.ts +0 -19
  114. package/dist/components/textarea/textarea.stories.svelte +0 -36
  115. package/dist/components/textarea/textarea.stories.svelte.d.ts +0 -19
  116. package/dist/components/toast/toast.stories.svelte +0 -96
  117. package/dist/components/toast/toast.stories.svelte.d.ts +0 -19
  118. package/dist/internal/utils/arrays.d.ts +0 -1
  119. package/dist/internal/utils/arrays.js +0 -30
@@ -209,6 +209,9 @@
209
209
  .cgui\:right-0 {
210
210
  right: calc(var(--cgui-spacing) * 0);
211
211
  }
212
+ .cgui\:right-2 {
213
+ right: calc(var(--cgui-spacing) * 2);
214
+ }
212
215
  .cgui\:right-4 {
213
216
  right: calc(var(--cgui-spacing) * 4);
214
217
  }
@@ -251,9 +254,15 @@
251
254
  .cgui\:ms-auto {
252
255
  margin-inline-start: auto;
253
256
  }
257
+ .cgui\:mt-2 {
258
+ margin-top: calc(var(--cgui-spacing) * 2);
259
+ }
254
260
  .cgui\:mt-4 {
255
261
  margin-top: calc(var(--cgui-spacing) * 4);
256
262
  }
263
+ .cgui\:mb-2 {
264
+ margin-bottom: calc(var(--cgui-spacing) * 2);
265
+ }
257
266
  .cgui\:scrollbar-thin {
258
267
  &::-webkit-scrollbar-track {
259
268
  background-color: var(--scrollbar-track);
@@ -459,8 +468,14 @@
459
468
  .cgui\:w-48 {
460
469
  width: calc(var(--cgui-spacing) * 48);
461
470
  }
462
- .cgui\:w-70 {
463
- width: calc(var(--cgui-spacing) * 70);
471
+ .cgui\:w-56 {
472
+ width: calc(var(--cgui-spacing) * 56);
473
+ }
474
+ .cgui\:w-64 {
475
+ width: calc(var(--cgui-spacing) * 64);
476
+ }
477
+ .cgui\:w-80 {
478
+ width: calc(var(--cgui-spacing) * 80);
464
479
  }
465
480
  .cgui\:w-\[420px\] {
466
481
  width: 420px;
@@ -696,6 +711,9 @@
696
711
  .cgui\:overflow-y-auto {
697
712
  overflow-y: auto;
698
713
  }
714
+ .cgui\:scroll-smooth {
715
+ scroll-behavior: smooth;
716
+ }
699
717
  .cgui\:rounded-\[inherit\] {
700
718
  border-radius: inherit;
701
719
  }
@@ -1172,8 +1190,8 @@
1172
1190
  .cgui\:outline-stroke-focus {
1173
1191
  outline-color: var(--cg-ui-palette-primary-60);
1174
1192
  }
1175
- .cgui\:transition-\[background-color\,color\] {
1176
- transition-property: background-color,color;
1193
+ .cgui\:transition-\[background-color\,color\,ring\,outline\,border-color\] {
1194
+ transition-property: background-color,color,ring,outline,border-color;
1177
1195
  transition-timing-function: var(--tw-ease, var(--cgui-default-transition-timing-function));
1178
1196
  transition-duration: var(--tw-duration, var(--cgui-default-transition-duration));
1179
1197
  }
@@ -1230,6 +1248,9 @@
1230
1248
  .cgui\:scrollbar-thumb-stroke-default {
1231
1249
  --scrollbar-thumb: var(--cg-ui-palette-neutral-40);
1232
1250
  }
1251
+ .cgui\:scrollbar-thumb-surface-light {
1252
+ --scrollbar-thumb: var(--cg-ui-palette-neutral-20);
1253
+ }
1233
1254
  .cgui\:scrollbar-thumb-surface-regular {
1234
1255
  --scrollbar-thumb: var(--cg-ui-palette-neutral-50);
1235
1256
  }
@@ -1408,6 +1429,13 @@
1408
1429
  }
1409
1430
  }
1410
1431
  }
1432
+ .cgui\:hover\:no-underline {
1433
+ &:hover {
1434
+ @media (hover: hover) {
1435
+ text-decoration-line: none;
1436
+ }
1437
+ }
1438
+ }
1411
1439
  .cgui\:focus\:ring-stroke-default {
1412
1440
  &:focus {
1413
1441
  --tw-ring-color: var(--cg-ui-palette-neutral-40);
@@ -1456,6 +1484,11 @@
1456
1484
  opacity: 50%;
1457
1485
  }
1458
1486
  }
1487
+ .cgui\:has-\[data-slot\=chevron\]\:pr-3 {
1488
+ &:has(*:is(data-slot=chevron)) {
1489
+ padding-right: calc(var(--cgui-spacing) * 3);
1490
+ }
1491
+ }
1459
1492
  .cgui\:has-\[\>\[data-slot\=button-group\]\]\:gap-2 {
1460
1493
  &:has(>[data-slot=button-group]) {
1461
1494
  gap: calc(var(--cgui-spacing) * 2);
@@ -1869,6 +1902,12 @@
1869
1902
  color: var(--cg-ui-palette-neutral-50);
1870
1903
  }
1871
1904
  }
1905
+ .cgui\:\[\&_svg\:not\(\[class\*\=\"size-\"\]\)\]\:size-4 {
1906
+ & svg:not([class*="size-"]) {
1907
+ width: calc(var(--cgui-spacing) * 4);
1908
+ height: calc(var(--cgui-spacing) * 4);
1909
+ }
1910
+ }
1872
1911
  .cgui\:\[\&_svg\:not\(\[class\*\=\"size-\"\]\)\]\:size-4\.5 {
1873
1912
  & svg:not([class*="size-"]) {
1874
1913
  width: calc(var(--cgui-spacing) * 4.5);
@@ -7,14 +7,14 @@
7
7
  import Separator from './components/breadcrumb.separator.svelte';
8
8
  import type { BreadcrumbProps } from './types.js';
9
9
 
10
- let { children, ref = $bindable(null), path, ...restProps }: BreadcrumbProps = $props();
10
+ let { ref = $bindable(null), path, ...restProps }: BreadcrumbProps = $props();
11
11
 
12
12
  const items = $derived(Array.isArray(path) ? path : path.split('/').filter(Boolean));
13
13
  </script>
14
14
 
15
15
  <Root bind:ref {...restProps}>
16
16
  <List>
17
- {#each items as item, idx}
17
+ {#each items as item, idx (idx)}
18
18
  {@const isLast = idx === items.length - 1}
19
19
 
20
20
  {#if isLast}
@@ -1,5 +1,5 @@
1
1
  import type { PrimitiveAnchorAttributes, PrimitiveElementAttributes, PrimitiveLiAttributes, PrimitiveOListAttributes, PrimitiveSpanAttributes } from '../../internal/types/html-attributes.js';
2
- import type { WithChild, WithChildren, WithElementRef, Without } from 'svelte-toolbelt';
2
+ import type { WithChild, WithChildren, WithElementRef, Without, WithoutChildrenOrChild } from 'svelte-toolbelt';
3
3
  import type { BreadcrumbVariantsProps } from './styles.js';
4
4
  type BreadcrumbRootPropsWithoutHTML = WithElementRef<WithChildren<{}>> & BreadcrumbVariantsProps;
5
5
  export type BreadcrumbRootProps = BreadcrumbRootPropsWithoutHTML & Without<PrimitiveElementAttributes, BreadcrumbRootPropsWithoutHTML>;
@@ -13,7 +13,7 @@ type BreadcrumbLinkPropsWithoutHTML = WithElementRef<WithChild<{}>>;
13
13
  export type BreadcrumbLinkProps = BreadcrumbLinkPropsWithoutHTML & Without<PrimitiveAnchorAttributes, BreadcrumbLinkPropsWithoutHTML>;
14
14
  type BreadcrumbPagePropsWithoutHTML = WithElementRef<WithChildren<{}>>;
15
15
  export type BreadcrumbPageProps = BreadcrumbPagePropsWithoutHTML & Without<PrimitiveSpanAttributes, BreadcrumbPagePropsWithoutHTML>;
16
- export type BreadcrumbProps = BreadcrumbRootProps & {
16
+ export type BreadcrumbProps = WithoutChildrenOrChild<BreadcrumbRootProps> & {
17
17
  path: string[] | string;
18
18
  };
19
19
  export {};
@@ -52,6 +52,11 @@ export declare const buttonVariants: import("tailwind-variants").TVReturnType<{
52
52
  root: string;
53
53
  };
54
54
  };
55
+ fullWidth: {
56
+ true: {
57
+ root: string;
58
+ };
59
+ };
55
60
  rounded: {
56
61
  sm: {
57
62
  root: string;
@@ -128,6 +133,11 @@ export declare const buttonVariants: import("tailwind-variants").TVReturnType<{
128
133
  root: string;
129
134
  };
130
135
  };
136
+ fullWidth: {
137
+ true: {
138
+ root: string;
139
+ };
140
+ };
131
141
  rounded: {
132
142
  sm: {
133
143
  root: string;
@@ -204,6 +214,11 @@ export declare const buttonVariants: import("tailwind-variants").TVReturnType<{
204
214
  root: string;
205
215
  };
206
216
  };
217
+ fullWidth: {
218
+ true: {
219
+ root: string;
220
+ };
221
+ };
207
222
  rounded: {
208
223
  sm: {
209
224
  root: string;
@@ -2,7 +2,7 @@ import { tv } from '../../internal/utils/tailwindcss.js';
2
2
  export const buttonVariants = tv({
3
3
  slots: {
4
4
  root: [
5
- 'cgui:flex cgui:items-center cgui:justify-center cgui:gap-1.5 cgui:cursor-pointer cgui:px-2 cgui:text-center cgui:overflow-hidden',
5
+ 'cgui:flex cgui:items-center cgui:justify-center cgui:gap-1 cgui:cursor-pointer cgui:px-2 cgui:text-center cgui:overflow-hidden',
6
6
  'cgui:transition-all cgui:duration-250 cgui:ease-in-out',
7
7
  'cgui:select-none cgui:font-medium',
8
8
  'cgui:disabled:cursor-not-allowed cgui:disabled:opacity-50',
@@ -49,13 +49,13 @@ export const buttonVariants = tv({
49
49
  },
50
50
  size: {
51
51
  xs: {
52
- root: 'cgui:h-7.5 cgui:px-2.5 cgui:text-body',
52
+ root: 'cgui:h-7.5 cgui:px-2 cgui:text-body',
53
53
  },
54
54
  sm: {
55
- root: 'cgui:h-8 cgui:px-3 cgui:text-body',
55
+ root: 'cgui:h-8 cgui:px-2.5 cgui:text-body',
56
56
  },
57
57
  md: {
58
- root: 'cgui:h-9 cgui:px-4 cgui:text-body',
58
+ root: 'cgui:h-9 cgui:px-3 cgui:text-body',
59
59
  },
60
60
  lg: {
61
61
  root: 'cgui:h-10.5 cgui:px-4 cgui:text-heading-2',
@@ -75,6 +75,11 @@ export const buttonVariants = tv({
75
75
  root: '',
76
76
  },
77
77
  },
78
+ fullWidth: {
79
+ true: {
80
+ root: 'cgui:w-full',
81
+ },
82
+ },
78
83
  rounded: {
79
84
  sm: {
80
85
  root: 'cgui:rounded-sm',
@@ -1,15 +1,13 @@
1
1
  <script lang="ts">
2
2
  import type { ButtonGroupRootProps } from '../types.js';
3
3
  import { SLOT_ATTR_NAME } from '../../../internal/constants/attrs.js';
4
- import { cn, useId } from '../../../internal/utils/common.js';
4
+ import { cn } from '../../../internal/utils/common.js';
5
5
  import { box } from 'svelte-toolbelt';
6
6
  import { ButtonGroupStylesContext, buttonGroupStyles } from '../styles.js';
7
7
 
8
- const uid = $props.id();
9
8
  let {
10
9
  children,
11
10
  ref = $bindable(null),
12
- id = useId(uid),
13
11
  orientation = 'horizontal',
14
12
  class: className,
15
13
  ...restProps
@@ -1,6 +1,6 @@
1
- import { arraysAreEqual } from '../../../internal/utils/arrays.js';
2
1
  import { getDataDisabled } from '../../../internal/utils/attrs.js';
3
2
  import { keyWithPrefix } from '../../../internal/utils/common.js';
3
+ import { isEqual } from '../../../internal/utils/equal.js';
4
4
  import { Context, watch } from 'runed';
5
5
  import { attachRef } from 'svelte-toolbelt';
6
6
  const CollapsibleRootContext = new Context(keyWithPrefix('collapsible-root'));
@@ -28,7 +28,7 @@ export class CollapsibleGroupState {
28
28
  newValue = [...$state.snapshot(this.opts.value.current), value];
29
29
  }
30
30
  this.opts.value.current = newValue;
31
- if (arraysAreEqual(this.opts.value.current, newValue))
31
+ if (isEqual(this.opts.value.current, newValue))
32
32
  return;
33
33
  this.opts.onValueChange.current(newValue);
34
34
  }
@@ -40,7 +40,7 @@ export class CollapsibleGroupState {
40
40
  return;
41
41
  const newValue = this.opts.value.current.filter((v) => v !== value);
42
42
  this.opts.value.current = newValue;
43
- if (arraysAreEqual(this.opts.value.current, newValue))
43
+ if (isEqual(this.opts.value.current, newValue))
44
44
  return;
45
45
  this.opts.onValueChange.current(newValue);
46
46
  }
@@ -14,7 +14,7 @@
14
14
  import FlexRender from './components/flex-render.svelte';
15
15
  import { type DataTableProps, type RowData } from './types.js';
16
16
 
17
- let { ref = $bindable(null), table, empty, loading, ...restProps }: DataTableProps<TData> = $props();
17
+ let { ref = $bindable(null), table, empty, ...restProps }: DataTableProps<TData> = $props();
18
18
 
19
19
  let isFirstLoaded = $state(false);
20
20
 
@@ -7,9 +7,9 @@ export const usePaginationState = (opts) => {
7
7
  get value() {
8
8
  return value;
9
9
  },
10
- set value(value) {
11
- value = value;
12
- opts?.onValueChange?.(value);
10
+ set value(v) {
11
+ value = v;
12
+ opts?.onValueChange?.(v);
13
13
  },
14
14
  updater: (updater) => {
15
15
  let newPaginationState;
@@ -4,9 +4,9 @@ export const useResizeState = (opts) => {
4
4
  get value() {
5
5
  return value;
6
6
  },
7
- set value(value) {
8
- value = value;
9
- opts?.onValueChange?.(value);
7
+ set value(v) {
8
+ value = v;
9
+ opts?.onValueChange?.(v);
10
10
  },
11
11
  updater: (updater) => {
12
12
  let newColumnSizing;
@@ -4,9 +4,9 @@ export const useRowSelectionState = (opts) => {
4
4
  get value() {
5
5
  return value;
6
6
  },
7
- set value(value) {
8
- value = value;
9
- opts?.onValueChange?.(value);
7
+ set value(v) {
8
+ value = v;
9
+ opts?.onValueChange?.(v);
10
10
  },
11
11
  updater: (updater) => {
12
12
  let newRowSelection;
@@ -8,13 +8,7 @@
8
8
 
9
9
  const uid = $props.id();
10
10
 
11
- let {
12
- children,
13
- id = useId(uid),
14
- ref = $bindable(null),
15
- class: className,
16
- ...restProps
17
- }: DialogOverlayProps = $props();
11
+ let { id = useId(uid), ref = $bindable(null), class: className, ...restProps }: DialogOverlayProps = $props();
18
12
 
19
13
  const overlayState = DialogOverlayState.create({
20
14
  ref: boxWith(
@@ -15,7 +15,6 @@
15
15
  shadow = true,
16
16
  w = 'default',
17
17
  gap = 'default',
18
- initial = false,
19
18
  ...restProps
20
19
  }: DropdownContentProps = $props();
21
20
  </script>
@@ -29,7 +28,6 @@
29
28
  shadow,
30
29
  w,
31
30
  gap,
32
- initial,
33
31
  }),
34
32
  className
35
33
  )}
@@ -1,40 +1,79 @@
1
1
  <script lang="ts" module>
2
2
  import type {
3
- DropdownGroupItemValue,
4
- DropdownItemLinkValue,
5
- DropdownItemSubValue,
6
- DropdownItemValue,
7
- DropdownSeparatorItemValue,
8
- DropdownSingleItemValue,
3
+ DropdownCollectionOptions,
4
+ DropdownItem,
5
+ DropdownItemAction,
6
+ DropdownItemLink,
7
+ DropdownItemSeparator,
8
+ DropdownItemSub,
9
+ DropdownSelectableItem,
9
10
  } from './types.js';
10
11
 
11
- export function itemCollection(items: DropdownItemValue[]): DropdownItemValue[] {
12
- return items;
13
- }
12
+ export function createDropdownCollection(options: DropdownCollectionOptions): ListCollection<DropdownItem> {
13
+ const { items, groups = [], groupSort } = options;
14
+
15
+ const groupOrderMap = new Map<string, number>();
16
+ groups.forEach((g, index) => {
17
+ groupOrderMap.set(g.key, g.order ?? index);
18
+ });
19
+
20
+ return createListCollection({
21
+ items,
22
+
23
+ itemToValue: (item) => item.key,
24
+
25
+ itemToString: (item) => {
26
+ if (item.type === 'separator') return '';
27
+ return item.textValue ?? item.label;
28
+ },
14
29
 
15
- function isGroup(item: DropdownItemValue): item is DropdownGroupItemValue {
16
- return item.type === 'group';
30
+ isItemDisabled: (item) => {
31
+ if (item.type === 'separator') return true;
32
+ return !!item.disabled;
33
+ },
34
+
35
+ groupBy: (item) => item.group ?? '',
36
+
37
+ groupSort:
38
+ groupSort ??
39
+ ((a, b) => {
40
+ const orderA = groupOrderMap.get(a) ?? Infinity;
41
+ const orderB = groupOrderMap.get(b) ?? Infinity;
42
+ if (orderA !== orderB) return orderA - orderB;
43
+ return a.localeCompare(b);
44
+ }),
45
+ });
17
46
  }
18
47
 
19
- function isSeparator(item: DropdownItemValue): item is DropdownSeparatorItemValue {
48
+ function isSeparator(item: DropdownItem): item is DropdownItemSeparator {
20
49
  return item.type === 'separator';
21
50
  }
22
51
 
23
- function isLink(item: DropdownSingleItemValue): item is DropdownItemLinkValue {
52
+ function isLink(item: DropdownSelectableItem): item is DropdownItemLink {
24
53
  return item.type === 'link';
25
54
  }
26
55
 
27
- function isSub(item: DropdownSingleItemValue): item is DropdownItemSubValue {
56
+ function isSub(item: DropdownSelectableItem): item is DropdownItemSub {
28
57
  return item.type === 'sub';
29
58
  }
59
+
60
+ function isAction(item: DropdownSelectableItem): item is DropdownItemAction {
61
+ return item.type === 'action';
62
+ }
63
+
64
+ function isSelectable(item: DropdownItem): item is DropdownSelectableItem {
65
+ return item.type !== 'separator';
66
+ }
30
67
  </script>
31
68
 
32
69
  <script lang="ts">
70
+ import { createListCollection, type ListCollection } from '../../internal/index.js';
33
71
  import * as Primitive from './exports-primitive.js';
34
72
  import type { DropdownProps } from './types.js';
35
73
 
36
74
  let {
37
- items,
75
+ collection,
76
+ groups = [],
38
77
  open = $bindable(false),
39
78
  trigger,
40
79
  contentProps,
@@ -42,61 +81,76 @@
42
81
  item: itemSnippet,
43
82
  ...restProps
44
83
  }: DropdownProps = $props();
84
+
85
+ const groupLabelMap = $derived(new Map(groups.map((g) => [g.key, g.label ?? g.key])));
86
+
87
+ const groupedItems = $derived(collection.group());
45
88
  </script>
46
89
 
47
- {#snippet defaultItemRenderer(item: DropdownSingleItemValue)}
48
- {#if isSub(item)}
49
- <Primitive.Sub>
50
- <Primitive.SubTrigger disabled={item.disabled}>
90
+ {#snippet defaultSubRenderer(item: DropdownItemSub)}
91
+ <Primitive.Sub>
92
+ <Primitive.SubTrigger disabled={item.disabled} textValue={item.textValue ?? item.label}>
93
+ {#if item.icon}
94
+ <item.icon width={16} height={16} />
95
+ {/if}
96
+ {item.label}
97
+ </Primitive.SubTrigger>
98
+ <Primitive.Portal>
99
+ <Primitive.SubContent data-value={item.key}>
100
+ {#each item.children as child (child.key)}
101
+ {#if isSelectable(child)}
102
+ {@render renderItem(child)}
103
+ {/if}
104
+ {/each}
105
+ </Primitive.SubContent>
106
+ </Primitive.Portal>
107
+ </Primitive.Sub>
108
+ {/snippet}
109
+
110
+ {#snippet defaultLinkRenderer(item: DropdownItemLink)}
111
+ <Primitive.Item
112
+ disabled={item.disabled}
113
+ textValue={item.textValue ?? item.label}
114
+ onSelect={item.onSelect}
115
+ data-value={item.key}
116
+ >
117
+ {#snippet child({ props })}
118
+ <a {...props} href={item.href} target={item.target} rel={item.rel}>
51
119
  {#if item.icon}
52
120
  <item.icon width={16} height={16} />
53
121
  {/if}
54
122
  {item.label}
55
- </Primitive.SubTrigger>
56
- <Primitive.Portal>
57
- <Primitive.SubContent>
58
- {#each item.children as child}
59
- {@render renderSingleItem(child)}
60
- {/each}
61
- </Primitive.SubContent>
62
- </Primitive.Portal>
63
- </Primitive.Sub>
64
- {:else if isLink(item)}
65
- {@const { type: _, disabled, onSelect, ...linkProps } = item}
66
- <Primitive.Item {disabled} {onSelect}>
67
- {#snippet child({ props })}
68
- <a {...props} {...linkProps}>
69
- {#if item.icon}
70
- <item.icon width={16} height={16} />
71
- {/if}
72
- {item.label}
73
- </a>
74
- {/snippet}
75
- </Primitive.Item>
76
- {:else}
77
- {@const { type: _, disabled, onSelect, ...actionProps } = item}
78
- <Primitive.Item {disabled} {onSelect}>
79
- {#snippet child({ props })}
80
- <button {...props} {...actionProps}>
81
- {#if item.icon}
82
- <item.icon width={16} height={16} />
83
- {/if}
84
- {item.label}
85
- </button>
86
- {/snippet}
87
- </Primitive.Item>
88
- {/if}
123
+ </a>
124
+ {/snippet}
125
+ </Primitive.Item>
126
+ {/snippet}
127
+
128
+ {#snippet defaultActionRenderer(item: DropdownItemAction)}
129
+ <Primitive.Item disabled={item.disabled} textValue={item.textValue ?? item.label} onSelect={item.onSelect}>
130
+ {#snippet child({ props })}
131
+ <button {...props}>
132
+ {#if item.icon}
133
+ <item.icon width={16} height={16} />
134
+ {/if}
135
+ {item.label}
136
+ </button>
137
+ {/snippet}
138
+ </Primitive.Item>
89
139
  {/snippet}
90
140
 
91
- {#snippet renderSingleItem(item: DropdownSingleItemValue)}
141
+ {#snippet renderItem(item: DropdownSelectableItem)}
92
142
  {#if itemSnippet}
93
- <Primitive.Item disabled={item.disabled} onSelect={item.onSelect}>
143
+ <Primitive.Item disabled={item.disabled} onSelect={item.onSelect} data-value={item.key}>
94
144
  {#snippet child({ props })}
95
145
  {@render itemSnippet({ item, props })}
96
146
  {/snippet}
97
147
  </Primitive.Item>
98
- {:else}
99
- {@render defaultItemRenderer(item)}
148
+ {:else if isSub(item)}
149
+ {@render defaultSubRenderer(item)}
150
+ {:else if isLink(item)}
151
+ {@render defaultLinkRenderer(item)}
152
+ {:else if isAction(item)}
153
+ {@render defaultActionRenderer(item)}
100
154
  {/if}
101
155
  {/snippet}
102
156
 
@@ -115,20 +169,26 @@
115
169
 
116
170
  <Primitive.Portal>
117
171
  <Primitive.Content {...contentProps} class={contentClass}>
118
- {#each items as item (item.key)}
119
- {#if isGroup(item)}
172
+ {#each groupedItems as [groupKey, items] (groupKey || '__ungrouped__')}
173
+ {#if groupKey}
120
174
  <Primitive.Group>
121
- {#if item.heading}
122
- <Primitive.GroupHeading>{item.heading}</Primitive.GroupHeading>
123
- {/if}
124
- {#each item.items as groupItem (groupItem.key)}
125
- {@render renderSingleItem(groupItem)}
175
+ <Primitive.GroupHeading>{groupLabelMap.get(groupKey) ?? groupKey}</Primitive.GroupHeading>
176
+ {#each items as item (item.key)}
177
+ {#if isSeparator(item)}
178
+ <Primitive.Separator />
179
+ {:else}
180
+ {@render renderItem(item)}
181
+ {/if}
126
182
  {/each}
127
183
  </Primitive.Group>
128
- {:else if isSeparator(item)}
129
- <Primitive.Separator />
130
184
  {:else}
131
- {@render renderSingleItem(item)}
185
+ {#each items as item (item.key)}
186
+ {#if isSeparator(item)}
187
+ <Primitive.Separator />
188
+ {:else}
189
+ {@render renderItem(item)}
190
+ {/if}
191
+ {/each}
132
192
  {/if}
133
193
  {/each}
134
194
  </Primitive.Content>
@@ -1,5 +1,6 @@
1
- import type { DropdownItemValue } from './types.js';
2
- export declare function itemCollection(items: DropdownItemValue[]): DropdownItemValue[];
1
+ import type { DropdownCollectionOptions, DropdownItem } from './types.js';
2
+ export declare function createDropdownCollection(options: DropdownCollectionOptions): ListCollection<DropdownItem>;
3
+ import { type ListCollection } from '../../internal/index.js';
3
4
  import type { DropdownProps } from './types.js';
4
5
  declare const Dropdown: import("svelte").Component<DropdownProps, {}, "open">;
5
6
  type Dropdown = ReturnType<typeof Dropdown>;
@@ -1 +1 @@
1
- export { itemCollection, default as Root } from './dropdown.svelte';
1
+ export { createDropdownCollection, default as Root } from './dropdown.svelte';
@@ -1 +1 @@
1
- export { itemCollection, default as Root } from './dropdown.svelte';
1
+ export { createDropdownCollection, default as Root } from './dropdown.svelte';
@@ -1,3 +1,3 @@
1
1
  export * as DropdownPrimitive from './exports-primitive.js';
2
2
  export * as Dropdown from './exports.js';
3
- export type { DropdownContentProps, DropdownGroupHeadingProps, DropdownGroupProps, DropdownItemProps, DropdownItemValue, DropdownPortalProps, DropdownProps, DropdownRootProps, DropdownSubContentProps, DropdownSubProps, DropdownSubTriggerProps, DropdownTriggerProps, } from './types.js';
3
+ export type { DropdownCollection, DropdownCollectionOptions, DropdownContentProps, DropdownGroup, DropdownGroupHeadingProps, DropdownGroupProps, DropdownItem, DropdownItemAction, DropdownItemBase, DropdownItemEvents, DropdownItemLink, DropdownItemProps, DropdownItemSeparator, DropdownItemSub, DropdownPortalProps, DropdownProps, DropdownRootProps, DropdownSelectableItem, DropdownSeparatorProps, DropdownSubContentProps, DropdownSubProps, DropdownSubTriggerProps, DropdownTriggerProps, } from './types.js';
@@ -8,6 +8,8 @@ export const dropdownTriggerStyles = tv({
8
8
  export const dropdownContentStyles = tv({
9
9
  base: [
10
10
  'cgui:max-h-(--bits-dropdown-menu-content-available-height)',
11
+ 'cgui:scrollbar-thin cgui:scroll-smooth',
12
+ 'cgui:scrollbar-track-surface-lightest cgui:scrollbar-thumb-surface-light cgui:scrollbar-thumb-rounded-full cgui:scrollbar-track-rounded-full',
11
13
  'cgui:overflow-x-hidden cgui:overflow-y-auto',
12
14
  'cgui:outline-none',
13
15
  'cgui:z-(--cg-ui-z-index-dropdown) cgui:origin-(--bits-dropdown-menu-content-transform-origin)',
@@ -51,11 +53,11 @@ export const dropdownContentStyles = tv({
51
53
  });
52
54
  export const dropdownItemStyles = tv({
53
55
  base: [
54
- 'cgui:flex cgui:items-center cgui:gap-1.5',
56
+ 'cgui:flex cgui:items-center cgui:gap-1.5 cgui:w-full',
55
57
  'cgui:text-body cgui:text-fg-dark cgui:font-normal cgui:select-none',
56
- 'cgui:overflow-hidden cgui:whitespace-nowrap',
58
+ 'cgui:overflow-hidden cgui:whitespace-nowrap cgui:outline-none',
57
59
  'cgui:[&_svg]:shrink-0 cgui:[&_svg]:pointer-events-none cgui:[&_svg]:text-icon-regular cgui:[&_svg:not([class*="size-"])]:size-4.5',
58
- 'cgui:transition-[background-color,color] cgui:duration-250 cgui:ease-in-out',
60
+ 'cgui:transition-[background-color,color,ring,outline,border-color] cgui:duration-250 cgui:ease-in-out',
59
61
  'cgui:data-highlighted:bg-surface-lightest',
60
62
  'cgui:data-[disabled]:cursor-not-allowed cgui:data-[disabled]:pointer-events-none cgui:data-[disabled]:opacity-50',
61
63
  ],