@dosgato/dialog 0.0.33 → 0.0.35

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 (77) hide show
  1. package/Button.svelte.d.ts +7 -7
  2. package/ButtonGroup.svelte.d.ts +5 -5
  3. package/Checkbox.svelte.d.ts +4 -4
  4. package/Container.svelte.d.ts +2 -2
  5. package/Dialog.svelte +3 -2
  6. package/Dialog.svelte.d.ts +14 -14
  7. package/FieldAutocomplete.svelte +7 -2
  8. package/FieldAutocomplete.svelte.d.ts +9 -9
  9. package/FieldCheckbox.svelte.d.ts +4 -4
  10. package/FieldChoices.svelte.d.ts +6 -6
  11. package/FieldChooserLink.svelte +7 -2
  12. package/FieldChooserLink.svelte.d.ts +8 -8
  13. package/FieldCodeEditor.svelte +2 -2
  14. package/FieldCodeEditor.svelte.d.ts +7 -7
  15. package/FieldDate.svelte.d.ts +4 -4
  16. package/FieldDateTime.svelte.d.ts +3 -3
  17. package/FieldDualListbox.svelte.d.ts +6 -6
  18. package/FieldHidden.svelte +1 -1
  19. package/FieldHidden.svelte.d.ts +2 -2
  20. package/FieldMultiple.svelte.d.ts +7 -7
  21. package/FieldMultiselect.svelte +5 -1
  22. package/FieldMultiselect.svelte.d.ts +5 -5
  23. package/FieldNumber.svelte.d.ts +5 -5
  24. package/FieldRadio.svelte.d.ts +13 -13
  25. package/FieldSelect.svelte.d.ts +15 -15
  26. package/FieldStandard.svelte +2 -1
  27. package/FieldStandard.svelte.d.ts +11 -10
  28. package/FieldText.svelte +1 -1
  29. package/FieldText.svelte.d.ts +8 -8
  30. package/FieldTextArea.svelte +1 -1
  31. package/FieldTextArea.svelte.d.ts +6 -6
  32. package/FileIcon.svelte.d.ts +5 -5
  33. package/Form.svelte +3 -3
  34. package/Form.svelte.d.ts +5 -5
  35. package/FormDialog.svelte +2 -2
  36. package/FormDialog.svelte.d.ts +24 -21
  37. package/Icon.svelte.d.ts +5 -5
  38. package/Input.svelte.d.ts +8 -8
  39. package/Listbox.svelte +2 -2
  40. package/Listbox.svelte.d.ts +6 -6
  41. package/Radio.svelte.d.ts +4 -4
  42. package/Switcher.svelte.d.ts +11 -11
  43. package/TabStore.d.ts +3 -3
  44. package/TabStore.js +7 -6
  45. package/Tabs.svelte +6 -6
  46. package/Tabs.svelte.d.ts +2 -2
  47. package/chooser/Chooser.svelte +4 -3
  48. package/chooser/Chooser.svelte.d.ts +12 -12
  49. package/chooser/ChooserStore.d.ts +4 -4
  50. package/chooser/ChooserStore.js +3 -3
  51. package/colorpicker/FieldColorPicker.svelte.d.ts +5 -5
  52. package/cropper/FieldCropper.svelte +219 -0
  53. package/cropper/FieldCropper.svelte.d.ts +24 -0
  54. package/cropper/cropper.d.ts +78 -0
  55. package/cropper/cropper.js +220 -0
  56. package/cropper/index.d.ts +2 -0
  57. package/cropper/index.js +2 -0
  58. package/helpers.d.ts +1 -1
  59. package/iconpicker/FieldIconPicker.svelte +5 -5
  60. package/iconpicker/FieldIconPicker.svelte.d.ts +3 -3
  61. package/index.d.ts +1 -1
  62. package/index.js +1 -1
  63. package/package.json +13 -14
  64. package/tree/LoadIcon.svelte.d.ts +2 -2
  65. package/tree/Tree.svelte.d.ts +11 -11
  66. package/tree/TreeNode.svelte +4 -1
  67. package/tree/TreeNode.svelte.d.ts +4 -4
  68. package/tree/treestore.d.ts +16 -16
  69. package/tree/treestore.js +3 -3
  70. package/imagecropper/FieldImageCropper.svelte +0 -380
  71. package/imagecropper/FieldImageCropper.svelte.d.ts +0 -25
  72. package/imagecropper/ImageCropperStore.d.ts +0 -16
  73. package/imagecropper/ImageCropperStore.js +0 -104
  74. package/imagecropper/imagecropper.d.ts +0 -21
  75. package/imagecropper/imagecropper.js +0 -1
  76. package/imagecropper/index.d.ts +0 -1
  77. package/imagecropper/index.js +0 -1
@@ -0,0 +1,219 @@
1
+ <script>import { resize, ScreenReaderOnly } from '@txstate-mws/svelte-components';
2
+ import { isNotBlank, randomid } from 'txstate-utils';
3
+ import FieldStandard from '../FieldStandard.svelte';
4
+ import { CropperStore } from './cropper';
5
+ export let id = undefined;
6
+ export let path;
7
+ export let imageSrc;
8
+ export let selectionAspectRatio = 1;
9
+ export let minSelection = 0; // percentage of image, a value 0-1
10
+ export let label = '';
11
+ export let required = false;
12
+ export let conditional = undefined;
13
+ export let helptext = undefined;
14
+ const store = new CropperStore({ width: 0, height: 0, minSelection, targetAspect: selectionAspectRatio });
15
+ const { output, selection } = store;
16
+ let setVal;
17
+ let value;
18
+ function init(spValue, spSetVal) {
19
+ setVal = spSetVal;
20
+ value = spValue;
21
+ }
22
+ $: store.setOutput(value);
23
+ $: setVal?.($output);
24
+ let rect;
25
+ function updateRect(..._) {
26
+ if (!container)
27
+ return false;
28
+ rect = container.getBoundingClientRect();
29
+ store.updateDimensions(rect.width, rect.height);
30
+ return true;
31
+ }
32
+ function isInside(clientX, clientY) {
33
+ return !(clientX < rect.left || clientX > rect.right || clientY > rect.bottom || clientY < rect.top);
34
+ }
35
+ function relativeToRect(clientX, clientY) {
36
+ return [Math.min(Math.max(0, clientX - rect.left), rect.width), Math.min(Math.max(0, clientY - rect.top), rect.height)];
37
+ }
38
+ let container;
39
+ function onMouseDown(e) {
40
+ if (!updateRect())
41
+ return;
42
+ if (e instanceof TouchEvent && e.touches.length > 1)
43
+ return;
44
+ const clientX = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX;
45
+ const clientY = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY;
46
+ if (isInside(clientX, clientY)) {
47
+ e.preventDefault();
48
+ store.startDrag(clientX - rect.left, clientY - rect.top);
49
+ }
50
+ }
51
+ function onMouseMove(e) {
52
+ if (!updateRect())
53
+ return;
54
+ if (e instanceof TouchEvent && e.touches.length > 1)
55
+ return;
56
+ const clientX = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX;
57
+ const clientY = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY;
58
+ if (e instanceof MouseEvent && !e.buttons && $store.drag)
59
+ store.endDrag();
60
+ if (isInside(clientX, clientY) || $store.drag)
61
+ store.mouseMove(...relativeToRect(clientX, clientY));
62
+ }
63
+ function onMouseUp(e) {
64
+ if (!updateRect())
65
+ return;
66
+ store.endDrag();
67
+ const clientX = e instanceof MouseEvent ? e.clientX : e.changedTouches[0].clientX;
68
+ const clientY = e instanceof MouseEvent ? e.clientY : e.changedTouches[0].clientY;
69
+ if (isInside(clientX, clientY)) {
70
+ store.mouseMove(...relativeToRect(clientX, clientY));
71
+ container?.querySelector('.selectionHilite')?.focus();
72
+ }
73
+ }
74
+ function onMaximize() {
75
+ if (!updateRect())
76
+ return;
77
+ store.maximize();
78
+ }
79
+ function onKeyDown(type) {
80
+ return (e) => {
81
+ const tl = type === 'tl';
82
+ const tr = type === 'tr';
83
+ const bl = type === 'bl';
84
+ const br = type === 'br';
85
+ const left = e.key === 'ArrowLeft';
86
+ const right = e.key === 'ArrowRight';
87
+ const up = e.key === 'ArrowUp';
88
+ const down = e.key === 'ArrowDown';
89
+ if (left || right || up || down) {
90
+ e.preventDefault();
91
+ e.stopPropagation();
92
+ }
93
+ else
94
+ return;
95
+ const step = e.shiftKey ? (e.altKey || e.metaKey ? 80 : 20) : (e.altKey || e.metaKey ? 40 : 1);
96
+ if (type === 'move') {
97
+ store.move(left ? -1 * step : (right ? step : 0), up ? -1 * step : (down ? step : 0));
98
+ }
99
+ else {
100
+ store.expand(type, ((tl || bl) && right) || ((tl || tr) && down) || ((tr || br) && left) || ((bl || br) && up) ? -1 * step : step);
101
+ }
102
+ };
103
+ }
104
+ $: updateRect(container);
105
+ const descid = randomid();
106
+ const movedescid = randomid();
107
+ let focusWithin = false;
108
+ </script>
109
+
110
+ <svelte:window on:mousemove={onMouseMove} on:mouseup={onMouseUp} on:touchend={onMouseUp} on:touchcancel={onMouseUp} />
111
+ <FieldStandard bind:id {label} {path} {required} {conditional} {helptext} {descid} let:value let:setVal let:helptextid>
112
+ {@const _ = init(value, setVal)}
113
+ {#if isNotBlank(imageSrc)}
114
+ <div on:focusin={() => { focusWithin = true }} on:focusout={() => { focusWithin = false }}>
115
+ <div bind:this={container} use:resize on:resize={() => updateRect()} class="crop-image-container" on:mousedown={onMouseDown} on:touchstart={onMouseDown} on:touchmove={onMouseMove} style:cursor={$store.cursor}>
116
+ <img class="crop-image" src={imageSrc} alt="" />
117
+ {#if $selection && $output}
118
+ <div class='crop-bg'>
119
+ <img class='crop-image clipped' src={imageSrc} alt="" style:clip-path="polygon({$output.left}% {$output.top}%, {100 - $output.right}% {$output.top}%, {100 - $output.right}% {100 - $output.bottom}%, {$output.left}% {100 - $output.bottom}%, {$output.left}% {$output.top}%)" />
120
+ </div>
121
+ <!-- svelte-ignore a11y-no-noninteractive-tabindex -->
122
+ <div class='selectionHilite' {id} tabindex="0" on:keydown={onKeyDown('move')}
123
+ aria-labelledby={descid}
124
+ aria-describedby="{movedescid} {helptextid ?? ''}"
125
+ style:left="{$selection.left}px"
126
+ style:top="{$selection.top}px"
127
+ style:width="{$selection.right - $selection.left}px"
128
+ style:height="{$selection.bottom - $selection.top}px"
129
+ >
130
+ <ScreenReaderOnly id={movedescid}>arrows move crop selection, hold shift and/or cmd/alt for bigger steps</ScreenReaderOnly>
131
+ {#if focusWithin}
132
+ <ScreenReaderOnly arialive="polite">top left x y coordinate is ({Math.round($selection.left)}, {Math.round($selection.top)}) bottom right x y coordinate is ({Math.round($selection.right)}, {Math.round($selection.bottom)})</ScreenReaderOnly>
133
+ <ScreenReaderOnly arialive="polite">crop area is {Math.round($store.width)} pixels wide by {Math.round($store.height)} pixels tall</ScreenReaderOnly>
134
+ {/if}
135
+ <div class='selectionCorner tl'
136
+ tabindex="0"
137
+ on:keydown={onKeyDown('tl')}
138
+ >
139
+ <ScreenReaderOnly>arrows adjust crop size, bottom right is fixed, hold shift and/or cmd/alt for bigger steps</ScreenReaderOnly>
140
+ </div>
141
+ <div class='selectionCorner tr'
142
+ tabindex="0"
143
+ on:keydown={onKeyDown('tr')}
144
+ >
145
+ <ScreenReaderOnly>arrows adjust crop size, bottom left is fixed, hold shift and/or cmd/alt for bigger steps</ScreenReaderOnly>
146
+ </div>
147
+ <div class='selectionCorner bl'
148
+ tabindex="0"
149
+ on:keydown={onKeyDown('bl')}
150
+ >
151
+ <ScreenReaderOnly>arrows adjust crop size, top right is fixed, hold shift and/or cmd/alt for bigger steps</ScreenReaderOnly>
152
+ </div>
153
+ <div class='selectionCorner br'
154
+ tabindex="0"
155
+ on:keydown={onKeyDown('br')}
156
+ >
157
+ <ScreenReaderOnly>arrows adjust crop size, top left is fixed, hold shift and/or cmd/alt for bigger steps</ScreenReaderOnly>
158
+ </div>
159
+ </div>
160
+ {/if}
161
+ </div>
162
+ <div class="action-buttons">
163
+ <button type="button" class='btn-center-max' on:click={onMaximize}>Center and Maximize</button>
164
+ <button type="button" class='btn-clear' on:click={() => store.reset()}>Clear</button>
165
+ </div>
166
+ <div class="cropper-instructions">
167
+ Click and drag to select a section of your image to use.
168
+ </div>
169
+ </div>
170
+ {:else}
171
+ Image not selected
172
+ {/if}
173
+ </FieldStandard>
174
+
175
+ <style>
176
+ .crop-image-container {
177
+ position: relative;
178
+ user-select: none;
179
+ }
180
+ .crop-image {
181
+ width: 100%;
182
+ display: block;
183
+ user-select: none;
184
+ }
185
+ .crop-bg {
186
+ position: absolute;
187
+ top: 0;
188
+ left: 0;
189
+ width: 100%;
190
+ height: 100%;
191
+ background-color: rgba(0, 0, 0, 0.8);
192
+ }
193
+ .selectionHilite {
194
+ position: absolute;
195
+ border: 1px dashed white;
196
+ }
197
+ .selectionCorner {
198
+ position: absolute;
199
+ width: 10px;
200
+ height: 10px;
201
+ }
202
+ .selectionCorner.tl {
203
+ top: 0;
204
+ left: 0;
205
+ }
206
+ .selectionCorner.tr {
207
+ top: 0;
208
+ right: 0;
209
+ }
210
+ .selectionCorner.bl {
211
+ bottom: 0;
212
+ left: 0;
213
+ }
214
+ .selectionCorner.br {
215
+ bottom: 0;
216
+ right: 0;
217
+ }
218
+
219
+ </style>
@@ -0,0 +1,24 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ id?: string | undefined;
5
+ path: string;
6
+ imageSrc: string;
7
+ selectionAspectRatio?: number | undefined;
8
+ minSelection?: number | undefined;
9
+ label?: string | undefined;
10
+ required?: boolean | undefined;
11
+ conditional?: boolean | undefined;
12
+ helptext?: string | undefined;
13
+ };
14
+ events: {
15
+ [evt: string]: CustomEvent<any>;
16
+ };
17
+ slots: {};
18
+ };
19
+ export type FieldCropperProps = typeof __propDef.props;
20
+ export type FieldCropperEvents = typeof __propDef.events;
21
+ export type FieldCropperSlots = typeof __propDef.slots;
22
+ export default class FieldCropper extends SvelteComponentTyped<FieldCropperProps, FieldCropperEvents, FieldCropperSlots> {
23
+ }
24
+ export {};
@@ -0,0 +1,78 @@
1
+ import { Store } from '@txstate-mws/svelte-store';
2
+ export interface CropOutput {
3
+ left: number;
4
+ right: number;
5
+ top: number;
6
+ bottom: number;
7
+ }
8
+ export interface CropSelectionPx {
9
+ left: number;
10
+ top: number;
11
+ right: number;
12
+ bottom: number;
13
+ }
14
+ export interface ICropperStore {
15
+ width: number;
16
+ height: number;
17
+ targetAspect: number;
18
+ minSelection: number;
19
+ selection?: CropOutput;
20
+ cursor: 'crosshair' | 'move' | 'ew-resize' | 'ns-resize' | 'nesw-resize' | 'nwse-resize' | 'grabbing';
21
+ drag?: {
22
+ start: {
23
+ x: number;
24
+ y: number;
25
+ };
26
+ selection?: CropSelectionPx;
27
+ edge: {
28
+ left: boolean;
29
+ right: boolean;
30
+ top: boolean;
31
+ bottom: boolean;
32
+ };
33
+ };
34
+ }
35
+ export declare class CropperStore extends Store<ICropperStore> {
36
+ selection: import("@txstate-mws/svelte-store").DerivedStore<{
37
+ left: number;
38
+ right: number;
39
+ top: number;
40
+ bottom: number;
41
+ } | undefined, ICropperStore>;
42
+ output: import("@txstate-mws/svelte-store").DerivedStore<CropOutput | undefined, ICropperStore>;
43
+ constructor(initialValue: Omit<ICropperStore, 'cursor'>);
44
+ setOutput(selection?: CropOutput): void;
45
+ updateDimensions(width: number, height: number): void;
46
+ /**
47
+ * The svelte component is responsible for making sure x and y are relative to the drawing area,
48
+ * e.g. (0, 0) is the top left corner of the drawing area
49
+ *
50
+ * negative coordinates are not allowed
51
+ */
52
+ startDrag(x: number, y: number): void;
53
+ endDrag(): void;
54
+ reset(): void;
55
+ maximize(): void;
56
+ convertToPct(sel: CropSelectionPx | undefined, width: number, height: number): {
57
+ left: number;
58
+ right: number;
59
+ top: number;
60
+ bottom: number;
61
+ } | undefined;
62
+ convertToPx(output: CropOutput | undefined, width: number, height: number): {
63
+ left: number;
64
+ right: number;
65
+ top: number;
66
+ bottom: number;
67
+ } | undefined;
68
+ determineSelection(startX: number, startY: number, x: number, y: number, v: ICropperStore): CropSelectionPx;
69
+ /**
70
+ * The svelte component is responsible for making sure x and y are relative to the drawing area,
71
+ * e.g. (0, 0) is the top left corner of the drawing area
72
+ *
73
+ * negative coordinates are not allowed
74
+ */
75
+ mouseMove(x: number, y: number): void;
76
+ move(dx: number, dy: number): void;
77
+ expand(type: 'tl' | 'tr' | 'bl' | 'br', by: number): void;
78
+ }
@@ -0,0 +1,220 @@
1
+ import { Store, derivedStore } from '@txstate-mws/svelte-store';
2
+ import { clone } from 'txstate-utils';
3
+ const edgeSensitivity = 4;
4
+ export class CropperStore extends Store {
5
+ // coordinates of the selection edges relative to the top left of the draw area, in pixels
6
+ // e.g. { left: 0, right: 10 } means the selection is 10 pixels wide
7
+ selection = derivedStore(this, v => {
8
+ return this.convertToPx(v.selection, v.width, v.height);
9
+ });
10
+ output = derivedStore(this, 'selection');
11
+ constructor(initialValue) {
12
+ super({ ...initialValue, cursor: 'crosshair' });
13
+ }
14
+ setOutput(selection) {
15
+ this.update(v => ({ ...v, selection }));
16
+ }
17
+ updateDimensions(width, height) {
18
+ this.update(v => ({ ...v, width, height }));
19
+ }
20
+ /**
21
+ * The svelte component is responsible for making sure x and y are relative to the drawing area,
22
+ * e.g. (0, 0) is the top left corner of the drawing area
23
+ *
24
+ * negative coordinates are not allowed
25
+ */
26
+ startDrag(x, y) {
27
+ this.update(v => {
28
+ const r = clone(v);
29
+ const selection = this.convertToPx(r.selection, r.width, r.height);
30
+ r.drag = { start: { x, y }, edge: { left: false, top: false, right: false, bottom: false } };
31
+ if (selection) {
32
+ r.drag.edge = {
33
+ left: Math.abs(x - selection.left) < edgeSensitivity,
34
+ top: Math.abs(y - selection.top) < edgeSensitivity,
35
+ right: Math.abs(selection.right - x) < edgeSensitivity,
36
+ bottom: Math.abs(selection.bottom - y) < edgeSensitivity
37
+ };
38
+ if ((r.drag.edge.left && r.drag.edge.top) ||
39
+ (r.drag.edge.top && r.drag.edge.right) ||
40
+ (r.drag.edge.right && r.drag.edge.bottom) ||
41
+ (r.drag.edge.bottom && r.drag.edge.left) ||
42
+ (x > selection.left && x < selection.right &&
43
+ y > selection.top && y < selection.bottom))
44
+ r.drag.selection = selection;
45
+ }
46
+ return r;
47
+ });
48
+ }
49
+ endDrag() {
50
+ this.update(v => ({ ...v, drag: undefined }));
51
+ }
52
+ reset() {
53
+ this.update(v => ({ ...v, selection: undefined }));
54
+ }
55
+ maximize() {
56
+ this.update(v => {
57
+ const ar = v.width / v.height;
58
+ const s = {};
59
+ if (ar > v.targetAspect) { // draw area is wider than aspect, fill height
60
+ s.left = 100 * (ar - v.targetAspect) / (2 * ar);
61
+ s.right = s.left;
62
+ s.top = 0;
63
+ s.bottom = 0;
64
+ }
65
+ else { // draw area is taller than aspect, fill width
66
+ s.left = 0;
67
+ s.right = 0;
68
+ s.top = 100 * (v.targetAspect - ar) / (2 * v.targetAspect);
69
+ s.bottom = s.top;
70
+ }
71
+ return { ...v, selection: s };
72
+ });
73
+ }
74
+ convertToPct(sel, width, height) {
75
+ if (!sel)
76
+ return undefined;
77
+ return {
78
+ left: 100.0 * sel.left / width,
79
+ right: 100.0 * (width - sel.right) / width,
80
+ top: 100.0 * sel.top / height,
81
+ bottom: 100.0 * (height - sel.bottom) / height
82
+ };
83
+ }
84
+ convertToPx(output, width, height) {
85
+ if (!output)
86
+ return undefined;
87
+ return {
88
+ left: output.left * width / 100.0,
89
+ right: width - output.right * width / 100.0,
90
+ top: output.top * height / 100.0,
91
+ bottom: height - output.bottom * height / 100.0
92
+ };
93
+ }
94
+ determineSelection(startX, startY, x, y, v) {
95
+ x = Math.min(v.width, Math.max(0, x));
96
+ y = Math.min(v.height, Math.max(0, y));
97
+ const dx = x - startX;
98
+ const dy = y - startY;
99
+ const dragar = Math.abs(dx / dy);
100
+ if (dragar > v.targetAspect) { // too wide, dy is dominant
101
+ const dragdx = Math.abs(dy * v.targetAspect);
102
+ return {
103
+ left: dx < 0 ? startX - dragdx : startX,
104
+ right: dx < 0 ? startX : startX + dragdx,
105
+ top: dy < 0 ? y : startY,
106
+ bottom: dy < 0 ? startY : y
107
+ };
108
+ }
109
+ else { // too tall, dx is dominant
110
+ const dragdy = Math.abs(dx / v.targetAspect);
111
+ return {
112
+ left: dx < 0 ? x : startX,
113
+ right: dx < 0 ? startX : x,
114
+ top: dy < 0 ? startY - dragdy : startY,
115
+ bottom: dy < 0 ? startY : startY + dragdy
116
+ };
117
+ }
118
+ }
119
+ /**
120
+ * The svelte component is responsible for making sure x and y are relative to the drawing area,
121
+ * e.g. (0, 0) is the top left corner of the drawing area
122
+ *
123
+ * negative coordinates are not allowed
124
+ */
125
+ mouseMove(x, y) {
126
+ this.update(v => {
127
+ const r = { ...v };
128
+ if (v.drag) {
129
+ let s = {};
130
+ const dx = x - v.drag.start.x;
131
+ const dy = y - v.drag.start.y;
132
+ if (v.drag.selection) { // adjust the selection
133
+ r.cursor = 'grabbing';
134
+ const old = v.drag.selection;
135
+ if (v.drag.edge.left && v.drag.edge.top) { // expanding
136
+ s = this.determineSelection(v.drag.selection.right, v.drag.selection.bottom, x, y, v);
137
+ }
138
+ else if (v.drag.edge.left && v.drag.edge.bottom) { // expanding
139
+ s = this.determineSelection(v.drag.selection.right, v.drag.selection.top, x, y, v);
140
+ }
141
+ else if (v.drag.edge.right && v.drag.edge.top) { // expanding
142
+ s = this.determineSelection(v.drag.selection.left, v.drag.selection.bottom, x, y, v);
143
+ }
144
+ else if (v.drag.edge.right && v.drag.edge.bottom) { // expanding
145
+ s = this.determineSelection(v.drag.selection.left, v.drag.selection.top, x, y, v);
146
+ }
147
+ else { // moving
148
+ const maxdx = Math.max(Math.min(v.width - old.right, dx), -1 * old.left);
149
+ const maxdy = Math.max(Math.min(v.height - old.bottom, dy), -1 * old.top);
150
+ s.left = old.left + maxdx;
151
+ s.right = old.right + maxdx;
152
+ s.top = old.top + maxdy;
153
+ s.bottom = old.bottom + maxdy;
154
+ }
155
+ }
156
+ else { // drawing a new selection
157
+ s = this.determineSelection(v.drag.start.x, v.drag.start.y, x, y, v);
158
+ }
159
+ return { ...r, selection: this.convertToPct(s, v.width, v.height) };
160
+ }
161
+ else {
162
+ r.cursor = 'crosshair';
163
+ if (r.selection) {
164
+ const selection = this.convertToPx(r.selection, r.width, r.height);
165
+ const left = Math.abs(x - selection.left) < edgeSensitivity;
166
+ const top = Math.abs(y - selection.top) < edgeSensitivity;
167
+ const right = Math.abs(selection.right - x) < edgeSensitivity;
168
+ const bottom = Math.abs(selection.bottom - y) < edgeSensitivity;
169
+ const inside = x > selection.left && x < selection.right && y > selection.top && y < selection.bottom;
170
+ if ((left && top) || (right && bottom))
171
+ r.cursor = 'nwse-resize';
172
+ else if ((right && top) || (left && bottom))
173
+ r.cursor = 'nesw-resize';
174
+ else if (inside)
175
+ r.cursor = 'move';
176
+ }
177
+ }
178
+ return r;
179
+ });
180
+ }
181
+ move(dx, dy) {
182
+ this.update(v => {
183
+ if (!v.selection)
184
+ return v;
185
+ const selection = this.convertToPx(v.selection, v.width, v.height);
186
+ if (dx < 0 && Math.abs(dx) > selection.left)
187
+ dx = -1 * selection.left;
188
+ if (dx > 0 && dx > v.width - selection.right)
189
+ dx = v.width - selection.right;
190
+ if (dy < 0 && Math.abs(dy) > selection.top)
191
+ dy = -1 * selection.top;
192
+ if (dy > 0 && dy > v.height - selection.bottom)
193
+ dy = v.height - selection.bottom;
194
+ selection.left += dx;
195
+ selection.right += dx;
196
+ selection.top += dy;
197
+ selection.bottom += dy;
198
+ return { ...v, selection: this.convertToPct(selection, v.width, v.height) };
199
+ });
200
+ }
201
+ expand(type, by) {
202
+ this.update(v => {
203
+ if (!v.selection)
204
+ return v;
205
+ const curr = this.convertToPx(v.selection, v.width, v.height);
206
+ const dx = by * v.targetAspect;
207
+ const dy = by / v.targetAspect;
208
+ let s;
209
+ if (type === 'tl')
210
+ s = this.determineSelection(curr.right, curr.bottom, curr.left - dx, curr.top - dy, v);
211
+ else if (type === 'tr')
212
+ s = this.determineSelection(curr.left, curr.bottom, curr.right + dx, curr.top - dy, v);
213
+ else if (type === 'bl')
214
+ s = this.determineSelection(curr.right, curr.top, curr.left - dx, curr.bottom + dy, v);
215
+ else if (type === 'br')
216
+ s = this.determineSelection(curr.left, curr.top, curr.right + dx, curr.bottom + dy, v);
217
+ return { ...v, selection: this.convertToPct(s, v.width, v.height) };
218
+ });
219
+ }
220
+ }
@@ -0,0 +1,2 @@
1
+ export { default as FieldCropper } from './FieldCropper.svelte';
2
+ export * from './cropper.js';
@@ -0,0 +1,2 @@
1
+ export { default as FieldCropper } from './FieldCropper.svelte';
2
+ export * from './cropper.js';
package/helpers.d.ts CHANGED
@@ -1 +1 @@
1
- export declare function getDescribedBy(ids: string[]): string;
1
+ export declare function getDescribedBy(ids: (string | undefined)[]): string | null;
@@ -105,7 +105,7 @@ function onKeyDown(e) {
105
105
 
106
106
  <FieldStandard bind:id {path} {descid} {label} {required} {defaultValue} {conditional} {helptext} let:value let:valid let:invalid let:id let:onBlur let:setVal let:messagesid let:helptextid>
107
107
  <Icon icon={`${value.prefix === 'fab' ? 'fa-brands' : 'fa-solid'}:${value.icon.slice(3)}`}/>
108
- <button id="btnSelectIcon" on:click={() => { modalOpen = true }} aria-describedby={getDescribedBy([descid, messagesid, helptextid])}>Select New Icon</button>
108
+ <button type="button" id="btnSelectIcon" on:click={() => { modalOpen = true }} aria-describedby={getDescribedBy([descid, messagesid, helptextid])}>Select New Icon</button>
109
109
  {#if modalOpen}
110
110
  <Modal>
111
111
  <section>
@@ -117,7 +117,7 @@ function onKeyDown(e) {
117
117
  <div class="filters">
118
118
  <div class="search-wrapper">
119
119
  <input bind:value={searchVal} id="search_for" placeholder="Search Icons" on:keyup={onSearch}/>
120
- <label for="search_for" class="fa fa-search" rel="tooltip" title="search"></label>
120
+ <label for="search_for" class="fa fa-search" title="search"></label>
121
121
  </div>
122
122
  <select bind:value={category} class="icon-category" aria-label="Select Category" on:change={onSelectCategory}>
123
123
  <option value="all">All</option>
@@ -143,8 +143,8 @@ function onKeyDown(e) {
143
143
  </div>
144
144
  </div>
145
145
  <footer class="actions">
146
- <button aria-describedby="{labelid} {descid}" on:click={onCancel(value)}>Cancel</button>
147
- <button aria-describedby="{labelid} {descid}" on:click={onSaveIconSelection(setVal)}>Save Changes</button>
146
+ <button type="button" aria-describedby="{labelid} {descid}" on:click={onCancel(value)}>Cancel</button>
147
+ <button type="button" aria-describedby="{labelid} {descid}" on:click={onSaveIconSelection(setVal)}>Save Changes</button>
148
148
  </footer>
149
149
  </section>
150
150
  </Modal>
@@ -192,7 +192,7 @@ function onKeyDown(e) {
192
192
  }
193
193
 
194
194
  .icon-modal-content fieldset {
195
- max-height: 80%;
195
+ max-height: 75vh;
196
196
  overflow-y: scroll;
197
197
  }
198
198
 
@@ -3,12 +3,12 @@ declare const __propDef: {
3
3
  props: {
4
4
  id?: string | undefined;
5
5
  path: string;
6
- label?: string;
7
- required?: boolean;
6
+ label?: string | undefined;
7
+ required?: boolean | undefined;
8
8
  defaultValue?: {
9
9
  icon: string;
10
10
  prefix: string;
11
- };
11
+ } | undefined;
12
12
  conditional?: boolean | undefined;
13
13
  helptext?: string | undefined;
14
14
  };
package/index.d.ts CHANGED
@@ -40,4 +40,4 @@ export * from './iconpicker/index.js';
40
40
  export * from './colorpicker/index.js';
41
41
  export * from './helpers.js';
42
42
  export * from './tree/index.js';
43
- export * from './imagecropper/index.js';
43
+ export * from './cropper/index.js';
package/index.js CHANGED
@@ -40,4 +40,4 @@ export * from './iconpicker/index.js';
40
40
  export * from './colorpicker/index.js';
41
41
  export * from './helpers.js';
42
42
  export * from './tree/index.js';
43
- export * from './imagecropper/index.js';
43
+ export * from './cropper/index.js';