@sentropic/design-system-svelte 0.4.0 → 0.5.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.
@@ -0,0 +1,126 @@
1
+ <script lang="ts">
2
+ type ContentSwitcherItem = {
3
+ value: string;
4
+ label: string;
5
+ disabled?: boolean;
6
+ };
7
+
8
+ type ContentSwitcherProps = {
9
+ items: ContentSwitcherItem[];
10
+ value?: string;
11
+ label?: string;
12
+ size?: "sm" | "md" | "lg";
13
+ onchange?: (value: string) => void;
14
+ class?: string;
15
+ };
16
+
17
+ let {
18
+ items,
19
+ value = $bindable(""),
20
+ label,
21
+ size = "md",
22
+ onchange,
23
+ class: className
24
+ }: ContentSwitcherProps = $props();
25
+
26
+ const groupClasses = () =>
27
+ ["st-contentSwitcher", `st-contentSwitcher--${size}`, className].filter(Boolean).join(" ");
28
+
29
+ function select(item: ContentSwitcherItem) {
30
+ if (item.disabled) return;
31
+ if (value === item.value) return;
32
+ value = item.value;
33
+ onchange?.(item.value);
34
+ }
35
+
36
+ function onKeydown(event: KeyboardEvent, index: number) {
37
+ const last = items.length - 1;
38
+ let target = -1;
39
+ if (event.key === "ArrowRight") target = index === last ? 0 : index + 1;
40
+ else if (event.key === "ArrowLeft") target = index === 0 ? last : index - 1;
41
+ else if (event.key === "Home") target = 0;
42
+ else if (event.key === "End") target = last;
43
+ if (target < 0) return;
44
+ event.preventDefault();
45
+ const item = items[target];
46
+ if (item) select(item);
47
+ }
48
+ </script>
49
+
50
+ <div class={groupClasses()} role="tablist" aria-label={label}>
51
+ {#each items as item, i (item.value)}
52
+ {@const selected = value === item.value}
53
+ <button
54
+ type="button"
55
+ class="st-contentSwitcher__option"
56
+ class:st-contentSwitcher__option--selected={selected}
57
+ role="tab"
58
+ aria-selected={selected ? "true" : "false"}
59
+ aria-disabled={item.disabled ? "true" : undefined}
60
+ tabindex={selected ? 0 : -1}
61
+ disabled={item.disabled}
62
+ onclick={() => select(item)}
63
+ onkeydown={(event) => onKeydown(event, i)}
64
+ >
65
+ {item.label}
66
+ </button>
67
+ {/each}
68
+ </div>
69
+
70
+ <style>
71
+ .st-contentSwitcher {
72
+ background: var(--st-semantic-surface-subtle);
73
+ border-radius: var(--st-component-control-radius, 0.375rem);
74
+ display: inline-flex;
75
+ padding: 0.125rem;
76
+ }
77
+
78
+ .st-contentSwitcher__option {
79
+ background: transparent;
80
+ border: 0;
81
+ border-radius: var(--st-component-control-radius, 0.375rem);
82
+ color: var(--st-semantic-text-secondary);
83
+ cursor: pointer;
84
+ font: inherit;
85
+ font-weight: 500;
86
+ padding: 0 0.875rem;
87
+ transition:
88
+ background-color var(--st-motion-fast, 120ms) var(--st-motion-easing, ease),
89
+ color var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
90
+ }
91
+
92
+ .st-contentSwitcher--sm .st-contentSwitcher__option {
93
+ font-size: 0.75rem;
94
+ min-height: 1.75rem;
95
+ }
96
+
97
+ .st-contentSwitcher--md .st-contentSwitcher__option {
98
+ font-size: 0.875rem;
99
+ min-height: 2.25rem;
100
+ }
101
+
102
+ .st-contentSwitcher--lg .st-contentSwitcher__option {
103
+ font-size: 0.9375rem;
104
+ min-height: 2.75rem;
105
+ }
106
+
107
+ .st-contentSwitcher__option:hover:not([disabled]):not(.st-contentSwitcher__option--selected) {
108
+ color: var(--st-semantic-text-primary);
109
+ }
110
+
111
+ .st-contentSwitcher__option:focus-visible {
112
+ outline: 2px solid var(--st-component-control-focusRing, var(--st-semantic-border-interactive));
113
+ outline-offset: 1px;
114
+ }
115
+
116
+ .st-contentSwitcher__option--selected {
117
+ background: var(--st-semantic-surface-default);
118
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
119
+ color: var(--st-semantic-text-primary);
120
+ }
121
+
122
+ .st-contentSwitcher__option:disabled {
123
+ cursor: not-allowed;
124
+ opacity: 0.55;
125
+ }
126
+ </style>
@@ -0,0 +1,17 @@
1
+ type ContentSwitcherItem = {
2
+ value: string;
3
+ label: string;
4
+ disabled?: boolean;
5
+ };
6
+ type ContentSwitcherProps = {
7
+ items: ContentSwitcherItem[];
8
+ value?: string;
9
+ label?: string;
10
+ size?: "sm" | "md" | "lg";
11
+ onchange?: (value: string) => void;
12
+ class?: string;
13
+ };
14
+ declare const ContentSwitcher: import("svelte").Component<ContentSwitcherProps, {}, "value">;
15
+ type ContentSwitcher = ReturnType<typeof ContentSwitcher>;
16
+ export default ContentSwitcher;
17
+ //# sourceMappingURL=ContentSwitcher.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentSwitcher.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ContentSwitcher.svelte.ts"],"names":[],"mappings":"AAGE,KAAK,mBAAmB,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,KAAK,oBAAoB,GAAG;IAC1B,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAmDJ,QAAA,MAAM,eAAe,+DAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
@@ -0,0 +1,132 @@
1
+ <script lang="ts">
2
+ import type { HTMLButtonAttributes } from "svelte/elements";
3
+
4
+ type CopyButtonProps = Omit<HTMLButtonAttributes, "class" | "type"> & {
5
+ value: string;
6
+ label?: string;
7
+ copiedLabel?: string;
8
+ feedbackTimeoutMs?: number;
9
+ size?: "sm" | "md" | "lg";
10
+ onCopied?: (value: string) => void;
11
+ onError?: (err: unknown) => void;
12
+ class?: string;
13
+ };
14
+
15
+ let {
16
+ value,
17
+ label = "Copy",
18
+ copiedLabel = "Copied",
19
+ feedbackTimeoutMs = 1500,
20
+ size = "md",
21
+ onCopied,
22
+ onError,
23
+ disabled,
24
+ class: className,
25
+ ...rest
26
+ }: CopyButtonProps = $props();
27
+
28
+ let copied = $state(false);
29
+ let timeoutId: ReturnType<typeof setTimeout> | undefined;
30
+
31
+ const classes = () =>
32
+ ["st-copyButton", `st-copyButton--${size}`, copied ? "st-copyButton--copied" : null, className]
33
+ .filter(Boolean)
34
+ .join(" ");
35
+
36
+ async function copy() {
37
+ if (disabled) return;
38
+ try {
39
+ await navigator.clipboard.writeText(value);
40
+ copied = true;
41
+ onCopied?.(value);
42
+ if (timeoutId) clearTimeout(timeoutId);
43
+ timeoutId = setTimeout(() => {
44
+ copied = false;
45
+ }, feedbackTimeoutMs);
46
+ } catch (err) {
47
+ onError?.(err);
48
+ }
49
+ }
50
+ </script>
51
+
52
+ <button
53
+ {...rest}
54
+ type="button"
55
+ class={classes()}
56
+ {disabled}
57
+ aria-live="polite"
58
+ onclick={copy}
59
+ >
60
+ <span class="st-copyButton__icon" aria-hidden="true">
61
+ {#if copied}
62
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" width="14" height="14">
63
+ <path d="m3 8 3.5 3.5L13 5" stroke-linecap="round" stroke-linejoin="round" />
64
+ </svg>
65
+ {:else}
66
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="14" height="14">
67
+ <rect x="4" y="4" width="9" height="10" rx="1.5" />
68
+ <path d="M3 11V3a1 1 0 0 1 1-1h7" />
69
+ </svg>
70
+ {/if}
71
+ </span>
72
+ <span class="st-copyButton__label">{copied ? copiedLabel : label}</span>
73
+ </button>
74
+
75
+ <style>
76
+ .st-copyButton {
77
+ align-items: center;
78
+ background: var(--st-component-control-background, var(--st-semantic-surface-default));
79
+ border: 1px solid var(--st-component-control-border, var(--st-semantic-border-subtle));
80
+ border-radius: var(--st-component-control-radius, 0.375rem);
81
+ color: var(--st-component-control-text, var(--st-semantic-text-primary));
82
+ cursor: pointer;
83
+ display: inline-flex;
84
+ font: inherit;
85
+ gap: 0.375rem;
86
+ padding: 0 0.625rem;
87
+ transition:
88
+ background-color var(--st-motion-fast, 120ms) var(--st-motion-easing, ease),
89
+ border-color var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
90
+ }
91
+
92
+ .st-copyButton--sm {
93
+ font-size: 0.75rem;
94
+ min-height: var(--st-component-control-smHeight, 2rem);
95
+ }
96
+
97
+ .st-copyButton--md {
98
+ font-size: 0.875rem;
99
+ min-height: var(--st-component-control-mdHeight, 2.5rem);
100
+ }
101
+
102
+ .st-copyButton--lg {
103
+ font-size: 0.9375rem;
104
+ min-height: var(--st-component-control-lgHeight, 3rem);
105
+ }
106
+
107
+ .st-copyButton:hover:not(:disabled) {
108
+ background: var(--st-component-control-hoverBackground, var(--st-semantic-surface-subtle));
109
+ border-color: var(--st-component-control-hoverBorder, var(--st-semantic-border-strong));
110
+ }
111
+
112
+ .st-copyButton:focus-visible {
113
+ border-color: var(--st-component-control-focusRing, var(--st-semantic-border-interactive));
114
+ box-shadow: 0 0 0 2px var(--st-component-control-focusRing, var(--st-semantic-border-interactive));
115
+ outline: none;
116
+ }
117
+
118
+ .st-copyButton:disabled {
119
+ color: var(--st-component-control-disabledText, var(--st-semantic-text-muted));
120
+ cursor: not-allowed;
121
+ }
122
+
123
+ .st-copyButton--copied {
124
+ color: var(--st-semantic-feedback-success);
125
+ }
126
+
127
+ .st-copyButton__icon {
128
+ align-items: center;
129
+ display: inline-flex;
130
+ justify-content: center;
131
+ }
132
+ </style>
@@ -0,0 +1,15 @@
1
+ import type { HTMLButtonAttributes } from "svelte/elements";
2
+ type CopyButtonProps = Omit<HTMLButtonAttributes, "class" | "type"> & {
3
+ value: string;
4
+ label?: string;
5
+ copiedLabel?: string;
6
+ feedbackTimeoutMs?: number;
7
+ size?: "sm" | "md" | "lg";
8
+ onCopied?: (value: string) => void;
9
+ onError?: (err: unknown) => void;
10
+ class?: string;
11
+ };
12
+ declare const CopyButton: import("svelte").Component<CopyButtonProps, {}, "">;
13
+ type CopyButton = ReturnType<typeof CopyButton>;
14
+ export default CopyButton;
15
+ //# sourceMappingURL=CopyButton.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CopyButton.svelte.d.ts","sourceRoot":"","sources":["../src/lib/CopyButton.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAG1D,KAAK,eAAe,GAAG,IAAI,CAAC,oBAAoB,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AA8DJ,QAAA,MAAM,UAAU,qDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}