@sentropic/design-system-svelte 0.3.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 (82) hide show
  1. package/dist/Alert.svelte +92 -0
  2. package/dist/Alert.svelte.d.ts +14 -0
  3. package/dist/Alert.svelte.d.ts.map +1 -0
  4. package/dist/Badge.svelte +55 -0
  5. package/dist/Badge.svelte.d.ts +11 -0
  6. package/dist/Badge.svelte.d.ts.map +1 -0
  7. package/dist/Breadcrumb.svelte +67 -0
  8. package/dist/Breadcrumb.svelte.d.ts +15 -0
  9. package/dist/Breadcrumb.svelte.d.ts.map +1 -0
  10. package/dist/Button.svelte +99 -0
  11. package/dist/Button.svelte.d.ts +14 -0
  12. package/dist/Button.svelte.d.ts.map +1 -0
  13. package/dist/Card.svelte +42 -0
  14. package/dist/Card.svelte.d.ts +11 -0
  15. package/dist/Card.svelte.d.ts.map +1 -0
  16. package/dist/Checkbox.svelte +56 -0
  17. package/dist/Checkbox.svelte.d.ts +11 -0
  18. package/dist/Checkbox.svelte.d.ts.map +1 -0
  19. package/dist/Drawer.svelte +135 -0
  20. package/dist/Drawer.svelte.d.ts +17 -0
  21. package/dist/Drawer.svelte.d.ts.map +1 -0
  22. package/dist/Dropdown.svelte +158 -0
  23. package/dist/Dropdown.svelte.d.ts +19 -0
  24. package/dist/Dropdown.svelte.d.ts.map +1 -0
  25. package/dist/EmptyState.svelte +65 -0
  26. package/dist/EmptyState.svelte.d.ts +13 -0
  27. package/dist/EmptyState.svelte.d.ts.map +1 -0
  28. package/dist/Input.svelte +121 -0
  29. package/dist/Input.svelte.d.ts +13 -0
  30. package/dist/Input.svelte.d.ts.map +1 -0
  31. package/dist/Link.svelte +90 -0
  32. package/dist/Link.svelte.d.ts +17 -0
  33. package/dist/Link.svelte.d.ts.map +1 -0
  34. package/dist/LoadingState.svelte +77 -0
  35. package/dist/LoadingState.svelte.d.ts +10 -0
  36. package/dist/LoadingState.svelte.d.ts.map +1 -0
  37. package/dist/Menu.svelte +72 -0
  38. package/dist/Menu.svelte.d.ts +16 -0
  39. package/dist/Menu.svelte.d.ts.map +1 -0
  40. package/dist/Modal.svelte +123 -0
  41. package/dist/Modal.svelte.d.ts +16 -0
  42. package/dist/Modal.svelte.d.ts.map +1 -0
  43. package/dist/Pagination.svelte +75 -0
  44. package/dist/Pagination.svelte.d.ts +13 -0
  45. package/dist/Pagination.svelte.d.ts.map +1 -0
  46. package/dist/Popover.svelte +74 -0
  47. package/dist/Popover.svelte.d.ts +14 -0
  48. package/dist/Popover.svelte.d.ts.map +1 -0
  49. package/dist/Radio.svelte +51 -0
  50. package/dist/Radio.svelte.d.ts +11 -0
  51. package/dist/Radio.svelte.d.ts.map +1 -0
  52. package/dist/Select.svelte +109 -0
  53. package/dist/Select.svelte.d.ts +15 -0
  54. package/dist/Select.svelte.d.ts.map +1 -0
  55. package/dist/SideNav.svelte +63 -0
  56. package/dist/SideNav.svelte.d.ts +15 -0
  57. package/dist/SideNav.svelte.d.ts.map +1 -0
  58. package/dist/Switch.svelte +88 -0
  59. package/dist/Switch.svelte.d.ts +10 -0
  60. package/dist/Switch.svelte.d.ts.map +1 -0
  61. package/dist/Table.svelte +104 -0
  62. package/dist/Table.svelte.d.ts +17 -0
  63. package/dist/Table.svelte.d.ts.map +1 -0
  64. package/dist/Tabs.svelte +102 -0
  65. package/dist/Tabs.svelte.d.ts +18 -0
  66. package/dist/Tabs.svelte.d.ts.map +1 -0
  67. package/dist/Textarea.svelte +97 -0
  68. package/dist/Textarea.svelte.d.ts +12 -0
  69. package/dist/Textarea.svelte.d.ts.map +1 -0
  70. package/dist/ThemeProvider.svelte +22 -0
  71. package/dist/ThemeProvider.svelte.d.ts +11 -0
  72. package/dist/ThemeProvider.svelte.d.ts.map +1 -0
  73. package/dist/Toast.svelte +84 -0
  74. package/dist/Toast.svelte.d.ts +13 -0
  75. package/dist/Toast.svelte.d.ts.map +1 -0
  76. package/dist/Tooltip.svelte +66 -0
  77. package/dist/Tooltip.svelte.d.ts +12 -0
  78. package/dist/Tooltip.svelte.d.ts.map +1 -0
  79. package/dist/index.d.ts +33 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +26 -0
  82. package/package.json +47 -0
@@ -0,0 +1,158 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+
4
+ export type DropdownOption = {
5
+ label: string;
6
+ value: string;
7
+ disabled?: boolean;
8
+ };
9
+
10
+ type DropdownProps = Omit<HTMLAttributes<HTMLDivElement>, "class" | "onselect"> & {
11
+ label: string;
12
+ options: DropdownOption[];
13
+ value?: string;
14
+ placeholder?: string;
15
+ open?: boolean;
16
+ class?: string;
17
+ onselect?: (value: string) => void;
18
+ };
19
+
20
+ let {
21
+ label,
22
+ options,
23
+ value,
24
+ placeholder = "Select",
25
+ open = false,
26
+ class: className,
27
+ onselect,
28
+ ...rest
29
+ }: DropdownProps = $props();
30
+
31
+ let expanded = $state(false);
32
+ let currentValue = $state<string | undefined>(undefined);
33
+ let syncedOpen = $state<boolean | undefined>(undefined);
34
+ let syncedValue = $state<string | undefined>(undefined);
35
+ const classes = () => ["st-dropdown", className].filter(Boolean).join(" ");
36
+ const selectedLabel = () => options.find((option) => option.value === currentValue)?.label ?? placeholder;
37
+ const selectOption = (option: DropdownOption) => {
38
+ if (option.disabled) return;
39
+ currentValue = option.value;
40
+ expanded = false;
41
+ onselect?.(option.value);
42
+ };
43
+
44
+ $effect(() => {
45
+ if (syncedOpen !== open) {
46
+ expanded = open;
47
+ syncedOpen = open;
48
+ }
49
+ });
50
+
51
+ $effect(() => {
52
+ if (syncedValue !== value) {
53
+ currentValue = value;
54
+ syncedValue = value;
55
+ }
56
+ });
57
+ </script>
58
+
59
+ <div {...rest} class={classes()}>
60
+ <button
61
+ class="st-dropdown__button"
62
+ type="button"
63
+ aria-haspopup="listbox"
64
+ aria-expanded={expanded}
65
+ onclick={() => (expanded = !expanded)}
66
+ >
67
+ <span>{label}: {selectedLabel()}</span>
68
+ <span aria-hidden="true">v</span>
69
+ </button>
70
+ {#if expanded}
71
+ <div class="st-dropdown__list" role="listbox" aria-label={label}>
72
+ {#each options as option (option.value)}
73
+ <button
74
+ class="st-dropdown__option"
75
+ type="button"
76
+ role="option"
77
+ aria-selected={option.value === currentValue ? "true" : "false"}
78
+ aria-disabled={option.disabled ? "true" : undefined}
79
+ disabled={option.disabled}
80
+ onclick={() => selectOption(option)}
81
+ >
82
+ {option.label}
83
+ </button>
84
+ {/each}
85
+ </div>
86
+ {/if}
87
+ </div>
88
+
89
+ <style>
90
+ .st-dropdown {
91
+ display: inline-grid;
92
+ min-width: 14rem;
93
+ position: relative;
94
+ }
95
+
96
+ .st-dropdown__button {
97
+ align-items: center;
98
+ background: var(--st-component-dropdown-background, var(--st-semantic-surface-default));
99
+ border: 1px solid var(--st-component-dropdown-border, var(--st-semantic-border-subtle));
100
+ border-radius: var(--st-component-dropdown-radius, 0.375rem);
101
+ color: var(--st-component-dropdown-text, var(--st-semantic-text-primary));
102
+ cursor: pointer;
103
+ display: flex;
104
+ font: inherit;
105
+ justify-content: space-between;
106
+ min-height: var(--st-component-control-mdHeight, 2.5rem);
107
+ padding: 0 var(--st-spacing-3, 0.75rem);
108
+ }
109
+
110
+ .st-dropdown__button:focus-visible {
111
+ outline: 2px solid var(--st-component-control-focusRing, var(--st-semantic-border-interactive));
112
+ outline-offset: 2px;
113
+ }
114
+
115
+ .st-dropdown__list {
116
+ background: var(--st-component-dropdown-background, var(--st-semantic-surface-default));
117
+ border: 1px solid var(--st-component-dropdown-border, var(--st-semantic-border-subtle));
118
+ border-radius: var(--st-component-dropdown-radius, 0.375rem);
119
+ box-shadow: var(--st-component-dropdown-shadow, 0 8px 24px rgb(15 23 42 / 0.14));
120
+ display: grid;
121
+ left: 0;
122
+ margin-top: var(--st-spacing-1, 0.25rem);
123
+ min-width: 100%;
124
+ overflow: hidden;
125
+ position: absolute;
126
+ top: 100%;
127
+ z-index: var(--st-component-popover-zIndex, 80);
128
+ }
129
+
130
+ .st-dropdown__option {
131
+ background: transparent;
132
+ border: 0;
133
+ color: var(--st-component-dropdown-text, var(--st-semantic-text-primary));
134
+ cursor: pointer;
135
+ font: inherit;
136
+ padding: var(--st-spacing-2, 0.5rem) var(--st-spacing-3, 0.75rem);
137
+ text-align: left;
138
+ }
139
+
140
+ .st-dropdown__option:hover:not(:disabled),
141
+ .st-dropdown__option:focus-visible {
142
+ background: var(
143
+ --st-component-dropdown-optionHoverBackground,
144
+ var(--st-semantic-surface-subtle)
145
+ );
146
+ outline: none;
147
+ }
148
+
149
+ .st-dropdown__option[aria-selected="true"] {
150
+ background: var(--st-component-dropdown-selectedBackground, var(--st-semantic-action-primary));
151
+ color: var(--st-component-dropdown-selectedText, var(--st-semantic-action-primaryText));
152
+ }
153
+
154
+ .st-dropdown__option:disabled {
155
+ color: var(--st-semantic-text-muted);
156
+ cursor: not-allowed;
157
+ }
158
+ </style>
@@ -0,0 +1,19 @@
1
+ import type { HTMLAttributes } from "svelte/elements";
2
+ export type DropdownOption = {
3
+ label: string;
4
+ value: string;
5
+ disabled?: boolean;
6
+ };
7
+ type DropdownProps = Omit<HTMLAttributes<HTMLDivElement>, "class" | "onselect"> & {
8
+ label: string;
9
+ options: DropdownOption[];
10
+ value?: string;
11
+ placeholder?: string;
12
+ open?: boolean;
13
+ class?: string;
14
+ onselect?: (value: string) => void;
15
+ };
16
+ declare const Dropdown: import("svelte").Component<DropdownProps, {}, "">;
17
+ type Dropdown = ReturnType<typeof Dropdown>;
18
+ export default Dropdown;
19
+ //# sourceMappingURL=Dropdown.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Dropdown.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,KAAK,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AAiEJ,QAAA,MAAM,QAAQ,mDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,65 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import type { HTMLAttributes } from "svelte/elements";
4
+
5
+ type EmptyStateProps = Omit<HTMLAttributes<HTMLElement>, "class"> & {
6
+ title: string;
7
+ message?: string;
8
+ class?: string;
9
+ action?: Snippet;
10
+ children?: Snippet;
11
+ };
12
+
13
+ let { title, message, class: className, action, children, ...rest }: EmptyStateProps = $props();
14
+ const classes = () => ["st-empty-state", className].filter(Boolean).join(" ");
15
+ </script>
16
+
17
+ <section {...rest} class={classes()}>
18
+ <div class="st-empty-state__content">
19
+ <h2 class="st-empty-state__title">{title}</h2>
20
+ {#if message}<p class="st-empty-state__message">{message}</p>{/if}
21
+ {@render children?.()}
22
+ </div>
23
+ {#if action}
24
+ <div class="st-empty-state__action">
25
+ {@render action()}
26
+ </div>
27
+ {/if}
28
+ </section>
29
+
30
+ <style>
31
+ .st-empty-state {
32
+ align-items: center;
33
+ background: var(--st-component-emptyState-background, var(--st-semantic-surface-subtle));
34
+ border: 1px solid var(--st-component-emptyState-border, var(--st-semantic-border-subtle));
35
+ border-radius: var(--st-component-emptyState-radius, 0.5rem);
36
+ color: var(--st-component-emptyState-titleText, var(--st-semantic-text-primary));
37
+ display: grid;
38
+ gap: var(--st-spacing-4, 1rem);
39
+ justify-items: center;
40
+ padding: var(--st-spacing-8, 2rem);
41
+ text-align: center;
42
+ }
43
+
44
+ .st-empty-state__content {
45
+ display: grid;
46
+ gap: var(--st-spacing-2, 0.5rem);
47
+ max-width: 34rem;
48
+ }
49
+
50
+ .st-empty-state__title {
51
+ font-size: 1.125rem;
52
+ margin: 0;
53
+ }
54
+
55
+ .st-empty-state__message {
56
+ color: var(--st-component-emptyState-messageText, var(--st-semantic-text-secondary));
57
+ line-height: 1.5;
58
+ margin: 0;
59
+ }
60
+
61
+ .st-empty-state__action {
62
+ display: flex;
63
+ justify-content: center;
64
+ }
65
+ </style>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+ type EmptyStateProps = Omit<HTMLAttributes<HTMLElement>, "class"> & {
4
+ title: string;
5
+ message?: string;
6
+ class?: string;
7
+ action?: Snippet;
8
+ children?: Snippet;
9
+ };
10
+ declare const EmptyState: import("svelte").Component<EmptyStateProps, {}, "">;
11
+ type EmptyState = ReturnType<typeof EmptyState>;
12
+ export default EmptyState;
13
+ //# sourceMappingURL=EmptyState.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmptyState.svelte.d.ts","sourceRoot":"","sources":["../src/lib/EmptyState.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,eAAe,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,GAAG;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AA2BJ,QAAA,MAAM,UAAU,qDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -0,0 +1,121 @@
1
+ <script lang="ts">
2
+ import type { HTMLInputAttributes } from "svelte/elements";
3
+
4
+ type InputProps = Omit<HTMLInputAttributes, "class" | "size"> & {
5
+ label?: string;
6
+ helperText?: string;
7
+ errorText?: string;
8
+ invalid?: boolean;
9
+ size?: "sm" | "md" | "lg";
10
+ class?: string;
11
+ };
12
+
13
+ let {
14
+ label,
15
+ helperText,
16
+ errorText,
17
+ invalid = false,
18
+ size = "md",
19
+ class: className,
20
+ ...rest
21
+ }: InputProps = $props();
22
+
23
+ const fieldClasses = () => ["st-field", className].filter(Boolean).join(" ");
24
+ const controlClasses = () => ["st-control", `st-control--${size}`].join(" ");
25
+ const isInvalid = () => invalid || Boolean(errorText);
26
+ </script>
27
+
28
+ <div class={fieldClasses()}>
29
+ <label class="st-field__control">
30
+ {#if label}<span class="st-field__label">{label}</span>{/if}
31
+ <input {...rest} class={controlClasses()} aria-invalid={isInvalid() ? "true" : undefined} />
32
+ </label>
33
+ {#if errorText}
34
+ <span class="st-field__error">{errorText}</span>
35
+ {:else if helperText}
36
+ <span class="st-field__help">{helperText}</span>
37
+ {/if}
38
+ </div>
39
+
40
+ <style>
41
+ .st-field {
42
+ color: var(--st-component-field-labelText, var(--st-semantic-text-primary));
43
+ display: grid;
44
+ gap: var(--st-component-field-gap, 0.5rem);
45
+ max-width: var(--st-component-field-maxWidth, 28rem);
46
+ }
47
+
48
+ .st-field__control {
49
+ display: grid;
50
+ gap: var(--st-component-field-gap, 0.5rem);
51
+ }
52
+
53
+ .st-field__label {
54
+ font-size: 0.875rem;
55
+ font-weight: 600;
56
+ }
57
+
58
+ .st-field__help,
59
+ .st-field__error {
60
+ font-size: 0.8125rem;
61
+ line-height: 1.4;
62
+ }
63
+
64
+ .st-field__help {
65
+ color: var(--st-component-field-helpText, var(--st-semantic-text-secondary));
66
+ }
67
+
68
+ .st-field__error {
69
+ color: var(--st-component-field-errorText, var(--st-semantic-feedback-error));
70
+ }
71
+
72
+ .st-control {
73
+ background: var(--st-component-control-background, var(--st-semantic-surface-default));
74
+ border: 1px solid var(--st-component-control-border, var(--st-semantic-border-subtle));
75
+ border-radius: var(--st-component-control-radius, 0.375rem);
76
+ color: var(--st-component-control-text, var(--st-semantic-text-primary));
77
+ font: inherit;
78
+ min-width: 0;
79
+ padding: 0 0.75rem;
80
+ transition:
81
+ border-color var(--st-motion-fast, 120ms) var(--st-motion-easing, ease),
82
+ box-shadow var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
83
+ width: 100%;
84
+ }
85
+
86
+ .st-control--sm {
87
+ min-height: var(--st-component-control-smHeight, 2rem);
88
+ }
89
+
90
+ .st-control--md {
91
+ min-height: var(--st-component-control-mdHeight, 2.5rem);
92
+ }
93
+
94
+ .st-control--lg {
95
+ min-height: var(--st-component-control-lgHeight, 3rem);
96
+ }
97
+
98
+ .st-control::placeholder {
99
+ color: var(--st-component-control-placeholderText, var(--st-semantic-text-muted));
100
+ }
101
+
102
+ .st-control:hover:not(:disabled) {
103
+ border-color: var(--st-component-control-hoverBorder, var(--st-semantic-border-strong));
104
+ }
105
+
106
+ .st-control:focus-visible {
107
+ border-color: var(--st-component-control-focusRing, var(--st-semantic-border-interactive));
108
+ box-shadow: 0 0 0 2px var(--st-component-control-focusRing, var(--st-semantic-border-interactive));
109
+ outline: none;
110
+ }
111
+
112
+ .st-control[aria-invalid="true"] {
113
+ border-color: var(--st-component-control-invalidBorder, var(--st-semantic-feedback-error));
114
+ }
115
+
116
+ .st-control:disabled {
117
+ background: var(--st-component-control-disabledBackground, var(--st-semantic-surface-subtle));
118
+ color: var(--st-component-control-disabledText, var(--st-semantic-text-muted));
119
+ cursor: not-allowed;
120
+ }
121
+ </style>
@@ -0,0 +1,13 @@
1
+ import type { HTMLInputAttributes } from "svelte/elements";
2
+ type InputProps = Omit<HTMLInputAttributes, "class" | "size"> & {
3
+ label?: string;
4
+ helperText?: string;
5
+ errorText?: string;
6
+ invalid?: boolean;
7
+ size?: "sm" | "md" | "lg";
8
+ class?: string;
9
+ };
10
+ declare const Input: import("svelte").Component<InputProps, {}, "">;
11
+ type Input = ReturnType<typeof Input>;
12
+ export default Input;
13
+ //# sourceMappingURL=Input.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Input.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Input.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAGzD,KAAK,UAAU,GAAG,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAoCJ,QAAA,MAAM,KAAK,gDAAwC,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
@@ -0,0 +1,90 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import type { HTMLAnchorAttributes } from "svelte/elements";
4
+
5
+ type LinkProps = Omit<HTMLAnchorAttributes, "class" | "href" | "target" | "rel" | "onclick"> & {
6
+ href: string;
7
+ variant?: "inline" | "standalone" | "muted";
8
+ disabled?: boolean;
9
+ external?: boolean;
10
+ class?: string;
11
+ target?: HTMLAnchorAttributes["target"];
12
+ rel?: string;
13
+ onclick?: (event: MouseEvent) => void;
14
+ children?: Snippet;
15
+ };
16
+
17
+ let {
18
+ href,
19
+ variant = "inline",
20
+ disabled = false,
21
+ external = false,
22
+ class: className,
23
+ target,
24
+ rel,
25
+ onclick,
26
+ children,
27
+ ...rest
28
+ }: LinkProps = $props();
29
+
30
+ const classes = () =>
31
+ ["st-link", `st-link--${variant}`, disabled ? "st-link--disabled" : undefined, className]
32
+ .filter(Boolean)
33
+ .join(" ");
34
+ const linkTarget = () => target ?? (external ? "_blank" : undefined);
35
+ const linkRel = () => rel ?? (external ? "noreferrer" : undefined);
36
+ const handleClick = (event: MouseEvent) => {
37
+ if (disabled) {
38
+ event.preventDefault();
39
+ return;
40
+ }
41
+ onclick?.(event);
42
+ };
43
+ </script>
44
+
45
+ <a
46
+ {...rest}
47
+ class={classes()}
48
+ href={disabled ? undefined : href}
49
+ target={linkTarget()}
50
+ rel={linkRel()}
51
+ aria-disabled={disabled ? "true" : undefined}
52
+ onclick={handleClick}
53
+ >
54
+ {@render children?.()}
55
+ </a>
56
+
57
+ <style>
58
+ .st-link {
59
+ color: var(--st-component-link-text, var(--st-semantic-text-link));
60
+ cursor: pointer;
61
+ text-decoration: underline;
62
+ text-underline-offset: 0.18em;
63
+ }
64
+
65
+ .st-link--standalone {
66
+ display: inline-flex;
67
+ font-weight: 600;
68
+ gap: var(--st-spacing-1, 0.25rem);
69
+ }
70
+
71
+ .st-link--muted {
72
+ color: var(--st-semantic-text-secondary);
73
+ }
74
+
75
+ .st-link:hover {
76
+ color: var(--st-component-link-hoverText, var(--st-semantic-action-primary));
77
+ }
78
+
79
+ .st-link:focus-visible {
80
+ border-radius: var(--st-radius-small, 0.375rem);
81
+ outline: 2px solid var(--st-component-link-focusRing, var(--st-semantic-border-interactive));
82
+ outline-offset: 2px;
83
+ }
84
+
85
+ .st-link--disabled {
86
+ color: var(--st-component-link-disabledText, var(--st-semantic-text-muted));
87
+ cursor: not-allowed;
88
+ text-decoration: none;
89
+ }
90
+ </style>
@@ -0,0 +1,17 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { HTMLAnchorAttributes } from "svelte/elements";
3
+ type LinkProps = Omit<HTMLAnchorAttributes, "class" | "href" | "target" | "rel" | "onclick"> & {
4
+ href: string;
5
+ variant?: "inline" | "standalone" | "muted";
6
+ disabled?: boolean;
7
+ external?: boolean;
8
+ class?: string;
9
+ target?: HTMLAnchorAttributes["target"];
10
+ rel?: string;
11
+ onclick?: (event: MouseEvent) => void;
12
+ children?: Snippet;
13
+ };
14
+ declare const Link: import("svelte").Component<LinkProps, {}, "">;
15
+ type Link = ReturnType<typeof Link>;
16
+ export default Link;
17
+ //# sourceMappingURL=Link.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Link.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Link.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAG1D,KAAK,SAAS,GAAG,IAAI,CAAC,oBAAoB,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC,GAAG;IAC7F,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,QAAQ,GAAG,YAAY,GAAG,OAAO,CAAC;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AA0CJ,QAAA,MAAM,IAAI,+CAAwC,CAAC;AACnD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;AACpC,eAAe,IAAI,CAAC"}
@@ -0,0 +1,77 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+
4
+ type LoadingStateProps = Omit<HTMLAttributes<HTMLElement>, "class"> & {
5
+ label?: string;
6
+ variant?: "spinner" | "skeleton";
7
+ class?: string;
8
+ };
9
+
10
+ let { label = "Loading", variant = "spinner", class: className, ...rest }: LoadingStateProps =
11
+ $props();
12
+
13
+ const classes = () =>
14
+ ["st-loading", `st-loading--${variant}`, className].filter(Boolean).join(" ");
15
+ </script>
16
+
17
+ <section {...rest} class={classes()} role="status" aria-label={label} aria-busy="true">
18
+ {#if variant === "spinner"}
19
+ <span class="st-loading__spinner" aria-hidden="true"></span>
20
+ {:else}
21
+ <span class="st-loading__skeleton" aria-hidden="true"></span>
22
+ {/if}
23
+ <span class="st-loading__label">{label}</span>
24
+ </section>
25
+
26
+ <style>
27
+ .st-loading {
28
+ align-items: center;
29
+ color: var(--st-component-loadingState-text, var(--st-semantic-text-secondary));
30
+ display: inline-flex;
31
+ gap: var(--st-spacing-2, 0.5rem);
32
+ }
33
+
34
+ .st-loading__spinner {
35
+ animation: st-loading-spin 800ms linear infinite;
36
+ border: 2px solid var(--st-component-loadingState-track, var(--st-semantic-surface-subtle));
37
+ border-radius: var(--st-component-loadingState-radius, 9999px);
38
+ border-top-color: var(--st-component-loadingState-indicator, var(--st-semantic-action-primary));
39
+ display: inline-block;
40
+ height: 1.25rem;
41
+ width: 1.25rem;
42
+ }
43
+
44
+ .st-loading__skeleton {
45
+ background: linear-gradient(
46
+ 90deg,
47
+ var(--st-component-loadingState-track, var(--st-semantic-surface-subtle)),
48
+ var(--st-component-loadingState-indicator, var(--st-semantic-action-primary)),
49
+ var(--st-component-loadingState-track, var(--st-semantic-surface-subtle))
50
+ );
51
+ background-size: 200% 100%;
52
+ border-radius: var(--st-component-loadingState-radius, 9999px);
53
+ display: inline-block;
54
+ height: 0.75rem;
55
+ width: 8rem;
56
+ }
57
+
58
+ .st-loading--skeleton .st-loading__skeleton {
59
+ animation: st-loading-skeleton 1200ms ease-in-out infinite;
60
+ }
61
+
62
+ .st-loading__label {
63
+ font-size: 0.875rem;
64
+ }
65
+
66
+ @keyframes st-loading-spin {
67
+ to {
68
+ transform: rotate(360deg);
69
+ }
70
+ }
71
+
72
+ @keyframes st-loading-skeleton {
73
+ to {
74
+ background-position: -200% 0;
75
+ }
76
+ }
77
+ </style>
@@ -0,0 +1,10 @@
1
+ import type { HTMLAttributes } from "svelte/elements";
2
+ type LoadingStateProps = Omit<HTMLAttributes<HTMLElement>, "class"> & {
3
+ label?: string;
4
+ variant?: "spinner" | "skeleton";
5
+ class?: string;
6
+ };
7
+ declare const LoadingState: import("svelte").Component<LoadingStateProps, {}, "">;
8
+ type LoadingState = ReturnType<typeof LoadingState>;
9
+ export default LoadingState;
10
+ //# sourceMappingURL=LoadingState.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingState.svelte.d.ts","sourceRoot":"","sources":["../src/lib/LoadingState.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,iBAAiB,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,GAAG;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAyBJ,QAAA,MAAM,YAAY,uDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -0,0 +1,72 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+
4
+ export type MenuItem = {
5
+ label: string;
6
+ value: string;
7
+ disabled?: boolean;
8
+ };
9
+
10
+ type MenuProps = Omit<HTMLAttributes<HTMLDivElement>, "class" | "onselect"> & {
11
+ label: string;
12
+ items: MenuItem[];
13
+ class?: string;
14
+ onselect?: (value: string) => void;
15
+ };
16
+
17
+ let { label, items, class: className, onselect, ...rest }: MenuProps = $props();
18
+ const classes = () => ["st-menu", className].filter(Boolean).join(" ");
19
+ const selectItem = (item: MenuItem) => {
20
+ if (!item.disabled) onselect?.(item.value);
21
+ };
22
+ </script>
23
+
24
+ <div {...rest} class={classes()} role="menu" aria-label={label}>
25
+ {#each items as item (item.value)}
26
+ <button
27
+ class="st-menu__item"
28
+ type="button"
29
+ role="menuitem"
30
+ aria-disabled={item.disabled ? "true" : undefined}
31
+ disabled={item.disabled}
32
+ onclick={() => selectItem(item)}
33
+ >
34
+ {item.label}
35
+ </button>
36
+ {/each}
37
+ </div>
38
+
39
+ <style>
40
+ .st-menu {
41
+ background: var(--st-component-menu-background, var(--st-semantic-surface-raised));
42
+ border: 1px solid var(--st-component-menu-border, var(--st-semantic-border-subtle));
43
+ border-radius: var(--st-component-menu-radius, 0.375rem);
44
+ box-shadow: var(--st-component-menu-shadow, 0 8px 24px rgb(15 23 42 / 0.14));
45
+ color: var(--st-component-menu-text, var(--st-semantic-text-primary));
46
+ display: grid;
47
+ min-width: 12rem;
48
+ padding: var(--st-spacing-1, 0.25rem);
49
+ }
50
+
51
+ .st-menu__item {
52
+ background: transparent;
53
+ border: 0;
54
+ border-radius: var(--st-radius-small, 0.375rem);
55
+ color: inherit;
56
+ cursor: pointer;
57
+ font: inherit;
58
+ padding: var(--st-spacing-2, 0.5rem) var(--st-spacing-3, 0.75rem);
59
+ text-align: left;
60
+ }
61
+
62
+ .st-menu__item:hover:not(:disabled),
63
+ .st-menu__item:focus-visible {
64
+ background: var(--st-component-menu-itemHoverBackground, var(--st-semantic-surface-subtle));
65
+ outline: none;
66
+ }
67
+
68
+ .st-menu__item:disabled {
69
+ color: var(--st-component-menu-disabledText, var(--st-semantic-text-muted));
70
+ cursor: not-allowed;
71
+ }
72
+ </style>