@poirazis/supercomponents-shared 1.2.16 → 1.2.19

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 (35) hide show
  1. package/dist/index.js +17785 -22317
  2. package/dist/index.umd.cjs +19 -19
  3. package/package.json +13 -13
  4. package/src/index.js +1 -0
  5. package/src/index.ts +1 -0
  6. package/src/lib/SuperButton/SuperButton.svelte +90 -43
  7. package/src/lib/SuperField/SuperField.svelte +2 -3
  8. package/src/lib/SuperForm/InnerForm.svelte +7 -8
  9. package/src/lib/SuperTable/SuperTable.css +13 -6
  10. package/src/lib/SuperTable/SuperTable.svelte +53 -38
  11. package/src/lib/SuperTable/constants.js +1 -1
  12. package/src/lib/SuperTable/controls/RowButtonsColumn.svelte +34 -18
  13. package/src/lib/SuperTable/controls/SelectionColumn.svelte +6 -5
  14. package/src/lib/SuperTableCells/CellBoolean.svelte +52 -45
  15. package/src/lib/SuperTableCells/CellCommon.css +0 -5
  16. package/src/lib/SuperTableCells/CellDatetime.svelte +268 -120
  17. package/src/lib/SuperTableCells/CellLink.svelte +16 -7
  18. package/src/lib/SuperTableCells/CellLinkPickerSelect.svelte +28 -24
  19. package/src/lib/SuperTableCells/CellLinkPickerTree.svelte +22 -20
  20. package/src/lib/SuperTableCells/CellNumber.svelte +55 -53
  21. package/src/lib/SuperTableCells/CellOptions.svelte +60 -33
  22. package/src/lib/SuperTableCells/CellOptionsAdvanced.svelte +131 -129
  23. package/src/lib/SuperTableCells/CellSQLLink.svelte +35 -33
  24. package/src/lib/SuperTableCells/CellSQLLinkPicker.svelte +4 -7
  25. package/src/lib/SuperTableCells/CellString.svelte +49 -47
  26. package/src/lib/SuperTableCells/CellStringMask.svelte +41 -40
  27. package/src/lib/SuperTableColumn/SuperTableColumn.svelte +2 -0
  28. package/src/lib/SuperTableColumn/parts/SuperColumnBody.svelte +1 -0
  29. package/src/lib/SuperTableColumn/parts/SuperColumnHeader.svelte +44 -42
  30. package/src/lib/SuperTableColumn/parts/SuperColumnRow.svelte +1 -1
  31. package/src/lib/SuperTabs/SuperTabs.svelte +33 -17
  32. package/src/lib/UI/elements/Checkbox.svelte +69 -11
  33. package/src/lib/UI/elements/Switch.svelte +162 -0
  34. package/src/lib/UI/elements/Textbox.svelte +210 -0
  35. package/src/lib/UI/elements/Tooltip.svelte +15 -43
@@ -6,9 +6,11 @@
6
6
  export let partial: boolean = false;
7
7
  export let disabled: boolean = false;
8
8
  export let hovered: boolean = false;
9
+ export let locked: boolean = false;
10
+ export let size: "small" | "medium" | "large" = "small";
9
11
 
10
12
  function toggle() {
11
- if (disabled) return;
13
+ if (disabled || locked) return;
12
14
  checked = !checked;
13
15
  dispatch("change", { checked });
14
16
  }
@@ -16,11 +18,20 @@
16
18
 
17
19
  <!-- svelte-ignore a11y-click-events-have-key-events -->
18
20
  <!-- svelte-ignore a11y-no-static-element-interactions -->
19
- <button class:checked class:disabled class:hovered on:click={toggle}>
21
+ <button
22
+ class:checked
23
+ class:disabled
24
+ class:hovered
25
+ class:locked
26
+ class={size}
27
+ on:click={toggle}
28
+ >
20
29
  {#if checked}
21
- <i class="ph ph-check"></i>
30
+ <i class="ph ph-bold ph-check"></i>
22
31
  {:else if partial}
23
32
  <i class="ph ph-minus"></i>
33
+ {:else if locked}
34
+ <i class="ph ph-lock"></i>
24
35
  {/if}
25
36
  </button>
26
37
 
@@ -31,16 +42,50 @@
31
42
  display: flex;
32
43
  align-items: center;
33
44
  justify-content: center;
34
- width: 0.85rem;
35
- height: 0.85rem;
36
45
  border-radius: 0.25rem;
37
46
  border: 1px solid var(--spectrum-global-color-gray-500);
38
47
  background-color: var(--spectrum-global-color-gray-50);
39
48
  transition: all 0.1s ease-in-out;
40
49
  }
41
50
 
51
+ /* Small size */
52
+ button.small {
53
+ width: 0.85rem;
54
+ height: 0.85rem;
55
+ }
56
+
57
+ button.small i {
58
+ font-size: 0.65rem;
59
+ }
60
+
61
+ /* Medium size */
62
+ button.medium {
63
+ width: 1rem;
64
+ height: 1rem;
65
+ }
66
+
67
+ button.medium i {
68
+ font-size: 0.75rem;
69
+ }
70
+
71
+ /* Large size */
72
+ button.large {
73
+ width: 1.25rem;
74
+ height: 1.25rem;
75
+ }
76
+
77
+ button.large i {
78
+ font-size: 0.9rem;
79
+ }
80
+
42
81
  button.checked {
43
- border-color: var(--spectrum-global-color-gray-700);
82
+ border-color: var(--spectrum-global-color-blue-600) !important;
83
+ background-color: var(--spectrum-global-color-blue-600);
84
+
85
+ & i {
86
+ color: white;
87
+ font-weight: 900;
88
+ }
44
89
  }
45
90
 
46
91
  button.disabled {
@@ -49,20 +94,33 @@
49
94
  border-color: var(--spectrum-global-color-gray-300);
50
95
  }
51
96
 
52
- button:hover:not(.disabled),
53
- button.hovered:not(.disabled) {
97
+ button.locked {
98
+ border-color: transparent;
99
+ }
100
+
101
+ button.locked i {
102
+ font-size: 1rem !important;
103
+ font-weight: 400 !important;
104
+ color: var(--spectrum-global-color-gray-500) !important;
105
+ }
106
+
107
+ button:hover:not(.disabled):not(.locked):not(.checked) {
108
+ background-color: var(--spectrum-global-color-gray-100);
109
+ border-color: var(--spectrum-global-color-gray-600);
110
+ }
111
+
112
+ button.hovered:not(.disabled):not(.locked):not(.checked) {
54
113
  border: 1px solid var(--spectrum-global-color-gray-600);
55
114
  }
56
115
 
57
- button:active {
116
+ button:active:not(.disabled):not(.locked):not(.checked) {
58
117
  background-color: var(--spectrum-global-color-blue-100);
59
118
  }
60
- button:focus {
119
+ button:focus:not(.disabled):not(.locked) {
61
120
  border: 1px solid var(--spectrum-global-color-gray-700);
62
121
  }
63
122
 
64
123
  i {
65
- font-size: 0.65rem;
66
124
  font-weight: 700;
67
125
  color: var(--spectrum-global-color-gray-700);
68
126
  animation: scaleIn 0.13s ease-out;
@@ -0,0 +1,162 @@
1
+ <script lang="ts">
2
+ import { createEventDispatcher } from "svelte";
3
+ const dispatch = createEventDispatcher();
4
+
5
+ export let checked: boolean | null = false;
6
+ export let disabled: boolean = false;
7
+ export let hovered: boolean = false;
8
+ export let size: "small" | "medium" | "large" = "medium";
9
+ export let tristate: boolean = false;
10
+
11
+ function toggle() {
12
+ if (disabled) return;
13
+
14
+ if (tristate) {
15
+ // Three-state cycle: off -> on -> null -> off
16
+ if (checked === false) {
17
+ checked = true;
18
+ } else if (checked === true) {
19
+ checked = null;
20
+ } else {
21
+ checked = false;
22
+ }
23
+ } else {
24
+ // Two-state toggle: off -> on -> off
25
+ checked = !checked;
26
+ }
27
+
28
+ dispatch("change", { checked });
29
+ }
30
+ </script>
31
+
32
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
33
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
34
+ <div
35
+ class="switch-container {size}"
36
+ class:checked={checked === true}
37
+ class:indeterminate={checked === null}
38
+ class:disabled
39
+ class:hovered
40
+ on:click|stopPropagation={toggle}
41
+ >
42
+ <div class="switch-track">
43
+ <div class="switch-thumb"></div>
44
+ </div>
45
+ </div>
46
+
47
+ <style>
48
+ .switch-container {
49
+ display: inline-flex;
50
+ align-items: center;
51
+ cursor: pointer;
52
+ user-select: none;
53
+ }
54
+
55
+ .switch-container.disabled {
56
+ cursor: not-allowed;
57
+ opacity: 0.6;
58
+ }
59
+
60
+ .switch-track {
61
+ position: relative;
62
+ background-color: var(--spectrum-global-color-gray-400);
63
+ border-radius: 1rem;
64
+ }
65
+
66
+ .switch-thumb {
67
+ position: absolute;
68
+ background-color: var(--spectrum-global-color-gray-50);
69
+ border-radius: 50%;
70
+ transition: transform 0.2s ease-in-out;
71
+ }
72
+
73
+ /* Small size */
74
+ .switch-container.small .switch-track {
75
+ width: 2rem;
76
+ height: 1rem;
77
+ }
78
+
79
+ .switch-container.small .switch-thumb {
80
+ width: 0.7rem;
81
+ height: 0.7rem;
82
+ top: 0.15rem;
83
+ left: 0.15rem;
84
+ }
85
+
86
+ .switch-container.small.checked .switch-thumb {
87
+ transform: translateX(1rem);
88
+ }
89
+
90
+ .switch-container.small.checked .switch-track {
91
+ justify-content: flex-end;
92
+ }
93
+
94
+ .switch-container.small.indeterminate .switch-thumb {
95
+ transform: translateX(0.45rem);
96
+ }
97
+
98
+ /* Medium size */
99
+ .switch-container.medium .switch-track {
100
+ width: 2.5rem;
101
+ height: 1.25rem;
102
+ }
103
+
104
+ .switch-container.medium .switch-thumb {
105
+ width: 1rem;
106
+ height: 1rem;
107
+ top: 0.125rem;
108
+ left: 0.125rem;
109
+ }
110
+
111
+ .switch-container.medium.checked .switch-thumb {
112
+ transform: translateX(1.25rem);
113
+ }
114
+
115
+ .switch-container.medium.indeterminate .switch-thumb {
116
+ transform: translateX(0.625rem);
117
+ }
118
+
119
+ /* Large size */
120
+ .switch-container.large .switch-track {
121
+ width: 3rem;
122
+ height: 1.5rem;
123
+ }
124
+
125
+ .switch-container.large .switch-thumb {
126
+ width: 1.25rem;
127
+ height: 1.25rem;
128
+ top: 0.125rem;
129
+ left: 0.125rem;
130
+ }
131
+
132
+ .switch-container.large.checked .switch-thumb {
133
+ transform: translateX(1.5rem);
134
+ }
135
+
136
+ .switch-container.large.indeterminate .switch-thumb {
137
+ transform: translateX(0.75rem);
138
+ }
139
+
140
+ /* Checked state */
141
+ .switch-container.checked .switch-track {
142
+ background-color: var(--spectrum-global-color-blue-500);
143
+ }
144
+
145
+ /* Indeterminate state */
146
+ .switch-container.indeterminate .switch-track {
147
+ background-color: var(--spectrum-global-color-orange-500);
148
+ }
149
+
150
+ /* Hover state */
151
+ .switch-container:hover:not(.disabled),
152
+ .switch-container.hovered:not(.disabled) {
153
+ filter: brightness(1.1);
154
+ }
155
+
156
+ /* Focus state */
157
+ .switch-container:focus-visible {
158
+ outline: 2px solid var(--spectrum-global-color-blue-600);
159
+ outline-offset: 2px;
160
+ border-radius: 0.5rem;
161
+ }
162
+ </style>
@@ -0,0 +1,210 @@
1
+ <script lang="ts">
2
+ import { createEventDispatcher } from "svelte";
3
+
4
+ const dispatch = createEventDispatcher();
5
+
6
+ interface TextboxProps {
7
+ value?: string | number;
8
+ disabled?: boolean;
9
+ copyLabel?: string;
10
+ copiedLabel?: string;
11
+ title?: string;
12
+ wrap?: boolean;
13
+ monospace?: boolean;
14
+ oncopy?: (detail: { value: string }) => void;
15
+ }
16
+
17
+ let {
18
+ value = "",
19
+ disabled = false,
20
+ copyLabel = "Copy to clipboard",
21
+ copiedLabel = "Copied !",
22
+ title,
23
+ wrap = false,
24
+ monospace = true,
25
+ oncopy,
26
+ }: TextboxProps = $props();
27
+
28
+ let justCopied = $state(false);
29
+ let copyTimeout: ReturnType<typeof setTimeout> | undefined;
30
+
31
+ let stringValue = $derived(String(value ?? "").trim());
32
+
33
+ let displayValue = $derived(
34
+ justCopied && copiedLabel?.trim() ? copiedLabel : stringValue || "",
35
+ );
36
+
37
+ function copyToClipboard() {
38
+ if (disabled || !stringValue || justCopied) return;
39
+
40
+ navigator.clipboard
41
+ .writeText(stringValue)
42
+ .then(() => {
43
+ justCopied = true;
44
+ const detail = { value: stringValue };
45
+
46
+ dispatch("copy", detail);
47
+ oncopy?.(detail);
48
+
49
+ if (copyTimeout) clearTimeout(copyTimeout);
50
+ copyTimeout = setTimeout(() => {
51
+ justCopied = false;
52
+ copyTimeout = undefined;
53
+ }, 800);
54
+ })
55
+ .catch((err) => {
56
+ console.error("Failed to copy to clipboard:", err);
57
+ });
58
+ }
59
+
60
+ function handleKeydown(e: KeyboardEvent) {
61
+ if (disabled) return;
62
+ if ((e.key === "Enter" || e.key === " ") && !justCopied) {
63
+ e.preventDefault();
64
+ copyToClipboard();
65
+ }
66
+ }
67
+
68
+ $effect(() => {
69
+ // Cleanup any pending timeout when the component is destroyed
70
+ return () => {
71
+ if (copyTimeout) clearTimeout(copyTimeout);
72
+ };
73
+ });
74
+ </script>
75
+
76
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
77
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
78
+ <span
79
+ class="textbox value copyable"
80
+ class:copied={justCopied}
81
+ class:disabled
82
+ class:monospace
83
+ role="button"
84
+ tabindex={disabled ? -1 : 0}
85
+ title={justCopied ? "" : (title ?? (stringValue ? copyLabel : ""))}
86
+ onclick={copyToClipboard}
87
+ onkeydown={handleKeydown}
88
+ >
89
+ <span class="textbox-text" class:wrap>
90
+ {displayValue}
91
+ </span>
92
+
93
+ {#if !justCopied && stringValue}
94
+ <span class="copy-icon">
95
+ <svg
96
+ xmlns="http://www.w3.org/2000/svg"
97
+ width="13"
98
+ height="13"
99
+ viewBox="0 0 24 24"
100
+ fill="none"
101
+ stroke="currentColor"
102
+ stroke-width="2.25"
103
+ stroke-linecap="round"
104
+ stroke-linejoin="round"
105
+ >
106
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
107
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
108
+ ></path>
109
+ </svg>
110
+ </span>
111
+ {/if}
112
+ </span>
113
+
114
+ <style>
115
+ .textbox.value {
116
+ color: var(--spectrum-global-color-gray-700);
117
+ border: 1px solid var(--spectrum-global-color-gray-300);
118
+ border-radius: 0.25rem;
119
+ padding: 0.5rem 0.75rem;
120
+ background: rgb(from var(--spectrum-global-color-gray-50) r g b / 0.5);
121
+ font-family: monospace;
122
+ font-size: 12px;
123
+ display: flex;
124
+ align-items: center;
125
+ gap: 0.5rem;
126
+ }
127
+
128
+ .textbox.value:not(.monospace) {
129
+ font-family: var(
130
+ --spectrum-global-font-family,
131
+ system-ui,
132
+ -apple-system,
133
+ sans-serif
134
+ );
135
+ font-size: 13px;
136
+ }
137
+
138
+ .textbox.value.copyable {
139
+ cursor: pointer;
140
+ transition:
141
+ background-color 0.1s ease,
142
+ border-color 0.1s ease;
143
+ min-width: 0;
144
+ justify-content: space-between;
145
+ }
146
+
147
+ .textbox.value.copyable:hover:not(.disabled) {
148
+ background-color: var(--spectrum-global-color-gray-100);
149
+ }
150
+
151
+ .textbox.value.copyable:focus:not(.disabled) {
152
+ outline: 1px solid var(--spectrum-global-color-gray-500);
153
+ background-color: var(--spectrum-global-color-gray-100);
154
+ outline-offset: 1px;
155
+ }
156
+
157
+ .textbox.value.copyable.copied {
158
+ border-color: var(--spectrum-global-color-gray-500);
159
+ background-color: var(--spectrum-global-color-gray-100);
160
+ color: var(--spectrum-global-color-gray-600);
161
+ font-weight: 600;
162
+ }
163
+
164
+ .textbox.value.copyable.disabled {
165
+ cursor: not-allowed;
166
+ opacity: 0.6;
167
+ pointer-events: none;
168
+ }
169
+
170
+ .textbox.value .copy-icon {
171
+ opacity: 0;
172
+ transition: opacity 0.15s ease;
173
+ flex-shrink: 0;
174
+ color: var(--spectrum-global-color-gray-600);
175
+ display: flex;
176
+ align-items: center;
177
+ }
178
+
179
+ .textbox.value.copyable:hover:not(.disabled) .copy-icon {
180
+ opacity: 0.65;
181
+ }
182
+
183
+ .textbox.value.copyable:focus:not(.disabled) .copy-icon {
184
+ opacity: 0.65;
185
+ }
186
+
187
+ .textbox.value.copyable:hover:not(.disabled) .copy-icon:hover {
188
+ opacity: 1;
189
+ }
190
+
191
+ .textbox-text {
192
+ flex: 1 1 auto;
193
+ min-width: 0;
194
+ overflow: hidden;
195
+ text-overflow: ellipsis;
196
+ white-space: nowrap;
197
+ }
198
+
199
+ /* Ensure the icon never shrinks and always has space when text is truncated */
200
+ .textbox.value .copy-icon {
201
+ flex-shrink: 0;
202
+ }
203
+
204
+ .textbox-text.wrap {
205
+ white-space: normal;
206
+ overflow: visible;
207
+ text-overflow: unset;
208
+ word-break: break-word;
209
+ }
210
+ </style>
@@ -1,59 +1,30 @@
1
1
  <script>
2
2
  import SuperPopover from "../../SuperPopover/SuperPopover.svelte";
3
- import { onDestroy } from "svelte";
4
3
 
5
4
  export let anchor;
6
5
  export let content;
7
6
  export let show = false;
8
- export let delay = 750;
9
7
  export let align = "top";
10
-
11
- let timer;
12
- let isHovered = false;
13
-
14
- const startTimer = () => {
15
- if (timer) clearTimeout(timer);
16
- timer = setTimeout(() => {
17
- show = true;
18
- }, delay);
19
- };
20
-
21
- const clearTimer = () => {
22
- if (timer) {
23
- clearTimeout(timer);
24
- timer = null;
25
- }
26
- show = false;
27
- };
28
-
29
- const handleMouseEnter = () => {
30
- isHovered = true;
31
- startTimer();
32
- };
33
-
34
- const handleMouseLeave = () => {
35
- isHovered = false;
36
- clearTimer();
37
- };
38
-
39
- onDestroy(() => {
40
- clearTimer();
41
- });
42
8
  </script>
43
9
 
44
- {#if show}
45
- <SuperPopover {anchor} {align} open={show} dismissible={false} animate={true}>
46
- <div class="tooltip-content info">
47
- {content}
48
- </div>
49
- </SuperPopover>
50
- {/if}
10
+ <SuperPopover
11
+ {anchor}
12
+ {align}
13
+ open={show}
14
+ dismissible={false}
15
+ animate={true}
16
+ customZindex={1000}
17
+ offsetBelow={12}
18
+ >
19
+ <div class="tooltip-content info">
20
+ {content}
21
+ </div>
22
+ </SuperPopover>
51
23
 
52
24
  <style>
53
25
  .tooltip-content {
54
- padding: 8px 12px;
26
+ padding: 4px 12px;
55
27
  font-size: 12px;
56
- line-height: 1.4;
57
28
  color: var(--spectrum-global-color-gray-700);
58
29
  background-color: var(--spectrum-global-color-gray-50);
59
30
  border: 1px solid var(--spectrum-global-color-gray-300);
@@ -64,6 +35,7 @@
64
35
  }
65
36
 
66
37
  .tooltip-content.info {
38
+ padding: 4px 12px;
67
39
  background-color: var(--spectrum-global-color-blue-100);
68
40
  border-color: rgb(from var(--spectrum-global-color-blue-500) r g b / 50%);
69
41
  color: var(--spectrum-global-color-gray-800);