noph-ui 0.49.0 → 0.50.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 (103) hide show
  1. package/dist/app-bar/AppBar.svelte +4 -4
  2. package/dist/autocomplete/AutoComplete.svelte +3 -4
  3. package/dist/autocomplete/types.d.ts +3 -3
  4. package/dist/badge/Badge.svelte +1 -1
  5. package/dist/button/Button.svelte +3 -3
  6. package/dist/button/ButtonGroup.svelte +2 -2
  7. package/dist/button/IconButton.svelte +3 -3
  8. package/dist/button/SegmentedButton.svelte +6 -5
  9. package/dist/button/SplitButton.svelte +1 -1
  10. package/dist/button/types.d.ts +13 -11
  11. package/dist/card/Card.svelte +16 -7
  12. package/dist/card/types.d.ts +4 -4
  13. package/dist/carousel/Carousel.svelte +11 -11
  14. package/dist/carousel/CarouselItem.svelte +24 -15
  15. package/dist/carousel/carouselMorph.js +1 -1
  16. package/dist/carousel/types.d.ts +5 -4
  17. package/dist/checkbox/Checkbox.svelte +1 -1
  18. package/dist/checkbox/types.d.ts +2 -3
  19. package/dist/chip/AssistChip.svelte +1 -1
  20. package/dist/chip/ChipSet.svelte +1 -1
  21. package/dist/chip/FilterChip.svelte +1 -1
  22. package/dist/chip/InputChip.svelte +1 -1
  23. package/dist/chip/SuggestionChip.svelte +1 -1
  24. package/dist/chip/types.d.ts +5 -8
  25. package/dist/date-picker/Calendar.svelte +8 -7
  26. package/dist/date-picker/DatePickerDialog.svelte +1 -1
  27. package/dist/date-picker/DateRangePicker.svelte +1 -1
  28. package/dist/date-picker/DockedDatePicker.svelte +1 -1
  29. package/dist/date-picker/DockedDateTimePicker.svelte +1 -1
  30. package/dist/date-picker/SelectionList.svelte +2 -2
  31. package/dist/date-picker/SelectionList.svelte.d.ts +1 -1
  32. package/dist/date-picker/TimeColumn.svelte +2 -2
  33. package/dist/date-picker/TimeColumn.svelte.d.ts +1 -1
  34. package/dist/date-picker/YearGrid.svelte +1 -1
  35. package/dist/date-picker/internalTypes.d.ts +7 -0
  36. package/dist/date-picker/internalTypes.js +1 -0
  37. package/dist/date-picker/types.d.ts +10 -44
  38. package/dist/dialog/Dialog.svelte +1 -1
  39. package/dist/divider/Divider.svelte +1 -1
  40. package/dist/fab/ExtendedFab.svelte +4 -4
  41. package/dist/fab/Fab.svelte +4 -4
  42. package/dist/fab/FabMenu.svelte +2 -2
  43. package/dist/icons/Icon.svelte +1 -1
  44. package/dist/internal/elementTag.d.ts +26 -0
  45. package/dist/internal/elementTag.js +23 -0
  46. package/dist/internal/fieldTypes.d.ts +24 -0
  47. package/dist/internal/fieldTypes.js +1 -0
  48. package/dist/list/Item.svelte +14 -6
  49. package/dist/list/List.svelte +1 -1
  50. package/dist/list/ListItem.svelte +1 -1
  51. package/dist/list/types.d.ts +7 -6
  52. package/dist/loading-indicator/LoadingIndicator.svelte +2 -2
  53. package/dist/menu/Menu.svelte +1 -1
  54. package/dist/menu/MenuItem.svelte +8 -4
  55. package/dist/navigation-bar/NavigationBar.svelte +1 -1
  56. package/dist/navigation-bar/NavigationBarItem.svelte +3 -3
  57. package/dist/navigation-drawer/NavigationDrawer.svelte +9 -7
  58. package/dist/navigation-drawer/NavigationDrawerItem.svelte +2 -2
  59. package/dist/navigation-drawer/types.d.ts +6 -2
  60. package/dist/navigation-rail/NavigationRail.svelte +1 -1
  61. package/dist/navigation-rail/NavigationRailItem.svelte +2 -2
  62. package/dist/progress/CircularProgress.svelte +1 -1
  63. package/dist/progress/LinearProgress.svelte +1 -1
  64. package/dist/radio/Radio.svelte +1 -1
  65. package/dist/radio/types.d.ts +2 -3
  66. package/dist/ripple/Ripple.svelte +1 -1
  67. package/dist/search/Search.svelte +2 -2
  68. package/dist/select/NativeSelect.svelte +2 -2
  69. package/dist/select/Option.svelte +1 -1
  70. package/dist/select/Select.svelte +7 -4
  71. package/dist/select/types.d.ts +4 -8
  72. package/dist/shared/types.d.ts +9 -0
  73. package/dist/shared/types.js +1 -0
  74. package/dist/sheet/Sheet.svelte +1 -1
  75. package/dist/slider/Slider.svelte +1 -1
  76. package/dist/slider/types.d.ts +2 -4
  77. package/dist/snackbar/Snackbar.svelte +1 -1
  78. package/dist/switch/Switch.svelte +1 -1
  79. package/dist/switch/types.d.ts +2 -4
  80. package/dist/tabs/Tab.svelte +1 -1
  81. package/dist/tabs/Tabs.svelte +2 -2
  82. package/dist/text-field/TextField.svelte +1 -1
  83. package/dist/text-field/types.d.ts +1 -21
  84. package/dist/time-picker/ClockDial.svelte +3 -3
  85. package/dist/time-picker/DockedTimePicker.svelte +1 -1
  86. package/dist/time-picker/PeriodSelector.svelte +2 -2
  87. package/dist/time-picker/PeriodSelector.svelte.d.ts +1 -1
  88. package/dist/time-picker/TimeInputs.svelte +1 -1
  89. package/dist/time-picker/TimeInputs.svelte.d.ts +1 -1
  90. package/dist/time-picker/TimePickerDialog.svelte +1 -1
  91. package/dist/time-picker/TimePickerPanel.svelte +1 -1
  92. package/dist/time-picker/TimePickerPanel.svelte.d.ts +1 -1
  93. package/dist/time-picker/TimeSelectors.svelte +2 -2
  94. package/dist/time-picker/TimeSelectors.svelte.d.ts +1 -1
  95. package/dist/time-picker/internalTypes.d.ts +76 -0
  96. package/dist/time-picker/internalTypes.js +1 -0
  97. package/dist/time-picker/types.d.ts +7 -95
  98. package/dist/toolbar/Toolbar.svelte +2 -2
  99. package/dist/tooltip/RichTooltip.svelte +1 -1
  100. package/dist/tooltip/Tooltip.svelte +1 -1
  101. package/dist/types.d.ts +1 -0
  102. package/dist/types.js +34 -33
  103. package/package.json +49 -49
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import type { AppBarProps } from './types.js'
2
+ import type { AppBarProps } from './types.ts'
3
3
 
4
4
  let {
5
5
  variant = 'small',
@@ -15,9 +15,9 @@
15
15
  ...attributes
16
16
  }: AppBarProps = $props()
17
17
 
18
- const twoLine = $derived(variant === 'medium' || variant === 'large')
19
- const isSearch = $derived(variant === 'search')
20
- const collapses = $derived(collapsible && twoLine)
18
+ let twoLine = $derived(variant === 'medium' || variant === 'large')
19
+ let isSearch = $derived(variant === 'search')
20
+ let collapses = $derived(collapsible && twoLine)
21
21
  </script>
22
22
 
23
23
  {#snippet titles(inline: boolean)}
@@ -3,7 +3,7 @@
3
3
  import Menu from '../menu/Menu.svelte'
4
4
  import VirtualList from '../select/VirtualList.svelte'
5
5
  import TextField from '../text-field/TextField.svelte'
6
- import type { AutoCompleteOption, AutoCompleteProps } from './types.js'
6
+ import type { AutoCompleteOption, AutoCompleteProps } from './types.ts'
7
7
 
8
8
  let {
9
9
  options = [],
@@ -28,8 +28,8 @@
28
28
  }: AutoCompleteProps = $props()
29
29
 
30
30
  const uid = $props.id()
31
- const query = $derived(value ? `${value}`.toLocaleLowerCase() : '')
32
- const filterFn = $derived(
31
+ let query = $derived(value ? `${value}`.toLocaleLowerCase() : '')
32
+ let filterFn = $derived(
33
33
  optionsFilter ||
34
34
  ((option: AutoCompleteOption) => !query || option.label.toLocaleLowerCase().includes(query)),
35
35
  )
@@ -121,7 +121,6 @@
121
121
  setActive(index)
122
122
  selectOption(option)
123
123
  }}
124
- variant="button"
125
124
  start={option.start}
126
125
  end={option.end}
127
126
  supportingText={option.supportingText}
@@ -1,8 +1,8 @@
1
- import type { ItemProps } from '../list/types.js';
1
+ import type { BaseOption } from '../shared/types.js';
2
2
  import type { TextFieldProps } from '../types.js';
3
- export interface AutoCompleteOption extends Pick<ItemProps, 'start' | 'end' | 'supportingText' | 'class' | 'style'> {
3
+ export interface AutoCompleteOption extends BaseOption {
4
+ /** Falls back to `label`. */
4
5
  value?: string | number;
5
- label: string;
6
6
  }
7
7
  export interface AutoCompleteProps extends Omit<TextFieldProps, 'clientWidth' | 'clientHeight'> {
8
8
  options: AutoCompleteOption[];
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import type { BadgeProps } from './types.js'
2
+ import type { BadgeProps } from './types.ts'
3
3
 
4
4
  let {
5
5
  label,
@@ -5,7 +5,7 @@
5
5
  import Ripple from '../ripple/Ripple.svelte'
6
6
  import Tooltip from '../tooltip/Tooltip.svelte'
7
7
  import type { HTMLButtonAttributes } from 'svelte/elements'
8
- import type { ButtonProps } from './types.js'
8
+ import type { ButtonProps } from './types.ts'
9
9
 
10
10
  let {
11
11
  variant = 'outlined',
@@ -26,9 +26,9 @@
26
26
 
27
27
  const uid = $props.id()
28
28
 
29
- const isLink = $derived(attributes.href != null && !disabled && !loading)
29
+ let isLink = $derived(attributes.href != null && !disabled && !loading)
30
30
 
31
- const tooltipId = $derived(title && !disabled && !loading ? uid : undefined)
31
+ let tooltipId = $derived(title && !disabled && !loading ? uid : undefined)
32
32
 
33
33
  const morph = pressMorph()
34
34
 
@@ -1,8 +1,8 @@
1
1
  <script lang="ts">
2
2
  import { reducedMotion } from '../media.js'
3
3
  import { onMount } from 'svelte'
4
- import { expandedWidths, parseMotion, resolveItem } from './buttonGroup.js'
5
- import type { ButtonGroupProps } from './types.js'
4
+ import { expandedWidths, parseMotion, resolveItem } from './buttonGroup.ts'
5
+ import type { ButtonGroupProps } from './types.ts'
6
6
 
7
7
  let {
8
8
  variant = 'standard',
@@ -5,7 +5,7 @@
5
5
  import Ripple from '../ripple/Ripple.svelte'
6
6
  import Tooltip from '../tooltip/Tooltip.svelte'
7
7
  import type { HTMLButtonAttributes } from 'svelte/elements'
8
- import type { IconButtonProps } from './types.js'
8
+ import type { IconButtonProps } from './types.ts'
9
9
 
10
10
  let {
11
11
  variant = 'text',
@@ -26,8 +26,8 @@
26
26
 
27
27
  const uid = $props.id()
28
28
 
29
- const isLink = $derived(attributes.href != null && !disabled && !loading)
30
- const tooltipId = $derived(title && !disabled && !loading ? uid : undefined)
29
+ let isLink = $derived(attributes.href != null && !disabled && !loading)
30
+ let tooltipId = $derived(title && !disabled && !loading ? uid : undefined)
31
31
 
32
32
  const morph = pressMorph()
33
33
 
@@ -2,7 +2,7 @@
2
2
  import '../internal/focus-ring.css'
3
3
  import CheckIcon from '../icons/CheckIcon.svelte'
4
4
  import Ripple from '../ripple/Ripple.svelte'
5
- import type { SegmentedButtonProps } from './types.js'
5
+ import type { SegmentedButtonProps } from './types.ts'
6
6
 
7
7
  let {
8
8
  name,
@@ -24,7 +24,8 @@
24
24
  style="{attributes.style};grid-template-columns: repeat({options.length}, minmax(max-content, 1fr));"
25
25
  >
26
26
  {#each options as option, i (i)}
27
- {@const optionLabel = option.label ?? `${name}-${i}`}
27
+ {let optionLabel = $derived(option.label ?? `${name}-${i}`)}
28
+ {let optionValue = $derived(option.value ?? optionLabel)}
28
29
  <label class={['np-segmented-button', option.icon && 'width-icon']}>
29
30
  <div class="check-icon-wrapper">
30
31
  <div class="check-icon">
@@ -56,7 +57,7 @@
56
57
  bind:group
57
58
  {name}
58
59
  aria-label={optionLabel}
59
- value={optionLabel}
60
+ value={optionValue}
60
61
  disabled={option.disabled}
61
62
  checked={option.selected}
62
63
  />
@@ -67,7 +68,7 @@
67
68
  bind:group
68
69
  {name}
69
70
  aria-label={optionLabel}
70
- value={optionLabel}
71
+ value={optionValue}
71
72
  disabled={option.disabled}
72
73
  checked={option.selected}
73
74
  />
@@ -78,7 +79,7 @@
78
79
  onclick={option.onclick}
79
80
  {name}
80
81
  aria-label={optionLabel}
81
- value={optionLabel}
82
+ value={optionValue}
82
83
  disabled={option.disabled}
83
84
  checked={option.selected}
84
85
  />
@@ -3,7 +3,7 @@
3
3
  import Menu from '../menu/Menu.svelte'
4
4
  import Button from './Button.svelte'
5
5
  import ButtonGroup from './ButtonGroup.svelte'
6
- import type { SplitButtonProps } from './types.js'
6
+ import type { SplitButtonProps } from './types.ts'
7
7
 
8
8
  let {
9
9
  label = '',
@@ -1,3 +1,4 @@
1
+ import type { Issue } from '../shared/types.js';
1
2
  import type { Snippet } from 'svelte';
2
3
  import type { HTMLAnchorAttributes, HTMLAttributes, HTMLButtonAttributes, MouseEventHandler } from 'svelte/elements';
3
4
  export type ButtonElement = HTMLButtonElement | HTMLAnchorElement;
@@ -40,20 +41,21 @@ export interface SplitButtonProps extends Omit<HTMLAttributes<HTMLDivElement>, '
40
41
  onclick?: MouseEventHandler<ButtonElement>;
41
42
  element?: HTMLElement;
42
43
  }
44
+ export interface SegmentedButtonOption {
45
+ /** Stored in `group` and submitted with the form. Falls back to `label`. */
46
+ value?: string | number;
47
+ label?: string;
48
+ labelIcon?: Snippet;
49
+ selected?: boolean;
50
+ disabled?: boolean | null;
51
+ icon?: Snippet;
52
+ onclick?: (event: Event) => void;
53
+ }
43
54
  export interface SegmentedButtonProps extends HTMLAttributes<HTMLDivElement> {
44
55
  name: string;
45
56
  multiSelect?: boolean;
46
- options: {
47
- label?: string;
48
- labelIcon?: Snippet;
49
- selected?: boolean;
50
- disabled?: boolean;
51
- icon?: Snippet;
52
- onclick?: (event: Event) => void;
53
- }[];
57
+ options: SegmentedButtonOption[];
54
58
  group?: string | number | (string | number)[] | null;
55
59
  element?: HTMLElement;
56
- issues?: {
57
- message: string;
58
- }[];
60
+ issues?: Issue[];
59
61
  }
@@ -1,10 +1,12 @@
1
1
  <script lang="ts">
2
2
  import '../internal/focus-ring.css'
3
+ import { buttonType, elementTag } from '../internal/elementTag.js'
3
4
  import Ripple from '../ripple/Ripple.svelte'
4
- import type { CardProps } from './types.js'
5
+ import type { CardProps } from './types.ts'
5
6
 
6
7
  let {
7
8
  image,
9
+ imageAlt,
8
10
  variant = 'outlined',
9
11
  disabled = false,
10
12
  element = $bindable(),
@@ -16,11 +18,18 @@
16
18
  type,
17
19
  ...attributes
18
20
  }: CardProps = $props()
21
+
22
+ let tag = $derived(elementTag(attributes, type))
19
23
  </script>
20
24
 
21
25
  {#snippet content()}
22
26
  {#if image}
23
- <div class="np-card-image" style="background-image: url({image})"></div>
27
+ <div
28
+ class="np-card-image"
29
+ style="background-image: url({image})"
30
+ role={imageAlt ? 'img' : undefined}
31
+ aria-label={imageAlt || undefined}
32
+ ></div>
24
33
  {/if}
25
34
  <div class="np-card-content">
26
35
  {#if headline}
@@ -45,12 +54,12 @@
45
54
  <div class="np-card-action">{@render action()}</div>
46
55
  {/if}
47
56
  </div>
48
- {#if !disabled && type !== 'text'}
57
+ {#if !disabled && tag !== 'div'}
49
58
  <Ripple />
50
59
  {/if}
51
60
  {/snippet}
52
61
 
53
- {#if type === 'text'}
62
+ {#if tag === 'div'}
54
63
  <div
55
64
  {...attributes}
56
65
  bind:this={element}
@@ -64,11 +73,11 @@
64
73
  >
65
74
  {@render content()}
66
75
  </div>
67
- {:else if type === 'button'}
76
+ {:else if tag === 'button'}
68
77
  <button
69
78
  {...attributes}
70
79
  aria-disabled={disabled}
71
- type="button"
80
+ type={buttonType(type)}
72
81
  bind:this={element}
73
82
  {disabled}
74
83
  class={[
@@ -80,7 +89,7 @@
80
89
  >
81
90
  {@render content()}
82
91
  </button>
83
- {:else if type === 'link'}
92
+ {:else}
84
93
  <a
85
94
  {...attributes}
86
95
  bind:this={element}
@@ -1,14 +1,14 @@
1
1
  import type { Snippet } from 'svelte';
2
- import type { HTMLAnchorAttributes, HTMLAttributes, HTMLButtonAttributes } from 'svelte/elements';
2
+ import type { ElementKindProps } from '../internal/elementTag.js';
3
3
  export type CardElement = HTMLDivElement | HTMLButtonElement | HTMLAnchorElement;
4
- export interface CardProps extends HTMLAttributes<CardElement>, Omit<HTMLButtonAttributes, keyof HTMLAttributes<HTMLButtonElement> | 'type'>, Omit<HTMLAnchorAttributes, keyof HTMLAttributes<HTMLAnchorElement> | 'type'> {
4
+ export interface CardProps extends ElementKindProps<CardElement> {
5
5
  variant?: 'elevated' | 'filled' | 'outlined';
6
- disabled?: boolean | null;
7
6
  image?: string | null;
7
+ /** Describes `image` for assistive technology. Leave it out for a decorative image. */
8
+ imageAlt?: string;
8
9
  element?: HTMLElement;
9
10
  headline?: string | null;
10
11
  subhead?: string | null;
11
12
  supportingText?: string | null;
12
13
  action?: Snippet<[]>;
13
- type: 'text' | 'button' | 'link';
14
14
  }
@@ -2,9 +2,9 @@
2
2
  import { arrowKeyNav } from '../keyboard-nav.js'
3
3
  import { reducedMotion } from '../media.js'
4
4
  import type { Attachment } from 'svelte/attachments'
5
- import { carouselMorph, scrollTimelines } from './carouselMorph.js'
5
+ import { carouselMorph, scrollTimelines } from './carouselMorph.ts'
6
6
  import { setCarouselContext } from './context.js'
7
- import type { CarouselContext, CarouselItemElement, CarouselProps } from './types.js'
7
+ import type { CarouselContext, CarouselItemElement, CarouselProps } from './types.ts'
8
8
 
9
9
  let {
10
10
  variant = 'multi-browse',
@@ -26,14 +26,14 @@
26
26
  let snapPoints = $state<HTMLDivElement>()
27
27
  let items = $state.raw<CarouselItemElement[]>([])
28
28
 
29
- const axis = $derived(orientation ?? (variant === 'full-screen' ? 'vertical' : 'horizontal'))
30
- const vertical = $derived(axis === 'vertical')
31
- const snapping = $derived(snap ?? variant !== 'uncontained')
29
+ let axis = $derived(orientation ?? (variant === 'full-screen' ? 'vertical' : 'horizontal'))
30
+ let vertical = $derived(axis === 'vertical')
31
+ let snapping = $derived(snap ?? variant !== 'uncontained')
32
32
 
33
- const keylined = $derived(variant === 'multi-browse' || variant === 'hero' ? variant : undefined)
34
- const morphing = $derived(!!keylined && scrollTimelines && !reducedMotion.current)
33
+ let keylined = $derived(variant === 'multi-browse' || variant === 'hero' ? variant : undefined)
34
+ let morphing = $derived(!!keylined && scrollTimelines && !reducedMotion.current)
35
35
 
36
- const cropping = $derived(variant === 'uncontained' && !reducedMotion.current)
36
+ let cropping = $derived(variant === 'uncontained' && !reducedMotion.current)
37
37
 
38
38
  const collectItems: Attachment<HTMLElement> = (node) => {
39
39
  const read = () => {
@@ -56,13 +56,13 @@
56
56
  return () => observer.disconnect()
57
57
  }
58
58
 
59
- const morph = $derived(
59
+ let morph = $derived(
60
60
  morphing && keylined
61
61
  ? carouselMorph({ variant: keylined, alignment, vertical, items, track, metrics, uid })
62
62
  : undefined,
63
63
  )
64
64
 
65
- const arrowHandler = $derived(arrowKeyNav('.np-carousel-item', axis, { wrap: false }))
65
+ let arrowHandler = $derived(arrowKeyNav('.np-carousel-item', axis, { wrap: false }))
66
66
 
67
67
  const handleKeydown = (
68
68
  event: KeyboardEvent & { currentTarget: EventTarget & HTMLDivElement },
@@ -71,7 +71,7 @@
71
71
  if (!event.defaultPrevented) arrowHandler(event)
72
72
  }
73
73
 
74
- const places = $derived(new Map(items.map((item, index) => [item, index + 1])))
74
+ let places = $derived(new Map(items.map((item, index) => [item, index + 1])))
75
75
 
76
76
  const handleFocusIn = (event: FocusEvent) => {
77
77
  const item = (event.target as HTMLElement | null)?.closest<HTMLElement>('.np-carousel-item')
@@ -1,15 +1,17 @@
1
1
  <script lang="ts">
2
2
  import '../internal/focus-ring.css'
3
3
  import { pressMorph } from '../press.svelte.js'
4
+ import { buttonType, elementTag } from '../internal/elementTag.js'
4
5
  import Ripple from '../ripple/Ripple.svelte'
5
- import { minVisibleFraction } from './carouselStrategy.js'
6
+ import { minVisibleFraction } from './carouselStrategy.ts'
6
7
  import { getCarouselContext } from './context.js'
7
- import type { CarouselItemElement, CarouselItemProps } from './types.js'
8
+ import type { CarouselItemElement, CarouselItemProps } from './types.ts'
8
9
 
9
10
  let {
10
11
  type,
11
12
  label,
12
13
  image,
14
+ imageAlt,
13
15
  aspectRatio,
14
16
  disabled = false,
15
17
  children,
@@ -19,13 +21,15 @@
19
21
  ...attributes
20
22
  }: CarouselItemProps = $props()
21
23
 
24
+ let tag = $derived(elementTag(attributes, type))
25
+
22
26
  const carouselContext = getCarouselContext()
23
27
  const press = pressMorph()
24
28
 
25
- const total = $derived(carouselContext.items.length)
26
- const position = $derived(element ? carouselContext.position(element) : 0)
29
+ let total = $derived(carouselContext.items.length)
30
+ let position = $derived(element ? carouselContext.position(element) : 0)
27
31
 
28
- const itemStyle = $derived(
32
+ let itemStyle = $derived(
29
33
  [
30
34
  `--_visible:${minVisibleFraction(aspectRatio)}`,
31
35
  aspectRatio != null && `--_aspect:${aspectRatio}`,
@@ -35,26 +39,31 @@
35
39
  .join(';'),
36
40
  )
37
41
 
38
- const accessibleName = $derived(
42
+ let accessibleName = $derived(
39
43
  attributes['aria-label'] ??
40
- (type !== 'text' && label && position > 0
44
+ (tag !== 'div' && label && position > 0
41
45
  ? carouselContext.itemLabel(label, position, total)
42
46
  : undefined),
43
47
  )
44
48
 
45
- const labelHidden = $derived(accessibleName !== undefined)
49
+ let labelHidden = $derived(accessibleName !== undefined)
46
50
 
47
51
  const handlePointerdown = (
48
52
  event: PointerEvent & { currentTarget: EventTarget & CarouselItemElement },
49
53
  ) => {
50
54
  onpointerdown?.(event)
51
- if (!disabled && type !== 'text') press.press()
55
+ if (!disabled && tag !== 'div') press.press()
52
56
  }
53
57
  </script>
54
58
 
55
59
  {#snippet content()}
56
60
  {#if image}
57
- <div class="np-carousel-item-image" style="background-image: url({image})"></div>
61
+ <div
62
+ class="np-carousel-item-image"
63
+ style="background-image: url({image})"
64
+ role={imageAlt ? 'img' : undefined}
65
+ aria-label={imageAlt || undefined}
66
+ ></div>
58
67
  {/if}
59
68
  {#if children}
60
69
  {@render children()}
@@ -62,12 +71,12 @@
62
71
  {#if label}
63
72
  <span class="np-carousel-item-label" aria-hidden={labelHidden || undefined}>{label}</span>
64
73
  {/if}
65
- {#if !disabled && type !== 'text'}
74
+ {#if !disabled && tag !== 'div'}
66
75
  <Ripple />
67
76
  {/if}
68
77
  {/snippet}
69
78
 
70
- {#if type === 'text'}
79
+ {#if tag === 'div'}
71
80
  <div
72
81
  {...attributes}
73
82
  bind:this={element}
@@ -83,11 +92,11 @@
83
92
  >
84
93
  {@render content()}
85
94
  </div>
86
- {:else if type === 'button'}
95
+ {:else if tag === 'button'}
87
96
  <button
88
97
  {...attributes}
89
98
  bind:this={element}
90
- type="button"
99
+ type={buttonType(type)}
91
100
  {disabled}
92
101
  aria-disabled={disabled}
93
102
  aria-label={accessibleName}
@@ -103,7 +112,7 @@
103
112
  >
104
113
  {@render content()}
105
114
  </button>
106
- {:else if type === 'link'}
115
+ {:else}
107
116
  <a
108
117
  {...attributes}
109
118
  bind:this={element}
@@ -1,4 +1,4 @@
1
- import { arrange, itemKeyframes, morphTrack, notches } from "./carouselStrategy.js";
1
+ import { arrange, itemKeyframes, morphTrack, notches } from './carouselStrategy.ts';
2
2
  export const scrollTimelines = typeof CSS !== 'undefined' && CSS.supports('animation-timeline', 'scroll(nearest inline)');
3
3
  const px = (value) => `${Math.round(value * 100) / 100}px`;
4
4
  const lengthOf = (value, fallback) => {
@@ -1,5 +1,6 @@
1
1
  import type { Snippet } from 'svelte';
2
- import type { HTMLAnchorAttributes, HTMLAttributes, HTMLButtonAttributes } from 'svelte/elements';
2
+ import type { ElementKindProps } from '../internal/elementTag.js';
3
+ import type { HTMLAttributes } from 'svelte/elements';
3
4
  export type CarouselVariant = 'multi-browse' | 'uncontained' | 'hero' | 'full-screen';
4
5
  export type CarouselAlignment = 'start' | 'center';
5
6
  export type CarouselOrientation = 'horizontal' | 'vertical';
@@ -15,12 +16,12 @@ export interface CarouselProps extends HTMLAttributes<HTMLDivElement> {
15
16
  scroller?: HTMLDivElement;
16
17
  element?: HTMLDivElement;
17
18
  }
18
- export interface CarouselItemProps extends HTMLAttributes<CarouselItemElement>, Omit<HTMLButtonAttributes, keyof HTMLAttributes<HTMLButtonElement> | 'type'>, Omit<HTMLAnchorAttributes, keyof HTMLAttributes<HTMLAnchorElement> | 'type'> {
19
- type: 'text' | 'button' | 'link';
19
+ export interface CarouselItemProps extends ElementKindProps<CarouselItemElement> {
20
20
  label?: string | null;
21
21
  image?: string | null;
22
+ /** Describes `image` for assistive technology. Leave it out for a decorative image. */
23
+ imageAlt?: string;
22
24
  aspectRatio?: number | null;
23
- disabled?: boolean | null;
24
25
  children?: Snippet;
25
26
  element?: CarouselItemElement;
26
27
  }
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import '../internal/focus-ring.css'
3
3
  import Ripple from '../ripple/Ripple.svelte'
4
- import type { CheckboxProps } from './types.js'
4
+ import type { CheckboxProps } from './types.ts'
5
5
 
6
6
  let {
7
7
  indeterminate = $bindable(),
@@ -1,8 +1,7 @@
1
+ import type { Issue } from '../shared/types.js';
1
2
  import type { HTMLInputAttributes } from 'svelte/elements';
2
3
  export interface CheckboxProps extends Omit<HTMLInputAttributes, 'type'> {
3
4
  element?: HTMLElement;
4
5
  group?: (string | number)[] | null;
5
- issues?: {
6
- message: string;
7
- }[];
6
+ issues?: Issue[];
8
7
  }
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import type { AssistChipProps } from './types.js'
2
+ import type { AssistChipProps } from './types.ts'
3
3
  import Button from '../button/Button.svelte'
4
4
 
5
5
  let {
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { arrowKeyNav, rovingTabindex } from '../keyboard-nav.js'
3
- import type { ChipSetProps } from './types.js'
3
+ import type { ChipSetProps } from './types.ts'
4
4
 
5
5
  let { children, element = $bindable(), ...attributes }: ChipSetProps = $props()
6
6
 
@@ -4,7 +4,7 @@
4
4
  import CheckIcon from '../icons/CheckIcon.svelte'
5
5
  import CloseIcon from '../icons/CloseIcon.svelte'
6
6
  import Ripple from '../ripple/Ripple.svelte'
7
- import type { FilterChipProps } from './types.js'
7
+ import type { FilterChipProps } from './types.ts'
8
8
 
9
9
  let {
10
10
  selected = $bindable(),
@@ -3,7 +3,7 @@
3
3
  import IconButton from '../button/IconButton.svelte'
4
4
  import CloseIcon from '../icons/CloseIcon.svelte'
5
5
  import Ripple from '../ripple/Ripple.svelte'
6
- import type { InputChipProps } from './types.js'
6
+ import type { InputChipProps } from './types.ts'
7
7
 
8
8
  let {
9
9
  selected = $bindable(),
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import Button from '../button/Button.svelte'
3
- import type { SuggestionChipProps } from './types.js'
3
+ import type { SuggestionChipProps } from './types.ts'
4
4
 
5
5
  let {
6
6
  variant = 'outlined',
@@ -1,3 +1,4 @@
1
+ import type { Issue } from '../shared/types.js';
1
2
  import type { ButtonElement } from '../button/types.js';
2
3
  import type { Snippet } from 'svelte';
3
4
  import type { HTMLAnchorAttributes, HTMLAttributes, HTMLButtonAttributes, MouseEventHandler } from 'svelte/elements';
@@ -16,7 +17,7 @@ export type SuggestionChipProps = Omit<AssistChipProps, 'icon'>;
16
17
  export interface FilterChipProps extends HTMLAttributes<HTMLDivElement> {
17
18
  selected?: boolean;
18
19
  removable?: boolean;
19
- disabled?: boolean;
20
+ disabled?: boolean | null;
20
21
  variant?: 'outlined' | 'elevated';
21
22
  label?: string;
22
23
  icon?: Snippet;
@@ -27,13 +28,11 @@ export interface FilterChipProps extends HTMLAttributes<HTMLDivElement> {
27
28
  group?: (string | number)[] | null;
28
29
  defaultSelected?: boolean | null;
29
30
  onremove?: MouseEventHandler<ButtonElement>;
30
- issues?: {
31
- message: string;
32
- }[];
31
+ issues?: Issue[];
33
32
  }
34
33
  export interface InputChipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onclick'> {
35
34
  selected?: boolean;
36
- disabled?: boolean;
35
+ disabled?: boolean | null;
37
36
  label?: string;
38
37
  icon?: Snippet;
39
38
  removeAriaLabel?: string;
@@ -43,9 +42,7 @@ export interface InputChipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
43
42
  value?: string | number;
44
43
  onclick?: MouseEventHandler<HTMLButtonElement>;
45
44
  onremove?: MouseEventHandler<ButtonElement>;
46
- issues?: {
47
- message: string;
48
- }[];
45
+ issues?: Issue[];
49
46
  }
50
47
  export interface ChipSetContext {
51
48
  chips: {
@@ -21,7 +21,7 @@
21
21
  today as getToday,
22
22
  } from './dateUtils.js'
23
23
  import { afterTwoFrames } from '../animation.js'
24
- import type { CalendarProps } from './types.js'
24
+ import type { CalendarProps } from './types.ts'
25
25
 
26
26
  let {
27
27
  month,
@@ -212,13 +212,14 @@
212
212
  {#if !inMonth && !adjacentMonthDays}
213
213
  <td role="gridcell" class="np-calendar-cell"></td>
214
214
  {:else}
215
- {@const isSelected =
215
+ {let isSelected = $derived(
216
216
  isSameDay(date, selected) ||
217
- isSameDay(date, rangeStart) ||
218
- isSameDay(date, rangeEnd)}
219
- {@const isToday = isSameDay(date, todayValue)}
220
- {@const enabled = isEnabled(date)}
221
- {@const between = inRange(date)}
217
+ isSameDay(date, rangeStart) ||
218
+ isSameDay(date, rangeEnd),
219
+ )}
220
+ {let isToday = $derived(isSameDay(date, todayValue))}
221
+ {let enabled = $derived(isEnabled(date))}
222
+ {let between = $derived(inRange(date))}
222
223
  <td
223
224
  role="gridcell"
224
225
  aria-selected={isSelected}
@@ -32,7 +32,7 @@
32
32
  toISODate,
33
33
  today as getToday,
34
34
  } from './dateUtils.js'
35
- import type { DatePickerDialogProps, ISODate } from './types.js'
35
+ import type { DatePickerDialogProps, ISODate } from './types.ts'
36
36
 
37
37
  let {
38
38
  value = $bindable(),