@tableslayer/ui 0.1.3 → 0.1.4

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 (205) hide show
  1. package/package.json +2 -13
  2. package/src/lib/components/Avatar/Avatar.svelte +82 -0
  3. package/src/lib/components/Avatar/AvatarFileInput.svelte +85 -0
  4. package/src/lib/components/Avatar/AvatarPopover.svelte +34 -0
  5. package/src/lib/components/Avatar/index.ts +4 -0
  6. package/src/lib/components/Avatar/types.ts +24 -0
  7. package/src/lib/components/BrushSizeSlider/BrushSizeSlider.svelte +174 -0
  8. package/src/lib/components/BrushSizeSlider/index.ts +1 -0
  9. package/src/lib/components/Button/Button.svelte +182 -0
  10. package/src/lib/components/Button/ConfirmActionButton.svelte +98 -0
  11. package/src/lib/components/Button/IconButton.svelte +121 -0
  12. package/src/lib/components/Button/RadioButton.svelte +93 -0
  13. package/src/lib/components/Button/index.ts +5 -0
  14. package/src/lib/components/Button/types.ts +54 -0
  15. package/src/lib/components/CardFan/CardFan.svelte +165 -0
  16. package/src/lib/components/CardFan/index.ts +2 -0
  17. package/src/lib/components/CardFan/types.ts +6 -0
  18. package/src/lib/components/CodeBlock/Code.svelte +7 -0
  19. package/src/lib/components/CodeBlock/CodeBlock.svelte +102 -0
  20. package/src/lib/components/CodeBlock/index.ts +3 -0
  21. package/src/lib/components/CodeBlock/types.ts +10 -0
  22. package/src/lib/components/ColorMode/ColorMode.svelte +8 -0
  23. package/src/lib/components/ColorMode/index.ts +2 -0
  24. package/src/lib/components/ColorMode/types.ts +12 -0
  25. package/src/lib/components/ColorPicker/ColorPicker.svelte +838 -0
  26. package/src/lib/components/ColorPicker/ColorPickerSwatch.svelte +32 -0
  27. package/src/lib/components/ColorPicker/index.ts +3 -0
  28. package/src/lib/components/ColorPicker/types.ts +51 -0
  29. package/src/lib/components/ContextMenu/ContextMenu.svelte +86 -0
  30. package/src/lib/components/ContextMenu/index.ts +2 -0
  31. package/src/lib/components/ContextMenu/types.ts +15 -0
  32. package/src/lib/components/DrawingSliders/DrawingSliders.svelte +379 -0
  33. package/src/lib/components/DrawingSliders/index.ts +1 -0
  34. package/src/lib/components/Editor/Editor.svelte +825 -0
  35. package/src/lib/components/Editor/index.ts +1 -0
  36. package/src/lib/components/FogSliders/FogSliders.svelte +33 -0
  37. package/src/lib/components/FogSliders/index.ts +1 -0
  38. package/src/lib/components/Hr/Hr.svelte +15 -0
  39. package/src/lib/components/Hr/index.ts +1 -0
  40. package/src/lib/components/Icon/Icon.svelte +6 -0
  41. package/src/lib/components/Icon/index.ts +2 -0
  42. package/src/lib/components/Icon/types.ts +20 -0
  43. package/src/lib/components/Input/DualInputSlider.svelte +126 -0
  44. package/src/lib/components/Input/FileInput.svelte +176 -0
  45. package/src/lib/components/Input/FormControl.svelte +150 -0
  46. package/src/lib/components/Input/FormError.svelte +37 -0
  47. package/src/lib/components/Input/Input.svelte +56 -0
  48. package/src/lib/components/Input/InputCheckbox.svelte +99 -0
  49. package/src/lib/components/Input/InputSlider.svelte +86 -0
  50. package/src/lib/components/Input/Label.svelte +19 -0
  51. package/src/lib/components/Input/index.ts +9 -0
  52. package/src/lib/components/Input/types.ts +39 -0
  53. package/src/lib/components/Link/Link.svelte +41 -0
  54. package/src/lib/components/Link/LinkBox.svelte +20 -0
  55. package/src/lib/components/Link/LinkOverlay.svelte +23 -0
  56. package/src/lib/components/Link/index.ts +4 -0
  57. package/src/lib/components/Link/types.ts +17 -0
  58. package/src/lib/components/Loading/Loader.svelte +60 -0
  59. package/src/lib/components/Loading/Skeleton.svelte +9 -0
  60. package/src/lib/components/Loading/index.ts +2 -0
  61. package/src/lib/components/Logo/Logo.svelte +16 -0
  62. package/src/lib/components/Logo/index.ts +1 -0
  63. package/src/lib/components/MarkerTooltip/MarkerTooltip.svelte +435 -0
  64. package/src/lib/components/MarkerTooltip/index.ts +1 -0
  65. package/src/lib/components/Menu/SelectorMenu.svelte +280 -0
  66. package/src/lib/components/Menu/index.ts +2 -0
  67. package/src/lib/components/Menu/types.ts +17 -0
  68. package/src/lib/components/MyCounterButton.svelte +11 -0
  69. package/src/lib/components/Panel/index.ts +2 -0
  70. package/src/lib/components/Panel/panel.svelte +18 -0
  71. package/src/lib/components/Panel/types.ts +8 -0
  72. package/src/lib/components/PersistButton/PersistButton.svelte +100 -0
  73. package/src/lib/components/PersistButton/index.ts +1 -0
  74. package/src/lib/components/Popover/Popover.svelte +81 -0
  75. package/src/lib/components/Popover/index.ts +2 -0
  76. package/src/lib/components/Popover/types.ts +19 -0
  77. package/src/lib/components/PropsTable/PropsTable.svelte +107 -0
  78. package/src/lib/components/RadialMenu/EffectPreview.svelte +36 -0
  79. package/src/lib/components/RadialMenu/EffectPreviewScene.svelte +194 -0
  80. package/src/lib/components/RadialMenu/RadialMenu.svelte +503 -0
  81. package/src/lib/components/RadialMenu/RadialMenuItem.svelte +176 -0
  82. package/src/lib/components/RadialMenu/index.ts +2 -0
  83. package/src/lib/components/RadialMenu/types.ts +35 -0
  84. package/src/lib/components/Select/Select.svelte +342 -0
  85. package/src/lib/components/Select/index.ts +2 -0
  86. package/src/lib/components/Select/types.ts +22 -0
  87. package/src/lib/components/Spacer/Spacer.svelte +14 -0
  88. package/src/lib/components/Spacer/index.ts +2 -0
  89. package/src/lib/components/Spacer/types.ts +5 -0
  90. package/src/lib/components/Stage/components/AnnotationLayer/AnnotationLayer.svelte +445 -0
  91. package/src/lib/components/Stage/components/AnnotationLayer/AnnotationMaterial.svelte +167 -0
  92. package/src/lib/components/Stage/components/AnnotationLayer/types.ts +196 -0
  93. package/src/lib/components/Stage/components/CursorLayer/CursorLayer.svelte +148 -0
  94. package/src/lib/components/Stage/components/CursorLayer/cursor.svg +26 -0
  95. package/src/lib/components/Stage/components/CursorLayer/index.ts +2 -0
  96. package/src/lib/components/Stage/components/CursorLayer/types.ts +23 -0
  97. package/src/lib/components/Stage/components/DrawingLayer/DrawingMaterial.svelte +364 -0
  98. package/src/lib/components/Stage/components/DrawingLayer/types.ts +65 -0
  99. package/src/lib/components/Stage/components/EdgeOverlayLayer/EdgeOverlayLayer.svelte +72 -0
  100. package/src/lib/components/Stage/components/EdgeOverlayLayer/types.ts +34 -0
  101. package/src/lib/components/Stage/components/FogLayer/FogLayer.svelte +75 -0
  102. package/src/lib/components/Stage/components/FogLayer/types.ts +51 -0
  103. package/src/lib/components/Stage/components/FogOfWarLayer/FogOfWarLayer.svelte +249 -0
  104. package/src/lib/components/Stage/components/FogOfWarLayer/FogOfWarMaterial.svelte +200 -0
  105. package/src/lib/components/Stage/components/FogOfWarLayer/types.ts +116 -0
  106. package/src/lib/components/Stage/components/GridLayer/GridLayer.svelte +20 -0
  107. package/src/lib/components/Stage/components/GridLayer/GridMaterial.svelte +69 -0
  108. package/src/lib/components/Stage/components/GridLayer/types.ts +79 -0
  109. package/src/lib/components/Stage/components/LayerInput/LayerInput.svelte +300 -0
  110. package/src/lib/components/Stage/components/MapLayer/MapLayer.svelte +196 -0
  111. package/src/lib/components/Stage/components/MapLayer/dataSources/GifDataSource.ts +265 -0
  112. package/src/lib/components/Stage/components/MapLayer/dataSources/IMapDataSource.ts +55 -0
  113. package/src/lib/components/Stage/components/MapLayer/dataSources/ImageDataSource.ts +87 -0
  114. package/src/lib/components/Stage/components/MapLayer/dataSources/VideoDataSource.ts +150 -0
  115. package/src/lib/components/Stage/components/MapLayer/dataSources/dataSourceFactory.ts +48 -0
  116. package/src/lib/components/Stage/components/MapLayer/dataSources/index.ts +16 -0
  117. package/src/lib/components/Stage/components/MapLayer/types.ts +58 -0
  118. package/src/lib/components/Stage/components/MarkerLayer/MarkerLayer.svelte +398 -0
  119. package/src/lib/components/Stage/components/MarkerLayer/MarkerToken.svelte +262 -0
  120. package/src/lib/components/Stage/components/MarkerLayer/types.ts +126 -0
  121. package/src/lib/components/Stage/components/MeasurementLayer/MeasurementLayer.svelte +364 -0
  122. package/src/lib/components/Stage/components/MeasurementLayer/MeasurementManager.svelte +473 -0
  123. package/src/lib/components/Stage/components/MeasurementLayer/measurements/BaseMeasurement.ts +427 -0
  124. package/src/lib/components/Stage/components/MeasurementLayer/measurements/BeamMeasurement.ts +105 -0
  125. package/src/lib/components/Stage/components/MeasurementLayer/measurements/CircleMeasurement.ts +98 -0
  126. package/src/lib/components/Stage/components/MeasurementLayer/measurements/ConeMeasurement.ts +163 -0
  127. package/src/lib/components/Stage/components/MeasurementLayer/measurements/LineMeasurement.ts +102 -0
  128. package/src/lib/components/Stage/components/MeasurementLayer/measurements/RectangleMeasurement.ts +120 -0
  129. package/src/lib/components/Stage/components/MeasurementLayer/measurements/index.ts +7 -0
  130. package/src/lib/components/Stage/components/MeasurementLayer/types.ts +94 -0
  131. package/src/lib/components/Stage/components/MeasurementLayer/utils/canvasDrawing.ts +357 -0
  132. package/src/lib/components/Stage/components/MeasurementLayer/utils/distanceCalculations.ts +170 -0
  133. package/src/lib/components/Stage/components/ParticleSystem/ParticleSystem.svelte +220 -0
  134. package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/ash.png +0 -0
  135. package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/leaves.png +0 -0
  136. package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/rain.png +0 -0
  137. package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/snow.png +0 -0
  138. package/src/lib/components/Stage/components/ParticleSystem/rng.js +20 -0
  139. package/src/lib/components/Stage/components/ParticleSystem/types.ts +95 -0
  140. package/src/lib/components/Stage/components/PerformanceDebugger/PerformanceDebugger.svelte +144 -0
  141. package/src/lib/components/Stage/components/PerformanceDebugger/index.ts +1 -0
  142. package/src/lib/components/Stage/components/PerformanceOverlay/PerformanceOverlay.svelte +208 -0
  143. package/src/lib/components/Stage/components/PerformanceOverlay/index.ts +1 -0
  144. package/src/lib/components/Stage/components/PointerInputManager/PointerInputManager.svelte +201 -0
  145. package/src/lib/components/Stage/components/Scene/Scene.svelte +651 -0
  146. package/src/lib/components/Stage/components/Scene/luts.ts +24 -0
  147. package/src/lib/components/Stage/components/Scene/types.ts +225 -0
  148. package/src/lib/components/Stage/components/Stage/Stage.svelte +332 -0
  149. package/src/lib/components/Stage/components/Stage/types.ts +136 -0
  150. package/src/lib/components/Stage/components/WeatherLayer/WeatherLayer.svelte +135 -0
  151. package/src/lib/components/Stage/components/WeatherLayer/presets/AshPreset.ts +71 -0
  152. package/src/lib/components/Stage/components/WeatherLayer/presets/LeavesPreset.ts +70 -0
  153. package/src/lib/components/Stage/components/WeatherLayer/presets/RainPreset.ts +68 -0
  154. package/src/lib/components/Stage/components/WeatherLayer/presets/SnowPreset.ts +70 -0
  155. package/src/lib/components/Stage/components/WeatherLayer/presets/index.ts +6 -0
  156. package/src/lib/components/Stage/components/WeatherLayer/types.ts +35 -0
  157. package/src/lib/components/Stage/helpers/clippingPlaneStore.svelte.ts +28 -0
  158. package/src/lib/components/Stage/helpers/debugState.svelte.ts +18 -0
  159. package/src/lib/components/Stage/helpers/grid.ts +548 -0
  160. package/src/lib/components/Stage/helpers/lazyBrush.ts +171 -0
  161. package/src/lib/components/Stage/helpers/performanceMetrics.svelte.ts +220 -0
  162. package/src/lib/components/Stage/helpers/utils.ts +21 -0
  163. package/src/lib/components/Stage/index.ts +49 -0
  164. package/src/lib/components/Stage/shaders/AnnotationEffects.frag +1070 -0
  165. package/src/lib/components/Stage/shaders/Annotations.frag +29 -0
  166. package/src/lib/components/Stage/shaders/Drawing.frag +83 -0
  167. package/src/lib/components/Stage/shaders/Drawing.vert +5 -0
  168. package/src/lib/components/Stage/shaders/Fog.frag +147 -0
  169. package/src/lib/components/Stage/shaders/FractalNoise.frag +96 -0
  170. package/src/lib/components/Stage/shaders/GridShader.frag +174 -0
  171. package/src/lib/components/Stage/shaders/Overlay.frag +23 -0
  172. package/src/lib/components/Stage/shaders/Overlay.vert +0 -0
  173. package/src/lib/components/Stage/shaders/Particles.frag +27 -0
  174. package/src/lib/components/Stage/shaders/Particles.vert +51 -0
  175. package/src/lib/components/Stage/shaders/ToolOutline.frag +59 -0
  176. package/src/lib/components/Stage/shaders/default.vert +8 -0
  177. package/src/lib/components/Stage/types.ts +4 -0
  178. package/src/lib/components/Table/Table.svelte +16 -0
  179. package/src/lib/components/Table/Td.svelte +17 -0
  180. package/src/lib/components/Table/Th.svelte +18 -0
  181. package/src/lib/components/Table/index.ts +4 -0
  182. package/src/lib/components/Table/types.ts +14 -0
  183. package/src/lib/components/Text/Text.svelte +23 -0
  184. package/src/lib/components/Text/index.ts +2 -0
  185. package/src/lib/components/Text/types.ts +12 -0
  186. package/src/lib/components/Title/Title.svelte +54 -0
  187. package/src/lib/components/Title/index.ts +2 -0
  188. package/src/lib/components/Title/types.ts +9 -0
  189. package/src/lib/components/Toast/Toast.svelte +155 -0
  190. package/src/lib/components/Toast/index.ts +5 -0
  191. package/src/lib/components/Toast/toastCookie.ts +24 -0
  192. package/src/lib/components/Toast/types.ts +6 -0
  193. package/src/lib/components/ToolTip/ToolTip.svelte +70 -0
  194. package/src/lib/components/ToolTip/index.ts +2 -0
  195. package/src/lib/components/ToolTip/types.ts +14 -0
  196. package/src/lib/components/index.ts +32 -0
  197. package/src/lib/components/types.ts +0 -0
  198. package/src/lib/index.ts +2 -0
  199. package/src/lib/styles/globals.css +108 -0
  200. package/src/lib/styles/normalize.css +9 -0
  201. package/src/lib/styles/reset.css +133 -0
  202. package/src/lib/styles/utilities.css +179 -0
  203. package/src/lib/styles/vars.css +1103 -0
  204. package/src/lib/types/awareness.ts +17 -0
  205. package/src/lib/utils/rle.ts +217 -0
@@ -0,0 +1,98 @@
1
+ <script lang="ts">
2
+ import { computePosition, offset, flip, shift, platform } from '@floating-ui/dom';
3
+ import { Button, type ConfirmActionButtonProps } from './';
4
+ import { tick } from 'svelte';
5
+
6
+ let {
7
+ trigger,
8
+ actionMessage,
9
+ actionButtonText = 'Confirm delete',
10
+ action,
11
+ isLoading,
12
+ positioning = { placement: 'bottom' },
13
+ ...restProps
14
+ }: ConfirmActionButtonProps = $props();
15
+
16
+ let triggerElement: HTMLElement | null = null;
17
+ let popoverElement = $state<HTMLElement | null>(null);
18
+ let isShowingConfirm = $state(false);
19
+ let floatingStyles = $state('');
20
+
21
+ const toggleShowConfirm = async () => {
22
+ isShowingConfirm = true;
23
+ await tick();
24
+ updatePosition();
25
+ };
26
+
27
+ const triggerProps = {
28
+ onclick: () => {
29
+ toggleShowConfirm();
30
+ }
31
+ };
32
+
33
+ function updatePosition() {
34
+ if (!triggerElement || !popoverElement) {
35
+ return;
36
+ }
37
+
38
+ computePosition(triggerElement, popoverElement, {
39
+ placement: positioning?.placement,
40
+ middleware: [offset(({ rects }) => -rects.reference.height / 2 - rects.floating.height / 2), flip(), shift()],
41
+ platform
42
+ })
43
+ .then(({ x, y, strategy }) => {
44
+ floatingStyles = `position: ${strategy}; left: ${x}px; top: ${y}px;`;
45
+ })
46
+ .catch((error) => {
47
+ console.error('Error in computePosition:', error);
48
+ });
49
+ }
50
+
51
+ const handleGlobalClick = (e: MouseEvent) => {
52
+ if (isShowingConfirm && popoverElement && triggerElement) {
53
+ const target = e.target as Node;
54
+ if (!popoverElement.contains(target) && !triggerElement.contains(target)) {
55
+ isShowingConfirm = false;
56
+ }
57
+ }
58
+ };
59
+ </script>
60
+
61
+ <svelte:window onclick={handleGlobalClick} />
62
+
63
+ <div class="confirmAction" bind:this={triggerElement} {...restProps}>
64
+ {@render trigger({ triggerProps })}
65
+ </div>
66
+
67
+ {#if isShowingConfirm}
68
+ <div bind:this={popoverElement} class="confirmAction__content" style={floatingStyles}>
69
+ {@render actionMessage()}
70
+ <div class="confirmAction__buttons">
71
+ <Button onclick={action} variant="danger" {isLoading} data-testid="confirmActionButton">
72
+ {actionButtonText}
73
+ </Button>
74
+ <Button onclick={() => (isShowingConfirm = false)} variant="ghost">Cancel</Button>
75
+ </div>
76
+ </div>
77
+ {/if}
78
+
79
+ <style>
80
+ .confirmAction {
81
+ display: inline-flex;
82
+ flex-direction: column;
83
+ align-items: center;
84
+ }
85
+ .confirmAction__content {
86
+ background-color: var(--popoverBg);
87
+ border-radius: var(--radius-2);
88
+ box-shadow: var(--shadow-1);
89
+ padding: 1rem;
90
+ z-index: 1000;
91
+ border: var(--borderThin);
92
+ }
93
+ .confirmAction__buttons {
94
+ margin-top: 0.5rem;
95
+ display: flex;
96
+ gap: 0.5rem;
97
+ }
98
+ </style>
@@ -0,0 +1,121 @@
1
+ <script lang="ts">
2
+ import type { IconButtonProps } from './types';
3
+
4
+ let { children, size = 'md', href, as, variant = 'primary', ...restProps }: IconButtonProps = $props();
5
+
6
+ const iconBtnClasses = $derived(['iconBtn', `iconBtn--${size}`, `iconBtn--${variant}`, restProps.class ?? '']);
7
+ const component = as ?? 'button';
8
+ let iconButtonProps = $state({});
9
+ if (component === 'a') {
10
+ iconButtonProps = { href };
11
+ }
12
+ </script>
13
+
14
+ <svelte:element this={component} {...iconButtonProps} {...restProps} class={iconBtnClasses}>
15
+ {@render children()}
16
+ </svelte:element>
17
+
18
+ <style>
19
+ :global(.light) {
20
+ --iconBtn-bg: var(--contrastEmpty);
21
+ --iconBtn-bgHover: var(--primary-50);
22
+ --iconBtn-border: solid 2px var(--fg);
23
+ --iconBtn-borderHover: solid 2px var(--primary-600);
24
+ --iconBtn-color: var(--fg);
25
+ --iconBtn-dangerStripesHover: var(--primary-300);
26
+ }
27
+
28
+ :global(.dark) {
29
+ color-scheme: dark;
30
+ --iconBtn-bg: var(--bg);
31
+ --iconBtn-bgHover: var(--primary-950);
32
+ --iconBtn-border: solid 2px var(--fg);
33
+ --iconBtn-borderHover: solid 2px var(--primary-500);
34
+ --iconBtn-color: var(--fg);
35
+ --iconBtn-dangerStripesHover: var(--primary-700);
36
+ }
37
+ .iconBtn {
38
+ color: var(--iconBtn-color);
39
+ background-color: var(--iconBtn-bg);
40
+ border-radius: var(--radius-2);
41
+ display: inline-flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ gap: var(--size-2);
45
+ cursor: pointer;
46
+ font-weight: var(--font-weight-5);
47
+ border: var(--iconBtn-border);
48
+ border-color: transparent;
49
+ font-weight: var(--font-weight-6);
50
+ }
51
+
52
+ .iconBtn--sm {
53
+ font-size: var(--font-size-1);
54
+ height: var(--size-6);
55
+ width: var(--size-6);
56
+ min-width: var(--size-6);
57
+ }
58
+ .iconBtn--md {
59
+ font-size: var(--font-size-1);
60
+ height: var(--size-8);
61
+ width: var(--size-8);
62
+ min-width: var(--size-8);
63
+ }
64
+ .iconBtn--lg {
65
+ font-size: var(--font-size-2);
66
+ height: var(--size-9);
67
+ width: var(--size-9);
68
+ min-width: var(--size-9);
69
+ }
70
+ .iconBtn--primary {
71
+ border-color: var(--fg);
72
+ }
73
+ .iconBtn--danger {
74
+ border-color: var(--fg);
75
+ background-image: linear-gradient(
76
+ 135deg,
77
+ transparent 10%,
78
+ transparent 10%,
79
+ transparent 50%,
80
+ color-mix(in srgb, var(--fg), transparent 40%) 50%,
81
+ color-mix(in srgb, var(--fg), transparent 40%) 50%,
82
+ transparent 60%,
83
+ transparent 100%
84
+ );
85
+ background-size: 14.14px 14.14px;
86
+ text-shadow: 0 0 4px var(--bg);
87
+ }
88
+ .iconBtn--danger:hover {
89
+ background-image: linear-gradient(
90
+ 135deg,
91
+ transparent 10%,
92
+ transparent 10%,
93
+ transparent 50%,
94
+ var(--iconBtn-dangerStripesHover),
95
+ var(--iconBtn-dangerStripesHover),
96
+ transparent 60%,
97
+ transparent 100%
98
+ );
99
+ }
100
+ .iconBtn:hover {
101
+ background-color: var(--iconBtn-bgHover);
102
+ border: var(--iconBtn-borderHover);
103
+ }
104
+ .iconBtn--isDisabled {
105
+ cursor: pointer;
106
+ }
107
+ .iconBtn--ghost {
108
+ background: none;
109
+ border-color: transparent;
110
+ }
111
+ .iconBtn--link {
112
+ background: none;
113
+ border-color: transparent;
114
+ color: var(--fgPrimary);
115
+ }
116
+ .iconBtn--link:hover {
117
+ background: none;
118
+ border-color: transparent;
119
+ text-decoration: underline;
120
+ }
121
+ </style>
@@ -0,0 +1,93 @@
1
+ <script lang="ts">
2
+ import type { RadioButtonProps } from './types';
3
+
4
+ let { options, selected = '', variant = 'default', onSelectedChange, ...restProps }: RadioButtonProps = $props();
5
+
6
+ function handleChange(value: string) {
7
+ selected = value;
8
+ onSelectedChange?.(value);
9
+ }
10
+
11
+ const radioClasses = (value: string) =>
12
+ ['radioButton', `radioButton--${variant}`, value === selected ? 'radioButton--checked' : ''].join(' ');
13
+
14
+ let radioGroupClasses = $derived(['radioGroup', restProps.class ?? '']);
15
+ </script>
16
+
17
+ <!--
18
+ @component
19
+ ## RadioButton
20
+
21
+ A radio button component styled like a segmented button group.
22
+
23
+ @props
24
+ - `options` - Array of `{ label, value }` objects for each option.
25
+ - `variant` - Optional styling variant.
26
+ - `selected` - The currently selected value (bindable).
27
+ - `onchange` - Callback when selection changes.
28
+ -->
29
+
30
+ <div {...restProps} class={radioGroupClasses}>
31
+ {#each options as { label, value }}
32
+ <label class={radioClasses(value)}>
33
+ <input
34
+ type="radio"
35
+ name="radio"
36
+ checked={value === selected}
37
+ {value}
38
+ bind:group={selected}
39
+ onchange={() => handleChange(value)}
40
+ />
41
+ {#if typeof label === 'string'}
42
+ {label}
43
+ {:else}
44
+ {@render label()}
45
+ {/if}
46
+ </label>
47
+ {/each}
48
+ </div>
49
+
50
+ <style>
51
+ .radioGroup {
52
+ display: inline-flex;
53
+ border-radius: var(--radius-2);
54
+ overflow: hidden;
55
+ height: var(--size-8);
56
+ border: var(--borderThin);
57
+ border-color: var(--inputBorderColor);
58
+ }
59
+
60
+ .radioButton {
61
+ display: flex;
62
+ align-items: center;
63
+ justify-content: center;
64
+ font-size: var(--font-size-1);
65
+ min-width: 2rem;
66
+ height: 100%;
67
+ cursor: pointer;
68
+ border: none;
69
+ padding: 0 0.5rem;
70
+ transition:
71
+ background-color 0.2s ease,
72
+ border-color 0.2s ease;
73
+ user-select: none;
74
+ font-weight: 600;
75
+ font-size: 0.875rem;
76
+ }
77
+
78
+ .radioButton input {
79
+ display: none;
80
+ }
81
+
82
+ .radioButton--default {
83
+ background-color: var(--btn-bg);
84
+ color: var(--fgMuted);
85
+ }
86
+ .radioButton--default:hover {
87
+ text-decoration: underline;
88
+ }
89
+ .radioButton--default.radioButton--checked {
90
+ background-color: var(--inputBorderColor);
91
+ color: var(--fg);
92
+ }
93
+ </style>
@@ -0,0 +1,5 @@
1
+ export { default as Button } from './Button.svelte';
2
+ export { default as ConfirmActionButton } from './ConfirmActionButton.svelte';
3
+ export { default as IconButton } from './IconButton.svelte';
4
+ export { default as RadioButton } from './RadioButton.svelte';
5
+ export * from './types';
@@ -0,0 +1,54 @@
1
+ import type { FloatingConfig } from '@melt-ui/svelte/internal/actions';
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAnchorAttributes, HTMLButtonAttributes, SvelteHTMLElements } from 'svelte/elements';
4
+
5
+ export type _ButtonProps = {
6
+ children: Snippet;
7
+ /**
8
+ * Renders inside of a flex before the children.
9
+ */
10
+ start?: Snippet;
11
+ /**
12
+ * Renders inside of a flex after the children.
13
+ */
14
+ end?: Snippet;
15
+ isLoading?: boolean;
16
+ isDisabled?: boolean;
17
+ as?: keyof SvelteHTMLElements;
18
+ /**
19
+ * Size of the button.
20
+ * @default md
21
+ */
22
+ size?: 'sm' | 'md' | 'lg';
23
+ variant?: 'primary' | 'ghost' | 'danger' | 'link' | 'special';
24
+ href?: string;
25
+ };
26
+
27
+ export type ButtonProps = (_ButtonProps & HTMLButtonAttributes) | (_ButtonProps & HTMLAnchorAttributes);
28
+
29
+ export type _IconButtonProps = {
30
+ children: Snippet;
31
+ size?: 'sm' | 'md' | 'lg';
32
+ variant?: 'primary' | 'ghost' | 'danger' | 'link';
33
+ href?: string;
34
+ as?: keyof SvelteHTMLElements;
35
+ };
36
+
37
+ export type IconButtonProps = (_IconButtonProps & HTMLButtonAttributes) | (_IconButtonProps & HTMLAnchorAttributes);
38
+
39
+ export type ConfirmActionButtonProps = {
40
+ trigger: Snippet<[{ triggerProps: { onclick: (e: Event) => void } }]>;
41
+ actionMessage: Snippet;
42
+ action: (e: Event) => void;
43
+ actionButtonText?: string;
44
+ isLoading?: boolean;
45
+ positioning?: FloatingConfig;
46
+ };
47
+
48
+ export type RadioOption = { label: string | Snippet; value: string };
49
+ export type RadioButtonProps = {
50
+ options: RadioOption[];
51
+ variant?: 'default';
52
+ selected: string;
53
+ onSelectedChange?: (value: string) => void;
54
+ } & SvelteHTMLElements['div'];
@@ -0,0 +1,165 @@
1
+ <script lang="ts">
2
+ import type { CardFanProps } from './types';
3
+ let { images, height = '120px', ...restProps }: CardFanProps = $props();
4
+ const cardFanClasses = $derived(['cardFan', `cardFan--count-${images.length}`, restProps.class ?? '']);
5
+ </script>
6
+
7
+ <div {...restProps} class={cardFanClasses} style="--cardFanHeight: {height}">
8
+ {#each images as image}
9
+ <div class="cardFan__card">
10
+ <div class="cardFan__cardImage" style="background-image: url({image});"></div>
11
+ </div>
12
+ {/each}
13
+ </div>
14
+
15
+ <style>
16
+ .cardFan {
17
+ position: relative;
18
+ height: calc(var(--cardFanHeight) * 1.3);
19
+ width: calc(var(--cardFanHeight) * 2);
20
+ }
21
+
22
+ .cardFan__card {
23
+ background: var(--bg);
24
+ height: var(--cardFanHeight);
25
+ width: calc(var(--cardFanHeight) * 0.6818);
26
+ border-radius: 0.25rem;
27
+ position: absolute;
28
+ box-shadow:
29
+ 0 0 0.5rem rgba(0, 0, 0, 0.2),
30
+ 1px 1px 32px 4px rgba(0, 0, 0, 0.76) inset;
31
+ left: 50%;
32
+ top: 50%;
33
+ transform-origin: center 120%;
34
+ border: var(--borderThick);
35
+ border-color: var(--fg);
36
+ transition: transform 0.2s var(--ease-in-2);
37
+ overflow: hidden;
38
+ }
39
+
40
+ .cardFan__cardImage {
41
+ position: absolute;
42
+ width: var(--cardFanHeight);
43
+ height: calc(var(--cardFanHeight) * 0.6818);
44
+ background-size: cover;
45
+ background-position: center center;
46
+ transform: rotate(-90deg);
47
+ transform-origin: center center;
48
+ top: 50%;
49
+ left: 50%;
50
+ translate: -50% -50%;
51
+ }
52
+
53
+ .cardFan__card:before {
54
+ content: '';
55
+ position: absolute;
56
+ top: 0;
57
+ left: 0;
58
+ right: 0;
59
+ bottom: 0;
60
+ border-radius: var(--radius-2);
61
+ border: solid var(--bg) 0.3rem;
62
+ z-index: 1;
63
+ }
64
+
65
+ .cardFan--count-1 .cardFan__card:nth-child(1) {
66
+ transform: translate(-50%, -50%) rotate(0deg);
67
+ }
68
+
69
+ .cardFan--count-2 .cardFan__card:nth-child(1) {
70
+ transform: translate(-50%, -50%) rotate(-10deg);
71
+ }
72
+ .cardFan--count-2 .cardFan__card:nth-child(2) {
73
+ transform: translate(-50%, -50%) rotate(10deg);
74
+ }
75
+
76
+ .cardFan--count-3 .cardFan__card:nth-child(1) {
77
+ transform: translate(-50%, -50%) rotate(-15deg);
78
+ }
79
+ .cardFan--count-3 .cardFan__card:nth-child(2) {
80
+ transform: translate(-50%, -50%) rotate(0deg);
81
+ }
82
+ .cardFan--count-3 .cardFan__card:nth-child(3) {
83
+ transform: translate(-50%, -50%) rotate(15deg);
84
+ }
85
+
86
+ .cardFan--count-4 .cardFan__card:nth-child(1) {
87
+ transform: translate(-50%, -50%) rotate(-20deg);
88
+ }
89
+ .cardFan--count-4 .cardFan__card:nth-child(2) {
90
+ transform: translate(-50%, -50%) rotate(-7deg);
91
+ }
92
+ .cardFan--count-4 .cardFan__card:nth-child(3) {
93
+ transform: translate(-50%, -50%) rotate(7deg);
94
+ }
95
+ .cardFan--count-4 .cardFan__card:nth-child(4) {
96
+ transform: translate(-50%, -50%) rotate(20deg);
97
+ }
98
+
99
+ .cardFan--count-5 .cardFan__card:nth-child(1) {
100
+ transform: translate(-50%, -50%) rotate(-25deg);
101
+ }
102
+ .cardFan--count-5 .cardFan__card:nth-child(2) {
103
+ transform: translate(-50%, -50%) rotate(-12.5deg);
104
+ }
105
+ .cardFan--count-5 .cardFan__card:nth-child(3) {
106
+ transform: translate(-50%, -50%) rotate(0deg);
107
+ }
108
+ .cardFan--count-5 .cardFan__card:nth-child(4) {
109
+ transform: translate(-50%, -50%) rotate(12.5deg);
110
+ }
111
+ .cardFan--count-5 .cardFan__card:nth-child(5) {
112
+ transform: translate(-50%, -50%) rotate(25deg);
113
+ }
114
+
115
+ :global {
116
+ *:hover > .cardFan--count-1 .cardFan__card:nth-child(1) {
117
+ transform: translate(-50%, -50%) rotate(0deg) !important;
118
+ }
119
+
120
+ *:hover > .cardFan--count-2 .cardFan__card:nth-child(1) {
121
+ transform: translate(-120%, -42%) rotate(-10deg) !important;
122
+ }
123
+ *:hover > .cardFan--count-2 .cardFan__card:nth-child(2) {
124
+ transform: translate(20%, -42%) rotate(10deg) !important;
125
+ }
126
+
127
+ *:hover > .cardFan--count-3 .cardFan__card:nth-child(1) {
128
+ transform: translate(-130%, -45%) rotate(-10deg) !important;
129
+ }
130
+ *:hover > .cardFan--count-3 .cardFan__card:nth-child(2) {
131
+ transform: translate(-50%, -50%) rotate(0deg) !important;
132
+ }
133
+ *:hover > .cardFan--count-3 .cardFan__card:nth-child(3) {
134
+ transform: translate(30%, -45%) rotate(10deg) !important;
135
+ }
136
+
137
+ *:hover > .cardFan--count-4 .cardFan__card:nth-child(1) {
138
+ transform: translate(-140%, -42%) rotate(-10deg) !important;
139
+ }
140
+ *:hover > .cardFan--count-4 .cardFan__card:nth-child(2) {
141
+ transform: translate(-70%, -46%) rotate(-5deg) !important;
142
+ }
143
+ *:hover > .cardFan--count-4 .cardFan__card:nth-child(3) {
144
+ transform: translate(-10%, -46%) rotate(5deg) !important;
145
+ }
146
+ *:hover > .cardFan--count-4 .cardFan__card:nth-child(4) {
147
+ transform: translate(60%, -42%) rotate(10deg) !important;
148
+ }
149
+ *:hover > .cardFan--count-5 .cardFan__card:nth-child(1) {
150
+ transform: translate(-150%, -42%) rotate(-10deg) !important;
151
+ }
152
+ *:hover > .cardFan--count-5 .cardFan__card:nth-child(2) {
153
+ transform: translate(-100%, -46%) rotate(-5deg) !important;
154
+ }
155
+ *:hover > .cardFan--count-5 .cardFan__card:nth-child(3) {
156
+ transform: translate(-50%, -50%) rotate(0deg) !important;
157
+ }
158
+ *:hover > .cardFan--count-5 .cardFan__card:nth-child(4) {
159
+ transform: translate(0%, -46%) rotate(5deg) !important;
160
+ }
161
+ *:hover > .cardFan--count-5 .cardFan__card:nth-child(5) {
162
+ transform: translate(50%, -42%) rotate(10deg) !important;
163
+ }
164
+ }
165
+ </style>
@@ -0,0 +1,2 @@
1
+ export { default as CardFan } from './CardFan.svelte';
2
+ export * from './types';
@@ -0,0 +1,6 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+
3
+ export type CardFanProps = {
4
+ images: string[];
5
+ height?: string;
6
+ } & HTMLAttributes<HTMLDivElement>;
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ import { CodeBlock } from './';
3
+ import type { CodeProps } from './';
4
+ let { code, lang = 'svelte', ...restProps }: CodeProps = $props();
5
+ </script>
6
+
7
+ <CodeBlock {code} {lang} variant="inline" {...restProps} />
@@ -0,0 +1,102 @@
1
+ <script lang="ts">
2
+ import type { CodeBlockProps } from './types';
3
+ import { onMount } from 'svelte';
4
+ import { codeToHtml } from 'shiki';
5
+
6
+ let { code, lang = 'svelte', variant = 'default' }: CodeBlockProps = $props();
7
+
8
+ let highlightedCode = $state('');
9
+
10
+ onMount(async () => {
11
+ highlightedCode = await codeToHtml(code, {
12
+ lang: lang,
13
+ themes: {
14
+ light: 'github-light',
15
+ dark: 'github-dark'
16
+ },
17
+ defaultColor: false // Forces shiki to use light / dark css vars which we need for nesting
18
+ });
19
+ });
20
+
21
+ let codeBlockClasses = $derived(['codeBlock', `codeBlock--${variant}`]);
22
+ </script>
23
+
24
+ <span class={codeBlockClasses}>
25
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -->
26
+ {@html highlightedCode}
27
+ </span>
28
+
29
+ <style>
30
+ :global(.shiki) {
31
+ font-family: var(--font-mono);
32
+ padding: var(--size-4);
33
+ margin: 0;
34
+ }
35
+ :global(.codeBlock--inline .shiki) {
36
+ font-family: var(--font-mono);
37
+ padding: 0 var(--size-1);
38
+ margin: 0;
39
+ }
40
+ .codeBlock {
41
+ font-family: var(--font-mono);
42
+ max-width: 100%;
43
+ overflow-x: auto;
44
+ border: var(--borderThin);
45
+ border-color: var(--contrastEmpty);
46
+ display: block;
47
+ }
48
+ .codeBlock--inline {
49
+ display: inline-block;
50
+ width: auto;
51
+ overflow-x: unset;
52
+ }
53
+ :global {
54
+ /* Default: Inherit colors from inline styles (Shiki sets both light & dark variables inline) */
55
+ .shiki,
56
+ .shiki span {
57
+ color: var(--shiki-light) !important;
58
+ background-color: var(--contrastLowest) !important;
59
+ font-style: var(--shiki-light-font-style) !important;
60
+ font-weight: var(--shiki-light-font-weight) !important;
61
+ text-decoration: var(--shiki-light-text-decoration) !important;
62
+ }
63
+
64
+ /* In light mode, just inherit (Shiki's inline styles apply the light theme by default) */
65
+ .light .shiki,
66
+ .light .shiki span {
67
+ color: var(--shiki-light) !important;
68
+ background-color: var(--contrastLowest) !important;
69
+ font-style: var(--shiki-light-font-style) !important;
70
+ font-weight: var(--shiki-light-font-weight) !important;
71
+ text-decoration: var(--shiki-light-text-decoration) !important;
72
+ }
73
+
74
+ /* In dark mode, override with the Shiki dark theme variables */
75
+ .dark .shiki,
76
+ .dark .shiki span {
77
+ color: var(--shiki-dark) !important;
78
+ background-color: var(--contrastLowest) !important;
79
+ font-style: var(--shiki-dark-font-style) !important;
80
+ font-weight: var(--shiki-dark-font-weight) !important;
81
+ text-decoration: var(--shiki-dark-text-decoration) !important;
82
+ }
83
+ .dark .light .shiki,
84
+ .dark .light .shiki span {
85
+ color: var(--shiki-light) !important;
86
+ background-color: var(--contrastLowest) !important;
87
+ font-style: var(--shiki-light-font-style) !important;
88
+ font-weight: var(--shiki-light-font-weight) !important;
89
+ text-decoration: var(--shiki-light-text-decoration) !important;
90
+ }
91
+
92
+ /* Handle nested dark inside light: force dark mode variables */
93
+ .light .dark .shiki,
94
+ .light .dark .shiki span {
95
+ color: var(--shiki-dark) !important;
96
+ background-color: var(--contrastLowest) !important;
97
+ font-style: var(--shiki-dark-font-style) !important;
98
+ font-weight: var(--shiki-dark-font-weight) !important;
99
+ text-decoration: var(--shiki-dark-text-decoration) !important;
100
+ }
101
+ }
102
+ </style>
@@ -0,0 +1,3 @@
1
+ export { default as Code } from './Code.svelte';
2
+ export { default as CodeBlock } from './CodeBlock.svelte';
3
+ export * from './types';
@@ -0,0 +1,10 @@
1
+ export type CodeBlockProps = {
2
+ code: string;
3
+ lang?: string;
4
+ variant?: 'default' | 'inline';
5
+ };
6
+
7
+ export type CodeProps = {
8
+ code: string;
9
+ lang?: string;
10
+ };
@@ -0,0 +1,8 @@
1
+ <script lang="ts">
2
+ import type { ColorModeProps } from './types';
3
+ let { children, mode, as = 'div', ...restProps }: ColorModeProps = $props();
4
+ </script>
5
+
6
+ <svelte:element this={as} class={mode} {...restProps}>
7
+ {@render children()}
8
+ </svelte:element>
@@ -0,0 +1,2 @@
1
+ export { default as ColorMode } from './ColorMode.svelte';
2
+ export type { ColorModeProps } from './types';