@casinogate/ui 1.8.7 → 1.9.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 (30) hide show
  1. package/dist/assets/css/root.css +85 -38
  2. package/dist/components/input/styles.js +1 -1
  3. package/dist/components/navigation/components/navigation.content.svelte +3 -4
  4. package/dist/components/navigation/components/navigation.item.svelte +19 -17
  5. package/dist/components/navigation/components/navigation.root.svelte +10 -12
  6. package/dist/components/navigation/components/navigation.sub-content.svelte +27 -28
  7. package/dist/components/navigation/components/navigation.sub-trigger.svelte +107 -0
  8. package/dist/components/navigation/components/navigation.sub-trigger.svelte.d.ts +4 -0
  9. package/dist/components/navigation/components/navigation.sub.svelte +55 -0
  10. package/dist/components/navigation/components/navigation.sub.svelte.d.ts +4 -0
  11. package/dist/components/navigation/components/navigation.svelte.d.ts +45 -15
  12. package/dist/components/navigation/components/navigation.svelte.js +68 -28
  13. package/dist/components/navigation/components/navigation.trigger.svelte +36 -80
  14. package/dist/components/navigation/exports-primitive.d.ts +2 -0
  15. package/dist/components/navigation/exports-primitive.js +2 -0
  16. package/dist/components/navigation/exports.d.ts +1 -1
  17. package/dist/components/navigation/exports.js +1 -1
  18. package/dist/components/navigation/index.d.ts +2 -1
  19. package/dist/components/navigation/index.js +1 -0
  20. package/dist/components/navigation/navigation.svelte +114 -29
  21. package/dist/components/navigation/navigation.svelte.d.ts +3 -0
  22. package/dist/components/navigation/styles.d.ts +19 -28
  23. package/dist/components/navigation/styles.js +45 -28
  24. package/dist/components/navigation/types.d.ts +59 -20
  25. package/dist/components/popover/popover.svelte +12 -3
  26. package/dist/components/popover/styles.js +1 -1
  27. package/dist/components/popover/types.d.ts +3 -1
  28. package/dist/components/select/styles.js +1 -1
  29. package/dist/components/textarea/styles.js +1 -1
  30. package/package.json +1 -1
@@ -226,6 +226,9 @@
226
226
  .cgui\:z-\(--cg-ui-z-index-dropdown\) {
227
227
  z-index: var(--cg-ui-z-index-dropdown);
228
228
  }
229
+ .cgui\:z-\(--cg-ui-z-index-popover\) {
230
+ z-index: var(--cg-ui-z-index-popover);
231
+ }
229
232
  .cgui\:z-\(--cg-ui-z-index-select\) {
230
233
  z-index: var(--cg-ui-z-index-select);
231
234
  }
@@ -291,6 +294,9 @@
291
294
  .cgui\:hidden {
292
295
  display: none;
293
296
  }
297
+ .cgui\:inline-block {
298
+ display: inline-block;
299
+ }
294
300
  .cgui\:inline-flex {
295
301
  display: inline-flex;
296
302
  }
@@ -431,9 +437,6 @@
431
437
  .cgui\:w-\(--app-shell-sidebar-width\) {
432
438
  width: var(--app-shell-sidebar-width);
433
439
  }
434
- .cgui\:w-0 {
435
- width: calc(var(--cgui-spacing) * 0);
436
- }
437
440
  .cgui\:w-1\.5 {
438
441
  width: calc(var(--cgui-spacing) * 1.5);
439
442
  }
@@ -536,6 +539,9 @@
536
539
  .cgui\:min-w-35 {
537
540
  min-width: calc(var(--cgui-spacing) * 35);
538
541
  }
542
+ .cgui\:min-w-40 {
543
+ min-width: calc(var(--cgui-spacing) * 40);
544
+ }
539
545
  .cgui\:min-w-42 {
540
546
  min-width: calc(var(--cgui-spacing) * 42);
541
547
  }
@@ -578,9 +584,6 @@
578
584
  --tw-scale-x: calc(1 * -1);
579
585
  scale: var(--tw-scale-x) var(--tw-scale-y);
580
586
  }
581
- .cgui\:rotate-180 {
582
- rotate: 180deg;
583
- }
584
587
  .cgui\:animate-pulse {
585
588
  animation: var(--cgui-animate-pulse);
586
589
  }
@@ -849,6 +852,9 @@
849
852
  .cgui\:bg-surface-darkest {
850
853
  background-color: var(--cg-ui-color-surface-darkest);
851
854
  }
855
+ .cgui\:bg-surface-hover {
856
+ background-color: var(--cg-ui-color-surface-hover);
857
+ }
852
858
  .cgui\:bg-surface-light {
853
859
  background-color: var(--cg-ui-color-surface-light);
854
860
  }
@@ -927,6 +933,9 @@
927
933
  .cgui\:p-4 {
928
934
  padding: calc(var(--cgui-spacing) * 4);
929
935
  }
936
+ .cgui\:px-1 {
937
+ padding-inline: calc(var(--cgui-spacing) * 1);
938
+ }
930
939
  .cgui\:px-1\.5 {
931
940
  padding-inline: calc(var(--cgui-spacing) * 1.5);
932
941
  }
@@ -1131,9 +1140,6 @@
1131
1140
  .cgui\:underline {
1132
1141
  text-decoration-line: underline;
1133
1142
  }
1134
- .cgui\:opacity-0 {
1135
- opacity: 0%;
1136
- }
1137
1143
  .cgui\:opacity-50 {
1138
1144
  opacity: 50%;
1139
1145
  }
@@ -1292,6 +1298,11 @@
1292
1298
  }
1293
1299
  }
1294
1300
  }
1301
+ .cgui\:group-data-\[compact\=true\]\/navigation\:justify-center {
1302
+ &:is(:where(.cgui\:group\/navigation)[data-compact="true"] *) {
1303
+ justify-content: center;
1304
+ }
1305
+ }
1295
1306
  .cgui\:group-data-\[compact\=true\]\/navigation\:py-3 {
1296
1307
  &:is(:where(.cgui\:group\/navigation)[data-compact="true"] *) {
1297
1308
  padding-block: calc(var(--cgui-spacing) * 3);
@@ -1302,9 +1313,12 @@
1302
1313
  rotate: calc(180deg * -1);
1303
1314
  }
1304
1315
  }
1305
- .cgui\:placeholder\:text-fg-regular {
1316
+ .cgui\:placeholder\:text-fg-regular\/70 {
1306
1317
  &::placeholder {
1307
1318
  color: var(--cg-ui-color-fg-regular);
1319
+ @supports (color: color-mix(in lab, red, red)) {
1320
+ color: color-mix(in oklab, var(--cg-ui-color-fg-regular) 70%, transparent);
1321
+ }
1308
1322
  }
1309
1323
  }
1310
1324
  .cgui\:before\:pointer-events-none {
@@ -1373,6 +1387,11 @@
1373
1387
  content: var(--tw-content);
1374
1388
  }
1375
1389
  }
1390
+ .cgui\:empty\:hidden {
1391
+ &:empty {
1392
+ display: none;
1393
+ }
1394
+ }
1376
1395
  .cgui\:hover\:bg-primary-60 {
1377
1396
  &:hover {
1378
1397
  @media (hover: hover) {
@@ -1596,14 +1615,12 @@
1596
1615
  color: var(--cg-ui-color-fg-regular);
1597
1616
  }
1598
1617
  }
1599
- .cgui\:data-\[popover-content\]\:rounded-md {
1600
- &[data-popover-content] {
1601
- border-radius: calc(var(--cg-ui-number-md) * 1px);
1602
- }
1603
- }
1604
- .cgui\:data-\[popover-content\]\:bg-surface-darkest {
1605
- &[data-popover-content] {
1606
- background-color: var(--cg-ui-color-surface-darkest);
1618
+ .cgui\:data-\[placeholder\]\:text-fg-regular\/70 {
1619
+ &[data-placeholder] {
1620
+ color: var(--cg-ui-color-fg-regular);
1621
+ @supports (color: color-mix(in lab, red, red)) {
1622
+ color: color-mix(in oklab, var(--cg-ui-color-fg-regular) 70%, transparent);
1623
+ }
1607
1624
  }
1608
1625
  }
1609
1626
  .cgui\:data-\[selected\=\"\"\]\:border-stroke-primary {
@@ -1784,13 +1801,6 @@
1784
1801
  --tw-enter-scale: .95;
1785
1802
  }
1786
1803
  }
1787
- .cgui\:data-\[sub-content\=\"false\"\]\:group-data-\[compact\=true\]\/navigation\:justify-center {
1788
- &[data-sub-content="false"] {
1789
- &:is(:where(.cgui\:group\/navigation)[data-compact="true"] *) {
1790
- justify-content: center;
1791
- }
1792
- }
1793
- }
1794
1804
  .cgui\:scrollbar-hover\:scrollbar-thumb-surface-regular\/60 {
1795
1805
  &::-webkit-scrollbar-thumb:hover {
1796
1806
  --scrollbar-thumb: var(--cg-ui-color-surface-regular);
@@ -1799,10 +1809,39 @@
1799
1809
  }
1800
1810
  }
1801
1811
  }
1802
- .cgui\:\[\&_\[data-slot\=\"icon\"\]\]\:size-6 {
1812
+ .cgui\:group-data-\[compact\=false\]\/navigation\:data-\[state\=open\]\:\[\&_\[data-slot\=\"chevron\"\]\]\:rotate-180 {
1813
+ &:is(:where(.cgui\:group\/navigation)[data-compact="false"] *) {
1814
+ &[data-state="open"] {
1815
+ & [data-slot="chevron"] {
1816
+ rotate: 180deg;
1817
+ }
1818
+ }
1819
+ }
1820
+ }
1821
+ .cgui\:\[\&_\[data-slot\=\"icon\"\]\]\:me-auto {
1803
1822
  & [data-slot="icon"] {
1804
- width: calc(var(--cgui-spacing) * 6);
1805
- height: calc(var(--cgui-spacing) * 6);
1823
+ margin-inline-end: auto;
1824
+ }
1825
+ }
1826
+ .cgui\:\[\&_\[data-slot\=\"trigger\"\]\]\:rounded-sm {
1827
+ & [data-slot="trigger"] {
1828
+ border-radius: calc(var(--cg-ui-number-sm) * 1px);
1829
+ }
1830
+ }
1831
+ .cgui\:\[\&_\[data-slot\=\"trigger\"\]\]\:px-2 {
1832
+ & [data-slot="trigger"] {
1833
+ padding-inline: calc(var(--cgui-spacing) * 2);
1834
+ }
1835
+ }
1836
+ .cgui\:\[\&_\[data-slot\=\"trigger\"\]\]\:py-2 {
1837
+ & [data-slot="trigger"] {
1838
+ padding-block: calc(var(--cgui-spacing) * 2);
1839
+ }
1840
+ }
1841
+ .cgui\:\[\&_\[data-slot\=\"trigger\"\]\]\:text-sm {
1842
+ & [data-slot="trigger"] {
1843
+ font-size: var(--cgui-text-sm);
1844
+ line-height: var(--tw-leading, var(--cgui-text-sm--line-height));
1806
1845
  }
1807
1846
  }
1808
1847
  .cgui\:data-\[compact\=false\]\:\[\&_\[data-slot\=\"trigger\"\]\]\:pl-0 {
@@ -1812,6 +1851,12 @@
1812
1851
  }
1813
1852
  }
1814
1853
  }
1854
+ .cgui\:\[\&_\[data-slot\=\"trigger\"\]_\[data-slot\=\"icon\"\]\]\:size-4 {
1855
+ & [data-slot="trigger"] [data-slot="icon"] {
1856
+ width: calc(var(--cgui-spacing) * 4);
1857
+ height: calc(var(--cgui-spacing) * 4);
1858
+ }
1859
+ }
1815
1860
  .cgui\:hover\:\[\&_\[data-slot\=icon\]\]\:text-icon-focus {
1816
1861
  &:hover {
1817
1862
  @media (hover: hover) {
@@ -1878,6 +1923,18 @@
1878
1923
  pointer-events: none;
1879
1924
  }
1880
1925
  }
1926
+ .cgui\:\[\&_svg\]\:size-4 {
1927
+ & svg {
1928
+ width: calc(var(--cgui-spacing) * 4);
1929
+ height: calc(var(--cgui-spacing) * 4);
1930
+ }
1931
+ }
1932
+ .cgui\:\[\&_svg\]\:size-6 {
1933
+ & svg {
1934
+ width: calc(var(--cgui-spacing) * 6);
1935
+ height: calc(var(--cgui-spacing) * 6);
1936
+ }
1937
+ }
1881
1938
  .cgui\:\[\&_svg\]\:shrink-0 {
1882
1939
  & svg {
1883
1940
  flex-shrink: 0;
@@ -1911,16 +1968,6 @@
1911
1968
  border-width: 0px;
1912
1969
  }
1913
1970
  }
1914
- .cgui\:\[data-disabled\]\:cursor-not-allowed {
1915
- &:is(data-disabled) {
1916
- cursor: not-allowed;
1917
- }
1918
- }
1919
- .cgui\:\[data-disabled\]\:opacity-50 {
1920
- &:is(data-disabled) {
1921
- opacity: 50%;
1922
- }
1923
- }
1924
1971
  .cgui\:\[\&\>\*\]\:focus-visible\:relative {
1925
1972
  &>* {
1926
1973
  &:focus-visible {
@@ -18,7 +18,7 @@ export const inputStyles = tv({
18
18
  variant: {
19
19
  primary: {
20
20
  input: [
21
- 'cgui:border cgui:border-stroke-default cgui:bg-surface-lightest cgui:placeholder:text-fg-regular cgui:shadow-none',
21
+ 'cgui:border cgui:border-stroke-default cgui:text-fg-dark cgui:bg-surface-lightest cgui:placeholder:text-fg-regular/70 cgui:shadow-none',
22
22
  'cgui:focus:ring-stroke-default cgui:focus-visible:border-stroke-focus',
23
23
  'cgui:aria-invalid:ring-stroke-error cgui:aria-invalid:border-stroke-error',
24
24
  ],
@@ -1,8 +1,7 @@
1
1
  <script lang="ts">
2
- import { boxWith, mergeProps } from 'svelte-toolbelt';
3
-
4
- import { NavigationStylesContext } from '../styles.js';
5
2
  import { cn, useId } from '../../../internal/utils/common.js';
3
+ import { boxWith, mergeProps } from 'svelte-toolbelt';
4
+ import { navigationContentStyles } from '../styles.js';
6
5
  import type { NavigationContentProps } from '../types.js';
7
6
  import { NavigationContentState } from './navigation.svelte.js';
8
7
 
@@ -26,7 +25,7 @@
26
25
  });
27
26
 
28
27
  const mergedProps = $derived(
29
- mergeProps(restProps, contentState.props, { class: cn(NavigationStylesContext.get().current.content(), className) })
28
+ mergeProps(restProps, contentState.props, { class: cn(navigationContentStyles(), className) })
30
29
  );
31
30
  </script>
32
31
 
@@ -1,11 +1,10 @@
1
1
  <script lang="ts">
2
- import { CollapsiblePrimitive } from '../../collapsible/index.js';
3
- import { NavigationStylesContext } from '../styles.js';
4
- import { PopoverPrimitive } from '../../popover/index.js';
2
+ import { DropdownPrimitive } from '../../dropdown/index.js';
5
3
  import { cn, useId } from '../../../internal/utils/common.js';
6
4
  import { boxWith, mergeProps } from 'svelte-toolbelt';
5
+ import { navigationItemStyles } from '../styles.js';
7
6
  import type { NavigationItemProps } from '../types.js';
8
- import { NavigationItemState } from './navigation.svelte.js';
7
+ import { NavigationItemState, NavigationSubStateCtx } from './navigation.svelte.js';
9
8
 
10
9
  const uid = $props.id();
11
10
 
@@ -18,6 +17,10 @@
18
17
  ...restProps
19
18
  }: NavigationItemProps = $props();
20
19
 
20
+ // Check if we're inside a Sub (SubContent context)
21
+ const subState = NavigationSubStateCtx.getOr(null);
22
+ const isInsideSub = $derived(subState !== null);
23
+
21
24
  const itemState = NavigationItemState.create({
22
25
  ref: boxWith(
23
26
  () => ref,
@@ -27,24 +30,23 @@
27
30
  });
28
31
 
29
32
  const mergedProps = $derived(
30
- mergeProps(restProps, itemState.props, { class: cn(NavigationStylesContext.get().current.item(), className) })
33
+ mergeProps(restProps, itemState.props, { class: cn(navigationItemStyles(), className) })
31
34
  );
35
+
36
+ // Should use dropdown item when inside Sub in compact mode
37
+ const useDropdownItem = $derived(isInsideSub && itemState.root.isCompact);
32
38
  </script>
33
39
 
34
40
  {#if child}
35
41
  {@render child({ props: mergedProps })}
36
- {:else if itemState.root.isCompact}
42
+ {:else if useDropdownItem}
43
+ <!-- Inside SubContent in compact mode: use Dropdown.Item -->
44
+ <DropdownPrimitive.Item {...mergedProps}>
45
+ {@render children?.()}
46
+ </DropdownPrimitive.Item>
47
+ {:else}
48
+ <!-- Regular list item -->
37
49
  <li {...mergedProps}>
38
- <PopoverPrimitive.Root>
39
- {@render children?.()}
40
- </PopoverPrimitive.Root>
50
+ {@render children?.()}
41
51
  </li>
42
- {:else}
43
- <CollapsiblePrimitive.Root variant="clean">
44
- {#snippet child({ props: childProps })}
45
- <li {...mergedProps} {...childProps}>
46
- {@render children?.()}
47
- </li>
48
- {/snippet}
49
- </CollapsiblePrimitive.Root>
50
52
  {/if}
@@ -1,11 +1,11 @@
1
1
  <script lang="ts">
2
- import { NavigationStylesContext, navigationVariants } from '../styles.js';
2
+ import { navigationRootStyles } from '../styles.js';
3
3
  import type { NavigationRootProps } from '../types.js';
4
4
 
5
5
  import { NavigationRootState } from './navigation.svelte.js';
6
6
 
7
7
  import { cn, useId } from '../../../internal/utils/common.js';
8
- import { box, mergeProps } from 'svelte-toolbelt';
8
+ import { boxWith, mergeProps } from 'svelte-toolbelt';
9
9
 
10
10
  const uid = $props.id();
11
11
 
@@ -16,25 +16,23 @@
16
16
  children,
17
17
  child,
18
18
  class: className,
19
- popoverProps,
19
+ dropdownProps,
20
20
  ...restProps
21
21
  }: NavigationRootProps = $props();
22
22
 
23
23
  const rootState = NavigationRootState.create({
24
- ref: box.with(
24
+ ref: boxWith(
25
25
  () => ref,
26
26
  (v) => (ref = v)
27
27
  ),
28
- id: box.with(() => id),
29
- compact: box.with(() => compact),
30
- popoverProps: box.with(() => popoverProps),
28
+ id: boxWith(() => id),
29
+ compact: boxWith(() => compact),
30
+ dropdownProps: boxWith(() => dropdownProps),
31
31
  });
32
32
 
33
- const variants = $derived(navigationVariants({ compact }));
34
-
35
- NavigationStylesContext.set(box.with(() => variants));
36
-
37
- const mergedProps = $derived(mergeProps(restProps, rootState.props, { class: cn(variants.root(), className) }));
33
+ const mergedProps = $derived(
34
+ mergeProps(restProps, rootState.props, { class: cn(navigationRootStyles({ compact }), className) })
35
+ );
38
36
  </script>
39
37
 
40
38
  {#if child}
@@ -1,12 +1,11 @@
1
1
  <script lang="ts">
2
- import { boxWith, mergeProps } from 'svelte-toolbelt';
3
-
4
2
  import { CollapsiblePrimitive } from '../../collapsible/index.js';
5
- import { NavigationStylesContext } from '../styles.js';
6
- import { PopoverPrimitive } from '../../popover/index.js';
3
+ import { DropdownPrimitive } from '../../dropdown/index.js';
7
4
  import { cn, useId } from '../../../internal/utils/common.js';
5
+ import { boxWith, mergeProps } from 'svelte-toolbelt';
8
6
  import { cubicInOut } from 'svelte/easing';
9
- import { fade, fly } from 'svelte/transition';
7
+ import { fade } from 'svelte/transition';
8
+ import { navigationDropdownContentStyles, navigationSubContentStyles } from '../styles.js';
10
9
  import type { NavigationSubContentProps } from '../types.js';
11
10
  import { NavigationSubContentState } from './navigation.svelte.js';
12
11
 
@@ -31,39 +30,39 @@
31
30
 
32
31
  const mergedProps = $derived(
33
32
  mergeProps(restProps, subContentState.props, {
34
- class: cn(NavigationStylesContext.get().current.subContent(), className),
33
+ class: cn(navigationSubContentStyles(), className),
35
34
  })
36
35
  );
36
+
37
+ // Safe access to dropdownProps
38
+ const dropdownProps = $derived(subContentState.root.opts.dropdownProps?.current);
37
39
  </script>
38
40
 
39
41
  {#if child}
40
42
  {@render child({ props: mergedProps, compact: subContentState.root.isCompact })}
41
43
  {:else if subContentState.root.isCompact}
42
- <PopoverPrimitive.Portal>
43
- <PopoverPrimitive.Content
44
- side={subContentState.root.opts.popoverProps.current?.side ?? 'right'}
45
- sideOffset={subContentState.root.opts.popoverProps.current?.sideOffset ?? 8}
46
- alignOffset={subContentState.root.opts.popoverProps.current?.alignOffset ?? 0}
47
- forceMount
44
+ <!-- Compact mode: Dropdown with Portal -->
45
+ <DropdownPrimitive.Portal>
46
+ <DropdownPrimitive.Content
47
+ side={dropdownProps?.side ?? 'right'}
48
+ sideOffset={dropdownProps?.sideOffset ?? 8}
49
+ alignOffset={dropdownProps?.alignOffset ?? 0}
50
+ variant="clean"
51
+ w="auto"
52
+ gap="clean"
53
+ rounded="clean"
54
+ class={cn(navigationDropdownContentStyles())}
48
55
  >
49
- {#snippet child({ props: childProps, wrapperProps, open })}
50
- {@const popoverProps = mergeProps(childProps, mergedProps)}
51
- {#if open}
52
- <div {...wrapperProps}>
53
- <ol {...popoverProps} transition:fly={{ duration: 250, easing: cubicInOut, x: 10 }}>
54
- {@render children?.({ compact: subContentState.root.isCompact })}
55
- </ol>
56
- </div>
57
- {/if}
58
- {/snippet}
59
- </PopoverPrimitive.Content>
60
- </PopoverPrimitive.Portal>
56
+ <ol {...mergedProps}>
57
+ {@render children?.({ compact: subContentState.root.isCompact })}
58
+ </ol>
59
+ </DropdownPrimitive.Content>
60
+ </DropdownPrimitive.Portal>
61
61
  {:else}
62
- <CollapsiblePrimitive.Content {...mergedProps}>
63
- {#snippet child({ props: childProps, open })}
64
- {@const collapsibleProps = mergeProps(childProps, mergedProps)}
62
+ <CollapsiblePrimitive.Content>
63
+ {#snippet child({ props: collapsibleProps, open })}
65
64
  {#if open}
66
- <ol {...collapsibleProps} transition:fade={{ duration: 250, easing: cubicInOut }}>
65
+ <ol {...collapsibleProps} {...mergedProps} transition:fade={{ duration: 250, easing: cubicInOut }}>
67
66
  {@render children?.({ compact: subContentState.root.isCompact })}
68
67
  </ol>
69
68
  {/if}
@@ -0,0 +1,107 @@
1
+ <script lang="ts">
2
+ import { CollapsiblePrimitive } from '../../collapsible/index.js';
3
+ import { DropdownPrimitive } from '../../dropdown/index.js';
4
+ import ChevronDown from '../../icons/chevron-down.svelte';
5
+ import { cn, useId } from '../../../internal/utils/common.js';
6
+ import { boxWith, mergeProps } from 'svelte-toolbelt';
7
+ import { cubicInOut } from 'svelte/easing';
8
+ import { slide } from 'svelte/transition';
9
+ import { navigationSubTriggerStyles } from '../styles.js';
10
+ import type { NavigationSubTriggerProps } from '../types.js';
11
+ import { NavigationSubTriggerState } from './navigation.svelte.js';
12
+
13
+ const uid = $props.id();
14
+
15
+ let {
16
+ ref = $bindable(null),
17
+ id = useId(uid),
18
+ child,
19
+ icon,
20
+ label,
21
+ class: className,
22
+ disabled = false,
23
+ ...restProps
24
+ }: NavigationSubTriggerProps = $props();
25
+
26
+ const subTriggerState = NavigationSubTriggerState.create({
27
+ ref: boxWith(
28
+ () => ref,
29
+ (v) => (ref = v)
30
+ ),
31
+ id: boxWith(() => id),
32
+ disabled: boxWith(() => disabled),
33
+ });
34
+
35
+ const mergedProps = $derived(
36
+ mergeProps(restProps, subTriggerState.props, {
37
+ class: cn(navigationSubTriggerStyles(), className),
38
+ })
39
+ );
40
+
41
+ const attrs = $derived({
42
+ compact: subTriggerState.root.isCompact,
43
+ open: subTriggerState.sub.isOpen,
44
+ });
45
+ </script>
46
+
47
+ {#snippet content()}
48
+ {#if icon}
49
+ <span
50
+ data-slot="icon"
51
+ class={cn('cgui:inline-flex cgui:items-center cgui:justify-center cgui:shrink-0 cgui:empty:hidden')}
52
+ >
53
+ {@render icon?.()}
54
+ </span>
55
+ {/if}
56
+
57
+ {#if label}
58
+ {#if typeof label === 'string'}
59
+ {#if !subTriggerState.root.isCompact}
60
+ <span
61
+ data-slot="label"
62
+ class="cgui:min-w-0 cgui:text-left cgui:whitespace-nowrap cgui:overflow-hidden cgui:flex-1"
63
+ transition:slide={{ axis: 'x', duration: 250, easing: cubicInOut }}
64
+ >
65
+ <span class="cgui:inline-block" transition:slide={{ axis: 'x', duration: 150, easing: cubicInOut }}>
66
+ {label}
67
+ </span>
68
+ </span>
69
+ {/if}
70
+ {:else}
71
+ {@render label?.({ props: { 'data-slot': 'label' } })}
72
+ {/if}
73
+ {/if}
74
+ {/snippet}
75
+
76
+ {#snippet chevron()}
77
+ <span
78
+ data-slot="chevron"
79
+ class={cn(
80
+ 'cgui:flex cgui:items-center cgui:justify-center cgui:shrink-0',
81
+ 'cgui:transition-transform cgui:duration-250 cgui:ease-in-out'
82
+ )}
83
+ >
84
+ <ChevronDown width={24} height={24} />
85
+ </span>
86
+ {/snippet}
87
+
88
+ {#if child}
89
+ {@render child({ props: mergedProps, ...attrs })}
90
+ {:else if subTriggerState.root.isCompact}
91
+ <DropdownPrimitive.Trigger>
92
+ {#snippet child({ props: dropdownProps })}
93
+ <button {...dropdownProps} {...mergedProps}>
94
+ {@render content?.()}
95
+ </button>
96
+ {/snippet}
97
+ </DropdownPrimitive.Trigger>
98
+ {:else}
99
+ <CollapsiblePrimitive.Trigger>
100
+ {#snippet child({ props: collapsibleProps })}
101
+ <button {...collapsibleProps} {...mergedProps}>
102
+ {@render content?.()}
103
+ {@render chevron()}
104
+ </button>
105
+ {/snippet}
106
+ </CollapsiblePrimitive.Trigger>
107
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { NavigationSubTriggerProps } from '../types.js';
2
+ declare const Navigation: import("svelte").Component<NavigationSubTriggerProps, {}, "ref">;
3
+ type Navigation = ReturnType<typeof Navigation>;
4
+ export default Navigation;
@@ -0,0 +1,55 @@
1
+ <script lang="ts">
2
+ import { CollapsiblePrimitive } from '../../collapsible/index.js';
3
+ import { DropdownPrimitive } from '../../dropdown/index.js';
4
+ import { cn, useId } from '../../../internal/utils/common.js';
5
+ import { boxWith, mergeProps } from 'svelte-toolbelt';
6
+ import { navigationSubStyles } from '../styles.js';
7
+ import type { NavigationSubProps } from '../types.js';
8
+ import { NavigationSubState } from './navigation.svelte.js';
9
+
10
+ const uid = $props.id();
11
+
12
+ let {
13
+ ref = $bindable(null),
14
+ id = useId(uid),
15
+ open = $bindable(false),
16
+ children,
17
+ child,
18
+ class: className,
19
+ ...restProps
20
+ }: NavigationSubProps = $props();
21
+
22
+ const subState = NavigationSubState.create({
23
+ ref: boxWith(
24
+ () => ref,
25
+ (v) => (ref = v)
26
+ ),
27
+ id: boxWith(() => id),
28
+ open: boxWith(
29
+ () => open,
30
+ (v) => (open = v)
31
+ ),
32
+ });
33
+
34
+ const mergedProps = $derived(mergeProps(restProps, subState.props, { class: cn(navigationSubStyles(), className) }));
35
+ </script>
36
+
37
+ {#if child}
38
+ {@render child({ props: mergedProps, open })}
39
+ {:else if subState.root.isCompact}
40
+ <!-- Compact mode: use Dropdown -->
41
+ <DropdownPrimitive.Root bind:open>
42
+ <li {...mergedProps}>
43
+ {@render children?.({ open })}
44
+ </li>
45
+ </DropdownPrimitive.Root>
46
+ {:else}
47
+ <!-- Expanded mode: use Collapsible -->
48
+ <CollapsiblePrimitive.Root bind:open variant="clean">
49
+ {#snippet child({ props: collapsibleProps })}
50
+ <li {...mergedProps} {...collapsibleProps}>
51
+ {@render children?.({ open })}
52
+ </li>
53
+ {/snippet}
54
+ </CollapsiblePrimitive.Root>
55
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { NavigationSubProps } from '../types.js';
2
+ declare const Navigation: import("svelte").Component<NavigationSubProps, {}, "ref" | "open">;
3
+ type Navigation = ReturnType<typeof Navigation>;
4
+ export default Navigation;