@ibobbyts/svelte-ui-utils 0.1.2

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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +379 -0
  3. package/dist/data-table/BaseDataTable.svelte +322 -0
  4. package/dist/data-table/BaseDataTable.svelte.d.ts +49 -0
  5. package/dist/data-table/BaseDataTable.svelte.d.ts.map +1 -0
  6. package/dist/data-table/DataTable.svelte +104 -0
  7. package/dist/data-table/DataTable.svelte.d.ts +59 -0
  8. package/dist/data-table/DataTable.svelte.d.ts.map +1 -0
  9. package/dist/data-table/DateRangeFilter.svelte +174 -0
  10. package/dist/data-table/DateRangeFilter.svelte.d.ts +30 -0
  11. package/dist/data-table/DateRangeFilter.svelte.d.ts.map +1 -0
  12. package/dist/data-table/FilterControl.svelte +184 -0
  13. package/dist/data-table/FilterControl.svelte.d.ts +5 -0
  14. package/dist/data-table/FilterControl.svelte.d.ts.map +1 -0
  15. package/dist/data-table/FilterTable.svelte +25 -0
  16. package/dist/data-table/FilterTable.svelte.d.ts +24 -0
  17. package/dist/data-table/FilterTable.svelte.d.ts.map +1 -0
  18. package/dist/data-table/NumberRangeFilter.svelte +80 -0
  19. package/dist/data-table/NumberRangeFilter.svelte.d.ts +32 -0
  20. package/dist/data-table/NumberRangeFilter.svelte.d.ts.map +1 -0
  21. package/dist/data-table/filter.d.ts +23 -0
  22. package/dist/data-table/filter.d.ts.map +1 -0
  23. package/dist/data-table/filter.js +38 -0
  24. package/dist/data-table/index.d.ts +11 -0
  25. package/dist/data-table/index.d.ts.map +1 -0
  26. package/dist/data-table/index.js +8 -0
  27. package/dist/data-table/state.d.ts +11 -0
  28. package/dist/data-table/state.d.ts.map +1 -0
  29. package/dist/data-table/state.js +58 -0
  30. package/dist/data-table/types.d.ts +167 -0
  31. package/dist/data-table/types.d.ts.map +1 -0
  32. package/dist/data-table/types.js +1 -0
  33. package/dist/dropdown/Dropdown.svelte +159 -0
  34. package/dist/dropdown/Dropdown.svelte.d.ts +28 -0
  35. package/dist/dropdown/Dropdown.svelte.d.ts.map +1 -0
  36. package/dist/dropdown/index.d.ts +3 -0
  37. package/dist/dropdown/index.d.ts.map +1 -0
  38. package/dist/dropdown/index.js +1 -0
  39. package/dist/dropdown/types.d.ts +9 -0
  40. package/dist/dropdown/types.d.ts.map +1 -0
  41. package/dist/dropdown/types.js +1 -0
  42. package/dist/dropdown-search/DropdownSearch.svelte +312 -0
  43. package/dist/dropdown-search/DropdownSearch.svelte.d.ts +51 -0
  44. package/dist/dropdown-search/DropdownSearch.svelte.d.ts.map +1 -0
  45. package/dist/dropdown-search/index.d.ts +6 -0
  46. package/dist/dropdown-search/index.d.ts.map +1 -0
  47. package/dist/dropdown-search/index.js +3 -0
  48. package/dist/dropdown-search/state.d.ts +15 -0
  49. package/dist/dropdown-search/state.d.ts.map +1 -0
  50. package/dist/dropdown-search/state.js +44 -0
  51. package/dist/dropdown-search/types.d.ts +24 -0
  52. package/dist/dropdown-search/types.d.ts.map +1 -0
  53. package/dist/dropdown-search/types.js +1 -0
  54. package/dist/i18n.d.ts +31 -0
  55. package/dist/i18n.d.ts.map +1 -0
  56. package/dist/i18n.js +118 -0
  57. package/dist/index.d.ts +7 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +5 -0
  60. package/dist/pagination/Pagination.svelte +112 -0
  61. package/dist/pagination/Pagination.svelte.d.ts +30 -0
  62. package/dist/pagination/Pagination.svelte.d.ts.map +1 -0
  63. package/dist/pagination/index.d.ts +6 -0
  64. package/dist/pagination/index.d.ts.map +1 -0
  65. package/dist/pagination/index.js +3 -0
  66. package/dist/style.css +1110 -0
  67. package/dist/toast/Toast.svelte +37 -0
  68. package/dist/toast/Toast.svelte.d.ts +26 -0
  69. package/dist/toast/Toast.svelte.d.ts.map +1 -0
  70. package/dist/toast/ToastManager.svelte +29 -0
  71. package/dist/toast/ToastManager.svelte.d.ts +26 -0
  72. package/dist/toast/ToastManager.svelte.d.ts.map +1 -0
  73. package/dist/toast/index.d.ts +7 -0
  74. package/dist/toast/index.d.ts.map +1 -0
  75. package/dist/toast/index.js +4 -0
  76. package/dist/toast/store.d.ts +7 -0
  77. package/dist/toast/store.d.ts.map +1 -0
  78. package/dist/toast/store.js +114 -0
  79. package/dist/toast/types.d.ts +36 -0
  80. package/dist/toast/types.d.ts.map +1 -0
  81. package/dist/toast/types.js +1 -0
  82. package/package.json +83 -0
@@ -0,0 +1,8 @@
1
+ export { default as DataTable } from './DataTable.svelte';
2
+ export { default as DateRangeFilter } from './DateRangeFilter.svelte';
3
+ export { default as FilterTable } from './FilterTable.svelte';
4
+ export { default as NumberRangeFilter } from './NumberRangeFilter.svelte';
5
+ export { default as Pagination } from '../pagination/Pagination.svelte';
6
+ export { filter } from './filter.js';
7
+ export { getUiMessages, resolveUiLanguage, uiLanguages } from '../i18n.js';
8
+ export { getAriaSort, getCellValue, getPageCount, normalizePagination, setDataTableFilters, setDataTablePageSize, setDataTablePagination, setDataTableSort, toggleSort } from './state.js';
@@ -0,0 +1,11 @@
1
+ import type { DataTableColumn, DataTableState, FilterState, PaginationState, SortState } from './types.js';
2
+ export declare function toggleSort(current: SortState | null, columnKey: string): SortState;
3
+ export declare function getAriaSort(sort: SortState | null, columnKey: string): 'none' | 'ascending' | 'descending';
4
+ export declare function getPageCount(totalRows: number, pageSize: number): number;
5
+ export declare function normalizePagination(pagination: PaginationState, totalRows: number): PaginationState;
6
+ export declare function setDataTableSort(state: DataTableState, columnKey: string): DataTableState;
7
+ export declare function setDataTablePagination(state: DataTableState, pagination: PaginationState, totalRows: number): DataTableState;
8
+ export declare function setDataTablePageSize(state: DataTableState, pageSize: number, totalRows: number): DataTableState;
9
+ export declare function setDataTableFilters(state: DataTableState, filters: FilterState): DataTableState;
10
+ export declare function getCellValue<Row = unknown>(row: Row, column: DataTableColumn<Row>): unknown;
11
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/lib/data-table/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE3G,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,CAMlF;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,YAAY,CAM1G;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMxE;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,CAQnG;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CAMzF;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CAK5H;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CAE/G;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,GAAG,cAAc,CAM/F;AAED,wBAAgB,YAAY,CAAC,GAAG,GAAG,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,WAUjF"}
@@ -0,0 +1,58 @@
1
+ export function toggleSort(current, columnKey) {
2
+ if (!current || current.key !== columnKey) {
3
+ return { key: columnKey, direction: 'asc' };
4
+ }
5
+ return { key: columnKey, direction: current.direction === 'asc' ? 'desc' : 'asc' };
6
+ }
7
+ export function getAriaSort(sort, columnKey) {
8
+ if (!sort || sort.key !== columnKey) {
9
+ return 'none';
10
+ }
11
+ return sort.direction === 'asc' ? 'ascending' : 'descending';
12
+ }
13
+ export function getPageCount(totalRows, pageSize) {
14
+ if (pageSize <= 0) {
15
+ return 1;
16
+ }
17
+ return Math.max(1, Math.ceil(Math.max(0, totalRows) / pageSize));
18
+ }
19
+ export function normalizePagination(pagination, totalRows) {
20
+ const pageSize = Math.max(1, pagination.pageSize);
21
+ const pageCount = getPageCount(totalRows, pageSize);
22
+ return {
23
+ pageSize,
24
+ page: Math.min(Math.max(1, pagination.page), pageCount)
25
+ };
26
+ }
27
+ export function setDataTableSort(state, columnKey) {
28
+ return {
29
+ ...state,
30
+ sort: toggleSort(state.sort, columnKey),
31
+ pagination: { ...state.pagination, page: 1 }
32
+ };
33
+ }
34
+ export function setDataTablePagination(state, pagination, totalRows) {
35
+ return {
36
+ ...state,
37
+ pagination: normalizePagination(pagination, totalRows)
38
+ };
39
+ }
40
+ export function setDataTablePageSize(state, pageSize, totalRows) {
41
+ return setDataTablePagination(state, { page: 1, pageSize }, totalRows);
42
+ }
43
+ export function setDataTableFilters(state, filters) {
44
+ return {
45
+ ...state,
46
+ filters,
47
+ pagination: { ...state.pagination, page: 1 }
48
+ };
49
+ }
50
+ export function getCellValue(row, column) {
51
+ if (column.render) {
52
+ return column.render(row, column);
53
+ }
54
+ const value = row && typeof row === 'object' && column.key in row
55
+ ? row[column.key]
56
+ : undefined;
57
+ return value === null || value === undefined ? '' : value;
58
+ }
@@ -0,0 +1,167 @@
1
+ import type { DropdownSearchChangeDetail, DropdownSearchItem, DropdownSearchItemValueGetter, DropdownSearchLoadOptions, DropdownSearchStatus } from '../dropdown-search/types.js';
2
+ import type { DropdownPlacement } from '../dropdown/types.js';
3
+ export type SortDirection = 'asc' | 'desc';
4
+ export type DataTableLayout = 'auto' | 'fixed';
5
+ export interface SortState {
6
+ key: string;
7
+ direction: SortDirection;
8
+ }
9
+ export type DataTableSortChangeHandler = (sort: SortState) => void | Promise<void>;
10
+ export type DataTableStateChangeHandler = (nextState: DataTableState) => void | Promise<void>;
11
+ export interface PaginationState {
12
+ page: number;
13
+ pageSize: number;
14
+ }
15
+ export type PaginationDropdownPlacement = DropdownPlacement;
16
+ export type PaginationChangeHandler = (pagination: PaginationState) => void | Promise<void>;
17
+ export type FilterValue = string | number | boolean | null | undefined | DateRangeFilterValue | NumberRangeFilterValue | Array<string | number> | Record<string, unknown>;
18
+ export type FilterState = Record<string, FilterValue>;
19
+ export interface DataTableState {
20
+ sort: SortState | null;
21
+ pagination: PaginationState;
22
+ filters: FilterState;
23
+ }
24
+ export type DataTableCellValue = unknown;
25
+ export type DataTableClassValue<Row = unknown> = string | undefined | null | ((row: Row, value: DataTableCellValue, column: DataTableColumn<Row>) => string | undefined | null);
26
+ export type DataTableRowKey<Row = unknown> = string | ((row: Row, index: number) => string | number);
27
+ export type DataTableRowAttributes<Row = unknown> = (row: Row, index: number) => Record<string, string | number | boolean | null | undefined>;
28
+ export interface DataTableColumn<Row = unknown> {
29
+ key: string;
30
+ header: string;
31
+ sortable?: boolean;
32
+ align?: 'left' | 'center' | 'right';
33
+ class?: DataTableClassValue<Row>;
34
+ headerClass?: string;
35
+ nowrap?: boolean;
36
+ render?: (row: Row, column: DataTableColumn<Row>) => DataTableCellValue;
37
+ }
38
+ export interface FilterOption {
39
+ label: string;
40
+ value: string | number;
41
+ disabled?: boolean;
42
+ }
43
+ export type FilterActionVariant = 'primary' | 'secondary' | 'outline' | 'ghost';
44
+ export type FilterActionIcon = 'search' | 'qr' | 'x';
45
+ export interface FilterButtonControl {
46
+ type: 'button';
47
+ label?: string;
48
+ ariaLabel?: string;
49
+ icon?: FilterActionIcon;
50
+ variant?: FilterActionVariant;
51
+ disabled?: boolean;
52
+ onClick: () => void | Promise<void>;
53
+ }
54
+ export interface FilterLinkControl {
55
+ type: 'link';
56
+ label: string;
57
+ href: string;
58
+ ariaLabel?: string;
59
+ icon?: FilterActionIcon;
60
+ variant?: FilterActionVariant;
61
+ }
62
+ export interface FilterSelectControl {
63
+ type: 'select';
64
+ value: string | number;
65
+ ariaLabel?: string;
66
+ options: FilterOption[];
67
+ onChange: (value: string) => void | Promise<void>;
68
+ }
69
+ export type DateRangePreset = 'last24Hours' | 'last7Days' | 'last30Days' | 'today' | 'thisWeek' | 'thisMonth' | 'thisYear';
70
+ export interface DateRangeFilterValue {
71
+ startDate: string;
72
+ endDate: string;
73
+ preset: DateRangePreset | null;
74
+ startDateTime?: string;
75
+ endDateTime?: string;
76
+ }
77
+ export interface NumberRangeFilterValue {
78
+ min: number | null;
79
+ max: number | null;
80
+ }
81
+ export interface CheckboxFilterControl {
82
+ type: 'checkbox';
83
+ value: Array<string | number>;
84
+ options: FilterOption[];
85
+ onChange: (value: Array<string | number>) => void | Promise<void>;
86
+ }
87
+ export interface RadioFilterControl {
88
+ type: 'radio';
89
+ value: string | number | null | undefined;
90
+ options: FilterOption[];
91
+ onChange: (value: string | number) => void | Promise<void>;
92
+ }
93
+ export interface DropdownSearchFilterControl {
94
+ type: 'dropdownSearch';
95
+ value: string;
96
+ selectedItem: DropdownSearchItem | null;
97
+ status: DropdownSearchStatus;
98
+ ariaLabel?: string;
99
+ placeholder?: string;
100
+ debounceMs?: number;
101
+ limit?: number;
102
+ minLength?: number;
103
+ noResultsText?: string;
104
+ loadingText?: string;
105
+ clearLabel?: string;
106
+ searchOnExternalValueChange?: boolean;
107
+ width?: string;
108
+ minWidth?: string;
109
+ maxWidth?: string;
110
+ getItemValue?: DropdownSearchItemValueGetter;
111
+ loadOptions: DropdownSearchLoadOptions;
112
+ onChange: (detail: DropdownSearchChangeDetail) => void | Promise<void>;
113
+ }
114
+ export interface DateRangeFilterControl {
115
+ type: 'dateRange';
116
+ value: DateRangeFilterValue;
117
+ startLabel?: string;
118
+ endLabel?: string;
119
+ presetLabels?: Partial<Record<DateRangePreset, string>>;
120
+ now?: () => Date;
121
+ weekStartsOn?: 0 | 1;
122
+ onChange: (value: DateRangeFilterValue) => void | Promise<void>;
123
+ }
124
+ export interface NumberRangeFilterControl {
125
+ type: 'numberRange';
126
+ value: NumberRangeFilterValue;
127
+ minLabel?: string;
128
+ maxLabel?: string;
129
+ prefixLabel?: string;
130
+ min?: number;
131
+ max?: number;
132
+ step?: number | string;
133
+ width?: string;
134
+ onChange: (value: NumberRangeFilterValue) => void | Promise<void>;
135
+ }
136
+ export interface FilterContainerControl {
137
+ type: 'container';
138
+ controls: FilterControl[];
139
+ }
140
+ export type FilterControl = CheckboxFilterControl | RadioFilterControl | DropdownSearchFilterControl | DateRangeFilterControl | NumberRangeFilterControl | FilterButtonControl | FilterLinkControl | FilterSelectControl | FilterContainerControl;
141
+ export interface FilterTableRow {
142
+ key: string;
143
+ title: string;
144
+ filter: FilterControl;
145
+ }
146
+ export type CheckboxFilterDefinition = CheckboxFilterControl & {
147
+ key: string;
148
+ label: string;
149
+ };
150
+ export type RadioFilterDefinition = RadioFilterControl & {
151
+ key: string;
152
+ label: string;
153
+ };
154
+ export type DropdownSearchFilterDefinition = DropdownSearchFilterControl & {
155
+ key: string;
156
+ label: string;
157
+ };
158
+ export type DateRangeFilterDefinition = DateRangeFilterControl & {
159
+ key: string;
160
+ label: string;
161
+ };
162
+ export type NumberRangeFilterDefinition = NumberRangeFilterControl & {
163
+ key: string;
164
+ label: string;
165
+ };
166
+ export type FilterDefinition = CheckboxFilterDefinition | RadioFilterDefinition | DropdownSearchFilterDefinition | DateRangeFilterDefinition | NumberRangeFilterDefinition;
167
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/data-table/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,159 @@
1
+ <script lang="ts">
2
+ import type { DropdownChangeHandler, DropdownOption, DropdownPlacement, DropdownValue } from './types.js';
3
+
4
+ export let id: string | undefined = undefined;
5
+ export let value: DropdownValue = '';
6
+ export let options: DropdownOption[] = [];
7
+ export let ariaLabel: string | undefined = undefined;
8
+ export let placement: DropdownPlacement = 'down';
9
+ export let disabled = false;
10
+ export let onChange: DropdownChangeHandler | undefined = undefined;
11
+
12
+ let open = false;
13
+ let activeValue: DropdownValue = value;
14
+ let buttonElement: HTMLButtonElement | undefined;
15
+
16
+ $: selectedOption = options.find((option) => option.value === value);
17
+ $: selectedText = selectedOption?.label ?? String(value);
18
+ $: if (!open) {
19
+ activeValue = selectedOption?.value ?? firstEnabledOption()?.value ?? value;
20
+ }
21
+
22
+ function firstEnabledOption(): DropdownOption | undefined {
23
+ return options.find((option) => !option.disabled);
24
+ }
25
+
26
+ function activeOptionIndex(nextActiveValue: DropdownValue): number {
27
+ const index = options.findIndex((option) => option.value === nextActiveValue && !option.disabled);
28
+ if (index >= 0) {
29
+ return index;
30
+ }
31
+ const fallbackIndex = options.findIndex((option) => option.value === value && !option.disabled);
32
+ if (fallbackIndex >= 0) {
33
+ return fallbackIndex;
34
+ }
35
+ return options.findIndex((option) => !option.disabled);
36
+ }
37
+
38
+ function moveActiveOption(offset: number) {
39
+ const enabledOptions = options.filter((option) => !option.disabled);
40
+ if (enabledOptions.length === 0) {
41
+ return;
42
+ }
43
+
44
+ const currentIndex = Math.max(0, enabledOptions.findIndex((option) => option.value === activeValue));
45
+ const nextIndex = (currentIndex + offset + enabledOptions.length) % enabledOptions.length;
46
+ activeValue = enabledOptions[nextIndex]?.value ?? activeValue;
47
+ }
48
+
49
+ function selectOption(option: DropdownOption) {
50
+ if (option.disabled) {
51
+ return;
52
+ }
53
+ open = false;
54
+ activeValue = option.value;
55
+ void onChange?.(option.value);
56
+ buttonElement?.focus();
57
+ }
58
+
59
+ function toggleOpen() {
60
+ if (disabled) {
61
+ return;
62
+ }
63
+ open = !open;
64
+ activeValue = selectedOption?.value ?? firstEnabledOption()?.value ?? value;
65
+ }
66
+
67
+ function handleKeydown(event: KeyboardEvent) {
68
+ if (disabled) {
69
+ return;
70
+ }
71
+
72
+ if (event.key === 'Escape') {
73
+ if (open) {
74
+ event.preventDefault();
75
+ open = false;
76
+ }
77
+ return;
78
+ }
79
+
80
+ if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
81
+ event.preventDefault();
82
+ if (!open) {
83
+ open = true;
84
+ activeValue = selectedOption?.value ?? firstEnabledOption()?.value ?? value;
85
+ }
86
+ moveActiveOption(event.key === 'ArrowDown' ? 1 : -1);
87
+ return;
88
+ }
89
+
90
+ if ((event.key === 'Enter' || event.key === ' ') && open) {
91
+ event.preventDefault();
92
+ const index = activeOptionIndex(activeValue);
93
+ const option = index >= 0 ? options[index] : undefined;
94
+ if (option) {
95
+ selectOption(option);
96
+ }
97
+ }
98
+ }
99
+
100
+ function handleFocusout(event: FocusEvent) {
101
+ const nextTarget = event.relatedTarget;
102
+ if (nextTarget instanceof Node && event.currentTarget instanceof Node && event.currentTarget.contains(nextTarget)) {
103
+ return;
104
+ }
105
+ open = false;
106
+ }
107
+ </script>
108
+
109
+ <span class="suu-dropdown" on:focusout={handleFocusout}>
110
+ <button
111
+ bind:this={buttonElement}
112
+ {id}
113
+ type="button"
114
+ class="suu-dropdown__button"
115
+ {disabled}
116
+ aria-label={ariaLabel}
117
+ aria-haspopup="listbox"
118
+ aria-expanded={open}
119
+ data-value={String(value)}
120
+ on:click={toggleOpen}
121
+ on:keydown={handleKeydown}
122
+ >
123
+ <span>{selectedText}</span>
124
+ <span class="suu-dropdown__chevron" aria-hidden="true"></span>
125
+ </button>
126
+
127
+ {#if open}
128
+ <div
129
+ class="suu-dropdown__menu"
130
+ class:suu-dropdown__menu--up={placement === 'up'}
131
+ class:suu-dropdown__menu--down={placement === 'down'}
132
+ >
133
+ <div class="suu-dropdown__panel" role="listbox" aria-label={ariaLabel}>
134
+ {#each options as option}
135
+ <button
136
+ type="button"
137
+ class="suu-dropdown__option"
138
+ class:suu-dropdown__option--active={option.value === activeValue}
139
+ class:suu-dropdown__option--disabled={option.disabled}
140
+ role="option"
141
+ aria-selected={option.value === value}
142
+ aria-disabled={option.disabled}
143
+ disabled={option.disabled}
144
+ data-value={String(option.value)}
145
+ on:mousedown|preventDefault={() => undefined}
146
+ on:mouseenter={() => {
147
+ if (!option.disabled) {
148
+ activeValue = option.value;
149
+ }
150
+ }}
151
+ on:click={() => selectOption(option)}
152
+ >
153
+ {option.label}
154
+ </button>
155
+ {/each}
156
+ </div>
157
+ </div>
158
+ {/if}
159
+ </span>
@@ -0,0 +1,28 @@
1
+ import type { DropdownChangeHandler, DropdownOption, DropdownPlacement, DropdownValue } from './types.js';
2
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
+ $$bindings?: Bindings;
5
+ } & Exports;
6
+ (internal: unknown, props: Props & {
7
+ $$events?: Events;
8
+ $$slots?: Slots;
9
+ }): Exports & {
10
+ $set?: any;
11
+ $on?: any;
12
+ };
13
+ z_$$bindings?: Bindings;
14
+ }
15
+ declare const Dropdown: $$__sveltets_2_IsomorphicComponent<{
16
+ id?: string | undefined;
17
+ value?: DropdownValue;
18
+ options?: DropdownOption[];
19
+ ariaLabel?: string | undefined;
20
+ placement?: DropdownPlacement;
21
+ disabled?: boolean;
22
+ onChange?: DropdownChangeHandler | undefined;
23
+ }, {
24
+ [evt: string]: CustomEvent<any>;
25
+ }, {}, {}, string>;
26
+ type Dropdown = InstanceType<typeof Dropdown>;
27
+ export default Dropdown;
28
+ //# sourceMappingURL=Dropdown.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/Dropdown.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAuI1G,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAC9G,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,QAAQ;SAV8I,MAAM,GAAG,SAAS;YAAU,aAAa;cAAY,cAAc,EAAE;gBAAc,MAAM,GAAG,SAAS;gBAAc,iBAAiB;;eAAyC,qBAAqB,GAAG,SAAS;;;kBAU7Q,CAAC;AAC5E,KAAK,QAAQ,GAAG,YAAY,CAAC,OAAO,QAAQ,CAAC,CAAC;AAChD,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { default as Dropdown } from './Dropdown.svelte';
2
+ export type { DropdownChangeHandler, DropdownOption, DropdownPlacement, DropdownValue } from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,YAAY,EAAE,qBAAqB,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1 @@
1
+ export { default as Dropdown } from './Dropdown.svelte';
@@ -0,0 +1,9 @@
1
+ export type DropdownValue = string | number;
2
+ export type DropdownPlacement = 'up' | 'down';
3
+ export interface DropdownOption {
4
+ label: string;
5
+ value: DropdownValue;
6
+ disabled?: boolean;
7
+ }
8
+ export type DropdownChangeHandler = (value: DropdownValue) => void | Promise<void>;
9
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/dropdown/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5C,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,MAAM,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};