fragment-tools 0.1.1 → 0.1.11

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 (48) hide show
  1. package/README.md +37 -16
  2. package/package.json +1 -1
  3. package/src/client/app/modules/Params.svelte +1 -1
  4. package/src/client/app/stores/props.js +24 -22
  5. package/src/client/app/triggers/Keyboard.js +1 -1
  6. package/src/client/app/triggers/MIDI.js +5 -1
  7. package/src/client/app/ui/Field.svelte +11 -7
  8. package/src/client/app/ui/FieldTrigger.svelte +12 -7
  9. package/src/client/app/ui/fields/ButtonInput.svelte +2 -0
  10. package/src/client/app/ui/fields/CheckboxInput.svelte +2 -0
  11. package/src/client/app/ui/fields/ColorInput.svelte +124 -80
  12. package/src/client/app/ui/fields/ImageInput.svelte +2 -0
  13. package/src/client/app/ui/fields/Input.svelte +7 -1
  14. package/src/client/app/ui/fields/ListInput.svelte +2 -0
  15. package/src/client/app/ui/fields/NumberInput.svelte +9 -0
  16. package/src/client/app/ui/fields/ProgressInput.svelte +2 -0
  17. package/src/client/app/ui/fields/Select.svelte +2 -0
  18. package/src/client/app/ui/fields/TextInput.svelte +3 -1
  19. package/src/client/app/ui/fields/VectorInput.svelte +37 -47
  20. package/src/client/app/utils/color.utils.js +191 -132
  21. package/src/client/app/utils/props.utils.js +11 -13
  22. package/. npmignore +0 -4
  23. package/docs/README.md +0 -18
  24. package/docs/api/CLI.md +0 -44
  25. package/docs/api/renderers.md +0 -80
  26. package/docs/api/sketch.md +0 -216
  27. package/docs/api/triggers.md +0 -101
  28. package/docs/guide/about.md +0 -16
  29. package/docs/guide/exports.md +0 -86
  30. package/docs/guide/external-dependencies.md +0 -22
  31. package/docs/guide/getting-started.md +0 -113
  32. package/docs/guide/hot-shader-reloading.md +0 -20
  33. package/docs/guide/shortcuts.md +0 -12
  34. package/docs/guide/triggers.png +0 -0
  35. package/docs/guide/using-triggers.md +0 -39
  36. package/examples/cube-three.js +0 -34
  37. package/examples/ellipse-p5.js +0 -26
  38. package/examples/icon.fs +0 -96
  39. package/examples/icon.js +0 -63
  40. package/examples/icon.png +0 -0
  41. package/examples/icon.transparent.png +0 -0
  42. package/examples/package-lock.json +0 -40
  43. package/examples/package.json +0 -14
  44. package/examples/shape-2d.js +0 -50
  45. package/examples/shape-three.js +0 -49
  46. package/examples/shape-tree.fs +0 -3
  47. package/src/client/app/ui/fields/Vec2Input.svelte +0 -5
  48. package/src/client/app/ui/fields/Vec3Input.svelte +0 -6
package/README.md CHANGED
@@ -17,33 +17,21 @@
17
17
 
18
18
  ## Installation
19
19
 
20
- `fragment` is not yet available on [npmjs.com](npmjs.com) so you need to clone and link the project in order to use it. It's only a few steps.
21
-
22
20
  ```
23
- # clone the project
24
- git clone https://github.com/raphaelameaume/fragment
25
-
26
- # move to the project directory
27
- cd fragment
28
-
29
- # link the project
30
- npm link
21
+ npm install fragment-tools -g
31
22
  ```
32
23
 
33
- You should now be able to run `fragment` from your command line. If you encounter any issues, you can read more about linking on [npmjs.com](https://docs.npmjs.com/cli/v8/commands/npm-link).
24
+ You should now be able to run `fragment` from your command line.
34
25
 
35
26
  ## Usage
36
27
 
37
28
  ```
38
29
  # create a new directory for your sketches
39
- mkdir ../sketches
30
+ mkdir sketches
40
31
 
41
32
  # move into that folder
42
33
  cd sketches
43
34
 
44
- # initialize npm for linking to work
45
- npm init
46
-
47
35
  # create a sketch from a template
48
36
  fragment ./sketch.js --new --template=2d
49
37
  ```
@@ -80,7 +68,7 @@ export let update = ({ context, width, height }) => {
80
68
  };
81
69
  ```
82
70
 
83
- Learn how to write your own sketch in the [API docs](./docs/api/sketch.md) or read the [examples](./examples/).
71
+ Learn how to write your own sketch by following the [Getting started](./docs//guide/getting-started.md) guide, reading the [API docs](./docs/api/sketch.md) or the [examples](./examples/).
84
72
 
85
73
  ## Contributing
86
74
 
@@ -88,6 +76,39 @@ If you find issues, please [file one](https://github.com/raphaelameaume/fragment
88
76
 
89
77
  Feel free to reach out on [Twitter](https://twitter.com/raphaelameaume) if you want to discuss the project.
90
78
 
79
+ ## Running it locally
80
+
81
+ ```
82
+ # clone or fork the project
83
+ git clone https://github.com/raphaelameaume/fragment.git
84
+
85
+ # move to the root of the repository
86
+ cd fragment
87
+
88
+ # run the command line locally
89
+ node ./bin/index.js examples/shape-2d.js --dev
90
+
91
+ # or from your sketch folder
92
+ node [path-to-root]/bin/index.js sketch.js --dev
93
+ ```
94
+
95
+ > The `--dev` flag only enables Vite `info` logLevel, helpful for development. Otherwise it will work the same as when you're running from the npm package.
96
+
97
+ Alternatively, you can tell npm to point the `fragment` command to the newly cloned folder.
98
+
99
+ ```
100
+ # at the root of the repo
101
+ npm link
102
+ ```
103
+
104
+ You should be able the command as before, only this time it will point to the repository instead of the globally installed package.
105
+
106
+ ```
107
+ fragment sketch.js
108
+ ```
109
+
110
+ If that's not the case, try to uninstall `fragment-tools` globally first, make sure the `fragment` command is not found anymore, then retry to link the project from the root of the repo.
111
+
91
112
  ## Credits
92
113
 
93
114
  - [Vite](https://vitejs.dev/)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fragment-tools",
3
- "version": "0.1.1",
3
+ "version": "0.1.11",
4
4
  "description": "A web development environment for creative coding",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -92,8 +92,8 @@ $: showOutputParams = (monitor && monitor.selected === "output") ||
92
92
  context={sketchKey}
93
93
  key={key}
94
94
  value={sketchProps[key].value}
95
- params={sketchProps[key].params || {}}
96
95
  type={sketchProps[key].type}
96
+ bind:params={sketchProps[key].params}
97
97
  on:click={() => {
98
98
  $props[sketchKey][key].value._refresh = true;
99
99
  }}
@@ -4,41 +4,43 @@ import { sketches } from "./sketches";
4
4
  export const props = writable({});
5
5
 
6
6
  sketches.subscribe((sketches) => {
7
- const $props = get(props);
7
+ props.update((currentProps) => {
8
+ Object.keys(sketches).forEach((key) => {
9
+ const sketch = sketches[key];
8
10
 
9
- Object.keys(sketches).forEach((key) => {
10
- const sketch = sketches[key];
11
-
12
- if (sketch) { // sketch can be undefined if failed to load
13
- $props[key] = reconcile(sketch.props, $props[key]);
14
- }
11
+ if (sketch) { // sketch can be undefined if failed to load
12
+ currentProps[key] = reconcile(sketch.props, currentProps[key]);
13
+ }
14
+ });
15
15
 
16
+ return currentProps;
16
17
  });
17
-
18
- props.set($props);
19
18
  });
20
19
 
21
- function reconcile(newProps = {}, existingProps = {}) {
22
- Object.keys(newProps).forEach(propKey => {
23
- newProps[propKey]._initialValue = newProps[propKey].value;
20
+ function reconcile(newProps = {}, prevProps = {}) {
21
+ Object.keys(newProps).forEach((propKey) => {
22
+ let newProp = newProps[propKey];
23
+
24
+ if (!newProp.params) {
25
+ newProp.params = {};
26
+ }
24
27
  });
25
28
 
26
- if (existingProps) {
27
- Object.keys(existingProps).forEach((propKey) => {
29
+ if (prevProps) {
30
+ Object.keys(prevProps).forEach((propKey) => {
31
+ let prevProp = prevProps[propKey];
28
32
  let newProp = newProps[propKey];
29
33
 
30
34
  if (newProp) {
31
- let prevProp = existingProps[propKey];
32
- let overrideValue =
33
- typeof prevProp._initialValue === "number" &&
34
- prevProp._initialValue === newProp._initialValue;
35
-
36
- if (overrideValue) {
37
- newProp.value = prevProp.value;
35
+ if (prevProp.params) {
36
+ // reconcile locked VectorInput from UI
37
+ if (prevProp.params.locked !== undefined) {
38
+ newProp.params.locked = prevProp.params.locked;
39
+ }
38
40
  }
39
41
  }
40
42
  });
41
- };
43
+ }
42
44
 
43
45
  return newProps;
44
46
  }
@@ -61,7 +61,7 @@ function createTrigger(eventName, collection) {
61
61
  const { hot, enabled, ...params } = options;
62
62
  const context = getContext();
63
63
 
64
- const keys = Array.isArray(key) ? key : [key];
64
+ const keys = Array.isArray(key) ? key : [...key.split(',').map(k => k.trim())];
65
65
 
66
66
  const trigger = new Trigger({
67
67
  inputType: 'Keyboard',
@@ -78,7 +78,11 @@ function createTrigger(eventName, collection) {
78
78
  }
79
79
 
80
80
  const { hot, enabled, ...params } = options;
81
- const keys = Array.isArray(key) ? key : [key];
81
+ let keys = Array.isArray(key) ? key : [...key.split(',').map(k => k.trim())];
82
+
83
+ if (["onControlChange", "onNumberOn", "onNumberOff"].includes(eventName)) {
84
+ keys = keys.map((k) => Number(k));
85
+ }
82
86
 
83
87
  if (!MIDI.enabled) {
84
88
  MIDI.request();
@@ -4,8 +4,7 @@ import { createEventDispatcher } from "svelte";
4
4
  import Select from "./fields/Select.svelte";
5
5
  import NumberInput from "./fields/NumberInput.svelte";
6
6
  import CheckboxInput from "./fields/CheckboxInput.svelte";
7
- import Vec2Input from "./fields/Vec2Input.svelte";
8
- import Vec3Input from "./fields/Vec3Input.svelte";
7
+ import VectorInput from "./fields/VectorInput.svelte";
9
8
  import TextInput from "./fields/TextInput.svelte";
10
9
  import ColorInput from "./fields/ColorInput.svelte";
11
10
  import ListInput from "./fields/ListInput.svelte";
@@ -20,7 +19,7 @@ import frameDebounce from "../lib/helpers/frameDebounce.js";
20
19
  import { getStore } from "../stores/utils";
21
20
  import { writable } from "svelte/store";
22
21
 
23
- export let key = '';
22
+ export let key = "";
24
23
  export let value = null;
25
24
  export let context = null;
26
25
  export let params = {};
@@ -50,8 +49,7 @@ const dispatch = createEventDispatcher();
50
49
  const fields = {
51
50
  "select": Select,
52
51
  "number": NumberInput,
53
- "vec2": Vec2Input,
54
- "vec3": Vec3Input,
52
+ "vec": VectorInput,
55
53
  "checkbox": CheckboxInput,
56
54
  "text": TextInput,
57
55
  "list": ListInput,
@@ -120,7 +118,11 @@ function toggleTriggers(event) {
120
118
  function composeFieldProps(params) {
121
119
  const { triggerable, controllable, ...rest } = params;
122
120
 
123
- return rest;
121
+ return {
122
+ ...rest,
123
+ key,
124
+ context,
125
+ };
124
126
  }
125
127
 
126
128
  </script>
@@ -149,7 +151,7 @@ function composeFieldProps(params) {
149
151
  </svg>
150
152
  </button>
151
153
  {/if}
152
- {#if (fieldType === "vec2" || fieldType === "vec3") && !disabled }
154
+ {#if (fieldType === "vec") && !disabled }
153
155
  <button class="field__action field__action--lock" on:click={() => params.locked = !params.locked}>
154
156
  {#if params.locked}
155
157
  <svg class="action__icon" width="16" height="16" fill="none" viewBox="0 0 24 24">
@@ -200,11 +202,13 @@ function composeFieldProps(params) {
200
202
 
201
203
  :global(.field__input .field) {
202
204
  padding-left: 0px !important;
205
+ padding-right: 0px !important;
203
206
  }
204
207
 
205
208
  :global(.field__input .field:last-child) {
206
209
  border-bottom: 0px solid #323233 !important;
207
210
  padding-bottom: 0px !important;
211
+
208
212
  }
209
213
 
210
214
  .field.disabled {
@@ -72,7 +72,7 @@ function onTypeChange(event) {
72
72
 
73
73
  if (!eventOptions.includes(eventName)) {
74
74
  eventName = undefined;
75
- key = null;
75
+ params.key = null;
76
76
  }
77
77
 
78
78
  if (trigger) {
@@ -82,19 +82,24 @@ function onTypeChange(event) {
82
82
  }
83
83
 
84
84
  function onEventChange(event) {
85
+ const clearParams = (inputType === "MIDI" && eventName !== undefined &&
86
+ ((eventName.includes("Number") && event.detail.includes("Note")) ||
87
+ (eventName.includes("Note") && event.detail.includes("Number")))
88
+ );
89
+
85
90
  eventName = event.detail;
86
91
 
92
+ if (clearParams) {
93
+ params.key = "";
94
+ }
95
+
87
96
  if (inputType === "Mouse") {
88
97
  registerTrigger();
89
98
  }
90
99
  }
91
100
 
92
101
  function onTextChange(e) {
93
- const castToNumber = ["onControlChange", "onNumberOn", "onNumberOff"].includes(eventName);
94
-
95
- params.key = e.detail.split(',').map((value) => {
96
- return castToNumber ? Number(value) : value;
97
- });
102
+ params.key = e.detail;
98
103
 
99
104
  registerTrigger();
100
105
  }
@@ -153,7 +158,7 @@ $: eventOptions = inputType ? [
153
158
  ] : [];
154
159
 
155
160
  $: isValid = inputType && eventName;
156
- $: key = params.key && params.key.length ? params.key.join(',') : "";
161
+ $: key = params.key;
157
162
 
158
163
  </script>
159
164
 
@@ -4,6 +4,8 @@ export let label;
4
4
  export let disabled = false;
5
5
  export let showLabel = true;
6
6
  export let title = "";
7
+ export let context = null;
8
+ export let key = "";
7
9
 
8
10
  </script>
9
11
 
@@ -2,6 +2,8 @@
2
2
  import { createEventDispatcher } from "svelte";
3
3
 
4
4
  export let value;
5
+ export let context = null;
6
+ export let key = "";
5
7
 
6
8
  const dispatch = createEventDispatcher();
7
9
 
@@ -5,55 +5,53 @@ import TextInput from "./TextInput.svelte";
5
5
  import Field from "../Field.svelte";
6
6
 
7
7
  export let value;
8
+ export let context = null;
9
+ export let key = "";
8
10
 
9
11
  const dispatch = createEventDispatcher();
10
12
 
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
-
13
+ $: format = color.getColorFormat(value);
14
+ $: hexValue = color.toHex(value, format);
15
+ $: textValue = color.toString(value, format);
16
+ $: alpha = 1;
17
+ $: hasAlpha = [
18
+ color.FORMATS.RGBA_STRING,
19
+ color.FORMATS.VEC4_STRING,
20
+ color.FORMATS.RGBA_OBJECT,
21
+ color.FORMATS.HSLA_STRING
22
+ ].includes(format);
44
23
  $: {
45
24
  if (hasAlpha) {
46
- const [r, g, b, a = 1] = color.toComponents(textValue);
25
+ const [r, g, b, a = 1] = color.toComponents(value);
47
26
  alpha = a;
27
+ } else {
28
+ alpha = 1;
48
29
  }
49
30
  }
50
31
 
51
32
  function dispatchChange() {
33
+ const [r, g, b] = color.hexToComponents(hexValue);
34
+
52
35
  // support THREE.Color
53
- if (format === color.FORMATS.THREE) {
54
- dispatch('change', value);
55
- } else {
56
- dispatch('change', textValue);
36
+ switch (format) {
37
+ case color.FORMATS.THREE:
38
+ case color.FORMATS.RGB_OBJECT:
39
+ value.r = r;
40
+ value.g = g;
41
+ value.b = b;
42
+
43
+ dispatch('change', value);
44
+ break;
45
+ case color.FORMATS.RGBA_OBJECT:
46
+ value.r = r;
47
+ value.g = g;
48
+ value.b = b;
49
+ value.a = alpha;
50
+
51
+ dispatch('change', value);
52
+ break;
53
+ default:
54
+ dispatch('change', textValue);
57
55
  }
58
56
  }
59
57
 
@@ -61,58 +59,74 @@ function handleBlur() {
61
59
  dispatchChange();
62
60
  }
63
61
 
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
62
  function onChangeText(event) {
86
- isInputDriven = false;
87
-
88
63
  const newColor = event.detail;
89
64
 
90
65
  if (color.isColor(newColor)) {
91
- format = color.getColorFormat(newColor);
92
66
  textValue = newColor;
67
+ } else {
68
+ // newColor is not a color, reset value
69
+ textValue = color.toString(value, format);
93
70
  }
71
+
72
+ hexValue = color.toHex(textValue);
73
+ dispatchChange();
94
74
  }
95
75
 
96
76
  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);
77
+ alpha = event.detail;
78
+
79
+ const [r, g, b] = color.hexToComponents(hexValue);
80
+
81
+ switch(format) {
82
+ case color.FORMATS.RGBA_STRING:
83
+ case color.FORMATS.RGBA_OBJECT:
84
+ textValue = color.componentsToRGBAString([r, g, b, alpha]);
85
+ break;
86
+ case color.FORMATS.VEC4_STRING:
87
+ textValue = color.componentsToVec4String([r, g, b, alpha]);
88
+ break;
89
+ case color.FORMATS.HSLA_STRING:
90
+ const [h, s, l] = color.hslToHSLComponents(textValue);
91
+ textValue = color.hslaToHSLAString([h, s, l, alpha]);
92
+ break;
93
+ }
105
94
 
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);
95
+ dispatchChange();
96
+ }
109
97
 
110
- textValue = color.hslaToHSLAString([h, s, l, event.detail]);
98
+ function onInput(event) {
99
+ hexValue = event.currentTarget.value;
100
+
101
+ const [r, g, b] = color.hexToComponents(hexValue);
102
+
103
+ switch(format) {
104
+ case color.FORMATS.RGBA_STRING:
105
+ case color.FORMATS.RGBA_OBJECT:
106
+ textValue = color.toRGBAString({ r, g, b, a: alpha });
107
+ break;
108
+ case color.FORMATS.VEC3_STRING:
109
+ textValue = color.componentsToVec3String([r, g, b]);
110
+ break;
111
+ case color.FORMATS.VEC4_STRING:
112
+ textValue = color.componentsToVec4String([r, g, b, alpha]);
113
+ break;
114
+ case color.FORMATS.RGB_STRING:
115
+ case color.FORMATS.RGB_OBJECT:
116
+ textValue = color.toRGBString(hexValue);
117
+ break;
118
+ case color.FORMATS.HSL_STRING:
119
+ textValue = color.componentsToHSLString([r, g, b]);
120
+ break;
121
+ case color.FORMATS.HSLA_STRING:
122
+ textValue = color.componentsToHSLAString([r, g, b, alpha]);
123
+ break;
124
+ default:
125
+ textValue = color.toString(hexValue);
126
+ break;
111
127
  }
112
- }
113
128
 
114
- function onInput() {
115
- isInputDriven = true;
129
+ dispatchChange();
116
130
  }
117
131
 
118
132
  </script>
@@ -120,13 +134,31 @@ function onInput() {
120
134
  <div class="color-input">
121
135
  <div class="layout">
122
136
  <div class="mirror" style="--currentColor: {hexValue}; --opacity: {alpha}">
137
+ {#if hasAlpha }
138
+ <svg width="calc(100% - 2px)" height="calc(100% - 2px)" class="alpha-svg">
139
+ <pattern id="checker" x="0" y="0" width="7.2" height="7.2" patternUnits="userSpaceOnUse">
140
+ <rect fill="white" x="0" width="3.6" height="3.6" y="0"></rect>
141
+ <rect fill="grey" x="3.6" width="3.6" height="3.6" y="0"></rect>
142
+ <rect fill="white" x="3.6" width="3.6" height="3.6" y="3.6"></rect>
143
+ <rect fill="grey" x="0" width="3.6" height="3.6" y="3.6"></rect>
144
+ </pattern>
145
+ <!-- The canvas with our applied pattern -->
146
+ <rect x="0" y="0" width="100%" height="100%" fill="url(#checker)"></rect>
147
+ </svg>
148
+ {/if}
123
149
  <!-- svelte-ignore -->
124
150
  <input class="input" type="color" bind:value={hexValue} on:blur={handleBlur} on:input={onInput} />
125
151
  </div>
126
- <TextInput value={textValue} on:change={onChangeText} />
152
+ <TextInput {context} {key} bind:value={textValue} on:change={onChangeText} />
127
153
  </div>
128
154
  {#if hasAlpha }
129
- <Field key="alpha" value={alpha} params={{min: 0, max: 1, step: 0.01}} on:change={onChangeAlpha}></Field>
155
+ <Field
156
+ key={`${key}.alpha`}
157
+ value={alpha}
158
+ params={{label: "alpha", min: 0, max: 1, step: 0.01}}
159
+ {context}
160
+ on:change={onChangeAlpha}
161
+ />
130
162
  {/if }
131
163
  </div>
132
164
 
@@ -143,6 +175,16 @@ function onInput() {
143
175
  align-items: center;
144
176
  }
145
177
 
178
+ .alpha-svg {
179
+ position: absolute;
180
+ top: 1px;
181
+ left: 1px;
182
+ right: 1px;
183
+ bottom: 1px;
184
+
185
+ border-radius: calc(var(--border-radius-input) * 0.5);
186
+ }
187
+
146
188
  .mirror {
147
189
  position: relative;
148
190
 
@@ -152,11 +194,12 @@ function onInput() {
152
194
  box-shadow: inset 0 0 0 1px var(--color-border-input);
153
195
  }
154
196
 
155
- .mirror:before {
197
+ .mirror:after {
156
198
  --gap: 1px;
157
199
 
158
200
  content: '';
159
201
  position: absolute;
202
+ z-index: 1;
160
203
  top: var(--gap);
161
204
  left: var(--gap);
162
205
  right: var(--gap);
@@ -165,6 +208,7 @@ function onInput() {
165
208
  background-color: var(--currentColor);
166
209
  border-radius: calc(var(--border-radius-input) * 0.5);
167
210
  opacity: var(--opacity, 1);
211
+ pointer-events: none;
168
212
  }
169
213
 
170
214
  .mirror:hover {
@@ -6,6 +6,8 @@ import FieldInputRow from "./FieldInputRow.svelte";
6
6
  import TextInput from "./TextInput.svelte";
7
7
 
8
8
  export let value;
9
+ export let context = null;
10
+ export let key = "";
9
11
 
10
12
  let img, input, name;
11
13
  $: url = typeof value === HTMLImageElement ? value.src : value;
@@ -5,6 +5,8 @@ import { createEventDispatcher } from "svelte";
5
5
  export let label = null;
6
6
  export let value;
7
7
  export let disabled = false;
8
+ export let context = null;
9
+ export let key = "";
8
10
 
9
11
  let node;
10
12
 
@@ -16,6 +18,10 @@ function onKeyPress(event) {
16
18
  }
17
19
  }
18
20
 
21
+ function handleInput(event) {
22
+ dispatch('input', event.currentTarget.value);
23
+ }
24
+
19
25
  function handleChange(event) {
20
26
  dispatch('change', event.currentTarget.value);
21
27
  }
@@ -31,7 +37,7 @@ function handleChange(event) {
31
37
  bind:this={node}
32
38
  bind:value={value}
33
39
  on:change={handleChange}
34
- on:input
40
+ on:input={handleInput}
35
41
  on:keypress={onKeyPress}
36
42
  on:keydown
37
43
  on:focus
@@ -3,6 +3,8 @@ import { afterUpdate } from "svelte";
3
3
 
4
4
  export let disabled;
5
5
  export let value = null;
6
+ export let context = null;
7
+ export let key = "";
6
8
 
7
9
  let container;
8
10