fragment-tools 0.1.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 (192) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +101 -0
  3. package/bin/index.js +19 -0
  4. package/docs/README.md +18 -0
  5. package/docs/api/CLI.md +44 -0
  6. package/docs/api/renderers.md +80 -0
  7. package/docs/api/sketch.md +216 -0
  8. package/docs/api/triggers.md +101 -0
  9. package/docs/guide/about.md +16 -0
  10. package/docs/guide/exports.md +86 -0
  11. package/docs/guide/external-dependencies.md +22 -0
  12. package/docs/guide/getting-started.md +113 -0
  13. package/docs/guide/hot-shader-reloading.md +20 -0
  14. package/docs/guide/shortcuts.md +12 -0
  15. package/docs/guide/triggers.png +0 -0
  16. package/docs/guide/using-triggers.md +39 -0
  17. package/examples/cube-three.js +34 -0
  18. package/examples/ellipse-p5.js +26 -0
  19. package/examples/icon.fs +96 -0
  20. package/examples/icon.js +63 -0
  21. package/examples/icon.png +0 -0
  22. package/examples/icon.transparent.png +0 -0
  23. package/examples/package-lock.json +40 -0
  24. package/examples/package.json +15 -0
  25. package/examples/shape-2d.js +45 -0
  26. package/examples/shape-three.js +49 -0
  27. package/examples/shape-tree.fs +3 -0
  28. package/package.json +37 -0
  29. package/screenshot.png +0 -0
  30. package/src/cli/db.js +17 -0
  31. package/src/cli/index.js +198 -0
  32. package/src/cli/log.js +26 -0
  33. package/src/cli/plugins/check-dependencies.js +77 -0
  34. package/src/cli/plugins/db.js +12 -0
  35. package/src/cli/plugins/hot-shader-reload.js +86 -0
  36. package/src/cli/plugins/hot-sketch-reload.js +39 -0
  37. package/src/cli/plugins/screenshot.js +31 -0
  38. package/src/cli/server.js +140 -0
  39. package/src/cli/templates/2d.js +15 -0
  40. package/src/cli/templates/fragment.fs +10 -0
  41. package/src/cli/templates/fragment.js +18 -0
  42. package/src/cli/templates/index.js +24 -0
  43. package/src/cli/templates/p5.js +13 -0
  44. package/src/cli/templates/three-fragment.js +53 -0
  45. package/src/cli/templates/three-orthographic.js +23 -0
  46. package/src/cli/templates/three-perspective.js +20 -0
  47. package/src/cli/ws.js +92 -0
  48. package/src/client/app/App.svelte +8 -0
  49. package/src/client/app/client.js +68 -0
  50. package/src/client/app/components/IconCross.svelte +29 -0
  51. package/src/client/app/components/Init.svelte +13 -0
  52. package/src/client/app/components/KeyBinding.svelte +32 -0
  53. package/src/client/app/inputs/Input.js +15 -0
  54. package/src/client/app/inputs/Keyboard.js +21 -0
  55. package/src/client/app/inputs/MIDI.js +144 -0
  56. package/src/client/app/inputs/Mouse.js +5 -0
  57. package/src/client/app/inputs/Webcam.js +98 -0
  58. package/src/client/app/lib/canvas-recorder/CanvasRecorder.js +88 -0
  59. package/src/client/app/lib/canvas-recorder/FFMPEGRecorder.js +56 -0
  60. package/src/client/app/lib/canvas-recorder/FrameRecorder.js +40 -0
  61. package/src/client/app/lib/canvas-recorder/GIFRecorder.js +52 -0
  62. package/src/client/app/lib/canvas-recorder/MP4Recorder.js +46 -0
  63. package/src/client/app/lib/canvas-recorder/WebMRecorder.js +30 -0
  64. package/src/client/app/lib/canvas-recorder/mp4.js +20 -0
  65. package/src/client/app/lib/canvas-recorder/mp4.wasm +0 -0
  66. package/src/client/app/lib/canvas-recorder/utils.js +22 -0
  67. package/src/client/app/lib/gl/Geometry.js +39 -0
  68. package/src/client/app/lib/gl/Program.js +130 -0
  69. package/src/client/app/lib/gl/Renderer.js +148 -0
  70. package/src/client/app/lib/gl/Texture.js +114 -0
  71. package/src/client/app/lib/gl/index.js +109 -0
  72. package/src/client/app/lib/gl/utils.js +5 -0
  73. package/src/client/app/lib/helpers/frameDebounce.js +40 -0
  74. package/src/client/app/lib/loader/index.js +20 -0
  75. package/src/client/app/lib/loader/loadImage.js +19 -0
  76. package/src/client/app/lib/loader/loadScript.js +14 -0
  77. package/src/client/app/lib/paper-sizes.js +104 -0
  78. package/src/client/app/lib/presets.js +12 -0
  79. package/src/client/app/lib/tempo/Analyser.js +165 -0
  80. package/src/client/app/lib/tempo/Range.js +97 -0
  81. package/src/client/app/lib/tempo/index.js +138 -0
  82. package/src/client/app/modules/AudioAnalyser/Range.svelte +93 -0
  83. package/src/client/app/modules/AudioAnalyser/Spectrum.svelte +31 -0
  84. package/src/client/app/modules/AudioAnalyser.svelte +70 -0
  85. package/src/client/app/modules/Console/ConsoleLine.svelte +254 -0
  86. package/src/client/app/modules/Console.svelte +82 -0
  87. package/src/client/app/modules/Exports.svelte +105 -0
  88. package/src/client/app/modules/MidiPanel.svelte +106 -0
  89. package/src/client/app/modules/Monitor.svelte +62 -0
  90. package/src/client/app/modules/Params.svelte +112 -0
  91. package/src/client/app/renderers/2DRenderer.js +5 -0
  92. package/src/client/app/renderers/FragmentRenderer.js +62 -0
  93. package/src/client/app/renderers/OGLRenderer.js +0 -0
  94. package/src/client/app/renderers/P5Renderer.js +39 -0
  95. package/src/client/app/renderers/THREERenderer.js +128 -0
  96. package/src/client/app/stores/audioAnalysis.js +10 -0
  97. package/src/client/app/stores/console.js +76 -0
  98. package/src/client/app/stores/errors.js +25 -0
  99. package/src/client/app/stores/exports.js +28 -0
  100. package/src/client/app/stores/index.js +2 -0
  101. package/src/client/app/stores/layout.js +187 -0
  102. package/src/client/app/stores/multisampling.js +16 -0
  103. package/src/client/app/stores/props.js +44 -0
  104. package/src/client/app/stores/renderers.js +60 -0
  105. package/src/client/app/stores/rendering.js +111 -0
  106. package/src/client/app/stores/sketches.js +40 -0
  107. package/src/client/app/stores/time.js +27 -0
  108. package/src/client/app/stores/utils.js +66 -0
  109. package/src/client/app/transitions/fade.js +17 -0
  110. package/src/client/app/transitions/index.js +12 -0
  111. package/src/client/app/transitions/splitX.js +16 -0
  112. package/src/client/app/transitions/splitY.js +16 -0
  113. package/src/client/app/triggers/Keyboard.js +95 -0
  114. package/src/client/app/triggers/MIDI.js +122 -0
  115. package/src/client/app/triggers/Mouse.js +96 -0
  116. package/src/client/app/triggers/Trigger.js +71 -0
  117. package/src/client/app/triggers/index.js +19 -0
  118. package/src/client/app/triggers/shared.js +37 -0
  119. package/src/client/app/ui/Build.svelte +96 -0
  120. package/src/client/app/ui/ErrorOverlay.svelte +130 -0
  121. package/src/client/app/ui/Field.svelte +262 -0
  122. package/src/client/app/ui/FieldGroup.svelte +103 -0
  123. package/src/client/app/ui/FieldSection.svelte +123 -0
  124. package/src/client/app/ui/FieldSpace.svelte +37 -0
  125. package/src/client/app/ui/FieldTrigger.svelte +263 -0
  126. package/src/client/app/ui/FieldTriggers.svelte +58 -0
  127. package/src/client/app/ui/FloatingParams.svelte +49 -0
  128. package/src/client/app/ui/Layout.svelte +50 -0
  129. package/src/client/app/ui/LayoutColumn.svelte +9 -0
  130. package/src/client/app/ui/LayoutComponent.svelte +279 -0
  131. package/src/client/app/ui/LayoutResizer.svelte +218 -0
  132. package/src/client/app/ui/LayoutRoot.svelte +11 -0
  133. package/src/client/app/ui/LayoutRow.svelte +9 -0
  134. package/src/client/app/ui/LayoutToolbar.svelte +264 -0
  135. package/src/client/app/ui/Module.svelte +154 -0
  136. package/src/client/app/ui/ModuleHeaderAction.svelte +87 -0
  137. package/src/client/app/ui/ModuleHeaderButton.svelte +21 -0
  138. package/src/client/app/ui/ModuleHeaderSelect.svelte +50 -0
  139. package/src/client/app/ui/ModuleRenderer.svelte +38 -0
  140. package/src/client/app/ui/OutputRenderer.svelte +149 -0
  141. package/src/client/app/ui/ParamsMultisampling.svelte +109 -0
  142. package/src/client/app/ui/ParamsOutput.svelte +139 -0
  143. package/src/client/app/ui/Preview.svelte +15 -0
  144. package/src/client/app/ui/SelectChevrons.svelte +25 -0
  145. package/src/client/app/ui/SketchRenderer.svelte +672 -0
  146. package/src/client/app/ui/SketchSelect.svelte +49 -0
  147. package/src/client/app/ui/fields/ButtonInput.svelte +54 -0
  148. package/src/client/app/ui/fields/CheckboxInput.svelte +70 -0
  149. package/src/client/app/ui/fields/ColorInput.svelte +187 -0
  150. package/src/client/app/ui/fields/FieldInputRow.svelte +13 -0
  151. package/src/client/app/ui/fields/ImageInput.svelte +145 -0
  152. package/src/client/app/ui/fields/Input.svelte +120 -0
  153. package/src/client/app/ui/fields/ListInput.svelte +106 -0
  154. package/src/client/app/ui/fields/NumberInput.svelte +114 -0
  155. package/src/client/app/ui/fields/ProgressInput.svelte +90 -0
  156. package/src/client/app/ui/fields/Select.svelte +116 -0
  157. package/src/client/app/ui/fields/TextInput.svelte +18 -0
  158. package/src/client/app/ui/fields/Vec2Input.svelte +5 -0
  159. package/src/client/app/ui/fields/Vec3Input.svelte +6 -0
  160. package/src/client/app/ui/fields/VectorInput.svelte +102 -0
  161. package/src/client/app/utils/canvas.utils.js +229 -0
  162. package/src/client/app/utils/color.utils.js +427 -0
  163. package/src/client/app/utils/file.utils.js +77 -0
  164. package/src/client/app/utils/glsl.utils.js +14 -0
  165. package/src/client/app/utils/glslErrors.js +154 -0
  166. package/src/client/app/utils/index.js +39 -0
  167. package/src/client/app/utils/math.utils.js +23 -0
  168. package/src/client/app/utils/props.utils.js +53 -0
  169. package/src/client/index.html +18 -0
  170. package/src/client/main.js +9 -0
  171. package/src/client/public/css/global.css +115 -0
  172. package/src/client/public/favicon.ico +0 -0
  173. package/src/client/public/fonts/Inter-Bold.woff2 +0 -0
  174. package/src/client/public/fonts/Inter-Italic.woff2 +0 -0
  175. package/src/client/public/fonts/Inter-Regular.woff2 +0 -0
  176. package/src/client/public/fonts/Inter-SemiBold.woff2 +0 -0
  177. package/src/client/public/fonts/JetBrainsMono-Regular.woff2 +0 -0
  178. package/src/client/public/icons/chevron-bottom.svg +3 -0
  179. package/src/client/public/icons/chevron-right.svg +3 -0
  180. package/src/client/public/icons/chevron-top.svg +3 -0
  181. package/src/client/public/icons/columns-horizontal.svg +4 -0
  182. package/src/client/public/icons/columns-vertical.svg +4 -0
  183. package/src/client/public/icons/folder-plus.svg +6 -0
  184. package/src/client/public/icons/lock.svg +4 -0
  185. package/src/client/public/icons/picture-in-picture.svg +4 -0
  186. package/src/client/public/icons/trash.svg +5 -0
  187. package/src/client/public/icons/trigger.svg +8 -0
  188. package/src/client/public/icons/unlock.svg +4 -0
  189. package/src/client/public/js/ffmpeg.min.js +2 -0
  190. package/src/client/public/js/ffmpeg.min.js.map +1 -0
  191. package/src/client/public/js/gif.js +2 -0
  192. package/src/client/public/js/gif.worker.js +2 -0
@@ -0,0 +1,54 @@
1
+ <script>
2
+ export let value = null;
3
+ export let label;
4
+ export let disabled = false;
5
+ export let showLabel = true;
6
+ export let title = "";
7
+
8
+ </script>
9
+
10
+ <div class="button-container" class:disabled={disabled}>
11
+ <button class="button" {disabled} on:click {title} on:mouseenter on:mouseleave>
12
+ <span class="label" class:visually-hidden={!showLabel}>{label}</span>
13
+ <slot></slot>
14
+ </button>
15
+ </div>
16
+
17
+ <style>
18
+ .button-container {
19
+ display: flex;
20
+ width: 100%;
21
+ }
22
+
23
+ .button {
24
+ display: flex;
25
+ width: 100%;
26
+ min-width: var(--height-input);
27
+ height: var(--height-input);
28
+ justify-content: center;
29
+ align-items: center;
30
+ padding: 0 4px;
31
+
32
+ color: rgba(255, 255, 255, 0.5);
33
+ font-size: var(--font-size-input);
34
+
35
+ border-radius: var(--border-radius-input);
36
+ background-color: var(--background-color, var(--color-background-input));
37
+ box-shadow: inset 0 0 0 1px var(--box-shadow-color, var(--color-border-input));
38
+ }
39
+
40
+ :global(.field.disabled) .button {
41
+ color: rgba(255, 255, 255, 0.2);
42
+ }
43
+
44
+ .button:hover {
45
+ color: var(--color-text);
46
+
47
+ box-shadow: inset 0 0 0 1px var(--box-shadow-color-active, var(--color-active));
48
+ }
49
+
50
+ .button:active {
51
+ box-shadow: 0 0 0 2px var(--box-shadow-color-active, var(--color-active));
52
+ }
53
+
54
+ </style>
@@ -0,0 +1,70 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte";
3
+
4
+ export let value;
5
+
6
+ const dispatch = createEventDispatcher();
7
+
8
+ function handleChange() {
9
+ dispatch("change", value);
10
+ }
11
+
12
+ </script>
13
+
14
+ <div class="checkbox">
15
+ <input class="input" bind:checked={value} type="checkbox" on:change={handleChange} />
16
+ <div class="checked">
17
+ </div>
18
+ </div>
19
+
20
+ <style>
21
+ .checkbox {
22
+ position: relative;
23
+
24
+ width: var(--height-input);
25
+ height: var(--height-input);
26
+ margin-right: calc(var(--padding));
27
+ box-shadow: inset 0 0 0 1px var(--color-border-input);
28
+
29
+ border-radius: var(--border-radius-input);
30
+ background-color: var(--color-background-input);
31
+ }
32
+
33
+ .checkbox:hover {
34
+ box-shadow: inset 0 0 0 1px var(--color-active);
35
+ }
36
+
37
+ .checkbox:focus-within {
38
+ box-shadow: 0 0 0 2px var(--color-active);
39
+ }
40
+
41
+ .input {
42
+ width: 100%;
43
+ height: 100%;
44
+ border: none;
45
+ border-radius: var(--border-radius-input);
46
+ background-color: transparent;
47
+ }
48
+
49
+ /* .input:checked {
50
+ background-color: var(--color-active);
51
+ } */
52
+
53
+ .checked {
54
+ position: absolute;
55
+ left: 3px;
56
+ top: 3px;
57
+ bottom: 3px;
58
+ right: 3px;
59
+
60
+ border-radius: calc(var(--border-radius-input) * 0.5);
61
+ background-color: var(--color-active);
62
+
63
+ opacity: 0;
64
+ pointer-events: none;
65
+ }
66
+
67
+ .input:checked + .checked {
68
+ opacity: 1;
69
+ }
70
+ </style>
@@ -0,0 +1,187 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte";
3
+ import * as color from "../../utils/color.utils.js";
4
+ import TextInput from "./TextInput.svelte";
5
+ import Field from "../Field.svelte";
6
+
7
+ export let value;
8
+
9
+ const dispatch = createEventDispatcher();
10
+
11
+ let hexValue = color.toHex(color.isTHREE(value) ? `#${value.getHexString()}` : value);
12
+ let isInputDriven = true;
13
+
14
+ let override = false;
15
+
16
+ let format = color.getColorFormat(value);
17
+ let textValue = formatColorFromHex(hexValue);
18
+ let alpha = 1;
19
+
20
+ $: hasAlpha = typeof textValue === "string" &&
21
+ (
22
+ color.isRGBAString(textValue) ||
23
+ color.isVec4String(textValue) ||
24
+ color.isHSLAString(textValue)
25
+ );
26
+ $: {
27
+ if (isInputDriven) {
28
+ textValue = formatColorFromHex(hexValue);
29
+ } else {
30
+ hexValue = color.toHex(textValue);
31
+ }
32
+
33
+ if (color.isTHREE(value)) {
34
+ const [r, g, b] = color.hexToComponents(hexValue);
35
+
36
+ value.r = r / 255;
37
+ value.g = g / 255;
38
+ value.b = b / 255;
39
+ }
40
+
41
+ dispatchChange();
42
+ }
43
+
44
+ $: {
45
+ if (hasAlpha) {
46
+ const [r, g, b, a = 1] = color.toComponents(textValue);
47
+ alpha = a;
48
+ }
49
+ }
50
+
51
+ function dispatchChange() {
52
+ // support THREE.Color
53
+ if (format === color.FORMATS.THREE) {
54
+ dispatch('change', value);
55
+ } else {
56
+ dispatch('change', textValue);
57
+ }
58
+ }
59
+
60
+ function handleBlur() {
61
+ dispatchChange();
62
+ }
63
+
64
+ function formatColorFromHex(hex) {
65
+ if (override) return textValue;
66
+
67
+ if (format === color.FORMATS.THREE) return color.threeToHexString(value);
68
+ if (format === color.FORMATS.HEX_STRING) return hex;
69
+ if (format === color.FORMATS.VEC3_STRING) return color.hexToVec3String(hex);
70
+ if (format === color.FORMATS.RGB_STRING) return color.hexToRGBString(hex);
71
+
72
+ let components = color.hexToComponents(hex);
73
+
74
+ if (hasAlpha && alpha !== 1) {
75
+ components[3] = alpha;
76
+ }
77
+
78
+ if (format === color.FORMATS.HSL_STRING) return color.hexToHSLString(components);
79
+ if (format === color.FORMATS.RGBA_STRING) return color.componentsToRGBAString(components);
80
+ if (format === color.FORMATS.VEC4_STRING) return color.componentsToVec4String(components);
81
+ if (format === color.FORMATS.HSLA_STRING) return color.componentsToHSLAString(components);
82
+
83
+ }
84
+
85
+ function onChangeText(event) {
86
+ isInputDriven = false;
87
+
88
+ const newColor = event.detail;
89
+
90
+ if (color.isColor(newColor)) {
91
+ format = color.getColorFormat(newColor);
92
+ textValue = newColor;
93
+ }
94
+ }
95
+
96
+ function onChangeAlpha(event) {
97
+ isInputDriven = false;
98
+
99
+ if (format === color.FORMATS.RGBA_STRING) {
100
+ const [r, g, b] = color.hexToComponents(hexValue);
101
+
102
+ textValue = color.componentsToRGBAString([r, g, b, event.detail]);
103
+ } else if (format === color.FORMATS.VEC4_STRING) {
104
+ const [r, g, b] = color.vecToComponents(textValue);
105
+
106
+ textValue = color.componentsToVec4String([r, g, b, event.detail]);
107
+ } else if (format === color.FORMATS.HSLA_STRING) {
108
+ const [h, s, l] = color.hslToHSLComponents(textValue);
109
+
110
+ textValue = color.hslaToHSLAString([h, s, l, event.detail]);
111
+ }
112
+ }
113
+
114
+ function onInput() {
115
+ isInputDriven = true;
116
+ }
117
+
118
+ </script>
119
+
120
+ <div class="color-input">
121
+ <div class="layout">
122
+ <div class="mirror" style="--currentColor: {hexValue}; --opacity: {alpha}">
123
+ <!-- svelte-ignore -->
124
+ <input class="input" type="color" bind:value={hexValue} on:blur={handleBlur} on:input={onInput} />
125
+ </div>
126
+ <TextInput value={textValue} on:change={onChangeText} />
127
+ </div>
128
+ {#if hasAlpha }
129
+ <Field key="alpha" value={alpha} params={{min: 0, max: 1, step: 0.01}} on:change={onChangeAlpha}></Field>
130
+ {/if }
131
+ </div>
132
+
133
+ <style>
134
+ .color-input {
135
+ position: relative;
136
+ width: 100%;
137
+ }
138
+
139
+ .layout {
140
+ display: grid;
141
+ column-gap: var(--column-gap);
142
+ grid-template-columns: 0.35fr 0.65fr;
143
+ align-items: center;
144
+ }
145
+
146
+ .mirror {
147
+ position: relative;
148
+
149
+ height: var(--height-input);
150
+
151
+ border-radius: var(--border-radius-input);
152
+ box-shadow: inset 0 0 0 1px var(--color-border-input);
153
+ }
154
+
155
+ .mirror:before {
156
+ --gap: 1px;
157
+
158
+ content: '';
159
+ position: absolute;
160
+ top: var(--gap);
161
+ left: var(--gap);
162
+ right: var(--gap);
163
+ bottom: var(--gap);
164
+
165
+ background-color: var(--currentColor);
166
+ border-radius: calc(var(--border-radius-input) * 0.5);
167
+ opacity: var(--opacity, 1);
168
+ }
169
+
170
+ .mirror:hover {
171
+ box-shadow: inset 0 0 0 1px var(--box-shadow-color, var(--color-active));
172
+ }
173
+
174
+ .mirror:focus-within {
175
+ box-shadow: 0 0 0 2px var(--box-shadow-color, var(--color-active));
176
+ }
177
+
178
+ .input {
179
+ width: 100%;
180
+ height: 100%;
181
+ opacity: 0;
182
+ cursor: pointer;
183
+ background: transparent;
184
+ border: none;
185
+ }
186
+
187
+ </style>
@@ -0,0 +1,13 @@
1
+ <div class="row">
2
+ <slot></slot>
3
+ </div>
4
+
5
+ <style>
6
+ .row {
7
+ display: grid;
8
+ width: 100%;
9
+ column-gap: var(--column-gap);
10
+ grid-template-columns: var(--grid-template-columns, 1fr);
11
+ align-items: center;
12
+ }
13
+ </style>
@@ -0,0 +1,145 @@
1
+ <script>
2
+ import { onMount } from "svelte";
3
+ import { loadImage } from "../../lib/loader/loadImage";
4
+ import ButtonInput from "./ButtonInput.svelte";
5
+ import FieldInputRow from "./FieldInputRow.svelte";
6
+ import TextInput from "./TextInput.svelte";
7
+
8
+ export let value;
9
+
10
+ let img, input, name;
11
+ $: url = typeof value === HTMLImageElement ? value.src : value;
12
+ $: displayUrl = name ? name : url.replace(`/@fs${__CWD__}`, '');
13
+ $: {
14
+ ;(async () => {
15
+ await loadImage(url, { img });
16
+ })();
17
+ }
18
+
19
+ function handleClick() {
20
+ input.click();
21
+ }
22
+
23
+ let reader = new FileReader();
24
+ let dragover = false;
25
+
26
+ function handleUpload(event) {
27
+ event.preventDefault();
28
+ event.stopPropagation();
29
+
30
+ let file;
31
+
32
+ if (event.dataTransfer) {
33
+ file = event.dataTransfer.files[0];
34
+ } else if(event.target) {
35
+ file = event.target.files[0];
36
+ }
37
+
38
+ name = file.name;
39
+
40
+ reader.onload = async (e) => {
41
+ reader.onload = null;
42
+
43
+ value = e.target.result;
44
+ };
45
+ reader.readAsDataURL(file);
46
+
47
+ dragover = false;
48
+ }
49
+
50
+ function handleDragover(event) {
51
+ event.preventDefault();
52
+ event.stopPropagation();
53
+
54
+ dragover = true;
55
+ }
56
+
57
+ function handleDragleave(event) {
58
+ event.preventDefault();
59
+ event.stopPropagation();
60
+
61
+ dragover = false;
62
+ }
63
+
64
+ </script>
65
+
66
+ <div
67
+ class="img-container"
68
+ class:dragover={dragover}
69
+ on:dragover={handleDragover}
70
+ on:dragleave={handleDragleave}
71
+ on:drop={handleUpload}
72
+ >
73
+ <FieldInputRow --grid-template-columns="1fr 0.5fr">
74
+ <div class="row">
75
+ <div
76
+ class="preview"
77
+ on:click={handleClick}
78
+ >
79
+ <img class="img" src="" alt="" bind:this={img}/>
80
+ <input class="input" type="file" bind:this={input} on:change={handleUpload} />
81
+ </div>
82
+ <TextInput disabled value={displayUrl} />
83
+ </div>
84
+ <ButtonInput
85
+ label="change"
86
+ on:click={handleClick}
87
+ on:dragover={handleDragover}
88
+ on:dragleave={handleDragleave}
89
+ on:drop={handleUpload}
90
+ />
91
+ </FieldInputRow>
92
+
93
+ </div>
94
+
95
+ <style>
96
+ .img-container {
97
+ width: 100%;
98
+ }
99
+
100
+ .preview {
101
+ width: calc(var(--height-input) * 1);
102
+ height: calc(var(--height-input) * 1);
103
+ ;
104
+ display: grid;
105
+ place-items: center;
106
+
107
+ border-radius: var(--border-radius-input);
108
+ background-color: var(--color-background-input);
109
+ box-shadow: inset 0 0 0 1px var(--color-border-input);
110
+
111
+ cursor: copy;
112
+ overflow: hidden;
113
+ }
114
+
115
+ .row {
116
+ display: grid;
117
+ grid-template-columns: 20px auto;
118
+ gap: var(--column-gap);
119
+ place-items: center;
120
+ }
121
+
122
+ .preview:hover {
123
+ color: var(--color-text);
124
+
125
+ box-shadow: inset 0 0 0 1px var(--box-shadow-color, var(--color-active));
126
+ }
127
+
128
+ .preview:active, .img-container.dragover .preview {
129
+ box-shadow: 0 0 0 2px var(--box-shadow-color, var(--color-active));
130
+ }
131
+
132
+ .img-container.dragover {
133
+ cursor: copy;
134
+ }
135
+
136
+ .img {
137
+ max-width: calc(100% - var(--padding) * 0.5);
138
+ max-height: calc(100% - var(--padding) * 0.5);
139
+ }
140
+
141
+ .input {
142
+ display: none;
143
+ }
144
+
145
+ </style>
@@ -0,0 +1,120 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte";
3
+
4
+
5
+ export let label = null;
6
+ export let value;
7
+ export let disabled = false;
8
+
9
+ let node;
10
+
11
+ const dispatch = createEventDispatcher();
12
+
13
+ function onKeyPress(event) {
14
+ if (event.key === 'Enter') {
15
+ node.blur();
16
+ }
17
+ }
18
+
19
+ function handleChange(event) {
20
+ dispatch('change', event.currentTarget.value);
21
+ }
22
+
23
+ </script>
24
+
25
+ <div class="input-container" class:disabled={disabled}>
26
+ {#if label }
27
+ <span class="label">{label}</span>
28
+ {/if}
29
+ <input
30
+ class="input"
31
+ bind:this={node}
32
+ bind:value={value}
33
+ on:change={handleChange}
34
+ on:input
35
+ on:keypress={onKeyPress}
36
+ on:keydown
37
+ on:focus
38
+ on:blur
39
+ {disabled}
40
+ autocomplete="off"
41
+ spellcheck="false"
42
+ />
43
+ </div>
44
+
45
+ <style>
46
+ .input-container {
47
+ position: relative;
48
+
49
+ display: flex;
50
+ height: var(--height-input);
51
+ margin: 2px 0;
52
+
53
+ border-radius: var(--border-radius-input);
54
+ background-color: var(--color-background-input);
55
+ box-shadow: inset 0 0 0 1px var(--color-border-input);
56
+ }
57
+
58
+ .input-container:not(.disabled):hover {
59
+ box-shadow: inset 0 0 0 1px var(--color-active);
60
+ }
61
+
62
+ .input-container:not(.disabled):focus-within {
63
+ box-shadow: 0 0 0 2px var(--color-active);
64
+ }
65
+
66
+ .label {
67
+ position: absolute;
68
+ top: 0;
69
+ left: 0;
70
+ bottom: 0;
71
+
72
+ display: flex;
73
+ align-items: center;
74
+ padding: var(--padding);
75
+
76
+ color: var(--color-text);
77
+ font-size: var(--font-size-input);
78
+ font-weight: 600;
79
+ pointer-events: none;
80
+ opacity: 0.35;
81
+ }
82
+
83
+ .input-container.disabled .label {
84
+ opacity: 0.15;
85
+ }
86
+
87
+ .input {
88
+ width: 100%;
89
+ height: 100%;
90
+ padding: 0 var(--padding);
91
+
92
+ color: rgba(255, 255, 255, 0.5);
93
+ font-size: var(--font-size-input);
94
+ text-align: right;
95
+
96
+ background: transparent;
97
+ outline: 0;
98
+ }
99
+
100
+ .input:disabled {
101
+ opacity: 0.4;
102
+ }
103
+
104
+ :global(.field.disabled) .input {
105
+ opacity: 0.4;
106
+ }
107
+
108
+ :global(.field__section:hover .container .input) {
109
+ color: var(--color-text);
110
+ }
111
+
112
+ input:focus {
113
+ color: var(--color-text);
114
+ }
115
+
116
+ /* .input:focus {
117
+ border: var(--borderWidth) solid var(--color-active);
118
+ } */
119
+
120
+ </style>
@@ -0,0 +1,106 @@
1
+ <script>
2
+ import { afterUpdate } from "svelte";
3
+
4
+ export let disabled;
5
+ export let value = null;
6
+
7
+ let container;
8
+
9
+ afterUpdate(() => {
10
+ container.scrollTo(0, container.scrollHeight);
11
+ });
12
+
13
+ </script>
14
+
15
+ <div class="list {disabled ? "disabled" : ""}">
16
+ <div class="container" bind:this={container}>
17
+ <ul class="ul">
18
+ {#each value as item, index}
19
+ <li class="item">
20
+ {#if disabled }
21
+ <span class="label">{item}</span>
22
+ {:else}
23
+ <button class="label">{item}</button>
24
+ {/if}
25
+ </li>
26
+ {/each}
27
+ </ul>
28
+ </div>
29
+ </div>
30
+
31
+ <style>
32
+ .list {
33
+ width: 100%;
34
+
35
+ pointer-events: auto;
36
+ }
37
+
38
+ .container {
39
+ margin-right: var(--padding);
40
+ padding: 1px 0;
41
+ height: 80px;
42
+
43
+ background-color: #1d1d1e;
44
+ border-radius: var(--border-radius-input);
45
+ box-shadow: inset 0 0 0 1px var(--color-border-input);
46
+ overflow-y: scroll;
47
+ }
48
+
49
+ .ul {
50
+ display: flex;
51
+ flex-direction: column;
52
+ width: 100%;
53
+ padding: 2px 0;
54
+
55
+ }
56
+
57
+ .container::-webkit-scrollbar {
58
+ width: 5px; /* width of the entire scrollbar */
59
+ }
60
+
61
+ .container::-webkit-scrollbar-track {
62
+ background-color: var(--color-lightblack); /* color of the tracking area */
63
+ }
64
+
65
+ .container::-webkit-scrollbar-thumb {
66
+ background-color: var(--color-active); /* color of the scroll thumb */
67
+ border-radius: 20px; /* roundness of the scroll thumb */
68
+ }
69
+
70
+ .item {
71
+ display: flex;
72
+ width: 100%;
73
+
74
+ margin: 0;
75
+ padding: 0 3px;
76
+ color: var(--color-text);
77
+ font-size: 10px;
78
+
79
+ opacity: 0.35;
80
+ user-select: none;
81
+ }
82
+
83
+ .label {
84
+ width: 100%;
85
+ padding: 1px var(--padding);
86
+ background-color: transparent;
87
+ text-align: left;
88
+ }
89
+
90
+ .list:not(.disabled) .label:hover {
91
+ box-shadow: inset 0 0 0 1px var(--color-active);
92
+ }
93
+
94
+ .list:not(.disabled) .label:active {
95
+ box-shadow: 0 0 0 2px var(--color-active);
96
+ }
97
+
98
+ .item:hover {
99
+ /* background-color: #0E0E0E; */
100
+ opacity: 1;
101
+ }
102
+
103
+ /* :global(.field:hover) .list:not(.disabled) .item {
104
+ opacity: 1;
105
+ } */
106
+ </style>